Exemple #1
0
/**
 * Traverses the horizontal inline boxes and appends the point coordinates to
 * the given array.
 * @param box inline box
 * @param pointArray array collecting coordinates
 * @param bottom \c true, collect bottom coordinates, \c false, collect top
 * 	coordinates.
 * @param limit lower limit that an y-coordinate must at least reach. Note
 *	that limit designates the highest y-coordinate for \c bottom, and
 *	the lowest for !\c bottom.
 */
static void collectHorizontalBoxCoordinates(InlineBox *box, QValueVector< QPoint > &pointArray, bool bottom, int offset, int limit = -500000)
{
    //   kdDebug(6000) << "collectHorizontalBoxCoordinates: " << endl;
    offset = bottom ? offset : -offset;
    int y = box->yPos() + bottom * box->height() + offset;
    if(limit != -500000 && (bottom ? y < limit : y > limit))
        y = limit;
    int x = box->xPos() + bottom * box->width() + offset;
    QPoint newPnt(x, y);
    // Add intersection point if point-array not empty.
    if(!pointArray.isEmpty())
    {
        QPoint lastPnt = pointArray.back();
        QPoint insPnt(newPnt.x(), lastPnt.y());
        if(offset && ((bottom && lastPnt.y() > y) || (!bottom && lastPnt.y() < y)))
        {
            insPnt.rx() = lastPnt.x();
            insPnt.ry() = y;
        }
        //         kdDebug(6040) << "left: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl;
        appendPoint(pointArray, insPnt);
    }
    // Insert starting point of box
    appendPoint(pointArray, newPnt);

    newPnt.rx() += (bottom ? -box->width() : box->width()) - 2 * offset;

    if(box->isInlineFlowBox())
    {
        InlineFlowBox *flowBox = static_cast< InlineFlowBox * >(box);
        for(InlineBox *b = bottom ? flowBox->lastChild() : flowBox->firstChild(); b; b = bottom ? b->prevOnLine() : b->nextOnLine())
        {
            // Don't let boxes smaller than this flow box' height influence
            // the vertical position of the outline if they have a different
            // x-coordinate
            int l2;
            if(b->xPos() != box->xPos() && b->xPos() + b->width() != box->xPos() + box->width())
                l2 = y;
            else
                l2 = limit;
            collectHorizontalBoxCoordinates(b, pointArray, bottom, kAbs(offset), l2);
        }

        // Add intersection point if flow box contained any children
        if(flowBox->firstChild())
        {
            QPoint lastPnt = pointArray.back();
            QPoint insPnt(lastPnt.x(), newPnt.y());
            //             kdDebug(6040) << "right: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl;
            appendPoint(pointArray, insPnt);
        }
    }

    // Insert ending point of box
    appendPoint(pointArray, newPnt);

    //     kdDebug(6000) << "collectHorizontalBoxCoordinates: " << "ende" << endl;
}
Exemple #2
0
FloatRect RenderSVGText::relativeBBox(bool includeStroke) const
{
    FloatRect repaintRect;

    for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
        ASSERT(runBox->isInlineFlowBox());

        InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
        for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine())
            repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height()));
    }

    // SVG needs to include the strokeWidth(), not the textStrokeWidth().
    if (includeStroke && style()->svgStyle()->hasStroke()) {
        float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0f);

#if ENABLE(SVG_FONTS)
        const Font& font = style()->font();
        if (font.primaryFont()->isSVGFont()) {
            float scale = font.unitsPerEm() > 0 ? font.size() / font.unitsPerEm() : 0.0f;

            if (scale != 0.0f)
                strokeWidth /= scale;
        }
#endif

        repaintRect.inflate(strokeWidth);
    }

    repaintRect.move(xPos(), yPos());
    return repaintRect;
}
FloatRect RenderSVGText::objectBoundingBox() const
{
    FloatRect boundingBox;

    for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) {
        for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine())
            boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height()));
    }

    boundingBox.move(x(), y());
    return boundingBox;
}
FloatRect RenderSVGText::objectBoundingBox() const
{
    FloatRect boundingBox;

    for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
        ASSERT(runBox->isInlineFlowBox());

        InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
        for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine())
            boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height()));
    }

    boundingBox.move(x(), y());
    return boundingBox;
}
void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads)
{
    RenderSVGRoot* root = findSVGRootObject(parent());
    if (!root)
        return;
 
    // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard
    // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
    for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) {
        for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) {
            FloatRect boxRect(box->x(), box->y(), box->width(), box->height());
            // FIXME: crawling up the parent chain to map each quad is very inefficient
            // we should compute the absoluteTransform outside this loop first.
            quads.append(localToAbsoluteQuad(boxRect));
        }
    }
}
FloatRect RenderSVGText::relativeBBox(bool includeStroke) const
{
    FloatRect repaintRect;

    for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
        ASSERT(runBox->isInlineFlowBox());

        InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
        for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine())
            repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height()));
    }

    // SVG needs to include the strokeWidth(), not the textStrokeWidth().
    if (includeStroke && style()->svgStyle()->hasStroke())
        repaintRect.inflate(narrowPrecisionToFloat(KSVGPainterFactory::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0)));

    repaintRect.move(xPos(), yPos());
    return repaintRect;
}
void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int)
{
    RenderSVGRoot* root = findSVGRootObject(parent());
    if (!root)
        return;
 
    // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard
    // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
    for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
        ASSERT(runBox->isInlineFlowBox());

        InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
        for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) {
            FloatRect boxRect(box->x(), box->y(), box->width(), box->height());
            // FIXME: crawling up the parent chain to map each rect is very inefficient
            // we should compute the absoluteTransform outside this loop first.
            rects.append(enclosingIntRect(localToAbsoluteQuad(boxRect).boundingBox()));
        }
    }
}
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;
}
void RenderFlow::detach()
{
    if (!documentBeingDestroyed()) {
        if (m_firstLineBox) {
            // We can't wait for RenderContainer::detach to clear the selection,
            // because by then we will have nuked the line boxes.
            if (isSelectionBorder())
                canvas()->clearSelection();

            // If line boxes are contained inside a root, that means we're an inline.
            // In that case, we need to remove all the line boxes so that the parent
            // lines aren't pointing to deleted children. If the first line box does
            // not have a parent that means they are either already disconnected or
            // root lines that can just be destroyed without disconnecting.
            if (m_firstLineBox->parent()) {
                for (InlineRunBox* box = m_firstLineBox; box; box = box->nextLineBox())
                    box->remove();
            }

            // If we are an anonymous block, then our line boxes might have children
            // that will outlast this block. In the non-anonymous block case those
            // children will be destroyed by the time we return from this function.
            if (isAnonymousBlock()) {
                for (InlineFlowBox* box = m_firstLineBox; box; box = box->nextFlowBox()) {
                    while (InlineBox *childBox = box->firstChild()) {
                        childBox->remove();
                    }
                }
            }
        }
        else if (isInline() && parent())
            parent()->dirtyLinesFromChangedChild(this, false);
    }

    deleteLineBoxes();

    RenderContainer::detach();
}
Exemple #10
0
void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
{
    RenderSVGRoot* root = findSVGRootObject(parent());
    if (!root)
        return;

    int x, y;
    absolutePosition(x, y);

    AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
 
    // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard
    // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
    for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
        ASSERT(runBox->isInlineFlowBox());

        InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
        for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) {
            FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height());
            boxRect.move(narrowPrecisionToFloat(x - htmlParentCtm.e()), narrowPrecisionToFloat(y - htmlParentCtm.f()));
            rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect)));
        }
    }
}