| 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 |