void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderBoxModelObject& start, bool& lastCharacterWasSpace) { ASSERT(!is<RenderSVGText>(start) || m_textPositions.isEmpty()); for (RenderObject* child = start.firstChild(); child; child = child->nextSibling()) { if (is<RenderSVGInlineText>(*child)) { processRenderSVGInlineText(downcast<RenderSVGInlineText>(*child), m_textLength, lastCharacterWasSpace); continue; } if (!is<RenderSVGInline>(*child)) continue; RenderSVGInline& inlineChild = downcast<RenderSVGInline>(*child); SVGTextPositioningElement* element = SVGTextPositioningElement::elementFromRenderer(inlineChild); unsigned atPosition = m_textPositions.size(); if (element) m_textPositions.append(TextPosition(element, m_textLength)); collectTextPositioningElements(inlineChild, lastCharacterWasSpace); if (!element) continue; // Update text position, after we're back from recursion. TextPosition& position = m_textPositions[atPosition]; ASSERT(!position.length); position.length = m_textLength - position.start; } }
void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject* start, bool& lastCharacterWasSpace) { ASSERT(!start->isSVGText() || m_textPositions.isEmpty()); for (RenderObject* child = start->firstChildSlow(); child; child = child->nextSibling()) { if (child->isSVGInlineText()) { processRenderSVGInlineText(*toRenderSVGInlineText(child), m_textLength, lastCharacterWasSpace); continue; } if (!child->isSVGInline()) continue; SVGTextPositioningElement* element = SVGTextPositioningElement::elementFromRenderer(child); unsigned atPosition = m_textPositions.size(); if (element) m_textPositions.append(TextPosition(element, m_textLength)); collectTextPositioningElements(child, lastCharacterWasSpace); if (!element) continue; // Update text position, after we're back from recursion. TextPosition& position = m_textPositions[atPosition]; ASSERT(!position.length); position.length = m_textLength - position.start; } }
bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSVGText& textRoot) { m_characterDataMap.clear(); if (m_textPositions.isEmpty()) { m_textLength = 0; bool lastCharacterWasSpace = true; collectTextPositioningElements(textRoot, lastCharacterWasSpace); } if (!m_textLength) return false; buildCharacterDataMap(textRoot); m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, nullptr, m_characterDataMap); return true; }
void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(RenderSVGInlineText& text) { auto* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text); if (!textRoot) return; if (m_textPositions.isEmpty()) { m_characterDataMap.clear(); m_textLength = 0; bool lastCharacterWasSpace = true; collectTextPositioningElements(*textRoot, lastCharacterWasSpace); if (!m_textLength) return; buildCharacterDataMap(*textRoot); } m_metricsBuilder.buildMetricsAndLayoutAttributes(*textRoot, &text, m_characterDataMap); }
void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextSubtree(RenderSVGText* textRoot) { ASSERT(textRoot); // We always clear our current attribute as we don't want to keep any stale ones that could survive DOM modification. Vector<SVGTextLayoutAttributes>& allAttributes = textRoot->layoutAttributes(); allAttributes.clear(); // Build list of x/y/dx/dy/rotate values for each subtree element that may define these values (tspan/textPath etc). unsigned atCharacter = 0; UChar lastCharacter = '\0'; collectTextPositioningElements(textRoot, atCharacter, lastCharacter); if (!atCharacter) return; // Collect x/y/dx/dy/rotate values for each character, stored in the m_positioningLists.xValues()/etc. lists. buildLayoutAttributesForAllCharacters(textRoot, atCharacter); // Propagate layout attributes to each RenderSVGInlineText object, and the whole list to the RenderSVGText root. atCharacter = 0; lastCharacter = '\0'; propagateLayoutAttributes(textRoot, allAttributes, atCharacter, lastCharacter); }