static GF_Err ft_get_glyphs(GF_FontReader *dr, const char *utf_string, u32 *glyph_buffer, u32 *io_glyph_buffer_size, const char *xml_lang, Bool *is_rtl) { u32 len; u32 i; u16 *conv; char *utf8 = (char*) utf_string; FTBuilder *ftpriv = (FTBuilder *)dr->udta; if (!ftpriv->active_face) return GF_BAD_PARAM; /*TODO: glyph substitution / ligature */ len = utf_string ? strlen(utf_string) : 0; if (!len) { *io_glyph_buffer_size = 0; return GF_OK; } if (*io_glyph_buffer_size < len+1) { *io_glyph_buffer_size = len+1; return GF_BUFFER_TOO_SMALL; } len = gf_utf8_mbstowcs((u16*) glyph_buffer, *io_glyph_buffer_size, (const char **) &utf8); if ((s32)len<0) return GF_IO_ERR; if (utf8) return GF_IO_ERR; /*perform bidi relayout*/ conv = (u16*) glyph_buffer; *is_rtl = gf_utf8_reorder_bidi(conv, len); /*move 16bit buffer to 32bit*/ for (i=len; i>0; i--) { glyph_buffer[i-1] = (u32) conv[i-1]; } *io_glyph_buffer_size = len; return GF_OK; }
/*translate string to glyph sequence*/ static GF_Err svg_font_get_glyphs(void *udta, const char *utf_string, u32 *glyph_buffer, u32 *io_glyph_buffer_size, const char *lang, Bool *is_rtl) { u32 prev_c; u32 len; u32 i, gl_idx; u16 *utf_res; GF_Node *node = (GF_Node *)udta; GF_ChildNodeItem *child; char *utf8 = (char*) utf_string; /*FIXME - use glyphs unicode attributes for glyph substitution*/ len = utf_string ? strlen(utf_string) : 0; if (!len) { *io_glyph_buffer_size = 0; return GF_OK; } if (*io_glyph_buffer_size < len+1) { *io_glyph_buffer_size = len+1; return GF_BUFFER_TOO_SMALL; } len = gf_utf8_mbstowcs((u16*) glyph_buffer, *io_glyph_buffer_size, (const char**)&utf8); if ((s32) len < 0) return GF_IO_ERR; /*should not happen*/ if (utf8) return GF_IO_ERR; /*perform bidi relayout*/ utf_res = (u16 *) glyph_buffer; *is_rtl = gf_utf8_reorder_bidi(utf_res, len); /*move 16bit buffer to 32bit*/ for (i=len; i>0; i--) { glyph_buffer[i-1] = utf_res[i-1]; } gl_idx = 0; prev_c = 0; for (i=0;i<len; i++) { SVG_GlyphStack *missing_glyph = NULL; SVG_GlyphStack *st = NULL; child = ((GF_ParentNode *) node)->children; while (child) { u32 tag = gf_node_get_tag(child->node); if (tag==TAG_SVG_missing_glyph) { missing_glyph = gf_node_get_private(child->node); } else if (tag ==TAG_SVG_glyph) { Bool glyph_ok = 0; SVGAllAttributes atts; st = gf_node_get_private(child->node); if (!st) { child = child->next; continue; } if (st->glyph.utf_name==glyph_buffer[i]) { u32 j, count; gf_svg_flatten_attributes((SVG_Element*)child->node, &atts); if (!lang) { glyph_ok = 1; } else { if (!atts.lang) { glyph_ok = 1; } else { count = gf_list_count(*atts.lang); for (j=0; j<count; j++) { char *name = gf_list_get(*atts.lang, j); if (!stricmp(name, lang) || strstr(lang, name)) { glyph_ok = 1; break; } } } } if (atts.arabic_form) { Bool first = (!prev_c || (prev_c==' ')) ? 1 : 0; Bool last = ((i+1==len) || (glyph_buffer[i+1]==' ') ) ? 1 : 0; if (!strcmp(*atts.arabic_form, "isolated")) { if (!first || !last) glyph_ok = 0; } if (!strcmp(*atts.arabic_form, "initial")) { if (!first) glyph_ok = 0; } if (!strcmp(*atts.arabic_form, "medial")) { if (first || last) glyph_ok = 0; } if (!strcmp(*atts.arabic_form, "terminal")) { if (!last) glyph_ok = 0; } } if (glyph_ok) break; } /*perform glyph substitution*/ else if (st->uni_len>1) { u32 j; for (j=0; j<st->uni_len; j++) { if (i+j>=len) break; if (glyph_buffer[i+j] != st->unicode[j]) break; } if (j==st->uni_len) break; } st = NULL; } child = child->next; } prev_c = glyph_buffer[i]; if (!st) st = missing_glyph; glyph_buffer[gl_idx] = st ? st->glyph.ID : 0; if (st && st->uni_len>1) i++; gl_idx++; } *io_glyph_buffer_size = len = gl_idx; return GF_OK; }