OLD | NEW |
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" | 8 #include "platform/fonts/GlyphBuffer.h" |
9 #include "platform/fonts/SimpleFontData.h" | 9 #include "platform/fonts/SimpleFontData.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 void addIsSkipInkException(GlyphBuffer* glyphBuffer, |
| 21 const TextRun& run, |
| 22 unsigned characterIndex) { |
| 23 // We want to skip descenders in general, but it is undesirable renderings for |
| 24 // CJK characters. |
| 25 DCHECK(!run.is8Bit()) << "8Bit() is always false, better to avoid to call"; |
| 26 UChar32 baseCharacter = run.codepointAt(characterIndex); |
| 27 glyphBuffer->addIsSkipInkException( |
| 28 Character::isCJKIdeographOrSymbol(baseCharacter)); |
| 29 } |
| 30 |
20 inline void addGlyphToBuffer(GlyphBuffer* glyphBuffer, | 31 inline void addGlyphToBuffer(GlyphBuffer* glyphBuffer, |
21 float advance, | 32 float advance, |
22 hb_direction_t direction, | 33 hb_direction_t direction, |
23 const SimpleFontData* fontData, | 34 const SimpleFontData* fontData, |
24 const HarfBuzzRunGlyphData& glyphData) { | 35 const HarfBuzzRunGlyphData& glyphData, |
| 36 const TextRun& run, |
| 37 unsigned characterIndex) { |
25 FloatPoint startOffset = HB_DIRECTION_IS_HORIZONTAL(direction) | 38 FloatPoint startOffset = HB_DIRECTION_IS_HORIZONTAL(direction) |
26 ? FloatPoint(advance, 0) | 39 ? FloatPoint(advance, 0) |
27 : FloatPoint(0, advance); | 40 : FloatPoint(0, advance); |
28 glyphBuffer->add(glyphData.glyph, fontData, startOffset + glyphData.offset); | 41 glyphBuffer->add(glyphData.glyph, fontData, startOffset + glyphData.offset); |
| 42 if (glyphBuffer->hasSkipInkExceptions()) |
| 43 addIsSkipInkException(glyphBuffer, run, characterIndex); |
29 } | 44 } |
30 | 45 |
31 inline void addEmphasisMark(GlyphBuffer* buffer, | 46 inline void addEmphasisMark(GlyphBuffer* buffer, |
32 const GlyphData* emphasisData, | 47 const GlyphData* emphasisData, |
33 FloatPoint glyphCenter, | 48 FloatPoint glyphCenter, |
34 float midGlyphOffset) { | 49 float midGlyphOffset) { |
35 ASSERT(buffer); | 50 ASSERT(buffer); |
36 ASSERT(emphasisData); | 51 ASSERT(emphasisData); |
37 | 52 |
38 const SimpleFontData* emphasisFontData = emphasisData->fontData; | 53 const SimpleFontData* emphasisFontData = emphasisData->fontData; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 numGraphemes++; | 86 numGraphemes++; |
72 } | 87 } |
73 return std::max(0, numGraphemes); | 88 return std::max(0, numGraphemes); |
74 } | 89 } |
75 | 90 |
76 } // anonymous namespace | 91 } // anonymous namespace |
77 | 92 |
78 template <TextDirection direction> | 93 template <TextDirection direction> |
79 float ShapeResultBuffer::fillGlyphBufferForRun(GlyphBuffer* glyphBuffer, | 94 float ShapeResultBuffer::fillGlyphBufferForRun(GlyphBuffer* glyphBuffer, |
80 const ShapeResult::RunInfo* run, | 95 const ShapeResult::RunInfo* run, |
| 96 const TextRun& textRun, |
81 float initialAdvance, | 97 float initialAdvance, |
82 unsigned from, | 98 unsigned from, |
83 unsigned to, | 99 unsigned to, |
84 unsigned runOffset) { | 100 unsigned runOffset) { |
85 if (!run) | 101 if (!run) |
86 return 0; | 102 return 0; |
87 float advanceSoFar = initialAdvance; | 103 float advanceSoFar = initialAdvance; |
88 const unsigned numGlyphs = run->m_glyphData.size(); | 104 const unsigned numGlyphs = run->m_glyphData.size(); |
89 for (unsigned i = 0; i < numGlyphs; ++i) { | 105 for (unsigned i = 0; i < numGlyphs; ++i) { |
90 const HarfBuzzRunGlyphData& glyphData = run->m_glyphData[i]; | 106 const HarfBuzzRunGlyphData& glyphData = run->m_glyphData[i]; |
91 uint16_t currentCharacterIndex = | 107 uint16_t currentCharacterIndex = |
92 run->m_startIndex + glyphData.characterIndex + runOffset; | 108 run->m_startIndex + glyphData.characterIndex + runOffset; |
93 if ((direction == TextDirection::Rtl && currentCharacterIndex >= to) || | 109 if ((direction == TextDirection::Rtl && currentCharacterIndex >= to) || |
94 (direction == TextDirection::Ltr && currentCharacterIndex < from)) { | 110 (direction == TextDirection::Ltr && currentCharacterIndex < from)) { |
95 advanceSoFar += glyphData.advance; | 111 advanceSoFar += glyphData.advance; |
96 } else if ((direction == TextDirection::Rtl && | 112 } else if ((direction == TextDirection::Rtl && |
97 currentCharacterIndex >= from) || | 113 currentCharacterIndex >= from) || |
98 (direction == TextDirection::Ltr && | 114 (direction == TextDirection::Ltr && |
99 currentCharacterIndex < to)) { | 115 currentCharacterIndex < to)) { |
100 addGlyphToBuffer(glyphBuffer, advanceSoFar, run->m_direction, | 116 addGlyphToBuffer(glyphBuffer, advanceSoFar, run->m_direction, |
101 run->m_fontData.get(), glyphData); | 117 run->m_fontData.get(), glyphData, textRun, |
| 118 currentCharacterIndex); |
102 advanceSoFar += glyphData.advance; | 119 advanceSoFar += glyphData.advance; |
103 } | 120 } |
104 } | 121 } |
105 return advanceSoFar - initialAdvance; | 122 return advanceSoFar - initialAdvance; |
106 } | 123 } |
107 | 124 |
108 float ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun( | 125 float ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun( |
109 GlyphBuffer* glyphBuffer, | 126 GlyphBuffer* glyphBuffer, |
110 const ShapeResult::RunInfo* run, | 127 const ShapeResult::RunInfo* run, |
111 const TextRun& textRun, | 128 const TextRun& textRun, |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 } | 207 } |
191 clusterStart = clusterEnd; | 208 clusterStart = clusterEnd; |
192 clusterAdvance = 0; | 209 clusterAdvance = 0; |
193 } | 210 } |
194 } | 211 } |
195 return advanceSoFar - initialAdvance; | 212 return advanceSoFar - initialAdvance; |
196 } | 213 } |
197 | 214 |
198 float ShapeResultBuffer::fillFastHorizontalGlyphBuffer( | 215 float ShapeResultBuffer::fillFastHorizontalGlyphBuffer( |
199 GlyphBuffer* glyphBuffer, | 216 GlyphBuffer* glyphBuffer, |
200 TextDirection dir) const { | 217 const TextRun& textRun) const { |
201 ASSERT(!hasVerticalOffsets()); | 218 ASSERT(!hasVerticalOffsets()); |
202 | 219 |
203 float advance = 0; | 220 float advance = 0; |
204 | 221 |
| 222 unsigned characterIndex = 0; |
205 for (unsigned i = 0; i < m_results.size(); ++i) { | 223 for (unsigned i = 0; i < m_results.size(); ++i) { |
206 const auto& wordResult = isLeftToRightDirection(dir) | 224 const auto& wordResult = isLeftToRightDirection(textRun.direction()) |
207 ? m_results[i] | 225 ? m_results[i] |
208 : m_results[m_results.size() - 1 - i]; | 226 : m_results[m_results.size() - 1 - i]; |
209 ASSERT(!wordResult->hasVerticalOffsets()); | 227 ASSERT(!wordResult->hasVerticalOffsets()); |
210 | 228 |
211 for (const auto& run : wordResult->m_runs) { | 229 for (const auto& run : wordResult->m_runs) { |
212 ASSERT(run); | 230 ASSERT(run); |
213 ASSERT(HB_DIRECTION_IS_HORIZONTAL(run->m_direction)); | 231 ASSERT(HB_DIRECTION_IS_HORIZONTAL(run->m_direction)); |
214 | 232 |
215 for (const auto& glyphData : run->m_glyphData) { | 233 for (const auto& glyphData : run->m_glyphData) { |
216 ASSERT(!glyphData.offset.height()); | 234 ASSERT(!glyphData.offset.height()); |
217 | 235 |
218 glyphBuffer->add(glyphData.glyph, run->m_fontData.get(), | 236 glyphBuffer->add(glyphData.glyph, run->m_fontData.get(), |
219 advance + glyphData.offset.width()); | 237 advance + glyphData.offset.width()); |
| 238 if (glyphBuffer->hasSkipInkExceptions()) { |
| 239 addIsSkipInkException(glyphBuffer, textRun, |
| 240 characterIndex + glyphData.characterIndex); |
| 241 } |
| 242 |
220 advance += glyphData.advance; | 243 advance += glyphData.advance; |
221 } | 244 } |
222 } | 245 } |
| 246 characterIndex += wordResult->m_numCharacters; |
223 } | 247 } |
224 | 248 |
225 ASSERT(!glyphBuffer->hasVerticalOffsets()); | 249 ASSERT(!glyphBuffer->hasVerticalOffsets()); |
226 | 250 |
227 return advance; | 251 return advance; |
228 } | 252 } |
229 | 253 |
230 float ShapeResultBuffer::fillGlyphBuffer(GlyphBuffer* glyphBuffer, | 254 float ShapeResultBuffer::fillGlyphBuffer(GlyphBuffer* glyphBuffer, |
231 const TextRun& textRun, | 255 const TextRun& textRun, |
232 unsigned from, | 256 unsigned from, |
233 unsigned to) const { | 257 unsigned to) const { |
234 // Fast path: full run with no vertical offsets | 258 // Fast path: full run with no vertical offsets |
235 if (!from && to == textRun.length() && !hasVerticalOffsets()) | 259 if (!from && to == textRun.length() && !hasVerticalOffsets()) |
236 return fillFastHorizontalGlyphBuffer(glyphBuffer, textRun.direction()); | 260 return fillFastHorizontalGlyphBuffer(glyphBuffer, textRun); |
237 | 261 |
238 float advance = 0; | 262 float advance = 0; |
239 | 263 |
240 if (textRun.rtl()) { | 264 if (textRun.rtl()) { |
241 unsigned wordOffset = textRun.length(); | 265 unsigned wordOffset = textRun.length(); |
242 for (unsigned j = 0; j < m_results.size(); j++) { | 266 for (unsigned j = 0; j < m_results.size(); j++) { |
243 unsigned resolvedIndex = m_results.size() - 1 - j; | 267 unsigned resolvedIndex = m_results.size() - 1 - j; |
244 const RefPtr<const ShapeResult>& wordResult = m_results[resolvedIndex]; | 268 const RefPtr<const ShapeResult>& wordResult = m_results[resolvedIndex]; |
245 for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { | 269 for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { |
246 advance += fillGlyphBufferForRun<TextDirection::Rtl>( | 270 advance += fillGlyphBufferForRun<TextDirection::Rtl>( |
247 glyphBuffer, wordResult->m_runs[i].get(), advance, from, to, | 271 glyphBuffer, wordResult->m_runs[i].get(), textRun, advance, from, |
248 wordOffset - wordResult->numCharacters()); | 272 to, wordOffset - wordResult->numCharacters()); |
249 } | 273 } |
250 wordOffset -= wordResult->numCharacters(); | 274 wordOffset -= wordResult->numCharacters(); |
251 } | 275 } |
252 } else { | 276 } else { |
253 unsigned wordOffset = 0; | 277 unsigned wordOffset = 0; |
254 for (unsigned j = 0; j < m_results.size(); j++) { | 278 for (unsigned j = 0; j < m_results.size(); j++) { |
255 const RefPtr<const ShapeResult>& wordResult = m_results[j]; | 279 const RefPtr<const ShapeResult>& wordResult = m_results[j]; |
256 for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { | 280 for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { |
257 advance += fillGlyphBufferForRun<TextDirection::Ltr>( | 281 advance += fillGlyphBufferForRun<TextDirection::Ltr>( |
258 glyphBuffer, wordResult->m_runs[i].get(), advance, from, to, | 282 glyphBuffer, wordResult->m_runs[i].get(), textRun, advance, from, |
259 wordOffset); | 283 to, wordOffset); |
260 } | 284 } |
261 wordOffset += wordResult->numCharacters(); | 285 wordOffset += wordResult->numCharacters(); |
262 } | 286 } |
263 } | 287 } |
264 | 288 |
265 return advance; | 289 return advance; |
266 } | 290 } |
267 | 291 |
268 float ShapeResultBuffer::fillGlyphBufferForTextEmphasis( | 292 float ShapeResultBuffer::fillGlyphBufferForTextEmphasis( |
269 GlyphBuffer* glyphBuffer, | 293 GlyphBuffer* glyphBuffer, |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 totalOffset += offsetForWord; | 471 totalOffset += offsetForWord; |
448 if (targetX >= 0 && targetX <= wordResult->width()) | 472 if (targetX >= 0 && targetX <= wordResult->width()) |
449 return totalOffset; | 473 return totalOffset; |
450 targetX -= wordResult->width(); | 474 targetX -= wordResult->width(); |
451 } | 475 } |
452 } | 476 } |
453 return totalOffset; | 477 return totalOffset; |
454 } | 478 } |
455 | 479 |
456 } // namespace blink | 480 } // namespace blink |
OLD | NEW |