Commit 379305ed authored by Fredrik Söderqvist's avatar Fredrik Söderqvist Committed by Commit Bot

Tidy up FEImage

 * Const qualify referenced objects (SVGPreserveAspectRatio, TreeScope).
 * Have ReferencedLayoutObject() return a const LayoutObject.
 * Rearrange the code in FEImage::MapInputs() and CreateImageFilter() to
   get the same general structure (element reference, external image,
   failure).
 * Reorder PaintRecord recording in CreateImageFilterForLayoutObject().
 * Mark local helper MakeMapBetweenRects() static. Split out "magic
   viewport"-mapping into a helper function.
 * Use DynamicTo<>() where applicable.

Change-Id: If9fe1cf076257cd680c05bb1c97e14ab2fe7c1c2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2110013
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751974}
parent ccbefaff
...@@ -23,16 +23,18 @@ ...@@ -23,16 +23,18 @@
#include "third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.h" #include "third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
#include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/paint/svg_object_painter.h" #include "third_party/blink/renderer/core/paint/svg_object_painter.h"
#include "third_party/blink/renderer/core/svg/svg_element.h" #include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg/svg_length_context.h" #include "third_party/blink/renderer/core/svg/svg_length_context.h"
#include "third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.h"
#include "third_party/blink/renderer/core/svg/svg_uri_reference.h" #include "third_party/blink/renderer/core/svg/svg_uri_reference.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h" #include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h" #include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h" #include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h" #include "third_party/blink/renderer/platform/transforms/affine_transform.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h" #include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
...@@ -40,7 +42,7 @@ namespace blink { ...@@ -40,7 +42,7 @@ namespace blink {
FEImage::FEImage(Filter* filter, FEImage::FEImage(Filter* filter,
scoped_refptr<Image> image, scoped_refptr<Image> image,
SVGPreserveAspectRatio* preserve_aspect_ratio) const SVGPreserveAspectRatio* preserve_aspect_ratio)
: FilterEffect(filter), : FilterEffect(filter),
image_(std::move(image)), image_(std::move(image)),
tree_scope_(nullptr), tree_scope_(nullptr),
...@@ -49,9 +51,9 @@ FEImage::FEImage(Filter* filter, ...@@ -49,9 +51,9 @@ FEImage::FEImage(Filter* filter,
} }
FEImage::FEImage(Filter* filter, FEImage::FEImage(Filter* filter,
TreeScope& tree_scope, const TreeScope& tree_scope,
const String& href, const String& href,
SVGPreserveAspectRatio* preserve_aspect_ratio) const SVGPreserveAspectRatio* preserve_aspect_ratio)
: FilterEffect(filter), : FilterEffect(filter),
tree_scope_(&tree_scope), tree_scope_(&tree_scope),
href_(href), href_(href),
...@@ -65,13 +67,13 @@ void FEImage::Trace(Visitor* visitor) { ...@@ -65,13 +67,13 @@ void FEImage::Trace(Visitor* visitor) {
FilterEffect::Trace(visitor); FilterEffect::Trace(visitor);
} }
static FloatRect GetLayoutObjectRepaintRect(LayoutObject* layout_object) { static FloatRect GetLayoutObjectRepaintRect(const LayoutObject* layout_object) {
return layout_object->LocalToSVGParentTransform().MapRect( return layout_object->LocalToSVGParentTransform().MapRect(
layout_object->VisualRectInLocalSVGCoordinates()); layout_object->VisualRectInLocalSVGCoordinates());
} }
AffineTransform MakeMapBetweenRects(const FloatRect& source, static AffineTransform MakeMapBetweenRects(const FloatRect& source,
const FloatRect& dest) { const FloatRect& dest) {
AffineTransform transform; AffineTransform transform;
transform.Translate(dest.X() - source.X(), dest.Y() - source.Y()); transform.Translate(dest.X() - source.X(), dest.Y() - source.Y());
transform.Scale(dest.Width() / source.Width(), transform.Scale(dest.Width() / source.Width(),
...@@ -79,48 +81,58 @@ AffineTransform MakeMapBetweenRects(const FloatRect& source, ...@@ -79,48 +81,58 @@ AffineTransform MakeMapBetweenRects(const FloatRect& source,
return transform; return transform;
} }
FloatRect FEImage::MapInputs(const FloatRect&) const { static base::Optional<AffineTransform> ComputeViewportAdjustmentTransform(
LayoutObject* layout_object = ReferencedLayoutObject(); const SVGElement* element,
if (!image_ && !layout_object) const FloatRect& target_rect) {
return FloatRect(); // 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.
// TODO(crbug/260709): This fixes relative lengths but breaks non-relative
// ones.
SVGLengthContext length_context(element);
FloatSize viewport_size;
if (!length_context.DetermineViewport(viewport_size))
return base::nullopt;
return MakeMapBetweenRects(FloatRect(FloatPoint(), viewport_size),
target_rect);
}
FloatRect FEImage::MapInputs(const FloatRect&) const {
FloatRect dest_rect = FloatRect dest_rect =
GetFilter()->MapLocalRectToAbsoluteRect(FilterPrimitiveSubregion()); GetFilter()->MapLocalRectToAbsoluteRect(FilterPrimitiveSubregion());
FloatRect src_rect; if (const LayoutObject* layout_object = ReferencedLayoutObject()) {
if (layout_object) { FloatRect src_rect = GetLayoutObjectRepaintRect(layout_object);
src_rect = GetLayoutObjectRepaintRect(layout_object);
auto* context_node = To<SVGElement>(layout_object->GetNode()); auto* context_node = To<SVGElement>(layout_object->GetNode());
if (context_node->HasRelativeLengths()) { if (context_node->HasRelativeLengths()) {
// FIXME: This fixes relative lengths but breaks non-relative ones (see auto viewport_transform =
// crbug/260709). ComputeViewportAdjustmentTransform(context_node, dest_rect);
SVGLengthContext length_context(context_node); if (viewport_transform)
FloatSize viewport_size; src_rect = viewport_transform->MapRect(src_rect);
if (length_context.DetermineViewport(viewport_size)) {
src_rect = MakeMapBetweenRects(FloatRect(FloatPoint(), viewport_size),
dest_rect)
.MapRect(src_rect);
}
} else { } else {
src_rect = GetFilter()->MapLocalRectToAbsoluteRect(src_rect); src_rect = GetFilter()->MapLocalRectToAbsoluteRect(src_rect);
src_rect.Move(dest_rect.X(), dest_rect.Y()); src_rect.Move(dest_rect.X(), dest_rect.Y());
} }
dest_rect.Intersect(src_rect); dest_rect.Intersect(src_rect);
} else { return dest_rect;
src_rect = FloatRect(FloatPoint(), FloatSize(image_->Size())); }
if (image_) {
FloatRect src_rect = FloatRect(FloatPoint(), FloatSize(image_->Size()));
preserve_aspect_ratio_->TransformRect(dest_rect, src_rect); preserve_aspect_ratio_->TransformRect(dest_rect, src_rect);
return dest_rect;
} }
return dest_rect; return FloatRect();
} }
LayoutObject* FEImage::ReferencedLayoutObject() const { const LayoutObject* FEImage::ReferencedLayoutObject() const {
if (!tree_scope_) if (!tree_scope_)
return nullptr; return nullptr;
Element* href_element = const SVGElement* target = DynamicTo<SVGElement>(
SVGURIReference::TargetElementFromIRIString(href_, *tree_scope_); SVGURIReference::TargetElementFromIRIString(href_, *tree_scope_));
if (!href_element || !href_element->IsSVGElement()) if (!target)
return nullptr; return nullptr;
return href_element->GetLayoutObject(); return target->GetLayoutObject();
} }
WTF::TextStream& FEImage::ExternalRepresentation(WTF::TextStream& ts, WTF::TextStream& FEImage::ExternalRepresentation(WTF::TextStream& ts,
...@@ -128,7 +140,7 @@ WTF::TextStream& FEImage::ExternalRepresentation(WTF::TextStream& ts, ...@@ -128,7 +140,7 @@ WTF::TextStream& FEImage::ExternalRepresentation(WTF::TextStream& ts,
IntSize image_size; IntSize image_size;
if (image_) { if (image_) {
image_size = image_->Size(); image_size = image_->Size();
} else if (LayoutObject* layout_object = ReferencedLayoutObject()) { } else if (const LayoutObject* layout_object = ReferencedLayoutObject()) {
image_size = image_size =
EnclosingIntRect(GetLayoutObjectRepaintRect(layout_object)).Size(); EnclosingIntRect(GetLayoutObjectRepaintRect(layout_object)).Size();
} }
...@@ -150,54 +162,44 @@ sk_sp<PaintFilter> FEImage::CreateImageFilterForLayoutObject( ...@@ -150,54 +162,44 @@ sk_sp<PaintFilter> FEImage::CreateImageFilterForLayoutObject(
auto* context_node = To<SVGElement>(layout_object.GetNode()); auto* context_node = To<SVGElement>(layout_object.GetNode());
if (context_node->HasRelativeLengths()) { if (context_node->HasRelativeLengths()) {
SVGLengthContext length_context(context_node); auto viewport_transform =
FloatSize viewport_size; ComputeViewportAdjustmentTransform(context_node, dst_rect);
if (viewport_transform)
// If we're referencing an element with percentage units, eg. <rect transform = *viewport_transform;
// 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 (length_context.DetermineViewport(viewport_size))
transform =
MakeMapBetweenRects(FloatRect(FloatPoint(), viewport_size), dst_rect);
} else { } else {
transform.Translate(dst_rect.X(), dst_rect.Y()); transform.Translate(dst_rect.X(), dst_rect.Y());
} }
PaintRecordBuilder builder;
SVGObjectPainter(layout_object).PaintResourceSubtree(builder.Context());
PaintRecorder paint_recorder; PaintRecorder paint_recorder;
cc::PaintCanvas* canvas = paint_recorder.beginRecording(dst_rect); cc::PaintCanvas* canvas = paint_recorder.beginRecording(dst_rect);
canvas->concat(AffineTransformToSkMatrix(transform)); canvas->concat(AffineTransformToSkMatrix(transform));
builder.EndRecording(*canvas); {
PaintRecordBuilder builder;
SVGObjectPainter(layout_object).PaintResourceSubtree(builder.Context());
builder.EndRecording(*canvas);
}
return sk_make_sp<RecordPaintFilter>( return sk_make_sp<RecordPaintFilter>(
paint_recorder.finishRecordingAsPicture(), dst_rect); paint_recorder.finishRecordingAsPicture(), dst_rect);
} }
sk_sp<PaintFilter> FEImage::CreateImageFilter() { sk_sp<PaintFilter> FEImage::CreateImageFilter() {
if (auto* layout_object = ReferencedLayoutObject()) if (const auto* layout_object = ReferencedLayoutObject())
return CreateImageFilterForLayoutObject(*layout_object); return CreateImageFilterForLayoutObject(*layout_object);
PaintImage image = if (PaintImage image =
image_ ? image_->PaintImageForCurrentFrame() : PaintImage(); image_ ? image_->PaintImageForCurrentFrame() : PaintImage()) {
if (!image) { FloatRect src_rect = FloatRect(FloatPoint(), FloatSize(image_->Size()));
// "A href reference that is an empty image (zero width or zero height), FloatRect dst_rect =
// that fails to download, is non-existent, or that cannot be displayed GetFilter()->MapLocalRectToAbsoluteRect(FilterPrimitiveSubregion());
// (e.g. because it is not in a supported image format) fills the filter preserve_aspect_ratio_->TransformRect(dst_rect, src_rect);
// primitive subregion with transparent black." return sk_make_sp<ImagePaintFilter>(std::move(image), src_rect, dst_rect,
return CreateTransparentBlack(); kHigh_SkFilterQuality);
} }
// "A href reference that is an empty image (zero width or zero height),
FloatRect src_rect = FloatRect(FloatPoint(), FloatSize(image_->Size())); // that fails to download, is non-existent, or that cannot be displayed
FloatRect dst_rect = // (e.g. because it is not in a supported image format) fills the filter
GetFilter()->MapLocalRectToAbsoluteRect(FilterPrimitiveSubregion()); // primitive subregion with transparent black."
return CreateTransparentBlack();
preserve_aspect_ratio_->TransformRect(dst_rect, src_rect);
return sk_make_sp<ImagePaintFilter>(std::move(image), src_rect, dst_rect,
kHigh_SkFilterQuality);
} }
} // namespace blink } // namespace blink
...@@ -24,19 +24,23 @@ ...@@ -24,19 +24,23 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_GRAPHICS_FILTERS_SVG_FE_IMAGE_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_GRAPHICS_FILTERS_SVG_FE_IMAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_GRAPHICS_FILTERS_SVG_FE_IMAGE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_GRAPHICS_FILTERS_SVG_FE_IMAGE_H_
#include "third_party/blink/renderer/core/dom/tree_scope.h"
#include "third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter_effect.h" #include "third_party/blink/renderer/platform/graphics/filters/filter_effect.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink { namespace blink {
class Image; class Image;
class LayoutObject; class LayoutObject;
class SVGPreserveAspectRatio;
class TreeScope;
class FEImage final : public FilterEffect { class FEImage final : public FilterEffect {
public: public:
FEImage(Filter*, scoped_refptr<Image>, SVGPreserveAspectRatio*); FEImage(Filter*, scoped_refptr<Image>, const SVGPreserveAspectRatio*);
FEImage(Filter*, TreeScope&, const String&, SVGPreserveAspectRatio*); FEImage(Filter*,
const TreeScope&,
const String&,
const SVGPreserveAspectRatio*);
// feImage does not perform color interpolation of any kind, so doesn't // feImage does not perform color interpolation of any kind, so doesn't
// depend on the value of color-interpolation-filters. // depend on the value of color-interpolation-filters.
...@@ -49,7 +53,7 @@ class FEImage final : public FilterEffect { ...@@ -49,7 +53,7 @@ class FEImage final : public FilterEffect {
private: private:
~FEImage() override = default; ~FEImage() override = default;
LayoutObject* ReferencedLayoutObject() const; const LayoutObject* ReferencedLayoutObject() const;
FilterEffectType GetFilterEffectType() const override { FilterEffectType GetFilterEffectType() const override {
return kFilterEffectTypeImage; return kFilterEffectTypeImage;
...@@ -62,11 +66,9 @@ class FEImage final : public FilterEffect { ...@@ -62,11 +66,9 @@ class FEImage final : public FilterEffect {
scoped_refptr<Image> image_; scoped_refptr<Image> image_;
// m_treeScope will never be a dangling reference. See Member<const TreeScope> tree_scope_;
// https://bugs.webkit.org/show_bug.cgi?id=99243
Member<TreeScope> tree_scope_;
String href_; String href_;
Member<SVGPreserveAspectRatio> preserve_aspect_ratio_; Member<const SVGPreserveAspectRatio> preserve_aspect_ratio_;
}; };
} // namespace blink } // namespace blink
......
...@@ -186,7 +186,7 @@ bool SVGPreserveAspectRatio::Parse(const UChar*& ptr, ...@@ -186,7 +186,7 @@ bool SVGPreserveAspectRatio::Parse(const UChar*& ptr,
} }
void SVGPreserveAspectRatio::TransformRect(FloatRect& dest_rect, void SVGPreserveAspectRatio::TransformRect(FloatRect& dest_rect,
FloatRect& src_rect) { FloatRect& src_rect) const {
if (align_ == kSvgPreserveaspectratioNone) if (align_ == kSvgPreserveaspectratioNone)
return; return;
......
...@@ -72,7 +72,7 @@ class SVGPreserveAspectRatio final ...@@ -72,7 +72,7 @@ class SVGPreserveAspectRatio final
} }
SVGMeetOrSliceType MeetOrSlice() const { return meet_or_slice_; } SVGMeetOrSliceType MeetOrSlice() const { return meet_or_slice_; }
void TransformRect(FloatRect& dest_rect, FloatRect& src_rect); void TransformRect(FloatRect& dest_rect, FloatRect& src_rect) const;
AffineTransform ComputeTransform(float logical_x, AffineTransform ComputeTransform(float logical_x,
float logical_y, float logical_y,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment