OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2012 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
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. | |
29 */ | |
30 | |
31 #include "config.h" | |
32 #include "core/platform/graphics/harfbuzz/HarfBuzzFace.h" | |
33 | |
34 #include "core/platform/graphics/FontPlatformData.h" | |
35 #include "hb-ot.h" | |
36 #include "hb.h" | |
37 | |
38 namespace WebCore { | |
39 | |
40 const hb_tag_t HarfBuzzFace::vertTag = HB_TAG('v', 'e', 'r', 't'); | |
41 const hb_tag_t HarfBuzzFace::vrt2Tag = HB_TAG('v', 'r', 't', '2'); | |
42 | |
43 // Though we have FontCache class, which provides the cache mechanism for | |
44 // WebKit's font objects, we also need additional caching layer for HarfBuzz | |
45 // to reduce the memory consumption because hb_face_t should be associated with | |
46 // underling font data (e.g. CTFontRef, FTFace). | |
47 | |
48 class FaceCacheEntry : public RefCounted<FaceCacheEntry> { | |
49 public: | |
50 static PassRefPtr<FaceCacheEntry> create(hb_face_t* face) | |
51 { | |
52 ASSERT(face); | |
53 return adoptRef(new FaceCacheEntry(face)); | |
54 } | |
55 ~FaceCacheEntry() | |
56 { | |
57 hb_face_destroy(m_face); | |
58 } | |
59 | |
60 hb_face_t* face() { return m_face; } | |
61 HashMap<uint32_t, uint16_t>* glyphCache() { return &m_glyphCache; } | |
62 | |
63 private: | |
64 explicit FaceCacheEntry(hb_face_t* face) | |
65 : m_face(face) | |
66 { } | |
67 | |
68 hb_face_t* m_face; | |
69 HashMap<uint32_t, uint16_t> m_glyphCache; | |
70 }; | |
71 | |
72 typedef HashMap<uint64_t, RefPtr<FaceCacheEntry>, WTF::IntHash<uint64_t>, WTF::U
nsignedWithZeroKeyHashTraits<uint64_t> > HarfBuzzFaceCache; | |
73 | |
74 static HarfBuzzFaceCache* harfBuzzFaceCache() | |
75 { | |
76 DEFINE_STATIC_LOCAL(HarfBuzzFaceCache, s_harfBuzzFaceCache, ()); | |
77 return &s_harfBuzzFaceCache; | |
78 } | |
79 | |
80 HarfBuzzFace::HarfBuzzFace(FontPlatformData* platformData, uint64_t uniqueID) | |
81 : m_platformData(platformData) | |
82 , m_uniqueID(uniqueID) | |
83 , m_scriptForVerticalText(HB_SCRIPT_INVALID) | |
84 { | |
85 HarfBuzzFaceCache::AddResult result = harfBuzzFaceCache()->add(m_uniqueID, 0
); | |
86 if (result.isNewEntry) | |
87 result.iterator->value = FaceCacheEntry::create(createFace()); | |
88 result.iterator->value->ref(); | |
89 m_face = result.iterator->value->face(); | |
90 m_glyphCacheForFaceCacheEntry = result.iterator->value->glyphCache(); | |
91 } | |
92 | |
93 HarfBuzzFace::~HarfBuzzFace() | |
94 { | |
95 HarfBuzzFaceCache::iterator result = harfBuzzFaceCache()->find(m_uniqueID); | |
96 ASSERT_WITH_SECURITY_IMPLICATION(result != harfBuzzFaceCache()->end()); | |
97 ASSERT(result.get()->value->refCount() > 1); | |
98 result.get()->value->deref(); | |
99 if (result.get()->value->refCount() == 1) | |
100 harfBuzzFaceCache()->remove(m_uniqueID); | |
101 } | |
102 | |
103 static hb_script_t findScriptForVerticalGlyphSubstitution(hb_face_t* face) | |
104 { | |
105 static const unsigned maxCount = 32; | |
106 | |
107 unsigned scriptCount = maxCount; | |
108 hb_tag_t scriptTags[maxCount]; | |
109 hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCount, sc
riptTags); | |
110 for (unsigned scriptIndex = 0; scriptIndex < scriptCount; ++scriptIndex) { | |
111 unsigned languageCount = maxCount; | |
112 hb_tag_t languageTags[maxCount]; | |
113 hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, scriptIndex,
0, &languageCount, languageTags); | |
114 for (unsigned languageIndex = 0; languageIndex < languageCount; ++langua
geIndex) { | |
115 unsigned featureIndex; | |
116 if (hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptI
ndex, languageIndex, HarfBuzzFace::vertTag, &featureIndex) | |
117 || hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scri
ptIndex, languageIndex, HarfBuzzFace::vrt2Tag, &featureIndex)) | |
118 return hb_ot_tag_to_script(scriptTags[scriptIndex]); | |
119 } | |
120 } | |
121 return HB_SCRIPT_INVALID; | |
122 } | |
123 | |
124 void HarfBuzzFace::setScriptForVerticalGlyphSubstitution(hb_buffer_t* buffer) | |
125 { | |
126 if (m_scriptForVerticalText == HB_SCRIPT_INVALID) | |
127 m_scriptForVerticalText = findScriptForVerticalGlyphSubstitution(m_face)
; | |
128 hb_buffer_set_script(buffer, m_scriptForVerticalText); | |
129 } | |
130 | |
131 } // namespace WebCore | |
OLD | NEW |