Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.cpp

Issue 1733193002: Move glyph lookup to hb-ot-font and remove glyph cache in HarfBuzzFace (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 Google Inc. All rights reserved. 2 * Copyright (c) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 30 matching lines...) Expand all
41 #include "SkRect.h" 41 #include "SkRect.h"
42 #include "SkTypeface.h" 42 #include "SkTypeface.h"
43 #include "platform/fonts/FontCache.h" 43 #include "platform/fonts/FontCache.h"
44 #include "platform/fonts/FontPlatformData.h" 44 #include "platform/fonts/FontPlatformData.h"
45 #include "platform/fonts/SimpleFontData.h" 45 #include "platform/fonts/SimpleFontData.h"
46 #include "platform/fonts/shaping/HarfBuzzShaper.h" 46 #include "platform/fonts/shaping/HarfBuzzShaper.h"
47 #include "wtf/HashMap.h" 47 #include "wtf/HashMap.h"
48 48
49 namespace blink { 49 namespace blink {
50 50
51 const hb_tag_t HarfBuzzFace::vertTag = HB_TAG('v', 'e', 'r', 't');
52
53 // Though we have FontCache class, which provides the cache mechanism for 51 // Though we have FontCache class, which provides the cache mechanism for
54 // WebKit's font objects, we also need additional caching layer for HarfBuzz 52 // WebKit's font objects, we also need additional caching layer for HarfBuzz
55 // to reduce the memory consumption because hb_face_t should be associated with 53 // to reduce the memory consumption because hb_face_t should be associated with
56 // underling font data (e.g. CTFontRef, FTFace). 54 // underling font data (e.g. CTFontRef, FTFace).
57 55
58 class FaceCacheEntry : public RefCounted<FaceCacheEntry> { 56 class FaceCacheEntry : public RefCounted<FaceCacheEntry> {
59 public: 57 public:
60 static PassRefPtr<FaceCacheEntry> create(hb_face_t* face) 58 static PassRefPtr<FaceCacheEntry> create(hb_face_t* face)
61 { 59 {
62 ASSERT(face); 60 ASSERT(face);
63 return adoptRef(new FaceCacheEntry(face)); 61 return adoptRef(new FaceCacheEntry(face));
64 } 62 }
65 ~FaceCacheEntry() 63 ~FaceCacheEntry()
66 { 64 {
67 hb_face_destroy(m_face); 65 hb_face_destroy(m_face);
68 } 66 }
69 67
70 hb_face_t* face() { return m_face; } 68 hb_face_t* face() { return m_face; }
71 HashMap<uint32_t, uint16_t>* glyphCache() { return &m_glyphCache; }
72 69
73 private: 70 private:
74 explicit FaceCacheEntry(hb_face_t* face) 71 explicit FaceCacheEntry(hb_face_t* face)
75 : m_face(face) 72 : m_face(face)
76 { } 73 { }
77 74
78 hb_face_t* m_face; 75 hb_face_t* m_face;
79 HashMap<uint32_t, uint16_t> m_glyphCache;
80 }; 76 };
81 77
82 typedef HashMap<uint64_t, RefPtr<FaceCacheEntry>, WTF::IntHash<uint64_t>, WTF::U nsignedWithZeroKeyHashTraits<uint64_t>> HarfBuzzFaceCache; 78 typedef HashMap<uint64_t, RefPtr<FaceCacheEntry>, WTF::IntHash<uint64_t>, WTF::U nsignedWithZeroKeyHashTraits<uint64_t>> HarfBuzzFaceCache;
83 79
84 static HarfBuzzFaceCache* harfBuzzFaceCache() 80 static HarfBuzzFaceCache* harfBuzzFaceCache()
85 { 81 {
86 DEFINE_STATIC_LOCAL(HarfBuzzFaceCache, s_harfBuzzFaceCache, ()); 82 DEFINE_STATIC_LOCAL(HarfBuzzFaceCache, s_harfBuzzFaceCache, ());
87 return &s_harfBuzzFaceCache; 83 return &s_harfBuzzFaceCache;
88 } 84 }
89 85
86
90 HarfBuzzFace::HarfBuzzFace(FontPlatformData* platformData, uint64_t uniqueID) 87 HarfBuzzFace::HarfBuzzFace(FontPlatformData* platformData, uint64_t uniqueID)
91 : m_platformData(platformData) 88 : m_platformData(platformData)
92 , m_uniqueID(uniqueID) 89 , m_uniqueID(uniqueID)
93 { 90 {
94 HarfBuzzFaceCache::AddResult result = harfBuzzFaceCache()->add(m_uniqueID, n ullptr); 91 HarfBuzzFaceCache::AddResult result = harfBuzzFaceCache()->add(m_uniqueID, n ullptr);
95 if (result.isNewEntry) 92 if (result.isNewEntry)
96 result.storedValue->value = FaceCacheEntry::create(createFace()); 93 result.storedValue->value = FaceCacheEntry::create(createFace());
97 result.storedValue->value->ref(); 94 result.storedValue->value->ref();
98 m_face = result.storedValue->value->face(); 95 m_face = result.storedValue->value->face();
99 m_glyphCacheForFaceCacheEntry = result.storedValue->value->glyphCache(); 96 prepareHarfBuzzFontData();
100 } 97 }
101 98
102 HarfBuzzFace::~HarfBuzzFace() 99 HarfBuzzFace::~HarfBuzzFace()
103 { 100 {
104 HarfBuzzFaceCache::iterator result = harfBuzzFaceCache()->find(m_uniqueID); 101 HarfBuzzFaceCache::iterator result = harfBuzzFaceCache()->find(m_uniqueID);
105 ASSERT_WITH_SECURITY_IMPLICATION(result != harfBuzzFaceCache()->end()); 102 ASSERT_WITH_SECURITY_IMPLICATION(result != harfBuzzFaceCache()->end());
106 ASSERT(result.get()->value->refCount() > 1); 103 ASSERT(result.get()->value->refCount() > 1);
107 result.get()->value->deref(); 104 result.get()->value->deref();
108 if (result.get()->value->refCount() == 1) 105 if (result.get()->value->refCount() == 1)
109 harfBuzzFaceCache()->remove(m_uniqueID); 106 harfBuzzFaceCache()->remove(m_uniqueID);
110 } 107 }
111 108
109 // struct to carry user-pointer data for hb_font_t callback functions.
112 struct HarfBuzzFontData { 110 struct HarfBuzzFontData {
113 USING_FAST_MALLOC(HarfBuzzFontData); 111 USING_FAST_MALLOC(HarfBuzzFontData);
114 WTF_MAKE_NONCOPYABLE(HarfBuzzFontData); 112 WTF_MAKE_NONCOPYABLE(HarfBuzzFontData);
115 public: 113 public:
116 HarfBuzzFontData(WTF::HashMap<uint32_t, uint16_t>* glyphCacheForFaceCacheEnt ry, hb_face_t* face, unsigned rangeFrom, unsigned rangeTo) 114 HarfBuzzFontData()
117 : m_glyphCacheForFaceCacheEntry(glyphCacheForFaceCacheEntry) 115 : m_rangeFrom(0)
118 , m_face(face) 116 , m_rangeTo(kMaxCodepoint)
119 , m_hbOpenTypeFont(nullptr)
120 , m_rangeFrom(rangeFrom)
121 , m_rangeTo(rangeTo)
122 { } 117 { }
123 118
124 ~HarfBuzzFontData()
125 {
126 if (m_hbOpenTypeFont)
127 hb_font_destroy(m_hbOpenTypeFont);
128 }
129
130 SkPaint m_paint; 119 SkPaint m_paint;
131 RefPtr<SimpleFontData> m_simpleFontData; 120 RefPtr<SimpleFontData> m_simpleFontData;
132 WTF::HashMap<uint32_t, uint16_t>* m_glyphCacheForFaceCacheEntry;
133 hb_face_t* m_face;
134 hb_font_t* m_hbOpenTypeFont;
135 unsigned m_rangeFrom; 121 unsigned m_rangeFrom;
136 unsigned m_rangeTo; 122 unsigned m_rangeTo;
137 }; 123 };
138 124
139 static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value) 125 static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value)
140 { 126 {
141 return SkScalarToFixed(value); 127 return SkScalarToFixed(value);
142 } 128 }
143 129
144 static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint , hb_position_t* width, hb_glyph_extents_t* extents) 130 static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint , hb_position_t* width, hb_glyph_extents_t* extents)
(...skipping 20 matching lines...) Expand all
165 skBounds.set(ir); 151 skBounds.set(ir);
166 } 152 }
167 // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be y-grows-up. 153 // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be y-grows-up.
168 extents->x_bearing = SkiaScalarToHarfBuzzPosition(skBounds.fLeft); 154 extents->x_bearing = SkiaScalarToHarfBuzzPosition(skBounds.fLeft);
169 extents->y_bearing = SkiaScalarToHarfBuzzPosition(-skBounds.fTop); 155 extents->y_bearing = SkiaScalarToHarfBuzzPosition(-skBounds.fTop);
170 extents->width = SkiaScalarToHarfBuzzPosition(skBounds.width()); 156 extents->width = SkiaScalarToHarfBuzzPosition(skBounds.width());
171 extents->height = SkiaScalarToHarfBuzzPosition(-skBounds.height()); 157 extents->height = SkiaScalarToHarfBuzzPosition(-skBounds.height());
172 } 158 }
173 } 159 }
174 160
175 #if !defined(HB_VERSION_ATLEAST)
176 #define HB_VERSION_ATLEAST(major, minor, micro) 0
177 #endif
178
179 static hb_bool_t harfBuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoin t_t unicode, hb_codepoint_t variationSelector, hb_codepoint_t* glyph, void* user Data) 161 static hb_bool_t harfBuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoin t_t unicode, hb_codepoint_t variationSelector, hb_codepoint_t* glyph, void* user Data)
180 { 162 {
181 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ; 163 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ;
182 164
183 RELEASE_ASSERT(hbFontData); 165 RELEASE_ASSERT(hbFontData);
184 if (unicode < hbFontData->m_rangeFrom || unicode > hbFontData->m_rangeTo) 166 if (unicode < hbFontData->m_rangeFrom || unicode > hbFontData->m_rangeTo)
185 return false; 167 return false;
186 168
187 if (variationSelector) { 169 return hb_font_get_glyph(hb_font_get_parent(hbFont), unicode, variationSelec tor, glyph);
188 #if !HB_VERSION_ATLEAST(0, 9, 28)
189 return false;
190 #else
191 // Skia does not support variation selectors, but hb does.
192 // We're not fully ready to switch to hb-ot-font yet,
193 // but are good enough to get glyph IDs for OpenType fonts.
194 if (!hbFontData->m_hbOpenTypeFont) {
195 hbFontData->m_hbOpenTypeFont = hb_font_create(hbFontData->m_face);
196 hb_ot_font_set_funcs(hbFontData->m_hbOpenTypeFont);
197 }
198 return hb_font_get_glyph(hbFontData->m_hbOpenTypeFont, unicode, variatio nSelector, glyph);
199 // When not found, glyph_func should return false rather than fallback t o the base.
200 // http://lists.freedesktop.org/archives/harfbuzz/2015-May/004888.html
201 #endif
202 }
203
204 WTF::HashMap<uint32_t, uint16_t>::AddResult result = hbFontData->m_glyphCach eForFaceCacheEntry->add(unicode, 0);
205 if (result.isNewEntry) {
206 SkPaint* paint = &hbFontData->m_paint;
207 paint->setTextEncoding(SkPaint::kUTF32_TextEncoding);
208 uint16_t glyph16;
209 paint->textToGlyphs(&unicode, sizeof(hb_codepoint_t), &glyph16);
210 result.storedValue->value = glyph16;
211 *glyph = glyph16;
212 }
213 *glyph = result.storedValue->value;
214 return !!*glyph;
215 } 170 }
216 171
217 static hb_position_t harfBuzzGetGlyphHorizontalAdvance(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, void* userData) 172 static hb_position_t harfBuzzGetGlyphHorizontalAdvance(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, void* userData)
218 { 173 {
219 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ; 174 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ;
220 hb_position_t advance = 0; 175 hb_position_t advance = 0;
221 176
222 SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, &advance, 0); 177 SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, &advance, 0);
223 return advance; 178 return advance;
224 } 179 }
225 180
226 static hb_bool_t harfBuzzGetGlyphHorizontalOrigin(hb_font_t* hbFont, void* fontD ata, hb_codepoint_t glyph, hb_position_t* x, hb_position_t* y, void* userData)
227 {
228 // Just return true, following the way that HarfBuzz-FreeType
229 // implementation does.
230 return true;
231 }
232
233 static hb_bool_t harfBuzzGetGlyphVerticalOrigin(hb_font_t* hbFont, void* fontDat a, hb_codepoint_t glyph, hb_position_t* x, hb_position_t* y, void* userData) 181 static hb_bool_t harfBuzzGetGlyphVerticalOrigin(hb_font_t* hbFont, void* fontDat a, hb_codepoint_t glyph, hb_position_t* x, hb_position_t* y, void* userData)
234 { 182 {
235 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ; 183 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ;
236 const OpenTypeVerticalData* verticalData = hbFontData->m_simpleFontData->ver ticalData(); 184 const OpenTypeVerticalData* verticalData = hbFontData->m_simpleFontData->ver ticalData();
237 if (!verticalData) 185 if (!verticalData)
238 return false; 186 return false;
239 187
240 float result[] = { 0, 0 }; 188 float result[] = { 0, 0 };
241 Glyph theGlyph = glyph; 189 Glyph theGlyph = glyph;
242 verticalData->getVerticalTranslationsForGlyphs(hbFontData->m_simpleFontData. get(), &theGlyph, 1, result); 190 verticalData->getVerticalTranslationsForGlyphs(hbFontData->m_simpleFontData. get(), &theGlyph, 1, result);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 { 239 {
292 static hb_font_funcs_t* harfBuzzSkiaFontFuncs = 0; 240 static hb_font_funcs_t* harfBuzzSkiaFontFuncs = 0;
293 241
294 // We don't set callback functions which we can't support. 242 // We don't set callback functions which we can't support.
295 // HarfBuzz will use the fallback implementation if they aren't set. 243 // HarfBuzz will use the fallback implementation if they aren't set.
296 if (!harfBuzzSkiaFontFuncs) { 244 if (!harfBuzzSkiaFontFuncs) {
297 harfBuzzSkiaFontFuncs = hb_font_funcs_create(); 245 harfBuzzSkiaFontFuncs = hb_font_funcs_create();
298 hb_font_funcs_set_glyph_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyph, 0, 0); 246 hb_font_funcs_set_glyph_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyph, 0, 0);
299 hb_font_funcs_set_glyph_h_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphHorizontalAdvance, 0, 0); 247 hb_font_funcs_set_glyph_h_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphHorizontalAdvance, 0, 0);
300 hb_font_funcs_set_glyph_h_kerning_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphHorizontalKerning, 0, 0); 248 hb_font_funcs_set_glyph_h_kerning_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphHorizontalKerning, 0, 0);
301 hb_font_funcs_set_glyph_h_origin_func(harfBuzzSkiaFontFuncs, harfBuzzGet GlyphHorizontalOrigin, 0, 0);
302 hb_font_funcs_set_glyph_v_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphVerticalAdvance, 0, 0); 249 hb_font_funcs_set_glyph_v_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphVerticalAdvance, 0, 0);
303 hb_font_funcs_set_glyph_v_origin_func(harfBuzzSkiaFontFuncs, harfBuzzGet GlyphVerticalOrigin, 0, 0); 250 hb_font_funcs_set_glyph_v_origin_func(harfBuzzSkiaFontFuncs, harfBuzzGet GlyphVerticalOrigin, 0, 0);
304 hb_font_funcs_set_glyph_extents_func(harfBuzzSkiaFontFuncs, harfBuzzGetG lyphExtents, 0, 0); 251 hb_font_funcs_set_glyph_extents_func(harfBuzzSkiaFontFuncs, harfBuzzGetG lyphExtents, 0, 0);
305 hb_font_funcs_make_immutable(harfBuzzSkiaFontFuncs); 252 hb_font_funcs_make_immutable(harfBuzzSkiaFontFuncs);
306 } 253 }
307 return harfBuzzSkiaFontFuncs; 254 return harfBuzzSkiaFontFuncs;
308 } 255 }
309 256
310 #if !OS(MACOSX) 257 #if !OS(MACOSX)
311 static hb_blob_t* harfBuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* user Data) 258 static hb_blob_t* harfBuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* user Data)
(...skipping 11 matching lines...) Expand all
323 size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer); 270 size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer);
324 if (tableSize != actualSize) { 271 if (tableSize != actualSize) {
325 WTF::Partitions::fastFree(buffer); 272 WTF::Partitions::fastFree(buffer);
326 return nullptr; 273 return nullptr;
327 } 274 }
328 275
329 return hb_blob_create(const_cast<char*>(buffer), tableSize, HB_MEMORY_MODE_W RITABLE, buffer, WTF::Partitions::fastFree); 276 return hb_blob_create(const_cast<char*>(buffer), tableSize, HB_MEMORY_MODE_W RITABLE, buffer, WTF::Partitions::fastFree);
330 } 277 }
331 #endif 278 #endif
332 279
333 static void destroyHarfBuzzFontData(void* userData)
334 {
335 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(userData) ;
336 delete hbFontData;
337 }
338
339 hb_face_t* HarfBuzzFace::createFace() 280 hb_face_t* HarfBuzzFace::createFace()
340 { 281 {
341 #if OS(MACOSX) 282 #if OS(MACOSX)
342 hb_face_t* face = hb_coretext_face_create(m_platformData->cgFont()); 283 hb_face_t* face = hb_coretext_face_create(m_platformData->cgFont());
343 #else 284 #else
344 hb_face_t* face = hb_face_create_for_tables(harfBuzzSkiaGetTable, m_platform Data->typeface(), 0); 285 hb_face_t* face = hb_face_create_for_tables(harfBuzzSkiaGetTable, m_platform Data->typeface(), 0);
345 #endif 286 #endif
346 ASSERT(face); 287 ASSERT(face);
347 return face; 288 return face;
348 } 289 }
349 290
291 void HarfBuzzFace::prepareHarfBuzzFontData()
292 {
293 m_harfBuzzFontData = adoptPtr(new HarfBuzzFontData());
294 m_harfBuzzFontData->m_simpleFontData = FontCache::fontCache()->fontDataFromF ontPlatformData(m_platformData);
295 ASSERT(m_harfBuzzFontData->m_simpleFontData);
296 HarfBuzzScopedPtr<hb_font_t> otFont(hb_font_create(m_face), hb_font_destroy) ;
kojii 2016/02/25 07:55:17 HarfBuzzScopedPtr is not needed for hb_font_t as I
drott 2016/02/25 09:05:59 Thanks, good point, updated accordingly.
297 hb_ot_font_set_funcs(otFont.get());
298 // Creating a sub font means that non-available functions
299 // are found from the parent.
300 m_unscaledFont = hb_font_create_sub_font(otFont.get());
301 hb_font_set_funcs(m_unscaledFont, harfBuzzSkiaGetFontFuncs(), m_harfBuzzFont Data.get(), nullptr);
302 }
303
350 hb_font_t* HarfBuzzFace::createFont(unsigned rangeFrom, unsigned rangeTo) const 304 hb_font_t* HarfBuzzFace::createFont(unsigned rangeFrom, unsigned rangeTo) const
351 { 305 {
352 HarfBuzzFontData* hbFontData = new HarfBuzzFontData(m_glyphCacheForFaceCache Entry, m_face, rangeFrom, rangeTo); 306 m_platformData->setupPaint(&m_harfBuzzFontData->m_paint);
353 m_platformData->setupPaint(&hbFontData->m_paint); 307 m_harfBuzzFontData->m_rangeFrom = rangeFrom;
354 hbFontData->m_simpleFontData = FontCache::fontCache()->fontDataFromFontPlatf ormData(m_platformData); 308 m_harfBuzzFontData->m_rangeTo = rangeTo;
355 ASSERT(hbFontData->m_simpleFontData); 309 int scale = SkiaScalarToHarfBuzzPosition(m_platformData->size());
356 hb_font_t* font = hb_font_create(m_face); 310 hb_font_set_scale(m_unscaledFont, scale, scale);
357 hb_font_set_funcs(font, harfBuzzSkiaGetFontFuncs(), hbFontData, destroyHarfB uzzFontData); 311 return hb_font_reference(m_unscaledFont);
358 float size = m_platformData->size();
359 int scale = SkiaScalarToHarfBuzzPosition(size);
360 hb_font_set_scale(font, scale, scale);
361 hb_font_make_immutable(font);
362 return font;
363 } 312 }
364 313
365 } // namespace blink 314 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698