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

Side by Side Diff: third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp

Issue 2714413003: Remove GlyphBuffer (Closed)
Patch Set: format Created 3 years, 9 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 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform/fonts/shaping/ShapeResultBuffer.h" 5 #include "platform/fonts/shaping/ShapeResultBuffer.h"
6 6
7 #include "platform/fonts/CharacterRange.h" 7 #include "platform/fonts/CharacterRange.h"
8 #include "platform/fonts/GlyphBuffer.h"
9 #include "platform/fonts/SimpleFontData.h" 8 #include "platform/fonts/SimpleFontData.h"
9 #include "platform/fonts/shaping/ShapeResultBloberizer.h"
10 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h" 10 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h"
11 #include "platform/geometry/FloatPoint.h" 11 #include "platform/geometry/FloatPoint.h"
12 #include "platform/text/Character.h" 12 #include "platform/text/Character.h"
13 #include "platform/text/TextBreakIterator.h" 13 #include "platform/text/TextBreakIterator.h"
14 #include "platform/text/TextDirection.h" 14 #include "platform/text/TextDirection.h"
15 15
16 namespace blink { 16 namespace blink {
17 17
18 namespace { 18 namespace {
19 19
20 inline bool isSkipInkException(const GlyphBuffer& glyphBuffer, 20 inline bool isSkipInkException(const ShapeResultBloberizer& bloberizer,
21 const TextRun& run, 21 const TextRun& run,
22 unsigned characterIndex) { 22 unsigned characterIndex) {
23 // We want to skip descenders in general, but it is undesirable renderings for 23 // We want to skip descenders in general, but it is undesirable renderings for
24 // CJK characters. 24 // CJK characters.
25 return glyphBuffer.type() == GlyphBuffer::Type::TextIntercepts && 25 return bloberizer.type() == ShapeResultBloberizer::Type::TextIntercepts &&
26 !run.is8Bit() && 26 !run.is8Bit() &&
27 Character::isCJKIdeographOrSymbol(run.codepointAt(characterIndex)); 27 Character::isCJKIdeographOrSymbol(run.codepointAt(characterIndex));
28 } 28 }
29 29
30 inline void addGlyphToBuffer(GlyphBuffer* glyphBuffer, 30 inline void addGlyphToBloberizer(ShapeResultBloberizer& bloberizer,
31 float advance, 31 float advance,
32 hb_direction_t direction, 32 hb_direction_t direction,
33 const SimpleFontData* fontData, 33 const SimpleFontData* fontData,
34 const HarfBuzzRunGlyphData& glyphData, 34 const HarfBuzzRunGlyphData& glyphData,
35 const TextRun& run, 35 const TextRun& run,
36 unsigned characterIndex) { 36 unsigned characterIndex) {
37 FloatPoint startOffset = HB_DIRECTION_IS_HORIZONTAL(direction) 37 FloatPoint startOffset = HB_DIRECTION_IS_HORIZONTAL(direction)
38 ? FloatPoint(advance, 0) 38 ? FloatPoint(advance, 0)
39 : FloatPoint(0, advance); 39 : FloatPoint(0, advance);
40 if (!isSkipInkException(*glyphBuffer, run, characterIndex)) { 40 if (!isSkipInkException(bloberizer, run, characterIndex))
41 glyphBuffer->add(glyphData.glyph, fontData, startOffset + glyphData.offset); 41 bloberizer.add(glyphData.glyph, fontData, startOffset + glyphData.offset);
42 }
43 } 42 }
44 43
45 inline void addEmphasisMark(GlyphBuffer* buffer, 44 inline void addEmphasisMark(ShapeResultBloberizer& bloberizer,
46 const GlyphData* emphasisData, 45 const GlyphData& emphasisData,
47 FloatPoint glyphCenter, 46 FloatPoint glyphCenter,
48 float midGlyphOffset) { 47 float midGlyphOffset) {
49 ASSERT(buffer); 48 const SimpleFontData* emphasisFontData = emphasisData.fontData;
50 ASSERT(emphasisData); 49 DCHECK(emphasisFontData);
51
52 const SimpleFontData* emphasisFontData = emphasisData->fontData;
53 ASSERT(emphasisFontData);
54 50
55 bool isVertical = emphasisFontData->platformData().isVerticalAnyUpright() && 51 bool isVertical = emphasisFontData->platformData().isVerticalAnyUpright() &&
56 emphasisFontData->verticalData(); 52 emphasisFontData->verticalData();
57 53
58 if (!isVertical) { 54 if (!isVertical) {
59 buffer->add(emphasisData->glyph, emphasisFontData, 55 bloberizer.add(emphasisData.glyph, emphasisFontData,
60 midGlyphOffset - glyphCenter.x()); 56 midGlyphOffset - glyphCenter.x());
61 } else { 57 } else {
62 buffer->add(emphasisData->glyph, emphasisFontData, 58 bloberizer.add(
63 FloatPoint(-glyphCenter.x(), midGlyphOffset - glyphCenter.y())); 59 emphasisData.glyph, emphasisFontData,
60 FloatPoint(-glyphCenter.x(), midGlyphOffset - glyphCenter.y()));
64 } 61 }
65 } 62 }
66 63
67 inline unsigned countGraphemesInCluster(const UChar* str, 64 inline unsigned countGraphemesInCluster(const UChar* str,
68 unsigned strLength, 65 unsigned strLength,
69 uint16_t startIndex, 66 uint16_t startIndex,
70 uint16_t endIndex) { 67 uint16_t endIndex) {
71 if (startIndex > endIndex) { 68 if (startIndex > endIndex) {
72 uint16_t tempIndex = startIndex; 69 uint16_t tempIndex = startIndex;
73 startIndex = endIndex; 70 startIndex = endIndex;
74 endIndex = tempIndex; 71 endIndex = tempIndex;
75 } 72 }
76 uint16_t length = endIndex - startIndex; 73 uint16_t length = endIndex - startIndex;
77 ASSERT(static_cast<unsigned>(startIndex + length) <= strLength); 74 ASSERT(static_cast<unsigned>(startIndex + length) <= strLength);
78 TextBreakIterator* cursorPosIterator = 75 TextBreakIterator* cursorPosIterator =
79 cursorMovementIterator(&str[startIndex], length); 76 cursorMovementIterator(&str[startIndex], length);
80 77
81 int cursorPos = cursorPosIterator->current(); 78 int cursorPos = cursorPosIterator->current();
82 int numGraphemes = -1; 79 int numGraphemes = -1;
83 while (0 <= cursorPos) { 80 while (0 <= cursorPos) {
84 cursorPos = cursorPosIterator->next(); 81 cursorPos = cursorPosIterator->next();
85 numGraphemes++; 82 numGraphemes++;
86 } 83 }
87 return std::max(0, numGraphemes); 84 return std::max(0, numGraphemes);
88 } 85 }
89 86
90 } // anonymous namespace 87 } // anonymous namespace
91 88
92 float ShapeResultBuffer::fillGlyphBufferForResult(GlyphBuffer* glyphBuffer, 89 float ShapeResultBuffer::fillGlyphsForResult(ShapeResultBloberizer& bloberizer,
93 const ShapeResult& result, 90 const ShapeResult& result,
94 const TextRun& textRun, 91 const TextRunPaintInfo& runInfo,
95 float initialAdvance, 92 float initialAdvance,
96 unsigned from, 93 unsigned runOffset) {
97 unsigned to,
98 unsigned runOffset) {
99 auto totalAdvance = initialAdvance; 94 auto totalAdvance = initialAdvance;
100 95
101 for (const auto& run : result.m_runs) { 96 for (const auto& run : result.m_runs) {
102 totalAdvance = run->forEachGlyphInRange( 97 totalAdvance = run->forEachGlyphInRange(
103 totalAdvance, from, to, runOffset, 98 totalAdvance, runInfo.from, runInfo.to, runOffset,
104 [&](const HarfBuzzRunGlyphData& glyphData, float totalAdvance, 99 [&](const HarfBuzzRunGlyphData& glyphData, float totalAdvance,
105 uint16_t characterIndex) -> bool { 100 uint16_t characterIndex) -> bool {
106 101
107 addGlyphToBuffer(glyphBuffer, totalAdvance, run->m_direction, 102 addGlyphToBloberizer(bloberizer, totalAdvance, run->m_direction,
108 run->m_fontData.get(), glyphData, textRun, 103 run->m_fontData.get(), glyphData, runInfo.run,
109 characterIndex); 104 characterIndex);
110 return true; 105 return true;
111 }); 106 });
112 } 107 }
113 108
114 return totalAdvance; 109 return totalAdvance;
115 } 110 }
116 111
117 float ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun( 112 float ShapeResultBuffer::fillTextEmphasisGlyphsForRun(
118 GlyphBuffer* glyphBuffer, 113 ShapeResultBloberizer& bloberizer,
119 const ShapeResult::RunInfo* run, 114 const ShapeResult::RunInfo* run,
120 const TextRun& textRun, 115 const TextRunPaintInfo& runInfo,
121 const GlyphData* emphasisData, 116 const GlyphData& emphasisData,
122 float initialAdvance, 117 float initialAdvance,
123 unsigned from,
124 unsigned to,
125 unsigned runOffset) { 118 unsigned runOffset) {
126 if (!run) 119 if (!run)
127 return 0; 120 return 0;
128 121
129 unsigned graphemesInCluster = 1; 122 unsigned graphemesInCluster = 1;
130 float clusterAdvance = 0; 123 float clusterAdvance = 0;
131 124
132 FloatPoint glyphCenter = 125 FloatPoint glyphCenter =
133 emphasisData->fontData->boundsForGlyph(emphasisData->glyph).center(); 126 emphasisData.fontData->boundsForGlyph(emphasisData.glyph).center();
127
128 const auto& textRun = runInfo.run;
129 const auto from = runInfo.from;
130 const auto to = runInfo.to;
134 131
135 TextDirection direction = textRun.direction(); 132 TextDirection direction = textRun.direction();
136 133
137 // A "cluster" in this context means a cluster as it is used by HarfBuzz: 134 // A "cluster" in this context means a cluster as it is used by HarfBuzz:
138 // The minimal group of characters and corresponding glyphs, that cannot be 135 // The minimal group of characters and corresponding glyphs, that cannot be
139 // broken down further from a text shaping point of view. A cluster can 136 // broken down further from a text shaping point of view. A cluster can
140 // contain multiple glyphs and grapheme clusters, with mutually overlapping 137 // contain multiple glyphs and grapheme clusters, with mutually overlapping
141 // boundaries. Below we count grapheme clusters per HarfBuzz clusters, then 138 // boundaries. Below we count grapheme clusters per HarfBuzz clusters, then
142 // linearly split the sum of corresponding glyph advances by the number of 139 // linearly split the sum of corresponding glyph advances by the number of
143 // grapheme clusters in order to find positions for emphasis mark drawing. 140 // grapheme clusters in order to find positions for emphasis mark drawing.
(...skipping 18 matching lines...) Expand all
162 advanceSoFar += glyphData.advance; 159 advanceSoFar += glyphData.advance;
163 direction == TextDirection::kRtl ? --clusterStart : ++clusterStart; 160 direction == TextDirection::kRtl ? --clusterStart : ++clusterStart;
164 continue; 161 continue;
165 } 162 }
166 163
167 clusterAdvance += glyphData.advance; 164 clusterAdvance += glyphData.advance;
168 165
169 if (textRun.is8Bit()) { 166 if (textRun.is8Bit()) {
170 float glyphAdvanceX = glyphData.advance; 167 float glyphAdvanceX = glyphData.advance;
171 if (Character::canReceiveTextEmphasis(textRun[currentCharacterIndex])) { 168 if (Character::canReceiveTextEmphasis(textRun[currentCharacterIndex])) {
172 addEmphasisMark(glyphBuffer, emphasisData, glyphCenter, 169 addEmphasisMark(bloberizer, emphasisData, glyphCenter,
173 advanceSoFar + glyphAdvanceX / 2); 170 advanceSoFar + glyphAdvanceX / 2);
174 } 171 }
175 advanceSoFar += glyphAdvanceX; 172 advanceSoFar += glyphAdvanceX;
176 } else if (isClusterEnd) { 173 } else if (isClusterEnd) {
177 uint16_t clusterEnd; 174 uint16_t clusterEnd;
178 if (direction == TextDirection::kRtl) 175 if (direction == TextDirection::kRtl)
179 clusterEnd = currentCharacterIndex; 176 clusterEnd = currentCharacterIndex;
180 else 177 else
181 clusterEnd = static_cast<uint16_t>( 178 clusterEnd = static_cast<uint16_t>(
182 isRunEnd ? run->m_startIndex + run->m_numCharacters + runOffset 179 isRunEnd ? run->m_startIndex + run->m_numCharacters + runOffset
183 : run->glyphToCharacterIndex(i + 1) + runOffset); 180 : run->glyphToCharacterIndex(i + 1) + runOffset);
184 181
185 graphemesInCluster = countGraphemesInCluster(textRun.characters16(), 182 graphemesInCluster = countGraphemesInCluster(textRun.characters16(),
186 textRun.charactersLength(), 183 textRun.charactersLength(),
187 clusterStart, clusterEnd); 184 clusterStart, clusterEnd);
188 if (!graphemesInCluster || !clusterAdvance) 185 if (!graphemesInCluster || !clusterAdvance)
189 continue; 186 continue;
190 187
191 float glyphAdvanceX = clusterAdvance / graphemesInCluster; 188 float glyphAdvanceX = clusterAdvance / graphemesInCluster;
192 for (unsigned j = 0; j < graphemesInCluster; ++j) { 189 for (unsigned j = 0; j < graphemesInCluster; ++j) {
193 // Do not put emphasis marks on space, separator, and control 190 // Do not put emphasis marks on space, separator, and control
194 // characters. 191 // characters.
195 if (Character::canReceiveTextEmphasis(textRun[currentCharacterIndex])) 192 if (Character::canReceiveTextEmphasis(textRun[currentCharacterIndex]))
196 addEmphasisMark(glyphBuffer, emphasisData, glyphCenter, 193 addEmphasisMark(bloberizer, emphasisData, glyphCenter,
197 advanceSoFar + glyphAdvanceX / 2); 194 advanceSoFar + glyphAdvanceX / 2);
198 advanceSoFar += glyphAdvanceX; 195 advanceSoFar += glyphAdvanceX;
199 } 196 }
200 clusterStart = clusterEnd; 197 clusterStart = clusterEnd;
201 clusterAdvance = 0; 198 clusterAdvance = 0;
202 } 199 }
203 } 200 }
204 return advanceSoFar - initialAdvance; 201 return advanceSoFar - initialAdvance;
205 } 202 }
206 203
207 float ShapeResultBuffer::fillFastHorizontalGlyphBuffer( 204 float ShapeResultBuffer::fillFastHorizontalGlyphs(
208 GlyphBuffer* glyphBuffer, 205 const TextRun& textRun,
209 const TextRun& textRun) const { 206 ShapeResultBloberizer& bloberizer) const {
210 DCHECK(!hasVerticalOffsets()); 207 DCHECK(!hasVerticalOffsets());
211 DCHECK_NE(glyphBuffer->type(), GlyphBuffer::Type::TextIntercepts); 208 DCHECK_NE(bloberizer.type(), ShapeResultBloberizer::Type::TextIntercepts);
212 209
213 float advance = 0; 210 float advance = 0;
214 211
215 for (unsigned i = 0; i < m_results.size(); ++i) { 212 for (unsigned i = 0; i < m_results.size(); ++i) {
216 const auto& wordResult = isLeftToRightDirection(textRun.direction()) 213 const auto& wordResult = isLeftToRightDirection(textRun.direction())
217 ? m_results[i] 214 ? m_results[i]
218 : m_results[m_results.size() - 1 - i]; 215 : m_results[m_results.size() - 1 - i];
219 DCHECK(!wordResult->hasVerticalOffsets()); 216 DCHECK(!wordResult->hasVerticalOffsets());
220 217
221 for (const auto& run : wordResult->m_runs) { 218 for (const auto& run : wordResult->m_runs) {
222 DCHECK(run); 219 DCHECK(run);
223 DCHECK(HB_DIRECTION_IS_HORIZONTAL(run->m_direction)); 220 DCHECK(HB_DIRECTION_IS_HORIZONTAL(run->m_direction));
224 221
225 advance = run->forEachGlyph( 222 advance = run->forEachGlyph(
226 advance, 223 advance,
227 [&](const HarfBuzzRunGlyphData& glyphData, 224 [&](const HarfBuzzRunGlyphData& glyphData,
228 float totalAdvance) -> bool { 225 float totalAdvance) -> bool {
229 DCHECK(!glyphData.offset.height()); 226 DCHECK(!glyphData.offset.height());
230 227 bloberizer.add(glyphData.glyph, run->m_fontData.get(),
231 glyphBuffer->add(glyphData.glyph, run->m_fontData.get(), 228 totalAdvance + glyphData.offset.width());
232 totalAdvance + glyphData.offset.width());
233 return true; 229 return true;
234 }); 230 });
235 } 231 }
236 } 232 }
237 233
238 ASSERT(!glyphBuffer->hasVerticalOffsets());
239
240 return advance; 234 return advance;
241 } 235 }
242 236
243 float ShapeResultBuffer::fillGlyphBuffer(GlyphBuffer* glyphBuffer, 237 float ShapeResultBuffer::fillGlyphs(const TextRunPaintInfo& runInfo,
244 const TextRun& textRun, 238 ShapeResultBloberizer& bloberizer) const {
245 unsigned from,
246 unsigned to) const {
247 // Fast path: full run with no vertical offsets, no text intercepts. 239 // Fast path: full run with no vertical offsets, no text intercepts.
248 if (!from && to == textRun.length() && !hasVerticalOffsets() && 240 if (!runInfo.from && runInfo.to == runInfo.run.length() &&
249 glyphBuffer->type() != GlyphBuffer::Type::TextIntercepts) 241 !hasVerticalOffsets() &&
250 return fillFastHorizontalGlyphBuffer(glyphBuffer, textRun); 242 bloberizer.type() != ShapeResultBloberizer::Type::TextIntercepts) {
243 return fillFastHorizontalGlyphs(runInfo.run, bloberizer);
244 }
251 245
252 float advance = 0; 246 float advance = 0;
253 247
254 if (textRun.rtl()) { 248 if (runInfo.run.rtl()) {
255 unsigned wordOffset = textRun.length(); 249 unsigned wordOffset = runInfo.run.length();
256 for (unsigned j = 0; j < m_results.size(); j++) { 250 for (unsigned j = 0; j < m_results.size(); j++) {
257 unsigned resolvedIndex = m_results.size() - 1 - j; 251 unsigned resolvedIndex = m_results.size() - 1 - j;
258 const RefPtr<const ShapeResult>& wordResult = m_results[resolvedIndex]; 252 const RefPtr<const ShapeResult>& wordResult = m_results[resolvedIndex];
259 wordOffset -= wordResult->numCharacters(); 253 wordOffset -= wordResult->numCharacters();
260 advance = fillGlyphBufferForResult(glyphBuffer, *wordResult, textRun, 254 advance = fillGlyphsForResult(bloberizer, *wordResult, runInfo, advance,
261 advance, from, to, wordOffset); 255 wordOffset);
262 } 256 }
263 } else { 257 } else {
264 unsigned wordOffset = 0; 258 unsigned wordOffset = 0;
265 for (const auto& wordResult : m_results) { 259 for (const auto& wordResult : m_results) {
266 advance = fillGlyphBufferForResult(glyphBuffer, *wordResult, textRun, 260 advance = fillGlyphsForResult(bloberizer, *wordResult, runInfo, advance,
267 advance, from, to, wordOffset); 261 wordOffset);
268 wordOffset += wordResult->numCharacters(); 262 wordOffset += wordResult->numCharacters();
269 } 263 }
270 } 264 }
271 265
272 return advance; 266 return advance;
273 } 267 }
274 268
275 float ShapeResultBuffer::fillGlyphBufferForTextEmphasis( 269 void ShapeResultBuffer::fillTextEmphasisGlyphs(
276 GlyphBuffer* glyphBuffer, 270 const TextRunPaintInfo& runInfo,
277 const TextRun& textRun, 271 const GlyphData& emphasisData,
278 const GlyphData* emphasisData, 272 ShapeResultBloberizer& bloberizer) const {
279 unsigned from,
280 unsigned to) const {
281 float advance = 0; 273 float advance = 0;
282 unsigned wordOffset = textRun.rtl() ? textRun.length() : 0; 274 unsigned wordOffset = runInfo.run.rtl() ? runInfo.run.length() : 0;
283 275
284 for (unsigned j = 0; j < m_results.size(); j++) { 276 for (unsigned j = 0; j < m_results.size(); j++) {
285 unsigned resolvedIndex = textRun.rtl() ? m_results.size() - 1 - j : j; 277 unsigned resolvedIndex = runInfo.run.rtl() ? m_results.size() - 1 - j : j;
286 const RefPtr<const ShapeResult>& wordResult = m_results[resolvedIndex]; 278 const RefPtr<const ShapeResult>& wordResult = m_results[resolvedIndex];
287 for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { 279 for (unsigned i = 0; i < wordResult->m_runs.size(); i++) {
288 unsigned resolvedOffset = 280 unsigned resolvedOffset =
289 wordOffset - (textRun.rtl() ? wordResult->numCharacters() : 0); 281 wordOffset - (runInfo.run.rtl() ? wordResult->numCharacters() : 0);
290 advance += fillGlyphBufferForTextEmphasisRun( 282 advance += fillTextEmphasisGlyphsForRun(
291 glyphBuffer, wordResult->m_runs[i].get(), textRun, emphasisData, 283 bloberizer, wordResult->m_runs[i].get(), runInfo, emphasisData,
292 advance, from, to, resolvedOffset); 284 advance, resolvedOffset);
293 } 285 }
294 wordOffset += wordResult->numCharacters() * (textRun.rtl() ? -1 : 1); 286 wordOffset += wordResult->numCharacters() * (runInfo.run.rtl() ? -1 : 1);
295 } 287 }
296
297 return advance;
298 } 288 }
299 289
300 // TODO(eae): This is a bit of a hack to allow reuse of the implementation 290 // TODO(eae): This is a bit of a hack to allow reuse of the implementation
301 // for both ShapeResultBuffer and single ShapeResult use cases. Ideally the 291 // for both ShapeResultBuffer and single ShapeResult use cases. Ideally the
302 // logic should move into ShapeResult itself and then the ShapeResultBuffer 292 // logic should move into ShapeResult itself and then the ShapeResultBuffer
303 // implementation may wrap that. 293 // implementation may wrap that.
304 CharacterRange ShapeResultBuffer::getCharacterRange( 294 CharacterRange ShapeResultBuffer::getCharacterRange(
305 RefPtr<const ShapeResult> result, 295 RefPtr<const ShapeResult> result,
306 TextDirection direction, 296 TextDirection direction,
307 float totalWidth, 297 float totalWidth,
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 return GlyphData( 498 return GlyphData(
509 run->m_glyphData[0].glyph, 499 run->m_glyphData[0].glyph,
510 run->m_fontData->emphasisMarkFontData(fontDescription).get()); 500 run->m_fontData->emphasisMarkFontData(fontDescription).get());
511 } 501 }
512 } 502 }
513 503
514 return GlyphData(); 504 return GlyphData();
515 } 505 }
516 506
517 } // namespace blink 507 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698