diff options
Diffstat (limited to 'Source/WebCore/rendering/svg/SVGRootInlineBox.cpp')
-rw-r--r-- | Source/WebCore/rendering/svg/SVGRootInlineBox.cpp | 102 |
1 files changed, 99 insertions, 3 deletions
diff --git a/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp b/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp index c2289d6..ddbd3ea 100644 --- a/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp +++ b/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp @@ -25,8 +25,8 @@ #if ENABLE(SVG) #include "GraphicsContext.h" -#include "RenderBlock.h" #include "RenderSVGInlineText.h" +#include "RenderSVGText.h" #include "SVGInlineFlowBox.h" #include "SVGInlineTextBox.h" #include "SVGNames.h" @@ -73,8 +73,15 @@ void SVGRootInlineBox::paint(PaintInfo& paintInfo, int, int) void SVGRootInlineBox::computePerCharacterLayoutInformation() { + RenderSVGText* parentBlock = toRenderSVGText(block()); + ASSERT(parentBlock); + + Vector<SVGTextLayoutAttributes>& attributes = parentBlock->layoutAttributes(); + if (parentBlock->needsReordering()) + reorderValueLists(attributes); + // Perform SVG text layout phase two (see SVGTextLayoutEngine for details). - SVGTextLayoutEngine characterLayout; + SVGTextLayoutEngine characterLayout(attributes); layoutCharactersInTextBoxes(this, characterLayout); // Perform SVG text layout phase three (see SVGTextChunkBuilder for details). @@ -108,8 +115,12 @@ void SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGText if (isTextPath) { // 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; + RenderSVGText* parentBlock = toRenderSVGText(block()); + ASSERT(parentBlock); + + SVGTextLayoutEngine lineLayout(parentBlock->layoutAttributes()); layoutCharactersInTextBoxes(flowBox, lineLayout); + characterLayout.beginTextPathLayout(child->renderer(), lineLayout); } @@ -215,6 +226,91 @@ InlineBox* SVGRootInlineBox::closestLeafChildForPosition(const IntPoint& point) return closestLeaf ? closestLeaf : lastLeaf; } + +static inline void swapItemsInVector(Vector<float>& firstVector, Vector<float>& lastVector, unsigned first, unsigned last) +{ + float temp = firstVector.at(first); + firstVector.at(first) = lastVector.at(last); + lastVector.at(last) = temp; +} + +static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes& firstAttributes, SVGTextLayoutAttributes& lastAttributes, unsigned firstPosition, unsigned lastPosition) +{ + swapItemsInVector(firstAttributes.xValues(), lastAttributes.xValues(), firstPosition, lastPosition); + swapItemsInVector(firstAttributes.yValues(), lastAttributes.yValues(), firstPosition, lastPosition); + swapItemsInVector(firstAttributes.dxValues(), lastAttributes.dxValues(), firstPosition, lastPosition); + swapItemsInVector(firstAttributes.dyValues(), lastAttributes.dyValues(), firstPosition, lastPosition); + swapItemsInVector(firstAttributes.rotateValues(), lastAttributes.rotateValues(), firstPosition, lastPosition); +} + +static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes>& attributes, RenderSVGInlineText* firstContext, RenderSVGInlineText* lastContext, + SVGTextLayoutAttributes*& first, SVGTextLayoutAttributes*& last) +{ + first = 0; + last = 0; + + unsigned attributesSize = attributes.size(); + for (unsigned i = 0; i < attributesSize; ++i) { + SVGTextLayoutAttributes& current = attributes.at(i); + if (!first && firstContext == current.context()) + first = ¤t; + if (!last && lastContext == current.context()) + last = ¤t; + if (first && last) + break; + } + + ASSERT(first); + ASSERT(last); +} + +static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last) +{ + ASSERT(userData); + Vector<SVGTextLayoutAttributes>& attributes = *reinterpret_cast<Vector<SVGTextLayoutAttributes>*>(userData); + + // This is a copy of std::reverse(first, last). It additionally assure that the value lists within the InlineBoxes are reordered as well. + while (true) { + if (first == last || first == --last) + return; + + ASSERT((*first)->isSVGInlineTextBox()); + ASSERT((*last)->isSVGInlineTextBox()); + + SVGInlineTextBox* firstTextBox = static_cast<SVGInlineTextBox*>(*first); + SVGInlineTextBox* lastTextBox = static_cast<SVGInlineTextBox*>(*last); + + // Reordering is only necessary for BiDi text that is _absolutely_ positioned. + if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) { + RenderSVGInlineText* firstContext = toRenderSVGInlineText(firstTextBox->textRenderer()); + RenderSVGInlineText* lastContext = toRenderSVGInlineText(lastTextBox->textRenderer()); + + SVGTextLayoutAttributes* firstAttributes = 0; + SVGTextLayoutAttributes* lastAttributes = 0; + findFirstAndLastAttributesInVector(attributes, firstContext, lastContext, firstAttributes, lastAttributes); + + unsigned firstBoxPosition = firstTextBox->start(); + unsigned firstBoxEnd = firstTextBox->end(); + + unsigned lastBoxPosition = lastTextBox->start(); + unsigned lastBoxEnd = lastTextBox->end(); + for (; firstBoxPosition <= firstBoxEnd && lastBoxPosition <= lastBoxEnd; ++lastBoxPosition, ++firstBoxPosition) + swapItemsInLayoutAttributes(*firstAttributes, *lastAttributes, firstBoxPosition, lastBoxPosition); + } + + InlineBox* temp = *first; + *first = *last; + *last = temp; + + ++first; + } +} + +void SVGRootInlineBox::reorderValueLists(Vector<SVGTextLayoutAttributes>& attributes) +{ + Vector<InlineBox*> leafBoxesInLogicalOrder; + collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder, reverseInlineBoxRangeAndValueListsIfNeeded, &attributes); +} } // namespace WebCore |