int Set_PictureBox_InitImage(LCUI_Widget *widget, LCUI_Graph *pic) /* 功能:设定正在加载另一图像时显示的图像 */ { LCUI_PictureBox *pic_box = (LCUI_PictureBox*)Get_Widget_PrivData(widget); if(Graph_Valid(pic)) { Graph_Copy(&pic_box->initial_image, pic); return 0; } return -1; }
int Set_PictureBox_ErrorImage(LCUI_Widget *widget, LCUI_Graph *pic) /* 功能:设定当加载图像失败时显示的图像 */ { LCUI_PictureBox *pic_box = (LCUI_PictureBox*) Get_Widget_PrivData(widget); if(Graph_Valid(pic)) { Graph_Copy(&pic_box->error_image, pic); return 0; } return -1; }
static size_t WidgetRenderer_Render( LCUI_WidgetRenderer renderer ) { size_t count = 0; LCUI_PaintContextRec self_paint; LCUI_WidgetRenderer that = renderer; /* 如果部件有需要绘制的内容 */ if( that->can_render_self ) { count += 1; self_paint = *that->paint; self_paint.canvas = that->self_graph; Widget_OnPaint( that->target, &self_paint ); /* 若不需要缓存自身位图则直接绘制到画布上 */ if( !that->has_self_graph ) { Graph_Mix( &that->paint->canvas, &that->self_graph, 0, 0, that->paint->with_alpha ); } } if( that->can_render_centent ) { count += WidgetRenderer_RenderChildren( that ); } /* 如果与圆角边框重叠,则裁剪掉边框外的内容 */ if( that->is_cover_border ) { /* content_graph ... */ } if( !that->has_layer_graph ) { if( that->has_content_graph ) { Graph_Mix( &that->paint->canvas, &that->content_graph, that->content_paint_rect.x, that->content_paint_rect.y, TRUE ); } return count; } /* 若需要绘制的是当前部件图层,则先混合部件自身位图和内容位图,得出当 * 前部件的图层,然后将该图层混合到输出的位图中 */ if( that->can_render_self ) { Graph_Copy( &that->layer_graph, &that->self_graph ); Graph_Mix( &that->layer_graph, &that->content_graph, that->content_paint_rect.x, that->content_paint_rect.y, TRUE ); } else { Graph_Create( &that->layer_graph, that->paint->rect.width, that->paint->rect.height ); Graph_Replace( &that->layer_graph, &that->content_graph, that->content_paint_rect.x, that->content_paint_rect.y ); } that->layer_graph.opacity = that->target->computed_style.opacity; Graph_Mix( &that->paint->canvas, &that->layer_graph, 0, 0, that->paint->with_alpha ); return count; }
/* 设定正在加载另一图像时显示的图像 */ LCUI_API int PictureBox_SetInitImage( LCUI_Widget *widget, LCUI_Graph *pic ) { LCUI_PictureBox *pic_box; pic_box = Widget_GetPrivData(widget); if(Graph_IsValid(pic)) { Graph_Copy(&pic_box->initial_image, pic); return 0; } return -1; }
/** * 渲染指定部件呈现的图形内容 * @param[in] w 部件 * @param[in] paint 进行绘制时所需的上下文 */ void Widget_Render( LCUI_Widget w, LCUI_PaintContext paint ) { int i, content_left, content_top; LCUI_Rect content_rect; LCUI_Graph content_graph, self_graph, layer_graph; LCUI_BOOL has_overlay, has_content_graph = FALSE, has_self_graph = FALSE,has_layer_graph = FALSE, is_cover_border = FALSE; Graph_Init( &layer_graph ); Graph_Init( &self_graph ); Graph_Init( &content_graph ); /* 若部件本身是透明的 */ if( w->style.opacity < 1.0 ) { has_self_graph = TRUE; has_content_graph = TRUE; has_layer_graph = TRUE; } else { /* 若使用了圆角边框,则判断当前脏矩形区域是否在圆角边框内 ... if( ... ) { has_content_graph = TRUE; is_cover_border = TRUE; } */ } /* 如果需要缓存自身的位图 */ if( has_self_graph ) { LCUI_PaintContextRec_ self_paint; /* 有位图缓存则直接截取出来,否则绘制一次 */ if( Graph_IsValid(&w->graph) ) { Graph_Quote( &self_graph, &w->graph, &paint->rect ); } else { Graph_Create( &self_graph, paint->rect.width, paint->rect.height ); } self_paint.canvas = self_graph; self_paint.rect = paint->rect; Widget_OnPaint( w, &self_paint ); } else { /* 直接将部件绘制到目标位图缓存中 */ if( Graph_IsValid(&w->graph) ) { Graph_Quote( &self_graph, &w->graph, &paint->rect ); Graph_Mix( &paint->canvas, &self_graph, Pos(0,0) ); Graph_WritePNG( "1,paint_canvas.png", &paint->canvas ); Graph_WritePNG( "2,self_graph.png", &self_graph ); } else { Widget_OnPaint( w, paint ); } } /* 计算内容框相对于图层的坐标 */ content_left = w->base.box.content.x - w->base.box.graph.x; content_top = w->base.box.content.y - w->base.box.graph.y; /* 获取内容框 */ content_rect.x = content_left; content_rect.y = content_top; content_rect.width = w->base.box.content.width; content_rect.height = w->base.box.content.height; /* 获取内容框与脏矩形重叠的区域 */ has_overlay = LCUIRect_GetOverlayRect( &content_rect, &paint->rect, &content_rect ); /* 如果没有与内容框重叠,则跳过内容绘制 */ if( !has_overlay ) { goto content_paint_done; } /* 将换重叠区域的坐标转换为相对于脏矩形的坐标 */ content_rect.x -= paint->rect.x; content_rect.y -= paint->rect.y; /* 若需要部件内容区的位图缓存 */ if( has_content_graph ) { content_graph.color_type = COLOR_TYPE_ARGB; Graph_Create( &content_graph, content_rect.w, content_rect.h ); } else { /* 引用该区域的位图,作为内容框的位图 */ Graph_Quote( &content_graph, &paint->canvas, &content_rect ); } i = LinkedList_GetTotal( &w->children_show ); /* 按照显示顺序,从底到顶,递归遍历子级部件 */ while( i-- ) { LCUI_Widget child; LCUI_Rect child_rect; LCUI_PaintContextRec_ child_paint; child = (LCUI_Widget)LinkedList_Get( &w->children_show ); if( !child->style.visible ) { continue; } /* 将子部件的区域,由相对于内容框转换为相对于当前脏矩形 */ child_rect = child->base.box.graph; child_rect.x += (content_left - paint->rect.x); child_rect.y += (content_top - paint->rect.y); /* 获取于内容框重叠的区域,作为子部件的绘制区域 */ has_overlay = LCUIRect_GetOverlayRect( &content_rect, &child_rect, &child_paint.rect ); /* 区域无效则不绘制 */ if( !has_overlay ) { continue; } /* 将子部件绘制区域转换相对于当前部件内容框 */ child_rect.x = child_paint.rect.x - content_rect.x; child_rect.y = child_paint.rect.y - content_rect.y; child_rect.width = child_paint.rect.width; child_rect.height = child_paint.rect.height; /* 在内容位图中引用所需的区域,作为子部件的画布 */ Graph_Quote( &child_paint.canvas, &content_graph, &child_rect ); Widget_Render( child, &child_paint ); } /* 如果与圆角边框重叠,则裁剪掉边框外的内容 */ if( is_cover_border ) { /* content_graph ... */ } content_paint_done: /* 若需要绘制的是当前部件图层,则先混合部件自身位图和内容位图,得出当 * 前部件的图层,然后将该图层混合到输出的位图中 */ if( has_layer_graph ) { Graph_Init( &layer_graph ); layer_graph.color_type = COLOR_TYPE_ARGB; Graph_Copy( &layer_graph, &self_graph ); Graph_Mix( &layer_graph, &content_graph, Pos(content_rect.x, content_rect.y) ); layer_graph.opacity = w->style.opacity; Graph_Mix( &paint->canvas, &layer_graph, Pos(0,0) ); } else if( has_content_graph ) { Graph_Mix( &paint->canvas, &content_graph, Pos(content_rect.x, content_rect.y) ); } Graph_WritePNG( "layer_graph.png", &layer_graph ); Graph_WritePNG( "self_graph.png", &self_graph ); Graph_WritePNG( "content_graph.png", &content_graph ); Graph_Free( &layer_graph ); Graph_Free( &self_graph ); Graph_Free( &content_graph ); }
int GaussianSmooth( LCUI_Graph *src, LCUI_Graph *des, double sigma ) /* 对图像进行高斯模糊处理 */ { LCUI_Graph temp; int32_t kcenter, i; uint_t x, y, ksize; uint_t temp_pos, temp_start_pos; uint_t a_src_pos, b_src_pos, src_start_pos; double amul, bmul, gmul, rmul, *kvalue_ptr; double *kernel, scale, cons, sum = 0; const double PI = 3.141592653; sigma = sigma > 0 ? sigma : -sigma; //ksize为奇数 ksize = ceil(sigma * 3) * 2 + 1; if(ksize == 1) { Graph_Copy( des, src ); return 0; } //计算一维高斯核 scale = -0.5/(sigma*sigma); cons = 1/sqrt(-scale / PI); kcenter = ksize/2; kernel = (double*) malloc( ksize*sizeof(double) ); for(i = 0; i < ksize; ++i) { int x = i - kcenter; *(kernel+i) = cons * exp(x * x * scale);//一维高斯函数 sum += *(kernel+i); } //归一化,确保高斯权值在[0,1]之间 for(i = 0; i < ksize; i++) { *(kernel+i) /= sum; } des->have_alpha = src->have_alpha; if( Graph_Create( des, src->width, src->height ) != 0 ) { return -1; } Graph_Init( &temp ); temp.have_alpha = src->have_alpha; if( Graph_Create( &temp, src->width, src->height ) != 0 ) { return -2; } Graph_Lock( src, RWLOCK_READ ); Graph_Lock( &temp, RWLOCK_WRITE ); //x方向一维高斯模糊 temp_start_pos = 0; src_start_pos = 0 - kcenter; for(y = 0; y < src->height; y++) { temp_pos = temp_start_pos; b_src_pos = src_start_pos; for(x = 0; x < src->width; x++) { sum = amul = bmul = gmul = rmul = 0; a_src_pos = b_src_pos; kvalue_ptr = kernel; for(i = -kcenter; i <= kcenter; i++) { if((x+i) >= 0 && (x+i) < src->width) { rmul += src->rgba[0][a_src_pos]*(*kvalue_ptr); gmul += src->rgba[1][a_src_pos]*(*kvalue_ptr); bmul += src->rgba[2][a_src_pos]*(*kvalue_ptr); if(src->have_alpha) { amul += src->rgba[3][a_src_pos]*(*kvalue_ptr); } sum += (*kvalue_ptr); } ++a_src_pos; ++kvalue_ptr; } temp.rgba[0][temp_pos] = rmul/sum; temp.rgba[1][temp_pos] = gmul/sum; temp.rgba[2][temp_pos] = bmul/sum; if(temp.have_alpha) { temp.rgba[3][temp_pos] = amul/sum; } ++temp_pos; ++b_src_pos; } temp_start_pos += temp.width; src_start_pos += src->width; } Graph_Unlock( &temp ); Graph_Lock( des, RWLOCK_WRITE ); Graph_Lock( &temp, RWLOCK_READ ); //y方向一维高斯模糊 src_start_pos = 0 - kcenter*temp.width; src_start_pos = 0 - kcenter*temp.width; for(x = 0; x < temp.width; x++) { temp_start_pos = x; b_src_pos = src_start_pos; for(y = 0; y < temp.height; y++) { sum = amul = bmul = gmul = rmul = 0; a_src_pos = b_src_pos; kvalue_ptr = kernel; for(i = -kcenter; i <= kcenter; i++) { if((y+i) >= 0 && (y+i) < temp.height) { rmul += temp.rgba[0][a_src_pos]*(*kvalue_ptr); gmul += temp.rgba[1][a_src_pos]*(*kvalue_ptr); bmul += temp.rgba[2][a_src_pos]*(*kvalue_ptr); if(temp.have_alpha) { amul += temp.rgba[3][a_src_pos]*(*kvalue_ptr); } sum += (*kvalue_ptr); } a_src_pos += temp.width; ++kvalue_ptr; } des->rgba[0][temp_start_pos] = rmul/sum; des->rgba[1][temp_start_pos] = gmul/sum; des->rgba[2][temp_start_pos] = bmul/sum; if(des->have_alpha) { des->rgba[3][temp_start_pos] = amul/sum; } temp_start_pos += des->width; b_src_pos += temp.width; } ++src_start_pos; } Graph_Unlock( &temp ); Graph_Unlock( des ); Graph_Unlock( src ); Graph_Free( &temp ); free(kernel); return 0; }
/** 对图像进行高斯模糊处理 */ LCUI_API int GaussianSmooth( LCUI_Graph *src, LCUI_Graph *des, double sigma ) { LCUI_Graph temp; int kcenter, i; int x, y, ksize; double *kernel, scale, cons, sum = 0; LCUI_ARGB *p_src_px, *p_des_px; sigma = sigma > 0 ? sigma : -sigma; // ksize为奇数 ksize = ceil(sigma * 3) * 2 + 1; if(ksize == 1) { Graph_Copy( des, src ); return 0; } // 计算一维高斯核 scale = -0.5/(sigma*sigma); cons = 1/sqrt(-scale / PI); kcenter = ksize/2; kernel = (double*)malloc( ksize*sizeof(double) ); for(i = 0; i < ksize; ++i) { int x = i - kcenter; *(kernel+i) = cons * exp(x * x * scale); // 一维高斯函数 sum += *(kernel+i); } // 归一化,确保高斯权值在[0,1]之间 for(i = 0; i < ksize; i++) { *(kernel+i) /= sum; } des->color_type = src->color_type; if( Graph_Create( des, src->w, src->h ) != 0 ) { return -1; } Graph_Init( &temp ); temp.color_type = src->color_type; if( Graph_Create( &temp, src->w, src->h ) != 0 ) { return -2; } // x方向一维高斯模糊 p_des_px = temp.argb; p_src_px = src->argb - kcenter; for( y=0; y<src->h; ++y ) { HorizSmoothARGB( p_src_px, p_des_px, src->w, kernel, kcenter ); p_des_px += temp.w; p_src_px += src->w; } // y方向一维高斯模糊 p_des_px = temp.argb; p_src_px = src->argb - kcenter*temp.w; for( x=0; x<temp.w; ++x ) { VertiSmoothARGB( p_src_px, p_des_px, src->h, src->w, kernel, kcenter ); ++p_des_px; ++p_src_px; } Graph_Free( &temp ); free(kernel); return 0; }