SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) { fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault(); int index; std::unique_ptr<SkStreamAsset> asset(fImpl->fTypeface->openStream(&index)); size_t size = asset->getLength(); SkAutoMalloc autoMalloc(size); // TODO(halcanary): Avoid this malloc+copy. asset->read(autoMalloc.get(), size); asset = nullptr; void* ptr = autoMalloc.get(); hb_blob_t* blob = hb_blob_create((char*)autoMalloc.release(), size, HB_MEMORY_MODE_READONLY, ptr, sk_free); SkASSERT(blob); hb_blob_make_immutable(blob); struct HBFaceDel { void operator()(hb_face_t* f) { hb_face_destroy(f); } }; std::unique_ptr<hb_face_t, HBFaceDel> face(hb_face_create(blob, (unsigned)index)); hb_blob_destroy(blob); SkASSERT(face); if (!face) { return; } hb_face_set_index(face.get(), (unsigned)index); hb_face_set_upem(face.get(), fImpl->fTypeface->getUnitsPerEm()); fImpl->fHarfBuzzFont.reset(hb_font_create(face.get())); SkASSERT(fImpl->fHarfBuzzFont); hb_font_set_scale(fImpl->fHarfBuzzFont.get(), FONT_SIZE_SCALE, FONT_SIZE_SCALE); hb_ot_font_set_funcs(fImpl->fHarfBuzzFont.get()); fImpl->fBuffer.reset(hb_buffer_create()); }
static hb_blob_t * icu_le_hb_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data) { const LEFontInstance *fontInstance = (const LEFontInstance *) user_data; size_t length = 0; const char *data = (const char *) fontInstance->getFontTable (tag, length); return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY, NULL, NULL); }
static hb_blob_t* harfBuzzCoreTextGetTable(hb_face_t* face, hb_tag_t tag, void* userData) { CGFontRef cgFont = reinterpret_cast<CGFontRef>(userData); CFDataRef cfData = CGFontCopyTableForTag(cgFont, tag); if (!cfData) return 0; const char* data = reinterpret_cast<const char*>(CFDataGetBytePtr(cfData)); const size_t length = CFDataGetLength(cfData); if (!data || !length) return 0; return hb_blob_create(data, length, HB_MEMORY_MODE_READONLY, reinterpret_cast<void*>(const_cast<__CFData*>(cfData)), releaseTableData); }
int glyphwidth (lua_State* L) { size_t font_l; unsigned int gid = luaL_checknumber(L, 1); const char * font_s = luaL_checklstring(L, 2, &font_l); unsigned int font_index = luaL_checknumber(L, 3); hb_blob_t* blob = hb_blob_create (font_s, font_l, HB_MEMORY_MODE_WRITABLE, (void*)font_s, NULL); hb_face_t* hbFace = hb_face_create (blob, font_index); hb_font_t* hbFont = hb_font_create (hbFace); short upem = hb_face_get_upem(hbFace); hb_ft_font_set_funcs(hbFont); hb_position_t width = hb_font_get_glyph_h_advance(hbFont, gid); lua_pushnumber(L, width / (double)upem); return 1; }
int get_typographic_extents (lua_State *L) { size_t font_l; const char * font_s = luaL_checklstring(L, 1, &font_l); unsigned int font_index = luaL_checknumber(L, 2); short upem; double ascender; double descender; double x_height; #ifdef USE_FREETYPE_METRICS if (!library) FT_Init_FreeType (&library); FT_Face ft_face = NULL; FT_Error err = FT_New_Memory_Face (library, (const FT_Byte *) font_s, font_l, font_index, &ft_face); if(err) { luaL_error(L, "FT_New_Memory_Face failed"); } upem = ft_face->units_per_EM; ascender = ft_face->ascender / (double)upem; descender = -ft_face->descender / (double)upem; TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(ft_face, ft_sfnt_os2); if (os2) { x_height = os2->sxHeight / (double)upem; } FT_Done_Face(ft_face); #else hb_blob_t* blob = hb_blob_create (font_s, font_l, HB_MEMORY_MODE_WRITABLE, (void*)font_s, NULL); hb_face_t* hbFace = hb_face_create (blob, font_index); hb_font_t* hbFont = hb_font_create (hbFace); hb_font_extents_t metrics = {0,0,0}; upem = hb_face_get_upem(hbFace); hb_ft_font_set_funcs(hbFont); hb_font_get_h_extents(hbFont, &metrics); ascender = metrics.ascender / (double)upem; descender = metrics.descender / (double)upem; hb_font_destroy(hbFont); #endif lua_newtable(L); lua_pushstring(L, "ascender"); lua_pushnumber(L, ascender); lua_settable(L, -3); lua_pushstring(L, "x_height"); lua_pushnumber(L, x_height); lua_settable(L, -3); lua_pushstring(L, "descender"); lua_pushnumber(L, descender); lua_settable(L, -3); return 1; }
hb_blob_t * gfxDWriteFont::GetFontTable(PRUint32 aTag) { const void *data; UINT32 size; void *context; BOOL exists; HRESULT hr = mFontFace->TryGetFontTable(NS_SWAP32(aTag), &data, &size, &context, &exists); if (SUCCEEDED(hr) && exists) { FontTableRec *ftr = new FontTableRec(mFontFace, context); return hb_blob_create(static_cast<const char*>(data), size, HB_MEMORY_MODE_READONLY, DestroyBlobFunc, ftr); } return hb_blob_create_empty(); }
static hb_blob_t* harfBuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* userData) { SkTypeface* typeface = reinterpret_cast<SkTypeface*>(userData); const size_t tableSize = typeface->getTableSize(tag); if (!tableSize) return 0; char* buffer = reinterpret_cast<char*>(fastMalloc(tableSize)); if (!buffer) return 0; size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer); if (tableSize != actualSize) { fastFree(buffer); return 0; } return hb_blob_create(const_cast<char*>(buffer), tableSize, HB_MEMORY_MODE_WRITABLE, buffer, fastFree); }
static hb_blob_t* harfbuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* userData) { FontPlatformData* font = reinterpret_cast<FontPlatformData*>(userData); const size_t tableSize = SkFontHost::GetTableSize(font->uniqueID(), tag); if (!tableSize) return 0; char* buffer = reinterpret_cast<char*>(fastMalloc(tableSize)); if (!buffer) return 0; size_t actualSize = SkFontHost::GetTableData(font->uniqueID(), tag, 0, tableSize, buffer); if (tableSize != actualSize) { fastFree(buffer); return 0; } return hb_blob_create(const_cast<char*>(buffer), tableSize, HB_MEMORY_MODE_WRITABLE, buffer, fastFree); }
static hb_blob_t* referenceTable(hb_face_t*, hb_tag_t tag, void *userData) { FT_Face ftFace = reinterpret_cast<FT_Face>(userData); FT_Byte *buffer; FT_ULong length = 0; if (FT_Load_Sfnt_Table(ftFace, tag, 0, NULL, &length)) return NULL; buffer = reinterpret_cast<FT_Byte*>(malloc(length)); if (buffer == NULL) return NULL; if (FT_Load_Sfnt_Table(ftFace, tag, 0, buffer, &length)) { free(buffer); return NULL; } return hb_blob_create((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, free); }
/** * pango_ot_info_get: * @face: a <type>FT_Face</type>. * * Returns the #PangoOTInfo structure for the given FreeType font face. * * Return value: the #PangoOTInfo for @face. This object will have * the same lifetime as @face. * * Since: 1.2 **/ PangoOTInfo * pango_ot_info_get (FT_Face face) { PangoOTInfo *info; if (G_LIKELY (face->generic.data && face->generic.finalizer == pango_ot_info_finalizer)) return face->generic.data; else { if (face->generic.finalizer) face->generic.finalizer (face); info = face->generic.data = g_object_new (PANGO_TYPE_OT_INFO, NULL); face->generic.finalizer = pango_ot_info_finalizer; info->face = face; if (face->stream->read == NULL) { hb_blob_t *blob; blob = hb_blob_create ((const char *) face->stream->base, (unsigned int) face->stream->size, HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, NULL, NULL); info->hb_face = hb_face_create_for_data (blob, face->face_index); hb_blob_destroy (blob); } else { info->hb_face = hb_face_create_for_tables (_get_table, NULL, info); } hb_face_set_unicode_funcs (info->hb_face, hb_glib_get_unicode_funcs ()); /* XXX this is such a waste if not SFNT */ if (!hb_ot_layout_has_font_glyph_classes (info->hb_face)) synthesize_class_def (info); } return info; }
static hb_blob_t * _get_table(hb_face_t *, hb_tag_t tag, void *user_data) { FT_Face face = (FT_Face) user_data; FT_ULong length = 0; FT_Byte *table; FT_Error error; hb_blob_t* blob = NULL; error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &length); if (!error) { table = (FT_Byte *) xmalloc(length * sizeof(char)); if (table != NULL) { error = FT_Load_Sfnt_Table(face, tag, 0, (FT_Byte*)table, &length); if (!error) { blob = hb_blob_create((const char*) table, length, HB_MEMORY_MODE_WRITABLE, table, free); } else { free(table); } } } return blob; }
static hb_blob_t * _get_table (hb_tag_t tag, void *user_data) { PangoOTInfo *info = (PangoOTInfo *) user_data; FT_Byte *buffer; FT_ULong length = 0; FT_Error error; error = FT_Load_Sfnt_Table (info->face, tag, 0, NULL, &length); if (error) return hb_blob_create_empty (); buffer = g_malloc (length); if (buffer == NULL) return hb_blob_create_empty (); error = FT_Load_Sfnt_Table (info->face, tag, 0, buffer, &length); if (error) return hb_blob_create_empty (); return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, g_free, buffer); }
int shape (lua_State *L) { size_t font_l; const char * text = luaL_checkstring(L, 1); const char * font_s = luaL_checklstring(L, 2, &font_l); unsigned int font_index = luaL_checknumber(L, 3); const char * script = luaL_checkstring(L, 4); const char * direction_s = luaL_checkstring(L, 5); const char * lang = luaL_checkstring(L, 6); double point_size = luaL_checknumber(L, 7); const char * featurestring = luaL_checkstring(L, 8); hb_segment_properties_t segment_props; hb_shape_plan_t *shape_plan; hb_direction_t direction; hb_feature_t* features; int nFeatures = 0; unsigned int glyph_count = 0; hb_font_t *hbFont; hb_buffer_t *buf; hb_glyph_info_t *glyph_info; hb_glyph_position_t *glyph_pos; unsigned int j; features = scan_feature_string(featurestring, &nFeatures); if (!strcasecmp(direction_s,"RTL")) direction = HB_DIRECTION_RTL; else if (!strcasecmp(direction_s,"TTB")) direction = HB_DIRECTION_TTB; else direction = HB_DIRECTION_LTR; hb_blob_t* blob = hb_blob_create (font_s, font_l, HB_MEMORY_MODE_WRITABLE, (void*)font_s, NULL); hb_face_t* hbFace = hb_face_create (blob, font_index); hbFont = hb_font_create (hbFace); unsigned int upem = hb_face_get_upem(hbFace); hb_font_set_scale(hbFont, upem, upem); /* Harfbuzz's support for OT fonts is great, but there's currently no support for CFF fonts, so downgrade to Freetype for those. */ if (strncmp(font_s, "OTTO", 4) == 0) { hb_ft_font_set_funcs(hbFont); } else { hb_ot_font_set_funcs(hbFont); } buf = hb_buffer_create(); hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text)); hb_buffer_set_script(buf, hb_tag_from_string(script, strlen(script))); hb_buffer_set_direction(buf, direction); hb_buffer_set_language(buf, hb_language_from_string(lang,strlen(lang))); hb_buffer_guess_segment_properties(buf); hb_buffer_get_segment_properties(buf, &segment_props); shape_plan = hb_shape_plan_create_cached(hbFace, &segment_props, features, nFeatures, NULL); int res = hb_shape_plan_execute(shape_plan, hbFont, buf, features, nFeatures); if (direction == HB_DIRECTION_RTL) { hb_buffer_reverse(buf); /* URGH */ } glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count); glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count); lua_checkstack(L, glyph_count); for (j = 0; j < glyph_count; ++j) { char namebuf[255]; hb_glyph_extents_t extents = {0,0,0,0}; hb_font_get_glyph_extents(hbFont, glyph_info[j].codepoint, &extents); lua_newtable(L); lua_pushstring(L, "name"); hb_font_get_glyph_name( hbFont, glyph_info[j].codepoint, namebuf, 255 ); lua_pushstring(L, namebuf); lua_settable(L, -3); /* We don't apply x-offset and y-offsets for TTB, which is arguably a bug. We should. The reason we don't is that Harfbuzz assumes that you want to shift the character from a top-center baseline to a bottom-left baseline, and gives you offsets which do that. We don't want to do that so we ignore the offsets. I'm told there is a way of configuring HB's idea of the baseline, and we should use that and take out this condition. */ if (direction != HB_DIRECTION_TTB) { if (glyph_pos[j].x_offset) { lua_pushstring(L, "x_offset"); lua_pushnumber(L, glyph_pos[j].x_offset * point_size / upem); lua_settable(L, -3); } if (glyph_pos[j].y_offset) { lua_pushstring(L, "y_offset"); lua_pushnumber(L, glyph_pos[j].y_offset * point_size / upem); lua_settable(L, -3); } } lua_pushstring(L, "codepoint"); lua_pushinteger(L, glyph_info[j].codepoint); lua_settable(L, -3); lua_pushstring(L, "index"); lua_pushinteger(L, glyph_info[j].cluster); lua_settable(L, -3); double height = extents.y_bearing * point_size / upem; double tHeight = extents.height * point_size / upem; double width = glyph_pos[j].x_advance * point_size / upem; /* The PDF model expects us to make positioning adjustments after a glyph is painted. For this we need to know the natural glyph advance. libtexpdf will use this to compute the adjustment. */ double glyphAdvance = hb_font_get_glyph_h_advance(hbFont, glyph_info[j].codepoint) * point_size / upem; if (direction == HB_DIRECTION_TTB) { height = -glyph_pos[j].y_advance * point_size / upem; tHeight = -height; /* Set depth to 0 - depth has no meaning for TTB */ width = glyphAdvance; glyphAdvance = height; } lua_pushstring(L, "glyphAdvance"); lua_pushnumber(L, glyphAdvance); lua_settable(L, -3); lua_pushstring(L, "width"); lua_pushnumber(L, width); lua_settable(L, -3); lua_pushstring(L, "height"); lua_pushnumber(L, height); lua_settable(L, -3); lua_pushstring(L, "depth"); lua_pushnumber(L, -tHeight - height); lua_settable(L, -3); } /* Cleanup */ hb_buffer_destroy(buf); hb_font_destroy(hbFont); hb_shape_plan_destroy(shape_plan); free(features); return glyph_count; }
static void * create_blob_inert (void) { return hb_blob_create (NULL, 0, HB_MEMORY_MODE_DUPLICATE, NULL, NULL); }
static void * create_blob (void) { static char data[] = "test data"; return hb_blob_create (data, sizeof (data), HB_MEMORY_MODE_READONLY, NULL, NULL); }