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; }
/** * 渲染指定部件呈现的图形内容 * @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 ); }
static int _Widget_ProcInvalidArea( LCUI_Widget w, LCUI_BOOL is_root, int x, int y, LCUI_Rect *valid_box, LCUI_DirtyRectList *rlist ) { int i, n, count; LCUI_Widget child; LCUI_Rect rect, child_box, *r; count = n = LinkedList_GetTotal( &w->dirty_rects ); /* 取出当前记录的脏矩形 */ for( i=0; i<n; ++i ) { LinkedList_Goto( &w->dirty_rects, 0 ); r = (LCUI_Rect*)LinkedList_Get( &w->dirty_rects ); /* 若有独立位图缓存,则重绘脏矩形区域 */ if( Graph_IsValid(&w->graph) ) { LCUI_PaintContextRec_ paint; paint.rect = *r; Graph_Quote( &paint.canvas, &w->graph, &paint.rect ); Widget_OnPaint( w, &paint ); } /* 转换为相对于父部件的坐标 */ rect.x = r->x; rect.y = r->y; /* 如果当前是根部件,则不用加上自身坐标 */ if( !is_root ) { rect.x += w->base.box.graph.x; rect.y += w->base.box.graph.y; } rect.w = r->w; rect.h = r->h; /* 取出与容器内有效区域相交的区域 */ if( LCUIRect_GetOverlayRect(&rect, valid_box, &rect) ) { /* 转换相对于根级部件的坐标 */ rect.x += x; rect.y += y; DirtyRectList_Add( rlist, &rect ); } LinkedList_Delete( &w->dirty_rects ); } /* 若子级部件没有脏矩形记录 */ if( !w->has_dirty_child ) { return count; } /* 缩小有效区域到当前部件内容框内,若没有重叠区域,则不向子级部件递归 */ if( !LCUIRect_GetOverlayRect(valid_box, &w->base.box.content, &child_box) ) { return count; } /* 转换有效区域的坐标,相对于当前部件的内容框 */ child_box.x -= w->base.box.content.x; child_box.y -= w->base.box.content.y; n = LinkedList_GetTotal( &w->children ); /* 向子级部件递归 */ for( i=0; i<n; ++i ) { child = (LCUI_Widget)LinkedList_Get( &w->children ); if( !child->style.visible ) { continue; } count += _Widget_ProcInvalidArea( child, FALSE, child->base.box.graph.x + x, child->base.box.graph.y + y, &child_box, rlist ); } return count; }