| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright (C) 2015 Google Inc. All rights reserved. | 2  * Copyright (C) 2015 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 | 5  * modification, are permitted provided that the following conditions | 
| 6  * are met: | 6  * are met: | 
| 7  * 1. Redistributions of source code must retain the above copyright | 7  * 1. Redistributions of source code must retain the above copyright | 
| 8  *    notice, this list of conditions and the following disclaimer. | 8  *    notice, this list of conditions and the following disclaimer. | 
| 9  * 2. Redistributions in binary form must reproduce the above copyright | 9  * 2. Redistributions in binary form must reproduce the above copyright | 
| 10  *    notice, this list of conditions and the following disclaimer in the | 10  *    notice, this list of conditions and the following disclaimer in the | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 29 #include "platform/fonts/SimpleFontData.h" | 29 #include "platform/fonts/SimpleFontData.h" | 
| 30 #include "platform/fonts/shaping/CachingWordShapeIterator.h" | 30 #include "platform/fonts/shaping/CachingWordShapeIterator.h" | 
| 31 #include "platform/fonts/shaping/HarfBuzzShaper.h" | 31 #include "platform/fonts/shaping/HarfBuzzShaper.h" | 
| 32 #include "platform/fonts/shaping/ShapeCache.h" | 32 #include "platform/fonts/shaping/ShapeCache.h" | 
| 33 #include "wtf/text/CharacterNames.h" | 33 #include "wtf/text/CharacterNames.h" | 
| 34 | 34 | 
| 35 namespace blink { | 35 namespace blink { | 
| 36 | 36 | 
| 37 class CachingWordShapeIterator { | 37 class CachingWordShapeIterator { | 
| 38 public: | 38 public: | 
| 39     CachingWordShapeIterator(ShapeCache* cache, const TextRun& run | 39     CachingWordShapeIterator(ShapeCache* cache, const TextRun& run, | 
| 40         , const Font* font) | 40         const Font* font, HashSet<const SimpleFontData*>* fallbackFonts) | 
| 41         : m_shapeCache(cache), m_textRun(run), m_font(font), m_startIndex(0) | 41         : m_shapeCache(cache), m_textRun(run), m_font(font) | 
|  | 42         , m_fallbackFonts(fallbackFonts), m_startIndex(0) | 
| 42     { | 43     { | 
| 43         ASSERT(font); | 44         ASSERT(font); | 
| 44         const FontDescription& fontDescription = font->fontDescription(); | 45         const FontDescription& fontDescription = font->fontDescription(); | 
| 45 | 46 | 
| 46         // Word and letter spacing can change the width of a word, as can tabs | 47         // Word and letter spacing can change the width of a word, as can tabs | 
| 47         // as we segment solely based on on space characters. | 48         // as we segment solely based on on space characters. | 
| 48         // If expansion is used (for justified text) the spacing between words | 49         // If expansion is used (for justified text) the spacing between words | 
| 49         // change and thus we need to shape the entire run. | 50         // change and thus we need to shape the entire run. | 
| 50         m_wordResultCachable = !fontDescription.wordSpacing() | 51         m_wordResultCachable = !fontDescription.wordSpacing() | 
| 51             && !fontDescription.letterSpacing() && !run.allowTabs() | 52             && !fontDescription.letterSpacing() && !run.allowTabs() | 
| 52             && m_textRun.expansion() == 0.0f; | 53             && m_textRun.expansion() == 0.0f; | 
| 53 | 54 | 
| 54         // Shaping word by word is faster as each word is cached. If we cannot | 55         // Shaping word by word is faster as each word is cached. If we cannot | 
| 55         // use the cache or if the font doesn't support word by word shaping | 56         // use the cache or if the font doesn't support word by word shaping | 
| 56         // fall back on shaping the entire run. | 57         // fall back on shaping the entire run. | 
| 57         m_shapeByWord = m_wordResultCachable && m_font->canShapeWordByWord(); | 58         m_shapeByWord = m_wordResultCachable && m_font->canShapeWordByWord(); | 
| 58     } | 59     } | 
| 59 | 60 | 
| 60     bool next(RefPtr<ShapeResult>* wordResult) | 61     bool next(RefPtr<ShapeResult>* wordResult) | 
| 61     { | 62     { | 
| 62         if (!m_shapeByWord) { | 63         if (!m_shapeByWord) { | 
| 63             if (m_startIndex) | 64             if (m_startIndex) | 
| 64                 return false; | 65                 return false; | 
| 65             *wordResult = shapeWord(m_textRun, m_font); | 66             *wordResult = shapeWord(m_textRun, m_font, m_fallbackFonts); | 
| 66             m_startIndex = 1; | 67             m_startIndex = 1; | 
| 67             return *wordResult; | 68             return *wordResult; | 
| 68         } | 69         } | 
| 69 | 70 | 
| 70         unsigned length = m_textRun.length(); | 71         unsigned length = m_textRun.length(); | 
| 71         if (m_startIndex < length) { | 72         if (m_startIndex < length) { | 
| 72             if (m_textRun[m_startIndex] == spaceCharacter) { | 73             if (m_textRun[m_startIndex] == spaceCharacter) { | 
| 73                 TextRun wordRun = m_textRun.subRun(m_startIndex, 1); | 74                 TextRun wordRun = m_textRun.subRun(m_startIndex, 1); | 
| 74                 *wordResult = shapeWord(wordRun, m_font); | 75                 *wordResult = shapeWord(wordRun, m_font, m_fallbackFonts); | 
| 75                 m_startIndex++; | 76                 m_startIndex++; | 
| 76                 return true; | 77                 return true; | 
| 77             } | 78             } | 
| 78 | 79 | 
| 79             for (unsigned i = m_startIndex; ; i++) { | 80             for (unsigned i = m_startIndex; ; i++) { | 
| 80                 if (i == length || m_textRun[i] == spaceCharacter) { | 81                 if (i == length || m_textRun[i] == spaceCharacter) { | 
| 81                     TextRun wordRun = m_textRun.subRun(m_startIndex, | 82                     TextRun wordRun = m_textRun.subRun(m_startIndex, | 
| 82                         i - m_startIndex); | 83                         i - m_startIndex); | 
| 83                     *wordResult = shapeWord(wordRun, m_font); | 84                     *wordResult = shapeWord(wordRun, m_font, m_fallbackFonts); | 
| 84                     m_startIndex = i; | 85                     m_startIndex = i; | 
| 85                     return true; | 86                     return true; | 
| 86                 } | 87                 } | 
| 87             } | 88             } | 
| 88         } | 89         } | 
| 89         return false; | 90         return false; | 
| 90     } | 91     } | 
| 91 | 92 | 
| 92 private: | 93 private: | 
| 93     PassRefPtr<ShapeResult> shapeWord(const TextRun& wordRun, const Font* font) | 94     void setFallbackFonts(const ShapeResult* wordResult, | 
|  | 95         HashSet<const SimpleFontData*>* fallbackFonts) | 
|  | 96     { | 
|  | 97         if (fallbackFonts) { | 
|  | 98             const HashSet<const SimpleFontData*>* fontsForWord = | 
|  | 99                 wordResult->fallbackFonts(); | 
|  | 100             HashSet<const SimpleFontData*>::const_iterator it; | 
|  | 101             for (it = fontsForWord->begin(); it != fontsForWord->end(); ++it) | 
|  | 102                 fallbackFonts->add(*it); | 
|  | 103         } | 
|  | 104     } | 
|  | 105 | 
|  | 106     PassRefPtr<ShapeResult> shapeWord(const TextRun& wordRun, | 
|  | 107         const Font* font, HashSet<const SimpleFontData*>* fallbackFonts) | 
| 94     { | 108     { | 
| 95         ShapeCacheEntry* cacheEntry = m_wordResultCachable | 109         ShapeCacheEntry* cacheEntry = m_wordResultCachable | 
| 96             ? m_shapeCache->add(wordRun, ShapeCacheEntry()) | 110             ? m_shapeCache->add(wordRun, ShapeCacheEntry()) | 
| 97             : nullptr; | 111             : nullptr; | 
| 98         if (cacheEntry && cacheEntry->m_shapeResult) | 112         if (cacheEntry && cacheEntry->m_shapeResult) { | 
|  | 113             setFallbackFonts(cacheEntry->m_shapeResult.get(), fallbackFonts); | 
| 99             return cacheEntry->m_shapeResult; | 114             return cacheEntry->m_shapeResult; | 
|  | 115         } | 
| 100 | 116 | 
| 101         HarfBuzzShaper shaper(font, wordRun); | 117         HashSet<const SimpleFontData*> fallbackFontsForWord; | 
|  | 118         HarfBuzzShaper shaper(font, wordRun, &fallbackFontsForWord); | 
| 102         RefPtr<ShapeResult> shapeResult = shaper.shapeResult(); | 119         RefPtr<ShapeResult> shapeResult = shaper.shapeResult(); | 
| 103         if (!shapeResult) | 120         if (!shapeResult) | 
| 104             return nullptr; | 121             return nullptr; | 
| 105 | 122 | 
| 106         if (cacheEntry) | 123         if (cacheEntry) | 
| 107             cacheEntry->m_shapeResult = shapeResult; | 124             cacheEntry->m_shapeResult = shapeResult; | 
| 108 | 125 | 
|  | 126         setFallbackFonts(shapeResult.get(), fallbackFonts); | 
| 109         return shapeResult.release(); | 127         return shapeResult.release(); | 
| 110     } | 128     } | 
| 111 | 129 | 
| 112     ShapeCache* m_shapeCache; | 130     ShapeCache* m_shapeCache; | 
| 113     const TextRun& m_textRun; | 131     const TextRun& m_textRun; | 
| 114     const Font* m_font; | 132     const Font* m_font; | 
|  | 133     HashSet<const SimpleFontData*>* m_fallbackFonts; | 
| 115     unsigned m_startIndex : 30; | 134     unsigned m_startIndex : 30; | 
| 116     unsigned m_wordResultCachable : 1; | 135     unsigned m_wordResultCachable : 1; | 
| 117     unsigned m_shapeByWord : 1; | 136     unsigned m_shapeByWord : 1; | 
| 118 }; | 137 }; | 
| 119 | 138 | 
| 120 } // namespace blink | 139 } // namespace blink | 
| 121 | 140 | 
| 122 #endif // CachingWordShapeIterator_h | 141 #endif // CachingWordShapeIterator_h | 
| OLD | NEW | 
|---|