PassRefPtr<const SkPicture> LayoutSVGResourcePattern::asPicture(const FloatRect& tileBounds,
    const AffineTransform& tileTransform) const
{
    ASSERT(!m_shouldCollectPatternAttributes);

    AffineTransform contentTransform;
    if (attributes().patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
        contentTransform = tileTransform;

    FloatRect bounds(FloatPoint(), tileBounds.size());
    SkPictureBuilder pictureBuilder(bounds);

    ASSERT(attributes().patternContentElement());
    LayoutSVGResourceContainer* patternLayoutObject =
        toLayoutSVGResourceContainer(attributes().patternContentElement()->layoutObject());
    ASSERT(patternLayoutObject);
    ASSERT(!patternLayoutObject->needsLayout());

    SubtreeContentTransformScope contentTransformScope(contentTransform);

    {
        TransformRecorder transformRecorder(pictureBuilder.context(), *patternLayoutObject, tileTransform);
        for (LayoutObject* child = patternLayoutObject->firstChild(); child; child = child->nextSibling())
            SVGPaintContext::paintSubtree(&pictureBuilder.context(), child);
    }

    return pictureBuilder.endRecording();
}
示例#2
0
void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName) {
  bool isLengthAttr =
      attrName == SVGNames::xAttr || attrName == SVGNames::yAttr ||
      attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr;

  if (isLengthAttr || attrName == SVGNames::maskUnitsAttr ||
      attrName == SVGNames::maskContentUnitsAttr ||
      SVGTests::isKnownAttribute(attrName)) {
    SVGElement::InvalidationGuard invalidationGuard(this);

    if (isLengthAttr) {
      invalidateSVGPresentationAttributeStyle();
      setNeedsStyleRecalc(LocalStyleChange,
                          StyleChangeReasonForTracing::fromAttribute(attrName));
      updateRelativeLengthsInformation();
    }

    LayoutSVGResourceContainer* layoutObject =
        toLayoutSVGResourceContainer(this->layoutObject());
    if (layoutObject)
      layoutObject->invalidateCacheAndMarkForLayout();

    return;
  }

  SVGElement::svgAttributeChanged(attrName);
}
void SVGRadialGradientElement::svgAttributeChanged(const QualifiedName& attrName)
{
    if (!isSupportedAttribute(attrName)) {
        SVGGradientElement::svgAttributeChanged(attrName);
        return;
    }

    SVGElement::InvalidationGuard invalidationGuard(this);

    updateRelativeLengthsInformation();

    LayoutSVGResourceContainer* renderer = toLayoutSVGResourceContainer(this->layoutObject());
    if (renderer)
        renderer->invalidateCacheAndMarkForLayout();
}
void SVGPatternElement::svgAttributeChanged(const QualifiedName& attrName)
{
    if (!isSupportedAttribute(attrName)) {
        SVGElement::svgAttributeChanged(attrName);
        return;
    }

    SVGElement::InvalidationGuard invalidationGuard(this);

    if (attrName == SVGNames::xAttr
        || attrName == SVGNames::yAttr
        || attrName == SVGNames::widthAttr
        || attrName == SVGNames::heightAttr)
        updateRelativeLengthsInformation();

    LayoutSVGResourceContainer* renderer = toLayoutSVGResourceContainer(this->layoutObject());
    if (renderer)
        renderer->invalidateCacheAndMarkForLayout();
}
void writeSVGResourceContainer(TextStream& ts, const LayoutObject& object, int indent)
{
    writeStandardPrefix(ts, object, indent);

    Element* element = toElement(object.node());
    const AtomicString& id = element->getIdAttribute();
    writeNameAndQuotedValue(ts, "id", id);

    LayoutSVGResourceContainer* resource = toLayoutSVGResourceContainer(const_cast<LayoutObject*>(&object));
    ASSERT(resource);

    if (resource->resourceType() == MaskerResourceType) {
        LayoutSVGResourceMasker* masker = toLayoutSVGResourceMasker(resource);
        writeNameValuePair(ts, "maskUnits", masker->maskUnits());
        writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits());
        ts << "\n";
    } else if (resource->resourceType() == FilterResourceType) {
        LayoutSVGResourceFilter* filter = toLayoutSVGResourceFilter(resource);
        writeNameValuePair(ts, "filterUnits", filter->filterUnits());
        writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits());
        ts << "\n";
        // Creating a placeholder filter which is passed to the builder.
        FloatRect dummyRect;
        IntRect dummyIntRect;
        RefPtrWillBeRawPtr<SVGFilter> dummyFilter = SVGFilter::create(dummyIntRect, dummyRect, dummyRect, true);
        if (RefPtrWillBeRawPtr<SVGFilterBuilder> builder = filter->buildPrimitives(dummyFilter.get())) {
            if (FilterEffect* lastEffect = builder->lastEffect())
                lastEffect->externalRepresentation(ts, indent + 1);
        }
    } else if (resource->resourceType() == ClipperResourceType) {
        writeNameValuePair(ts, "clipPathUnits", toLayoutSVGResourceClipper(resource)->clipPathUnits());
        ts << "\n";
    } else if (resource->resourceType() == MarkerResourceType) {
        LayoutSVGResourceMarker* marker = toLayoutSVGResourceMarker(resource);
        writeNameValuePair(ts, "markerUnits", marker->markerUnits());
        ts << " [ref at " << marker->referencePoint() << "]";
        ts << " [angle=";
        if (marker->angle() == -1)
            ts << marker->orientType() << "]\n";
        else
            ts << marker->angle() << "]\n";
    } else if (resource->resourceType() == PatternResourceType) {
        LayoutSVGResourcePattern* pattern = static_cast<LayoutSVGResourcePattern*>(resource);

        // Dump final results that are used for layout. No use in asking SVGPatternElement for its patternUnits(), as it may
        // link to other patterns using xlink:href, we need to build the full inheritance chain, aka. collectPatternProperties()
        PatternAttributes attributes;
        toSVGPatternElement(pattern->element())->collectPatternAttributes(attributes);

        writeNameValuePair(ts, "patternUnits", attributes.patternUnits());
        writeNameValuePair(ts, "patternContentUnits", attributes.patternContentUnits());

        AffineTransform transform = attributes.patternTransform();
        if (!transform.isIdentity())
            ts << " [patternTransform=" << transform << "]";
        ts << "\n";
    } else if (resource->resourceType() == LinearGradientResourceType) {
        LayoutSVGResourceLinearGradient* gradient = static_cast<LayoutSVGResourceLinearGradient*>(resource);

        // Dump final results that are used for layout. No use in asking SVGGradientElement for its gradientUnits(), as it may
        // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties()
        LinearGradientAttributes attributes;
        toSVGLinearGradientElement(gradient->element())->collectGradientAttributes(attributes);
        writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits());

        ts << " [start=" << gradient->startPoint(attributes) << "] [end=" << gradient->endPoint(attributes) << "]\n";
    }  else if (resource->resourceType() == RadialGradientResourceType) {
        LayoutSVGResourceRadialGradient* gradient = toLayoutSVGResourceRadialGradient(resource);

        // Dump final results that are used for layout. No use in asking SVGGradientElement for its gradientUnits(), as it may
        // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties()
        RadialGradientAttributes attributes;
        toSVGRadialGradientElement(gradient->element())->collectGradientAttributes(attributes);
        writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits());

        FloatPoint focalPoint = gradient->focalPoint(attributes);
        FloatPoint centerPoint = gradient->centerPoint(attributes);
        float radius = gradient->radius(attributes);
        float focalRadius = gradient->focalRadius(attributes);

        ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "] [focalRadius=" << focalRadius << "]\n";
    } else {
        ts << "\n";
    }
    writeChildren(ts, object, indent);
}