/* * File : dc_trans.c * This file is part of RT-Thread GUI * COPYRIGHT (C) 2006 - 2014, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Change Logs: * Date Author Notes * 2014-03-15 Grissom The first version */ #include #include #include #include struct rtgui_dc_trans { struct rtgui_matrix m; struct rtgui_dc *owner; int use_aa; }; struct rtgui_dc_trans* rtgui_dc_trans_create(struct rtgui_dc *owner) { struct rtgui_dc_trans *dct; dct = (struct rtgui_dc_trans*)rtgui_malloc(sizeof(*dct)); if (!dct) return RT_NULL; rtgu_matrix_identity(&dct->m); dct->owner = owner; dct->use_aa = 0; return dct; } RTM_EXPORT(rtgui_dc_trans_create); void rtgui_dc_trans_destroy(struct rtgui_dc_trans *dct) { rtgui_free(dct); } RTM_EXPORT(rtgui_dc_trans_destroy); void rtgui_dc_trans_set_aa(struct rtgui_dc_trans *dct, int use_aa) { RT_ASSERT(dct); dct->use_aa = use_aa; } RTM_EXPORT(rtgui_dc_trans_set_aa); void rtgui_dc_trans_rotate(struct rtgui_dc_trans *dct, double degree) { RT_ASSERT(dct); rtgui_matrix_rotate(&dct->m, degree * RTGUI_MATRIX_FRAC / 360.0); } RTM_EXPORT(rtgui_dc_trans_rotate); void rtgui_dc_trans_scale(struct rtgui_dc_trans *dct, double sx, double sy) { RT_ASSERT(dct); rtgui_matrix_scale(&dct->m, sx * RTGUI_MATRIX_FRAC, sy * RTGUI_MATRIX_FRAC); } RTM_EXPORT(rtgui_dc_trans_scale); void rtgui_dc_trans_move(struct rtgui_dc_trans *dct, int dx, int dy) { RT_ASSERT(dct); rtgui_matrix_move(&dct->m, dx, dy); } RTM_EXPORT(rtgui_dc_trans_move); void rtgui_dc_trans_get_new_wh(struct rtgui_dc_trans *dct, int *new_wp, int *new_hp) { struct rtgui_rect rect; struct rtgui_point topleft, topright, bottomright; RT_ASSERT(dct); if (!new_wp && !new_hp) return; rtgui_dc_get_rect(dct->owner, &rect); /* We ignore the movement components in the matrix. */ /* Transform result of (0, h). */ rtgui_matrix_mul_point_nomove(&topleft, 0, rect.y2, &dct->m); /* Transform result of (w, h). */ rtgui_matrix_mul_point_nomove(&topright, rect.x2, rect.y2, &dct->m); /* Transform result of (w, 0). */ rtgui_matrix_mul_point_nomove(&bottomright, rect.x2, 0, &dct->m); /* Transform result of (0, 0) is always (0, 0). */ #define NORMALIZE(x) do { if (x < 0) x = 0; } while (0) if (new_wp) { int neww; /* Ignore the nagtive parts. */ NORMALIZE(topright.x); NORMALIZE(topleft.x); NORMALIZE(bottomright.x); neww = _UI_MAX(topright.x, _UI_ABS(topleft.x - bottomright.x)) + dct->m.m[4]; NORMALIZE(neww); *new_wp = neww; } if (new_hp) { int newh; NORMALIZE(topright.y); NORMALIZE(topleft.y); NORMALIZE(bottomright.y); newh = _UI_MAX(topright.y, _UI_ABS(topleft.y - bottomright.y)) + dct->m.m[5]; NORMALIZE(newh); *new_hp = newh; } #undef NORMALIZE } RTM_EXPORT(rtgui_dc_trans_get_new_wh); struct _fb_rect { void *fb; /* unit: pixel */ rt_uint16_t width, height; /* unit: pixel */ rt_uint16_t skip; }; /* FrameRect to FrameRect, same format, 2 Bytes/pixel. */ static void _blit_rotate_FR2FR_SF2B(struct _fb_rect* RTGUI_RESTRICT src, const struct rtgui_point *dc_point, struct _fb_rect* RTGUI_RESTRICT dst, const struct rtgui_matrix *invm) { rt_uint16_t* RTGUI_RESTRICT srcp = (rt_uint16_t*)src->fb; rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb; int neww = dst->width; int newh = dst->height; int oriw = src->width; int orih = src->height; int nx, ny; int dx, dy; /* Delta of bx/by when nx++. */ dx = invm->m[0]; dy = invm->m[1]; for (ny = dc_point->y; ny < newh; ny++) { /* Base x, y. */ int bx, by; bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4]; by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5]; for (nx = dc_point->x; nx < neww; nx++, dstp++) { /* The coordinate in the source frame. */ int rx, ry; bx += dx; by += dy; if (bx < 0 || by < 0) continue; rx = bx / RTGUI_MATRIX_FRAC; ry = by / RTGUI_MATRIX_FRAC; if (oriw <= rx || orih <= ry) continue; /* We take the source as a whole and ignore the src->skip. */ *dstp = srcp[ry * oriw + rx]; } dstp += dst->skip - neww; } } /* FrameRect to FrameRect, same format, 2 Bytes/pixel, with AA. */ static void _blit_rotate_FR2FR_SF2B_AA(struct _fb_rect* RTGUI_RESTRICT src, const struct rtgui_point *dc_point, struct _fb_rect* RTGUI_RESTRICT dst, const struct rtgui_matrix *invm) { rt_uint16_t* RTGUI_RESTRICT srcp = (rt_uint16_t*)src->fb; rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb; int neww = dst->width; int newh = dst->height; int oriw = src->width; int orih = src->height; int nx, ny; int dx, dy; dx = invm->m[0]; dy = invm->m[1]; for (ny = dc_point->y; ny < newh; ny++) { /* Base x, y. */ int bx, by; bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4]; by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5]; for (nx = dc_point->x; nx < neww; nx++, dstp++) { /* Color of pixels: * c00 c01 * c10 c11 */ rt_uint32_t c00, c01, c10, c11; int rx, ry, sx, sy; bx += dx; by += dy; if (bx < 0 || by < 0) continue; rx = bx / RTGUI_MATRIX_FRAC; ry = by / RTGUI_MATRIX_FRAC; if (oriw - 1 <= rx || orih - 1 <= ry) continue; c00 = srcp[ry * oriw + rx]; c01 = srcp[ry * oriw + rx + 1]; c10 = srcp[(ry + 1) * oriw + rx]; c11 = srcp[(ry + 1) * oriw + rx + 1]; c00 = (c00 | c00 << 16) & 0x07e0f81f; c01 = (c01 | c01 << 16) & 0x07e0f81f; c10 = (c10 | c10 << 16) & 0x07e0f81f; c11 = (c11 | c11 << 16) & 0x07e0f81f; /* We down scale the interpolate factor to 5 bits to avoid color * corruption. */ sx = ((unsigned int)bx % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5); sy = ((unsigned int)by % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5); if (sx) c00 = ((c01 - c00) * sx / 32 + c00) & 0x07e0f81f; if (sx && sy) c10 = ((c11 - c10) * sx / 32 + c10) & 0x07e0f81f; if (sy) c00 = ((c10 - c00) * sy / 32 + c00) & 0x07e0f81f; /* We take the source as a whole and ignore the src->skip. */ *dstp = c00 | (c00 >> 16); } dstp += dst->skip - neww; } } union _rgba { rt_uint32_t blk; struct { rt_uint8_t r, g, b, a; } d; }; /* FrameRect to FrameRect, same format, 4 Bytes/pixel. */ static void _blit_rotate_FR2FR_SF4B(struct _fb_rect* RTGUI_RESTRICT src, const struct rtgui_point *dc_point, struct _fb_rect* RTGUI_RESTRICT dst, const struct rtgui_matrix *invm) { rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb; rt_uint32_t* RTGUI_RESTRICT dstp = (rt_uint32_t*)dst->fb; int neww = dst->width; int newh = dst->height; int oriw = src->width; int orih = src->height; int nx, ny; int dx, dy; dx = invm->m[0]; dy = invm->m[1]; for (ny = dc_point->y; ny < newh; ny++) { /* Base x, y. */ int bx, by; bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4]; by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5]; for (nx = dc_point->x; nx < neww; nx++, dstp++) { union _rgba spix, dpix; int rx, ry, a; bx += dx; by += dy; if (bx < 0 || by < 0) continue; rx = bx / RTGUI_MATRIX_FRAC; ry = by / RTGUI_MATRIX_FRAC; if (oriw <= rx || orih <= ry) continue; spix.blk = srcp[ry * oriw + rx]; /* Down scale the alpha to 5 bits. */ a = spix.d.a >> 3; if (a == 0) continue; if (a == 31) { *dstp = spix.blk; continue; } dpix.blk = *dstp; dpix.d.r = (spix.d.r - dpix.d.r) * a / 32 + dpix.d.r; dpix.d.g = (spix.d.g - dpix.d.g) * a / 32 + dpix.d.g; dpix.d.b = (spix.d.b - dpix.d.b) * a / 32 + dpix.d.b; *dstp = dpix.blk; } dstp += dst->skip - neww; } } /* FrameRect to FrameRect, same format, 4 Bytes/pixel, with AA. */ static void _blit_rotate_FR2FR_SF4B_AA(struct _fb_rect* RTGUI_RESTRICT src, const struct rtgui_point *dc_point, struct _fb_rect* RTGUI_RESTRICT dst, const struct rtgui_matrix *invm) { rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb; rt_uint32_t* RTGUI_RESTRICT dstp = (rt_uint32_t*)dst->fb; int neww = dst->width; int newh = dst->height; int oriw = src->width; int orih = src->height; int nx, ny; int dx, dy; dx = invm->m[0]; dy = invm->m[1]; for (ny = dc_point->y; ny < newh; ny++) { /* Base x, y. */ int bx, by; bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4]; by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5]; for (nx = dc_point->x; nx < neww; nx++, dstp++) { union _rgba spix00, spix01, spix10, spix11, dpix; int rx, ry, a, sx, sy; bx += dx; by += dy; if (bx < 0 || by < 0) continue; rx = bx / RTGUI_MATRIX_FRAC; ry = by / RTGUI_MATRIX_FRAC; if (oriw - 1 <= rx || orih - 1 <= ry) continue; spix00.blk = srcp[ry * oriw + rx]; /* Down scale the interpolate factor to 5 bits. */ sx = ((unsigned int)bx % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5); sy = ((unsigned int)by % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5); spix01.blk = srcp[ry * oriw + rx + 1]; spix10.blk = srcp[(ry + 1) * oriw + rx]; spix11.blk = srcp[(ry + 1) * oriw + rx + 1]; if (sx) spix00.d.a = (spix01.d.a - spix00.d.a) * sx / 32 + spix00.d.a; if (sx && sy) spix10.d.a = (spix11.d.a - spix10.d.a) * sx / 32 + spix10.d.a; if (sy) spix00.d.a = (spix10.d.a - spix00.d.a) * sy / 32 + spix00.d.a; a = spix00.d.a >> 3; if (a == 0) continue; if (sx) { spix00.d.r = (spix01.d.r - spix00.d.r) * sx / 32 + spix00.d.r; spix00.d.g = (spix01.d.g - spix00.d.g) * sx / 32 + spix00.d.g; spix00.d.b = (spix01.d.b - spix00.d.b) * sx / 32 + spix00.d.b; } if (sx && sy) { spix10.d.r = (spix11.d.r - spix10.d.r) * sx / 32 + spix10.d.r; spix10.d.g = (spix11.d.g - spix10.d.g) * sx / 32 + spix10.d.g; spix10.d.b = (spix11.d.b - spix10.d.b) * sx / 32 + spix10.d.b; } if (sy) { spix00.d.r = (spix10.d.r - spix00.d.r) * sy / 32 + spix00.d.r; spix00.d.g = (spix10.d.g - spix00.d.g) * sy / 32 + spix00.d.g; spix00.d.b = (spix10.d.b - spix00.d.b) * sy / 32 + spix00.d.b; } if (a == (255 >> 3)) { *dstp = spix00.blk; continue; } dpix.blk = *dstp; dpix.d.r = (spix00.d.r - dpix.d.r) * a / 32 + dpix.d.r; dpix.d.g = (spix00.d.g - dpix.d.g) * a / 32 + dpix.d.g; dpix.d.b = (spix00.d.b - dpix.d.b) * a / 32 + dpix.d.b; *dstp = dpix.blk; } dstp += dst->skip - neww; } } /* FrameRect to FrameRect, from ARGB8888 to RGB565. */ static void _blit_rotate_FR2FR_ARGB2RGB565(struct _fb_rect* RTGUI_RESTRICT src, const struct rtgui_point *dc_point, struct _fb_rect* RTGUI_RESTRICT dst, const struct rtgui_matrix *invm) { rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb; rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb; int neww = dst->width; int newh = dst->height; int oriw = src->width; int orih = src->height; int nx, ny; int dx, dy; dx = invm->m[0]; dy = invm->m[1]; for (ny = dc_point->y; ny < newh; ny++) { /* Base x, y. */ int bx, by; bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4]; by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5]; for (nx = dc_point->x; nx < neww; nx++, dstp++) { int rx, ry; int alpha; rt_uint32_t op; bx += dx; by += dy; if (bx < 0 || by < 0) continue; rx = bx / RTGUI_MATRIX_FRAC; ry = by / RTGUI_MATRIX_FRAC; if (oriw <= rx || orih <= ry) continue; /* We take the source as a whole and ignore the src->skip. */ op = srcp[ry * oriw + rx]; /* downscale alpha to 5 bits */ alpha = op >> 27; if (alpha == (255 >> 3)) { *dstp = (rt_uint16_t)((op >> 8 & 0xf800) + (op >> 5 & 0x7e0) + (op >> 3 & 0x1f)); } else if (alpha != 0) { /* We take the source as a whole and ignore the src->skip. */ rt_uint32_t d = *dstp; /* * convert source and destination to G0RAB65565 * and blend all components at the same time */ op = ((op & 0xfc00) << 11) + (op >> 8 & 0xf800) + (op >> 3 & 0x1f); d = (d | d << 16) & 0x07e0f81f; d += (op - d) * alpha >> 5; d &= 0x07e0f81f; *dstp = (rt_uint16_t)(d | d >> 16); } } dstp += dst->skip - neww; } } /* FrameRect to FrameRect, from ARGB8888 to RGB565. */ static void _blit_rotate_FR2FR_ARGB2RGB565_AA(struct _fb_rect* RTGUI_RESTRICT src, const struct rtgui_point *dc_point, struct _fb_rect* RTGUI_RESTRICT dst, const struct rtgui_matrix *invm) { rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb; rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb; int neww = dst->width; int newh = dst->height; int oriw = src->width; int orih = src->height; int nx, ny; int dx, dy; dx = invm->m[0]; dy = invm->m[1]; for (ny = dc_point->y; ny < newh; ny++) { /* Base x, y. */ int bx, by; bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4]; by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5]; for (nx = dc_point->x; nx < neww; nx++, dstp++) { rt_uint32_t op00, op01, op10, op11; rt_uint8_t a00, a01, a10, a11; int rx, ry, sx, sy; bx += dx; by += dy; if (bx < 0 || by < 0) continue; rx = bx / RTGUI_MATRIX_FRAC; ry = by / RTGUI_MATRIX_FRAC; if (oriw - 1 <= rx || orih - 1 <= ry) continue; op00 = srcp[ry * oriw + rx]; op01 = srcp[ry * oriw + rx + 1]; op10 = srcp[(ry + 1) * oriw + rx]; op11 = srcp[(ry + 1) * oriw + rx + 1]; /* Down scale the interpolate factor to 5 bits. */ sx = ((unsigned int)bx % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5); sy = ((unsigned int)by % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5); a00 = op00 >> 27; a01 = op01 >> 27; a11 = op11 >> 27; a10 = op10 >> 27; if (sx) a00 = (a01 - a00) * sx / 32 + a00; if (sx && sy) a10 = (a11 - a10) * sx / 32 + a10; if (sy) a00 = (a10 - a00) * sy / 32 + a00; if (a00 == 0) continue; op00 = (((op00 >> 10) & 0x3f) << 21) | (((op00 >> 19) & 0x1f) << 11) | (op00 >> 3 & 0x1f); op10 = (((op10 >> 10) & 0x3f) << 21) | (((op10 >> 19) & 0x1f) << 11) | (op10 >> 3 & 0x1f); op01 = (((op01 >> 10) & 0x3f) << 21) | (((op01 >> 19) & 0x1f) << 11) | (op01 >> 3 & 0x1f); op11 = (((op11 >> 10) & 0x3f) << 21) | (((op11 >> 19) & 0x1f) << 11) | (op11 >> 3 & 0x1f); if (sx) { op00 = ((op01 - op00) * sx / 32 + op00) & 0x07e0f81f; } if (sx && sy) { op10 = ((op11 - op10) * sx / 32 + op10) & 0x07e0f81f; } if (sy) { op00 = ((op10 - op00) * sy / 32 + op00) & 0x07e0f81f; } if (a00 == (255 >> 3)) { *dstp = op00 | (op00 >> 16); } else if (a00 != 0) { rt_uint32_t d = *dstp; d = (d | d << 16) & 0x07e0f81f; d += (op00 - d) * a00 >> 5; d &= 0x07e0f81f; *dstp = (rt_uint16_t)(d | d >> 16); } } dstp += dst->skip - neww; } } static void _blit_rotate_B2B(struct rtgui_dc_trans *dct, const struct rtgui_point *dc_point, struct rtgui_dc_buffer* RTGUI_RESTRICT dest, struct rtgui_rect *rect, const struct rtgui_matrix *invm, int neww, int newh) { struct rtgui_rect srcrect; struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer*)dct->owner; struct _fb_rect srcfb, dstfb; rtgui_dc_get_rect(dct->owner, &srcrect); srcfb.fb = ((struct rtgui_dc_buffer*)dct->owner)->pixel; srcfb.width = srcrect.x2; srcfb.height = srcrect.y2; srcfb.skip = 0; dstfb.fb = dest->pixel + rtgui_color_get_bpp(dest->pixel_format) * (rect->x1 + rect->y1 * dest->width); dstfb.width = neww; dstfb.height = newh; dstfb.skip = dest->width; if (dc->pixel_format == dest->pixel_format) { switch (rtgui_color_get_bpp(dest->pixel_format)) { case 2: if (dct->use_aa) _blit_rotate_FR2FR_SF2B_AA(&srcfb, dc_point, &dstfb, invm); else _blit_rotate_FR2FR_SF2B(&srcfb, dc_point, &dstfb, invm); break; case 4: if (dct->use_aa) _blit_rotate_FR2FR_SF4B_AA(&srcfb, dc_point, &dstfb, invm); else _blit_rotate_FR2FR_SF4B(&srcfb, dc_point, &dstfb, invm); break; default: rt_kprintf("could not handle bpp: %d\n", rtgui_color_get_bpp(dest->pixel_format)); return; } } else if (dc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888 && dest->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565) { if (dct->use_aa) _blit_rotate_FR2FR_ARGB2RGB565_AA(&srcfb, dc_point, &dstfb, invm); else _blit_rotate_FR2FR_ARGB2RGB565(&srcfb, dc_point, &dstfb, invm); } else { rt_kprintf("not implemented yet\n"); return; } } static void _blit_rotate_B2H(struct rtgui_dc_trans *dct, const struct rtgui_point *dc_point, struct rtgui_dc_hw* dest, struct rtgui_rect *rect, const struct rtgui_matrix *invm, int neww, int newh) { struct rtgui_rect srcrect; int start_pix; struct _fb_rect srcfb, dstfb; struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer*)dct->owner; if (dest->hw_driver->framebuffer == RT_NULL) { rt_kprintf("Only support framebuffer hw dc\n"); return; } rtgui_dc_get_rect(dct->owner, &srcrect); srcfb.fb = ((struct rtgui_dc_buffer*)dct->owner)->pixel; srcfb.width = srcrect.x2; srcfb.height = srcrect.y2; srcfb.skip = 0; /* Start point of the widget. */ start_pix = dest->owner->extent.x1 + dest->owner->extent.y1 * dest->hw_driver->width; /* Start point of the inner rect. */ start_pix += rect->x1 + rect->y1 * dest->hw_driver->width; dstfb.fb = (void*)(dest->hw_driver->framebuffer + rtgui_color_get_bpp(dest->hw_driver->pixel_format) * start_pix); dstfb.width = neww; dstfb.height = newh; dstfb.skip = dest->hw_driver->width; if (dc->pixel_format == dest->hw_driver->pixel_format) { switch (rtgui_color_get_bpp(dest->hw_driver->pixel_format)) { case 2: if (dct->use_aa) _blit_rotate_FR2FR_SF2B_AA(&srcfb, dc_point, &dstfb, invm); else _blit_rotate_FR2FR_SF2B(&srcfb, dc_point, &dstfb, invm); break; case 4: if (dct->use_aa) _blit_rotate_FR2FR_SF4B_AA(&srcfb, dc_point, &dstfb, invm); else _blit_rotate_FR2FR_SF4B(&srcfb, dc_point, &dstfb, invm); break; default: rt_kprintf("could not handle bpp: %d\n", rtgui_color_get_bpp(dest->hw_driver->pixel_format)); return; } } else if (dc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888 && dest->hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565) { if (dct->use_aa) _blit_rotate_FR2FR_ARGB2RGB565_AA(&srcfb, dc_point, &dstfb, invm); else _blit_rotate_FR2FR_ARGB2RGB565(&srcfb, dc_point, &dstfb, invm); } else { rt_kprintf("not implemented yet\n"); return; } } void rtgui_dc_trans_blit(struct rtgui_dc_trans *dct, struct rtgui_point *dc_point, struct rtgui_dc *dest, struct rtgui_rect *rect) { struct rtgui_rect bkrect; struct rtgui_matrix invm; struct rtgui_point dp; int neww, newh; RT_ASSERT(dct); RT_ASSERT(dest); if (dc_point == RT_NULL) { dp.x = dp.y = 0; dc_point = &dp; } if (rect == RT_NULL) { rtgui_dc_get_rect(dest, &bkrect); rect = &bkrect; } rtgui_dc_trans_get_new_wh(dct, &neww, &newh); if (dc_point->x < 0) { neww -= dc_point->x; if (neww < 0) return; dc_point->x = 0; } else if (dc_point->x > neww) return; if (dc_point->y < 0) { newh -= dc_point->y; if (newh < 0) return; dc_point->y = 0; } else if (dc_point->y > newh) return; if (rtgui_matrix_inverse(&dct->m, &invm)) return; if (rtgui_rect_width(*rect) < neww - dc_point->x) neww = dc_point->x + rtgui_rect_width(*rect); if (rtgui_rect_height(*rect) < newh - dc_point->y) newh = dc_point->y + rtgui_rect_height(*rect); /* Route to different optimized routines. */ if (dct->owner->type == RTGUI_DC_BUFFER) { if (dest->type == RTGUI_DC_BUFFER) _blit_rotate_B2B(dct, dc_point, (struct rtgui_dc_buffer*)dest, rect, &invm, neww, newh); else if (dest->type == RTGUI_DC_HW) _blit_rotate_B2H(dct, dc_point, (struct rtgui_dc_hw*)dest, rect, &invm, neww, newh); else if (dest->type == RTGUI_DC_CLIENT) // TODO: ; else rt_kprintf("unknown dc for dc_trans\n"); } else rt_kprintf("not implemented yet\n"); } RTM_EXPORT(rtgui_dc_trans_blit);