867 lines
26 KiB
C
867 lines
26 KiB
C
/*
|
|
* 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 <rtgui/rtgui.h>
|
|
#include <rtgui/rtgui_system.h>
|
|
#include <rtgui/dc.h>
|
|
#include <rtgui/dc_trans.h>
|
|
|
|
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);
|
|
|