| 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 |