Exemplo n.º 1
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;
}
Exemplo n.º 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 );
		}
	}
}
Exemplo n.º 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 );
	}
}
Exemplo n.º 4
0
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 );
		}
	}
}
Exemplo n.º 5
0
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 );
		}
	}
}
Exemplo n.º 6
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 );
	}
}
Exemplo n.º 7
0
static int check_rect_correct( LCUI_Rect *corret, LCUI_Rect *actual )
{
	LCUI_Rect rect;
	if( LCUIRect_GetOverlayRect( corret, actual, &rect ) ) {
		if( rect.x == corret->x &&
		    rect.y == corret->y &&
		    rect.width == corret->width &&
		    rect.height == corret->height ) {
			return 1;
		}
	}
	return 0;
}
Exemplo n.º 8
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 );
		}
	}
}
Exemplo n.º 9
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 );
	}
}
Exemplo n.º 10
0
/**
 * 绘制上边阴影
 * @param[in] paint 绘制上下文
 * @param[in] box 可供绘制阴影的区域范围
 * @param[in] shadow 阴影参数
 */
static void Graph_DrawTopShadow( 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 = 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);
	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 ) + 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);
	/* 调整坐标 */
	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( y = area.y; y < bound_y; ++y, --t ) {
		/* 计算当前行像素点的透明度 */
		color.alpha = (uchar_t)(s - (v*t - (a*t*t) / 2));
		color.alpha *= shadow->color.a / 255.0;
		for( x = area.x; x < bound_x; ++x ) {
			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 );
		}
	}
}
Exemplo n.º 11
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 );
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
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 );
	}
}
Exemplo n.º 14
0
static LCUI_WidgetRenderer WidgetRenderer( LCUI_Widget w,
					   LCUI_PaintContext paint,
					   LCUI_WidgetRenderer parent )
{
	LCUI_RectF rect;
	ASSIGN( that, LCUI_WidgetRenderer );

	that->target = w;
	that->paint = paint;
	that->is_cover_border = FALSE;
	that->has_self_graph = FALSE;
	that->has_layer_graph = FALSE;
	that->has_content_graph = FALSE;
	if( parent ) {
		that->root_paint = parent->root_paint;
		that->x = parent->x + parent->content_left + w->box.graph.x;
		that->y = parent->y + parent->content_top + w->box.graph.y;
	} else {
		that->x = that->y = 0;
		that->root_paint = that->paint;
	}
	/* 若部件本身是透明的 */
	if( w->computed_style.opacity < 1.0 ) {
		that->has_self_graph = TRUE;
		that->has_content_graph = TRUE;
		that->has_layer_graph = TRUE;
	} else {
		/* 若使用了圆角边框,则判断当前脏矩形区域是否在圆角边框内
		...
		if( ... ) {
			that->has_content_graph = TRUE;
			that->is_cover_border = TRUE;
		}
		*/
	}
	Graph_Init( &that->self_graph );
	Graph_Init( &that->layer_graph );
	Graph_Init( &that->content_graph );
	that->layer_graph.color_type = COLOR_TYPE_ARGB;
	that->can_render_self = Widget_IsPaintable( w );
	if( that->can_render_self ) {
		that->self_graph.color_type = COLOR_TYPE_ARGB;
		Graph_Create( &that->self_graph,
			      that->paint->rect.width,
			      that->paint->rect.height );
	}
	/* 获取内容框相对于图层的间距 */
	that->content_left = w->box.padding.x - w->box.graph.x;
	that->content_top = w->box.padding.y - w->box.graph.y;
	/* 获取内容区域,相对于根级部件 */
	rect.x = that->x + that->content_left;
	rect.y = that->y + that->content_top;
	rect.width = w->box.padding.width;
	rect.height = w->box.padding.height;
	/* 栅格化内容区域 */
	LCUIMetrics_ComputeRectActual( &that->content_rect, &rect );
	rect.x -= that->x;
	rect.y -= that->y;
	LCUIMetrics_ComputeRectActual( &that->content_paint_rect, &rect );
	/* 获取内容区域中实际需要绘制的区域 */
	that->can_render_centent = LCUIRect_GetOverlayRect(
		&that->content_paint_rect, &that->paint->rect,
		&that->content_paint_rect
	);
	/* 转换坐标为相对于绘制区域 */
	that->content_paint_rect.x -= that->paint->rect.x;
	that->content_paint_rect.y -= that->paint->rect.y;
	if( !that->can_render_centent ) {
		return that;
	}
	/* 若需要部件内容区的位图缓存 */
	if( that->has_content_graph ) {
		that->content_graph.color_type = COLOR_TYPE_ARGB;
		Graph_Create( &that->content_graph, that->content_paint_rect.width,
			      that->content_paint_rect.height );
	}
	return that;
}
Exemplo n.º 15
0
Arquivo: border.c Projeto: add0/LCUI
/** 绘制边框 */
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;
}