AffineTransform SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject& renderer)
{
    AffineTransform absoluteTransform = currentContentTransformation();

    float deviceScaleFactor = renderer.document().deviceScaleFactor();
    // Walk up the render tree, accumulating SVG transforms.
    const RenderObject* ancestor = &renderer;
    while (ancestor) {
        absoluteTransform = ancestor->localToParentTransform() * absoluteTransform;
        if (ancestor->isSVGRoot())
            break;
        ancestor = ancestor->parent();
    }

    // Continue walking up the layer tree, accumulating CSS transforms.
    RenderLayer* layer = ancestor ? ancestor->enclosingLayer() : nullptr;
    while (layer) {
        if (TransformationMatrix* layerTransform = layer->transform())
            absoluteTransform = layerTransform->toAffineTransform() * absoluteTransform;

        // We can stop at compositing layers, to match the backing resolution.
        if (layer->isComposited())
            break;

        layer = layer->parent();
    }

    absoluteTransform.scale(deviceScaleFactor);
    return absoluteTransform;
}
void SVGImageBufferTools::renderSubtreeToImageBuffer(ImageBuffer* image, RenderObject* item, const AffineTransform& subtreeContentTransformation)
{
    ASSERT(item);
    ASSERT(image);
    ASSERT(image->context());

    PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, 0, 0, 0);

    RenderSVGContainer* svgContainer = 0;
    if (item && item->isSVGContainer() && !item->isSVGViewportContainer())
        svgContainer = toRenderSVGContainer(item);

    bool drawsContents = svgContainer ? svgContainer->drawsContents() : false;
    if (svgContainer && !drawsContents)
        svgContainer->setDrawsContents(true);

    AffineTransform& contentTransformation = currentContentTransformation();
    AffineTransform savedContentTransformation = contentTransformation;
    contentTransformation.multiply(subtreeContentTransformation);

    item->layoutIfNeeded();
    item->paint(info, 0, 0);

    contentTransformation = savedContentTransformation;

    if (svgContainer && !drawsContents)
        svgContainer->setDrawsContents(false);
}
Beispiel #3
0
void SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform)
{
    const RenderObject* current = renderer;
    ASSERT(current);

    absoluteTransform = currentContentTransformation();
    while (current) {
        absoluteTransform = current->localToParentTransform() * absoluteTransform;
        if (current->isSVGRoot())
            break;
        current = current->parent();
    }
}
Beispiel #4
0
void SVGImageBufferTools::clipToImageBuffer(GraphicsContext* context, const AffineTransform& absoluteTransform, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>& imageBuffer)
{
    ASSERT(context);
    ASSERT(imageBuffer);

    // The mask image has been created in the absolute coordinate space, as the image should not be scaled.
    // So the actual masking process has to be done in the absolute coordinate space as well.
    context->concatCTM(absoluteTransform.inverse());
    context->clipToImageBuffer(imageBuffer.get(), clampedAbsoluteTargetRect);
    context->concatCTM(absoluteTransform);

    // When nesting resources, with objectBoundingBox as content unit types, there's no use in caching the
    // resulting image buffer as the parent resource already caches the result.
    if (!currentContentTransformation().isIdentity())
        imageBuffer.clear();
}
void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderElement& item, const AffineTransform& subtreeContentTransformation)
{
    ASSERT(image);

    // Rendering into a buffer implies we're being used for masking, clipping, patterns or filters. In each of these
    // cases we don't want to paint the selection.
    PaintInfo info(image->context(), LayoutRect::infiniteRect(), PaintPhaseForeground, PaintBehaviorSkipSelectionHighlight);

    AffineTransform& contentTransformation = currentContentTransformation();
    AffineTransform savedContentTransformation = contentTransformation;
    contentTransformation = subtreeContentTransformation * contentTransformation;

    ASSERT(!item.needsLayout());
    item.paint(info, IntPoint());

    contentTransformation = savedContentTransformation;
}
Beispiel #6
0
void SVGImageBufferTools::renderSubtreeToImageBuffer(ImageBuffer* image, RenderObject* item, const AffineTransform& subtreeContentTransformation)
{
    ASSERT(item);
    ASSERT(image);
    ASSERT(image->context());

    PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, 0, 0, 0, 0);

    AffineTransform& contentTransformation = currentContentTransformation();
    AffineTransform savedContentTransformation = contentTransformation;
    contentTransformation = subtreeContentTransformation * contentTransformation;

    item->layoutIfNeeded();
    item->paint(info, IntPoint());

    contentTransformation = savedContentTransformation;
}
void SVGRenderingContext::clipToImageBuffer(GraphicsContext& context, const AffineTransform& absoluteTransform, const FloatRect& targetRect, std::unique_ptr<ImageBuffer>& imageBuffer, bool safeToClear)
{
    if (!imageBuffer)
        return;

    FloatRect absoluteTargetRect = calculateImageBufferRect(targetRect, absoluteTransform);

    // The mask image has been created in the absolute coordinate space, as the image should not be scaled.
    // So the actual masking process has to be done in the absolute coordinate space as well.
    context.concatCTM(absoluteTransform.inverse().valueOr(AffineTransform()));
    context.clipToImageBuffer(*imageBuffer, absoluteTargetRect);
    context.concatCTM(absoluteTransform);

    // When nesting resources, with objectBoundingBox as content unit types, there's no use in caching the
    // resulting image buffer as the parent resource already caches the result.
    if (safeToClear && !currentContentTransformation().isIdentity())
        imageBuffer.reset();
}