static void rtgui_dc_client_blit_line (struct rtgui_dc* self, int x1, int x2, int y, rt_uint8_t* line_data) { register rt_base_t index; rtgui_widget_t *owner; if (self == RT_NULL) return; /* get owner */ owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type); if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return; /* convert logic to device */ x1 = x1 + owner->extent.x1; x2 = x2 + owner->extent.x1; if (x1 > x2) _int_swap(x1, x2); y = y + owner->extent.y1; if (rtgui_region_is_flat(&(owner->clip)) == RT_EOK) { rtgui_rect_t* prect; int offset = 0; prect = &(owner->clip.extents); /* calculate vline intersect */ if (prect->y1 > y || prect->y2 <= y ) return; if (prect->x2 <= x1 || prect->x1 > x2) return; if (prect->x1 > x1) x1 = prect->x1; if (prect->x2 < x2) x2 = prect->x2; /* patch note: * We need to adjust the offset when update widget clip! * Of course at ordinary times for 0. General */ offset = owner->clip.extents.x1 - owner->extent.x1; offset = offset * hw_driver->bits_per_pixel/8; /* draw hline */ hw_driver->ops->draw_raw_hline(line_data+offset, x1, x2, y); } else for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++) { rtgui_rect_t* prect; register rt_base_t draw_x1, draw_x2; prect = ((rtgui_rect_t *)(owner->clip.data + index + 1)); draw_x1 = x1; draw_x2 = x2; /* calculate hline clip */ if (prect->y1 > y || prect->y2 <= y ) continue; if (prect->x2 <= x1 || prect->x1 > x2) continue; if (prect->x1 > x1) draw_x1 = prect->x1; if (prect->x2 < x2) draw_x2 = prect->x2; /* draw hline */ hw_driver->ops->draw_raw_hline(line_data + (draw_x1 - x1) * hw_driver->bits_per_pixel/8, draw_x1, draw_x2, y); } }
/* * draw a logic horizontal line on device */ static void rtgui_dc_client_draw_hline(struct rtgui_dc* self, int x1, int x2, int y) { register rt_base_t index; rtgui_widget_t *owner; if (self == RT_NULL) return; /* get owner */ owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type); if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return; /* convert logic to device */ x1 = x1 + owner->extent.x1; x2 = x2 + owner->extent.x1; if (x1 > x2) _int_swap(x1, x2); y = y + owner->extent.y1; if (owner->clip.data == RT_NULL) { rtgui_rect_t* prect; prect = &(owner->clip.extents); /* calculate vline intersect */ if (prect->y1 > y || prect->y2 <= y ) return; if (prect->x2 <= x1 || prect->x1 > x2) return; if (prect->x1 > x1) x1 = prect->x1; if (prect->x2 < x2) x2 = prect->x2; /* draw hline */ hw_driver->ops->draw_hline(&(owner->gc.foreground), x1, x2, y); } else for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++) { rtgui_rect_t* prect; register rt_base_t draw_x1, draw_x2; prect = ((rtgui_rect_t *)(owner->clip.data + index + 1)); draw_x1 = x1; draw_x2 = x2; /* calculate hline clip */ if (prect->y1 > y || prect->y2 <= y ) continue; if (prect->x2 <= x1 || prect->x1 > x2) continue; if (prect->x1 > x1) draw_x1 = prect->x1; if (prect->x2 < x2) draw_x2 = prect->x2; /* draw hline */ hw_driver->ops->draw_hline(&(owner->gc.foreground), draw_x1, draw_x2, y); } }
/* * draw a logic vertical line on device */ static void rtgui_dc_client_draw_vline(struct rtgui_dc* self, int x, int y1, int y2) { register rt_base_t index; rtgui_widget_t *owner; if (self == RT_NULL) return; /* get owner */ owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type); if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return; x = x + owner->extent.x1; y1 = y1 + owner->extent.y1; y2 = y2 + owner->extent.y1; if (y1 > y2) _int_swap(y1, y2); if (owner->clip.data == RT_NULL) { rtgui_rect_t* prect; prect = &(owner->clip.extents); /* calculate vline intersect */ if (prect->x1 > x || prect->x2 <= x) return; if (prect->y2 <= y1 || prect->y1 > y2) return; if (prect->y1 > y1) y1 = prect->y1; if (prect->y2 < y2) y2 = prect->y2; /* draw vline */ hw_driver->ops->draw_vline(&(owner->gc.foreground), x, y1, y2); } else for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++) { rtgui_rect_t* prect; register rt_base_t draw_y1, draw_y2; prect = ((rtgui_rect_t *)(owner->clip.data + index + 1)); draw_y1 = y1; draw_y2 = y2; /* calculate vline clip */ if (prect->x1 > x || prect->x2 <= x) continue; if (prect->y2 <= y1 || prect->y1 > y2) continue; if (prect->y1 > y1) draw_y1 = prect->y1; if (prect->y2 < y2) draw_y2 = prect->y2; /* draw vline */ hw_driver->ops->draw_vline(&(owner->gc.foreground), x, draw_y1, draw_y2); } }
/* blit a dc to another dc */ static void rtgui_dc_buffer_blit(struct rtgui_dc *self, struct rtgui_point *dc_pt, struct rtgui_dc *dest, rtgui_rect_t *rect) { int pitch; rt_uint16_t rect_width, rect_height; struct rtgui_rect _rect, *dest_rect; struct rtgui_point dc_point; struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer *)self; if (rtgui_dc_get_visible(dest) == RT_FALSE) return; /* use the (0,0) origin point */ if (dc_pt == RT_NULL) dc_point = rtgui_empty_point; else { dc_point = *dc_pt; } rtgui_dc_get_rect(dest, &_rect); /* use the rect of dest dc */ if (rect == RT_NULL) { dest_rect = &_rect; } else { dest_rect = rect; if (dest_rect->x1 >= _rect.x2 || dest_rect->y1 >= _rect.y2) return; if (dest_rect->x1 < 0) { if (-dest_rect->x1 >= dc->width) return; dc_point.x += -dest_rect->x1; dest_rect->x1 = 0; } if (dest_rect->y1 < 0) { if (-dest_rect->y1 >= dc->height) return; dc_point.y += -dest_rect->y1; dest_rect->y1 = 0; } if (dest_rect->x2 > _rect.x2) dest_rect->x2 = _rect.x2; if (dest_rect->y2 > _rect.y2) dest_rect->y2 = _rect.y2; } if (dest_rect->x2 < dest_rect->x1 || dest_rect->y2 < dest_rect->y1) return; if (dc_point.x >= dc->width || dc_point.y >= dc->height) return; /* get the minimal width and height */ rect_width = _UI_MIN(rtgui_rect_width(*dest_rect), dc->width - dc_point.x); rect_height = _UI_MIN(rtgui_rect_height(*dest_rect), dc->height - dc_point.y); if ((dest->type == RTGUI_DC_HW) || (dest->type == RTGUI_DC_CLIENT)) { int index; rt_uint8_t *line_ptr, *pixels; rtgui_blit_line_func blit_line; struct rtgui_graphic_driver *hw_driver; hw_driver = rtgui_graphic_driver_get_default(); /* prepare pixel line */ pixels = _dc_get_pixel(dc, dc_point.x, dc_point.y); if (dest->type == RTGUI_DC_HW && hw_driver->framebuffer != RT_NULL) { /* use rtgui_blit */ struct rtgui_blit_info info = { 0 }; struct rtgui_widget *owner; if (self->type == RTGUI_DC_BUFFER) info.a = dc->pixel_alpha; else info.a = 255; /* blit source */ info.src = _dc_get_pixel(dc, dc_point.x, dc_point.y); info.src_fmt = dc->pixel_format; info.src_h = rect_height; info.src_w = rect_width; info.src_pitch = dc->pitch; info.src_skip = info.src_pitch - info.src_w * rtgui_color_get_bpp(dc->pixel_format); owner = ((struct rtgui_dc_hw*)dest)->owner; /* blit destination */ info.dst = (rt_uint8_t*)hw_driver->framebuffer; info.dst = info.dst + (owner->extent.y1 + dest_rect->y1) * hw_driver->pitch + (owner->extent.x1 + dest_rect->x1) * rtgui_color_get_bpp(hw_driver->pixel_format); info.dst_fmt = hw_driver->pixel_format; info.dst_h = rect_height; info.dst_w = rect_width; info.dst_pitch = hw_driver->pitch; info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(hw_driver->pixel_format); rtgui_blit(&info); } else if (dest->type == RTGUI_DC_CLIENT&& hw_driver->framebuffer != RT_NULL) { /* use rtgui_blit */ rt_uint8_t bpp, hw_bpp; struct rtgui_blit_info info = { 0 }; struct rtgui_widget *owner; struct rtgui_region dest_region; struct rtgui_rect dest_extent; int num_rects; struct rtgui_rect *rects; /* get owner */ owner = RTGUI_CONTAINER_OF(dest, struct rtgui_widget, dc_type); dest_extent = *dest_rect; rtgui_widget_rect_to_device(owner, &dest_extent); rtgui_region_init_with_extents(&dest_region, &dest_extent); rtgui_region_intersect_rect(&dest_region, &(owner->clip), &dest_extent); bpp = rtgui_color_get_bpp(dc->pixel_format); hw_bpp = rtgui_color_get_bpp(hw_driver->pixel_format); num_rects = rtgui_region_num_rects(&dest_region); rects = rtgui_region_rects(&dest_region); /* common info */ if (self->type == RTGUI_DC_BUFFER) info.a = dc->pixel_alpha; else info.a = 255; info.src_fmt = dc->pixel_format; info.src_pitch = dc->pitch; info.dst_fmt = hw_driver->pixel_format; info.dst_pitch = hw_driver->pitch; for (index = 0; index < num_rects; index ++) { struct rtgui_rect *r = &rects[index]; /* blit source */ info.src = _dc_get_pixel(dc, dc_point.x + (r->x1 - dest_extent.x1), dc_point.y + (r->y1 - dest_extent.y1)); info.src_h = rtgui_rect_height(*r); info.src_w = rtgui_rect_width(*r); info.src_skip = info.src_pitch - info.src_w * bpp; /* blit destination */ info.dst = (rt_uint8_t*)hw_driver->framebuffer + r->y1 * hw_driver->pitch + r->x1 * hw_bpp; info.dst_h = rtgui_rect_height(*r); info.dst_w = rtgui_rect_width(*r); info.dst_skip = info.dst_pitch - info.dst_w * hw_bpp; rtgui_blit(&info); } rtgui_region_fini(&dest_region); }