Example #1
0
SVGResource* getResourceById(Document* document, const AtomicString& id)
{
    if (id.isEmpty())
        return 0;

    Element* element = document->getElementById(id);
    SVGElement* svgElement = 0;
    if (element && element->isSVGElement())
        svgElement = static_cast<SVGElement*>(element);

    if (svgElement && svgElement->isStyled())
        return static_cast<SVGStyledElement*>(svgElement)->canvasResource();

    return 0;
}
Example #2
0
void RenderSVGResource::markForLayoutAndResourceInvalidation(RenderObject* object)
{
    ASSERT(object);
    ASSERT(object->node());
    ASSERT(object->node()->isSVGElement());

    // Mark the renderer for layout
    object->setNeedsLayout(true);

    // Notify any resources in the ancestor chain, that we've been invalidated
    SVGElement* element = static_cast<SVGElement*>(object->node());
    if (!element->isStyled())
        return;

    static_cast<SVGStyledElement*>(element)->invalidateResourcesInAncestorChain();
}
Example #3
0
void FEImage::platformApplySoftware()
{
    RenderObject* renderer = referencedRenderer();
    if (!m_image && !renderer)
        return;

    ImageBuffer* resultImage = createImageBufferResult();
    if (!resultImage)
        return;

    SVGFilter* svgFilter = static_cast<SVGFilter*>(filter());
    FloatRect destRect = svgFilter->absoluteTransform().mapRect(filterPrimitiveSubregion());

    FloatRect srcRect;
    if (renderer)
        srcRect = svgFilter->absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates());
    else {
        srcRect = FloatRect(FloatPoint(), m_image->size());
        m_preserveAspectRatio.transformRect(destRect, srcRect);
    }

    IntPoint paintLocation = absolutePaintRect().location();
    destRect.move(-paintLocation.x(), -paintLocation.y());

    if (renderer) {
        const AffineTransform& absoluteTransform = svgFilter->absoluteTransform();
        resultImage->context()->concatCTM(absoluteTransform);

        SVGElement* contextNode = static_cast<SVGElement*>(renderer->node());
        if (contextNode->isStyled() && static_cast<SVGStyledElement*>(contextNode)->hasRelativeLengths()) {
            SVGLengthContext lengthContext(contextNode);
            float width = 0;
            float height = 0;

            // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport.
            // Build up a transformation that maps from the viewport space to the filter primitive subregion.
            if (lengthContext.determineViewport(width, height))
                resultImage->context()->concatCTM(makeMapBetweenRects(FloatRect(0, 0, width, height), destRect));
        }

        AffineTransform contentTransformation;
        SVGRenderingContext::renderSubtreeToImageBuffer(resultImage, renderer, contentTransformation);
        return;
    }

    resultImage->context()->drawImage(m_image.get(), ColorSpaceDeviceRGB, destRect, srcRect);
}
Example #4
0
bool SVGUseElement::selfHasRelativeLengths() const
{
    if (x().isRelative()
     || y().isRelative()
     || width().isRelative()
     || height().isRelative())
        return true;

    if (!m_targetElementInstance)
        return false;

    SVGElement* element = m_targetElementInstance->correspondingElement();
    if (!element || !element->isStyled())
        return false;

    return static_cast<SVGStyledElement*>(element)->hasRelativeLengths();
}
void SVGStyledElement::invalidateResourcesInAncestorChain() const
{
    Node* node = parentNode();
    while (node) {
        if (!node->isSVGElement())
            break;

        SVGElement* element = static_cast<SVGElement*>(node);
        if (SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element->isStyled() ? element : 0)) {
            styledElement->invalidateResourceClients();

            // If we found the first resource in the ancestor chain, immediately stop.
            break;
        }

        node = node->parentNode();
    }
}
Example #6
0
void RenderPath::calculateMarkerBoundsIfNeeded() const
{
    Document* doc = document();

    SVGElement* svgElement = static_cast<SVGElement*>(node());
    ASSERT(svgElement && svgElement->document());
    if (!svgElement->isStyled())
        return;

    SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
    if (!styledElement->supportsMarkers())
        return;

    const SVGRenderStyle* svgStyle = style()->svgStyle();
    AtomicString startMarkerId(svgStyle->startMarker());
    AtomicString midMarkerId(svgStyle->midMarker());
    AtomicString endMarkerId(svgStyle->endMarker());

    SVGResourceMarker* startMarker = getMarkerById(doc, startMarkerId, this);
    SVGResourceMarker* midMarker = getMarkerById(doc, midMarkerId, this);
    SVGResourceMarker* endMarker = getMarkerById(doc, endMarkerId, this);

    if (!startMarker && !startMarkerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(startMarkerId, styledElement);
    else if (startMarker)
        startMarker->addClient(styledElement);

    if (!midMarker && !midMarkerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(midMarkerId, styledElement);
    else if (midMarker)
        midMarker->addClient(styledElement);

    if (!endMarker && !endMarkerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(endMarkerId, styledElement);
    else if (endMarker)
        endMarker->addClient(styledElement);

    if (!startMarker && !midMarker && !endMarker)
        return;

    float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, svgStyle->strokeWidth(), 1.0f);
    m_cachedLocalMarkerBBox = m_markerLayoutInfo.calculateBoundaries(startMarker, midMarker, endMarker, strokeWidth, m_path);
}
static void getElementCTM(SVGElement* element, AffineTransform& transform)
{
    ASSERT(element);
    element->document()->updateLayoutIgnorePendingStylesheets();

    SVGElement* stopAtElement = SVGLocatable::nearestViewportElement(element);
    ASSERT(stopAtElement);

    Node* current = element;
    while (current && current->isSVGElement()) {
        SVGElement* currentElement = static_cast<SVGElement*>(current);
        if (currentElement->isStyled())
            transform = const_cast<AffineTransform&>(currentElement->renderer()->localToParentTransform()).multiply(transform);

        // For getCTM() computation, stop at the nearest viewport element
        if (currentElement == stopAtElement)
            break;

        current = current->parentOrHostNode();
    }
}
Example #8
0
SVGPaintServer* SVGPaintServer::fillPaintServer(const RenderStyle* style, const RenderObject* item)
{
    if (!style->svgStyle()->hasFill())
        return 0;

    SVGPaint* fill = style->svgStyle()->fillPaint();

    SVGPaintServer* fillPaintServer = 0;
    SVGPaint::SVGPaintType paintType = fill->paintType();
    if (paintType == SVGPaint::SVG_PAINTTYPE_URI ||
        paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR) {
        AtomicString id(SVGURIReference::getTarget(fill->uri()));
        fillPaintServer = getPaintServerById(item->document(), id);

        SVGElement* svgElement = static_cast<SVGElement*>(item->node());
        ASSERT(svgElement && svgElement->document() && svgElement->isStyled());

        if (item->isRenderPath() && fillPaintServer)
            fillPaintServer->addClient(static_cast<SVGStyledElement*>(svgElement));
        else if (!fillPaintServer && paintType == SVGPaint::SVG_PAINTTYPE_URI)
            svgElement->document()->accessSVGExtensions()->addPendingResource(id, static_cast<SVGStyledElement*>(svgElement)); 
    }
    if (paintType != SVGPaint::SVG_PAINTTYPE_URI && !fillPaintServer) {
        fillPaintServer = sharedSolidPaintServer();
        SVGPaintServerSolid* fillPaintServerSolid = static_cast<SVGPaintServerSolid*>(fillPaintServer);
        if (paintType == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR)
            fillPaintServerSolid->setColor(style->color());
        else
            fillPaintServerSolid->setColor(fill->color());
        // FIXME: Ideally invalid colors would never get set on the RenderStyle and this could turn into an ASSERT
        if (!fillPaintServerSolid->color().isValid())
            fillPaintServer = 0;
    }
    if (!fillPaintServer) {
        // default value (black), see bug 11017
        fillPaintServer = sharedSolidPaintServer();
        static_cast<SVGPaintServerSolid*>(fillPaintServer)->setColor(Color::black);
    }
    return fillPaintServer;
}
Example #9
0
// FIXME: This funtion will eventually become part of the AnimationCompositor
void SVGTimer::applyAnimations(double elapsedSeconds, const SVGTimer::TargetAnimationMap& targetMap)
{    
    TargetAnimationMap::const_iterator targetIterator = targetMap.begin();
    TargetAnimationMap::const_iterator tend = targetMap.end();
    for (; targetIterator != tend; ++targetIterator) {
        // FIXME: This is still not 100% correct.  Correct would be:
        // 1. Walk backwards through the priority list until a replace (!isAdditive()) is found
        // -- This optimization is not possible without careful consideration for dependent values (such as cx and fx in SVGRadialGradient)
        // 2. Set the initial value (or last replace) as the new animVal
        // 3. Call each enabled animation in turn, to have it apply its changes
        // 4. After building a new animVal, set it on the element.
        
        // Currenly we use the actual animVal on the element as "temporary storage"
        // and abstract the getting/setting of the attributes into the SVGAnimate* classes
        
        unsigned count = targetIterator->second.size();
        for (unsigned i = 0; i < count; ++i) {
            SVGAnimationElement* animation = targetIterator->second[i];
            
            if (!animation->isValidAnimation())
                continue;
            
            if (!animation->updateAnimationBaseValueFromElement())
                continue;
            
            if (!animation->updateAnimatedValueForElapsedSeconds(elapsedSeconds))
                continue;
            
            animation->applyAnimatedValueToElement();
        }
    }
    
    // Make a second pass through the map to avoid multiple setChanged calls on the same element.
    for (targetIterator = targetMap.begin(); targetIterator != tend; ++targetIterator) {
        SVGElement* key = targetIterator->first;
        if (key && key->isStyled())
            static_cast<SVGStyledElement*>(key)->setChanged(true);
    }
}
Example #10
0
void SVGStyledElement::updateRelativeLengthsInformation(bool hasRelativeLengths, SVGStyledElement* element)
{
    // If we're not yet in a document, this function will be called again from insertedIntoDocument(). Do nothing now.
    if (!inDocument())
        return;

    // An element wants to notify us that its own relative lengths state changed.
    // Register it in the relative length map, and register us in the parent relative length map.
    // Register the parent in the grandparents map, etc. Repeat procedure until the root of the SVG tree.

    if (hasRelativeLengths)
        m_elementsWithRelativeLengths.add(element);
    else {
        if (!m_elementsWithRelativeLengths.contains(element)) {
            // We were never registered. Do nothing.
            return;
        }

        m_elementsWithRelativeLengths.remove(element);
    }

    // Find first styled parent node, and notify it that we've changed our relative length state.
    Node* node = parent();
    while (node) {
        if (!node->isSVGElement())
            break;

        SVGElement* element = static_cast<SVGElement*>(node);
        if (!element->isStyled()) {
            node = node->parent();
            continue;
        }

        // Register us in the parent element map.
        static_cast<SVGStyledElement*>(element)->updateRelativeLengthsInformation(hasRelativeLengths, this);
        break;
    }
}
Example #11
0
void writeRenderResources(TextStream &ts, Node *parent)
{
    ASSERT(parent);
    Node *node = parent;
    do {
        if (!node->isSVGElement())
            continue;
        SVGElement *svgElement = static_cast<SVGElement *>(node);
        if (!svgElement->isStyled())
            continue;

        SVGStyledElement *styled = static_cast<SVGStyledElement *>(svgElement);
        KCanvasResource *resource = styled->canvasResource();
        if (!resource)
            continue;
        
        DeprecatedString elementId = svgElement->getAttribute(HTMLNames::idAttr).deprecatedString();
        if (resource->isPaintServer())
            ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *static_cast<KRenderingPaintServer *>(resource) << "}" << endl;
        else
            ts << "KCanvasResource {id=\"" << elementId << "\" " << *resource << "}" << endl;
    } while ((node = node->traverseNextNode(parent)));
}
Example #12
0
SVGPaintServer* SVGPaintServer::strokePaintServer(const RenderStyle* style, const RenderObject* item)
{
    if (!style->svgStyle()->hasStroke())
        return 0;

    SVGPaint* stroke = style->svgStyle()->strokePaint();

    SVGPaintServer* strokePaintServer = 0;
    SVGPaint::SVGPaintType paintType = stroke->paintType();
    if (paintType == SVGPaint::SVG_PAINTTYPE_URI ||
        paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR) {
        AtomicString id(SVGURIReference::getTarget(stroke->uri()));
        strokePaintServer = getPaintServerById(item->document(), id);

        SVGElement* svgElement = static_cast<SVGElement*>(item->element());
        ASSERT(svgElement && svgElement->document() && svgElement->isStyled());
 
        if (item->isRenderPath() && strokePaintServer)
            strokePaintServer->addClient(static_cast<SVGStyledElement*>(svgElement));
        else if (!strokePaintServer && paintType == SVGPaint::SVG_PAINTTYPE_URI)
            svgElement->document()->accessSVGExtensions()->addPendingResource(id, static_cast<SVGStyledElement*>(svgElement)); 
    }
    if (paintType != SVGPaint::SVG_PAINTTYPE_URI && !strokePaintServer) {
        strokePaintServer = sharedSolidPaintServer();
        SVGPaintServerSolid* strokePaintServerSolid = static_cast<SVGPaintServerSolid*>(strokePaintServer);
        if (paintType == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR)
            strokePaintServerSolid->setColor(style->color());
        else
            strokePaintServerSolid->setColor(stroke->color());
        // FIXME: Ideally invalid colors would never get set on the RenderStyle and this could turn into an ASSERT
        if (!strokePaintServerSolid->color().isValid())
            strokePaintServer = 0;
    }

    return strokePaintServer;
}
Example #13
0
void writeRenderResources(TextStream& ts, Node* parent)
{
    ASSERT(parent);
    Node* node = parent;
    do {
        if (!node->isSVGElement())
            continue;
        SVGElement* svgElement = static_cast<SVGElement*>(node);
        if (!svgElement->isStyled())
            continue;

        SVGStyledElement* styled = static_cast<SVGStyledElement*>(svgElement);
        RefPtr<SVGResource> resource(styled->canvasResource());
        if (!resource)
            continue;

        String elementId = svgElement->getAttribute(HTMLNames::idAttr);
        if (resource->isPaintServer()) {
            RefPtr<SVGPaintServer> paintServer = WTF::static_pointer_cast<SVGPaintServer>(resource);
            ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *paintServer << "}" << "\n";
        } else
            ts << "KCanvasResource {id=\"" << elementId << "\" " << *resource << "}" << "\n";
    } while ((node = node->traverseNextNode(parent)));
}
Example #14
0
PassOwnPtr<ImageBuffer> SVGMaskElement::drawMaskerContent(const FloatRect& targetRect, FloatRect& maskDestRect) const
{    
    // Determine specified mask size
    float xValue;
    float yValue;
    float widthValue;
    float heightValue;

    if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
        xValue = x().valueAsPercentage() * targetRect.width();
        yValue = y().valueAsPercentage() * targetRect.height();
        widthValue = width().valueAsPercentage() * targetRect.width();
        heightValue = height().valueAsPercentage() * targetRect.height();
    } else {
        xValue = x().value(this);
        yValue = y().value(this);
        widthValue = width().value(this);
        heightValue = height().value(this);
    } 

    IntSize imageSize(lroundf(widthValue), lroundf(heightValue));
    clampImageBufferSizeToViewport(document()->view(), imageSize);

    if (imageSize.width() < static_cast<int>(widthValue))
        widthValue = imageSize.width();

    if (imageSize.height() < static_cast<int>(heightValue))
        heightValue = imageSize.height();

    OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(imageSize, false);
    if (!maskImage)
        return 0;

    maskDestRect = FloatRect(xValue, yValue, widthValue, heightValue);
    if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
        maskDestRect.move(targetRect.x(), targetRect.y());

    GraphicsContext* maskImageContext = maskImage->context();
    ASSERT(maskImageContext);

    maskImageContext->save();
    maskImageContext->translate(-xValue, -yValue);

    if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
        maskImageContext->save();
        maskImageContext->scale(FloatSize(targetRect.width(), targetRect.height()));
    }

    // Render subtree into ImageBuffer
    for (Node* n = firstChild(); n; n = n->nextSibling()) {
        SVGElement* elem = 0;
        if (n->isSVGElement())
            elem = static_cast<SVGElement*>(n);
        if (!elem || !elem->isStyled())
            continue;

        SVGStyledElement* e = static_cast<SVGStyledElement*>(elem);
        RenderObject* item = e->renderer();
        if (!item)
            continue;

        renderSubtreeToImage(maskImage.get(), item);
    }

    if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
        maskImageContext->restore();

    maskImageContext->restore();
    return maskImage.release();
}
Example #15
0
void RenderSVGContainer::paint(PaintInfo& paintInfo, int parentX, int parentY)
{
    if (paintInfo.context->paintingDisabled())
        return;

    // This should only exist for <svg> renderers
    if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) 
        paintBoxDecorations(paintInfo, m_x + parentX, m_y + parentY);

    if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)
        paintOutline(paintInfo.context, parentX, parentY, width(), height(), style());
    
    if (paintInfo.phase != PaintPhaseForeground || !drawsContents())
        return;

    const SVGRenderStyle* svgStyle = style()->svgStyle();
    AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter()));

