LCUI_API int Graph_PutImage( LCUI_Graph *graph, LCUI_Graph *image, int flag ) { LCUI_Pos pos; if(!Graph_IsValid(graph) || ! Graph_IsValid(image)) { return -1; } pos.x = pos.y = 0; if((flag & ALIGN_TOP_LEFT) == ALIGN_TOP_LEFT); /* 左上角对齐 */ else if((flag & ALIGN_TOP_CENTER) == ALIGN_TOP_CENTER) { /* 向上中间对齐 */ pos.x = (graph->w - image->w) / 2; }/* 向右上角对齐 */ else if((flag & ALIGN_TOP_RIGHT) == ALIGN_TOP_RIGHT) { pos.x = graph->w - image->w; }/* 向中央偏左对齐 */ else if((flag & ALIGN_MIDDLE_LEFT) == ALIGN_MIDDLE_LEFT) { pos.y = (graph->h - image->h) / 2; }/* 向正中央对齐 */ else if((flag & ALIGN_MIDDLE_CENTER) == ALIGN_MIDDLE_CENTER) { pos.x = (graph->w - image->w) / 2; pos.y = (graph->h - image->h) / 2; }/* 向中央偏右对齐 */ else if((flag & ALIGN_MIDDLE_RIGHT) == ALIGN_MIDDLE_RIGHT) { pos.x = graph->w - image->w; pos.y = (graph->h - image->h) / 2; }/* 向底部偏左对齐 */ else if((flag & ALIGN_BOTTOM_LEFT) == ALIGN_BOTTOM_LEFT) { pos.y = graph->h - image->h; }/* 向底部居中对齐 */ else if((flag & ALIGN_BOTTOM_CENTER) == ALIGN_BOTTOM_CENTER) { pos.x = (graph->w - image->w) / 2; pos.y = graph->h - image->h; }/* 向底部偏右对齐 */ else if((flag & ALIGN_BOTTOM_RIGHT) == ALIGN_BOTTOM_RIGHT) { pos.x = graph->w - image->w; pos.y = graph->h - image->h; } if( Check_Option(flag, GRAPH_MIX_FLAG_OVERLAY) ) { /* 如果包含GRAPH_MIX_FLAG_OVERLAY选项 */ Graph_Mix(graph, image, pos); } else if( Check_Option(flag, GRAPH_MIX_FLAG_REPLACE) ) { /* 如果包含GRAPH_MIX_FLAG_REPLACE选项 */ Graph_Replace(graph, image, pos); } else { Graph_Mix(graph, image, pos); } return 0; }
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 Graph_FillImage( LCUI_Graph *graph, LCUI_Graph *bg, int mode, LCUI_RGB color ) { LCUI_Size size; LCUI_Pos pos; LCUI_Graph temp_bg; LCUI_BOOL replace_mix; if( Check_Option( mode, GRAPH_MIX_FLAG_REPLACE ) ) { /* 将alpha通道置为0 */ Graph_FillAlpha( graph, 0 ); replace_mix = TRUE; } else { /* 填充背景色,将alpha通道置为255 */ Graph_FillColor( graph, color ); Graph_FillAlpha( graph, 255 ); replace_mix = FALSE; } if(!Graph_IsValid(bg) || !Graph_IsValid(graph)) { return -1; } size.w = graph->w; size.h = graph->h; Graph_Init(&temp_bg); pos.x = pos.y = 0; /* 平铺 */ if( Check_Option( mode, LAYOUT_TILE ) ) { return Graph_Tile( bg, graph, replace_mix ); } /* 缩放 */ if( Check_Option( mode, LAYOUT_ZOOM ) ) { Graph_Zoom( bg, &temp_bg, TRUE, size ); pos.x = (size.w - temp_bg.w) / 2.0; pos.y = (size.h - temp_bg.h) / 2.0; bg = &temp_bg; } /* 拉伸 */ else if( Check_Option( mode, LAYOUT_STRETCH ) ) { Graph_Zoom( bg, &temp_bg, FALSE, size ); bg = &temp_bg; } /* 居中 */ else if( Check_Option( mode, LAYOUT_CENTER ) ) { pos.x = (size.w - bg->w) / 2.0; pos.y = (size.h - bg->h) / 2.0; } if( replace_mix ) { Graph_Replace( graph, bg, pos ); } else { Graph_Mix( graph, bg, pos ); } Graph_Free( &temp_bg ); return 0; }
LCUI_API int Graph_Tile( LCUI_Graph *src, LCUI_Graph *des, LCUI_BOOL replace ) { int ret = 0; LCUI_Pos pos; if(!Graph_IsValid(src) || !Graph_IsValid(des)) { return -1; } for(pos.y=0; pos.y<des->h; pos.y+=src->h) { for(pos.x=0; pos.x<des->w; pos.x+=src->w) { if( replace ) { ret += Graph_Replace( des, src, pos ); } else { ret += Graph_Mix( des, src, pos ); } } } return ret; }
int Graph_Tile( LCUI_Graph *buff, const LCUI_Graph *graph, LCUI_BOOL replace ) { int ret = 0; LCUI_Pos pos; if(!Graph_IsValid(graph) || !Graph_IsValid(buff)) { return -1; } for(pos.y=0; pos.y<buff->h; pos.y+=graph->h) { for(pos.x=0; pos.x<buff->w; pos.x+=graph->w) { if( replace ) { ret += Graph_Replace( buff, graph, pos ); } else { ret += Graph_Mix( buff, graph, pos ); } } } return ret; }
/** * 渲染指定部件呈现的图形内容 * @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 void Exec_Update_PictureBox(LCUI_Widget *widget) /* 功能:更新PictureBox部件 */ { LCUI_Pos pos; LCUI_PictureBox *pic_box; LCUI_Graph graph, *p; //printf("Exec_Update_PictureBox(): start\n"); pos = Pos(0,0); Graph_Init(&graph); pic_box = (LCUI_PictureBox*)Get_Widget_PrivData(widget); //print_widget_info(widget); //Print_Graph_Info(&widget->graph); //Print_Graph_Info(pic_box->image); //printf("Exec_Update_PictureBox(): 1\n"); if(! Graph_Valid(pic_box->image)) return; //printf("Exec_Update_PictureBox(): widget size: w: %d, h: %d\n", widget->size.w, widget->size.h); //printf("Exec_Update_PictureBox(): read box: %d,%d,%d,%d\n", //pic_box->read_box.x, pic_box->read_box.y, //pic_box->read_box.width, pic_box->read_box.height); switch(pic_box->size_mode) { case SIZE_MODE_BLOCK_ZOOM: case SIZE_MODE_ZOOM: /* 裁剪图像 */ if(pic_box->scale == 1.00) p = pic_box->image; else p = &pic_box->buff_graph; if(! Graph_Valid(p)) { //printf("! Graph_Valid(p)\n"); return; } pos.x = (widget->size.w - pic_box->read_box.width)/2.0; pos.y = (widget->size.h - pic_box->read_box.height)/2.0; /* 引用图像中指定区域的图形 */ Quote_Graph(&graph, p, pic_box->read_box); break; case SIZE_MODE_NORMAL:/* 正常模式 */ Quote_Graph(&graph, pic_box->image, pic_box->read_box); break; case SIZE_MODE_STRETCH:/* 拉伸模式 */ /* 开始缩放图片 */ Graph_Zoom( pic_box->image, &graph, CUSTOM, widget->size ); break; case SIZE_MODE_TILE:/* 平铺模式 */ Graph_Tile( pic_box->image, &graph, widget->size.w, widget->size.h); break; case SIZE_MODE_CENTER: /* 判断图像的尺寸是否小于图片盒子的尺寸,并计算坐标位置 */ if(pic_box->image->width < widget->size.w) { pic_box->read_box.x = 0; pic_box->read_box.width = pic_box->image->width; pos.x = (widget->size.w - pic_box->image->width)/2 + 0.5; } if(pic_box->image->height < widget->size.h) { pos.y = (widget->size.h - pic_box->image->height)/2 + 0.5; pic_box->read_box.y = 0; pic_box->read_box.height = pic_box->image->height; } if(pic_box->read_box.y + pic_box->read_box.height >= pic_box->image->height) /* 如果读取区域的尺寸大于图片尺寸 */ pic_box->read_box.y = pic_box->image->height - pic_box->read_box.height; if(pic_box->read_box.x + pic_box->read_box.width >= pic_box->image->width) pic_box->read_box.x = pic_box->image->width - pic_box->read_box.width; Quote_Graph(&graph, pic_box->image, pic_box->read_box); break; default : break; } // 用于调试 //printf("Exec_Update_PictureBox(): read box: %d,%d,%d,%d; %d/%d, %d/%d\n", //pic_box->read_box.x, pic_box->read_box.y, //pic_box->read_box.width, pic_box->read_box.height, //pic_box->read_box.x + pic_box->read_box.width, pic_box->buff_graph.width, //pic_box->read_box.y + pic_box->read_box.height, pic_box->buff_graph.height); if(!Graph_Valid(&widget->background_image)) { Graph_Replace(&widget->graph, &graph, pos); } else { Graph_Mix(&widget->graph, &graph, pos); } Graph_Free(&graph); //printf("scale: %.4f\n", pic_box->scale); //printf("Exec_Update_PictureBox(): end\n"); Refresh_Widget(widget); }
/* 在PictureBox部件更新时进行附加处理 */ static void PictureBox_ExecUpdate(LCUI_Widget *widget) { LCUI_Pos pos; LCUI_PictureBox *pic_box; LCUI_Graph graph, *widget_graph, *p; pos = Pos(0,0); Graph_Init(&graph); pic_box = (LCUI_PictureBox*)Widget_GetPrivData(widget); widget_graph = Widget_GetSelfGraph( widget ); //print_widget_info(widget); //Graph_PrintInfo(widget_graph); //Graph_PrintInfo(pic_box->image); //printf("PictureBox_ExecUpdate(): 1\n"); if(! Graph_IsValid(pic_box->image)) { return; } //printf("PictureBox_ExecUpdate(): widget size: w: %d, h: %d\n", widget->size.w, widget->size.h); //printf("PictureBox_ExecUpdate(): read box: %d,%d,%d,%d\n", //pic_box->read_box.x, pic_box->read_box.y, //pic_box->read_box.width, pic_box->read_box.height); switch(pic_box->size_mode) { case SIZE_MODE_BLOCK_ZOOM: case SIZE_MODE_ZOOM: /* 裁剪图像 */ if(pic_box->scale == 1.00) p = pic_box->image; else p = &pic_box->buff_graph; if(! Graph_IsValid(p)) { //printf("! Graph_IsValid(p)\n"); return; } pos.x = (widget->size.w - pic_box->read_box.width)/2.0; pos.y = (widget->size.h - pic_box->read_box.height)/2.0; /* 引用图像中指定区域的图形 */ Graph_Quote(&graph, p, pic_box->read_box); break; case SIZE_MODE_NORMAL:/* 正常模式 */ Graph_Quote(&graph, pic_box->image, pic_box->read_box); break; case SIZE_MODE_STRETCH:/* 拉伸模式 */ /* 开始缩放图片 */ Graph_Zoom( pic_box->image, &graph, FALSE, widget->size ); break; case SIZE_MODE_TILE:/* 平铺模式 */ Graph_Tile( pic_box->image, &graph, TRUE ); break; case SIZE_MODE_CENTER: /* 判断图像的尺寸是否小于图片盒子的尺寸,并计算坐标位置 */ if(pic_box->image->w < widget->size.w) { pic_box->read_box.x = 0; pic_box->read_box.width = pic_box->image->w; pos.x = (widget->size.w - pic_box->image->w)/2 + 0.5; } if(pic_box->image->h < widget->size.h) { pos.y = (widget->size.h - pic_box->image->h)/2 + 0.5; pic_box->read_box.y = 0; pic_box->read_box.height = pic_box->image->h; } if(pic_box->read_box.y + pic_box->read_box.height >= pic_box->image->h) /* 如果读取区域的尺寸大于图片尺寸 */ pic_box->read_box.y = pic_box->image->h - pic_box->read_box.height; if(pic_box->read_box.x + pic_box->read_box.width >= pic_box->image->w) pic_box->read_box.x = pic_box->image->w - pic_box->read_box.width; Graph_Quote(&graph, pic_box->image, pic_box->read_box); break; default : break; } // 用于调试 //printf("PictureBox_ExecUpdate(): read box: %d,%d,%d,%d; %d/%d, %d/%d\n", //pic_box->read_box.x, pic_box->read_box.y, //pic_box->read_box.width, pic_box->read_box.height, //pic_box->read_box.x + pic_box->read_box.width, pic_box->buff_graph.w, //pic_box->read_box.y + pic_box->read_box.height, pic_box->buff_graph.h); if(!Graph_IsValid(&widget->background.image)) { Graph_Replace( widget_graph, &graph, pos ); } else { Graph_Mix( widget_graph, &graph, pos ); } Graph_Free(&graph); //printf("scale: %.4f\n", pic_box->scale); //printf("PictureBox_ExecUpdate(): end\n"); Widget_Refresh(widget); }
LCUI_API int GraphLayer_GetGraph( LCUI_GraphLayer *ctnr, LCUI_Graph *graph_buff, LCUI_Rect rect ) { int i, total; uchar_t tmp_alpha, alpha; LCUI_Pos pos, glayer_pos; LCUI_GraphLayer *glayer; LCUI_Queue glayerQ; LCUI_Rect valid_area; LCUI_Graph tmp_graph; /* 检测这个区域是否有效 */ if (rect.x < 0 || rect.y < 0) { return -1; } if (rect.x + rect.width > ctnr->graph.w || rect.y + rect.height > ctnr->graph.h ) { return -1; } if (rect.width <= 0 || rect.height <= 0) { return -2; } if( !Graph_IsValid(graph_buff) ) { graph_buff->color_type = COLOR_TYPE_ARGB; Graph_Create( graph_buff, rect.width, rect.height ); } Graph_Init( &tmp_graph ); Queue_Init( &glayerQ, 0, NULL); Queue_UsingPointer( &glayerQ ); /* 获取rect区域内的图层列表 */ GraphLayer_GetLayers( ctnr, rect, &glayerQ ); total = Queue_GetTotal( &glayerQ ); DEBUG_MSG( "total: %d\n", total ); /* 若记录数为零,则表明该区域没有图层 */ if( total <= 0 ) { /* 若没有父图层,则填充白色 */ if( ctnr == NULL ) { Graph_FillColor( graph_buff, RGB(255,255,255) ); } else { /* 否则使用父图层的图形 */ Graph_Cut( &ctnr->graph, rect, graph_buff ); } /* 销毁记录 */ Queue_Destroy( &glayerQ ); return 0; } /* 从顶层到底层遍历图层,排除被其它图层完全遮挡或者自身完全透明的图层 */ for(i=total-1; i>=0; --i) { glayer = (LCUI_GraphLayer*)Queue_Get( &glayerQ, i ); valid_area = GraphLayer_GetValidRect( ctnr, glayer ); glayer_pos = GraphLayer_GetGlobalPos( ctnr, glayer ); valid_area.x += glayer_pos.x; valid_area.y += glayer_pos.y; alpha = GraphLayer_GetRealAlpha( glayer ); /* 当前图层的透明度小于255的话,就跳过 */ if( alpha < 255 ) { continue; } /* 跳过有alpha通道的图层 */ if( glayer->graph.color_type == COLOR_TYPE_ARGB ) { continue; } /* 如果该图层的有效区域包含目标区域 */ if( rect.x >= valid_area.x && rect.y >= valid_area.y && rect.x + rect.w <= valid_area.x + valid_area.w && rect.y + rect.h <= valid_area.y + valid_area.h ) { /* 移除底层的图层,因为已经被完全遮挡 */ for(total=i-1;total>=0; --total) { Queue_DeletePointer( &glayerQ, 0 ); } goto skip_loop; } } skip_loop: total = Queue_GetTotal( &glayerQ ); DEBUG_MSG( "total: %d\n", total ); if(i <= 0 && ctnr ) { Graph_Cut( &ctnr->graph, rect, graph_buff ); } /* 获取图层列表中的图层 */ for(i=0; i<total; ++i) { glayer = (LCUI_GraphLayer*)Queue_Get( &glayerQ, i ); //_DEBUG_MSG("%p = Queue_Get( %p, %d )\n", glayer, &glayerQ, i); if( !glayer ) { continue; } DEBUG_MSG("%d,%d,%d,%d\n", glayer->pos.x, glayer->pos.y, glayer->graph.w, glayer->graph.h); /* 获取该图层的有效区域及全局坐标 */ pos = GraphLayer_GetGlobalPos( ctnr, glayer ); valid_area = GraphLayer_GetValidRect( ctnr, glayer ); /* 引用该图层的有效区域内的图像 */ Graph_Quote( &tmp_graph, &glayer->graph, valid_area ); //_DEBUG_MSG("valid area: %d,%d,%d,%d, pos: %d,%d, size: %d,%d\n", // valid_area.x, valid_area.y, valid_area.width, valid_area.height, // pos.x, pos.y, glayer->graph.w, glayer->graph.h // ); /* 获取相对坐标 */ pos.x = pos.x - rect.x + valid_area.x; pos.y = pos.y - rect.y + valid_area.y; //_DEBUG_MSG("mix pos: %d,%d\n", pos.x, pos.y); /* 如果该图层没有继承父图层的透明度 */ if( !glayer->inherit_alpha ) { /* 直接叠加至graph_buff */ Graph_Mix( graph_buff, &tmp_graph, pos ); } else { /* 否则,计算该图层应有的透明度 */ alpha = GraphLayer_GetRealAlpha( glayer ); /* 备份该图层的全局透明度 */ tmp_alpha = glayer->graph.alpha; /* 将实际透明度作为全局透明度,参与图像叠加 */ glayer->graph.alpha = alpha; Graph_Mix( graph_buff, &tmp_graph, pos ); /* 还原全局透明度 */ glayer->graph.alpha = tmp_alpha; } } Queue_Destroy( &glayerQ ); return 0; }
void Graph_DrawBackground( LCUI_PaintContext paint, const LCUI_Rect *box, LCUI_Background *bg ) { float scale; LCUI_Graph graph; LCUI_BOOL with_alpha; LCUI_Rect read_rect, paint_rect; int image_x, image_y, image_w, image_h; /* 计算背景图应有的尺寸 */ if( bg->size.using_value ) { switch( bg->size.value ) { case SV_CONTAIN: image_w = box->width; scale = 1.0 * bg->image.width / image_w; image_h = 1.0 * bg->image.height / scale; if( image_h > box->height ) { image_h = box->height; scale = 1.0 * bg->image.height / box->height; image_w = (int)(1.0 * bg->image.width / scale); } break; case SV_COVER: image_w = box->width; scale = 1.0 * bg->image.width / image_w; image_h = 1.0 * bg->image.height / scale; if( image_h < box->height ) { image_h = box->height; scale = 1.0 * bg->image.height / image_h; image_w = (int)(1.0 * bg->image.width / scale); } break; case SV_AUTO: default: image_w = bg->image.width; image_h = bg->image.height; break; } } else { switch( bg->size.w.type ) { case SVT_SCALE: image_w = box->w * bg->size.w.scale; break; case SVT_PX: image_w = bg->size.w.px; break; default: image_w = bg->image.width; break; } switch( bg->size.h.type ) { case SVT_SCALE: image_h = box->h * bg->size.h.scale; break; case SVT_PX: image_h = bg->size.h.px; break; default: image_h = bg->image.height; break; } } /* 计算背景图的像素坐标 */ if( bg->position.using_value ) { switch( bg->position.value ) { case SV_TOP: case SV_TOP_CENTER: image_x = (box->w - image_w) / 2; image_y = 0; break; case SV_TOP_RIGHT: image_x = box->w - image_w; image_y = 0; break; case SV_CENTER_LEFT: image_x = 0; image_y = (box->h - image_h) / 2; break; case SV_CENTER: case SV_CENTER_CENTER: image_x = (box->w - image_w) / 2; image_y = (box->h - image_h) / 2; break; case SV_CENTER_RIGHT: image_x = box->w - image_w; image_y = (box->h - image_h) / 2; break; case SV_BOTTOM_LEFT: image_x = 0; image_y = box->h - image_h; break; case SV_BOTTOM_CENTER: image_x = (box->w - image_w) / 2; image_y = box->h - image_h; break; case SV_BOTTOM_RIGHT: image_x = box->w - image_w; image_y = box->h - image_h; break; case SV_TOP_LEFT: default:image_x = image_y = 0; break; } } else { switch( bg->position.x.type ) { case SVT_SCALE: image_x = box->w - image_w; image_x *= bg->position.x.scale; break; case SVT_PX: image_x = bg->position.x.px; break; default:image_x = 0; break; } switch( bg->position.y.type ) { case SVT_SCALE: image_y = box->h - image_h; image_y *= bg->position.y.scale; break; case SVT_PX: image_y = bg->position.y.px; break; default:image_y = 0; break; } } /* 获取当前绘制区域与背景内容框的重叠区域 */ if( !LCUIRect_GetOverlayRect( box, &paint->rect, &paint_rect ) ) { return; } with_alpha = bg->color.alpha < 255; paint_rect.x -= paint->rect.x; paint_rect.y -= paint->rect.y; Graph_Quote( &graph, &paint->canvas, &paint_rect ); Graph_FillRect( &graph, bg->color, NULL, TRUE ); /* 将坐标转换为相对于背景内容框 */ paint_rect.x += paint->rect.x - box->x; paint_rect.y += paint->rect.y - box->y; /* 保存背景图像区域 */ read_rect.x = image_x; read_rect.y = image_y; read_rect.width = image_w; read_rect.height = image_h; /* 获取当前绘制区域与背景图像的重叠区域 */ if( !LCUIRect_GetOverlayRect( &read_rect, &paint_rect, &read_rect ) ) { return; } /* 转换成相对于图像的坐标 */ read_rect.x -= image_x; read_rect.y -= image_y; /* 如果尺寸没有变化则直接引用 */ if( image_w == bg->image.w && image_h == bg->image.h ) { Graph_Quote( &graph, &bg->image, &read_rect ); /* 转换成相对于当前绘制区域的坐标 */ image_x = image_x + box->x - paint->rect.x; image_y = image_y + box->y - paint->rect.y; image_x += read_rect.x; image_y += read_rect.y; Graph_Mix( &paint->canvas, &graph, image_x, image_y, with_alpha ); } else { float scale; LCUI_Graph buffer; LCUI_Rect quote_rect; Graph_Init( &buffer ); quote_rect = read_rect; /* 根据宽高的缩放比例,计算实际需要引用的区域 */ if( image_w != bg->image.w ) { scale = 1.0 * bg->image.width / image_w; quote_rect.x *= scale; quote_rect.width *= scale; } if( image_h != bg->image.h ) { scale = 1.0 * bg->image.height / image_h; quote_rect.y *= scale; quote_rect.height *= scale; } /* 引用源背景图像的一块区域 */ Graph_Quote( &graph, &bg->image, "e_rect ); image_w = read_rect.width; image_h = read_rect.height; /* 计算相对于绘制区域的坐标 */ image_x = read_rect.x + image_x; image_x = image_x + box->x - paint->rect.x; image_y = read_rect.y + image_y; image_y = image_y + box->y - paint->rect.y; /* 按比例进行缩放 */ Graph_Zoom( &graph, &buffer, FALSE, image_w, image_h ); Graph_Mix( &paint->canvas, &buffer, image_x, image_y, with_alpha ); Graph_Free( &buffer ); } }