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 |