Index: Source/core/layout/svg/SVGTextLayoutEngine.cpp |
diff --git a/Source/core/layout/svg/SVGTextLayoutEngine.cpp b/Source/core/layout/svg/SVGTextLayoutEngine.cpp |
index 94783b42f8659457ce1ff6f8ef673c89d7d7d1ac..36d860b289ff2f66a0434c57e9e114383caacbb1 100644 |
--- a/Source/core/layout/svg/SVGTextLayoutEngine.cpp |
+++ b/Source/core/layout/svg/SVGTextLayoutEngine.cpp |
@@ -25,6 +25,7 @@ |
#include "core/layout/svg/SVGTextChunkBuilder.h" |
#include "core/layout/svg/SVGTextLayoutEngineBaseline.h" |
#include "core/layout/svg/SVGTextLayoutEngineSpacing.h" |
+#include "core/layout/svg/line/SVGInlineFlowBox.h" |
#include "core/layout/svg/line/SVGInlineTextBox.h" |
#include "core/svg/SVGElement.h" |
#include "core/svg/SVGLengthContext.h" |
@@ -43,6 +44,7 @@ SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou |
, m_dy(0) |
, m_isVerticalText(false) |
, m_inPathLayout(false) |
+ , m_textLengthSpacingInEffect(false) |
, m_textPathCalculator(0) |
, m_textPathLength(0) |
, m_textPathCurrentOffset(0) |
@@ -140,32 +142,16 @@ void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox) |
m_currentTextFragment = SVGTextFragment(); |
} |
-bool SVGTextLayoutEngine::parentDefinesTextLength(LayoutObject* parent) const |
+void SVGTextLayoutEngine::beginTextPathLayout(SVGInlineFlowBox* flowBox) |
{ |
- LayoutObject* currentParent = parent; |
- while (currentParent) { |
- if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromLayoutObject(currentParent)) { |
- SVGLengthContext lengthContext(textContentElement); |
- if (textContentElement->lengthAdjust()->currentValue()->enumValue() == SVGLengthAdjustSpacing && textContentElement->textLengthIsSpecifiedByUser()) |
- return true; |
- } |
- |
- if (currentParent->isSVGText()) |
- return false; |
- |
- currentParent = currentParent->parent(); |
- } |
- |
- ASSERT_NOT_REACHED(); |
- return false; |
-} |
- |
-void SVGTextLayoutEngine::beginTextPathLayout(LayoutObject* object, SVGTextLayoutEngine& lineLayout) |
-{ |
- ASSERT(object); |
+ // Build text chunks for all <textPath> children, using the line layout algorithm. |
+ // This is needeed as text-anchor is just an additional startOffset for text paths. |
+ SVGTextLayoutEngine lineLayout(m_layoutAttributes); |
+ lineLayout.m_textLengthSpacingInEffect = m_textLengthSpacingInEffect; |
+ lineLayout.layoutCharactersInTextBoxes(flowBox); |
m_inPathLayout = true; |
- LayoutSVGTextPath* textPath = toLayoutSVGTextPath(object); |
+ LayoutSVGTextPath* textPath = &toLayoutSVGTextPath(flowBox->layoutObject()); |
Path path = textPath->layoutPath(); |
if (path.isEmpty()) |
@@ -238,6 +224,42 @@ void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox* textBox) |
m_lineLayoutBoxes.append(textBox); |
} |
+static bool definesTextLengthWithSpacing(const InlineFlowBox* start) |
+{ |
+ SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromLayoutObject(&start->layoutObject()); |
+ return textContentElement |
+ && textContentElement->lengthAdjust()->currentValue()->enumValue() == SVGLengthAdjustSpacing |
+ && textContentElement->textLengthIsSpecifiedByUser(); |
+} |
+ |
+void SVGTextLayoutEngine::layoutCharactersInTextBoxes(InlineFlowBox* start) |
+{ |
+ bool textLengthSpacingInEffect = m_textLengthSpacingInEffect || definesTextLengthWithSpacing(start); |
+ TemporaryChange<bool> textLengthSpacingScope(m_textLengthSpacingInEffect, textLengthSpacingInEffect); |
+ |
+ for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) { |
+ if (child->isSVGInlineTextBox()) { |
+ ASSERT(child->layoutObject().isSVGInlineText()); |
+ layoutInlineTextBox(toSVGInlineTextBox(child)); |
+ } else { |
+ // Skip generated content. |
+ Node* node = child->layoutObject().node(); |
+ if (!node) |
+ continue; |
+ |
+ SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child); |
+ bool isTextPath = isSVGTextPathElement(*node); |
+ if (isTextPath) |
+ beginTextPathLayout(flowBox); |
+ |
+ layoutCharactersInTextBoxes(flowBox); |
+ |
+ if (isTextPath) |
+ endTextPathLayout(); |
+ } |
+ } |
+} |
+ |
void SVGTextLayoutEngine::finishLayout() |
{ |
m_visualMetricsIterator = SVGInlineTextMetricsIterator(); |
@@ -316,9 +338,6 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, cons |
if (m_inPathLayout && !m_textPathCalculator) |
return; |
- LayoutObject* textParent = text.parent(); |
- bool definesTextLength = textParent ? parentDefinesTextLength(textParent) : false; |
- |
const SVGComputedStyle& svgStyle = style.svgStyle(); |
// Find the start of the current text box in the metrics list. |
@@ -454,7 +473,7 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, cons |
// Determine whether we have to start a new fragment. |
bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPathLayout || angle || angle != lastAngle |
- || orientationAngle || applySpacingToNextCharacter || definesTextLength; |
+ || orientationAngle || applySpacingToNextCharacter || m_textLengthSpacingInEffect; |
// If we already started a fragment, close it now. |
if (didStartTextFragment && shouldStartNewFragment) { |