efl/legacy/evas/src/lib/engines/common_8/evas_soft8_font.c

287 lines
6.9 KiB
C

#include "evas_common_soft8.h"
#include "evas_soft8_scanline_blend.c"
static always_inline void
_glyph_pt_mask_solid_solid(DATA8 * dst, const DATA8 gry8, const DATA8 * mask)
{
DATA8 alpha = *mask;
if (alpha == 0xff)
*dst = gry8;
else if (alpha > 0)
{
*dst = GRY_8_BLEND_UNMUL(gry8, *dst, alpha);
}
}
static void
_glyph_scanline_mask_solid_solid(DATA8 * dst,
int size, const DATA8 gry8, const DATA8 * mask)
{
DATA8 *start, *end;
start = dst;
pld(start, 0);
pld(mask, 0);
end = start + (size & ~3);
while (start < end)
{
pld(start, 8);
pld(mask, 4);
UNROLL4(
{
_glyph_pt_mask_solid_solid(start, gry8, mask);
start++; mask++;}
);
}
end = start + (size & 3);
for (; start < end; start++, mask++)
_glyph_pt_mask_solid_solid(start, gry8, mask);
}
static always_inline void
_glyph_pt_mask_transp_solid(DATA8 * dst,
DATA8 gry8, DATA8 alpha, const DATA8 * mask)
{
DATA32 a, b;
int rel_alpha;
rel_alpha = *mask;
alpha = (alpha * rel_alpha) >> 8;
if (alpha == 0)
return;
alpha++;
*dst = GRY_8_BLEND((gry8 * rel_alpha) >> 8, *dst, alpha);
}
static void
_glyph_scanline_mask_transp_solid(DATA8 * dst,
int size,
const DATA8 gry8,
const DATA8 rel_alpha, const DATA8 * mask)
{
DATA8 *start, *end;
start = dst;
pld(start, 0);
pld(mask, 0);
end = start + (size & ~3);
while (start < end)
{
pld(start, 8);
pld(mask, 4);
UNROLL4(
{
_glyph_pt_mask_transp_solid(start, gry8, rel_alpha, mask);
start++; mask++;}
);
}
end = start + (size & 3);
for (; start < end; start++, mask++)
_glyph_pt_mask_transp_solid(start, gry8, rel_alpha, mask);
}
static inline void
_calc_ext(const Soft8_Image * dst, const RGBA_Draw_Context * dc,
Eina_Rectangle * ext)
{
EINA_RECTANGLE_SET(ext, 0, 0, dst->cache_entry.w, dst->cache_entry.h);
if (dc->clip.use)
{
int v;
EINA_RECTANGLE_SET(ext, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
if (ext->x < 0)
{
ext->w += ext->x;
ext->x = 0;
}
if (ext->y < 0)
{
ext->h += ext->y;
ext->y = 0;
}
v = dst->cache_entry.w - ext->x;
if (ext->w > v)
ext->w = v;
v = dst->cache_entry.h - ext->y;
if (ext->h > v)
ext->h = v;
}
}
static inline void
_glyph_scanline(Soft8_Image * dst, const DATA8 * p_mask,
const Eina_Rectangle ext, int dx, int dy, int max_x, int max_y,
int w, DATA8 alpha, const DATA8 gry8)
{
int size, in_x, in_w;
DATA8 *p_pixels;
if ((dx >= max_x) || (dy < ext.y) || (dy >= max_y))
return;
in_x = 0;
in_w = 0;
if (dx + w > max_x)
in_w += (dx + w) - max_x;
if (dx < ext.x)
{
in_w += ext.x - dx;
in_x = ext.x - dx;
dx = ext.x;
}
size = w - in_w;
p_pixels = dst->pixels + (dy * dst->stride) + dx;
p_mask += in_x;
if (size > 1)
{
if (alpha == 0xff)
_glyph_scanline_mask_solid_solid(p_pixels, size, gry8, p_mask);
else if (alpha != 0)
_glyph_scanline_mask_transp_solid
(p_pixels, size, gry8, alpha, p_mask);
}
else if (size == 1)
{
if (alpha == 0xff)
_glyph_pt_mask_solid_solid(p_pixels, gry8, p_mask);
else if (alpha != 0)
_glyph_pt_mask_transp_solid(p_pixels, gry8, alpha, p_mask);
}
}
static void
_soft8_font_glyph_draw_grayscale(Soft8_Image * dst,
RGBA_Draw_Context * dc __UNUSED__,
RGBA_Font_Glyph * fg __UNUSED__, int x, int y,
DATA8 alpha, DATA8 gry8,
const Eina_Rectangle ext, int bw, int bh,
int bpitch, const DATA8 * bitmap)
{
int i, max_x, max_y;
max_x = ext.x + ext.w;
max_y = ext.y + ext.h;
for (i = 0; i < bh; i++, bitmap += bpitch)
_glyph_scanline(dst, bitmap, ext, x, y + i, max_x, max_y, bw,
alpha, gry8);
}
static inline void
_glyph_create_mask_line(DATA8 * mask, const DATA8 * bitmap, int w)
{
const DATA8 bitrepl[2] = { 0x0, 0xff };
int i;
for (i = 0; i < w; i += 8, bitmap++)
{
int j, size;
DATA32 bits;
if (i + 8 < w)
size = 8;
else
size = w - i;
bits = *bitmap;
for (j = size - 1; j >= 0; j--, mask++)
*mask = bitrepl[(bits >> j) & 0x1];
}
}
static void
_soft8_font_glyph_draw_mono(Soft8_Image * dst,
RGBA_Draw_Context * dc __UNUSED__,
RGBA_Font_Glyph * fg __UNUSED__, int x, int y,
DATA8 alpha, DATA8 gry8, const Eina_Rectangle ext,
int bw, int bh, int bpitch, const DATA8 * bitmap)
{
DATA8 *mask;
int i, max_x, max_y;
max_x = ext.x + ext.w;
max_y = ext.y + ext.h;
mask = alloca(bpitch);
for (i = 0; i < bh; i++, bitmap += bpitch)
{
_glyph_create_mask_line(mask, bitmap, bw);
_glyph_scanline(dst, mask, ext, x, y + i, max_x, max_y, bw,
alpha, gry8);
}
}
void
soft8_font_glyph_draw(void *data, void *dest __UNUSED__, void *context,
RGBA_Font_Glyph * fg, int x, int y)
{
Soft8_Image *dst;
RGBA_Draw_Context *dc;
const DATA8 *bitmap;
DATA8 alpha, r, g, b;
DATA8 gry8;
Eina_Rectangle ext;
int bpitch, bw, bh;
dst = data;
dc = context;
alpha = A_VAL(&dc->col.col);
if (alpha == 0)
return;
gry8 = GRY_8_FROM_RGB(&dc->col.col);
/*
* if (r > alpha) r = alpha;
* if (g > alpha) g = alpha;
* if (b > alpha) b = alpha;
*
* gry8 = GRY_8_FROM_COMPONENTS(r, g, b);
*/
bitmap = fg->glyph_out->bitmap.buffer;
bh = fg->glyph_out->bitmap.rows;
bw = fg->glyph_out->bitmap.width;
bpitch = fg->glyph_out->bitmap.pitch;
if (bpitch < bw)
bpitch = bw;
_calc_ext(dst, dc, &ext);
if ((fg->glyph_out->bitmap.num_grays == 256) &&
(fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
_soft8_font_glyph_draw_grayscale(dst, dc, fg, x, y, alpha, gry8,
ext, bw, bh, bpitch, bitmap);
else
_soft8_font_glyph_draw_mono(dst, dc, fg, x, y, alpha, gry8,
ext, bw, bh, bpitch, bitmap);
}
void *
soft8_font_glyph_new(void *data __UNUSED__, RGBA_Font_Glyph * fg __UNUSED__)
{
return (void *)1; /* core requires != NULL to work */
}
void
soft8_font_glyph_free(void *ext_dat __UNUSED__)
{
}