Skip to content

Provide GraphicsContext::fillRect(const FloatRect&, Gradient&, const AffineTransform& gradientSpaceTransform) variant#22352

Merged
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
nikolaszimmermann:eng/Provide-GraphicsContextfillRectconst-FloatRect-Gradient-const-AffineTransform-gradientSpaceTransform-variant
Jan 4, 2024
Merged

Provide GraphicsContext::fillRect(const FloatRect&, Gradient&, const AffineTransform& gradientSpaceTransform) variant#22352
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
nikolaszimmermann:eng/Provide-GraphicsContextfillRectconst-FloatRect-Gradient-const-AffineTransform-gradientSpaceTransform-variant

Conversation

@nikolaszimmermann
Copy link
Copy Markdown
Contributor

@nikolaszimmermann nikolaszimmermann commented Jan 3, 2024

df59d72

Provide GraphicsContext::fillRect(const FloatRect&, Gradient&, const AffineTransform& gradientSpaceTransform) variant
https://bugs.webkit.org/show_bug.cgi?id=267040

Reviewed by Said Abou-Hallawa.

The existing fillRect(const FloatRect&, Gradient&) accessor, only calls
gradient.paint(), but does not handle gradient space transformations, nor
drop shadows, nor does it clip to the rect, etc. in contrary to the generic
fillRect(const FloatRect&) variant, which supports all these features,
but only when using the fillGradient() and the fillGradientSpaceTransform().

For LBSE gradient support it would be useful to be able to fill a rectangle
using the _stroke_ gradient, therefore extend the GraphicsContext::fillRect()
variants to provide one that takes a specific Gradient + AffineTransform pair.

Implement the new fillRect() variant in various places: NullGraphicsContext,
BifurcatedGraphicsCOntext, and all other variants inheriting from GraphicsContext.

No change in existing functionality, thus no new tests.

* Source/WebCore/platform/graphics/BifurcatedGraphicsContext.cpp:
(WebCore::BifurcatedGraphicsContext::fillRect):
* Source/WebCore/platform/graphics/BifurcatedGraphicsContext.h:
* Source/WebCore/platform/graphics/GraphicsContext.h:
* Source/WebCore/platform/graphics/NullGraphicsContext.h:
* Source/WebCore/platform/graphics/cairo/CairoOperations.cpp:
(WebCore::Cairo::FillSource::FillSource):
* Source/WebCore/platform/graphics/cairo/CairoOperations.h:
* Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp:
(WebCore::GraphicsContextCairo::fillRect):
* Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.h:
* Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::GraphicsContextCG::fillRect):
* Source/WebCore/platform/graphics/cg/GraphicsContextCG.h:
* Source/WebCore/platform/graphics/displaylists/DisplayListItem.h:
* Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp:
(WebCore::DisplayList::FillRectWithGradient::apply const):
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::FillRectWithGradientAndSpaceTransform):
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::apply const):
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::dump const):
* Source/WebCore/platform/graphics/displaylists/DisplayListItems.h:
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::rect const):
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::gradient const):
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::gradientSpaceTransform const):
* Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp:
(WebCore::DisplayList::Recorder::fillRect):
* Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h:
* Source/WebCore/platform/graphics/displaylists/DisplayListRecorderImpl.cpp:
(WebCore::DisplayList::RecorderImpl::recordFillRectWithGradientAndSpaceTransform):
* Source/WebCore/platform/graphics/displaylists/DisplayListRecorderImpl.h:
* Source/WebCore/platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.cpp:
(Nicosia::CairoOperationRecorder::fillRect):
* Source/WebCore/platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.h:
* Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp:
(WebKit::RemoteDisplayListRecorder::fillRectWithGradientAndSpaceTransform):
* Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.h:
* Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.messages.in:
* Source/WebKit/Shared/DisplayListArgumentCoders.serialization.in:
* Source/WebKit/WebProcess/GPU/graphics/RemoteDisplayListRecorderProxy.cpp:
(WebKit::RemoteDisplayListRecorderProxy::recordFillRectWithGradientAndSpaceTransform):
* Source/WebKit/WebProcess/GPU/graphics/RemoteDisplayListRecorderProxy.h:

