Chromium Code Reviews| 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 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |