| 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" | |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |