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; }
int Graph_Create( LCUI_Graph *graph, int w, int h ) { size_t size; if( w > 10000 || h > 10000 ) { _DEBUG_MSG("graph size is too large!"); abort(); } if( h <= 0 || w <= 0 ) { Graph_Free( graph ); return -1; } graph->bytes_per_pixel = get_pixel_size( graph->color_type ); graph->bytes_per_row = graph->bytes_per_pixel * w; size = graph->bytes_per_row * h; if( Graph_IsValid(graph) ) { /* 如果现有图形尺寸大于要创建的图形的尺寸,直接改尺寸即可 */ if( graph->mem_size >= size ) { if( (w != graph->w || h != graph->h) && graph->color_type == COLOR_TYPE_ARGB ) { Graph_FillAlpha( graph, 0 ); Graph_FillColor(graph, RGB(255,255,255)); } graph->w = w; graph->h = h; return 0; } Graph_Free( graph ); } graph->mem_size = size; graph->bytes = (uchar_t*)malloc( size ); if( !graph->bytes ) { graph->w = 0; graph->h = 0; return -2; } /* 默认全透明 */ if( graph->color_type == COLOR_TYPE_ARGB ) { Graph_FillAlpha( graph, 0 ); } graph->w = w; graph->h = h; return 0; }
/** 清除已记录的无效矩形 */ void TextLayer_ClearInvalidRect( LCUI_TextLayer layer ) { LinkedListNode *node; LCUI_Graph invalid_graph; if( !layer->is_using_buffer ) { RectList_Clear( &layer->dirty_rect ); return; } for( LinkedList_Each( node, &layer->dirty_rect ) ) { Graph_Quote( &invalid_graph, &layer->graph, node->data ); Graph_FillAlpha( &invalid_graph, 0 ); } RectList_Clear( &layer->dirty_rect ); }
/* 将动画当前帧的图像写入至槽中 */ static int Frames_UpdateGraphSlot( LCUI_Frames *frames, int num ) { LCUI_Pos pos; LCUI_Frame *frame; frame = Queue_Get( &frames->pic, num ); if( !frame ) { return -1; } if(!Graph_IsValid(&frames->slot)){ return -2; } Graph_FillAlpha(&frames->slot, 0); if(0 < Queue_GetTotal(&frames->pic)) { pos = Frames_GetFrameMixPos(frames, frame); Graph_Replace(&frames->slot, frame->pic, pos); } 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 void DrawCircle( LCUI_Graph *graph, LCUI_Pos center, int r, LCUI_ARGB color ) { int x, y; int t = r; int s = 255; float v = 512.0/t; float a = 2*(v*t-s)/(t*t); LCUI_Rect area, box_rect; LCUI_Graph *src, box_graph; LCUI_ARGB tmp_px, *px; uchar_t *px_row_bytes; LCUI_Rect2 circle; tmp_px = color; Graph_GetValidRect( graph, &area ); src = Graph_GetQuote( graph ); center.x += area.x; center.y += area.y; circle.r = center.x + r; circle.l = center.x - r; circle.b = center.y + r; circle.t = center.y - r; /* 先填充 圆外切矩形 外的矩形区域 */ box_rect.x = area.x; box_rect.y = area.y; box_rect.w = area.w; box_rect.h = circle.t - area.y; Graph_Quote( &box_graph, src, &box_rect ); Graph_FillAlpha( &box_graph, 0 ); box_rect.y = circle.t; box_rect.w = circle.l - area.x; box_rect.h = area.y + area.h - circle.t; Graph_Quote( &box_graph, src, &box_rect ); Graph_FillAlpha( &box_graph, 0 ); /* 调整圆的区域 */ if( circle.l < area.x ) { circle.l = area.x; } if( circle.t < area.y ) { circle.t = area.y; } if( circle.r > area.x + area.w ) { circle.r = area.x + area.w; } if( circle.b > area.y + area.h ) { circle.b = area.y + area.h; } if( src->color_type != COLOR_TYPE_ARGB ) { return; } px_row_bytes = src->bytes + circle.top*src->bytes_per_row; px_row_bytes += circle.left * src->bytes_per_pixel; /* 遍历区域内每个像素点,根据点到圆心的距离,计算其alpha透明度 */ for( y=circle.top; y<circle.bottom; ++y ) { px = (LCUI_ARGB*)px_row_bytes; for( x=circle.left; x<circle.right; ++x ) { t = (y-center.y)*(y-center.y); t += (x-center.x)*(x-center.x); t = (int)((double)sqrt(1.0*t)+0.5); if( t <= r ) { tmp_px.a = (uchar_t)(s-(v*t-(a*t*t)/2)); tmp_px.a *= color.a/255.0; } else { tmp_px.alpha = 0; } *px++ = tmp_px; } px_row_bytes += src->bytes_per_row; } }
LCUI_EXPORT(int) Draw_Empty_Slot(LCUI_Graph *graph, int width, int height) /* 功能:绘制进度条的空槽 */ { int i, n; unsigned char c; if(width < 4 || height < 4) { return -1; } graph->have_alpha = TRUE; Graph_Create(graph, width, height); /* 申请内存 */ Graph_FillColor(graph, RGB(250,250,250));/* 填充白色 */ Graph_FillAlpha(graph, 255); /* 四个角上的一个像素点完全透明 */ graph->rgba[3][0] = 0; graph->rgba[3][width-1] = 0; graph->rgba[3][width*(height-1)] = 0; graph->rgba[3][width*height-1] = 0; /* 绘制左边和右边的竖线条 */ for(i=0; i<height; ++i) { n = i*width; c = 160 +(30-(30.0/height)*i); graph->rgba[0][n] = c; graph->rgba[1][n] = c; graph->rgba[2][n] = c; graph->rgba[0][n+1] = 230; graph->rgba[1][n+1] = 230; graph->rgba[2][n+1] = 230; n = n+width-1; graph->rgba[0][n] = c; graph->rgba[1][n] = c; graph->rgba[2][n] = c; graph->rgba[0][n-1] = 230; graph->rgba[1][n-1] = 230; graph->rgba[2][n-1] = 230; } /* 绘制顶端的线条 */ memset(graph->rgba[0], 180, width); memset(graph->rgba[1], 180, width); memset(graph->rgba[2], 180, width); memset(graph->rgba[0]+width+1, 240, width-2); memset(graph->rgba[1]+width+1, 240, width-2); memset(graph->rgba[2]+width+1, 240, width-2); /* 绘制底端的线条 */ n = width*(height-1); memset(graph->rgba[0]+n, 140, width); memset(graph->rgba[1]+n, 140, width); memset(graph->rgba[2]+n, 140, width); n = width*(height-2); memset(graph->rgba[0]+n+1, 225, width-2); memset(graph->rgba[1]+n+1, 225, width-2); memset(graph->rgba[2]+n+1, 225, width-2); return 0; }
TextLayer_Draw( LCUI_Widget *widget, LCUI_TextLayer *layer, int mode ) /* 将文本图层绘制到目标部件的图层上 */ { LCUI_Rect area; LCUI_Pos pos, mix_pos; LCUI_BOOL draw_all = FALSE, redraw_row; int i, j, n, rows, size; LCUI_RGB color; LCUI_Graph slot, *graph; LCUI_CharData *p_data; Text_RowData *p_row; //clock_t start; //start = clock(); //_DEBUG_MSG("enter\n"); graph = Widget_GetSelfGraph( widget ); /* 如果文本缓存区内有数据 */ if( layer->need_proc_buff ) { __TextLayer_Text( layer ); layer->need_proc_buff = FALSE; } /* 如果需要滚动图层 */ if( layer->need_scroll_layer ) { layer->need_scroll_layer = FALSE; //_DEBUG_MSG("layer->need_scroll_layer\n"); /* 根据之前记录的偏移坐标,刷新文本图层 */ __TextLayer_OldArea_Erase( layer, Widget_GetSelfGraph( widget ) ); draw_all = TRUE; } //_DEBUG_MSG("1, use time: %ld\n", clock() - start ); //start = clock(); Graph_Init( &slot ); /* 先处理需要清空的区域 */ n = Queue_GetTotal( &layer->clear_area ); for(i=0; i<n; ++i) { RectQueue_Get( &area, 0 , &layer->clear_area ); area.x += layer->offset_pos.x; area.y += layer->offset_pos.y; Queue_Delete( &layer->clear_area, 0 ); Graph_Quote( &slot, graph, area ); /* 将该区域的alpha通道填充为0 */ Graph_FillAlpha( &slot, 0 ); Widget_InvalidArea( widget, area ); //printf("refresh area: %d,%d,%d,%d\n", //area.x, area.y, area.width, area.height); } //_DEBUG_MSG("2, use time: %ld\n", clock() - start ); //start = clock(); /* 开始绘制文本位图至目标图层上 */ rows = Queue_GetTotal( &layer->rows_data ); for(pos.y=layer->offset_pos.y,i=0; i<rows; ++i) { redraw_row = FALSE; p_row = Queue_Get( &layer->rows_data, i ); if( !p_row ) { continue; } n = Queue_GetTotal( &p_row->string ); /* 如果当前字的位图的Y轴跨距不在有效绘制区域内 */ if( pos.y + p_row->max_size.h <= 0 ) { pos.y += p_row->max_size.h; continue; } for(pos.x=layer->offset_pos.x,j=0; j<n; ++j) { /* 如果设置了屏蔽符 */ p_data = Queue_Get( &p_row->string, j ); if( !p_data ) { continue; } if( layer->password_char.char_code > 0 ) { layer->password_char.need_update = p_data->need_update; p_data = &layer->password_char; } /* 如果当前字的位图的X轴跨距不在有效绘制区域内 */ if( pos.x + p_data->bitmap->advance.x <= 0) { pos.x += p_data->bitmap->advance.x; continue; } /* 获取该字体位图的大致尺寸 */ if( p_data->data ) { size = p_data->data->pixel_size; size += 2; color = p_data->data->fore_color; } else { size = layer->default_data.pixel_size + 2; color = layer->default_data.fore_color; } /* 如果字体位图已标记更新,则绘制它 */ if( p_data->need_update || draw_all ) { p_data->need_update = FALSE; if( !redraw_row ) { area.x = pos.x; area.height = p_row->max_size.h; redraw_row = TRUE; } mix_pos.x = pos.x + p_data->bitmap->left; mix_pos.y = pos.y + p_row->max_size.h-1; mix_pos.y -= p_data->bitmap->top; /* 贴上字体位图 */ FontBMP_Mix( graph, mix_pos, p_data->bitmap, color, mode ); } pos.x += p_data->bitmap->advance.x; if( pos.x > widget->size.w ) { break; } } if(redraw_row) { area.y = pos.y; area.width = pos.x - area.x; //_DEBUG_MSG("area:%d,%d,%d,%d\n", //area.x, area.y, area.width, area.height); Widget_InvalidArea( widget, area ); } pos.y += p_row->max_size.h; if( pos.y > widget->size.h ) { break; } } //_DEBUG_MSG("3, use time: %ld\n", clock() - start ); //_DEBUG_MSG("quit\n"); }