Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(375)

Side by Side Diff: Source/platform/fonts/shaping/CachingWordShapeIterator.h

Issue 1242213002: Add tab characters support in complex path (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebase Created 5 years, 4 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
OLDNEW
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 20 matching lines...) Expand all
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)
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_widthSoFar(0), 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) {
64 if (UNLIKELY(m_textRun.allowTabs()))
65 return nextForAllowTabs(wordResult);
63 if (m_startIndex) 66 if (m_startIndex)
64 return false; 67 return false;
65 *wordResult = shapeWord(m_textRun, m_font); 68 *wordResult = shapeWord(m_textRun, m_font);
66 m_startIndex = 1; 69 m_startIndex = 1;
67 return *wordResult; 70 return *wordResult;
68 } 71 }
69 72
70 unsigned length = m_textRun.length(); 73 unsigned length = m_textRun.length();
71 if (m_startIndex < length) { 74 if (m_startIndex < length) {
72 if (m_textRun[m_startIndex] == spaceCharacter) { 75 if (m_textRun[m_startIndex] == spaceCharacter) {
73 TextRun wordRun = m_textRun.subRun(m_startIndex, 1); 76 TextRun wordRun = m_textRun.subRun(m_startIndex, 1);
74 *wordResult = shapeWord(wordRun, m_font); 77 *wordResult = shapeWord(wordRun, m_font);
75 m_startIndex++; 78 m_startIndex++;
76 return true; 79 return true;
77 } 80 }
78 81
79 for (unsigned i = m_startIndex; ; i++) { 82 *wordResult = shapeWordUntilCharacter(spaceCharacter);
80 if (i == length || m_textRun[i] == spaceCharacter) { 83 return true;
eae 2015/08/10 17:24:07 Shouldn't this be "return *wordResult != nullptr;"
kojii 2015/08/11 07:22:21 Done. The fix was moved to nextUntilCharacterOrTab
81 TextRun wordRun = m_textRun.subRun(m_startIndex,
82 i - m_startIndex);
83 *wordResult = shapeWord(wordRun, m_font);
84 m_startIndex = i;
85 return true;
86 }
87 }
88 } 84 }
85
89 return false; 86 return false;
90 } 87 }
91 88
92 private: 89 private:
93 PassRefPtr<ShapeResult> shapeWord(const TextRun& wordRun, const Font* font) 90 PassRefPtr<ShapeResult> shapeWord(const TextRun& wordRun, const Font* font)
94 { 91 {
95 ShapeCacheEntry* cacheEntry = m_wordResultCachable 92 ShapeCacheEntry* cacheEntry = m_wordResultCachable
96 ? m_shapeCache->add(wordRun, ShapeCacheEntry()) 93 ? m_shapeCache->add(wordRun, ShapeCacheEntry())
97 : nullptr; 94 : nullptr;
98 if (cacheEntry && cacheEntry->m_shapeResult) 95 if (cacheEntry && cacheEntry->m_shapeResult)
99 return cacheEntry->m_shapeResult; 96 return cacheEntry->m_shapeResult;
100 97
101 HarfBuzzShaper shaper(font, wordRun); 98 HarfBuzzShaper shaper(font, wordRun);
102 RefPtr<ShapeResult> shapeResult = shaper.shapeResult(); 99 RefPtr<ShapeResult> shapeResult = shaper.shapeResult();
103 if (!shapeResult) 100 if (!shapeResult)
104 return nullptr; 101 return nullptr;
105 102
106 if (cacheEntry) 103 if (cacheEntry)
107 cacheEntry->m_shapeResult = shapeResult; 104 cacheEntry->m_shapeResult = shapeResult;
108 105
109 return shapeResult.release(); 106 return shapeResult.release();
110 } 107 }
111 108
109 PassRefPtr<ShapeResult> shapeWordUntilCharacter(UChar delimiter)
110 {
111 unsigned length = m_textRun.length();
112 ASSERT(m_startIndex < length);
113 for (unsigned i = m_startIndex + 1;; i++) {
114 if (i == length || m_textRun[i] == delimiter) {
115 TextRun wordRun = m_textRun.subRun(m_startIndex,
116 i - m_startIndex);
117 m_startIndex = i;
118 return shapeWord(wordRun, m_font);
119 }
120 }
eae 2015/08/10 17:24:07 Missing "return nullptr"?
kojii 2015/08/11 07:22:20 The loop exits only with "return", so it's not nec
121 }
122
123 bool nextForAllowTabs(RefPtr<ShapeResult>* wordResult)
124 {
125 unsigned length = m_textRun.length();
126 if (m_startIndex >= length)
127 return false;
128
129 if (UNLIKELY(m_textRun[m_startIndex] == tabulationCharacter)) {
130 for (unsigned i = m_startIndex + 1;; i++) {
131 if (i == length || m_textRun[i] != tabulationCharacter) {
132 *wordResult = ShapeResult::createForTabulationCharacters(
133 m_font, m_textRun, m_widthSoFar, i - m_startIndex);
134 m_startIndex = i;
135 break;
136 }
137 }
138 } else {
139 *wordResult = shapeWordUntilCharacter(tabulationCharacter);
eae 2015/08/10 17:24:07 Shouldn't this still segment on space? I.e. shape
kojii 2015/08/11 07:22:21 Good point, we need to do that if we want to cache
140 }
141 m_widthSoFar += (*wordResult)->width();
142 return true;
143 }
144
112 ShapeCache* m_shapeCache; 145 ShapeCache* m_shapeCache;
113 const TextRun& m_textRun; 146 const TextRun& m_textRun;
114 const Font* m_font; 147 const Font* m_font;
148 float m_widthSoFar; // Used only when allowTabs()
115 unsigned m_startIndex : 30; 149 unsigned m_startIndex : 30;
116 unsigned m_wordResultCachable : 1; 150 unsigned m_wordResultCachable : 1;
117 unsigned m_shapeByWord : 1; 151 unsigned m_shapeByWord : 1;
118 }; 152 };
119 153
120 } // namespace blink 154 } // namespace blink
121 155
122 #endif // CachingWordShapeIterator_h 156 #endif // CachingWordShapeIterator_h
OLDNEW
« no previous file with comments | « LayoutTests/fast/css/tab-size-complex-path-expected.html ('k') | Source/platform/fonts/shaping/HarfBuzzShaper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698