#if ENABLE(SVG_EXPERIMENTAL_FEATURES) 
    SVGResourceFilter* filter = getFilterById(document(), filterId);
#endif

    if (!firstChild()
#if ENABLE(SVG_EXPERIMENTAL_FEATURES) 
        && !filter
#endif
        )
        return; // Spec: groups w/o children still may render filter content.
    
    paintInfo.context->save();

    if (!parent()->isSVGContainer()) {
        // Translate from parent offsets (html renderers) to a relative transform (svg renderers)
        IntPoint origin;
        origin.move(parentX, parentY);
        origin.move(m_x, m_y);
        origin.move(borderLeft(), borderTop());
        origin.move(paddingLeft(), paddingTop());
        if (origin.x() || origin.y()) {
            paintInfo.context->concatCTM(AffineTransform().translate(origin.x(), origin.y()));
            paintInfo.rect.move(-origin.x(), -origin.y());
        }
        parentX = parentY = 0;
        SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
        paintInfo.context->concatCTM(AffineTransform().scale(svg->currentScale()));
    } else {
        // Only the root <svg> element should need any translations using the HTML/CSS system
        // parentX, parentY are also non-zero for first-level kids of these
        // CSS-transformed <svg> root-elements (due to RenderBox::paint) for any other element
        // they should be 0.   m_x, m_y should always be 0 for non-root svg containers
        ASSERT(m_x == 0);
        ASSERT(m_y == 0);
    }

    if (!viewport().isEmpty()) {
        if (style()->overflowX() != OVISIBLE)
            paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping

        paintInfo.context->concatCTM(AffineTransform().translate(viewport().x(), viewport().y()));
    }
    if (!localTransform().isIdentity())
        paintInfo.context->concatCTM(localTransform());
    if (!parent()->isSVGContainer()) {
        SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
        paintInfo.context->concatCTM(AffineTransform().translate(svg->currentTranslate().x(), svg->currentTranslate().y()));
    }

    FloatRect strokeBBox = relativeBBox(true);

    SVGElement* svgElement = static_cast<SVGElement*>(element());
    ASSERT(svgElement && svgElement->document() && svgElement->isStyled());

    SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
 
    AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath()));
    AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement()));

    SVGResourceClipper* clipper = getClipperById(document(), clipperId);
    SVGResourceMasker* masker = getMaskerById(document(), maskerId);

    if (clipper) {
        clipper->addClient(styledElement);
        clipper->applyClip(paintInfo.context, strokeBBox);
    } else if (!clipperId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement);

    if (masker) {
        masker->addClient(styledElement);
        masker->applyMask(paintInfo.context, strokeBBox);
    } else if (!maskerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement);

    float opacity = style()->opacity();
    if (opacity < 1.0f) {
        paintInfo.context->clip(enclosingIntRect(strokeBBox));
        paintInfo.context->beginTransparencyLayer(opacity);
    }

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    if (filter)
        filter->prepareFilter(paintInfo.context, strokeBBox);
    else if (!filterId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);
