/** 追加子部件 */ int $(Append)( LCUI_Widget container, LCUI_Widget widget ) { int i, n; LCUI_Widget old_container; LCUI_WidgetEvent e; DEBUG_MSG("container: %p, widget: %p\n", container, widget); if( !container || !widget || container == widget->parent ) { return -1; } if( container == widget ) { return -2; } if( widget->parent ) { old_container = widget->parent; } else { goto remove_done; } /* 移除在之前的容器中的记录 */ n = LinkedList_GetTotal( &old_container->children ); for( i=0; i<n; ++i ) { LinkedList_Goto( &old_container->children, i ); if( LinkedList_Get(&old_container->children) == widget ) { LinkedList_Delete( &old_container->children ); break; } } /* 如果是从根级部件中移出,则触发 WET_REMOVE 事件 */ if( i < n && old_container == LCUIRootWidget ) { e.type_name = "TopLevelWidget"; e.target = widget; Widget_PostEvent( LCUIRootWidget, &e, (int*)WET_REMOVE ); } n = LinkedList_GetTotal( &old_container->children_show ); for( i=0; i<n; ++i ) { LinkedList_Goto( &old_container->children_show, i ); if( LinkedList_Get(&old_container->children_show) == widget ) { LinkedList_Delete( &old_container->children_show ); break; } } remove_done: widget->parent = container; LinkedList_AddData( &container->children, widget ); LinkedList_AddData( &container->children_show, widget ); /* 如果是添加至根部件内,则触发 WET_ADD 事件 */ if( container == LCUIRootWidget ) { int ret; e.type_name = "TopLevelWidget"; e.target = widget; ret = Widget_PostEvent( LCUIRootWidget, &e, (int*)WET_ADD ); DEBUG_MSG("post done, ret = %d\n", ret); } Widget_UpdateTaskStatus( widget ); DEBUG_MSG("tip\n"); return 0; }
/** 设备处理线程 */ static void DeviceThread( void *arg ) { DeviceData *data_ptr; int n, i, timeout_count = 0; is_running = TRUE; while( is_running ) { LCUIMutex_Lock( &list_mutex ); n = LinkedList_GetTotal( &dev_list ); for( i=0; i<n; ++i ) { data_ptr = (DeviceData*)LinkedList_Get( &dev_list ); if( !data_ptr || !data_ptr->proc ) { continue; } if( data_ptr->proc() ) { ++timeout_count; } } LCUIMutex_Unlock( &list_mutex ); if( timeout_count > 20 ) { LCUI_MSleep( 10 ); timeout_count = 0; } LCUI_MSleep( 5 ); } LCUIThread_Exit(NULL); }
/** 直接将事件发送至事件处理器进行处理 */ int $(Send)( LCUI_EventBox box, const char *name, void *data ) { int i, n; LCUI_Event event; LCUI_RBTreeNode *node; LCUI_EventSlot *slot; LCUI_EventHandler *handler; if( !(node = RBTree_CustomSearch(&box->event_name, (const void*)name)) ) { return -1; } if( !(node = RBTree_Search(&box->event_slot, node->key)) ) { return -2; } slot = (LCUI_EventSlot*)node->data; event.id = slot->id; event.name = slot->name; event.data = data; event.destroy_data = NULL; n = LinkedList_GetTotal( &slot->handlers ); LinkedList_Goto( &slot->handlers, 0 ); for( i=0; i<n; ++i ) { handler = (LCUI_EventHandler*)LinkedList_Get( &slot->handlers ); handler->func( &event, handler->func_data ); LinkedList_ToNext( &slot->handlers ); } return 0; }
/** 解除事件连接 */ int $(Unbind)( LCUI_EventBox box, int handler_id ) { int i, n; LCUI_RBTreeNode *node; LCUI_EventSlot *slot; LCUI_EventHandler *handler; if( !(node = RBTree_Search(&box->event_handler, handler_id)) ) { return -1; } if( !(node = RBTree_Search(&box->event_slot, (int)(node->data))) ) { return -2; } slot = (LCUI_EventSlot*)node->data; LinkedList_Goto( &slot->handlers, 0 ); n = LinkedList_GetTotal( &slot->handlers ); for( i=0; i<n; ++i ) { handler = (LCUI_EventHandler*)LinkedList_Get( &slot->handlers ); if( handler->id == handler_id ) { LinkedList_Delete( &slot->handlers ); RBTree_Erase( &box->event_handler, handler_id ); return 0; } LinkedList_ToNext( &slot->handlers ); } return -3; }
/** 从已触发的事件记录中删除一个事件信息 */ int $(DeleteEvent)( LCUI_EventBox box ) { LinkedList *elist; elist = &box->events[box->current == 1 ? 0:1]; if( LinkedList_GetTotal( elist ) <= 0 ) { return -2; } LinkedList_Delete( elist ); return 0; }
/** 更新各种图形元素的显示 */ 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 StyleTagStack_Delete( LCUI_StyleTagStack *tags, LCUI_StyleTagID tag ) { int i, total; LCUI_StyleTagData *p; total = LinkedList_GetTotal( tags ); DEBUG_MSG("delete start, total tag: %d\n", total); if(total <= 0) { return; } for(i=total-1; i>=0; --i) { LinkedList_Goto( tags, i ); p = (LCUI_StyleTagData*)LinkedList_Get( tags ); if( p->tag_id == tag ) { LinkedList_Delete( tags ); break; } } DEBUG_MSG("delete end, total tag: %d\n", LinkedList_GetTotal( tags )); }
/** 获取当前的文本样式 */ LCUI_TextStyle* StyleTagStack_GetTextStyle( LCUI_StyleTagStack *tags ) { LCUI_StyleTagData *tag_data; LCUI_TextStyle *style_data; int i, total, equal = 0, flags[MAX_TAG_NUM]; style_data = (LCUI_TextStyle*)malloc( sizeof(LCUI_TextStyle) ); TextStyle_Init( style_data ); memset( flags, 0, sizeof(flags) ); total = LinkedList_GetTotal( tags ); if(total <= 0) { free( style_data ); return NULL; } /* 根据已经记录的各种样式,生成当前应有的文本样式 */ for(equal=0,i=total-1; i>=0; --i) { LinkedList_Goto( tags, i ); tag_data = (LCUI_StyleTagData*)LinkedList_Get( tags ); DEBUG_MSG("tag id: %d\n", tag_data->tag_id); switch( tag_data->tag_id ) { case TAG_ID_COLOR: if( flags[0] != 0 ) { break; } style_data->_fore_color = TRUE; style_data->fore_color = tag_data->style.color; DEBUG_MSG("color: %d,%d,%d\n", data->fore_color.red, data->fore_color.green, data->fore_color.blue); flags[0] = 1; ++equal; break; case TAG_ID_SIZE: if( flags[1] != 0 ) { break; } style_data->_pixel_size = TRUE; style_data->pixel_size = tag_data->style.size.px; flags[1] = 1; ++equal; break; default: break; } if(equal == MAX_TAG_NUM) { break; } } if( equal == 0 ) { free( style_data ); return NULL; } return style_data; }
static void LCUIDisplay_CleanSurfaces( void ) { int i, n; SurfaceRecord *p_sr; n = LinkedList_GetTotal( &display.surfaces ); for( i=0; i<n; ++i ) { LinkedList_Goto( &display.surfaces, 0 ); p_sr = (SurfaceRecord*) LinkedList_Get( &display.surfaces ); Surface_Delete( p_sr->surface ); LinkedList_Delete( &display.surfaces ); } }
/* 销毁程序占用的资源 */ static void LCUIApp_Destroy(void) { if( LinkedList_GetTotal(&MainApp.loop_list) > 0 ) { /* 等待其它线程上的主循环都完全退出 */ LCUICond_Wait( &MainApp.loop_list_empty ); } /* 开始清理 */ LCUICond_Destroy( &MainApp.loop_list_empty ); LCUICond_Destroy( &MainApp.loop_cond ); LCUIMutex_Destroy( &MainApp.loop_mutex ); LCUIMutex_Destroy( &MainApp.loop_changed ); LCUIMutex_Destroy( &MainApp.task_run_mutex ); LCUIMutex_Destroy( &MainApp.task_list_mutex ); LinkedList_Destroy( &MainApp.loop_list ); }
/** 退出所有主循环 */ static void LCUIApp_QuitAllMainLoop(void) { LCUI_MainLoop loop; int n = LinkedList_GetTotal( &MainApp.loop_list ); LinkedList_Goto( &MainApp.loop_list, 0 ); while( n-- ) { loop = (LCUI_MainLoop)LinkedList_Get( &MainApp.loop_list ); if( !loop ) { break; } loop->state = STATE_EXITED; LinkedList_ToNext( &MainApp.loop_list ); } LCUICond_Broadcast( &MainApp.loop_cond ); }
/** 获取指定按键的状态数据 */ static key_state* KeyStateRecord_FindData( int key_code ) { int i, n; key_state* data_ptr; n = LinkedList_GetTotal( &key_state_record ); for( i=0; i<n; ++i ) { data_ptr = (key_state*)LinkedList_Get( &key_state_record ); if( data_ptr && data_ptr->key_code == key_code ) { return data_ptr; } LinkedList_ToNext( &key_state_record ); } return NULL; }
/** 从已触发的事件记录中取出(不会移除)一个事件信息 */ int $(GetEvent)( LCUI_EventBox box, LCUI_Event *ebuff ) { int n; LCUI_Event *event; LinkedList *elist; elist = &box->events[box->current == 1 ? 0:1]; n = LinkedList_GetTotal( elist ); if( n <= 0 ) { return -1; } LinkedList_Goto( elist, 0 ); event = (LCUI_Event*)LinkedList_Get( elist ); *ebuff = *event; return 0; }
static LCUI_Surface LCUIDisplay_GetBindSurface( LCUI_Widget widget ) { int i, n; SurfaceRecord *p_sr; n = LinkedList_GetTotal( &display.surfaces ); for( i=0; i<n; ++i ) { LinkedList_Goto( &display.surfaces, i ); p_sr = (SurfaceRecord*) LinkedList_Get( &display.surfaces ); if( p_sr->widget == widget ) { return p_sr->surface; } } return NULL; }
/** 在 surface 主动产生无效区域的时候 */ static void OnInvalidRect( LCUI_Surface surface, LCUI_Rect *rect ) { int i, n; SurfaceRecord *p_sr; n = LinkedList_GetTotal( &display.surfaces ); for( i=0; i<n; ++i ) { LinkedList_Goto( &display.surfaces, i ); p_sr = (SurfaceRecord*) LinkedList_Get( &display.surfaces ); if( p_sr->surface != surface ) { continue; } Widget_InvalidateArea( p_sr->widget, rect, SV_GRAPH_BOX ); continue; } }
/** * 获取部件中的无效区域 * @param[in] widget 目标部件 * @area[out] area 无效区域 */ int Widget_GetInvalidArea( LCUI_Widget widget, LCUI_Rect *area ) { LCUI_Rect *p_rect; if( LinkedList_GetTotal(&widget->dirty_rects) <= 0 ) { return -1; } LinkedList_Goto( &widget->dirty_rects, 0 ); DEBUG_MSG("list: %p, used node num: %d, current: %p, pos: %d\n", &widget->dirty_rects, widget->dirty_rects.used_node_num, widget->dirty_rects.current_node, widget->dirty_rects.current_node_pos); p_rect = (LCUI_Rect*)LinkedList_Get( &widget->dirty_rects ); if( !p_rect ) { return -2; } DEBUG_MSG("p_rect: %d,%d,%d,%d\n", p_rect->x, p_rect->y, p_rect->w, p_rect->h); *area = *p_rect; return 0; }
/** 解除 widget 与 sruface 的绑定 */ static void LCUIDisplay_UnbindSurface( LCUI_Widget widget ) { int i, n; SurfaceRecord *p_sr; n = LinkedList_GetTotal( &display.surfaces ); for( i=0; i<n; ++i ) { LinkedList_Goto( &display.surfaces, i ); p_sr = (SurfaceRecord*) LinkedList_Get( &display.surfaces ); if( p_sr->widget != widget ) { continue; } Surface_Delete( p_sr->surface ); LinkedList_Delete( &display.surfaces ); break; } }
/** 停用设备处理模块 */ void LCUIModule_Device_End(void) { int n, i; DeviceData *data_ptr; LCUIMutex_Lock( &list_mutex ); n = LinkedList_GetTotal( &dev_list ); for( i=0; i<n; ++i ) { data_ptr = (DeviceData*)LinkedList_Get( &dev_list ); if( !data_ptr ) { break; } if( data_ptr->exit ) { data_ptr->exit(); } LinkedList_ToNext( &dev_list ); } LCUIMutex_Unlock( &list_mutex ); }
/** 前置显示 */ int $(Front)( LCUI_Widget widget ) { int i, n, src_pos = -1, des_pos = -1; LCUI_Widget parent, child; parent = widget->parent ? widget->parent:LCUIRootWidget; n = LinkedList_GetTotal( &parent->children_show ); /* 先在队列中找到自己,以及z-index值小于或等于它的第一个部件 */ for( i=0; i<n; ++i ) { LinkedList_Goto( &parent->children_show, i ); child = (LCUI_Widget)LinkedList_Get( &parent->children_show ); if( child == widget ) { src_pos = i; continue; } if( des_pos >= 0 ) { if( src_pos >= 0 ) { break; } continue; } /* 如果该位置的图层的z-index值不大于自己 */ if( child->style.z_index <= widget->style.z_index ) { /* 如果未找到自己的源位置 */ if( src_pos == -1 ) { des_pos = i; continue; } /* 否则,退出循环,因为已经在前排了 */ break; } } /* 没有找到就退出 */ if( des_pos == -1 || src_pos == -1 ) { return -1; } /* 找到的话就移动位置 */ LinkedList_Goto( &parent->children_show, src_pos ); LinkedList_MoveTo( &parent->children_show, des_pos ); // XXX return 0; }
/** 派发当前待处理的事件至对应的处理器 */ int $(Dispatch)( LCUI_EventBox box ) { int i, n; LCUI_Event *e; LinkedList *elist; box->current = box->current ? 0:1; elist = &box->events[box->current ? 0:1]; n = LinkedList_GetTotal( elist ); LinkedList_Goto( elist, 0 ); for( i=0; i<n; ++i ) { e = (LCUI_Event*)LinkedList_Get( elist ); $(Send)( box, e->name, e->data ); e->destroy_data ? e->destroy_data( e->data ):0; LinkedList_Goto( elist, 0 ); LinkedList_Delete( elist ); } box->current = box->current ? 0:1; return 0; }
/** 更新数据 */ void TextLayer_Update( LCUI_TextLayer* layer, LinkedList *rect_list ) { if( layer->task.update_bitmap ) { TextLayer_InvalidateAllRowRect( layer ); TextLayer_ReloadCharBitmap( layer ); TextLayer_InvalidateAllRowRect( layer ); layer->task.update_bitmap = FALSE; layer->task.redraw_all = TRUE; } if( layer->task.update_typeset ) { TextLayer_TextTypeset( layer, layer->task.typeset_start_row ); layer->task.update_typeset = FALSE; layer->task.typeset_start_row = 0; } /* 如果坐标偏移量有变化,记录各个文本行区域 */ if( layer->new_offset_x != layer->offset_x || layer->new_offset_y != layer->offset_y ) { TextLayer_InvalidateAllRowRect( layer ); layer->offset_x = layer->new_offset_x; layer->offset_y = layer->new_offset_y; TextLayer_InvalidateAllRowRect( layer ); layer->task.redraw_all = TRUE; } if( rect_list ) { int n; void *data_ptr; n = LinkedList_GetTotal( &layer->dirty_rect ); LinkedList_Goto( &layer->dirty_rect, 0 ); /* 转移脏矩形记录,供利用 */ while(n--) { data_ptr = LinkedList_Get( &layer->dirty_rect ); LinkedList_AddDataCopy( rect_list, data_ptr ); LinkedList_ToNext( &layer->dirty_rect ); } } }
/** 从程序任务队列中删除有指定回调函数的任务 */ int LCUI_RemoveTask( CallBackFunc task_func, LCUI_BOOL need_lock ) { int n; LCUI_Task *exist_task; if( need_lock ) { LCUIMutex_Lock( &MainApp.task_list_mutex ); } n = LinkedList_GetTotal( &MainApp.task_list ); for ( ; n>0; --n ) { exist_task = (LCUI_Task*)LinkedList_Get( &MainApp.task_list ); if( exist_task && exist_task->func == task_func ) { LinkedList_Delete( &MainApp.task_list ); } else { LinkedList_ToNext( &MainApp.task_list ); } } if( need_lock ) { LCUIMutex_Unlock( &MainApp.task_list_mutex ); } return n; }
/** 派发当前待处理的事件至对应的处理器 */ int $(Dispatch)( LCUI_EventBox box ) { int i, n; LCUI_Event *e; LinkedList *elist; elist = &box->events[box->current]; box->current = box->current ? 0:1; n = LinkedList_GetTotal( elist ); LinkedList_Goto( elist, 0 ); DEBUG_MSG("event total: %d\n", n); for( i=0; i<n; ++i ) { e = (LCUI_Event*)LinkedList_Get( elist ); $(Send)( box, e->name, e->data ); e->destroy_data ? e->destroy_data( e->data ):0; e->data = NULL; LinkedList_Goto( elist, 0 ); LinkedList_Delete( elist ); } DEBUG_MSG("quit\n"); return 0; }
/** 清除已记录的无效矩形 */ void TextLayer_ClearInvalidRect( LCUI_TextLayer *layer ) { int n; LCUI_Rect *rect_ptr; LCUI_Graph invalid_graph; if( !layer->is_using_buffer ) { DirtyRectList_Destroy( &layer->dirty_rect ); DirtyRectList_Init( &layer->dirty_rect ); return; } n = LinkedList_GetTotal( &layer->dirty_rect ); LinkedList_Goto( &layer->dirty_rect, 0 ); while(n--) { rect_ptr = (LCUI_Rect*)LinkedList_Get( &layer->dirty_rect ); Graph_Quote( &invalid_graph, &layer->graph, rect_ptr ); Graph_FillAlpha( &invalid_graph, 0 ); LinkedList_ToNext( &layer->dirty_rect ); } DirtyRectList_Destroy( &layer->dirty_rect ); DirtyRectList_Init( &layer->dirty_rect ); }
static int LCUIDisplay_Seamless( void ) { int i, n; LCUI_Widget widget; DEBUG_MSG("display.mode: %d\n", display.mode); switch( display.mode ) { case LDM_SEAMLESS: return 0; case LDM_FULLSCREEN: case LDM_WINDOWED: default: LCUIDisplay_CleanSurfaces(); break; } n = LinkedList_GetTotal( &LCUIRootWidget->children ); for( i=0; i<n; ++i ) { LinkedList_Goto( &LCUIRootWidget->children, i ); widget = (LCUI_Widget) LinkedList_Get( &LCUIRootWidget->children ); LCUIDisplay_BindSurface( widget ); } display.mode = LDM_SEAMLESS; return 0; }
/** 运行目标主循环 */ int LCUI_MainLoop_Run( LCUI_MainLoop loop ) { if( loop->state == STATE_RUNNING ) { _DEBUG_MSG("error: main-loop already running."); return -1; } DEBUG_MSG("loop: %p, enter\n", loop); loop->state = STATE_RUNNING; /* 将主循环记录插入至列表表头 */ LinkedList_Goto( &MainApp.loop_list, 0 ); LinkedList_Insert( &MainApp.loop_list, loop ); MainApp.loop = loop; LCUIMutex_Lock( &MainApp.loop_changed ); /* 广播,让其它线程交出主循环运行权 */ LCUICond_Broadcast( &MainApp.loop_cond ); /* 获取运行权 */ LCUIMutex_Lock( &MainApp.loop_mutex ); LCUIMutex_Unlock( &MainApp.loop_changed ); loop->tid = LCUIThread_SelfID(); while( loop->state != STATE_EXITED ) { if( LinkedList_GetTotal(&MainApp.task_list) <= 0 ) { DEBUG_MSG("loop: %p, sleeping...\n", loop); LCUICond_TimedWait( &MainApp.loop_cond, 1000 ); DEBUG_MSG("loop: %p, wakeup\n", loop); /** 如果当前运行的主循环不是自己 */ if( MainApp.loop != loop ) { loop->state = STATE_PAUSED; DEBUG_MSG("loop: %p, release control.\n", loop); LCUIMutex_Unlock( &MainApp.loop_mutex ); /* 等待其它线程获得主循环运行权 */ LCUIMutex_Lock( &MainApp.loop_changed ); LCUIMutex_Unlock( &MainApp.loop_changed ); DEBUG_MSG("loop: %p, waiting...\n", loop); /* 等待其它线程释放主循环运行权 */ LCUIMutex_Lock( &MainApp.loop_mutex ); } continue; } DEBUG_MSG("loop: %p, run task.\n", loop); LCUI_RunTask(); } loop->state = STATE_EXITED; LinkedList_Goto( &MainApp.loop_list, 0 ); LinkedList_Delete( &MainApp.loop_list ); /* 获取处于列表表头的主循环 */ loop = (LCUI_MainLoop)LinkedList_Get( &MainApp.loop_list ); if( loop ) { /* 改变当前运行的主循环 */ MainApp.loop = loop; LCUICond_Broadcast( &MainApp.loop_cond ); } /* 释放运行权 */ LCUIMutex_Unlock( &MainApp.loop_mutex ); /* 如果列表为空,一般意味着LCUI需要退出了 */ if( LinkedList_GetTotal( &MainApp.loop_list ) <= 0 ) { /** 广播,通知相关线程开始进行清理操作 */ LCUICond_Broadcast( &MainApp.loop_list_empty ); } DEBUG_MSG("loop: %p, exit\n", loop); return 0; }
/** * 渲染指定部件呈现的图形内容 * @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; }