2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
5 #include "evas_common.h"
6 #include "evas_private.h"
7 #include "evas_blend_private.h"
9 #include "evas_intl_utils.h" /*defines INTERNATIONAL_SUPPORT if possible */
10 #include "evas_font_private.h" /* for Frame-Queuing support */
12 #ifdef EVAS_FRAME_QUEUING
14 evas_common_font_draw_init(void)
21 evas_common_font_draw_finish(void)
29 _fash_int_free(Fash_Int *fash)
33 for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
40 Fash_Int *fash = calloc(1, sizeof(Fash_Int));
41 fash->freeme = _fash_int_free;
45 static Fash_Item_Index_Map *
46 _fash_int_find(Fash_Int *fash, int item)
50 item &= 0xffff; // fixme: to do > 65k
51 maj = (item >> 8) & 0xff;
53 if (!fash->bucket[maj]) return NULL;
54 return &(fash->bucket[maj]->item[min]);
58 _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int index)
62 item &= 0xffff; // fixme: to do > 65k
63 maj = (item >> 8) & 0xff;
65 if (!fash->bucket[maj])
66 fash->bucket[maj] = calloc(1, sizeof(Fash_Int_Map));
67 fash->bucket[maj]->item[min].fint = fint;
68 fash->bucket[maj]->item[min].index = index;
76 _fash_gl_free(Fash_Glyph *fash)
80 for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
87 Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph));
88 fash->freeme = _fash_gl_free;
92 static RGBA_Font_Glyph *
93 _fash_gl_find(Fash_Glyph *fash, int item)
97 item &= 0xffff; // fixme: to do > 65k
98 maj = (item >> 8) & 0xff;
100 if (!fash->bucket[maj]) return NULL;
101 return fash->bucket[maj]->item[min];
105 _fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph)
109 item &= 0xffff; // fixme: to do > 65k
110 maj = (item >> 8) & 0xff;
112 if (!fash->bucket[maj])
113 fash->bucket[maj] = calloc(1, sizeof(Fash_Int_Map));
114 fash->bucket[maj]->item[min] = glyph;
121 EAPI RGBA_Font_Glyph *
122 evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index)
127 const FT_Int32 hintflags[3] =
128 { FT_LOAD_NO_HINTING, FT_LOAD_FORCE_AUTOHINT, FT_LOAD_NO_AUTOHINT };
132 fg = _fash_gl_find(fi->fash, index);
133 if (fg == (void *)(-1)) return NULL;
134 else if (fg) return fg;
137 hindex = index + (fi->hinting * 500000000);
139 // fg = eina_hash_find(fi->glyphs, &hindex);
140 // if (fg) return fg;
143 // error = FT_Load_Glyph(fi->src->ft.face, index, FT_LOAD_NO_BITMAP);
144 error = FT_Load_Glyph(fi->src->ft.face, index,
145 FT_LOAD_RENDER | hintflags[fi->hinting]);
149 if (!fi->fash) fi->fash = _fash_gl_new();
150 if (fi->fash) _fash_gl_add(fi->fash, index, (void *)(-1));
154 fg = malloc(sizeof(struct _RGBA_Font_Glyph));
155 if (!fg) return NULL;
156 memset(fg, 0, (sizeof(struct _RGBA_Font_Glyph)));
159 error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
164 if (!fi->fash) fi->fash = _fash_gl_new();
165 if (fi->fash) _fash_gl_add(fi->fash, index, (void *)(-1));
168 if (fg->glyph->format != FT_GLYPH_FORMAT_BITMAP)
171 error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1);
174 FT_Done_Glyph(fg->glyph);
177 if (!fi->fash) fi->fash = _fash_gl_new();
178 if (fi->fash) _fash_gl_add(fi->fash, index, (void *)(-1));
183 fg->glyph_out = (FT_BitmapGlyph)fg->glyph;
188 if (!fi->fash) fi->fash = _fash_gl_new();
189 if (fi->fash) _fash_gl_add(fi->fash, index, fg);
191 // eina_hash_direct_add(fi->glyphs, &fg->index, fg);
195 typedef struct _Font_Char_Index Font_Char_Index;
196 struct _Font_Char_Index
203 _evas_common_get_char_index(RGBA_Font_Int* fi, int gl)
205 Font_Char_Index result;
209 /// pthread_mutex_lock(&fi->ft_mutex);
212 // result = eina_hash_find(fi->indexes, &gl);
213 // if (result) goto on_correct;
215 // result = malloc(sizeof (Font_Char_Index));
218 //#ifdef HAVE_PTHREAD
219 // pthread_mutex_unlock(&fi->ft_mutex);
221 // return FT_Get_Char_Index(fi->src->ft.face, gl);
225 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
229 // eina_hash_direct_add(fi->indexes, &result->gl, result);
233 // pthread_mutex_unlock(&fi->ft_mutex);
239 evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
245 Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl);
253 else if (fm->index == -1) return 0;
257 for (l = fn->fonts; l; l = l->next)
264 #if 0 /* FIXME: charmap user is disabled and use a deprecated data type. */
266 if (fi->src->charmap) // Charmap loaded, FI/FS blank
268 index = evas_array_hash_search(fi->src->charmap, gl);
271 evas_common_font_source_load_complete(fi->src);
272 evas_common_font_int_load_complete(fi);
274 evas_array_hash_free(fi->src->charmap);
275 fi->src->charmap = NULL;
284 if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */
286 if (evas_common_font_source_load_complete(fi->src))
288 #if 0 /* FIXME: disable this. this can eat a LOT of memory and in my tests with expedite at any rate shows no visible improvements */
290 index = FT_Get_Char_Index(fi->src->ft.face, gl);
297 fi->src->charmap = evas_array_hash_new();
298 charcode = FT_Get_First_Char(fi->src->ft.face, &gindex);
301 evas_array_hash_add(fi->src->charmap, charcode, gindex);
302 charcode = FT_Get_Next_Char(fi->src->ft.face, charcode, &gindex);
306 FT_Done_Face(fi->src->ft.face);
307 fi->src->ft.face = NULL;
311 evas_common_font_int_load_complete(fi);
319 else /* Charmap not loaded, FS loaded */
321 index = _evas_common_get_char_index(fi, gl);
325 evas_common_font_int_load_complete(fi);
326 if (!fn->fash) fn->fash = _fash_int_new();
327 if (fn->fash) _fash_int_add(fn->fash, gl, fi, index);
333 if (!fn->fash) fn->fash = _fash_int_new();
334 if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1);
344 evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *in_text,
345 RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w, int ext_h, RGBA_Font_Int *fi,
346 int im_w, int im_h __UNUSED__, int use_kerning
351 const char *text = in_text;
352 FT_Face pface = NULL;
356 int char_index = 0; /* the index of the current char */
358 #ifdef INTERNATIONAL_SUPPORT
360 /*FIXME: should get the direction by parmater */
361 EvasIntlParType direction = FRIBIDI_TYPE_ON;
362 EvasIntlLevel *level_list;
364 /* change the text to visual ordering and update the level list
365 * for as minimum impact on the code as possible just use text as an
366 * holder, will change in the future.*/
367 char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, NULL, NULL, &level_list);
368 text = (visual_text) ? visual_text : in_text;
375 im = dst->image.data;
376 for (char_index = 0, c = 0, chr = 0; text[chr]; char_index++)
383 gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
386 index = evas_common_font_glyph_search(fn, &fi, gl);
388 if (fi->src->current_size != fi->size)
390 FT_Activate_Size(fi->ft.size);
391 fi->src->current_size = fi->size;
393 /* hmmm kerning means i can't sanely do my own cached metric tables! */
394 /* grrr - this means font face sharing is kinda... not an option if */
395 /* you want performance */
396 if ((use_kerning) && (prev_index) && (index) &&
397 (pface == fi->src->ft.face))
399 #ifdef INTERNATIONAL_SUPPORT
400 /* if it's rtl, the kerning matching should be reversed, i.e prev
401 * index is now the index and the other way around. */
402 if (evas_intl_is_rtl_char(level_list, char_index))
404 if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
411 if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
416 pface = fi->src->ft.face;
417 fg = evas_common_font_int_cache_glyph_get(fi, index);
421 if (dc->font_ext.func.gl_new)
423 /* extension calls */
424 fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg);
425 fg->ext_dat_free = dc->font_ext.func.gl_free;
428 chr_x = (pen_x + (fg->glyph_out->left));
429 chr_y = (pen_y + (fg->glyph_out->top));
431 if (chr_x < (ext_x + ext_w))
436 data = fg->glyph_out->bitmap.buffer;
437 j = fg->glyph_out->bitmap.pitch;
438 w = fg->glyph_out->bitmap.width;
440 h = fg->glyph_out->bitmap.rows;
442 if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)
443 && (fg->glyph_out->bitmap.num_grays == 256)
447 if ((j > 0) && (chr_x + w > ext_x))
449 if ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
452 dc->font_ext.func.gl_draw(dc->font_ext.data,
461 if ((fg->glyph_out->bitmap.num_grays == 256) &&
462 (fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
464 for (i = 0; i < h; i++)
472 dy = y - (chr_y - i - y);
474 if (((dy) % dc->sli.h) == dc->sli.y)
477 if ((dx < (ext_x + ext_w)) &&
479 (dy < (ext_y + ext_h)))
481 if (dx + w > (ext_x + ext_w))
482 in_w += (dx + w) - (ext_x + ext_w);
491 func(NULL, data + (i * j) + in_x, dc->col.col,
492 im + (dy * im_w) + dx, w - in_w);
500 DATA8 *tmpbuf = NULL, *dp, *tp, bits;
502 const DATA8 bitrepl[2] = {0x0, 0xff};
505 for (i = 0; i < h; i++)
513 dy = y - (chr_y - i - y);
515 if (((dy) % dc->sli.h) == dc->sli.y)
519 dp = data + (i * fg->glyph_out->bitmap.pitch);
520 for (bi = 0; bi < w; bi += 8)
523 if ((w - bi) < 8) end = w - bi;
525 for (bj = 0; bj < end; bj++)
527 *tp = bitrepl[(bits >> (7 - bj)) & 0x1];
532 if ((dx < (ext_x + ext_w)) &&
534 (dy < (ext_y + ext_h)))
536 if (dx + w > (ext_x + ext_w))
537 in_w += (dx + w) - (ext_x + ext_w);
546 func(NULL, tmpbuf + in_x, dc->col.col,
547 im + (dy * im_w) + dx, w - in_w);
560 pen_x += fg->glyph->advance.x >> 16;
563 #ifdef INTERNATIONAL_SUPPORT
564 if (level_list) free(level_list);
565 if (visual_text) free(visual_text);
570 evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text)
572 int ext_x, ext_y, ext_w, ext_h;
579 int c, cx, cy, cw, ch;
582 fi = fn->fonts->data;
584 im_w = dst->cache_entry.w;
585 im_h = dst->cache_entry.h;
587 ext_x = 0; ext_y = 0; ext_w = im_w; ext_h = im_h;
604 if ((ext_x + ext_w) > im_w)
605 ext_w = im_w - ext_x;
606 if ((ext_y + ext_h) > im_h)
607 ext_h = im_h - ext_y;
609 if (ext_w <= 0) return;
610 if (ext_h <= 0) return;
612 #ifndef EVAS_FRAME_QUEUING
615 // evas_common_font_size_use(fn);
616 use_kerning = FT_HAS_KERNING(fi->src->ft.face);
617 func = evas_common_gfx_func_composite_mask_color_span_get(dc->col.col, dst, 1, dc->render_op);
619 if (!dc->cutout.rects)
621 evas_common_font_draw_internal(dst, dc, fn, x, y, text,
622 func, ext_x, ext_y, ext_w, ext_h, fi,
623 im_w, im_h, use_kerning
628 c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h;
629 evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w, dst->cache_entry.h);
630 /* our clip is 0 size.. abort */
631 if ((dc->clip.w > 0) && (dc->clip.h > 0))
633 rects = evas_common_draw_context_apply_cutouts(dc);
634 for (i = 0; i < rects->active; ++i)
636 r = rects->rects + i;
637 evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
638 evas_common_font_draw_internal(dst, dc, fn, x, y, text,
639 func, r->x, r->y, r->w, r->h, fi,
640 im_w, im_h, use_kerning
643 evas_common_draw_context_apply_clear_cutouts(rects);
645 dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
647 #ifndef EVAS_FRAME_QUEUING