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

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

Issue 1880623002: Revert "Reland: 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, 8 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
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/UnicodeRangeSet.h" 46 #include "platform/fonts/UnicodeRangeSet.h"
47 #include "platform/fonts/shaping/HarfBuzzShaper.h" 47 #include "platform/fonts/shaping/HarfBuzzShaper.h"
48 #include "wtf/HashMap.h" 48 #include "wtf/HashMap.h"
49 #include "wtf/MathExtras.h" 49 #include "wtf/MathExtras.h"
50 50
51 namespace blink { 51 namespace blink {
52 52
53 const hb_tag_t HarfBuzzFace::vertTag = HB_TAG('v', 'e', 'r', 't');
54
53 // Though we have FontCache class, which provides the cache mechanism for 55 // Though we have FontCache class, which provides the cache mechanism for
54 // WebKit's font objects, we also need additional caching layer for HarfBuzz 56 // 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 57 // to reduce the memory consumption because hb_face_t should be associated with
56 // underling font data (e.g. CTFontRef, FTFace). 58 // underling font data (e.g. CTFontRef, FTFace).
57 59
58 class FaceCacheEntry : public RefCounted<FaceCacheEntry> { 60 class FaceCacheEntry : public RefCounted<FaceCacheEntry> {
59 public: 61 public:
60 static PassRefPtr<FaceCacheEntry> create(hb_face_t* face) 62 static PassRefPtr<FaceCacheEntry> create(hb_face_t* face)
61 { 63 {
62 ASSERT(face); 64 ASSERT(face);
63 return adoptRef(new FaceCacheEntry(face)); 65 return adoptRef(new FaceCacheEntry(face));
64 } 66 }
65 ~FaceCacheEntry() 67 ~FaceCacheEntry()
66 { 68 {
67 hb_face_destroy(m_face); 69 hb_face_destroy(m_face);
68 } 70 }
69 71
70 hb_face_t* face() { return m_face; } 72 hb_face_t* face() { return m_face; }
73 HashMap<uint32_t, uint16_t>* glyphCache() { return &m_glyphCache; }
71 74
72 private: 75 private:
73 explicit FaceCacheEntry(hb_face_t* face) 76 explicit FaceCacheEntry(hb_face_t* face)
74 : m_face(face) 77 : m_face(face)
75 { } 78 { }
76 79
77 hb_face_t* m_face; 80 hb_face_t* m_face;
81 HashMap<uint32_t, uint16_t> m_glyphCache;
78 }; 82 };
79 83
80 typedef HashMap<uint64_t, RefPtr<FaceCacheEntry>, WTF::IntHash<uint64_t>, WTF::U nsignedWithZeroKeyHashTraits<uint64_t>> HarfBuzzFaceCache; 84 typedef HashMap<uint64_t, RefPtr<FaceCacheEntry>, WTF::IntHash<uint64_t>, WTF::U nsignedWithZeroKeyHashTraits<uint64_t>> HarfBuzzFaceCache;
81 85
82 static HarfBuzzFaceCache* harfBuzzFaceCache() 86 static HarfBuzzFaceCache* harfBuzzFaceCache()
83 { 87 {
84 DEFINE_STATIC_LOCAL(HarfBuzzFaceCache, s_harfBuzzFaceCache, ()); 88 DEFINE_STATIC_LOCAL(HarfBuzzFaceCache, s_harfBuzzFaceCache, ());
85 return &s_harfBuzzFaceCache; 89 return &s_harfBuzzFaceCache;
86 } 90 }
87 91
88 HarfBuzzFace::HarfBuzzFace(FontPlatformData* platformData, uint64_t uniqueID) 92 HarfBuzzFace::HarfBuzzFace(FontPlatformData* platformData, uint64_t uniqueID)
89 : m_platformData(platformData) 93 : m_platformData(platformData)
90 , m_uniqueID(uniqueID) 94 , m_uniqueID(uniqueID)
91 { 95 {
92 HarfBuzzFaceCache::AddResult result = harfBuzzFaceCache()->add(m_uniqueID, n ullptr); 96 HarfBuzzFaceCache::AddResult result = harfBuzzFaceCache()->add(m_uniqueID, n ullptr);
93 if (result.isNewEntry) 97 if (result.isNewEntry)
94 result.storedValue->value = FaceCacheEntry::create(createFace()); 98 result.storedValue->value = FaceCacheEntry::create(createFace());
95 result.storedValue->value->ref(); 99 result.storedValue->value->ref();
96 m_face = result.storedValue->value->face(); 100 m_face = result.storedValue->value->face();
97 prepareHarfBuzzFontData(); 101 m_glyphCacheForFaceCacheEntry = result.storedValue->value->glyphCache();
98 } 102 }
99 103
100 HarfBuzzFace::~HarfBuzzFace() 104 HarfBuzzFace::~HarfBuzzFace()
101 { 105 {
102 HarfBuzzFaceCache::iterator result = harfBuzzFaceCache()->find(m_uniqueID); 106 HarfBuzzFaceCache::iterator result = harfBuzzFaceCache()->find(m_uniqueID);
103 ASSERT_WITH_SECURITY_IMPLICATION(result != harfBuzzFaceCache()->end()); 107 ASSERT_WITH_SECURITY_IMPLICATION(result != harfBuzzFaceCache()->end());
104 ASSERT(result.get()->value->refCount() > 1); 108 ASSERT(result.get()->value->refCount() > 1);
105 result.get()->value->deref(); 109 result.get()->value->deref();
106 if (result.get()->value->refCount() == 1) 110 if (result.get()->value->refCount() == 1)
107 harfBuzzFaceCache()->remove(m_uniqueID); 111 harfBuzzFaceCache()->remove(m_uniqueID);
108 } 112 }
109 113
110 // struct to carry user-pointer data for hb_font_t callback functions.
111 struct HarfBuzzFontData { 114 struct HarfBuzzFontData {
112 USING_FAST_MALLOC(HarfBuzzFontData); 115 USING_FAST_MALLOC(HarfBuzzFontData);
113 WTF_MAKE_NONCOPYABLE(HarfBuzzFontData); 116 WTF_MAKE_NONCOPYABLE(HarfBuzzFontData);
114 public: 117 public:
115
116 HarfBuzzFontData() {}
117 HarfBuzzFontData(WTF::HashMap<uint32_t, uint16_t>* glyphCacheForFaceCacheEnt ry, hb_face_t* face, PassRefPtr<UnicodeRangeSet> rangeSet) 118 HarfBuzzFontData(WTF::HashMap<uint32_t, uint16_t>* glyphCacheForFaceCacheEnt ry, hb_face_t* face, PassRefPtr<UnicodeRangeSet> rangeSet)
118 : m_face(face) 119 : m_glyphCacheForFaceCacheEntry(glyphCacheForFaceCacheEntry)
120 , m_face(face)
119 , m_hbOpenTypeFont(nullptr) 121 , m_hbOpenTypeFont(nullptr)
120 , m_rangeSet(rangeSet) 122 , m_rangeSet(rangeSet)
121 { 123 {
122 } 124 }
123 125
126 ~HarfBuzzFontData()
127 {
128 if (m_hbOpenTypeFont)
129 hb_font_destroy(m_hbOpenTypeFont);
130 }
131
124 SkPaint m_paint; 132 SkPaint m_paint;
125 RefPtr<SimpleFontData> m_simpleFontData; 133 RefPtr<SimpleFontData> m_simpleFontData;
134 WTF::HashMap<uint32_t, uint16_t>* m_glyphCacheForFaceCacheEntry;
126 hb_face_t* m_face; 135 hb_face_t* m_face;
127 hb_font_t* m_hbOpenTypeFont; 136 hb_font_t* m_hbOpenTypeFont;
128 RefPtr<UnicodeRangeSet> m_rangeSet; 137 RefPtr<UnicodeRangeSet> m_rangeSet;
129 }; 138 };
130 139
131 static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value) 140 static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value)
132 { 141 {
133 // We treat HarfBuzz hb_position_t as 16.16 fixed-point. 142 // We treat HarfBuzz hb_position_t as 16.16 fixed-point.
134 static const int kHbPosition1 = 1 << 16; 143 static const int kHbPosition1 = 1 << 16;
135 return clampTo<int>(value * kHbPosition1); 144 return clampTo<int>(value * kHbPosition1);
(...skipping 23 matching lines...) Expand all
159 skBounds.set(ir); 168 skBounds.set(ir);
160 } 169 }
161 // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be y-grows-up. 170 // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be y-grows-up.
162 extents->x_bearing = SkiaScalarToHarfBuzzPosition(skBounds.fLeft); 171 extents->x_bearing = SkiaScalarToHarfBuzzPosition(skBounds.fLeft);
163 extents->y_bearing = SkiaScalarToHarfBuzzPosition(-skBounds.fTop); 172 extents->y_bearing = SkiaScalarToHarfBuzzPosition(-skBounds.fTop);
164 extents->width = SkiaScalarToHarfBuzzPosition(skBounds.width()); 173 extents->width = SkiaScalarToHarfBuzzPosition(skBounds.width());
165 extents->height = SkiaScalarToHarfBuzzPosition(-skBounds.height()); 174 extents->height = SkiaScalarToHarfBuzzPosition(-skBounds.height());
166 } 175 }
167 } 176 }
168 177
178 #if !defined(HB_VERSION_ATLEAST)
179 #define HB_VERSION_ATLEAST(major, minor, micro) 0
180 #endif
181
169 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) 182 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)
170 { 183 {
171 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ; 184 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ;
172 185
173 RELEASE_ASSERT(hbFontData); 186 RELEASE_ASSERT(hbFontData);
174 if (hbFontData->m_rangeSet && !hbFontData->m_rangeSet->contains(unicode)) 187 if (hbFontData->m_rangeSet && !hbFontData->m_rangeSet->contains(unicode))
175 return false; 188 return false;
176 189
177 return hb_font_get_glyph(hb_font_get_parent(hbFont), unicode, variationSelec tor, glyph); 190 if (variationSelector) {
191 #if !HB_VERSION_ATLEAST(0, 9, 28)
192 return false;
193 #else
194 // Skia does not support variation selectors, but hb does.
195 // We're not fully ready to switch to hb-ot-font yet,
196 // but are good enough to get glyph IDs for OpenType fonts.
197 if (!hbFontData->m_hbOpenTypeFont) {
198 hbFontData->m_hbOpenTypeFont = hb_font_create(hbFontData->m_face);
199 hb_ot_font_set_funcs(hbFontData->m_hbOpenTypeFont);
200 }
201 return hb_font_get_glyph(hbFontData->m_hbOpenTypeFont, unicode, variatio nSelector, glyph);
202 // When not found, glyph_func should return false rather than fallback t o the base.
203 // http://lists.freedesktop.org/archives/harfbuzz/2015-May/004888.html
204 #endif
205 }
206
207 WTF::HashMap<uint32_t, uint16_t>::AddResult result = hbFontData->m_glyphCach eForFaceCacheEntry->add(unicode, 0);
208 if (result.isNewEntry) {
209 SkPaint* paint = &hbFontData->m_paint;
210 paint->setTextEncoding(SkPaint::kUTF32_TextEncoding);
211 uint16_t glyph16;
212 paint->textToGlyphs(&unicode, sizeof(hb_codepoint_t), &glyph16);
213 result.storedValue->value = glyph16;
214 *glyph = glyph16;
215 }
216 *glyph = result.storedValue->value;
217 return !!*glyph;
178 } 218 }
179 219
180 static hb_position_t harfBuzzGetGlyphHorizontalAdvance(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, void* userData) 220 static hb_position_t harfBuzzGetGlyphHorizontalAdvance(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, void* userData)
181 { 221 {
182 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ; 222 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ;
183 hb_position_t advance = 0; 223 hb_position_t advance = 0;
184 224
185 SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, &advance, 0); 225 SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, &advance, 0);
186 return advance; 226 return advance;
187 } 227 }
188 228
229 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)
230 {
231 // Just return true, following the way that HarfBuzz-FreeType
232 // implementation does.
233 return true;
234 }
235
189 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) 236 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)
190 { 237 {
191 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ; 238 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData) ;
192 const OpenTypeVerticalData* verticalData = hbFontData->m_simpleFontData->ver ticalData(); 239 const OpenTypeVerticalData* verticalData = hbFontData->m_simpleFontData->ver ticalData();
193 if (!verticalData) 240 if (!verticalData)
194 return false; 241 return false;
195 242
196 float result[] = { 0, 0 }; 243 float result[] = { 0, 0 };
197 Glyph theGlyph = glyph; 244 Glyph theGlyph = glyph;
198 verticalData->getVerticalTranslationsForGlyphs(hbFontData->m_simpleFontData. get(), &theGlyph, 1, result); 245 verticalData->getVerticalTranslationsForGlyphs(hbFontData->m_simpleFontData. get(), &theGlyph, 1, result);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 { 294 {
248 static hb_font_funcs_t* harfBuzzSkiaFontFuncs = 0; 295 static hb_font_funcs_t* harfBuzzSkiaFontFuncs = 0;
249 296
250 // We don't set callback functions which we can't support. 297 // We don't set callback functions which we can't support.
251 // HarfBuzz will use the fallback implementation if they aren't set. 298 // HarfBuzz will use the fallback implementation if they aren't set.
252 if (!harfBuzzSkiaFontFuncs) { 299 if (!harfBuzzSkiaFontFuncs) {
253 harfBuzzSkiaFontFuncs = hb_font_funcs_create(); 300 harfBuzzSkiaFontFuncs = hb_font_funcs_create();
254 hb_font_funcs_set_glyph_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyph, 0, 0); 301 hb_font_funcs_set_glyph_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyph, 0, 0);
255 hb_font_funcs_set_glyph_h_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphHorizontalAdvance, 0, 0); 302 hb_font_funcs_set_glyph_h_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphHorizontalAdvance, 0, 0);
256 hb_font_funcs_set_glyph_h_kerning_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphHorizontalKerning, 0, 0); 303 hb_font_funcs_set_glyph_h_kerning_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphHorizontalKerning, 0, 0);
304 hb_font_funcs_set_glyph_h_origin_func(harfBuzzSkiaFontFuncs, harfBuzzGet GlyphHorizontalOrigin, 0, 0);
257 hb_font_funcs_set_glyph_v_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphVerticalAdvance, 0, 0); 305 hb_font_funcs_set_glyph_v_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGe tGlyphVerticalAdvance, 0, 0);
258 hb_font_funcs_set_glyph_v_origin_func(harfBuzzSkiaFontFuncs, harfBuzzGet GlyphVerticalOrigin, 0, 0); 306 hb_font_funcs_set_glyph_v_origin_func(harfBuzzSkiaFontFuncs, harfBuzzGet GlyphVerticalOrigin, 0, 0);
259 hb_font_funcs_set_glyph_extents_func(harfBuzzSkiaFontFuncs, harfBuzzGetG lyphExtents, 0, 0); 307 hb_font_funcs_set_glyph_extents_func(harfBuzzSkiaFontFuncs, harfBuzzGetG lyphExtents, 0, 0);
260 hb_font_funcs_make_immutable(harfBuzzSkiaFontFuncs); 308 hb_font_funcs_make_immutable(harfBuzzSkiaFontFuncs);
261 } 309 }
262 return harfBuzzSkiaFontFuncs; 310 return harfBuzzSkiaFontFuncs;
263 } 311 }
264 312
265 #if !OS(MACOSX) 313 #if !OS(MACOSX)
266 static hb_blob_t* harfBuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* user Data) 314 static hb_blob_t* harfBuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* user Data)
(...skipping 11 matching lines...) Expand all
278 size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer); 326 size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer);
279 if (tableSize != actualSize) { 327 if (tableSize != actualSize) {
280 WTF::Partitions::fastFree(buffer); 328 WTF::Partitions::fastFree(buffer);
281 return nullptr; 329 return nullptr;
282 } 330 }
283 331
284 return hb_blob_create(const_cast<char*>(buffer), tableSize, HB_MEMORY_MODE_W RITABLE, buffer, WTF::Partitions::fastFree); 332 return hb_blob_create(const_cast<char*>(buffer), tableSize, HB_MEMORY_MODE_W RITABLE, buffer, WTF::Partitions::fastFree);
285 } 333 }
286 #endif 334 #endif
287 335
336 static void destroyHarfBuzzFontData(void* userData)
337 {
338 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(userData) ;
339 delete hbFontData;
340 }
341
288 hb_face_t* HarfBuzzFace::createFace() 342 hb_face_t* HarfBuzzFace::createFace()
289 { 343 {
290 #if OS(MACOSX) 344 #if OS(MACOSX)
291 hb_face_t* face = hb_coretext_face_create(m_platformData->cgFont()); 345 hb_face_t* face = hb_coretext_face_create(m_platformData->cgFont());
292 #else 346 #else
293 hb_face_t* face = hb_face_create_for_tables(harfBuzzSkiaGetTable, m_platform Data->typeface(), 0); 347 hb_face_t* face = hb_face_create_for_tables(harfBuzzSkiaGetTable, m_platform Data->typeface(), 0);
294 #endif 348 #endif
295 ASSERT(face); 349 ASSERT(face);
296 return face; 350 return face;
297 } 351 }
298 352
299 void HarfBuzzFace::prepareHarfBuzzFontData() 353 hb_font_t* HarfBuzzFace::createFont(PassRefPtr<UnicodeRangeSet> rangeSet) const
300 { 354 {
301 m_harfBuzzFontData = adoptPtr(new HarfBuzzFontData()); 355 HarfBuzzFontData* hbFontData = new HarfBuzzFontData(m_glyphCacheForFaceCache Entry, m_face, rangeSet);
302 m_harfBuzzFontData->m_simpleFontData = FontCache::fontCache()->fontDataFromF ontPlatformData(m_platformData); 356 m_platformData->setupPaint(&hbFontData->m_paint);
303 ASSERT(m_harfBuzzFontData->m_simpleFontData); 357 hbFontData->m_simpleFontData = FontCache::fontCache()->fontDataFromFontPlatf ormData(m_platformData);
304 OwnPtr<hb_font_t> otFont = adoptPtr(hb_font_create(m_face)); 358 ASSERT(hbFontData->m_simpleFontData);
305 hb_ot_font_set_funcs(otFont.get()); 359 hb_font_t* font = hb_font_create(m_face);
306 // Creating a sub font means that non-available functions 360 hb_font_set_funcs(font, harfBuzzSkiaGetFontFuncs(), hbFontData, destroyHarfB uzzFontData);
307 // are found from the parent. 361 float size = m_platformData->size();
308 m_unscaledFont = adoptPtr(hb_font_create_sub_font(otFont.get())); 362 int scale = SkiaScalarToHarfBuzzPosition(size);
309 hb_font_set_funcs(m_unscaledFont.get(), harfBuzzSkiaGetFontFuncs(), m_harfBu zzFontData.get(), nullptr); 363 hb_font_set_scale(font, scale, scale);
310 } 364 hb_font_make_immutable(font);
311 365 return font;
312 hb_font_t* HarfBuzzFace::getScaledFont(PassRefPtr<UnicodeRangeSet> rangeSet)
313 {
314 m_platformData->setupPaint(&m_harfBuzzFontData->m_paint);
315 m_harfBuzzFontData->m_rangeSet = rangeSet;
316 int scale = SkiaScalarToHarfBuzzPosition(m_platformData->size());
317 hb_font_set_scale(m_unscaledFont.get(), scale, scale);
318 return m_unscaledFont.get();
319 } 366 }
320 367
321 } // namespace blink 368 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698