// A port of hb_icu_script_to_script because harfbuzz on CrOS is built // without hb-icu. See http://crbug.com/356929 static inline hb_script_t ICUScriptToHBScript(UScriptCode script) { if (UNLIKELY(script == USCRIPT_INVALID_CODE)) return HB_SCRIPT_INVALID; return hb_script_from_string(uscript_getShortName(script), -1); }
TextLayout::TextLayout (int direction, const char *script, const char *language) { if (strlen (script) != 4) return; mFont = 0; mHBFont = 0; mDirection = (hb_direction_t)direction; mLanguage = (long)hb_language_from_string (language, strlen (language)); mScript = hb_script_from_string (script, -1); mBuffer = hb_buffer_create (); hb_buffer_set_direction ((hb_buffer_t*)mBuffer, (hb_direction_t)mDirection); hb_buffer_set_script ((hb_buffer_t*)mBuffer, (hb_script_t)mScript); hb_buffer_set_language ((hb_buffer_t*)mBuffer, (hb_language_t)mLanguage); }
ilG_gui_textlayout *ilG_gui_textlayout_new(ilG_context *ctx, const char *lang, enum ilG_gui_textdir direction, const char *script, il_base *font, const ilA_file *tc, double pt, il_string *source) { il_return_null_on_fail(ctx && lang && script && font && source); struct text_globalctx *gctx = il_base_get(&ctx->base, "il.graphics.gui.text.ctx", NULL, NULL); if (!gctx) { gctx = calloc(1, sizeof(struct text_globalctx)); il_return_null_on_fail(!FT_Init_FreeType(&gctx->library)); il_base_set(&ctx->base, "il.graphics.gui.text.ctx", gctx, sizeof(struct text_globalctx), IL_VOID); } ilG_gui_textlayout *l = il_new(&ilG_gui_textlayout_type); l->context = ctx; l->lang = strdup(lang); l->script = strdup(script); l->font = il_ref(font); l->direction = direction; l->pt = pt; l->source = il_string_ref(source); size_t size; void *data = ilA_contents(tc, font, &size); if (!data) { il_error("Could not open font"); return NULL; } il_return_null_on_fail(!FT_New_Memory_Face(gctx->library, data, size, 0, &l->ft_face)); il_return_null_on_fail(!FT_Set_Char_Size(l->ft_face, 0, pt * 64, 0, 0)); l->hb_ft_font = hb_ft_font_create(l->ft_face, NULL); l->buf = hb_buffer_create(); hb_buffer_set_unicode_funcs(l->buf, hb_icu_get_unicode_funcs()); if (direction == ILG_GUI_DEFAULTDIR) { // TODO: find out how to determine this based on script direction = ILG_GUI_LTR; } hb_buffer_set_direction(l->buf, direction + 3); // Hacky solution hb_buffer_set_script(l->buf, hb_script_from_string(script, -1)); hb_buffer_set_language(l->buf, hb_language_from_string(lang, -1)); hb_buffer_add_utf8(l->buf, source->data, source->length, 0, source->length); hb_shape(l->hb_ft_font, l->buf, NULL, 0); l->glyph_info = hb_buffer_get_glyph_infos(l->buf, &l->glyph_count); l->glyph_pos = hb_buffer_get_glyph_positions(l->buf, &l->glyph_count); return l; }
void TextLayout::SetScript (const char* script) { mScript = hb_script_from_string (script, -1); }
static inline hb_script_t _icu_script_to_script(UScriptCode script) { if (script == USCRIPT_INVALID_CODE) return HB_SCRIPT_INVALID; return hb_script_from_string(uscript_getShortName(script), -1); }
bool sui_layout_init(sui_layout *layout, sui_font *font, const sui_layout_format *fmt, const char *text, size_t length, char **error) { static const int text_dir_table[] = { HB_DIRECTION_LTR, HB_DIRECTION_RTL, HB_DIRECTION_TTB, HB_DIRECTION_BTT }; memset(layout, 0, sizeof(sui_layout)); layout->fmt = *fmt; layout->font = font; FT_Error fterr; if ((fterr = FT_Set_Pixel_Sizes(font->face, 0, fmt->size))) { *error = sui_aprintf("FT_Set_Char_Size: %i\n", fterr); return false; } layout->buffer = hb_buffer_create(); hb_buffer_set_unicode_funcs(layout->buffer, hb_icu_get_unicode_funcs()); hb_buffer_set_direction(layout->buffer, text_dir_table[fmt->dir]); hb_script_t script = hb_script_from_string(fmt->script, -1); if (script == HB_SCRIPT_INVALID || script == HB_SCRIPT_UNKNOWN) { *error = sui_aprintf("Invalid script: %s\n", fmt->script); return false; } hb_buffer_set_script(layout->buffer, script); hb_language_t lang = hb_language_from_string(fmt->lang, -1); if (lang == HB_LANGUAGE_INVALID) { *error = sui_aprintf("Invalid language: %s\n", fmt->lang); return false; } hb_buffer_set_language(layout->buffer, lang); hb_buffer_add_utf8(layout->buffer, text, length, 0, length); hb_shape(font->hb_font, layout->buffer, NULL, 0); layout->infos = hb_buffer_get_glyph_infos(layout->buffer, &layout->count); layout->positions = hb_buffer_get_glyph_positions(layout->buffer, &layout->count); int pen_x = 0, pen_y = 0; int lx = 0, ly = 0, hx = 0, hy = 0; for (unsigned i = 0; i < layout->count; i++) { uint32_t codepoint = layout->infos[i].codepoint; if ((fterr = FT_Load_Glyph(font->face, codepoint, FT_LOAD_DEFAULT))) { *error = sui_aprintf("FT_Load_Glyph: %i\n", fterr); return false; } if (pen_x < lx) { lx = pen_x; } if (pen_y < ly) { ly = pen_y; } int w = font->face->glyph->metrics.width, h = font->face->glyph->metrics.height; if (pen_x + w > hx) { hx = pen_x + w; } if (pen_y + h > hy) { hy = pen_y + h; } pen_x += layout->positions[i].x_advance; pen_y += layout->positions[i].y_advance; } layout->origin = sui_mkpoint(-lx, -ly); layout->size = sui_mkpoint(hx-lx, hy-ly); return true; }