#endif

    if (!viewBox().isEmpty())
        paintInfo.context->concatCTM(viewportTransform());

    RenderContainer::paint(paintInfo, 0, 0);

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    if (filter)
        filter->applyFilter(paintInfo.context, strokeBBox);
#endif

    if (opacity < 1.0f)
        paintInfo.context->endTransparencyLayer();

    paintInfo.context->restore();
}
Example #16
0
PassOwnPtr<ImageBuffer> SVGMaskElement::drawMaskerContent(const FloatRect& targetRect, FloatRect& maskDestRect) const
{    
    // Determine specified mask size
    if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
        maskDestRect = FloatRect(x().valueAsPercentage() * targetRect.width(),
                                 y().valueAsPercentage() * targetRect.height(),
                                 width().valueAsPercentage() * targetRect.width(),
                                 height().valueAsPercentage() * targetRect.height());
    else
        maskDestRect = FloatRect(x().value(this),
                                 y().value(this),
                                 width().value(this),
                                 height().value(this));

    IntSize imageSize(lroundf(maskDestRect.width()), lroundf(maskDestRect.height()));
    clampImageBufferSizeToViewport(document()->view(), imageSize);

    if (imageSize.width() < static_cast<int>(maskDestRect.width()))
        maskDestRect.setWidth(imageSize.width());

    if (imageSize.height() < static_cast<int>(maskDestRect.height()))
        maskDestRect.setHeight(imageSize.height());

    // FIXME: This changes color space to linearRGB, the default color space
    // for masking operations in SVG. We need a switch for the other color-space
    // attribute values sRGB, inherit and auto.
    OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(imageSize, LinearRGB);
    if (!maskImage)
        return 0;

    FloatPoint maskContextLocation = maskDestRect.location();
    if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
        maskDestRect.move(targetRect.x(), targetRect.y());

    if (maskContentUnits() != SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
        maskContextLocation.move(targetRect.x(), targetRect.y());

    GraphicsContext* maskImageContext = maskImage->context();
    ASSERT(maskImageContext);

    maskImageContext->save();
    maskImageContext->translate(-maskContextLocation.x(), -maskContextLocation.y());

    if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
        maskImageContext->save();
        maskImageContext->scale(FloatSize(targetRect.width(), targetRect.height()));
    }

    // Render subtree into ImageBuffer
    for (Node* n = firstChild(); n; n = n->nextSibling()) {
        SVGElement* elem = 0;
        if (n->isSVGElement())
            elem = static_cast<SVGElement*>(n);
        if (!elem || !elem->isStyled())
            continue;

        SVGStyledElement* e = static_cast<SVGStyledElement*>(elem);
        RenderObject* item = e->renderer();
        if (!item)
            continue;

        renderSubtreeToImage(maskImage.get(), item);
    }

    if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
        maskImageContext->restore();

    maskImageContext->restore();
    return maskImage.release();
}
Example #17
0
void RenderPath::paint(PaintInfo& paintInfo, int, int)
{
    if (paintInfo.context->paintingDisabled() || (paintInfo.phase != PaintPhaseForeground) || style()->visibility() == HIDDEN || m_path.isEmpty())
        return;

    paintInfo.context->save();
    paintInfo.context->concatCTM(localTransform());

    FloatRect strokeBBox = relativeBBox(true);

    SVGElement* svgElement = static_cast<SVGElement*>(element());
    ASSERT(svgElement && svgElement->document() && svgElement->isStyled());

    SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
    const SVGRenderStyle* svgStyle = style()->svgStyle();

    AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter()));
    AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath()));
    AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement()));

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    SVGResourceFilter* filter = getFilterById(document(), filterId);
#endif
    SVGResourceClipper* clipper = getClipperById(document(), clipperId);
    SVGResourceMasker* masker = getMaskerById(document(), maskerId);

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    if (filter)
        filter->prepareFilter(paintInfo.context, strokeBBox);
    else if (!filterId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);
#endif

    if (clipper) {
        clipper->addClient(styledElement);
        clipper->applyClip(paintInfo.context, strokeBBox);
    } else if (!clipperId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement);

    if (masker) {
        masker->addClient(styledElement);
        masker->applyMask(paintInfo.context, strokeBBox);
    } else if (!maskerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement);

    paintInfo.context->beginPath();

    SVGPaintServer* fillPaintServer = KSVGPainterFactory::fillPaintServer(style(), this);
    if (fillPaintServer) {
        paintInfo.context->addPath(m_path);
        fillPaintServer->draw(paintInfo.context, this, ApplyToFillTargetType);
    }

    SVGPaintServer* strokePaintServer = KSVGPainterFactory::strokePaintServer(style(), this);
    if (strokePaintServer) {
        paintInfo.context->addPath(m_path); // path is cleared when filled.
        strokePaintServer->draw(paintInfo.context, this, ApplyToStrokeTargetType);
    }

    if (styledElement->supportsMarkers())
        m_markerBounds = drawMarkersIfNeeded(paintInfo.context, paintInfo.rect, m_path);

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    // actually apply the filter
    if (filter)
        filter->applyFilter(paintInfo.context, strokeBBox);
#endif

    paintInfo.context->restore();
}
void SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter)
{
#if !ENABLE(FILTERS)
    UNUSED_PARAM(filter);
    UNUSED_PARAM(rootFilter);
#endif

    ASSERT(object);
    SVGElement* svgElement = static_cast<SVGElement*>(object->node());
    ASSERT(svgElement && svgElement->document() && svgElement->isStyled());

    SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
    const RenderStyle* style = object->style();
    ASSERT(style);

    const SVGRenderStyle* svgStyle = style->svgStyle();
    ASSERT(svgStyle);

    // Setup transparency layers before setting up filters!
    float opacity = style->opacity(); 
    if (opacity < 1.0f) {
        paintInfo.context->clip(enclosingIntRect(boundingBox));
        paintInfo.context->beginTransparencyLayer(opacity);
    }

#if ENABLE(FILTERS)
    AtomicString filterId(svgStyle->filter());
#endif

    AtomicString clipperId(svgStyle->clipPath());
    AtomicString maskerId(svgStyle->maskElement());

    Document* document = object->document();

#if ENABLE(FILTERS)
    SVGResourceFilter* newFilter = getFilterById(document, filterId);
    if (newFilter == rootFilter) {
        // Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>.
        // The filter is NOT meant to be applied twice in that case!
        filter = 0;
        filterId = String();
    } else
        filter = newFilter;
#endif

    SVGResourceClipper* clipper = getClipperById(document, clipperId);
    SVGResourceMasker* masker = getMaskerById(document, maskerId);

#if ENABLE(FILTERS)
    if (filter) {
        filter->addClient(styledElement);
        filter->prepareFilter(paintInfo.context, object);
    } else if (!filterId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);
#endif

    if (clipper) {
        clipper->addClient(styledElement);
        clipper->applyClip(paintInfo.context, boundingBox);
    } else if (!clipperId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement);

    if (masker) {
        masker->addClient(styledElement);
        masker->applyMask(paintInfo.context, boundingBox);
    } else if (!maskerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement);
}
Example #19
0
FloatRect RenderPath::drawMarkersIfNeeded(GraphicsContext* context, const FloatRect&, const Path& path) const
{
    Document* doc = document();

    SVGElement* svgElement = static_cast<SVGElement*>(node());
    ASSERT(svgElement && svgElement->document() && svgElement->isStyled());

    SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
    const SVGRenderStyle* svgStyle = style()->svgStyle();

    AtomicString startMarkerId(svgStyle->startMarker());
    AtomicString midMarkerId(svgStyle->midMarker());
    AtomicString endMarkerId(svgStyle->endMarker());

    SVGResourceMarker* startMarker = getMarkerById(doc, startMarkerId);
    SVGResourceMarker* midMarker = getMarkerById(doc, midMarkerId);
    SVGResourceMarker* endMarker = getMarkerById(doc, endMarkerId);

    if (!startMarker && !startMarkerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(startMarkerId, styledElement);
    else if (startMarker)
        startMarker->addClient(styledElement);

    if (!midMarker && !midMarkerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(midMarkerId, styledElement);
    else if (midMarker)
        midMarker->addClient(styledElement);

    if (!endMarker && !endMarkerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(endMarkerId, styledElement);
    else if (endMarker)
        endMarker->addClient(styledElement);

    if (!startMarker && !midMarker && !endMarker)
        return FloatRect();

    double strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, svgStyle->strokeWidth(), 1.0f);
    DrawMarkersData data(context, startMarker, midMarker, strokeWidth);

    path.apply(&data, drawStartAndMidMarkers);

    data.previousMarkerData.marker = endMarker;
    data.previousMarkerData.type = End;
    drawMarkerWithData(context, data.previousMarkerData);

    // We know the marker boundaries, only after they're drawn!
    // Otherwhise we'd need to do all the marker calculation twice
    // once here (through paint()) and once in absoluteClippedOverflowRect().
    FloatRect bounds;

    if (startMarker)
        bounds.unite(startMarker->cachedBounds());

    if (midMarker)
        bounds.unite(midMarker->cachedBounds());

    if (endMarker)
        bounds.unite(endMarker->cachedBounds());

    return bounds;
}
Example #20
0
void RenderSVGImage::paint(PaintInfo& paintInfo, int parentX, int parentY)
{
    if (paintInfo.context->paintingDisabled() || (paintInfo.phase != PaintPhaseForeground) || style()->visibility() == HIDDEN)
        return;
    
    paintInfo.context->save();
    paintInfo.context->concatCTM(AffineTransform().translate(parentX, parentY));
    paintInfo.context->concatCTM(localTransform());
    paintInfo.context->concatCTM(translationForAttributes());

    FloatRect boundingBox = FloatRect(0, 0, width(), height());

    SVGElement* svgElement = static_cast<SVGElement*>(element());
    ASSERT(svgElement && svgElement->document() && svgElement->isStyled());

    SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
    const SVGRenderStyle* svgStyle = style()->svgStyle();

    AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter()));
    AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath()));
    AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement()));

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    SVGResourceFilter* filter = getFilterById(document(), filterId);
#endif
    SVGResourceClipper* clipper = getClipperById(document(), clipperId);
    SVGResourceMasker* masker = getMaskerById(document(), maskerId);

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    if (filter)
        filter->prepareFilter(paintInfo.context, boundingBox);
    else if (!filterId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);
#endif

    if (clipper) {
        clipper->addClient(styledElement);
        clipper->applyClip(paintInfo.context, boundingBox);
    } else if (!clipperId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement);

    if (masker) {
        masker->addClient(styledElement);
        masker->applyMask(paintInfo.context, boundingBox);
    } else if (!maskerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement);

    float opacity = style()->opacity();
    if (opacity < 1.0f) {
        paintInfo.context->clip(enclosingIntRect(boundingBox));
        paintInfo.context->beginTransparencyLayer(opacity);
    }

    PaintInfo pi(paintInfo);
    pi.rect = absoluteTransform().inverse().mapRect(pi.rect);

    SVGImageElement* imageElt = static_cast<SVGImageElement*>(node());

    FloatRect destRect(m_x, m_y, contentWidth(), contentHeight());
    FloatRect srcRect(0, 0, image()->width(), image()->height());

    if (imageElt->preserveAspectRatio()->align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE)
        adjustRectsForAspectRatio(destRect, srcRect, imageElt->preserveAspectRatio());

    paintInfo.context->drawImage(image(), destRect, srcRect);

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    if (filter)
        filter->applyFilter(paintInfo.context, boundingBox);
#endif

    if (opacity < 1.0f)
        paintInfo.context->endTransparencyLayer();

    paintInfo.context->restore();
}
Example #21
0
void paintSVGInlineFlow(InlineFlowBox* flow, RenderObject* object, RenderObject::PaintInfo& paintInfo, int tx, int ty)
{
    if (paintInfo.context->paintingDisabled())
        return;

    paintInfo.context->save();
    paintInfo.context->concatCTM(object->localTransform());

    FloatRect boundingBox(tx + flow->xPos(), ty + flow->yPos(), flow->width(), flow->height());

    SVGElement* svgElement = static_cast<SVGElement*>(object->element());
    ASSERT(svgElement && svgElement->document() && svgElement->isStyled());

    SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
    const SVGRenderStyle* svgStyle = object->style()->svgStyle();

    AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter()));
    AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath()));
    AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement()));

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    SVGResourceFilter* filter = getFilterById(object->document(), filterId);
#endif
    SVGResourceClipper* clipper = getClipperById(object->document(), clipperId);
    SVGResourceMasker* masker = getMaskerById(object->document(), maskerId);

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    if (filter)
        filter->prepareFilter(paintInfo.context, boundingBox);
    else if (!filterId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);
