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(svgElement->idAttributeName());
        // FIXME: These names are lies!
        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 #2
0
FloatRect RenderSVGPath::calculateMarkerBoundsIfNeeded()
{
    SVGElement* svgElement = static_cast<SVGElement*>(node());
    ASSERT(svgElement && svgElement->document());
    if (!svgElement->isStyled())
        return FloatRect();

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

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

    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
    if (!resources)
        return FloatRect();

    RenderSVGResourceMarker* markerStart = resources->markerStart();
    RenderSVGResourceMarker* markerMid = resources->markerMid();
    RenderSVGResourceMarker* markerEnd = resources->markerEnd();
    if (!markerStart && !markerMid && !markerEnd)
        return FloatRect();

    return m_markerLayoutInfo.calculateBoundaries(markerStart, markerMid, markerEnd, svgStyle->strokeWidth().value(svgElement), m_path);
}
Example #3
0
static DeprecatedString getTagName(void *node)
{
    SVGStyledElement *elem = static_cast<SVGStyledElement *>(node);
    if (elem)
        return String(elem->nodeName()).deprecatedString();
    return DeprecatedString();
}
Example #4
0
KCanvasClipper *SVGClipPathElement::canvasResource()
{
    if (!view())
        return 0;
    if (!m_clipper)
        m_clipper = static_cast<KCanvasClipper *>(renderingDevice()->createResource(RS_CLIPPER));
    else
        m_clipper->resetClipData();

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

    RenderStyle *clipPathStyle = styleForRenderer(parent()->renderer()); // FIXME: Manual style resolution is a hack
    for (Node *n = firstChild(); n != 0; n = n->nextSibling()) {
        SVGElement *e = svg_dynamic_cast(n);
        if (e && e->isStyled()) {
            SVGStyledElement *styled = static_cast<SVGStyledElement *>(e);
            RenderStyle *pathStyle = document()->styleSelector()->styleForElement(styled, clipPathStyle);
            if (KCanvasPath* pathData = styled->toPathData())
                m_clipper->addClipData(pathData, (KCWindRule) pathStyle->svgStyle()->clipRule(), bbox);
            pathStyle->deref(view()->renderArena());
        }
    }
    clipPathStyle->deref(view()->renderArena());
    return m_clipper;
}
Example #5
0
void SVGResource::invalidate()
{
    HashSet<SVGStyledElement*>::const_iterator it = m_clients.begin();
    const HashSet<SVGStyledElement*>::const_iterator end = m_clients.end();

    for (; it != end; ++it) {
        SVGStyledElement* cur = *it;

        if (cur->renderer())
            cur->renderer()->setNeedsLayout(true);

        cur->invalidateResourcesInAncestorChain();
    }
}
Example #6
0
float SVGRenderStyle::cssPrimitiveToLength(const RenderObject* item, CSSValue* value, float defaultValue)
{
    CSSPrimitiveValue* primitive = static_cast<CSSPrimitiveValue*>(value);

    unsigned short cssType = (primitive ? primitive->primitiveType() : (unsigned short) CSSPrimitiveValue::CSS_UNKNOWN);
    if (!(cssType > CSSPrimitiveValue::CSS_UNKNOWN && cssType <= CSSPrimitiveValue::CSS_PC))
        return defaultValue;

    if (cssType == CSSPrimitiveValue::CSS_PERCENTAGE) {
        SVGStyledElement* element = static_cast<SVGStyledElement*>(item->node());
        SVGElement* viewportElement = (element ? element->viewportElement() : 0);
        if (viewportElement) {
            float result = primitive->getFloatValue() / 100.0f;
            return SVGLength::PercentageOfViewport(result, element, LengthModeOther);
        }
    }

    return primitive->computeLengthFloat(const_cast<RenderStyle*>(item->style()), item->document()->documentElement()->renderStyle());
}
Example #7
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);
}
Example #8
0
void SVGGradientElement::notifyAttributeChange() const
{
    if(ownerDocument()->parsing() || !attached())
        return;

    // Update clients of this gradient resource...
    buildGradient(m_resource);
    
    m_resource->invalidate();  // should this be added to build gradient?
    
    const KCanvasItemList &clients = m_resource->clients();
    for(KCanvasItemList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
    {
        const RenderPath *current = (*it);
        SVGStyledElement *styled = (current ? static_cast<SVGStyledElement *>(current->element()) : 0);
        if(styled)
            styled->setChanged(true);
    }
}
Example #9
0
void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource)
{
    ASSERT(resource);
    SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource);

    // The resource itself may have clients, that need to be notified.
    cache->removeResourcesFromRenderObject(resource);

    HashMap<RenderObject*, SVGResources*>::iterator end = cache->m_cache.end();
    for (HashMap<RenderObject*, SVGResources*>::iterator it = cache->m_cache.begin(); it != end; ++it) {
        it->second->resourceDestroyed(resource);

        // Mark users of destroyed resources as pending resolution based on the id of the old resource.
        Element* resourceElement = toElement(resource->node());
        SVGStyledElement* clientElement = toSVGStyledElement(it->first->node());
        SVGDocumentExtensions* extensions = clientElement->document()->accessSVGExtensions();

        extensions->addPendingResource(resourceElement->fastGetAttribute(HTMLNames::idAttr), clientElement);
    }
}
Example #10
0
void SVGPatternElement::notifyClientsToRepaint() const
{
    const KCanvasItemList &clients = m_paintServer->clients();

    KCanvasItemList::ConstIterator it = clients.begin();
    KCanvasItemList::ConstIterator end = clients.end();

    for(; it != end; ++it)
    {
        const RenderPath *current = (*it);

        SVGStyledElement* styled = (current ? static_cast<SVGStyledElement* >(current->element()) : 0);
        if (styled)
        {
            styled->setChanged(true);

            if (styled->renderer())
                styled->renderer()->repaint();
        }
    }
}
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
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 #13
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();
}
Example #14
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 #15
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;
}