/** * 将色彩类型为RGB的前景图像,覆盖至色彩类型为RGBA的目标背景图像中 * param back * 背景图像 * param des_rect * 背景图像中的写入区域 * param fore * 前景图像 * param src_pos * 前景图像中的读取区域的坐标 * warning * 此函数不会对传入的参数进行有效性判断,因为此函数主要被Graph_Replace函 * 数调用,Graph_Replace函数会预先进行参数有效性判断 */ static int Graph_RGBReplaceRGBA( LCUI_Graph *back, LCUI_Rect des_rect, LCUI_Graph *fore, LCUI_Pos src_pos ) { int y; int des_n, src_n; LCUI_Graph *src, *des; src = Graph_GetQuote(fore); des = Graph_GetQuote(back); src_n = src_pos.y * src->w + src_pos.x; des_n = des_rect.y * des->w + des_rect.x; for(y=0; y<des_rect.height; ++y) { memcpy( &des->rgba[0][des_n], &src->rgba[0][src_n], des_rect.width ); memcpy( &des->rgba[1][des_n], &src->rgba[1][src_n], des_rect.width ); memcpy( &des->rgba[2][des_n], &src->rgba[2][src_n], des_rect.width ); memset( &des->rgba[3][des_n], src->alpha, des_rect.width ); des_n += des->w; src_n += src->w; } return 0; }
int Graph_Replace( LCUI_Graph *back, const LCUI_Graph *fore, LCUI_Pos pos ) { LCUI_Graph write_slot; LCUI_Rect read_rect,write_rect; 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; 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: return Graph_RGBReplaceRGB( back, write_rect, fore, pos ); case COLOR_TYPE_ARGB8888: return Graph_ARGBReplaceARGB( back, write_rect, fore, pos ); default:break; } return -1; }
/** * 将色彩类型为RGBA的前景图像,覆盖至色彩类型为RGB的目标背景图像中 * param back * 背景图像 * param des_rect * 背景图像中的写入区域 * param fore * 前景图像 * param src_pos * 前景图像中的读取区域的坐标 * warning * 此函数不会对传入的参数进行有效性判断,因为此函数主要被Graph_Replace函 * 数调用,Graph_Replace函数会预先进行参数有效性判断 */ static int Graph_RGBAReplaceRGB( LCUI_Graph *back, LCUI_Rect des_rect, LCUI_Graph *fore, LCUI_Pos src_pos ) { int x, y; int src_n, des_n; int des_row_start, src_row_start; LCUI_Graph *src, *des; src = Graph_GetQuote(fore); des = Graph_GetQuote(back); src_row_start = src_pos.y * src->w + src_pos.x; des_row_start = des_rect.y * des->w + des_rect.x; for(y=0; y<des_rect.height; ++y) { des_n = des_row_start; src_n = src_row_start; for(x=0; x<des_rect.width; ++x) { des->rgba[0][des_n] = _ALPHA_BLEND( src->rgba[0][src_n], 255, src->rgba[3][src_n] ); des->rgba[1][des_n] = _ALPHA_BLEND( src->rgba[1][src_n], 255, src->rgba[3][src_n] ); des->rgba[2][des_n] = _ALPHA_BLEND( src->rgba[2][src_n], 255, src->rgba[3][src_n] ); ++src_n; ++des_n; } des_row_start += des->w; src_row_start += src->w; } return 0; }
/** * 将前景图像,直接覆盖目标背景图像中(两个图像的色彩类型相同) * param back * 背景图像 * param des_rect * 背景图像中的写入区域 * param fore * 前景图像 * param src_pos * 前景图像中的读取区域的坐标 * warning * 此函数不会对传入的参数进行有效性判断,因为此函数主要被Graph_Replace函 * 数调用,Graph_Replace函数会预先进行参数有效性判断 */ static int Graph_DirectReplace( LCUI_Graph *back, LCUI_Rect des_rect, LCUI_Graph *fore, LCUI_Pos src_pos ) { int y; int des_n, src_n; LCUI_Graph *src, *des; src = Graph_GetQuote(fore); des = Graph_GetQuote(back); src_n = src_pos.y * src->w + src_pos.x; des_n = des_rect.y * des->w + des_rect.x; for(y=0; y<des_rect.height; ++y) { memcpy( &des->rgba[0][des_n], &src->rgba[0][src_n], des_rect.width ); memcpy( &des->rgba[1][des_n], &src->rgba[1][src_n], des_rect.width ); memcpy( &des->rgba[2][des_n], &src->rgba[2][src_n], des_rect.width ); if( des->color_type == src->color_type && des->color_type == COLOR_TYPE_RGBA ) { memcpy( &des->rgba[3][des_n], &src->rgba[3][src_n], des_rect.width ); } des_n += des->w; src_n += src->w; } return 0; }
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; }
static int Graph_VertiFlipARGB( const LCUI_Graph *graph, LCUI_Graph *buff ) { int y; LCUI_Rect rect; uchar_t *byte_src, *byte_des; if(!Graph_IsValid(graph)) { return -1; } Graph_GetValidRect( graph, &rect ); graph = Graph_GetQuote( graph ); buff->opacity = graph->opacity; buff->color_type = graph->color_type; if( 0 != Graph_Create( buff, rect.width, rect.height ) ) { return -2; } byte_src = graph->bytes + (rect.y + rect.h - 1)*graph->bytes_per_row; byte_src += rect.x * graph->bytes_per_pixel; byte_des = buff->bytes; for( y=0; y<rect.h; ++y ) { memcpy( byte_des, byte_src, buff->bytes_per_row ); byte_src -= graph->bytes_per_row; byte_des += buff->bytes_per_row; } return 0; }
static int Graph_HorizFlipARGB( const LCUI_Graph *graph, LCUI_Graph *buff ) { int x, y; LCUI_Rect rect; LCUI_ARGB *pixel_src, *pixel_des; if(!Graph_IsValid(graph)) { return -1; } Graph_GetValidRect( graph, &rect ); graph = Graph_GetQuote( graph ); buff->opacity = graph->opacity; buff->color_type = graph->color_type; if( 0 != Graph_Create( buff, rect.width, rect.height ) ) { return -2; } for( y=0; y<rect.h; ++y ) { pixel_des = buff->argb + y*buff->w; pixel_src = graph->argb + (rect.y+y)*graph->w; pixel_src += rect.x + rect.w - 1; for( x=0; x<rect.w; ++x ) { *pixel_des++ = *pixel_src--; } } return 0; }
int Graph_FillRectRGB( LCUI_Graph *graph, LCUI_Color color, LCUI_Rect rect ) { int x, y; LCUI_Graph canvas; uchar_t *rowbytep, *bytep; if(!Graph_IsValid(graph)) { return -1; } Graph_Quote( &canvas, graph, &rect ); Graph_GetValidRect( &canvas, &rect ); graph = Graph_GetQuote( &canvas ); rowbytep = graph->bytes + rect.y*graph->bytes_per_row; rowbytep += rect.x*graph->bytes_per_pixel; for( y=0; y<rect.h; ++y ) { bytep = rowbytep; for( x=0; x<rect.w; ++x ) { *bytep++ = color.blue; *bytep++ = color.green; *bytep++ = color.red; } rowbytep += graph->bytes_per_row; } return 0; }
static int Graph_HorizFlipRGB( const LCUI_Graph *graph, LCUI_Graph *buff ) { int x, y, n; LCUI_Rect rect; uchar_t *byte_src, *byte_des; if(!Graph_IsValid(graph)) { return -1; } Graph_GetValidRect( graph, &rect ); graph = Graph_GetQuote( graph ); buff->color_type = graph->color_type; if( 0 != Graph_Create( buff, rect.width, rect.height ) ) { return -2; } for( y=0; y<rect.h; ++y ) { byte_des = buff->bytes + y*buff->w*3; n = ((rect.y+y)*graph->w + rect.x + rect.w - 1)*3; byte_src = buff->bytes + n; for( x=0; x<rect.w; ++x ) { *byte_des++ = *byte_src--; *byte_des++ = *byte_src--; *byte_des++ = *byte_src--; } } return 0; }
LCUI_API int Graph_FillAlpha( LCUI_Graph *src, uchar_t alpha ) { int y, row_start; LCUI_Rect src_rect; /* 获取引用的区域在源图形中的有效区域 */ src_rect = Graph_GetValidRect( src ); /* 获取引用的源图指针 */ src = Graph_GetQuote( src ); if(! Graph_IsValid(src) ) { return -1; } if( !Graph_HaveAlpha(src) ) { return -2; } row_start = src_rect.x + src_rect.y * src->w; for(y=0; y<src_rect.height; ++y) { memset( &src->rgba[3][row_start], alpha, src_rect.width*sizeof(uchar_t) ); row_start += src->w; } return 0; }
int Graph_FillAlpha( LCUI_Graph *graph, uchar_t alpha ) { int x, y; LCUI_Rect rect; LCUI_ARGB *pixel, *pixel_row; Graph_GetValidRect( graph, &rect ); graph = Graph_GetQuote( graph ); if( !Graph_IsValid(graph) ) { return -1; } if( !Graph_HasAlpha(graph) ) { return -2; } pixel_row = graph->argb + rect.y*graph->w + rect.x; for(y=0; y<rect.h; ++y) { pixel = pixel_row; for( x=0; x<rect.w; ++x ) { pixel->alpha = alpha; ++pixel; } pixel_row += graph->w; } return 0; }
LCUI_API LCUI_BOOL Graph_GetPixel( LCUI_Graph *graph, LCUI_Pos pos, LCUI_RGBA *pixel ) { int i; LCUI_Rect rect; if( pos.x < 0 || pos.y < 0 ) { return FALSE; } rect = Graph_GetValidRect( graph ); /* 若坐标超出范围 */ if( pos.x >= rect.width || pos.y >= rect.height ) { return FALSE; } graph = Graph_GetQuote( graph ); if( !Graph_IsValid(graph) ) { return FALSE; } i = graph->w*(pos.y+rect.y) + pos.x + rect.x; pixel->red = graph->rgba[0][i]; pixel->green = graph->rgba[1][i]; pixel->blue = graph->rgba[2][i]; if(graph->color_type == COLOR_TYPE_RGBA) { pixel->alpha = graph->rgba[3][i]; } else { pixel->alpha = 255; } return TRUE; }
LCUI_API void Graph_Free( LCUI_Graph *pic ) { LCUI_Graph *p; if( pic && pic->quote ) { pic->src = NULL; pic->quote = FALSE; return; } p = Graph_GetQuote( pic ); if( !Graph_IsValid(p)) { return; } LCUIMutex_Lock( &p->mutex ); free( p->rgba[0] ); free( p->rgba[1] ); free( p->rgba[2] ); if( p->color_type == COLOR_TYPE_RGBA ) { free( p->rgba[3] ); } free( p->rgba ); p->rgba = NULL; p->w = 0; p->h = 0; LCUIMutex_Unlock( &p->mutex ); LCUIMutex_Destroy( &pic->mutex ); }
LCUI_API int Graph_VertiFlip( LCUI_Graph *src_graph, LCUI_Graph *out_graph ) { uchar_t buff; LCUI_Rect rect; int x, y, center; int src_top_pos, src_bottom_pos; int des_top_pos, des_bottom_pos; int src_start_top_pos, src_start_bottom_pos; int des_start_top_pos, des_start_bottom_pos; if(!Graph_IsValid(src_graph)) { return -1; } src_graph = Graph_GetQuote(src_graph ); rect = Graph_GetValidRect( src_graph ); out_graph->color_type = src_graph->color_type; if( 0 != Graph_Create(out_graph, rect.width, rect.height ) ) { return -2; } center = (int)(rect.height / 2.0); /* 记录基坐标 */ des_start_top_pos = 0; des_start_bottom_pos = (rect.height-1)*rect.width; src_start_top_pos = rect.y * src_graph->w + rect.x; src_start_bottom_pos = (rect.y + rect.height-1)*src_graph->w + rect.x; for (x=0; x < rect.width; ++x) { /* 当前坐标=基坐标+x */ des_top_pos = des_start_top_pos + x; des_bottom_pos = des_start_bottom_pos + x; src_top_pos = src_start_top_pos + x; src_bottom_pos = src_start_bottom_pos + x; for (y = 0; y <= center; ++y) { buff = src_graph->rgba[0][src_top_pos]; out_graph->rgba[0][des_top_pos] = src_graph->rgba[0][src_bottom_pos]; out_graph->rgba[0][des_bottom_pos] = buff; buff = src_graph->rgba[1][src_top_pos]; out_graph->rgba[1][des_top_pos] = src_graph->rgba[1][src_bottom_pos]; out_graph->rgba[1][des_bottom_pos] = buff; buff = src_graph->rgba[2][src_top_pos]; out_graph->rgba[2][des_top_pos] = src_graph->rgba[2][src_bottom_pos]; out_graph->rgba[2][des_bottom_pos] = buff; if(src_graph->color_type == COLOR_TYPE_RGBA) { buff = src_graph->rgba[3][src_top_pos]; out_graph->rgba[3][des_top_pos] = src_graph->rgba[3][src_bottom_pos]; out_graph->rgba[3][des_bottom_pos] = buff; } src_top_pos += src_graph->w; des_top_pos += rect.width; src_bottom_pos -= src_graph->w; des_bottom_pos -= rect.width; } } return 0; }
LCUI_API LCUI_BOOL Graph_HaveAlpha( LCUI_Graph *graph ) { graph = Graph_GetQuote(graph); if( graph && graph->color_type == COLOR_TYPE_RGBA ) { return TRUE; } return FALSE; }
static void Graph_DrawLeftShadow( LCUI_PaintContext paint, LCUI_Rect *box, LCUI_BoxShadow *shadow ) { float v, a; LCUI_Color color; LCUI_Graph *graph; int s, t, x, y, bound_x, bound_y; LCUI_Rect shadow_area, box_area, paint_area, area; s = 255; t = BLUR_WIDTH(shadow); v = 512.0/t; a = 2*(v*t-s)/(t*t); color = shadow->color; box_area.x = BoxShadow_GetBoxX( shadow ); box_area.y = BoxShadow_GetBoxY( shadow ); box_area.w = BoxShadow_GetBoxWidth( shadow, box->w ); box_area.h = BoxShadow_GetBoxHeight( shadow, box->h ); shadow_area.x = BoxShadow_GetX( shadow ); shadow_area.y = BoxShadow_GetY( shadow ) + BLUR_WIDTH(shadow); shadow_area.w = BLUR_WIDTH(shadow); shadow_area.h = box_area.h + INNER_SHADOW_WIDTH(shadow)*2; box_area.x += box->x; box_area.y += box->y; shadow_area.x += box->x; shadow_area.y += box->y; if( !LCUIRect_GetOverlayRect( &shadow_area, &paint->rect, &area ) ) { return; } Graph_GetValidRect( &paint->canvas, &paint_area ); graph = Graph_GetQuote( &paint->canvas ); shadow_area.x -= paint->rect.x; shadow_area.y -= paint->rect.y; box_area.x -= paint->rect.x; box_area.y -= paint->rect.y; area.x -= paint->rect.x; area.y -= paint->rect.y; bound_x = area.x + area.width; bound_y = area.y + area.height; if( bound_x > paint_area.x + paint_area.width ) { bound_x = paint_area.x + paint_area.width; } if( bound_y > paint_area.y + paint_area.height ) { bound_y = paint_area.y + paint_area.height; } t -= area.x - shadow_area.x; for( x = area.x; x < bound_x; ++x, --t ) { color.alpha = (uchar_t)(s - (v*t - (a*t*t) / 2)); color.alpha *= shadow->color.a / 255.0; for( y = area.y; y < bound_y; ++y ) { if( y >= box_area.y && y < box_area.y + box_area.h && x >= box_area.x && x < box_area.x + box_area.w ) { continue; } Graph_SetPixel( graph, x, y, color ); } } }
/* * 功能:获取指向被引用的图形的指针 * 说明:如果当前图形引用了另一个图形,并且,该图形处于一条引用链中,那么,本函数会返 * 回指向被引用的最终图形的指针。 * */ LCUI_API LCUI_Graph* Graph_GetQuote( LCUI_Graph *graph ) { if( !graph ) { return NULL; } if( !graph->quote ) { return graph; } return Graph_GetQuote(graph->src); }
LCUI_API LCUI_BOOL Graph_IsValid( LCUI_Graph *graph ) { LCUI_Graph *p; p = Graph_GetQuote(graph); if(p != NULL && p->rgba != NULL && p->h > 0 && p->w > 0 ) { return TRUE; } return FALSE; }
static void Graph_DrawTopShadow( LCUI_PaintContext paint, LCUI_Rect *box, LCUI_BoxShadow *shadow ) { float v, a; int s, t, x, y, bound_x, bound_y; LCUI_Color color; LCUI_Graph *graph; LCUI_Rect shadow_area, box_area, area; box_area.x = BoxShadow_GetBoxX( shadow ); box_area.y = BoxShadow_GetBoxY( shadow ); box_area.w = BoxShadow_GetBoxWidth( shadow, box->w ); box_area.h = BoxShadow_GetBoxHeight( shadow, box->h ); /* 计算需要绘制上边阴影的区域 */ shadow_area.x = BoxShadow_GetX( shadow ) + BLUR_WIDTH(shadow); shadow_area.y = BoxShadow_GetY( shadow ); shadow_area.w = box_area.w + INNER_SHADOW_WIDTH(shadow)*2; shadow_area.h = BLUR_WIDTH(shadow); color = shadow->color; bound_x = shadow_area.x + shadow_area.w; bound_y = shadow_area.y + shadow_area.h; graph = Graph_GetQuote( &paint->canvas ); Graph_GetValidRect( &paint->canvas, &area ); if( !LCUIRect_GetOverlayRect( &area, &paint->rect, &area ) ) { return; } /** * 这里采用匀减速直线运动的公式: s = vt - at²/2 * 加速度 a 的求值公式为:a = 2x(vt - s)/t² */ s = 255; t = BLUR_WIDTH(shadow); v = 512.0/t; a = 2*(v*t-s)/(t*t); for( y=shadow_area.y; y<bound_y; ++y,--t ) { /* 忽略不在有效区域内的像素 */ if( y < area.y || y >= area.y + area.h ) { continue; } /* 计算当前行阴影的透明度 */ color.alpha = (uchar_t)(s-(v*t-(a*t*t)/2)); color.alpha *= shadow->color.a/255.0; for( x=shadow_area.x; x<bound_x; ++x ) { if( x < area.x || x >= area.x + area.w ) { continue; } if( y >= box_area.y && y < box_area.y + box_area.h && x >= box_area.x && x < box_area.x + box_area.w ) { continue; } Graph_SetPixel( graph, x, y, color ); } } }
LCUI_API int Graph_Zoom( LCUI_Graph *in_graph, LCUI_Graph *out_graph, LCUI_BOOL keep_scale, LCUI_Size size ) { LCUI_Graph *src; LCUI_Rect rect; LCUI_Pos pos; int des_n, src_n, x, y, k, m; double scale_x,scale_y; if(!Graph_IsValid(in_graph)) { return -1; } if(size.w <=0 || size.h <= 0) { Graph_Free(out_graph); return -1; } /* 获取引用的有效区域,以及指向引用的对象的指针 */ rect = Graph_GetValidRect(in_graph); src = Graph_GetQuote(in_graph); scale_x = (double)rect.width / size.w; scale_y = (double)rect.height / size.h; /* 如果缩放方式为缺省,图像的宽和高的缩放比例将会一样 */ if( keep_scale ) { if (scale_x<scale_y) { scale_y = scale_x; } else { scale_x = scale_y; } } out_graph->color_type = in_graph->color_type; if( Graph_Create(out_graph, size.w, size.h) < 0) { return -2; } for (y=0; y < size.h; ++y) { pos.y = y*scale_y; k = y*size.w; m = (pos.y+rect.y)*src->w + rect.x; for (x = 0; x < size.w; ++x) { pos.x = x*scale_x; src_n = k + x; des_n = m + pos.x; out_graph->rgba[0][src_n] = src->rgba[0][des_n]; out_graph->rgba[1][src_n] = src->rgba[1][des_n]; out_graph->rgba[2][src_n] = src->rgba[2][des_n]; if( in_graph->color_type == COLOR_TYPE_RGBA) { out_graph->rgba[3][src_n] = src->rgba[3][des_n]; } } } return 0; }
void Graph_Copy( LCUI_Graph *des, const LCUI_Graph *src ) { const LCUI_Graph *graph; if( !des || !Graph_IsValid(src) ) { return; } graph = Graph_GetQuote( src ); des->color_type = graph->color_type; /* 创建合适尺寸的Graph */ Graph_Create( des, src->w, src->h ); Graph_Replace( des, src, Pos(0,0) ); des->opacity = src->opacity; }
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_HorizFlip( LCUI_Graph *src_graph, LCUI_Graph *out_graph ) { int x, y, center; int src_left_pos, src_right_pos; int des_left_pos, des_right_pos; uchar_t buff; LCUI_Graph *src; LCUI_Rect rect; if(!Graph_IsValid(src_graph)) { return -1; } rect = Graph_GetValidRect( src_graph ); src = Graph_GetQuote( src_graph ); out_graph->color_type = src->color_type; if( 0 != Graph_Create( out_graph, rect.width, rect.height ) ) { return -2; } /* 水平翻转其实也就是交换两边的数据 */ center = (int)(rect.width / 2.0); for (y = 0; y < rect.height; ++y) { des_left_pos = y * rect.width; des_right_pos = des_left_pos + rect.width -1; src_left_pos = (y + rect.y) * src->w + rect.x; src_right_pos = src_left_pos + rect.width -1; for (x = 0; x <= center; ++x) { buff = src->rgba[0][src_left_pos]; out_graph->rgba[0][des_left_pos] = src->rgba[0][src_right_pos]; out_graph->rgba[0][des_right_pos] = buff; buff = src->rgba[1][src_left_pos]; out_graph->rgba[1][des_left_pos] = src->rgba[1][src_right_pos]; out_graph->rgba[1][des_right_pos] = buff; buff = src->rgba[2][src_left_pos]; out_graph->rgba[2][des_left_pos] = src->rgba[2][src_right_pos]; out_graph->rgba[2][des_right_pos] = buff; if(src->color_type == COLOR_TYPE_RGBA) { buff = src->rgba[3][src_left_pos]; out_graph->rgba[3][des_left_pos] = src->rgba[3][src_right_pos]; out_graph->rgba[3][des_right_pos] = buff; } ++src_left_pos; ++des_left_pos; --src_right_pos; --des_right_pos; } } return 0; }
static void Graph_DrawRightShadow( LCUI_PaintContext paint, LCUI_Rect *box, LCUI_BoxShadow *shadow ) { float v, a; int s, t, x, y, bound_x, bound_y; LCUI_Color color; LCUI_Graph *graph; LCUI_Rect shadow_area, box_area, area; box_area.x = BoxShadow_GetBoxX( shadow ); box_area.y = BoxShadow_GetBoxY( shadow ); box_area.w = BoxShadow_GetBoxWidth( shadow, box->w ); box_area.h = BoxShadow_GetBoxHeight( shadow, box->h ); shadow_area.x = BoxShadow_GetX( shadow ) + SHADOW_WIDTH(shadow); shadow_area.x += box_area.w + INNER_SHADOW_WIDTH(shadow); shadow_area.y = BoxShadow_GetY( shadow ) + BLUR_WIDTH(shadow); shadow_area.w = BLUR_WIDTH(shadow); shadow_area.h = box_area.h + INNER_SHADOW_WIDTH(shadow)*2; color = shadow->color; bound_x = shadow_area.x + shadow_area.w; bound_y = shadow_area.y + shadow_area.h; graph = Graph_GetQuote( &paint->canvas ); Graph_GetValidRect( &paint->canvas, &area ); if( !LCUIRect_GetOverlayRect( &area, &paint->rect, &area ) ) { return; } s = 255; t = BLUR_WIDTH(shadow); v = 512.0/t; a = 2*(v*t-s)/(t*t); for( t=0,x=shadow_area.x; x<bound_x; ++x,++t ) { if( x < area.x || x >= area.x + area.w ) { continue; } color.alpha = (uchar_t)(s-(v*t-(a*t*t)/2)); color.alpha *= shadow->color.a/255.0; for( y=shadow_area.y; y<bound_y; ++y ) { if( y < area.y || y >= area.y + area.h ) { continue; } if( y >= box_area.y && y < box_area.y + box_area.h && x >= box_area.x && x < box_area.x + box_area.w ) { continue; } Graph_SetPixel( graph, x, y, color ); } } }
static int Graph_ZoomRGB( const LCUI_Graph *graph, LCUI_Graph *buff, LCUI_BOOL keep_scale, LCUI_Size size ) { LCUI_Rect rect; int x, y, src_x, src_y, tmp; double scale_x, scale_y; uchar_t *byte_src, *byte_des; if( !Graph_IsValid(graph) ) { return -1; } if( size.w <= 0 || size.h <= 0 ) { Graph_Free( buff ); return -1; } /* 获取引用的有效区域,以及指向引用的对象的指针 */ Graph_GetValidRect( graph, &rect ); graph = Graph_GetQuote( graph ); scale_x = (double)rect.width / size.w; scale_y = (double)rect.height / size.h; /* 如果保持宽高比 */ if( keep_scale ) { if (scale_x<scale_y) { scale_y = scale_x; } else { scale_x = scale_y; } } buff->color_type = graph->color_type; if( Graph_Create(buff, size.w, size.h) < 0) { return -2; } for( y=0; y < size.h; ++y ) { src_y = y * scale_y; tmp = ((src_y + rect.y) * graph->w + rect.x) * 3; byte_des = buff->bytes + y * size.w * 3; for( x=0; x < size.w; ++x ) { src_x = x * scale_x * 3; byte_src = graph->bytes + tmp + src_x; *byte_des++ = *byte_src++; *byte_des++ = *byte_src++; *byte_des++ = *byte_src++; } } return 0; }
/** * 将色彩类型为RGBA的前景图像,覆盖至色彩类型为RGB的目标背景图像中 * 当背景图像没有alpha通道时,该函数使用白色背景与前景图像进行混合,并将源图像 * 的全局透明度计算在内 * param back * 背景图像 * param des_rect * 背景图像中的写入区域 * param fore * 前景图像 * param src_pos * 前景图像中的读取区域的坐标 * warning * 此函数不会对传入的参数进行有效性判断,因为此函数主要被Graph_Replace函 * 数调用,Graph_Replace函数会预先进行参数有效性判断 */ static int Graph_RGBAReplaceRGBWithGlobalAlpha( LCUI_Graph *back, LCUI_Rect des_rect, LCUI_Graph *fore, LCUI_Pos src_pos ) { int x, y; double k; uchar_t alpha; int src_n, des_n; int des_row_start, src_row_start; LCUI_Graph *src, *des; src = Graph_GetQuote(fore); des = Graph_GetQuote(back); k = 1.0 / src->alpha; src_row_start = src_pos.y * src->w + src_pos.x; des_row_start = des_rect.y * des->w + des_rect.x; for(y=0; y<des_rect.height; ++y) { des_n = des_row_start; src_n = src_row_start; for(x=0; x<des_rect.width; ++x) { alpha = src->alpha * k; des->rgba[0][des_n] = _ALPHA_BLEND( src->rgba[0][src_n], 255, alpha ); des->rgba[1][des_n] = _ALPHA_BLEND( src->rgba[1][src_n], 255, alpha ); des->rgba[2][des_n] = _ALPHA_BLEND( src->rgba[2][src_n], 255, alpha ); ++src->w; ++des->w; } des_row_start += des->w; src_row_start += src->w; } return 0; }
void Graph_PrintInfo( LCUI_Graph *graph ) { printf("address:%p\n", graph); if( !graph ) { return; } printf("width:%d, ", graph->w); printf("height:%d, ", graph->h); printf("opacity:%.2f, ", graph->opacity); printf("%s\n", graph->color_type == COLOR_TYPE_ARGB ? "RGBA":"RGB"); if( graph->quote.is_valid ) { printf("graph src:"); Graph_PrintInfo(Graph_GetQuote(graph)); } }
LCUI_API void Graph_PrintInfo( LCUI_Graph *graph ) { printf("address:%p\n", graph); if( !graph ) { return; } printf("width:%d, ", graph->w); printf("height:%d, ", graph->h); printf("alpha:%u, ", graph->alpha); printf("%s\n", graph->color_type == COLOR_TYPE_RGBA ? "RGBA":"RGB"); if( graph->quote ) { printf("graph src:"); Graph_PrintInfo(Graph_GetQuote(graph)); } }
LCUI_API int Graph_FillRect( LCUI_Graph *graph, LCUI_RGB color, LCUI_Rect rect ) { size_t size; int pos, y; LCUI_Rect src_rect; uchar_t *r_ptr, *g_ptr, *b_ptr; src_rect = Graph_GetValidRect( graph ); graph = Graph_GetQuote( graph ); if(! Graph_IsValid(graph) ) { return -1; } rect.x = rect.x + src_rect.x; rect.y = rect.y + src_rect.y; /* 计算出该填充区域实际的有效区域范围 */ if( rect.x < src_rect.x ) { rect.width -= (src_rect.x-rect.x); rect.x = src_rect.x; } if( rect.x + rect.width > src_rect.x + src_rect.width ) { rect.width = src_rect.x + src_rect.width - rect.x; } if( rect.y < src_rect.y ) { rect.height -= (src_rect.y-rect.y); rect.y = src_rect.y; } if( rect.y + rect.height > src_rect.x + src_rect.height ) { rect.height = src_rect.y + src_rect.height - rect.y; } size = sizeof(uchar_t) * rect.width; pos = rect.x + rect.y * graph->w; r_ptr = graph->rgba[0] + pos; g_ptr = graph->rgba[1] + pos; b_ptr = graph->rgba[2] + pos; for(y=0; y<rect.height; ++y) { memset( r_ptr, color.red, size ); memset( g_ptr, color.green, size ); memset( b_ptr, color.blue, size ); r_ptr += graph->w; g_ptr += graph->w; b_ptr += graph->w; } return 0; }
static int Graph_FillRectARGB( LCUI_Graph *graph, LCUI_Color color, LCUI_Rect rect ) { int x, y; LCUI_Rect rect_src; LCUI_ARGB *px_p, *px_row_p; if(!Graph_IsValid(graph)) { return -1; } Graph_GetValidRect( graph, &rect_src ); graph = Graph_GetQuote( graph ); px_row_p = graph->argb + (rect_src.y+rect.y)*graph->w; px_row_p += rect.x + rect_src.x; for( y=0; y<rect.h; ++y ) { px_p = px_row_p; for( x=0; x<rect.w; ++x ) { *px_p++ = color; } px_row_p += graph->w; } return 0; }