OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 Google Inc. All rights reserved. | 2 * Copyright (c) 2012 Google Inc. All rights reserved. |
3 * Copyright (C) 2013 BlackBerry Limited. All rights reserved. | 3 * Copyright (C) 2013 BlackBerry Limited. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
7 * met: | 7 * met: |
8 * | 8 * |
9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 (*m_destroy)(m_ptr); | 71 (*m_destroy)(m_ptr); |
72 } | 72 } |
73 | 73 |
74 T* get() { return m_ptr; } | 74 T* get() { return m_ptr; } |
75 void set(T* ptr) { m_ptr = ptr; } | 75 void set(T* ptr) { m_ptr = ptr; } |
76 private: | 76 private: |
77 T* m_ptr; | 77 T* m_ptr; |
78 DestroyFunction m_destroy; | 78 DestroyFunction m_destroy; |
79 }; | 79 }; |
80 | 80 |
81 | |
82 static const unsigned cHarfBuzzCacheMaxSize = 256; | |
83 | |
84 struct CachedShapingResultsLRUNode; | |
85 struct CachedShapingResults; | |
86 typedef std::map<std::wstring, CachedShapingResults*> CachedShapingResultsMap; | |
87 typedef std::list<CachedShapingResultsLRUNode*> CachedShapingResultsLRU; | |
88 | |
89 struct CachedShapingResults { | |
90 CachedShapingResults(hb_buffer_t* harfBuzzBuffer, const Font* runFont, hb_di
rection_t runDir, const String& newLocale); | |
91 ~CachedShapingResults(); | |
92 | |
93 hb_buffer_t* buffer; | |
94 Font font; | |
95 hb_direction_t dir; | |
96 String locale; | |
97 CachedShapingResultsLRU::iterator lru; | |
98 }; | |
99 | |
100 struct CachedShapingResultsLRUNode { | |
101 CachedShapingResultsLRUNode(const CachedShapingResultsMap::iterator& cacheEn
try); | |
102 ~CachedShapingResultsLRUNode(); | |
103 | |
104 CachedShapingResultsMap::iterator entry; | |
105 }; | |
106 | |
107 CachedShapingResults::CachedShapingResults(hb_buffer_t* harfBuzzBuffer, const Fo
nt* fontData, hb_direction_t dirData, const String& newLocale) | |
108 : buffer(harfBuzzBuffer) | |
109 , font(*fontData) | |
110 , dir(dirData) | |
111 , locale(newLocale) | |
112 { | |
113 } | |
114 | |
115 CachedShapingResults::~CachedShapingResults() | |
116 { | |
117 hb_buffer_destroy(buffer); | |
118 } | |
119 | |
120 CachedShapingResultsLRUNode::CachedShapingResultsLRUNode(const CachedShapingResu
ltsMap::iterator& cacheEntry) | |
121 : entry(cacheEntry) | |
122 { | |
123 } | |
124 | |
125 CachedShapingResultsLRUNode::~CachedShapingResultsLRUNode() | |
126 { | |
127 } | |
128 | |
129 class HarfBuzzRunCache { | |
130 public: | |
131 HarfBuzzRunCache(); | |
132 ~HarfBuzzRunCache(); | |
133 | |
134 CachedShapingResults* find(const std::wstring& key) const; | |
135 void remove(CachedShapingResults* node); | |
136 void moveToBack(CachedShapingResults* node); | |
137 bool insert(const std::wstring& key, CachedShapingResults* run); | |
138 | |
139 private: | |
140 CachedShapingResultsMap m_harfBuzzRunMap; | |
141 CachedShapingResultsLRU m_harfBuzzRunLRU; | |
142 }; | |
143 | |
144 | |
145 HarfBuzzRunCache::HarfBuzzRunCache() | |
146 { | |
147 } | |
148 | |
149 HarfBuzzRunCache::~HarfBuzzRunCache() | |
150 { | |
151 for (CachedShapingResultsMap::iterator it = m_harfBuzzRunMap.begin(); it !=
m_harfBuzzRunMap.end(); ++it) | |
152 delete it->second; | |
153 for (CachedShapingResultsLRU::iterator it = m_harfBuzzRunLRU.begin(); it !=
m_harfBuzzRunLRU.end(); ++it) | |
154 delete *it; | |
155 } | |
156 | |
157 bool HarfBuzzRunCache::insert(const std::wstring& key, CachedShapingResults* dat
a) | |
158 { | |
159 std::pair<CachedShapingResultsMap::iterator, bool> results = | |
160 m_harfBuzzRunMap.insert(CachedShapingResultsMap::value_type(key, data)); | |
161 | |
162 if (!results.second) | |
163 return false; | |
164 | |
165 CachedShapingResultsLRUNode* node = new CachedShapingResultsLRUNode(results.
first); | |
166 | |
167 m_harfBuzzRunLRU.push_back(node); | |
168 data->lru = --m_harfBuzzRunLRU.end(); | |
169 | |
170 if (m_harfBuzzRunMap.size() > cHarfBuzzCacheMaxSize) { | |
171 CachedShapingResultsLRUNode* lru = m_harfBuzzRunLRU.front(); | |
172 CachedShapingResults* foo = lru->entry->second; | |
173 m_harfBuzzRunMap.erase(lru->entry); | |
174 m_harfBuzzRunLRU.pop_front(); | |
175 delete foo; | |
176 delete lru; | |
177 } | |
178 | |
179 return true; | |
180 } | |
181 | |
182 inline CachedShapingResults* HarfBuzzRunCache::find(const std::wstring& key) con
st | |
183 { | |
184 CachedShapingResultsMap::const_iterator it = m_harfBuzzRunMap.find(key); | |
185 | |
186 return it != m_harfBuzzRunMap.end() ? it->second : 0; | |
187 } | |
188 | |
189 inline void HarfBuzzRunCache::remove(CachedShapingResults* node) | |
190 { | |
191 CachedShapingResultsLRUNode* lruNode = *node->lru; | |
192 | |
193 m_harfBuzzRunLRU.erase(node->lru); | |
194 m_harfBuzzRunMap.erase(lruNode->entry); | |
195 delete lruNode; | |
196 delete node; | |
197 } | |
198 | |
199 inline void HarfBuzzRunCache::moveToBack(CachedShapingResults* node) | |
200 { | |
201 CachedShapingResultsLRUNode* lruNode = *node->lru; | |
202 m_harfBuzzRunLRU.erase(node->lru); | |
203 m_harfBuzzRunLRU.push_back(lruNode); | |
204 node->lru = --m_harfBuzzRunLRU.end(); | |
205 } | |
206 | |
207 HarfBuzzRunCache& harfBuzzRunCache() | |
208 { | |
209 DEFINE_STATIC_LOCAL(HarfBuzzRunCache, globalHarfBuzzRunCache, ()); | |
210 return globalHarfBuzzRunCache; | |
211 } | |
212 | |
213 static inline float harfBuzzPositionToFloat(hb_position_t value) | 81 static inline float harfBuzzPositionToFloat(hb_position_t value) |
214 { | 82 { |
215 return static_cast<float>(value) / (1 << 16); | 83 return static_cast<float>(value) / (1 << 16); |
216 } | 84 } |
217 | 85 |
218 static inline unsigned countGraphemesInCluster(const UChar* normalizedBuffer, un
signed normalizedBufferLength, uint16_t startIndex, uint16_t endIndex) | 86 static inline unsigned countGraphemesInCluster(const UChar* normalizedBuffer, un
signed normalizedBufferLength, uint16_t startIndex, uint16_t endIndex) |
219 { | 87 { |
220 if (startIndex > endIndex) { | 88 if (startIndex > endIndex) { |
221 uint16_t tempIndex = startIndex; | 89 uint16_t tempIndex = startIndex; |
222 startIndex = endIndex; | 90 startIndex = endIndex; |
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 // current versions of all compilers we care about and avoids making | 673 // current versions of all compilers we care about and avoids making |
806 // a copy of the string. | 674 // a copy of the string. |
807 COMPILE_ASSERT(sizeof(UChar) == sizeof(uint16_t), UChar_is_the_same_size_as_
uint16_t); | 675 COMPILE_ASSERT(sizeof(UChar) == sizeof(uint16_t), UChar_is_the_same_size_as_
uint16_t); |
808 return reinterpret_cast<const uint16_t*>(src); | 676 return reinterpret_cast<const uint16_t*>(src); |
809 } | 677 } |
810 | 678 |
811 bool HarfBuzzShaper::shapeHarfBuzzRuns() | 679 bool HarfBuzzShaper::shapeHarfBuzzRuns() |
812 { | 680 { |
813 HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), hb_buffer_
destroy); | 681 HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), hb_buffer_
destroy); |
814 | 682 |
815 HarfBuzzRunCache& runCache = harfBuzzRunCache(); | |
816 const FontDescription& fontDescription = m_font->fontDescription(); | 683 const FontDescription& fontDescription = m_font->fontDescription(); |
817 const String& localeString = fontDescription.locale(); | 684 const String& localeString = fontDescription.locale(); |
818 CString locale = localeString.latin1(); | 685 CString locale = localeString.latin1(); |
819 | 686 |
820 for (unsigned i = 0; i < m_harfBuzzRuns.size(); ++i) { | 687 for (unsigned i = 0; i < m_harfBuzzRuns.size(); ++i) { |
821 unsigned runIndex = m_run.rtl() ? m_harfBuzzRuns.size() - i - 1 : i; | 688 unsigned runIndex = m_run.rtl() ? m_harfBuzzRuns.size() - i - 1 : i; |
822 HarfBuzzRun* currentRun = m_harfBuzzRuns[runIndex].get(); | 689 HarfBuzzRun* currentRun = m_harfBuzzRuns[runIndex].get(); |
823 const SimpleFontData* currentFontData = currentRun->fontData(); | 690 const SimpleFontData* currentFontData = currentRun->fontData(); |
824 if (currentFontData->isSVGFont()) | 691 if (currentFontData->isSVGFont()) |
825 return false; | 692 return false; |
826 | 693 |
827 FontPlatformData* platformData = const_cast<FontPlatformData*>(¤tF
ontData->platformData()); | 694 FontPlatformData* platformData = const_cast<FontPlatformData*>(¤tF
ontData->platformData()); |
828 HarfBuzzFace* face = platformData->harfBuzzFace(); | 695 HarfBuzzFace* face = platformData->harfBuzzFace(); |
829 if (!face) | 696 if (!face) |
830 return false; | 697 return false; |
831 | 698 |
832 hb_buffer_set_language(harfBuzzBuffer.get(), hb_language_from_string(loc
ale.data(), locale.length())); | 699 hb_buffer_set_language(harfBuzzBuffer.get(), hb_language_from_string(loc
ale.data(), locale.length())); |
833 hb_buffer_set_script(harfBuzzBuffer.get(), currentRun->script()); | 700 hb_buffer_set_script(harfBuzzBuffer.get(), currentRun->script()); |
834 hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->rtl() ? HB_DIR
ECTION_RTL : HB_DIRECTION_LTR); | 701 hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->rtl() ? HB_DIR
ECTION_RTL : HB_DIRECTION_LTR); |
835 | 702 |
836 hb_segment_properties_t props; | 703 hb_segment_properties_t props; |
837 hb_buffer_get_segment_properties(harfBuzzBuffer.get(), &props); | 704 hb_buffer_get_segment_properties(harfBuzzBuffer.get(), &props); |
838 | 705 |
839 const UChar* src = m_normalizedBuffer.get() + currentRun->startIndex(); | 706 const UChar* src = m_normalizedBuffer.get() + currentRun->startIndex(); |
840 std::wstring key(src, src + currentRun->numCharacters()); | 707 std::wstring key(src, src + currentRun->numCharacters()); |
841 | 708 |
842 CachedShapingResults* cachedResults = runCache.find(key); | |
843 if (cachedResults) { | |
844 if (cachedResults->dir == props.direction && cachedResults->font ==
*m_font && cachedResults->locale == localeString) { | |
845 currentRun->applyShapeResult(cachedResults->buffer); | |
846 setGlyphPositionsForHarfBuzzRun(currentRun, cachedResults->buffe
r); | |
847 | |
848 hb_buffer_clear_contents(harfBuzzBuffer.get()); | |
849 | |
850 runCache.moveToBack(cachedResults); | |
851 | |
852 continue; | |
853 } | |
854 | |
855 runCache.remove(cachedResults); | |
856 } | |
857 | |
858 // Add a space as pre-context to the buffer. This prevents showing dotte
d-circle | 709 // Add a space as pre-context to the buffer. This prevents showing dotte
d-circle |
859 // for combining marks at the beginning of runs. | 710 // for combining marks at the beginning of runs. |
860 static const uint16_t preContext = ' '; | 711 static const uint16_t preContext = ' '; |
861 hb_buffer_add_utf16(harfBuzzBuffer.get(), &preContext, 1, 1, 0); | 712 hb_buffer_add_utf16(harfBuzzBuffer.get(), &preContext, 1, 1, 0); |
862 | 713 |
863 if (fontDescription.variant() == FontVariantSmallCaps && u_islower(m_nor
malizedBuffer[currentRun->startIndex()])) { | 714 if (fontDescription.variant() == FontVariantSmallCaps && u_islower(m_nor
malizedBuffer[currentRun->startIndex()])) { |
864 String upperText = String(m_normalizedBuffer.get() + currentRun->sta
rtIndex(), currentRun->numCharacters()).upper(); | 715 String upperText = String(m_normalizedBuffer.get() + currentRun->sta
rtIndex(), currentRun->numCharacters()).upper(); |
865 ASSERT(!upperText.is8Bit()); // m_normalizedBuffer is 16 bit, theref
ore upperText is 16 bit, even after we call makeUpper(). | 716 ASSERT(!upperText.is8Bit()); // m_normalizedBuffer is 16 bit, theref
ore upperText is 16 bit, even after we call makeUpper(). |
866 hb_buffer_add_utf16(harfBuzzBuffer.get(), toUint16(upperText.charact
ers16()), currentRun->numCharacters(), 0, currentRun->numCharacters()); | 717 hb_buffer_add_utf16(harfBuzzBuffer.get(), toUint16(upperText.charact
ers16()), currentRun->numCharacters(), 0, currentRun->numCharacters()); |
867 } else { | 718 } else { |
868 hb_buffer_add_utf16(harfBuzzBuffer.get(), toUint16(m_normalizedBuffe
r.get() + currentRun->startIndex()), currentRun->numCharacters(), 0, currentRun-
>numCharacters()); | 719 hb_buffer_add_utf16(harfBuzzBuffer.get(), toUint16(m_normalizedBuffe
r.get() + currentRun->startIndex()), currentRun->numCharacters(), 0, currentRun-
>numCharacters()); |
869 } | 720 } |
870 | 721 |
871 if (fontDescription.orientation() == Vertical) | 722 if (fontDescription.orientation() == Vertical) |
872 face->setScriptForVerticalGlyphSubstitution(harfBuzzBuffer.get()); | 723 face->setScriptForVerticalGlyphSubstitution(harfBuzzBuffer.get()); |
873 | 724 |
874 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(), hb_font_de
stroy); | 725 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(), hb_font_de
stroy); |
875 | 726 |
876 hb_shape(harfBuzzFont.get(), harfBuzzBuffer.get(), m_features.isEmpty()
? 0 : m_features.data(), m_features.size()); | 727 hb_shape(harfBuzzFont.get(), harfBuzzBuffer.get(), m_features.isEmpty()
? 0 : m_features.data(), m_features.size()); |
877 currentRun->applyShapeResult(harfBuzzBuffer.get()); | 728 currentRun->applyShapeResult(harfBuzzBuffer.get()); |
878 setGlyphPositionsForHarfBuzzRun(currentRun, harfBuzzBuffer.get()); | 729 setGlyphPositionsForHarfBuzzRun(currentRun, harfBuzzBuffer.get()); |
879 | 730 |
880 runCache.insert(key, new CachedShapingResults(harfBuzzBuffer.get(), m_fo
nt, props.direction, localeString)); | |
881 | |
882 harfBuzzBuffer.set(hb_buffer_create()); | 731 harfBuzzBuffer.set(hb_buffer_create()); |
883 } | 732 } |
884 | 733 |
885 return true; | 734 return true; |
886 } | 735 } |
887 | 736 |
888 void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb
_buffer_t* harfBuzzBuffer) | 737 void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb
_buffer_t* harfBuzzBuffer) |
889 { | 738 { |
890 const SimpleFontData* currentFontData = currentRun->fontData(); | 739 const SimpleFontData* currentFontData = currentRun->fontData(); |
891 hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(harfBuzzBuffer, 0); | 740 hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(harfBuzzBuffer, 0); |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 point.x() + fromX, point.x() + toX, | 990 point.x() + fromX, point.x() + toX, |
1142 point.y(), height); | 991 point.y(), height); |
1143 } | 992 } |
1144 | 993 |
1145 return Font::pixelSnappedSelectionRect( | 994 return Font::pixelSnappedSelectionRect( |
1146 point.x() + toX, point.x() + fromX, | 995 point.x() + toX, point.x() + fromX, |
1147 point.y(), height); | 996 point.y(), height); |
1148 } | 997 } |
1149 | 998 |
1150 } // namespace blink | 999 } // namespace blink |
OLD | NEW |