and add in the 8bpp gray stuff
[framework/uifw/evas.git] / src / lib / engines / common_8 / evas_soft8_font.c
1 #include "evas_common_soft8.h"
2 #include "evas_soft8_scanline_blend.c"
3
4 static always_inline void
5 _glyph_pt_mask_solid_solid(DATA8 * dst, const DATA8 gry8, const DATA8 * mask)
6 {
7    DATA8 alpha = *mask;
8
9    if (alpha == 0xff)
10       *dst = gry8;
11    else if (alpha > 0)
12      {
13         *dst = GRY_8_BLEND_UNMUL(gry8, *dst, alpha);
14      }
15 }
16
17 static void
18 _glyph_scanline_mask_solid_solid(DATA8 * dst,
19                                  int size, const DATA8 gry8, const DATA8 * mask)
20 {
21    DATA8 *start, *end;
22
23    start = dst;
24    pld(start, 0);
25    pld(mask, 0);
26    end = start + (size & ~3);
27
28    while (start < end)
29      {
30         pld(start, 8);
31         pld(mask, 4);
32         UNROLL4(
33                   {
34                   _glyph_pt_mask_solid_solid(start, gry8, mask);
35                   start++; mask++;}
36         );
37      }
38
39    end = start + (size & 3);
40    for (; start < end; start++, mask++)
41       _glyph_pt_mask_solid_solid(start, gry8, mask);
42 }
43
44 static always_inline void
45 _glyph_pt_mask_transp_solid(DATA8 * dst,
46                             DATA8 gry8, DATA8 alpha, const DATA8 * mask)
47 {
48    DATA32 a, b;
49    int rel_alpha;
50
51    rel_alpha = *mask;
52    alpha = (alpha * rel_alpha) >> 8;
53    if (alpha == 0)
54       return;
55
56    alpha++;
57
58    *dst = GRY_8_BLEND((gry8 * rel_alpha) >> 8, *dst, alpha);
59 }
60
61 static void
62 _glyph_scanline_mask_transp_solid(DATA8 * dst,
63                                   int size,
64                                   const DATA8 gry8,
65                                   const DATA8 rel_alpha, const DATA8 * mask)
66 {
67    DATA8 *start, *end;
68
69    start = dst;
70    pld(start, 0);
71    pld(mask, 0);
72    end = start + (size & ~3);
73
74    while (start < end)
75      {
76         pld(start, 8);
77         pld(mask, 4);
78         UNROLL4(
79                   {
80                   _glyph_pt_mask_transp_solid(start, gry8, rel_alpha, mask);
81                   start++; mask++;}
82         );
83      }
84
85    end = start + (size & 3);
86    for (; start < end; start++, mask++)
87       _glyph_pt_mask_transp_solid(start, gry8, rel_alpha, mask);
88 }
89
90 static inline void
91 _calc_ext(const Soft8_Image * dst, const RGBA_Draw_Context * dc,
92           Eina_Rectangle * ext)
93 {
94    EINA_RECTANGLE_SET(ext, 0, 0, dst->cache_entry.w, dst->cache_entry.h);
95
96    if (dc->clip.use)
97      {
98         int v;
99
100         EINA_RECTANGLE_SET(ext, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
101         if (ext->x < 0)
102           {
103              ext->w += ext->x;
104              ext->x = 0;
105           }
106         if (ext->y < 0)
107           {
108              ext->h += ext->y;
109              ext->y = 0;
110           }
111
112         v = dst->cache_entry.w - ext->x;
113         if (ext->w > v)
114            ext->w = v;
115
116         v = dst->cache_entry.h - ext->y;
117         if (ext->h > v)
118            ext->h = v;
119      }
120 }
121
122 static inline void
123 _glyph_scanline(Soft8_Image * dst, const DATA8 * p_mask,
124                 const Eina_Rectangle ext, int dx, int dy, int max_x, int max_y,
125                 int w, DATA8 alpha, const DATA8 gry8)
126 {
127    int size, in_x, in_w;
128    DATA8 *p_pixels;
129
130    if ((dx >= max_x) || (dy < ext.y) || (dy >= max_y))
131       return;
132
133    in_x = 0;
134    in_w = 0;
135
136    if (dx + w > max_x)
137       in_w += (dx + w) - max_x;
138
139    if (dx < ext.x)
140      {
141         in_w += ext.x - dx;
142         in_x = ext.x - dx;
143         dx = ext.x;
144      }
145
146    size = w - in_w;
147    p_pixels = dst->pixels + (dy * dst->stride) + dx;
148    p_mask += in_x;
149
150    if (size > 1)
151      {
152         if (alpha == 0xff)
153            _glyph_scanline_mask_solid_solid(p_pixels, size, gry8, p_mask);
154         else if (alpha != 0)
155            _glyph_scanline_mask_transp_solid
156                (p_pixels, size, gry8, alpha, p_mask);
157      }
158    else if (size == 1)
159      {
160         if (alpha == 0xff)
161            _glyph_pt_mask_solid_solid(p_pixels, gry8, p_mask);
162         else if (alpha != 0)
163            _glyph_pt_mask_transp_solid(p_pixels, gry8, alpha, p_mask);
164      }
165 }
166
167 static void
168 _soft8_font_glyph_draw_grayscale(Soft8_Image * dst,
169                                  RGBA_Draw_Context * dc __UNUSED__,
170                                  RGBA_Font_Glyph * fg __UNUSED__, int x, int y,
171                                  DATA8 alpha, DATA8 gry8,
172                                  const Eina_Rectangle ext, int bw, int bh,
173                                  int bpitch, const DATA8 * bitmap)
174 {
175    int i, max_x, max_y;
176
177    max_x = ext.x + ext.w;
178    max_y = ext.y + ext.h;
179
180    for (i = 0; i < bh; i++, bitmap += bpitch)
181       _glyph_scanline(dst, bitmap, ext, x, y + i, max_x, max_y, bw,
182                       alpha, gry8);
183 }
184
185 static inline void
186 _glyph_create_mask_line(DATA8 * mask, const DATA8 * bitmap, int w)
187 {
188    const DATA8 bitrepl[2] = { 0x0, 0xff };
189    int i;
190
191    for (i = 0; i < w; i += 8, bitmap++)
192      {
193         int j, size;
194         DATA32 bits;
195
196         if (i + 8 < w)
197            size = 8;
198         else
199            size = w - i;
200
201         bits = *bitmap;
202
203         for (j = size - 1; j >= 0; j--, mask++)
204            *mask = bitrepl[(bits >> j) & 0x1];
205      }
206 }
207
208 static void
209 _soft8_font_glyph_draw_mono(Soft8_Image * dst,
210                             RGBA_Draw_Context * dc __UNUSED__,
211                             RGBA_Font_Glyph * fg __UNUSED__, int x, int y,
212                             DATA8 alpha, DATA8 gry8, const Eina_Rectangle ext,
213                             int bw, int bh, int bpitch, const DATA8 * bitmap)
214 {
215    DATA8 *mask;
216    int i, max_x, max_y;
217
218    max_x = ext.x + ext.w;
219    max_y = ext.y + ext.h;
220
221    mask = alloca(bpitch);
222    for (i = 0; i < bh; i++, bitmap += bpitch)
223      {
224         _glyph_create_mask_line(mask, bitmap, bw);
225         _glyph_scanline(dst, mask, ext, x, y + i, max_x, max_y, bw,
226                         alpha, gry8);
227      }
228 }
229
230 void
231 soft8_font_glyph_draw(void *data, void *dest __UNUSED__, void *context,
232                       RGBA_Font_Glyph * fg, int x, int y)
233 {
234    Soft8_Image *dst;
235    RGBA_Draw_Context *dc;
236    const DATA8 *bitmap;
237    DATA8 alpha, r, g, b;
238    DATA8 gry8;
239    Eina_Rectangle ext;
240    int bpitch, bw, bh;
241
242    dst = data;
243    dc = context;
244
245    alpha = A_VAL(&dc->col.col);
246    if (alpha == 0)
247       return;
248
249    gry8 = GRY_8_FROM_RGB(&dc->col.col);
250
251    /*
252     * if (r > alpha) r = alpha;
253     * if (g > alpha) g = alpha;
254     * if (b > alpha) b = alpha;
255     *
256     * gry8 = GRY_8_FROM_COMPONENTS(r, g, b);
257     */
258
259    bitmap = fg->glyph_out->bitmap.buffer;
260    bh = fg->glyph_out->bitmap.rows;
261    bw = fg->glyph_out->bitmap.width;
262    bpitch = fg->glyph_out->bitmap.pitch;
263    if (bpitch < bw)
264       bpitch = bw;
265
266    _calc_ext(dst, dc, &ext);
267
268    if ((fg->glyph_out->bitmap.num_grays == 256) &&
269        (fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
270       _soft8_font_glyph_draw_grayscale(dst, dc, fg, x, y, alpha, gry8,
271                                        ext, bw, bh, bpitch, bitmap);
272    else
273       _soft8_font_glyph_draw_mono(dst, dc, fg, x, y, alpha, gry8,
274                                   ext, bw, bh, bpitch, bitmap);
275 }
276
277 void *
278 soft8_font_glyph_new(void *data __UNUSED__, RGBA_Font_Glyph * fg __UNUSED__)
279 {
280    return (void *)1;            /* core requires != NULL to work */
281 }
282
283 void
284 soft8_font_glyph_free(void *ext_dat __UNUSED__)
285 {
286 }