#endif

    if (clipper) {
        clipper->addClient(styledElement);
        clipper->applyClip(paintInfo.context, boundingBox);
    } else if (!clipperId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement);

    if (masker) {
        masker->addClient(styledElement);
        masker->applyMask(paintInfo.context, boundingBox);
    } else if (!maskerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement);

    RenderObject::PaintInfo pi(paintInfo);

    if (!flow->isRootInlineBox())
        pi.rect = (object->localTransform()).inverse().mapRect(pi.rect);

    float opacity = object->style()->opacity();
    if (opacity < 1.0f) {
        paintInfo.context->clip(enclosingIntRect(boundingBox));
        paintInfo.context->beginTransparencyLayer(opacity);
    }

    SVGPaintServer* fillPaintServer = KSVGPainterFactory::fillPaintServer(object->style(), object);
    if (fillPaintServer) {
        if (fillPaintServer->setup(pi.context, object, ApplyToFillTargetType, true)) {
            flow->InlineFlowBox::paint(pi, tx, ty);
            fillPaintServer->teardown(pi.context, object, ApplyToFillTargetType, true);
        }
    }

    SVGPaintServer* strokePaintServer = KSVGPainterFactory::strokePaintServer(object->style(), object);
    if (strokePaintServer) {
        if (strokePaintServer->setup(pi.context, object, ApplyToStrokeTargetType, true)) {
            flow->InlineFlowBox::paint(pi, tx, ty);
            strokePaintServer->teardown(pi.context, object, ApplyToStrokeTargetType, true);
        }
    }

