/** 更新各种图形元素的显示 */ static void LCUIDisplay_Update(void) { int i, n, j, m; LCUI_Rect *p_rect; SurfaceRecord *p_sr; LCUI_DirtyRectList rlist; LCUI_PaintContext paint; DirtyRectList_Init( &rlist ); n = LinkedList_GetTotal( &display.surfaces ); /* 遍历当前的 surface 记录列表 */ for( i=0; i<n; ++i ) { LinkedList_Goto( &display.surfaces, i ); p_sr = (SurfaceRecord*) LinkedList_Get( &display.surfaces ); if( !p_sr->widget || !p_sr->surface || !Surface_IsReady(p_sr->surface) ) { continue; } /* 更新表面 */ Surface_Update( p_sr->surface ); /* 收集无效区域记录 */ Widget_ProcInvalidArea( p_sr->widget, &rlist ); m = LinkedList_GetTotal( &rlist ); DEBUG_MSG("proc invalid area, m = %d\n", m); LinkedList_Goto( &rlist, 0 ); /* 在 surface 上逐个重绘无效区域 */ for( j=0; j<m; ++j ) { p_rect = (LCUI_Rect*)LinkedList_Get( &rlist ); paint = Surface_BeginPaint( p_sr->surface, p_rect ); DEBUG_MSG( "[%s]: render rect: (%d,%d,%d,%d), %d\n", p_sr->widget->type, paint->rect.left, paint->rect.top, paint->rect.w, paint->rect.h, j ); Widget_Render( p_sr->widget, paint ); Surface_EndPaint( p_sr->surface, paint ); LinkedList_Delete( &rlist ); } if( m > 0 ) { Surface_Present( p_sr->surface ); } } LinkedList_Destroy( &rlist ); }
/** 更新各种图形元素的显示 */ static void LCUIDisplay_Update(void) { LinkedList rlist; SurfaceRecord *p_sr; LinkedListNode *sn, *rn; LCUI_PaintContext paint; LinkedList_Init( &rlist ); /* 遍历当前的 surface 记录列表 */ for( LinkedList_Each( sn, &display.surfaces ) ) { p_sr = sn->data; if( !p_sr->widget || !p_sr->surface || !Surface_IsReady(p_sr->surface) ) { continue; } Surface_Update( p_sr->surface ); /* 收集无效区域记录 */ Widget_ProcInvalidArea( p_sr->widget, &rlist ); /* 在 surface 上逐个重绘无效区域 */ for( LinkedList_Each( rn, &rlist ) ) { paint = Surface_BeginPaint( p_sr->surface, rn->data ); if( !paint ) { continue; } DEBUG_MSG( "[%s]: render rect: (%d,%d,%d,%d)\n", p_sr->widget->type, paint->rect.left, paint->rect.top, paint->rect.w, paint->rect.h ); Widget_Render( p_sr->widget, paint ); if( display.show_rect_border ) { DrawBorder( paint ); } Surface_EndPaint( p_sr->surface, paint ); } if( rlist.length > 0 ) { Surface_Present( p_sr->surface ); } RectList_Clear( &rlist ); } RectList_Clear( &rlist ); }
/** * 渲染指定部件呈现的图形内容 * @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 ); }