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