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);
}
Ejemplo n.º 5
0
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);
}