Canonical link: https://commits.webkit.org/272648@main

5f3b8af

Misc iOS, tvOS & watchOS macOS Linux Windows
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 wincairo
✅ 🧪 bindings ✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 api-wpe
✅ 🧪 ios-wk2-wpt ✅ 🧪 mac-wk1 ✅ 🛠 gtk
✅ 🧪 api-ios ✅ 🧪 mac-wk2 ✅ 🧪 gtk-wk2
✅ 🛠 tv ✅ 🧪 mac-AS-debug-wk2 ✅ 🧪 api-gtk
✅ 🛠 tv-sim
✅ 🛠 🧪 merge ✅ 🛠 watch
✅ 🛠 watch-sim

@nikolaszimmermann nikolaszimmermann self-assigned this Jan 3, 2024
@nikolaszimmermann nikolaszimmermann added the SVG For bugs in the SVG implementation. label Jan 3, 2024
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just pass m_gradient and the reference operator will implicitly do the conversion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can have only this constructor and you make the RecorderImpl pass

append(FillRectWithGradientAndSpaceTransform(rect, Ref { gradient }, gradientSpaceTransform));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to check. I followed the existing pattern where most classes offer two constructors, e.g.

DrawDisplayListItems::DrawDisplayListItems(const Vector<Item>& items, const FloatPoint& destination)
    : m_items(items)
    , m_destination(destination)
{
}

DrawDisplayListItems::DrawDisplayListItems(Vector<Item>&& items, const FloatPoint& destination)
    : m_items(WTFMove(items))
    , m_destination(destination)
{
}

However, we can try to unify them, and get rid of the FIXME in the DisplayListItems header as well for both FillRectWithGradient and the new FillRectWithGradientAndSpaceTransform.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One possibility is to keep only the constructor taking the rvalue references, e.g.:

