ClipPathHelper(GraphicsContext* context, const PaintLayer& paintLayer, PaintLayerPaintingInfo& paintingInfo, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed, const LayoutPoint& offsetFromRoot, PaintLayerFlags paintFlags) : m_resourceClipper(0), m_paintLayer(paintLayer), m_context(context) { const ComputedStyle& style = paintLayer.layoutObject()->styleRef(); // Clip-path, like border radius, must not be applied to the contents of a composited-scrolling container. // It must, however, still be applied to the mask layer, so that the compositor can properly mask the // scrolling contents and scrollbars. if (!paintLayer.layoutObject()->hasClipPath() || (paintLayer.needsCompositedScrolling() && !(paintFlags & PaintLayerPaintingChildClippingMaskPhase))) return; m_clipperState = SVGClipPainter::ClipperNotApplied; paintingInfo.ancestorHasClipPathClipping = true; ASSERT(style.clipPath()); if (style.clipPath()->type() == ClipPathOperation::SHAPE) { ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style.clipPath()); if (clipPath->isValid()) { if (!rootRelativeBoundsComputed) { rootRelativeBounds = paintLayer.physicalBoundingBoxIncludingReflectionAndStackingChildren(offsetFromRoot); rootRelativeBoundsComputed = true; } m_clipPathRecorder.emplace(*context, *paintLayer.layoutObject(), clipPath->path(FloatRect(rootRelativeBounds))); } } else if (style.clipPath()->type() == ClipPathOperation::REFERENCE) { ReferenceClipPathOperation* referenceClipPathOperation = toReferenceClipPathOperation(style.clipPath()); Document& document = paintLayer.layoutObject()->document(); // FIXME: It doesn't work with forward or external SVG references (https://bugs.webkit.org/show_bug.cgi?id=90405) Element* element = document.getElementById(referenceClipPathOperation->fragment()); if (isSVGClipPathElement(element) && element->layoutObject()) { if (!rootRelativeBoundsComputed) { rootRelativeBounds = paintLayer.physicalBoundingBoxIncludingReflectionAndStackingChildren(offsetFromRoot); rootRelativeBoundsComputed = true; } m_resourceClipper = toLayoutSVGResourceClipper(toLayoutSVGResourceContainer(element->layoutObject())); if (!SVGClipPainter(*m_resourceClipper).prepareEffect(*paintLayer.layoutObject(), FloatRect(rootRelativeBounds), FloatRect(rootRelativeBounds), context, m_clipperState)) { // No need to post-apply the clipper if this failed. m_resourceClipper = 0; } } } }
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); }