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

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

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

Powered by Google App Engine
This is Rietveld 408576698