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

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

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

Powered by Google App Engine
This is Rietveld 408576698