diff --git a/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h b/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h
index 0e4218629b6c..5befb335467b 100644
--- a/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h
+++ b/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h
@@ -936,8 +936,7 @@ class FillRectWithGradient {
 public:
     static constexpr char name[] = "fill-rect-with-gradient";
 
-    WEBCORE_EXPORT FillRectWithGradient(const FloatRect&, Gradient&);
-    WEBCORE_EXPORT FillRectWithGradient(FloatRect&&, Ref<Gradient>&&);
+    WEBCORE_EXPORT FillRectWithGradient(const FloatRect&&, Ref<Gradient>&&);
 
     const FloatRect& rect() const { return m_rect; }
     const Ref<Gradient>& gradient() const { return m_gradient; }

Note the rather unfamiiar "const Foo&&" usage, that is required to pass on the "const FloatRect&" from the recorder as-is:

diff --git a/Source/WebCore/platform/graphics/displaylists/DisplayListRecorderImpl.cpp b/Source/WebCore/platform/graphics/displaylists/DisplayListRecorderImpl.cpp
index 69f9b7705378..061981b04ffd 100644
--- a/Source/WebCore/platform/graphics/displaylists/DisplayListRecorderImpl.cpp
+++ b/Source/WebCore/platform/graphics/displaylists/DisplayListRecorderImpl.cpp
@@ -274,12 +274,12 @@ void RecorderImpl::recordFillRectWithColor(const FloatRect& rect, const Color& c
 
 void RecorderImpl::recordFillRectWithGradient(const FloatRect& rect, Gradient& gradient)
 {
-    append(FillRectWithGradient(rect, gradient));
+    append(FillRectWithGradient(WTFMove(rect), Ref { gradient }));
 }

I will try this further and see if I hit any issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DisplayListTests (API tests) require a change, that makes the code slightly harder to read:

diff --git a/Tools/TestWebKitAPI/Tests/WebCore/DisplayListTests.cpp b/Tools/TestWebKitAPI/Tests/WebCore/DisplayListTests.cpp
index d45c209e3951..200639129af4 100644
--- a/Tools/TestWebKitAPI/Tests/WebCore/DisplayListTests.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebCore/DisplayListTests.cpp
@@ -74,7 +74,10 @@ TEST(DisplayListTests, AppendItems)
     for (int i = 0; i < 50; ++i) {
         list.append(SetInlineStroke(1.5));
         list.append(FillPath(path));
-        list.append(FillRectWithGradient(FloatRect { 1., 1., 10., 10. }, gradient));
+        {
+            auto rect = FloatRect { 1., 1., 10., 10. };
+            list.append(FillRectWithGradient(WTFMove(rect), Ref { gradient }));
+        }
         list.append(SetInlineFillColor(Color::red));
 #if ENABLE(INLINE_PATH_DATA)
         list.append(StrokeLine(PathDataLine { { 0., 0. }, { 10., 15. } }));

Anything else benefits so, I think we should still go with your suggestion, and get away with a single constructor.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think we should make the apply methods non const functions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will have a look at it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mutable is unnecessary, there is no const method that attempts to modify 'm_gradient'.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the change cover the fillRect() only? Do not we need to add a similar variant to strokeRect()?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, stroking is not needed, at least not for the purposes of LBSE gradients. I need to be able to fill a rectangle using the stroke, gradient in a clean way.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't just the caller do this:

CGContextStateSaver stateSaver(context);
context.setFillGradient(gradient, gradientSpaceTransform);
context.fillRect(rect);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is fully correct, however, I need it in a cross-platform fashion.

To achieve that before this patch, I simply adjusted the fill gradient to point to the stroke gradient, fill the rectangle, and swap back. To avoid that, I added the new fillRect variant.

@nikolaszimmermann nikolaszimmermann force-pushed the eng/Provide-GraphicsContextfillRectconst-FloatRect-Gradient-const-AffineTransform-gradientSpaceTransform-variant branch from 88a79e2 to c974a5d Compare January 3, 2024 21:31
@nikolaszimmermann
Copy link
Copy Markdown
Contributor Author

@shallawa pushed a new version addressing all comments.

@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Jan 3, 2024
@nikolaszimmermann
Copy link
Copy Markdown
Contributor Author

That won't work, e.g. Gtk complains:

/app/webkit/WebKitBuild/GTK/Release/WTF/Headers/wtf/StdLibExtras.h: In instantiation of ‘constexpr typename std::remove_reference<_Arg>::type&& std::move(T&&) [with WTF::CheckMoveParameterTag <anonymous> = WTF::CheckMoveParameter; T = const WebCore::FloatRect&; typename remove_reference<_Arg>::type = const WebCore::FloatRect]’:
/app/webkit/Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp:559:14:   required from here
/app/webkit/WebKitBuild/GTK/Release/WTF/Headers/wtf/StdLibExtras.h:580:51: error: static assertion failed: T is const qualified.
  580 |     static_assert(!is_const<NonRefQualifiedType>::value, "T is const qualified.");
      |                                                   ^~~~~

I will stay with the two constructors, as the other DisplayListItems handle it.

@nikolaszimmermann nikolaszimmermann removed the merging-blocked Applied to prevent a change from being merged label Jan 3, 2024
@nikolaszimmermann nikolaszimmermann force-pushed the eng/Provide-GraphicsContextfillRectconst-FloatRect-Gradient-const-AffineTransform-gradientSpaceTransform-variant branch from c974a5d to 5f3b8af Compare January 3, 2024 22:41
@nikolaszimmermann nikolaszimmermann added the merge-queue Applied to send a pull request to merge-queue label Jan 4, 2024
…AffineTransform& gradientSpaceTransform) variant

https://bugs.webkit.org/show_bug.cgi?id=267040

Reviewed by Said Abou-Hallawa.

The existing fillRect(const FloatRect&, Gradient&) accessor, only calls
gradient.paint(), but does not handle gradient space transformations, nor
drop shadows, nor does it clip to the rect, etc. in contrary to the generic
fillRect(const FloatRect&) variant, which supports all these features,
but only when using the fillGradient() and the fillGradientSpaceTransform().

For LBSE gradient support it would be useful to be able to fill a rectangle
using the _stroke_ gradient, therefore extend the GraphicsContext::fillRect()
variants to provide one that takes a specific Gradient + AffineTransform pair.

Implement the new fillRect() variant in various places: NullGraphicsContext,
BifurcatedGraphicsCOntext, and all other variants inheriting from GraphicsContext.

No change in existing functionality, thus no new tests.

* Source/WebCore/platform/graphics/BifurcatedGraphicsContext.cpp:
(WebCore::BifurcatedGraphicsContext::fillRect):
* Source/WebCore/platform/graphics/BifurcatedGraphicsContext.h:
* Source/WebCore/platform/graphics/GraphicsContext.h:
* Source/WebCore/platform/graphics/NullGraphicsContext.h:
* Source/WebCore/platform/graphics/cairo/CairoOperations.cpp:
(WebCore::Cairo::FillSource::FillSource):
* Source/WebCore/platform/graphics/cairo/CairoOperations.h:
* Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp:
(WebCore::GraphicsContextCairo::fillRect):
* Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.h:
* Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::GraphicsContextCG::fillRect):
* Source/WebCore/platform/graphics/cg/GraphicsContextCG.h:
* Source/WebCore/platform/graphics/displaylists/DisplayListItem.h:
* Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp:
(WebCore::DisplayList::FillRectWithGradient::apply const):
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::FillRectWithGradientAndSpaceTransform):
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::apply const):
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::dump const):
* Source/WebCore/platform/graphics/displaylists/DisplayListItems.h:
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::rect const):
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::gradient const):
(WebCore::DisplayList::FillRectWithGradientAndSpaceTransform::gradientSpaceTransform const):
* Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp:
(WebCore::DisplayList::Recorder::fillRect):
* Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h:
* Source/WebCore/platform/graphics/displaylists/DisplayListRecorderImpl.cpp:
(WebCore::DisplayList::RecorderImpl::recordFillRectWithGradientAndSpaceTransform):
* Source/WebCore/platform/graphics/displaylists/DisplayListRecorderImpl.h:
* Source/WebCore/platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.cpp:
(Nicosia::CairoOperationRecorder::fillRect):
* Source/WebCore/platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.h:
* Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp:
(WebKit::RemoteDisplayListRecorder::fillRectWithGradientAndSpaceTransform):
* Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.h:
* Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.messages.in:
* Source/WebKit/Shared/DisplayListArgumentCoders.serialization.in:
* Source/WebKit/WebProcess/GPU/graphics/RemoteDisplayListRecorderProxy.cpp:
(WebKit::RemoteDisplayListRecorderProxy::recordFillRectWithGradientAndSpaceTransform):
* Source/WebKit/WebProcess/GPU/graphics/RemoteDisplayListRecorderProxy.h:

Canonical link: https://commits.webkit.org/272648@main
@webkit-commit-queue webkit-commit-queue force-pushed the eng/Provide-GraphicsContextfillRectconst-FloatRect-Gradient-const-AffineTransform-gradientSpaceTransform-variant branch from 5f3b8af to df59d72 Compare January 4, 2024 08:42
@webkit-commit-queue
Copy link
Copy Markdown
Collaborator

Committed 272648@main (df59d72): https://commits.webkit.org/272648@main

Reviewed commits have been landed. Closing PR #22352 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit df59d72 into WebKit:main Jan 4, 2024
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Jan 4, 2024
@nikolaszimmermann nikolaszimmermann deleted the eng/Provide-GraphicsContextfillRectconst-FloatRect-Gradient-const-AffineTransform-gradientSpaceTransform-variant branch January 4, 2024 08:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

SVG For bugs in the SVG implementation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants