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 ); } } }
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 ); } } }
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 ); } } }
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 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 ); } }
/** * 绘制上边阴影 * @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 ); } } }