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 1943993003: Cache hb_font_t and the user data container instead of hb_face_t (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
« no previous file with comments | « third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 12 matching lines...) Expand all
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "platform/fonts/shaping/HarfBuzzFace.h" 31 #include "platform/fonts/shaping/HarfBuzzFace.h"
32 32
33 #include "hb-ot.h"
34 #include "hb.h"
35 #if OS(MACOSX)
36 #include "hb-coretext.h"
37 #endif
38 #include "SkPaint.h"
39 #include "SkPath.h"
40 #include "SkPoint.h"
41 #include "SkRect.h"
42 #include "SkTypeface.h"
43 #include "platform/fonts/FontCache.h" 33 #include "platform/fonts/FontCache.h"
44 #include "platform/fonts/FontPlatformData.h" 34 #include "platform/fonts/FontPlatformData.h"
45 #include "platform/fonts/SimpleFontData.h" 35 #include "platform/fonts/SimpleFontData.h"
46 #include "platform/fonts/UnicodeRangeSet.h" 36 #include "platform/fonts/UnicodeRangeSet.h"
47 #include "platform/fonts/shaping/HarfBuzzShaper.h" 37 #include "platform/fonts/shaping/HarfBuzzShaper.h"
48 #include "wtf/HashMap.h" 38 #include "wtf/HashMap.h"
49 #include "wtf/MathExtras.h" 39 #include "wtf/MathExtras.h"
50 40
41 #include <hb-ot.h>
42 #include <hb.h>
43 #if OS(MACOSX)
44 #include <hb-coretext.h>
45 #endif
46
47 #include <SkPaint.h>
48 #include <SkPath.h>
49 #include <SkPoint.h>
50 #include <SkRect.h>
51 #include <SkTypeface.h>
52
53
51 namespace blink { 54 namespace blink {
52 55
53 // Though we have FontCache class, which provides the cache mechanism for
54 // 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
56 // underling font data (e.g. CTFontRef, FTFace).
57
58 class FaceCacheEntry : public RefCounted<FaceCacheEntry> {
59 public:
60 static PassRefPtr<FaceCacheEntry> create(hb_face_t* face)
61 {
62 ASSERT(face);
63 return adoptRef(new FaceCacheEntry(face));
64 }
65 ~FaceCacheEntry()
66 {
67 hb_face_destroy(m_face);
68 }
69
70 hb_face_t* face() { return m_face; }
71
72 private:
73 explicit FaceCacheEntry(hb_face_t* face)
74 : m_face(face)
75 { }
76
77 hb_face_t* m_face;
78 };
79
80 typedef HashMap<uint64_t, RefPtr<FaceCacheEntry>, WTF::IntHash<uint64_t>, WTF::U nsignedWithZeroKeyHashTraits<uint64_t>> HarfBuzzFaceCache;
81
82 static HarfBuzzFaceCache* harfBuzzFaceCache()
83 {
84 DEFINE_STATIC_LOCAL(HarfBuzzFaceCache, s_harfBuzzFaceCache, ());
85 return &s_harfBuzzFaceCache;
86 }
87
88 HarfBuzzFace::HarfBuzzFace(FontPlatformData* platformData, uint64_t uniqueID)
89 : m_platformData(platformData)
90 , m_uniqueID(uniqueID)
91 {
92 HarfBuzzFaceCache::AddResult result = harfBuzzFaceCache()->add(m_uniqueID, n ullptr);
93 if (result.isNewEntry)
94 result.storedValue->value = FaceCacheEntry::create(createFace());
95 result.storedValue->value->ref();
96 m_face = result.storedValue->value->face();
97 prepareHarfBuzzFontData();
98 }
99
100 HarfBuzzFace::~HarfBuzzFace()
101 {
102 HarfBuzzFaceCache::iterator result = harfBuzzFaceCache()->find(m_uniqueID);
103 ASSERT_WITH_SECURITY_IMPLICATION(result != harfBuzzFaceCache()->end());
104 ASSERT(result.get()->value->refCount() > 1);
105 result.get()->value->deref();
106 if (result.get()->value->refCount() == 1)
107 harfBuzzFaceCache()->remove(m_uniqueID);
108 }
109
110 // struct to carry user-pointer data for hb_font_t callback functions. 56 // struct to carry user-pointer data for hb_font_t callback functions.
111 struct HarfBuzzFontData { 57 struct HarfBuzzFontData {
112 USING_FAST_MALLOC(HarfBuzzFontData); 58 USING_FAST_MALLOC(HarfBuzzFontData);
113 WTF_MAKE_NONCOPYABLE(HarfBuzzFontData); 59 WTF_MAKE_NONCOPYABLE(HarfBuzzFontData);
114 public: 60 public:
115 61
116 HarfBuzzFontData() {} 62 HarfBuzzFontData()
117 HarfBuzzFontData(WTF::HashMap<uint32_t, uint16_t>* glyphCacheForFaceCacheEnt ry, hb_face_t* face, PassRefPtr<UnicodeRangeSet> rangeSet) 63 : m_paint(SkPaint())
118 : m_face(face) 64 , m_simpleFontData(nullptr)
119 , m_hbOpenTypeFont(nullptr) 65 , m_rangeSet(nullptr)
120 , m_rangeSet(rangeSet)
121 { 66 {
122 } 67 }
123 68
124 SkPaint m_paint; 69 SkPaint m_paint;
125 RefPtr<SimpleFontData> m_simpleFontData; 70 RefPtr<SimpleFontData> m_simpleFontData;
126 hb_face_t* m_face;
127 hb_font_t* m_hbOpenTypeFont;
128 RefPtr<UnicodeRangeSet> m_rangeSet; 71 RefPtr<UnicodeRangeSet> m_rangeSet;
129 }; 72 };
130 73
74 // Though we have FontCache class, which provides the cache mechanism for
75 // WebKit's font objects, we also need additional caching layer for HarfBuzz to
76 // reduce the number of hb_font_t objects created. Without it, we would create
77 // an hb_font_t object for every FontPlatformData object. But insted, we only
78 // need one for each unique SkTypeface.
79 // FIXME: We should fix the FontCache to only keep one FontPlatformData object
80 // independet of size, then consider using this here.
eae 2016/05/04 12:46:03 If (when) we fix that, would we even need this cac
81 class HbFontCacheEntry : public RefCounted<HbFontCacheEntry> {
82 public:
83 static PassRefPtr<HbFontCacheEntry> create(hb_font_t* hbFont)
84 {
85 ASSERT(hbFont);
86 return adoptRef(new HbFontCacheEntry(hbFont));
87 }
88
89 hb_font_t* hbFont() { return m_hbFont.get(); }
90 HarfBuzzFontData* hbFontData() { return m_hbFontData.get(); }
91
92 private:
93 explicit HbFontCacheEntry(hb_font_t* font)
94 : m_hbFont(adoptPtr(font))
95 , m_hbFontData(adoptPtr(new HarfBuzzFontData()))
96 { };
97
98 OwnPtr<hb_font_t> m_hbFont;
99 OwnPtr<HarfBuzzFontData> m_hbFontData;
100 };
101
102 typedef HashMap<uint64_t, RefPtr<HbFontCacheEntry>, WTF::IntHash<uint64_t>, WTF: :UnsignedWithZeroKeyHashTraits<uint64_t>> HarfBuzzFontCache;
103
104 static HarfBuzzFontCache* harfBuzzFontCache()
105 {
106 DEFINE_STATIC_LOCAL(HarfBuzzFontCache, s_harfBuzzFontCache, ());
107 return &s_harfBuzzFontCache;
108 }
109
110 static PassRefPtr<HbFontCacheEntry> createHbFontCacheEntry(hb_face_t*);
111
112 HarfBuzzFace::HarfBuzzFace(FontPlatformData* platformData, uint64_t uniqueID)
113 : m_platformData(platformData)
114 , m_uniqueID(uniqueID)
115 {
116 HarfBuzzFontCache::AddResult result = harfBuzzFontCache()->add(m_uniqueID, n ullptr);
117 if (result.isNewEntry) {
118 OwnPtr<hb_face_t> face = adoptPtr(createFace());
119 result.storedValue->value = createHbFontCacheEntry(face.get());
120 }
121 result.storedValue->value->ref();
122 m_unscaledFont = result.storedValue->value->hbFont();
123 m_harfBuzzFontData = result.storedValue->value->hbFontData();
124 }
125
126 HarfBuzzFace::~HarfBuzzFace()
127 {
128 HarfBuzzFontCache::iterator result = harfBuzzFontCache()->find(m_uniqueID);
129 ASSERT_WITH_SECURITY_IMPLICATION(result != harfBuzzFontCache()->end());
130 ASSERT(result.get()->value->refCount() > 1);
131 result.get()->value->deref();
132 if (result.get()->value->refCount() == 1)
133 harfBuzzFontCache()->remove(m_uniqueID);
134 }
135
131 static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value) 136 static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value)
132 { 137 {
133 // We treat HarfBuzz hb_position_t as 16.16 fixed-point. 138 // We treat HarfBuzz hb_position_t as 16.16 fixed-point.
134 static const int kHbPosition1 = 1 << 16; 139 static const int kHbPosition1 = 1 << 16;
135 return clampTo<int>(value * kHbPosition1); 140 return clampTo<int>(value * kHbPosition1);
136 } 141 }
137 142
138 static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint , hb_position_t* width, hb_glyph_extents_t* extents) 143 static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint , hb_position_t* width, hb_glyph_extents_t* extents)
139 { 144 {
140 ASSERT(codepoint <= 0xFFFF); 145 ASSERT(codepoint <= 0xFFFF);
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 } 278 }
274 279
275 char* buffer = reinterpret_cast<char*>(WTF::Partitions::fastMalloc(tableSize , WTF_HEAP_PROFILER_TYPE_NAME(HarfBuzzFontData))); 280 char* buffer = reinterpret_cast<char*>(WTF::Partitions::fastMalloc(tableSize , WTF_HEAP_PROFILER_TYPE_NAME(HarfBuzzFontData)));
276 if (!buffer) 281 if (!buffer)
277 return nullptr; 282 return nullptr;
278 size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer); 283 size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer);
279 if (tableSize != actualSize) { 284 if (tableSize != actualSize) {
280 WTF::Partitions::fastFree(buffer); 285 WTF::Partitions::fastFree(buffer);
281 return nullptr; 286 return nullptr;
282 } 287 }
283
284 return hb_blob_create(const_cast<char*>(buffer), tableSize, HB_MEMORY_MODE_W RITABLE, buffer, WTF::Partitions::fastFree); 288 return hb_blob_create(const_cast<char*>(buffer), tableSize, HB_MEMORY_MODE_W RITABLE, buffer, WTF::Partitions::fastFree);
285 } 289 }
286 #endif 290 #endif
287 291
288 hb_face_t* HarfBuzzFace::createFace() 292 hb_face_t* HarfBuzzFace::createFace()
289 { 293 {
290 #if OS(MACOSX) 294 #if OS(MACOSX)
291 hb_face_t* face = hb_coretext_face_create(m_platformData->cgFont()); 295 hb_face_t* face = hb_coretext_face_create(m_platformData->cgFont());
292 #else 296 #else
293 hb_face_t* face = hb_face_create_for_tables(harfBuzzSkiaGetTable, m_platform Data->typeface(), 0); 297 hb_face_t* face = hb_face_create_for_tables(harfBuzzSkiaGetTable, m_platform Data->typeface(), 0);
294 #endif 298 #endif
295 ASSERT(face); 299 ASSERT(face);
296 return face; 300 return face;
297 } 301 }
298 302
299 void HarfBuzzFace::prepareHarfBuzzFontData() 303 PassRefPtr<HbFontCacheEntry> createHbFontCacheEntry(hb_face_t* face)
300 { 304 {
301 m_harfBuzzFontData = adoptPtr(new HarfBuzzFontData()); 305 OwnPtr<hb_font_t> otFont = adoptPtr(hb_font_create(face));
302 m_harfBuzzFontData->m_simpleFontData = FontCache::fontCache()->fontDataFromF ontPlatformData(m_platformData);
303 ASSERT(m_harfBuzzFontData->m_simpleFontData);
304 OwnPtr<hb_font_t> otFont = adoptPtr(hb_font_create(m_face));
305 hb_ot_font_set_funcs(otFont.get()); 306 hb_ot_font_set_funcs(otFont.get());
306 // Creating a sub font means that non-available functions 307 // Creating a sub font means that non-available functions
307 // are found from the parent. 308 // are found from the parent.
308 m_unscaledFont = adoptPtr(hb_font_create_sub_font(otFont.get())); 309 hb_font_t* unscaledFont = hb_font_create_sub_font(otFont.get());
309 hb_font_set_funcs(m_unscaledFont.get(), harfBuzzSkiaGetFontFuncs(), m_harfBu zzFontData.get(), nullptr); 310 RefPtr<HbFontCacheEntry> cacheEntry = HbFontCacheEntry::create(unscaledFont) ;
311 hb_font_set_funcs(unscaledFont, harfBuzzSkiaGetFontFuncs(), cacheEntry->hbFo ntData(), nullptr);
312 return cacheEntry;
310 } 313 }
311 314
312 hb_font_t* HarfBuzzFace::getScaledFont(PassRefPtr<UnicodeRangeSet> rangeSet) 315 hb_font_t* HarfBuzzFace::getScaledFont(PassRefPtr<UnicodeRangeSet> rangeSet) con st
313 { 316 {
314 m_platformData->setupPaint(&m_harfBuzzFontData->m_paint); 317 m_platformData->setupPaint(&m_harfBuzzFontData->m_paint);
315 m_harfBuzzFontData->m_rangeSet = rangeSet; 318 m_harfBuzzFontData->m_rangeSet = rangeSet;
319 m_harfBuzzFontData->m_simpleFontData = FontCache::fontCache()->fontDataFromF ontPlatformData(m_platformData);
320 ASSERT(m_harfBuzzFontData->m_simpleFontData);
316 int scale = SkiaScalarToHarfBuzzPosition(m_platformData->size()); 321 int scale = SkiaScalarToHarfBuzzPosition(m_platformData->size());
317 hb_font_set_scale(m_unscaledFont.get(), scale, scale); 322 hb_font_set_scale(m_unscaledFont, scale, scale);
318 return m_unscaledFont.get(); 323 return m_unscaledFont;
319 } 324 }
320 325
321 } // namespace blink 326 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698