FloatRect LayoutSVGResourceMasker::resourceBoundingBox(const LayoutObject* object) { SVGMaskElement* maskElement = toSVGMaskElement(element()); ASSERT(maskElement); FloatRect objectBoundingBox = object->objectBoundingBox(); FloatRect maskBoundaries = SVGLengthContext::resolveRectangle<SVGMaskElement>(maskElement, maskElement->maskUnits()->currentValue()->enumValue(), objectBoundingBox); // Resource was not layouted yet. Give back clipping rect of the mask. if (selfNeedsLayout()) return maskBoundaries; if (m_maskContentBoundaries.isEmpty()) calculateMaskContentPaintInvalidationRect(); FloatRect maskRect = m_maskContentBoundaries; if (maskElement->maskContentUnits()->currentValue()->value() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { AffineTransform transform; transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); maskRect = transform.mapRect(maskRect); } maskRect.intersect(maskBoundaries); return maskRect; }
sk_sp<const SkPicture> LayoutSVGResourceMasker::createContentPicture( AffineTransform& contentTransformation, const FloatRect& targetBoundingBox, GraphicsContext& context) { SVGUnitTypes::SVGUnitType contentUnits = toSVGMaskElement(element()) ->maskContentUnits() ->currentValue() ->enumValue(); if (contentUnits == SVGUnitTypes::kSvgUnitTypeObjectboundingbox) { contentTransformation.translate(targetBoundingBox.x(), targetBoundingBox.y()); contentTransformation.scaleNonUniform(targetBoundingBox.width(), targetBoundingBox.height()); } if (m_maskContentPicture) return m_maskContentPicture; SubtreeContentTransformScope contentTransformScope(contentTransformation); // Using strokeBoundingBox instead of visualRectInLocalCoordinates // to avoid the intersection with local clips/mask, which may yield incorrect // results when mixing objectBoundingBox and userSpaceOnUse units. // http://crbug.com/294900 FloatRect bounds = strokeBoundingBox(); SkPictureBuilder pictureBuilder(bounds, nullptr, &context); ColorFilter maskContentFilter = style()->svgStyle().colorInterpolation() == CI_LINEARRGB ? ColorFilterSRGBToLinearRGB : ColorFilterNone; pictureBuilder.context().setColorFilter(maskContentFilter); for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) { LayoutObject* layoutObject = childElement->layoutObject(); if (!layoutObject) continue; const ComputedStyle* style = layoutObject->style(); if (!style || style->display() == EDisplay::None || style->visibility() != EVisibility::Visible) continue; SVGPaintContext::paintSubtree(pictureBuilder.context(), layoutObject); } m_maskContentPicture = pictureBuilder.endRecording(); return m_maskContentPicture; }
void RenderSVGResourceMasker::drawMaskForRenderer(GraphicsContext* context, const FloatRect& targetBoundingBox) { ASSERT(context); AffineTransform contentTransformation; SVGUnitTypes::SVGUnitType contentUnits = toSVGMaskElement(element())->maskContentUnits()->currentValue()->enumValue(); if (contentUnits == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { contentTransformation.translate(targetBoundingBox.x(), targetBoundingBox.y()); contentTransformation.scaleNonUniform(targetBoundingBox.width(), targetBoundingBox.height()); context->concatCTM(contentTransformation); } if (!m_maskContentDisplayList) createDisplayList(context, contentTransformation); ASSERT(m_maskContentDisplayList); context->drawDisplayList(m_maskContentDisplayList.get()); }
PassRefPtr<const SkPicture> LayoutSVGResourceMasker::createContentPicture(AffineTransform& contentTransformation, const FloatRect& targetBoundingBox) { SVGUnitTypes::SVGUnitType contentUnits = toSVGMaskElement(element())->maskContentUnits()->currentValue()->enumValue(); if (contentUnits == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { contentTransformation.translate(targetBoundingBox.x(), targetBoundingBox.y()); contentTransformation.scaleNonUniform(targetBoundingBox.width(), targetBoundingBox.height()); } if (m_maskContentPicture) return m_maskContentPicture; SubtreeContentTransformScope contentTransformScope(contentTransformation); // Using strokeBoundingBox (instead of paintInvalidationRectInLocalCoordinates) to avoid the intersection // with local clips/mask, which may yield incorrect results when mixing objectBoundingBox and // userSpaceOnUse units (http://crbug.com/294900). FloatRect bounds = strokeBoundingBox(); OwnPtr<DisplayItemList> displayItemList; if (RuntimeEnabledFeatures::slimmingPaintEnabled()) displayItemList = DisplayItemList::create(); GraphicsContext context(nullptr, displayItemList.get()); context.beginRecording(bounds); ColorFilter maskContentFilter = style()->svgStyle().colorInterpolation() == CI_LINEARRGB ? ColorFilterSRGBToLinearRGB : ColorFilterNone; context.setColorFilter(maskContentFilter); for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) { LayoutObject* layoutObject = childElement->layoutObject(); if (!layoutObject) continue; const ComputedStyle* style = layoutObject->style(); if (!style || style->display() == NONE || style->visibility() != VISIBLE) continue; SVGPaintContext::paintSubtree(&context, layoutObject); } if (displayItemList) displayItemList->commitNewDisplayItemsAndReplay(context); m_maskContentPicture = context.endRecording(); return m_maskContentPicture; }