OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. |
3 * | 3 * |
4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 30 matching lines...) Expand all Loading... |
41 m_logicalCharacterOffset(0), | 41 m_logicalCharacterOffset(0), |
42 m_logicalMetricsListOffset(0), | 42 m_logicalMetricsListOffset(0), |
43 m_isVerticalText(false), | 43 m_isVerticalText(false), |
44 m_inPathLayout(false), | 44 m_inPathLayout(false), |
45 m_textLengthSpacingInEffect(false), | 45 m_textLengthSpacingInEffect(false), |
46 m_textPath(nullptr), | 46 m_textPath(nullptr), |
47 m_textPathCurrentOffset(0), | 47 m_textPathCurrentOffset(0), |
48 m_textPathDisplacement(0), | 48 m_textPathDisplacement(0), |
49 m_textPathSpacing(0), | 49 m_textPathSpacing(0), |
50 m_textPathScaling(1) { | 50 m_textPathScaling(1) { |
51 ASSERT(!m_descendantTextNodes.isEmpty()); | 51 DCHECK(!m_descendantTextNodes.isEmpty()); |
52 } | 52 } |
53 | 53 |
54 SVGTextLayoutEngine::~SVGTextLayoutEngine() = default; | 54 SVGTextLayoutEngine::~SVGTextLayoutEngine() = default; |
55 | 55 |
56 bool SVGTextLayoutEngine::setCurrentTextPosition(const SVGCharacterData& data) { | 56 bool SVGTextLayoutEngine::setCurrentTextPosition(const SVGCharacterData& data) { |
57 bool hasX = data.hasX(); | 57 bool hasX = data.hasX(); |
58 if (hasX) | 58 if (hasX) |
59 m_textPosition.setX(data.x); | 59 m_textPosition.setX(data.x); |
60 | 60 |
61 bool hasY = data.hasY(); | 61 bool hasY = data.hasY(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 } | 114 } |
115 | 115 |
116 void SVGTextLayoutEngine::computeCurrentFragmentMetrics( | 116 void SVGTextLayoutEngine::computeCurrentFragmentMetrics( |
117 SVGInlineTextBox* textBox) { | 117 SVGInlineTextBox* textBox) { |
118 LineLayoutSVGInlineText textLineLayout = | 118 LineLayoutSVGInlineText textLineLayout = |
119 LineLayoutSVGInlineText(textBox->getLineLayoutItem()); | 119 LineLayoutSVGInlineText(textBox->getLineLayoutItem()); |
120 TextRun run = textBox->constructTextRun(textLineLayout.styleRef(), | 120 TextRun run = textBox->constructTextRun(textLineLayout.styleRef(), |
121 m_currentTextFragment); | 121 m_currentTextFragment); |
122 | 122 |
123 float scalingFactor = textLineLayout.scalingFactor(); | 123 float scalingFactor = textLineLayout.scalingFactor(); |
124 ASSERT(scalingFactor); | 124 DCHECK(scalingFactor); |
125 const Font& scaledFont = textLineLayout.scaledFont(); | 125 const Font& scaledFont = textLineLayout.scaledFont(); |
126 FloatRect glyphOverflowBounds; | 126 FloatRect glyphOverflowBounds; |
127 | 127 |
128 const SimpleFontData* fontData = scaledFont.primaryFont(); | 128 const SimpleFontData* fontData = scaledFont.primaryFont(); |
129 DCHECK(fontData); | 129 DCHECK(fontData); |
130 if (!fontData) | 130 if (!fontData) |
131 return; | 131 return; |
132 | 132 |
133 float width = scaledFont.width(run, nullptr, &glyphOverflowBounds); | 133 float width = scaledFont.width(run, nullptr, &glyphOverflowBounds); |
134 float ascent = fontData->getFontMetrics().floatAscent(); | 134 float ascent = fontData->getFontMetrics().floatAscent(); |
135 float descent = fontData->getFontMetrics().floatDescent(); | 135 float descent = fontData->getFontMetrics().floatDescent(); |
136 m_currentTextFragment.glyphOverflow.setFromBounds(glyphOverflowBounds, ascent, | 136 m_currentTextFragment.glyphOverflow.setFromBounds(glyphOverflowBounds, ascent, |
137 descent, width); | 137 descent, width); |
138 m_currentTextFragment.glyphOverflow.top /= scalingFactor; | 138 m_currentTextFragment.glyphOverflow.top /= scalingFactor; |
139 m_currentTextFragment.glyphOverflow.left /= scalingFactor; | 139 m_currentTextFragment.glyphOverflow.left /= scalingFactor; |
140 m_currentTextFragment.glyphOverflow.right /= scalingFactor; | 140 m_currentTextFragment.glyphOverflow.right /= scalingFactor; |
141 m_currentTextFragment.glyphOverflow.bottom /= scalingFactor; | 141 m_currentTextFragment.glyphOverflow.bottom /= scalingFactor; |
142 | 142 |
143 float height = fontData->getFontMetrics().floatHeight(); | 143 float height = fontData->getFontMetrics().floatHeight(); |
144 m_currentTextFragment.height = height / scalingFactor; | 144 m_currentTextFragment.height = height / scalingFactor; |
145 m_currentTextFragment.width = width / scalingFactor; | 145 m_currentTextFragment.width = width / scalingFactor; |
146 } | 146 } |
147 | 147 |
148 void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox) { | 148 void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox) { |
149 ASSERT(!m_currentTextFragment.length); | 149 DCHECK(!m_currentTextFragment.length); |
150 | 150 |
151 // Figure out length of fragment. | 151 // Figure out length of fragment. |
152 m_currentTextFragment.length = m_visualMetricsIterator.characterOffset() - | 152 m_currentTextFragment.length = m_visualMetricsIterator.characterOffset() - |
153 m_currentTextFragment.characterOffset; | 153 m_currentTextFragment.characterOffset; |
154 | 154 |
155 // Figure out fragment metrics. | 155 // Figure out fragment metrics. |
156 computeCurrentFragmentMetrics(textBox); | 156 computeCurrentFragmentMetrics(textBox); |
157 | 157 |
158 textBox->textFragments().push_back(m_currentTextFragment); | 158 textBox->textFragments().push_back(m_currentTextFragment); |
159 m_currentTextFragment = SVGTextFragment(); | 159 m_currentTextFragment = SVGTextFragment(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 void SVGTextLayoutEngine::endTextPathLayout() { | 213 void SVGTextLayoutEngine::endTextPathLayout() { |
214 m_inPathLayout = false; | 214 m_inPathLayout = false; |
215 m_textPath = nullptr; | 215 m_textPath = nullptr; |
216 m_textPathStartOffset = 0; | 216 m_textPathStartOffset = 0; |
217 m_textPathCurrentOffset = 0; | 217 m_textPathCurrentOffset = 0; |
218 m_textPathSpacing = 0; | 218 m_textPathSpacing = 0; |
219 m_textPathScaling = 1; | 219 m_textPathScaling = 1; |
220 } | 220 } |
221 | 221 |
222 void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox* textBox) { | 222 void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox* textBox) { |
223 ASSERT(textBox); | 223 DCHECK(textBox); |
224 | 224 |
225 LineLayoutSVGInlineText textLineLayout = | 225 LineLayoutSVGInlineText textLineLayout = |
226 LineLayoutSVGInlineText(textBox->getLineLayoutItem()); | 226 LineLayoutSVGInlineText(textBox->getLineLayoutItem()); |
227 ASSERT(textLineLayout.parent()); | 227 DCHECK(textLineLayout.parent()); |
228 ASSERT(textLineLayout.parent().node()); | 228 DCHECK(textLineLayout.parent().node()); |
229 ASSERT(textLineLayout.parent().node()->isSVGElement()); | 229 DCHECK(textLineLayout.parent().node()->isSVGElement()); |
230 | 230 |
231 const ComputedStyle& style = textLineLayout.styleRef(); | 231 const ComputedStyle& style = textLineLayout.styleRef(); |
232 | 232 |
233 textBox->clearTextFragments(); | 233 textBox->clearTextFragments(); |
234 m_isVerticalText = !style.isHorizontalWritingMode(); | 234 m_isVerticalText = !style.isHorizontalWritingMode(); |
235 layoutTextOnLineOrPath(textBox, textLineLayout, style); | 235 layoutTextOnLineOrPath(textBox, textLineLayout, style); |
236 | 236 |
237 if (m_inPathLayout) | 237 if (m_inPathLayout) |
238 return; | 238 return; |
239 | 239 |
(...skipping 12 matching lines...) Expand all Loading... |
252 | 252 |
253 void SVGTextLayoutEngine::layoutCharactersInTextBoxes(InlineFlowBox* start) { | 253 void SVGTextLayoutEngine::layoutCharactersInTextBoxes(InlineFlowBox* start) { |
254 bool textLengthSpacingInEffect = | 254 bool textLengthSpacingInEffect = |
255 m_textLengthSpacingInEffect || definesTextLengthWithSpacing(start); | 255 m_textLengthSpacingInEffect || definesTextLengthWithSpacing(start); |
256 AutoReset<bool> textLengthSpacingScope(&m_textLengthSpacingInEffect, | 256 AutoReset<bool> textLengthSpacingScope(&m_textLengthSpacingInEffect, |
257 textLengthSpacingInEffect); | 257 textLengthSpacingInEffect); |
258 | 258 |
259 for (InlineBox* child = start->firstChild(); child; | 259 for (InlineBox* child = start->firstChild(); child; |
260 child = child->nextOnLine()) { | 260 child = child->nextOnLine()) { |
261 if (child->isSVGInlineTextBox()) { | 261 if (child->isSVGInlineTextBox()) { |
262 ASSERT(child->getLineLayoutItem().isSVGInlineText()); | 262 DCHECK(child->getLineLayoutItem().isSVGInlineText()); |
263 layoutInlineTextBox(toSVGInlineTextBox(child)); | 263 layoutInlineTextBox(toSVGInlineTextBox(child)); |
264 } else { | 264 } else { |
265 // Skip generated content. | 265 // Skip generated content. |
266 Node* node = child->getLineLayoutItem().node(); | 266 Node* node = child->getLineLayoutItem().node(); |
267 if (!node) | 267 if (!node) |
268 continue; | 268 continue; |
269 | 269 |
270 SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child); | 270 SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child); |
271 bool isTextPath = isSVGTextPathElement(*node); | 271 bool isTextPath = isSVGTextPathElement(*node); |
272 if (isTextPath) | 272 if (isTextPath) |
(...skipping 14 matching lines...) Expand all Loading... |
287 // SVGInlineTextBoxes, we can layout individual text chunks. | 287 // SVGInlineTextBoxes, we can layout individual text chunks. |
288 // Chunk layouting is only performed for line layout boxes, not for path | 288 // Chunk layouting is only performed for line layout boxes, not for path |
289 // layout, where it has already been done. | 289 // layout, where it has already been done. |
290 SVGTextChunkBuilder chunkLayoutBuilder; | 290 SVGTextChunkBuilder chunkLayoutBuilder; |
291 chunkLayoutBuilder.processTextChunks(m_lineLayoutBoxes); | 291 chunkLayoutBuilder.processTextChunks(m_lineLayoutBoxes); |
292 | 292 |
293 m_lineLayoutBoxes.clear(); | 293 m_lineLayoutBoxes.clear(); |
294 } | 294 } |
295 | 295 |
296 const LayoutSVGInlineText* SVGTextLayoutEngine::nextLogicalTextNode() { | 296 const LayoutSVGInlineText* SVGTextLayoutEngine::nextLogicalTextNode() { |
297 ASSERT(m_currentLogicalTextNodeIndex < m_descendantTextNodes.size()); | 297 DCHECK_LT(m_currentLogicalTextNodeIndex, m_descendantTextNodes.size()); |
298 ++m_currentLogicalTextNodeIndex; | 298 ++m_currentLogicalTextNodeIndex; |
299 if (m_currentLogicalTextNodeIndex == m_descendantTextNodes.size()) | 299 if (m_currentLogicalTextNodeIndex == m_descendantTextNodes.size()) |
300 return nullptr; | 300 return nullptr; |
301 | 301 |
302 m_logicalMetricsListOffset = 0; | 302 m_logicalMetricsListOffset = 0; |
303 m_logicalCharacterOffset = 0; | 303 m_logicalCharacterOffset = 0; |
304 return m_descendantTextNodes[m_currentLogicalTextNodeIndex]; | 304 return m_descendantTextNodes[m_currentLogicalTextNodeIndex]; |
305 } | 305 } |
306 | 306 |
307 const LayoutSVGInlineText* SVGTextLayoutEngine::currentLogicalCharacterMetrics( | 307 const LayoutSVGInlineText* SVGTextLayoutEngine::currentLogicalCharacterMetrics( |
308 SVGTextMetrics& logicalMetrics) { | 308 SVGTextMetrics& logicalMetrics) { |
309 // If we've consumed all text nodes, there can be no more metrics. | 309 // If we've consumed all text nodes, there can be no more metrics. |
310 if (m_currentLogicalTextNodeIndex == m_descendantTextNodes.size()) | 310 if (m_currentLogicalTextNodeIndex == m_descendantTextNodes.size()) |
311 return nullptr; | 311 return nullptr; |
312 | 312 |
313 const LayoutSVGInlineText* logicalTextNode = | 313 const LayoutSVGInlineText* logicalTextNode = |
314 m_descendantTextNodes[m_currentLogicalTextNodeIndex]; | 314 m_descendantTextNodes[m_currentLogicalTextNodeIndex]; |
315 const Vector<SVGTextMetrics>* metricsList = &logicalTextNode->metricsList(); | 315 const Vector<SVGTextMetrics>* metricsList = &logicalTextNode->metricsList(); |
316 unsigned metricsListSize = metricsList->size(); | 316 unsigned metricsListSize = metricsList->size(); |
317 ASSERT(m_logicalMetricsListOffset <= metricsListSize); | 317 DCHECK(m_logicalMetricsListOffset <= metricsListSize); |
318 | 318 |
319 // Find the next non-collapsed text metrics cell. | 319 // Find the next non-collapsed text metrics cell. |
320 while (true) { | 320 while (true) { |
321 // If we run out of metrics, move to the next set of non-empty layout | 321 // If we run out of metrics, move to the next set of non-empty layout |
322 // attributes. | 322 // attributes. |
323 if (m_logicalMetricsListOffset == metricsListSize) { | 323 if (m_logicalMetricsListOffset == metricsListSize) { |
324 logicalTextNode = nextLogicalTextNode(); | 324 logicalTextNode = nextLogicalTextNode(); |
325 if (!logicalTextNode) | 325 if (!logicalTextNode) |
326 return nullptr; | 326 return nullptr; |
327 metricsList = &logicalTextNode->metricsList(); | 327 metricsList = &logicalTextNode->metricsList(); |
328 metricsListSize = metricsList->size(); | 328 metricsListSize = metricsList->size(); |
329 // Return to the while so that we check if the new metrics list is | 329 // Return to the while so that we check if the new metrics list is |
330 // non-empty before using it. | 330 // non-empty before using it. |
331 continue; | 331 continue; |
332 } | 332 } |
333 | 333 |
334 ASSERT(metricsListSize); | 334 DCHECK(metricsListSize); |
335 logicalMetrics = metricsList->at(m_logicalMetricsListOffset); | 335 logicalMetrics = metricsList->at(m_logicalMetricsListOffset); |
336 // Stop if we found the next valid logical text metrics object. | 336 // Stop if we found the next valid logical text metrics object. |
337 if (!logicalMetrics.isEmpty()) | 337 if (!logicalMetrics.isEmpty()) |
338 break; | 338 break; |
339 | 339 |
340 advanceToNextLogicalCharacter(logicalMetrics); | 340 advanceToNextLogicalCharacter(logicalMetrics); |
341 } | 341 } |
342 | 342 |
343 return logicalTextNode; | 343 return logicalTextNode; |
344 } | 344 } |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 angle != lastAngle || applySpacingToNextCharacter; | 482 angle != lastAngle || applySpacingToNextCharacter; |
483 | 483 |
484 // If we already started a fragment, close it now. | 484 // If we already started a fragment, close it now. |
485 if (didStartTextFragment && shouldStartNewFragment) { | 485 if (didStartTextFragment && shouldStartNewFragment) { |
486 applySpacingToNextCharacter = false; | 486 applySpacingToNextCharacter = false; |
487 recordTextFragment(textBox); | 487 recordTextFragment(textBox); |
488 } | 488 } |
489 | 489 |
490 // Eventually start a new fragment, if not yet done. | 490 // Eventually start a new fragment, if not yet done. |
491 if (!didStartTextFragment || shouldStartNewFragment) { | 491 if (!didStartTextFragment || shouldStartNewFragment) { |
492 ASSERT(!m_currentTextFragment.characterOffset); | 492 DCHECK(!m_currentTextFragment.characterOffset); |
493 ASSERT(!m_currentTextFragment.length); | 493 DCHECK(!m_currentTextFragment.length); |
494 | 494 |
495 didStartTextFragment = true; | 495 didStartTextFragment = true; |
496 m_currentTextFragment.characterOffset = | 496 m_currentTextFragment.characterOffset = |
497 m_visualMetricsIterator.characterOffset(); | 497 m_visualMetricsIterator.characterOffset(); |
498 m_currentTextFragment.metricsListOffset = | 498 m_currentTextFragment.metricsListOffset = |
499 m_visualMetricsIterator.metricsListOffset(); | 499 m_visualMetricsIterator.metricsListOffset(); |
500 m_currentTextFragment.x = position.x(); | 500 m_currentTextFragment.x = position.x(); |
501 m_currentTextFragment.y = position.y(); | 501 m_currentTextFragment.y = position.y(); |
502 | 502 |
503 // Build fragment transformation. | 503 // Build fragment transformation. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 } | 536 } |
537 | 537 |
538 if (!didStartTextFragment) | 538 if (!didStartTextFragment) |
539 return; | 539 return; |
540 | 540 |
541 // Close last open fragment, if needed. | 541 // Close last open fragment, if needed. |
542 recordTextFragment(textBox); | 542 recordTextFragment(textBox); |
543 } | 543 } |
544 | 544 |
545 } // namespace blink | 545 } // namespace blink |
OLD | NEW |