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