Пример #1
0
void SVGTextLayoutAttributesBuilder::buildLayoutScope(LayoutScope& scope, RenderObject* renderer, unsigned textContentStart, unsigned textContentLength) const
{
    ASSERT(renderer);
    ASSERT(renderer->style());

    scope.textContentStart = textContentStart;
    scope.textContentLength = textContentLength;

    SVGTextPositioningElement* element = SVGTextPositioningElement::elementFromRenderer(renderer);
    if (!element)
        return;

    SVGTextLayoutAttributes& attributes = scope.attributes;
    extractFloatValuesFromSVGLengthList(element, element->x(), attributes.xValues(), textContentLength);
    extractFloatValuesFromSVGLengthList(element, element->y(), attributes.yValues(), textContentLength);
    extractFloatValuesFromSVGLengthList(element, element->dx(), attributes.dxValues(), textContentLength);
    extractFloatValuesFromSVGLengthList(element, element->dy(), attributes.dyValues(), textContentLength);
    extractFloatValuesFromSVGNumberList(element->rotate(), attributes.rotateValues(), textContentLength);

    // The last rotation value spans the whole scope.
    Vector<float>& rotateValues = attributes.rotateValues();
    if (rotateValues.isEmpty())
        return;

    unsigned rotateValuesSize = rotateValues.size();
    if (rotateValuesSize == textContentLength)
        return;

    float lastRotation = rotateValues.last();

    rotateValues.resize(textContentLength);
    for (unsigned i = rotateValuesSize; i < textContentLength; ++i)
        rotateValues.at(i) = lastRotation;
}
Пример #2
0
static bool translateBox(InlineBox* box, int x, int y, bool topLevel)
{
    if (box->object()->isText()) {
        box->setXPos(box->xPos() + x);
        box->setYPos(box->yPos() + y);
    } else if (!box->object()->element()->hasTagName(aTag)) {
        InlineFlowBox* flow = static_cast<InlineFlowBox*>(box);
        SVGTextPositioningElement* text = static_cast<SVGTextPositioningElement*>(box->object()->element());

        if (topLevel || !(text->x()->getFirst().value() || text->y()->getFirst().value() ||
                          text->dx()->getFirst().value() || text->dy()->getFirst().value())) {
            box->setXPos(box->xPos() + x);
            box->setYPos(box->yPos() + y);
            for (InlineBox* curr = flow->firstChild(); curr; curr = curr->nextOnLine()) {
                if (!translateBox(curr, x, y, false))
                    return false;
            }
        }
    }
    return true;
}
Пример #3
0
static int placePositionedBoxesHorizontally(InlineFlowBox* flow, int x, int& leftPosition, int& rightPosition, int& leftAlign, int& rightAlign, bool& needsWordSpacing, int xPos, bool positioned)
{
    int mn = INT_MAX;
    int mx = INT_MIN;
    int amn = INT_MAX;
    int amx = INT_MIN;
    int startx = x;
    bool seenPositionedElement = false;
    flow->setXPos(x);
    for (InlineBox* curr = flow->firstChild(); curr; curr = curr->nextOnLine()) {
        if (curr->object()->isText()) {
            mn = min(mn, x);
            amn = min(amn, x);
            InlineTextBox* text = static_cast<InlineTextBox*>(curr);
            RenderText* rt = static_cast<RenderText*>(text->object());
            if (rt->textLength()) {
                if (needsWordSpacing && DeprecatedChar(rt->characters()[text->start()]).isSpace())
                    x += rt->style(flow->isFirstLineStyle())->font().wordSpacing();
                needsWordSpacing = !DeprecatedChar(rt->characters()[text->end()]).isSpace();
            }
            text->setXPos(x);
            x += text->width();
            mx = max(mx, x);
            amx = max(amx, x);
        } else if (curr->object()->isInlineFlow()) {
            InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
            if (flow->object()->element()->hasTagName(aTag)) {
                x = placePositionedBoxesHorizontally(flow, x, mn, mx, amn, amx, needsWordSpacing, xPos, false);
            } else {
                SVGTextPositioningElement* text = static_cast<SVGTextPositioningElement*>(flow->object()->element());
                x += (int)(text->dx()->getFirst().value());
                if (text->x()->numberOfItems() > 0)
                    x = (int)(text->x()->getFirst().value() - xPos);
                if (text->x()->numberOfItems() > 0 || text->y()->numberOfItems() > 0 ||
                    text->dx()->numberOfItems() > 0 || text->dy()->numberOfItems() > 0) {
                    seenPositionedElement = true;
                    needsWordSpacing = false;
                    int ignoreX, ignoreY;
                    x = placePositionedBoxesHorizontally(flow, x, mn, mx, ignoreX, ignoreY, needsWordSpacing, xPos, true);
                } else if (seenPositionedElement) {
                    int ignoreX, ignoreY;
                    x = placePositionedBoxesHorizontally(flow, x, mn, mx, ignoreX, ignoreY, needsWordSpacing, xPos, false);
                } else
                    x = placePositionedBoxesHorizontally(flow, x, mn, mx, amn, amx, needsWordSpacing, xPos, false);
            }
        }
    }

    if (mn > mx)
        mn = mx = startx;
    if (amn > amx)
        amn = amx = startx;

    int width = mx - mn;
    flow->setWidth(width);

    int awidth = amx - amn;
    int dx = 0;
    if (positioned) {
        switch (flow->object()->style()->svgStyle()->textAnchor()) {
            case TA_MIDDLE:
                translateBox(flow, dx = -awidth / 2, 0, true);
                break;
            case TA_END:
                translateBox(flow, dx = -awidth, 0, true);
                break;
            case TA_START:
            default:
                break;
        }

        if (dx) {
            x += dx;
            mn += dx;
            mx += dx;
        }
    }

    leftPosition = min(leftPosition, mn);
    rightPosition = max(rightPosition, mx);
    leftAlign = min(leftAlign, amn);
    rightAlign = max(rightAlign, amx);

    return x;
}