#if ENABLE(SVG_EXPERIMENTAL_FEATURES)
    if (filter)
        filter->applyFilter(paintInfo.context, boundingBox);
#endif

    if (opacity < 1.0f)
        paintInfo.context->endTransparencyLayer();

    paintInfo.context->restore();
}
Example #22
0
bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& repaintRect, RenderSVGResourceFilter*& filter, RenderSVGResourceFilter* rootFilter)
{
#if !ENABLE(FILTERS)
    UNUSED_PARAM(filter);
    UNUSED_PARAM(rootFilter);
#endif

    ASSERT(object);
    SVGElement* svgElement = static_cast<SVGElement*>(object->node());
    ASSERT(svgElement && svgElement->document() && svgElement->isStyled());

    SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
    RenderStyle* style = object->style();
    ASSERT(style);

    const SVGRenderStyle* svgStyle = style->svgStyle();
    ASSERT(svgStyle);

    // Setup transparency layers before setting up filters!
    float opacity = style->opacity(); 
    if (opacity < 1.0f) {
        paintInfo.context->clip(repaintRect);
        paintInfo.context->beginTransparencyLayer(opacity);
    }

    if (const ShadowData* shadow = svgStyle->shadow()) {
        paintInfo.context->clip(repaintRect);
        paintInfo.context->setShadow(IntSize(shadow->x(), shadow->y()), shadow->blur(), shadow->color(), style->colorSpace());
        paintInfo.context->beginTransparencyLayer(1.0f);
    }

#if ENABLE(FILTERS)
    AtomicString filterId(svgStyle->filterResource());
#endif

    AtomicString clipperId(svgStyle->clipperResource());
    AtomicString maskerId(svgStyle->maskerResource());

    Document* document = object->document();

#if ENABLE(FILTERS)
    RenderSVGResourceFilter* newFilter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, filterId);
    if (newFilter == rootFilter) {
        // Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>.
        // The filter is NOT meant to be applied twice in that case!
        filter = 0;
        filterId = String();
    } else
        filter = newFilter;
