| Index: Source/core/layout/svg/SVGTextChunkBuilder.cpp
|
| diff --git a/Source/core/layout/svg/SVGTextChunkBuilder.cpp b/Source/core/layout/svg/SVGTextChunkBuilder.cpp
|
| index 84e2dc5f37c48b90447383654ce3962d281fb7c9..127fd4f5596b0a31abcbc313bc49be0a98eb52c8 100644
|
| --- a/Source/core/layout/svg/SVGTextChunkBuilder.cpp
|
| +++ b/Source/core/layout/svg/SVGTextChunkBuilder.cpp
|
| @@ -21,7 +21,6 @@
|
| #include "core/layout/svg/SVGTextChunkBuilder.h"
|
|
|
| #include "core/layout/svg/LayoutSVGInlineText.h"
|
| -#include "core/layout/svg/SVGTextChunk.h"
|
| #include "core/layout/svg/line/SVGInlineTextBox.h"
|
| #include "core/svg/SVGLengthContext.h"
|
| #include "core/svg/SVGTextContentElement.h"
|
| @@ -30,57 +29,34 @@ namespace blink {
|
|
|
| namespace {
|
|
|
| -SVGTextChunk createTextChunk(const SVGInlineTextBox& textBox)
|
| +float calculateTextAnchorShift(const ComputedStyle& style, float length)
|
| {
|
| - LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(textBox.layoutObject());
|
| - const ComputedStyle& style = textLayoutObject.styleRef();
|
| - const SVGComputedStyle& svgStyle = style.svgStyle();
|
| -
|
| - // Build chunk style flags.
|
| - unsigned chunkStyle = SVGTextChunk::DefaultStyle;
|
| -
|
| - // Handle 'direction' property.
|
| - if (!style.isLeftToRightDirection())
|
| - chunkStyle |= SVGTextChunk::RightToLeftText;
|
| -
|
| - // Handle 'writing-mode' property.
|
| - if (svgStyle.isVerticalWritingMode())
|
| - chunkStyle |= SVGTextChunk::VerticalText;
|
| -
|
| - // Handle 'text-anchor' property.
|
| - switch (svgStyle.textAnchor()) {
|
| + bool isLTR = style.isLeftToRightDirection();
|
| + switch (style.svgStyle().textAnchor()) {
|
| + default:
|
| + ASSERT_NOT_REACHED();
|
| case TA_START:
|
| - break;
|
| + return isLTR ? 0 : -length;
|
| case TA_MIDDLE:
|
| - chunkStyle |= SVGTextChunk::MiddleAnchor;
|
| - break;
|
| + return -length / 2;
|
| case TA_END:
|
| - chunkStyle |= SVGTextChunk::EndAnchor;
|
| - break;
|
| + return isLTR ? -length : 0;
|
| }
|
| +}
|
|
|
| - // Handle 'lengthAdjust' property.
|
| - float desiredTextLength = 0;
|
| - if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromLayoutObject(textLayoutObject.parent())) {
|
| - SVGLengthContext lengthContext(textContentElement);
|
| - if (textContentElement->textLengthIsSpecifiedByUser())
|
| - desiredTextLength = textContentElement->textLength()->currentValue()->value(lengthContext);
|
| - else
|
| - desiredTextLength = 0;
|
| -
|
| - switch (textContentElement->lengthAdjust()->currentValue()->enumValue()) {
|
| - case SVGLengthAdjustUnknown:
|
| - break;
|
| - case SVGLengthAdjustSpacing:
|
| - chunkStyle |= SVGTextChunk::LengthAdjustSpacing;
|
| - break;
|
| - case SVGLengthAdjustSpacingAndGlyphs:
|
| - chunkStyle |= SVGTextChunk::LengthAdjustSpacingAndGlyphs;
|
| - break;
|
| - }
|
| +bool needsTextAnchorAdjustment(const ComputedStyle& style)
|
| +{
|
| + bool isLTR = style.isLeftToRightDirection();
|
| + switch (style.svgStyle().textAnchor()) {
|
| + default:
|
| + ASSERT_NOT_REACHED();
|
| + case TA_START:
|
| + return !isLTR;
|
| + case TA_MIDDLE:
|
| + return true;
|
| + case TA_END:
|
| + return isLTR;
|
| }
|
| -
|
| - return SVGTextChunk(chunkStyle, desiredTextLength);
|
| }
|
|
|
| class ChunkLengthAccumulator {
|
| @@ -183,13 +159,13 @@ SVGTextPathChunkBuilder::SVGTextPathChunkBuilder()
|
|
|
| void SVGTextPathChunkBuilder::handleTextChunk(BoxListConstIterator boxStart, BoxListConstIterator boxEnd)
|
| {
|
| - SVGTextChunk chunk = createTextChunk(**boxStart);
|
| + const ComputedStyle& style = (*boxStart)->layoutObject().styleRef();
|
|
|
| - ChunkLengthAccumulator lengthAccumulator(chunk.isVerticalText());
|
| + ChunkLengthAccumulator lengthAccumulator(style.svgStyle().isVerticalWritingMode());
|
| lengthAccumulator.processRange(boxStart, boxEnd);
|
|
|
| // Handle text-anchor as additional start offset for text paths.
|
| - m_totalTextAnchorShift += chunk.calculateTextAnchorShift(lengthAccumulator.length());
|
| + m_totalTextAnchorShift += calculateTextAnchorShift(style, lengthAccumulator.length());
|
|
|
| m_totalLength += lengthAccumulator.length();
|
| m_totalCharacters += lengthAccumulator.numCharacters();
|
| @@ -209,14 +185,30 @@ static void buildSpacingAndGlyphsTransform(bool isVerticalText, float scale, con
|
|
|
| void SVGTextChunkBuilder::handleTextChunk(BoxListConstIterator boxStart, BoxListConstIterator boxEnd)
|
| {
|
| - SVGTextChunk chunk = createTextChunk(**boxStart);
|
| + ASSERT(*boxStart);
|
| +
|
| + const LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText((*boxStart)->layoutObject());
|
| + const ComputedStyle& style = textLayoutObject.styleRef();
|
| +
|
| + // Handle 'lengthAdjust' property.
|
| + float desiredTextLength = 0;
|
| + SVGLengthAdjustType lengthAdjust = SVGLengthAdjustUnknown;
|
| + if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromLayoutObject(textLayoutObject.parent())) {
|
| + lengthAdjust = textContentElement->lengthAdjust()->currentValue()->enumValue();
|
| +
|
| + SVGLengthContext lengthContext(textContentElement);
|
| + if (textContentElement->textLengthIsSpecifiedByUser())
|
| + desiredTextLength = textContentElement->textLength()->currentValue()->value(lengthContext);
|
| + else
|
| + desiredTextLength = 0;
|
| + }
|
|
|
| - bool processTextLength = chunk.hasDesiredTextLength();
|
| - bool processTextAnchor = chunk.hasTextAnchor();
|
| + bool processTextLength = desiredTextLength > 0;
|
| + bool processTextAnchor = needsTextAnchorAdjustment(style);
|
| if (!processTextAnchor && !processTextLength)
|
| return;
|
|
|
| - bool isVerticalText = chunk.isVerticalText();
|
| + bool isVerticalText = style.svgStyle().isVerticalWritingMode();
|
|
|
| // Calculate absolute length of whole text chunk (starting from text box 'start', spanning 'length' text boxes).
|
| ChunkLengthAccumulator lengthAccumulator(isVerticalText);
|
| @@ -224,8 +216,8 @@ void SVGTextChunkBuilder::handleTextChunk(BoxListConstIterator boxStart, BoxList
|
|
|
| if (processTextLength) {
|
| float chunkLength = lengthAccumulator.length();
|
| - if (chunk.hasLengthAdjustSpacing()) {
|
| - float textLengthShift = (chunk.desiredTextLength() - chunkLength) / lengthAccumulator.numCharacters();
|
| + if (lengthAdjust == SVGLengthAdjustSpacing) {
|
| + float textLengthShift = (desiredTextLength - chunkLength) / lengthAccumulator.numCharacters();
|
| unsigned atCharacter = 0;
|
| for (auto boxIter = boxStart; boxIter != boxEnd; ++boxIter) {
|
| Vector<SVGTextFragment>& fragments = (*boxIter)->textFragments();
|
| @@ -241,8 +233,8 @@ void SVGTextChunkBuilder::handleTextChunk(BoxListConstIterator boxStart, BoxList
|
| lengthAccumulator.processRange(boxStart, boxEnd);
|
| }
|
| } else {
|
| - ASSERT(chunk.hasLengthAdjustSpacingAndGlyphs());
|
| - float textLengthScale = chunk.desiredTextLength() / chunkLength;
|
| + ASSERT(lengthAdjust == SVGLengthAdjustSpacingAndGlyphs);
|
| + float textLengthScale = desiredTextLength / chunkLength;
|
| AffineTransform spacingAndGlyphsTransform;
|
|
|
| bool foundFirstFragment = false;
|
| @@ -265,7 +257,7 @@ void SVGTextChunkBuilder::handleTextChunk(BoxListConstIterator boxStart, BoxList
|
| if (!processTextAnchor)
|
| return;
|
|
|
| - float textAnchorShift = chunk.calculateTextAnchorShift(lengthAccumulator.length());
|
| + float textAnchorShift = calculateTextAnchorShift(style, lengthAccumulator.length());
|
| for (auto boxIter = boxStart; boxIter != boxEnd; ++boxIter) {
|
| Vector<SVGTextFragment>& fragments = (*boxIter)->textFragments();
|
| if (fragments.isEmpty())
|
|
|