harfbuzz_font_skia.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/gfx/harfbuzz_font_skia.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <limits>
  8. #include <map>
  9. #include "base/check_op.h"
  10. #include "base/containers/lru_cache.h"
  11. #include "base/lazy_instance.h"
  12. #include "base/memory/raw_ptr.h"
  13. #include "base/no_destructor.h"
  14. #include "build/build_config.h"
  15. #include "third_party/skia/include/core/SkFont.h"
  16. #include "third_party/skia/include/core/SkTypeface.h"
  17. #include "ui/gfx/render_text.h"
  18. #include "ui/gfx/skia_util.h"
  19. namespace gfx {
  20. namespace {
  21. class TypefaceData;
  22. // Maps from code points to glyph indices in a font.
  23. using GlyphCache = std::map<uint32_t, uint16_t>;
  24. // Wraps a custom user data attached to a hb_font object. Font data provider for
  25. // HarfBuzz using Skia. Copied from Blink.
  26. // TODO(ckocagil): Eliminate the duplication. http://crbug.com/368375
  27. struct FontData {
  28. explicit FontData(GlyphCache* glyph_cache) : glyph_cache_(glyph_cache) {}
  29. SkFont font_;
  30. raw_ptr<GlyphCache> glyph_cache_;
  31. };
  32. // Deletes the object at the given pointer after casting it to the given type.
  33. template<typename Type>
  34. void DeleteByType(void* data) {
  35. Type* typed_data = reinterpret_cast<Type*>(data);
  36. delete typed_data;
  37. }
  38. template<typename Type>
  39. void DeleteArrayByType(void* data) {
  40. Type* typed_data = reinterpret_cast<Type*>(data);
  41. delete[] typed_data;
  42. }
  43. // Outputs the |width| and |extents| of the glyph with index |codepoint| in
  44. // |paint|'s font.
  45. void GetGlyphWidthAndExtents(const SkFont& font,
  46. hb_codepoint_t codepoint,
  47. hb_position_t* width,
  48. hb_glyph_extents_t* extents) {
  49. DCHECK_LE(codepoint, std::numeric_limits<uint16_t>::max());
  50. SkScalar sk_width;
  51. SkRect sk_bounds;
  52. uint16_t glyph = static_cast<uint16_t>(codepoint);
  53. font.getWidths(&glyph, 1, &sk_width, &sk_bounds);
  54. if (width)
  55. *width = SkiaScalarToHarfBuzzUnits(sk_width);
  56. if (extents) {
  57. // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be
  58. // y-grows-up.
  59. extents->x_bearing = SkiaScalarToHarfBuzzUnits(sk_bounds.fLeft);
  60. extents->y_bearing = SkiaScalarToHarfBuzzUnits(-sk_bounds.fTop);
  61. extents->width = SkiaScalarToHarfBuzzUnits(sk_bounds.width());
  62. extents->height = SkiaScalarToHarfBuzzUnits(-sk_bounds.height());
  63. }
  64. }
  65. // Writes the |glyph| index for the given |unicode| code point. Returns whether
  66. // the glyph exists, i.e. it is not a missing glyph.
  67. hb_bool_t GetGlyph(hb_font_t* font,
  68. void* data,
  69. hb_codepoint_t unicode,
  70. hb_codepoint_t variation_selector,
  71. hb_codepoint_t* glyph,
  72. void* user_data) {
  73. FontData* font_data = reinterpret_cast<FontData*>(data);
  74. GlyphCache* cache = font_data->glyph_cache_;
  75. GlyphCache::iterator iter = cache->find(unicode);
  76. if (iter == cache->end()) {
  77. auto result = cache->insert(
  78. std::make_pair(unicode, font_data->font_.unicharToGlyph(unicode)));
  79. DCHECK(result.second);
  80. iter = result.first;
  81. }
  82. *glyph = iter->second;
  83. return !!*glyph;
  84. }
  85. hb_bool_t GetNominalGlyph(hb_font_t* font,
  86. void* data,
  87. hb_codepoint_t unicode,
  88. hb_codepoint_t* glyph,
  89. void* user_data) {
  90. return GetGlyph(font, data, unicode, 0, glyph, user_data);
  91. }
  92. // Returns the horizontal advance value of the |glyph|.
  93. hb_position_t GetGlyphHorizontalAdvance(hb_font_t* font,
  94. void* data,
  95. hb_codepoint_t glyph,
  96. void* user_data) {
  97. FontData* font_data = reinterpret_cast<FontData*>(data);
  98. hb_position_t advance = 0;
  99. GetGlyphWidthAndExtents(font_data->font_, glyph, &advance, 0);
  100. return advance;
  101. }
  102. hb_bool_t GetGlyphHorizontalOrigin(hb_font_t* font,
  103. void* data,
  104. hb_codepoint_t glyph,
  105. hb_position_t* x,
  106. hb_position_t* y,
  107. void* user_data) {
  108. // Just return true, like the HarfBuzz-FreeType implementation.
  109. return true;
  110. }
  111. hb_position_t GetGlyphKerning(FontData* font_data,
  112. hb_codepoint_t first_glyph,
  113. hb_codepoint_t second_glyph) {
  114. SkTypeface* typeface = font_data->font_.getTypeface();
  115. const uint16_t glyphs[2] = { static_cast<uint16_t>(first_glyph),
  116. static_cast<uint16_t>(second_glyph) };
  117. int32_t kerning_adjustments[1] = { 0 };
  118. if (!typeface->getKerningPairAdjustments(glyphs, 2, kerning_adjustments))
  119. return 0;
  120. SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm());
  121. SkScalar size = font_data->font_.getSize();
  122. return SkiaScalarToHarfBuzzUnits(SkIntToScalar(kerning_adjustments[0]) *
  123. size / upm);
  124. }
  125. hb_position_t GetGlyphHorizontalKerning(hb_font_t* font,
  126. void* data,
  127. hb_codepoint_t left_glyph,
  128. hb_codepoint_t right_glyph,
  129. void* user_data) {
  130. FontData* font_data = reinterpret_cast<FontData*>(data);
  131. return GetGlyphKerning(font_data, left_glyph, right_glyph);
  132. }
  133. hb_position_t GetGlyphVerticalKerning(hb_font_t* font,
  134. void* data,
  135. hb_codepoint_t top_glyph,
  136. hb_codepoint_t bottom_glyph,
  137. void* user_data) {
  138. FontData* font_data = reinterpret_cast<FontData*>(data);
  139. return GetGlyphKerning(font_data, top_glyph, bottom_glyph);
  140. }
  141. // Writes the |extents| of |glyph|.
  142. hb_bool_t GetGlyphExtents(hb_font_t* font,
  143. void* data,
  144. hb_codepoint_t glyph,
  145. hb_glyph_extents_t* extents,
  146. void* user_data) {
  147. FontData* font_data = reinterpret_cast<FontData*>(data);
  148. GetGlyphWidthAndExtents(font_data->font_, glyph, 0, extents);
  149. return true;
  150. }
  151. class FontFuncs {
  152. public:
  153. FontFuncs() : font_funcs_(hb_font_funcs_create()) {
  154. hb_font_funcs_set_variation_glyph_func(font_funcs_, GetGlyph, 0, 0);
  155. hb_font_funcs_set_nominal_glyph_func(font_funcs_, GetNominalGlyph, 0, 0);
  156. hb_font_funcs_set_glyph_h_advance_func(
  157. font_funcs_, GetGlyphHorizontalAdvance, 0, 0);
  158. hb_font_funcs_set_glyph_h_kerning_func(
  159. font_funcs_, GetGlyphHorizontalKerning, 0, 0);
  160. hb_font_funcs_set_glyph_h_origin_func(
  161. font_funcs_, GetGlyphHorizontalOrigin, 0, 0);
  162. hb_font_funcs_set_glyph_v_kerning_func(
  163. font_funcs_, GetGlyphVerticalKerning, 0, 0);
  164. hb_font_funcs_set_glyph_extents_func(
  165. font_funcs_, GetGlyphExtents, 0, 0);
  166. hb_font_funcs_make_immutable(font_funcs_);
  167. }
  168. FontFuncs(const FontFuncs&) = delete;
  169. FontFuncs& operator=(const FontFuncs&) = delete;
  170. ~FontFuncs() {
  171. hb_font_funcs_destroy(font_funcs_);
  172. }
  173. hb_font_funcs_t* get() { return font_funcs_; }
  174. private:
  175. raw_ptr<hb_font_funcs_t> font_funcs_;
  176. };
  177. base::LazyInstance<FontFuncs>::Leaky g_font_funcs = LAZY_INSTANCE_INITIALIZER;
  178. // Returns the raw data of the font table |tag|.
  179. hb_blob_t* GetFontTable(hb_face_t* face, hb_tag_t tag, void* user_data) {
  180. SkTypeface* typeface = reinterpret_cast<SkTypeface*>(user_data);
  181. const size_t table_size = typeface->getTableSize(tag);
  182. if (!table_size)
  183. return 0;
  184. std::unique_ptr<char[]> buffer(new char[table_size]);
  185. if (!buffer)
  186. return 0;
  187. size_t actual_size = typeface->getTableData(tag, 0, table_size, buffer.get());
  188. if (table_size != actual_size)
  189. return 0;
  190. char* buffer_raw = buffer.release();
  191. return hb_blob_create(buffer_raw, static_cast<uint32_t>(table_size),
  192. HB_MEMORY_MODE_WRITABLE, buffer_raw,
  193. DeleteArrayByType<char>);
  194. }
  195. // For a given skia typeface, maps to its harfbuzz face and its glyphs cache.
  196. class TypefaceData {
  197. public:
  198. explicit TypefaceData(sk_sp<SkTypeface> skia_face) : sk_typeface_(skia_face) {
  199. face_ = hb_face_create_for_tables(GetFontTable, skia_face.get(), nullptr);
  200. DCHECK(face_);
  201. }
  202. TypefaceData(TypefaceData&& data) {
  203. face_ = data.face_;
  204. glyphs_ = std::move(data.glyphs_);
  205. data.face_ = nullptr;
  206. }
  207. TypefaceData(const TypefaceData&) = delete;
  208. TypefaceData& operator=(const TypefaceData&) = delete;
  209. ~TypefaceData() { hb_face_destroy(face_); }
  210. hb_face_t* face() { return face_; }
  211. GlyphCache* glyphs() { return &glyphs_; }
  212. private:
  213. TypefaceData() = delete;
  214. GlyphCache glyphs_;
  215. raw_ptr<hb_face_t> face_ = nullptr;
  216. // The skia typeface must outlive |face_| since it's being used by harfbuzz.
  217. sk_sp<SkTypeface> sk_typeface_;
  218. };
  219. } // namespace
  220. // Creates a HarfBuzz font from the given Skia face and text size.
  221. hb_font_t* CreateHarfBuzzFont(sk_sp<SkTypeface> skia_face,
  222. SkScalar text_size,
  223. const FontRenderParams& params,
  224. bool subpixel_rendering_suppressed) {
  225. // A cache from Skia font to harfbuzz typeface information.
  226. using TypefaceCache = base::LRUCache<SkFontID, TypefaceData>;
  227. constexpr int kTypefaceCacheSize = 64;
  228. static base::NoDestructor<TypefaceCache> face_caches(kTypefaceCacheSize);
  229. TypefaceCache* typeface_cache = face_caches.get();
  230. TypefaceCache::iterator typeface_data =
  231. typeface_cache->Get(skia_face->uniqueID());
  232. if (typeface_data == typeface_cache->end()) {
  233. TypefaceData new_typeface_data(skia_face);
  234. typeface_data = typeface_cache->Put(skia_face->uniqueID(),
  235. std::move(new_typeface_data));
  236. }
  237. DCHECK(typeface_data->second.face());
  238. hb_font_t* harfbuzz_font = hb_font_create(typeface_data->second.face());
  239. const int scale = SkiaScalarToHarfBuzzUnits(text_size);
  240. hb_font_set_scale(harfbuzz_font, scale, scale);
  241. FontData* hb_font_data = new FontData(typeface_data->second.glyphs());
  242. hb_font_data->font_.setTypeface(std::move(skia_face));
  243. hb_font_data->font_.setSize(text_size);
  244. // TODO(ckocagil): Do we need to update these params later?
  245. internal::ApplyRenderParams(params, subpixel_rendering_suppressed,
  246. &hb_font_data->font_);
  247. hb_font_set_funcs(harfbuzz_font, g_font_funcs.Get().get(), hb_font_data,
  248. DeleteByType<FontData>);
  249. hb_font_make_immutable(harfbuzz_font);
  250. return harfbuzz_font;
  251. }
  252. } // namespace gfx