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

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

Issue 2598393002: Do not skip ink for ideographic scripts (Closed)
Patch Set: drott review Created 3 years, 11 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" 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 DCHECK(!run.is8Bit()) << "8Bit() is always false, better to avoid to call";
24 UChar32 baseCharacter = run.codepointAt(characterIndex);
25 UBlockCode blockCode = ublock_getCode(baseCharacter);
drott 2017/01/02 15:07:46 I'd very much prefer if we could reuse the isCJKId
26 switch (blockCode) {
27 case UBLOCK_BOPOMOFO:
28 case UBLOCK_BOPOMOFO_EXTENDED:
29 case UBLOCK_CJK_COMPATIBILITY:
30 case UBLOCK_CJK_COMPATIBILITY_FORMS:
31 case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS:
32 case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT:
33 case UBLOCK_CJK_RADICALS_SUPPLEMENT:
34 case UBLOCK_CJK_STROKES:
35 case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION:
36 case UBLOCK_CJK_UNIFIED_IDEOGRAPHS:
37 case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A:
38 case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B:
39 case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C:
40 case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D:
41 case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E:
42 case UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS:
43 case UBLOCK_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT:
44 case UBLOCK_HANGUL_COMPATIBILITY_JAMO:
45 case UBLOCK_HANGUL_JAMO:
46 case UBLOCK_HANGUL_JAMO_EXTENDED_A:
47 case UBLOCK_HANGUL_JAMO_EXTENDED_B:
48 case UBLOCK_HANGUL_SYLLABLES:
49 case UBLOCK_HIRAGANA:
50 case UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS:
51 case UBLOCK_IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION:
52 case UBLOCK_KATAKANA:
53 case UBLOCK_LINEAR_B_IDEOGRAMS:
54 case UBLOCK_TANGUT:
55 case UBLOCK_TANGUT_COMPONENTS:
56 glyphBuffer->addIsSkipInkException(true);
57 break;
58 default:
59 glyphBuffer->addIsSkipInkException(false);
60 break;
61 }
62 }
63
20 inline void addGlyphToBuffer(GlyphBuffer* glyphBuffer, 64 inline void addGlyphToBuffer(GlyphBuffer* glyphBuffer,
21 float advance, 65 float advance,
22 hb_direction_t direction, 66 hb_direction_t direction,
23 const SimpleFontData* fontData, 67 const SimpleFontData* fontData,
24 const HarfBuzzRunGlyphData& glyphData) { 68 const HarfBuzzRunGlyphData& glyphData,
69 const TextRun& run,
70 unsigned characterIndex) {
25 FloatPoint startOffset = HB_DIRECTION_IS_HORIZONTAL(direction) 71 FloatPoint startOffset = HB_DIRECTION_IS_HORIZONTAL(direction)
26 ? FloatPoint(advance, 0) 72 ? FloatPoint(advance, 0)
27 : FloatPoint(0, advance); 73 : FloatPoint(0, advance);
28 glyphBuffer->add(glyphData.glyph, fontData, startOffset + glyphData.offset); 74 glyphBuffer->add(glyphData.glyph, fontData, startOffset + glyphData.offset);
75 if (glyphBuffer->shouldSaveSkipInkExceptions() && !run.is8Bit())
76 addIsSkipInkException(glyphBuffer, run, characterIndex);
29 } 77 }
30 78
31 inline void addEmphasisMark(GlyphBuffer* buffer, 79 inline void addEmphasisMark(GlyphBuffer* buffer,
32 const GlyphData* emphasisData, 80 const GlyphData* emphasisData,
33 FloatPoint glyphCenter, 81 FloatPoint glyphCenter,
34 float midGlyphOffset) { 82 float midGlyphOffset) {
35 ASSERT(buffer); 83 ASSERT(buffer);
36 ASSERT(emphasisData); 84 ASSERT(emphasisData);
37 85
38 const SimpleFontData* emphasisFontData = emphasisData->fontData; 86 const SimpleFontData* emphasisFontData = emphasisData->fontData;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 numGraphemes++; 119 numGraphemes++;
72 } 120 }
73 return std::max(0, numGraphemes); 121 return std::max(0, numGraphemes);
74 } 122 }
75 123
76 } // anonymous namespace 124 } // anonymous namespace
77 125
78 template <TextDirection direction> 126 template <TextDirection direction>
79 float ShapeResultBuffer::fillGlyphBufferForRun(GlyphBuffer* glyphBuffer, 127 float ShapeResultBuffer::fillGlyphBufferForRun(GlyphBuffer* glyphBuffer,
80 const ShapeResult::RunInfo* run, 128 const ShapeResult::RunInfo* run,
129 const TextRun& textRun,
81 float initialAdvance, 130 float initialAdvance,
82 unsigned from, 131 unsigned from,
83 unsigned to, 132 unsigned to,
84 unsigned runOffset) { 133 unsigned runOffset) {
85 if (!run) 134 if (!run)
86 return 0; 135 return 0;
87 float advanceSoFar = initialAdvance; 136 float advanceSoFar = initialAdvance;
88 const unsigned numGlyphs = run->m_glyphData.size(); 137 const unsigned numGlyphs = run->m_glyphData.size();
89 for (unsigned i = 0; i < numGlyphs; ++i) { 138 for (unsigned i = 0; i < numGlyphs; ++i) {
90 const HarfBuzzRunGlyphData& glyphData = run->m_glyphData[i]; 139 const HarfBuzzRunGlyphData& glyphData = run->m_glyphData[i];
91 uint16_t currentCharacterIndex = 140 uint16_t currentCharacterIndex =
92 run->m_startIndex + glyphData.characterIndex + runOffset; 141 run->m_startIndex + glyphData.characterIndex + runOffset;
93 if ((direction == TextDirection::Rtl && currentCharacterIndex >= to) || 142 if ((direction == TextDirection::Rtl && currentCharacterIndex >= to) ||
94 (direction == TextDirection::Ltr && currentCharacterIndex < from)) { 143 (direction == TextDirection::Ltr && currentCharacterIndex < from)) {
95 advanceSoFar += glyphData.advance; 144 advanceSoFar += glyphData.advance;
96 } else if ((direction == TextDirection::Rtl && 145 } else if ((direction == TextDirection::Rtl &&
97 currentCharacterIndex >= from) || 146 currentCharacterIndex >= from) ||
98 (direction == TextDirection::Ltr && 147 (direction == TextDirection::Ltr &&
99 currentCharacterIndex < to)) { 148 currentCharacterIndex < to)) {
100 addGlyphToBuffer(glyphBuffer, advanceSoFar, run->m_direction, 149 addGlyphToBuffer(glyphBuffer, advanceSoFar, run->m_direction,
101 run->m_fontData.get(), glyphData); 150 run->m_fontData.get(), glyphData, textRun,
151 currentCharacterIndex);
102 advanceSoFar += glyphData.advance; 152 advanceSoFar += glyphData.advance;
103 } 153 }
104 } 154 }
105 return advanceSoFar - initialAdvance; 155 return advanceSoFar - initialAdvance;
106 } 156 }
107 157
108 float ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun( 158 float ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun(
109 GlyphBuffer* glyphBuffer, 159 GlyphBuffer* glyphBuffer,
110 const ShapeResult::RunInfo* run, 160 const ShapeResult::RunInfo* run,
111 const TextRun& textRun, 161 const TextRun& textRun,
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 } 240 }
191 clusterStart = clusterEnd; 241 clusterStart = clusterEnd;
192 clusterAdvance = 0; 242 clusterAdvance = 0;
193 } 243 }
194 } 244 }
195 return advanceSoFar - initialAdvance; 245 return advanceSoFar - initialAdvance;
196 } 246 }
197 247
198 float ShapeResultBuffer::fillFastHorizontalGlyphBuffer( 248 float ShapeResultBuffer::fillFastHorizontalGlyphBuffer(
199 GlyphBuffer* glyphBuffer, 249 GlyphBuffer* glyphBuffer,
200 TextDirection dir) const { 250 const TextRun& textRun) const {
201 ASSERT(!hasVerticalOffsets()); 251 ASSERT(!hasVerticalOffsets());
202 252
203 float advance = 0; 253 float advance = 0;
204 254
255 unsigned characterIndex = 0;
205 for (unsigned i = 0; i < m_results.size(); ++i) { 256 for (unsigned i = 0; i < m_results.size(); ++i) {
206 const auto& wordResult = isLeftToRightDirection(dir) 257 const auto& wordResult = isLeftToRightDirection(textRun.direction())
207 ? m_results[i] 258 ? m_results[i]
208 : m_results[m_results.size() - 1 - i]; 259 : m_results[m_results.size() - 1 - i];
209 ASSERT(!wordResult->hasVerticalOffsets()); 260 ASSERT(!wordResult->hasVerticalOffsets());
210 261
211 for (const auto& run : wordResult->m_runs) { 262 for (const auto& run : wordResult->m_runs) {
212 ASSERT(run); 263 ASSERT(run);
213 ASSERT(HB_DIRECTION_IS_HORIZONTAL(run->m_direction)); 264 ASSERT(HB_DIRECTION_IS_HORIZONTAL(run->m_direction));
214 265
215 for (const auto& glyphData : run->m_glyphData) { 266 for (const auto& glyphData : run->m_glyphData) {
216 ASSERT(!glyphData.offset.height()); 267 ASSERT(!glyphData.offset.height());
217 268
218 glyphBuffer->add(glyphData.glyph, run->m_fontData.get(), 269 glyphBuffer->add(glyphData.glyph, run->m_fontData.get(),
219 advance + glyphData.offset.width()); 270 advance + glyphData.offset.width());
271 if (glyphBuffer->shouldSaveSkipInkExceptions() && !textRun.is8Bit()) {
272 addIsSkipInkException(glyphBuffer, textRun,
273 characterIndex + glyphData.characterIndex);
274 }
275
220 advance += glyphData.advance; 276 advance += glyphData.advance;
221 } 277 }
222 } 278 }
279 characterIndex += wordResult->m_numCharacters;
223 } 280 }
224 281
225 ASSERT(!glyphBuffer->hasVerticalOffsets()); 282 ASSERT(!glyphBuffer->hasVerticalOffsets());
226 283
227 return advance; 284 return advance;
228 } 285 }
229 286
230 float ShapeResultBuffer::fillGlyphBuffer(GlyphBuffer* glyphBuffer, 287 float ShapeResultBuffer::fillGlyphBuffer(GlyphBuffer* glyphBuffer,
231 const TextRun& textRun, 288 const TextRun& textRun,
232 unsigned from, 289 unsigned from,
233 unsigned to) const { 290 unsigned to) const {
234 // Fast path: full run with no vertical offsets 291 // Fast path: full run with no vertical offsets
235 if (!from && to == textRun.length() && !hasVerticalOffsets()) 292 if (!from && to == textRun.length() && !hasVerticalOffsets())
236 return fillFastHorizontalGlyphBuffer(glyphBuffer, textRun.direction()); 293 return fillFastHorizontalGlyphBuffer(glyphBuffer, textRun);
237 294
238 float advance = 0; 295 float advance = 0;
239 296
240 if (textRun.rtl()) { 297 if (textRun.rtl()) {
241 unsigned wordOffset = textRun.length(); 298 unsigned wordOffset = textRun.length();
242 for (unsigned j = 0; j < m_results.size(); j++) { 299 for (unsigned j = 0; j < m_results.size(); j++) {
243 unsigned resolvedIndex = m_results.size() - 1 - j; 300 unsigned resolvedIndex = m_results.size() - 1 - j;
244 const RefPtr<const ShapeResult>& wordResult = m_results[resolvedIndex]; 301 const RefPtr<const ShapeResult>& wordResult = m_results[resolvedIndex];
245 for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { 302 for (unsigned i = 0; i < wordResult->m_runs.size(); i++) {
246 advance += fillGlyphBufferForRun<TextDirection::Rtl>( 303 advance += fillGlyphBufferForRun<TextDirection::Rtl>(
247 glyphBuffer, wordResult->m_runs[i].get(), advance, from, to, 304 glyphBuffer, wordResult->m_runs[i].get(), textRun, advance, from,
248 wordOffset - wordResult->numCharacters()); 305 to, wordOffset - wordResult->numCharacters());
249 } 306 }
250 wordOffset -= wordResult->numCharacters(); 307 wordOffset -= wordResult->numCharacters();
251 } 308 }
252 } else { 309 } else {
253 unsigned wordOffset = 0; 310 unsigned wordOffset = 0;
254 for (unsigned j = 0; j < m_results.size(); j++) { 311 for (unsigned j = 0; j < m_results.size(); j++) {
255 const RefPtr<const ShapeResult>& wordResult = m_results[j]; 312 const RefPtr<const ShapeResult>& wordResult = m_results[j];
256 for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { 313 for (unsigned i = 0; i < wordResult->m_runs.size(); i++) {
257 advance += fillGlyphBufferForRun<TextDirection::Ltr>( 314 advance += fillGlyphBufferForRun<TextDirection::Ltr>(
258 glyphBuffer, wordResult->m_runs[i].get(), advance, from, to, 315 glyphBuffer, wordResult->m_runs[i].get(), textRun, advance, from,
259 wordOffset); 316 to, wordOffset);
260 } 317 }
261 wordOffset += wordResult->numCharacters(); 318 wordOffset += wordResult->numCharacters();
262 } 319 }
263 } 320 }
264 321
265 return advance; 322 return advance;
266 } 323 }
267 324
268 float ShapeResultBuffer::fillGlyphBufferForTextEmphasis( 325 float ShapeResultBuffer::fillGlyphBufferForTextEmphasis(
269 GlyphBuffer* glyphBuffer, 326 GlyphBuffer* glyphBuffer,
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 totalOffset += offsetForWord; 504 totalOffset += offsetForWord;
448 if (targetX >= 0 && targetX <= wordResult->width()) 505 if (targetX >= 0 && targetX <= wordResult->width())
449 return totalOffset; 506 return totalOffset;
450 targetX -= wordResult->width(); 507 targetX -= wordResult->width();
451 } 508 }
452 } 509 }
453 return totalOffset; 510 return totalOffset;
454 } 511 }
455 512
456 } // namespace blink 513 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698