int Graph_Mix( LCUI_Graph *back, const LCUI_Graph *fore, LCUI_Pos pos ) { LCUI_Graph write_slot; LCUI_Rect read_rect, write_rect; void (*mixer)(LCUI_Graph*, LCUI_Rect, const LCUI_Graph *, LCUI_Pos) = NULL; /* 预先进行有效性判断 */ if( !Graph_IsValid(back) || !Graph_IsValid(fore) ) { return -1; } write_rect.x = pos.x; write_rect.y = pos.y; write_rect.width = fore->width; write_rect.height = fore->height; LCUIRect_GetCutArea( Size( back->width, back->height ), write_rect, &read_rect ); write_rect.x += read_rect.x; write_rect.y += read_rect.y; write_rect.width = read_rect.width; write_rect.height = read_rect.height; Graph_Quote( &write_slot, back, &write_rect ); /* 获取实际操作区域 */ Graph_GetValidRect( &write_slot, &write_rect ); Graph_GetValidRect( fore, &read_rect ); /* 若读或写的区域无效 */ if( write_rect.width <= 0 || write_rect.height <= 0 || read_rect.width <= 0 || read_rect.height <= 0 ) { return -2; } pos.x = read_rect.x; pos.y = read_rect.y; /* 获取引用的源图像 */ fore = Graph_GetQuote( fore ); back = Graph_GetQuote( back ); switch( fore->color_type ) { case COLOR_TYPE_RGB888: if( back->color_type == COLOR_TYPE_RGB888 ) { mixer = Graph_RGBReplaceRGB; } else { mixer = Graph_ARGBReplaceRGB; } break; case COLOR_TYPE_ARGB8888: if( back->color_type == COLOR_TYPE_RGB888 ) { mixer = Graph_RGBMixARGB; } else { mixer = Graph_ARGBMixARGB; } default:break; } if( mixer ) { mixer( back, write_rect, fore, pos ); return 0; } return -3; }
LCUI_API int LCUIScreen_PutGraph (LCUI_Graph *graph, LCUI_Pos des_pos ) { int total, y, n, des_row_x, src_row_x, des_x, src_x; LCUI_Graph *src; LCUI_Rect cut, src_rect; LCUI_Size screen_size; uchar_t *des_ptr; src = Graph_GetQuote( graph ); src_rect = Graph_GetValidRect( graph ); screen_size = LCUIScreen_GetSize(); if(!Graph_IsValid(src)) { return -1; } if(des_pos.x >= screen_size.w || des_pos.y >= screen_size.h) { return -1; } des_ptr = pixel_mem; Graph_Lock( src ); /* 获取图像的截取区域 */ if( LCUIRect_GetCutArea( screen_size, Rect( des_pos.x, des_pos.y, src_rect.width, src_rect.height ), &cut )) { des_pos.x += cut.x; des_pos.y += cut.y; } /* 根据二维坐标和图像尺寸,计算源图像的起始读取点的一维坐标 */ src_row_x = (cut.y + src_rect.y) * src->width + cut.x + src_rect.x; /* 根据二维坐标和屏幕尺寸,计算帧缓冲的起始写入点的一维坐标 */ des_row_x = des_pos.y * screen_size.w + des_pos.x; for(y=0; y<cut.height; ++y) { src_x = src_row_x; des_x = des_row_x; total = src_x + cut.width; for (; src_x < total; ++des_x,++src_x) { n = des_x << 2; des_ptr[n++] = src->rgba[2][src_x]; des_ptr[n++] = src->rgba[1][src_x]; des_ptr[n++] = src->rgba[0][src_x]; } src_row_x += src->width; /* DIB扫描行是上下颠倒的,因此是从行尾到行首递减 */ des_row_x += screen_size.w; } Graph_Unlock( src ); return 0; }
LCUI_API int Graph_Mix( LCUI_Graph *back_graph, LCUI_Graph *fore_graph, LCUI_Pos des_pos ) { LCUI_Graph *src, *des; LCUI_Rect cut, src_rect, area, des_rect; LCUI_Size box_size; LCUI_Pos src_pos; /* 预先进行有效性判断 */ if( !Graph_IsValid(back_graph) || !Graph_IsValid(fore_graph) ) { return -1; } /* 获取引用的源图像的最终区域 */ src_rect = Graph_GetValidRect(fore_graph); des_rect = Graph_GetValidRect(back_graph); /* 获取引用的源图像 */ src = Graph_GetQuote(fore_graph); des = Graph_GetQuote(back_graph); /* 判断引用的源图像的有效性 */ if(!Graph_IsValid(des) || !Graph_IsValid(src)) { return -1; } /* 判断坐标是否在背景图的范围内 */ if(des_pos.x > des->w || des_pos.y > des->h) { return -1; } /* 记录容器尺寸 */ box_size.w = des_rect.width; box_size.h = des_rect.height; /* 记录前景图像在容器中的区域 */ area.x = des_pos.x; area.y = des_pos.y; area.width = src_rect.width; area.height = src_rect.height; /* 获取前景图像区域中的需要裁减的区域 */ LCUIRect_GetCutArea( box_size, area, &cut ); /* 移动前景图像区域的坐标 */ des_pos.x += cut.x; des_pos.y += cut.y; /* 得出源图像的读取区域的坐标 */ src_pos.x = cut.x + src_rect.x; src_pos.y = cut.y + src_rect.y; /* 得出目标图像的写入区域 */ des_rect.x = des_pos.x + des_rect.x; des_rect.y = des_pos.y + des_rect.y; des_rect.width = cut.width; des_rect.height = cut.height; /* 如果前景图像有alpha通道 */ if( src->color_type == COLOR_TYPE_RGBA ) { /* 如果全局透明度为255,则说明混合时不需要考虑全局透明度 */ if( src->alpha == 255 ) { Graph_RGBAMix( des, des_rect, src, src_pos ); return 0; } Graph_RGBAMixWithGlobalAlpha( des, des_rect, src, src_pos ); return 0; } /* 否则,前景图像没有Alpha通道 */ /* 如果全局透明度为255,说明前景图形没有透明效果 */ if( src->alpha == 255 ) { Graph_RGBMix( des, des_rect, src, src_pos ); return 0; } /* 否则,将全局透明度计算在内,进行alpha混合 */ Graph_RGBMixWithGlobalAlpha( des, des_rect, des, src_pos ); return 0; }
LCUI_API int Graph_Replace( LCUI_Graph *back_graph, LCUI_Graph *fore_graph, LCUI_Pos des_pos ) { LCUI_Graph *src, *des; LCUI_Rect cut, src_rect, area, des_rect; LCUI_Size box_size; LCUI_Pos src_pos; /* 预先进行有效性判断 */ if( !Graph_IsValid(back_graph) || !Graph_IsValid(fore_graph) ) { return -1; } /* 获取引用的源图像的最终区域 */ src_rect = Graph_GetValidRect(fore_graph); des_rect = Graph_GetValidRect(back_graph); /* 获取引用的源图像 */ src = Graph_GetQuote(fore_graph); des = Graph_GetQuote(back_graph); /* 判断引用的源图像的有效性 */ if(!Graph_IsValid(des) || !Graph_IsValid(src)) { return -1; } /* 判断坐标是否在背景图的范围内 */ if(des_pos.x > des->w || des_pos.y > des->h) { return -1; } /* 记录容器尺寸 */ box_size.w = des_rect.width; box_size.h = des_rect.height; /* 记录前景图像在容器中的区域 */ area.x = des_pos.x; area.y = des_pos.y; area.width = src_rect.width; area.height = src_rect.height; /* 获取前景图像区域中的需要裁减的区域 */ LCUIRect_GetCutArea( box_size, area, &cut ); /* 移动前景图像区域的坐标 */ des_pos.x += cut.x; des_pos.y += cut.y; /* 得出源图像的读取区域的坐标 */ src_pos.x = cut.x + src_rect.x; src_pos.y = cut.y + src_rect.y; /* 得出目标图像的写入区域 */ des_rect.x = des_pos.x + des_rect.x; des_rect.y = des_pos.y + des_rect.y; des_rect.width = cut.width; des_rect.height = cut.height; /* 如果前景图像有透明度 */ if( src->color_type == COLOR_TYPE_RGBA ) { /* 若背景图有透明度 */ if( des->color_type == COLOR_TYPE_RGBA ) { return Graph_DirectReplace( des, des_rect, src, src_pos ); } if( src->alpha == 255 ) { return Graph_RGBAReplaceRGB( des, des_rect, src, src_pos ); } return Graph_RGBAReplaceRGBWithGlobalAlpha( des, des_rect, src, src_pos ); } if( des->color_type == COLOR_TYPE_RGBA ) { return Graph_RGBReplaceRGBA( des, des_rect, src, src_pos ); } return Graph_DirectReplace( des, des_rect, src, src_pos ); }
/** 将字体位图绘制到目标图像上 */ int FontBMP_Mix( LCUI_Graph *graph, LCUI_Pos pos, LCUI_FontBMP *bmp, LCUI_Color color ) { int val, x, y; LCUI_Graph *des; LCUI_Rect des_rect, cut; LCUI_ARGB *px_des, *px_row_des; uchar_t *bmp_src, *bmp_row_src, *byte_row_des, *byte_des; /* 数据有效性检测 */ if( !FontBMP_IsValid( bmp ) || !Graph_IsValid( graph ) ) { return -1; } /* 获取背景图形的有效区域 */ Graph_GetValidRect( graph, &des_rect ); /* 获取背景图引用的源图形 */ des = Graph_GetQuote( graph ); /* 起点位置的有效性检测 */ if(pos.x > des->w || pos.y > des->h) { return -2; } /* 获取需要裁剪的区域 */ LCUIRect_GetCutArea( Size( des_rect.width, des_rect.height ), Rect( pos.x, pos.y, bmp->width, bmp->rows ), &cut ); pos.x += cut.x; pos.y += cut.y; if( graph->color_type == COLOR_TYPE_ARGB ) { bmp_row_src = bmp->buffer + cut.y*bmp->width + cut.x; px_row_des = des->argb + (pos.y + des_rect.y) * des->w; px_row_des += pos.x + des_rect.x; for( y=0; y<cut.h; ++y ) { bmp_src = bmp_row_src; px_des = px_row_des; for( x=0; x<cut.w; ++x ) { ALPHA_BLEND( px_des->r, color.r, *bmp_src ); ALPHA_BLEND( px_des->g, color.g, *bmp_src ); ALPHA_BLEND( px_des->b, color.b, *bmp_src ); if( px_des->alpha == 255 || *bmp_src == 255 ) { px_des->alpha = 255; } else { val = (255 - *bmp_src)*(255 - px_des->alpha); px_des->alpha = (uchar_t)(255 - val / 65025); } ++bmp_src; ++px_des; } px_row_des += des->w; bmp_row_src += bmp->width; } return 0; } bmp_row_src = bmp->buffer + cut.y*bmp->width + cut.x; byte_row_des = des->bytes + (pos.y + des_rect.y) * des->bytes_per_row; byte_row_des += (pos.x + des_rect.x)*des->bytes_per_pixel; for( y=0; y<cut.h; ++y ) { bmp_src = bmp_row_src; byte_des = byte_row_des; for( x=0; x<cut.w; ++x ) { ALPHA_BLEND( *byte_des, color.b, *bmp_src ); byte_des++; ALPHA_BLEND( *byte_des, color.g, *bmp_src ); byte_des++; ALPHA_BLEND( *byte_des, color.r, *bmp_src ); byte_des++; ++bmp_src; } byte_row_des += des->w*3; bmp_row_src += bmp->width; } return 0; }