Exemple #1
0
static void AsyncLoadImage( LCUI_Widget widget, const char *path )
{
	ImageCache cache;
	LCUI_Task task = {0};
	LCUI_Style *s = &widget->cached_style->sheet[key_background_image];

	if( !is_inited ) {
		RBTree_Init( &images );
		RBTree_Init( &refs );
		RBTree_OnJudge( &refs, OnCompareWidget );
		RBTree_OnJudge( &images, OnComparePath );
		RBTree_OnDestroy( &refs, free );
		RBTree_OnDestroy( &images, OnDestroyCache );
		is_inited = TRUE;
	}
	if( s->is_valid && s->type == SVT_STRING ) {
		cache = RBTree_CustomGetData( &images, s->string );
		if( cache ) {
			DelRef( widget, cache );
		}
	}
	cache = RBTree_CustomGetData( &images, path );
	if( cache ) {
		AddRef( widget, cache );
		Graph_Quote( &widget->computed_style.background.image,
			     &cache->image, NULL );
		Widget_AddTask( widget, WTT_BODY );
		return;
	}
	task.func = ExecLoadImage;
	task.arg[0] = widget;
	task.arg[1] = strdup( path );
	LCUI_AddTask( &task );
}
Exemple #2
0
void Graph_ClearShadowArea( LCUI_PaintContext paint, LCUI_Rect *box,
			    LCUI_BoxShadow *shadow )
{
	int i;
	LCUI_Graph canvas;
	LCUI_Rect rect, box_area, rects[4];

	rect.w = box->w;
	rect.h = box->h;
	rect.x = rect.y = 0;
	/* 获取内容框区域 */
	box_area.x = box->x + BoxShadow_GetBoxX( shadow );
	box_area.y = box->y + BoxShadow_GetBoxY( shadow );
	box_area.w = BoxShadow_GetBoxWidth( shadow, box->w );
	box_area.h = BoxShadow_GetBoxHeight( shadow, box->h );
	/* 获取内容框外的阴影区域 */
	LCUIRect_CutFourRect( &box_area, &rect, rects );
	for( i=0; i<4; ++i ) {
		if( LCUIRect_GetOverlayRect( &paint->rect, &rects[i], &rects[i] ) ) {
			rects[i].x -= paint->rect.x;
			rects[i].y -= paint->rect.y;
			Graph_Quote( &canvas, &paint->canvas, &rects[i] );
			Graph_FillRect( &canvas, ARGB(0,0,0,0), NULL, TRUE );
		}
	}
}
Exemple #3
0
static void Graph_DrawBottomRightShadow( LCUI_PaintContext paint, LCUI_Rect *box,
					 LCUI_BoxShadow *shadow )
{
	LCUI_Graph canvas;
	LCUI_Rect bound;
	LCUI_Pos pos;
	
	bound.x = BoxShadow_GetX( shadow ) + BLUR_WIDTH(shadow);
	bound.x += BoxShadow_GetBoxWidth( shadow, box->w );
	bound.x += INNER_SHADOW_WIDTH(shadow)*2;
	bound.y = BoxShadow_GetY( shadow ) + BLUR_WIDTH(shadow);
	bound.y += BoxShadow_GetBoxHeight( shadow, box->h );
	bound.y += INNER_SHADOW_WIDTH(shadow)*2;
	bound.w = bound.h = BLUR_WIDTH(shadow);
	pos.x = 0;
	pos.y = 0;
	if( LCUIRect_GetOverlayRect( &bound, &paint->rect, &bound ) ) {
		bound.x -= paint->rect.x;
		bound.y -= paint->rect.y;
		pos.x -= paint->rect.x;
		pos.y -= paint->rect.y;
		Graph_Quote( &canvas, &paint->canvas, &bound );
		draw_circle( &canvas, pos, bound.w, shadow->color );
	}
}
Exemple #4
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;
}
Exemple #5
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;
}
Exemple #6
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;
}
Exemple #7
0
/** 计算背景样式 */
void Widget_ComputeBackgroundStyle( LCUI_Widget widget )
{
	LCUI_Style *s;
	LCUI_StyleSheet ss = widget->style;
	LCUI_Background *bg = &widget->computed_style.background;
	int key = key_background_start + 1;

	for( ; key < key_background_end; ++key ) {
		s = &ss->sheet[key];
		if( !s->is_valid ) {
			continue;
		}
		switch( key ) {
		case key_background_color:
			bg->color = s->color;
			break;
		case key_background_image:
			switch( s->type ) {
			case SVT_IMAGE:
				if( !s->image ) {
					Graph_Init( &bg->image );
					break;
				}
				Graph_Quote( &bg->image, s->image, NULL );
				break;
			case SVT_STRING:
				AsyncLoadImage( widget, s->string );
			default: break;
			}
			break;
		case key_background_position:
			bg->position.using_value = TRUE;
			bg->position.value = s->value;
			break;
		case key_background_position_x:
			bg->position.using_value = FALSE;
			bg->position.x = *s;
			break;
		case key_background_position_y:
			bg->position.using_value = FALSE;
			bg->position.y = *s;
			break;
		case key_background_size:
			bg->size.using_value = TRUE;
			bg->position.value = s->value;
			break;
		case key_background_size_width:
			bg->size.using_value = FALSE;
			bg->size.w = *s;
			break;
		case key_background_size_height:
			bg->size.using_value = FALSE;
			bg->size.h = *s;
			break;
		default: break;
		}
	}
	Widget_AddTask( widget, WTT_BODY );
}
Exemple #8
0
LCUI_PaintContext LCUIPainter_Begin( LCUI_Graph *canvas, LCUI_Rect *rect )
{
	ASSIGN( paint, LCUI_PaintContext );
	paint->rect = *rect;
	paint->with_alpha = FALSE;
	Graph_Init( &paint->canvas );
	Graph_Quote( &paint->canvas, canvas, &paint->rect );
	return paint;
}
Exemple #9
0
static size_t WidgetRenderer_RenderChildren( LCUI_WidgetRenderer that )
{
	size_t count = 0;
	LCUI_Widget child;
	LinkedListNode *node;
	LCUI_RectF rect;
	LCUI_PaintContextRec paint;
	LCUI_WidgetRenderer renderer;
	LCUI_Rect actual_rect, paint_rect;

	/* 按照显示顺序,从底到顶,递归遍历子级部件 */
	for( LinkedList_EachReverse( node, &that->target->children_show ) ) {
		child = node->data;
		if( !child->computed_style.visible ||
		    child->state != WSTATE_NORMAL ) {
			continue;
		}
		rect.width = child->box.graph.width;
		rect.height = child->box.graph.height;
		rect.x = that->x + child->box.graph.x + that->content_left;
		rect.y = that->y + child->box.graph.y + that->content_top;
		/* 栅格化部件区域,即:转换为相对于根级部件的实际区域 */
		LCUIMetrics_ComputeRectActual( &actual_rect, &rect );
		if( !LCUIRect_GetOverlayRect( &that->content_rect,
					      &actual_rect,
					      &paint_rect ) ) {
			continue;
		}
		if( !LCUIRect_GetOverlayRect( &that->root_paint->rect,
					      &paint_rect,
					      &paint_rect ) ) {
			continue;
		}
		if( that->has_content_graph ) {
			paint.with_alpha = TRUE;
		} else {
			paint.with_alpha = that->paint->with_alpha;
		}
		paint.rect = paint_rect;
		/* 转换绘制区域坐标为相对于自身图层区域 */
		paint.rect.x -= actual_rect.x;
		paint.rect.y -= actual_rect.y;
		/* 转换绘制区域坐标为相对于部件内容区域,作为子部件的绘制区域 */
		paint_rect.x -= that->root_paint->rect.x;
		paint_rect.y -= that->root_paint->rect.y;
		Graph_Quote( &paint.canvas, &that->root_paint->canvas,
			     &paint_rect );
		renderer = WidgetRenderer( child, &paint, that );
		count += WidgetRenderer_Render( renderer );
		WidgetRenderer_Delete( renderer );
	}
	return count;
}
Exemple #10
0
static void Graph_DrawInnerShadow( LCUI_PaintContext paint, LCUI_Rect *box,
				   LCUI_BoxShadow *shadow )
{
	int i;
	LCUI_Graph canvas;
	LCUI_Rect rsd, rb, rects[4];

	rb.x = BoxShadow_GetBoxX( shadow );
	rb.y = BoxShadow_GetBoxY( shadow );
	rb.w = BoxShadow_GetBoxWidth( shadow, box->w );
	rb.h = BoxShadow_GetBoxHeight( shadow, box->h );
	rsd.x = BoxShadow_GetX( shadow ) + BLUR_WIDTH(shadow);
	rsd.y = BoxShadow_GetY( shadow ) + BLUR_WIDTH(shadow);
	rsd.w = rb.w + INNER_SHADOW_WIDTH(shadow)*2;
	rsd.h = rb.h + INNER_SHADOW_WIDTH(shadow)*2;

	/* 截取出与内容区重叠的区域 */
	if( LCUIRect_GetOverlayRect(&rb, &rsd, &rb) ) {
		LCUIRect_CutFourRect( &rb, &rsd, rects );
		/* 从阴影区域中排除部件占用的区域 */
		for( i=0; i<4; ++i ) {
			if( !LCUIRect_GetOverlayRect(
				&paint->rect, &rects[i],&rects[i]) ) {
				continue;
			}
			rects[i].x -= paint->rect.x;
			rects[i].y -= paint->rect.y;
			Graph_Quote( &canvas, &paint->canvas, &rects[i] );
			Graph_FillColor( &canvas, shadow->color );
		}
		return;
	}
	/* 不重叠则直接填充 */
	if( LCUIRect_GetOverlayRect(&paint->rect, &rsd, &rb) ) {
		rb.x -= paint->rect.x;
		rb.y -= paint->rect.y;
		Graph_Quote( &canvas, &paint->canvas, &rb );
		Graph_FillColor( &canvas, shadow->color );
	}
}
Exemple #11
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 );
}
Exemple #12
0
static void Graph_DrawTopLeftShadow( LCUI_PaintContext paint, LCUI_Rect *box, 
				     LCUI_BoxShadow *shadow)
{
	LCUI_Pos pos;
	LCUI_Rect bound;
	LCUI_Graph canvas;
	bound.w = bound.h = BLUR_WIDTH(shadow);
	bound.x = box->x + BoxShadow_GetX( shadow );
	bound.y = box->y + BoxShadow_GetY( shadow );
	if( LCUIRect_GetOverlayRect( &bound, &paint->rect, &bound ) ) {
		Graph_Init( &canvas );
		bound.x -= paint->rect.x;
		bound.y -= paint->rect.y;
		pos.x = bound.x + BLUR_WIDTH( shadow );
		pos.y = bound.y + BLUR_WIDTH( shadow );
		Graph_Quote( &canvas, &paint->canvas, &bound );
		DrawCircle( &canvas, pos, bound.w, shadow->color );
	}
}
Exemple #13
0
static void ExecLoadImage( void *arg1, void *arg2 )
{
	char *path = arg2;
	LCUI_Graph image;
	LCUI_Widget widget = arg1;
	ImageCache cache;

	Graph_Init( &image );
	if( Graph_LoadImage( path, &image ) != 0 ) {
		return;
	}
	cache = NEW(ImageCacheRec, 1);
	cache->ref_count = 0;
	cache->image = image;
	cache->path = path;
	RBTree_CustomInsert( &images, path, cache );
	AddRef( widget, cache );
	Graph_Quote( &widget->computed_style.background.image,
		     &cache->image, NULL );
	Widget_AddTask( widget, WTT_BODY );
}
Exemple #14
0
Resize_Frames(LCUI_Frames *p, LCUI_Size new_size)
/* 功能:调整动画的容器尺寸 */
{
	int i, total;
	LCUI_Pos pos;
	LCUI_Frame *frame;
	LCUI_Graph *graph;
	LCUI_Size size;
	
	if(new_size.w <= 0 || new_size.h <= 0)	{
		return -1;
	}
	if( !p ) {
		return -2;
	}
	
	p->size = new_size;
	total = Queue_GetTotal(&p->pic);
	for(i=0; i<total; ++i){
		frame = Queue_Get(&p->pic, i);
		graph = frame->pic->src;
		size = Graph_GetSize(graph);
		pos = Frames_GetFrameMixPos(p, frame);
		if(pos.x+size.w > new_size.w){
			size.w = new_size.w - pos.x;
			size.w<0 ? size.w=0 :1;
		}
		if(pos.y+size.h > new_size.h){
			size.h = new_size.h - pos.y;
			size.h<0 ? size.h=0 :1;
		}
		Graph_Quote(frame->pic, graph, Rect(0,0,size.w, size.h));
	}
	Graph_Create(&p->slot, new_size.w, new_size.h);
	Frames_UpdateGraphSlot( p, p->current );
	Frames_CallFunc( p );
	return 0;
}
Exemple #15
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 );
}
Exemple #16
0
/** 绘制边框 */
int Graph_DrawBorder( LCUI_PaintContext paint, LCUI_Rect *box, LCUI_Border *border )
{
	int  radius;
	LCUI_Rect bound;
	LCUI_Pos start, end;
	LCUI_Graph canvas;

	if( !Graph_IsValid(&paint->canvas) ) {
		return -1;
	}

	/* 绘制上边框线 */
	bound.x = box->x + border->top_left_radius;
	bound.y = box->y;
	bound.width = box->width - border->top_right_radius;
	bound.width -= border->top_left_radius;
	bound.height = border->top.width;
	if( LCUIRect_GetOverlayRect( &bound, &paint->rect, &bound ) ) {
		bound.x -= paint->rect.x;
		bound.y -= paint->rect.y;
		Graph_Quote( &canvas, &paint->canvas, &bound );
		Graph_FillColor( &canvas, border->top.color );
	}
	/* 绘制下边框线 */
	bound.x = box->x;
	bound.y = box->y + box->height - border->bottom.width;
	bound.width = box->width - border->bottom_right_radius;
	bound.width -= border->bottom_left_radius;
	bound.height = border->bottom.width;
	if( LCUIRect_GetOverlayRect( &bound, &paint->rect, &bound ) ) {
		bound.x -= paint->rect.x;
		bound.y -= paint->rect.y;
		Graph_Quote( &canvas, &paint->canvas, &bound );
		Graph_FillColor( &canvas, border->bottom.color );
	}
	/* 绘制左边框线 */
	bound.y = box->y + border->top_left_radius;
	bound.x = box->x;
	bound.width = border->left.width;
	bound.height = box->height - border->top_left_radius;
	bound.height -= border->bottom_left_radius;
	if( LCUIRect_GetOverlayRect( &bound, &paint->rect, &bound ) ) {
		bound.x -= paint->rect.x;
		bound.y -= paint->rect.y;
		Graph_Quote( &canvas, &paint->canvas, &bound );
		Graph_FillColor( &canvas, border->left.color );
	}
	/* 绘制右边框线 */
	bound.x = box->x + box->width - border->right.width;
	bound.y = box->y + border->top_right_radius;
	bound.width = border->right.width;
	bound.height = box->height - border->top_right_radius;
	bound.height -= border->bottom_right_radius;
	if( LCUIRect_GetOverlayRect( &bound, &paint->rect, &bound ) ) {
		bound.x -= paint->rect.x;
		bound.y -= paint->rect.y;
		Graph_Quote( &canvas, &paint->canvas, &bound );
		Graph_FillColor( &canvas, border->right.color );
	}
	return 0;
}
Exemple #17
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");
}
Exemple #18
0
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;
	}
}
Exemple #19
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 );
}
Exemple #20
0
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;
}
Exemple #21
0
/* 在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); 
}
Exemple #22
0
LCUI_API int Graph_DrawBorder( LCUI_Graph *des, LCUI_Border border )
/* 简单的为图形边缘绘制边框 */
{
	int  radius;
	LCUI_Rect rect;
	LCUI_Pos start, end;
	LCUI_Graph des_area;
	
	if( !Graph_IsValid(des) ) {
		return -1;
	}
	
	/* 绘制左上角的圆角,先引用左上角区域,再将圆绘制到这个区域里 */
	radius = border.top_left_radius;
	rect = Rect( 0, 0, radius, radius );
	Graph_Quote( &des_area, des, rect );
	Graph_Draw_RoundBorder_LeftTop( 
		&des_area		, Pos( radius, radius ), 
		radius			, border.left_width, 
		border.left_color	, TRUE
	);
	Graph_Draw_RoundBorder_TopLeft( 
		&des_area		, Pos( radius, radius ), 
		radius			, border.top_width, 
		border.top_color	, TRUE 
	);
	
	/* 右上角 */
	radius = border.top_right_radius;
	rect = Rect( des->width-radius-1, 0, radius, radius );
	Graph_Quote( &des_area, des, rect );
	Graph_Draw_RoundBorder_RightTop( 
		&des_area		, Pos( 0, radius ), 
		radius			, border.right_width, 
		border.right_color	, TRUE 
	);
	Graph_Draw_RoundBorder_TopRight( 
		&des_area		, Pos( 0, radius ), 
		radius			, border.top_width, 
		border.top_color	, TRUE 
	);
	
	/* 左下角 */
	radius = border.bottom_left_radius;
	rect = Rect( 0, des->height-radius-1, radius, radius );
	Graph_Quote( &des_area, des, rect );
	Graph_Draw_RoundBorder_LeftBottom( 
		&des_area		, Pos( radius, 0 ), 
		radius			, border.left_width, 
		border.left_color	, TRUE 
	);
	Graph_Draw_RoundBorder_BottomLeft( 
		&des_area		, Pos( radius, 0 ), 
		radius			, border.bottom_width, 
		border.bottom_color	, TRUE 
	);
	
	/* 右下角 */
	radius = border.bottom_left_radius;
	rect = Rect(	des->width-radius-1, 
			des->height-radius-1, radius, radius );
	Graph_Quote( &des_area, des, rect );
	Graph_Draw_RoundBorder_RightBottom( 
		&des_area		, Pos( 0, 0 ), 
		radius			, border.right_width, 
		border.right_color	, TRUE 
	);
	Graph_Draw_RoundBorder_BottomRight( 
		&des_area		, Pos( 0, 0 ), 
		radius			, border.bottom_width, 
		border.bottom_color	, TRUE 
	);
	
	start.x = border.top_left_radius;
	start.y = 0;
	end.x = des->width - border.top_right_radius;
	/* 绘制上边框 */
	Graph_DrawHorizLine( des, border.top_color, border.top_width, start, end.x );
	/* 绘制下边的线 */
	start.y = des->height - border.bottom_width;
	end.x = des->width - border.bottom_right_radius;
	Graph_DrawHorizLine( des, border.top_color, border.bottom_width, start, end.x );
	/* 绘制左边的线 */
	start.x = start.y = 0;
	end.y = des->height - border.bottom_left_radius;
	Graph_DrawVertiLine( des, border.left_color, border.left_width, start, end.y );
	/* 绘制右边的线 */
	start.x = des->width - border.right_width;
	start.y = border.top_right_radius;
	end.y = des->height - border.bottom_right_radius;
	Graph_DrawVertiLine( des, border.right_color, border.right_width, start, end.y );
	/* 边框线绘制完成 */
	return 0;
}
Exemple #23
0
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;
}
Exemple #24
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, &quote_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 );
	}
}