#endif

    if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, maskerId)) {
        if (!masker->applyResource(object, style, paintInfo.context, ApplyToDefaultMode))
            return false;
    } else if (!maskerId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement);

    if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, clipperId))
        clipper->applyResource(object, style, paintInfo.context, ApplyToDefaultMode);
    else if (!clipperId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement);

#if ENABLE(FILTERS)
    if (filter) {
        if (!filter->applyResource(object, style, paintInfo.context, ApplyToDefaultMode))
            return false;
    } else if (!filterId.isEmpty())
        svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);
#endif

    return true;
}
Example #23
0
void SVGPatternElement::drawPatternContentIntoTile(const SVGPatternElement* target, const IntSize& newSize, KCanvasMatrix patternTransformMatrix) const
{
    KRenderingDevice* device = renderingDevice();
    
    SVGStyledElement* activeElement = static_cast<SVGStyledElement*>(m_paintServer->activeClient()->element());

    bool bbox = (patternUnits()->baseVal() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);

    const SVGStyledElement* savedContext = 0;
    if (bbox) {
        if (width()->baseVal()->unitType() != SVGLength::SVG_LENGTHTYPE_PERCENTAGE)
            width()->baseVal()->newValueSpecifiedUnits(SVGLength::SVG_LENGTHTYPE_PERCENTAGE, width()->baseVal()->value() * 100.);
        if (height()->baseVal()->unitType() != SVGLength::SVG_LENGTHTYPE_PERCENTAGE)
            height()->baseVal()->newValueSpecifiedUnits(SVGLength::SVG_LENGTHTYPE_PERCENTAGE, height()->baseVal()->value() * 100.);
        if (activeElement)
            savedContext = const_cast<SVGPatternElement* >(this)->pushAttributeContext(activeElement);
    }
    
    delete m_tile;
    m_tile = static_cast<KCanvasImage*>(device->createResource(RS_IMAGE));
    m_tile->init(newSize);

    KRenderingDeviceContext* patternContext = device->contextForImage(m_tile);
    device->pushContext(patternContext);
    FloatRect rect(x()->baseVal()->value(), y()->baseVal()->value(), width()->baseVal()->value(), height()->baseVal()->value());
    m_paintServer->setBbox(rect);
    m_paintServer->setPatternTransform(patternTransformMatrix);
    m_paintServer->setTile(m_tile);

    OwnPtr<GraphicsContext> context(patternContext->createGraphicsContext());

    for(Node *n = target->firstChild(); n != 0; n = n->nextSibling())
    {
        SVGElement* elem = svg_dynamic_cast(n);
        if (!elem || !elem->isStyled())
            continue;
        SVGStyledElement* e = static_cast<SVGStyledElement* >(elem);
        RenderObject *item = e->renderer();
        if (!item)
            continue;
#if 0
        // FIXME: None of this code seems to be necessary
        // to pass the w3c tests (and infact breaks them)
        // However, I'm leaving it #if 0'd for now until
        // I can quiz WildFox on the subject -- ecs 11/24/05
        // It's possible that W3C-SVG-1.1/coords-units-01-b
        // is failing due to lack of this code.
        KCanvasMatrix savedMatrix = item->localTransform();

        const SVGStyledElement* savedContext = 0;
        if (patternContentUnits()->baseVal() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
        {
            if (activeElement)
                savedContext = e->pushAttributeContext(activeElement);
        }

        // Take into account viewportElement's viewBox, if existant...
        if (viewportElement() && viewportElement()->hasTagName(SVGNames::svgTag))
        {
            SVGSVGElement* svgElement = static_cast<SVGSVGElement* >(viewportElement());

            RefPtr<SVGMatrix> svgCTM = svgElement->getCTM();
            RefPtr<SVGMatrix> ctm = getCTM();

            KCanvasMatrix newMatrix(svgCTM->matrix());
            newMatrix.multiply(savedMatrix);
            newMatrix.scale(1.0 / ctm->a(), 1.0 / ctm->d());

            item->setLocalTransform(newMatrix.matrix());
        }
#endif

        RenderObject::PaintInfo info(context.get(), IntRect(), PaintPhaseForeground, 0, 0, 0);
        item->paint(info, 0, 0);

#if 0
        if (savedContext)
            e->pushAttributeContext(savedContext);

        item->setLocalTransform(savedMatrix.matrix());
#endif
    }

    if (savedContext)
        const_cast<SVGPatternElement* >(this)->pushAttributeContext(savedContext);

    device->popContext();
    delete patternContext;
}