Title: [246391] trunk
Revision
246391
Author
[email protected]
Date
2019-06-12 21:10:33 -0700 (Wed, 12 Jun 2019)

Log Message

[cairo][SVG] If clipPath has multiple elements, clip-path doesn't work with transform
https://bugs.webkit.org/show_bug.cgi?id=198746
Source/WebCore:

Patch by Carlos Garcia Campos <[email protected]> on 2019-06-12
Reviewed by Don Olmstead.

We need to save the current transformation matrix at the moment the image mask is set and set it again on
restore right before applying the mask. This patch also creates a pattern for the image mask surface and set its
transformation matrix according to the mask position, so that we don't need to save the mask rectangle too.

Tests: svg/clip-path/clip-hidpi-expected.svg
       svg/clip-path/clip-hidpi.svg
       svg/clip-path/clip-opacity-translate-expected.svg
       svg/clip-path/clip-opacity-translate.svg

* platform/graphics/cairo/PlatformContextCairo.cpp:
(WebCore::PlatformContextCairo::restore):
(WebCore::PlatformContextCairo::pushImageMask):

LayoutTests:

<rdar://problem/51620347>

Patch by Carlos Garcia Campos <[email protected]> on 2019-06-12
Reviewed by Don Olmstead.

* svg/clip-path/clip-hidpi-expected.svg: Added.
* svg/clip-path/clip-hidpi.svg: Added.
* svg/clip-path/clip-opacity-translate-expected.svg: Added.
* svg/clip-path/clip-opacity-translate.svg: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (246390 => 246391)


--- trunk/LayoutTests/ChangeLog	2019-06-13 03:44:24 UTC (rev 246390)
+++ trunk/LayoutTests/ChangeLog	2019-06-13 04:10:33 UTC (rev 246391)
@@ -1,3 +1,16 @@
+2019-06-12  Carlos Garcia Campos  <[email protected]>
+
+        [cairo][SVG] If clipPath has multiple elements, clip-path doesn't work with transform
+        https://bugs.webkit.org/show_bug.cgi?id=198746
+        <rdar://problem/51620347>
+
+        Reviewed by Don Olmstead.
+
+        * svg/clip-path/clip-hidpi-expected.svg: Added.
+        * svg/clip-path/clip-hidpi.svg: Added.
+        * svg/clip-path/clip-opacity-translate-expected.svg: Added.
+        * svg/clip-path/clip-opacity-translate.svg: Added.
+
 2019-06-12  Myles C. Maxfield  <[email protected]>
 
         [WHLSL] Educate the property resolver about IndexExpressions

Added: trunk/LayoutTests/svg/clip-path/clip-hidpi-expected.svg (0 => 246391)


--- trunk/LayoutTests/svg/clip-path/clip-hidpi-expected.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/clip-path/clip-hidpi-expected.svg	2019-06-13 04:10:33 UTC (rev 246391)
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+<!-- The FO should be clipped with only the green half visible. -->
+<defs>
+<clipPath id="clip">
+    <rect width="200" height="50"/>
+    <rect width="200" height="50"/>
+</clipPath>
+</defs>
+<foreignObject width="200" height="100" clip-path="url(#clip)" opacity=".5">
+    <html xmlns="http://www.w3.org/1999/xhtml">
+    <body>
+        <div style="background: green; height: 50px;"></div>
+        <div style="background: red; height: 50px;"></div>
+    </body>
+    </html>
+</foreignObject>
+</svg>
+

Added: trunk/LayoutTests/svg/clip-path/clip-hidpi.svg (0 => 246391)


--- trunk/LayoutTests/svg/clip-path/clip-hidpi.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/clip-path/clip-hidpi.svg	2019-06-13 04:10:33 UTC (rev 246391)
@@ -0,0 +1,22 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+<!-- The FO should be clipped with only the green half visible. -->
+<defs>
+<clipPath id="clip">
+    <rect width="200" height="50"/>
+    <rect width="200" height="50"/>
+</clipPath>
+</defs>
+<foreignObject width="200" height="100" clip-path="url(#clip)" opacity=".5">
+    <html xmlns="http://www.w3.org/1999/xhtml">
+    <body>
+        <div style="background: green; height: 50px;"></div>
+        <div style="background: red; height: 50px;"></div>
+    </body>
+    </html>
+</foreignObject>
+<script>
+  testRunner.setBackingScaleFactor(2, () -> { testRunner.notifyDone() });
+  testRunner.waitUntilDone();
+</script>
+</svg>
+

Added: trunk/LayoutTests/svg/clip-path/clip-opacity-translate-expected.svg (0 => 246391)


--- trunk/LayoutTests/svg/clip-path/clip-opacity-translate-expected.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/clip-path/clip-opacity-translate-expected.svg	2019-06-13 04:10:33 UTC (rev 246391)
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="350">
+<g>
+  <circle cx="50" cy="50" r="50" fill="green"/>
+  <circle cx="100" cy="50" r="50" fill="red" />
+  <g opacity=".5">
+    <circle cx="50" cy="100" r="50" fill="green"/>
+    <circle cx="100" cy="100" r="50" fill="red" />
+  </g>
+</g>
+<g transform="translate(200,0)">
+  <circle cx="50" cy="50" r="50" fill="green"/>
+  <circle cx="100" cy="50" r="50" fill="red" />
+  <g opacity=".5">
+    <circle cx="50" cy="100" r="50" fill="green"/>
+    <circle cx="100" cy="100" r="50" fill="red" />
+  </g>
+</g>
+</svg>

Added: trunk/LayoutTests/svg/clip-path/clip-opacity-translate.svg (0 => 246391)


--- trunk/LayoutTests/svg/clip-path/clip-opacity-translate.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/clip-path/clip-opacity-translate.svg	2019-06-13 04:10:33 UTC (rev 246391)
@@ -0,0 +1,27 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="350">
+<defs>
+<clipPath id="clip1">
+    <rect width="200" height="200"/>
+</clipPath>
+<clipPath id="clip2">
+    <rect width="200" height="200"/>
+    <rect width="200" height="200"/>
+</clipPath>
+</defs>
+<g>
+  <circle cx="50" cy="50" r="50" fill="green"/>
+  <circle cx="100" cy="50" r="50" fill="red" />
+  <g clip-path="url(#clip1)" opacity=".5">
+    <circle cx="50" cy="100" r="50" fill="green"/>
+    <circle cx="100" cy="100" r="50" fill="red" />
+  </g>
+</g>
+<g transform="translate(200,0)">
+  <circle cx="50" cy="50" r="50" fill="green"/>
+  <circle cx="100" cy="50" r="50" fill="red" />
+  <g clip-path="url(#clip2)" opacity=".5">
+    <circle cx="50" cy="100" r="50" fill="green"/>
+    <circle cx="100" cy="100" r="50" fill="red" />
+  </g>
+</g>
+</svg>

Modified: trunk/Source/WebCore/ChangeLog (246390 => 246391)


--- trunk/Source/WebCore/ChangeLog	2019-06-13 03:44:24 UTC (rev 246390)
+++ trunk/Source/WebCore/ChangeLog	2019-06-13 04:10:33 UTC (rev 246391)
@@ -1,3 +1,23 @@
+2019-06-12  Carlos Garcia Campos  <[email protected]>
+
+        [cairo][SVG] If clipPath has multiple elements, clip-path doesn't work with transform
+        https://bugs.webkit.org/show_bug.cgi?id=198746
+
+        Reviewed by Don Olmstead.
+
+        We need to save the current transformation matrix at the moment the image mask is set and set it again on
+        restore right before applying the mask. This patch also creates a pattern for the image mask surface and set its
+        transformation matrix according to the mask position, so that we don't need to save the mask rectangle too.
+
+        Tests: svg/clip-path/clip-hidpi-expected.svg
+               svg/clip-path/clip-hidpi.svg
+               svg/clip-path/clip-opacity-translate-expected.svg
+               svg/clip-path/clip-opacity-translate.svg
+
+        * platform/graphics/cairo/PlatformContextCairo.cpp:
+        (WebCore::PlatformContextCairo::restore):
+        (WebCore::PlatformContextCairo::pushImageMask):
+
 2019-06-12  Simon Fraser  <[email protected]>
 
         paddingBoxRect() is wrong with RTL scrollbars on the left

Modified: trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp (246390 => 246391)


--- trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp	2019-06-13 03:44:24 UTC (rev 246390)
+++ trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp	2019-06-13 04:10:33 UTC (rev 246391)
@@ -30,34 +30,10 @@
 
 #if USE(CAIRO)
 
-#include "CairoUtilities.h"
-#include "Gradient.h"
-#include "GraphicsContext.h"
-#include "Pattern.h"
 #include <cairo.h>
 
 namespace WebCore {
 
-// In Cairo image masking is immediate, so to emulate image clipping we must save masking
-// details as part of the context state and apply them during platform restore.
-class ImageMaskInformation {
-public:
-    void update(cairo_surface_t* maskSurface, const FloatRect& maskRect)
-    {
-        m_maskSurface = maskSurface;
-        m_maskRect = maskRect;
-    }
-
-    bool isValid() const { return m_maskSurface; }
-    cairo_surface_t* maskSurface() const { return m_maskSurface.get(); }
-    const FloatRect& maskRect() const { return m_maskRect; }
-
-private:
-    RefPtr<cairo_surface_t> m_maskSurface;
-    FloatRect m_maskRect;
-};
-
-
 // Encapsulates the additional painting state information we store for each
 // pushed graphics state.
 class PlatformContextCairo::State {
@@ -64,7 +40,10 @@
 public:
     State() = default;
 
-    ImageMaskInformation m_imageMaskInformation;
+    struct {
+        RefPtr<cairo_pattern_t> pattern;
+        cairo_matrix_t matrix;
+    } m_mask;
 };
 
 PlatformContextCairo::PlatformContextCairo(cairo_t* cr)
@@ -76,11 +55,14 @@
 
 void PlatformContextCairo::restore()
 {
-    const ImageMaskInformation& maskInformation = m_state->m_imageMaskInformation;
-    if (maskInformation.isValid()) {
-        const FloatRect& maskRect = maskInformation.maskRect();
+    if (m_state->m_mask.pattern) {
         cairo_pop_group_to_source(m_cr.get());
-        cairo_mask_surface(m_cr.get(), maskInformation.maskSurface(), maskRect.x(), maskRect.y());
+
+        cairo_matrix_t matrix;
+        cairo_get_matrix(m_cr.get(), &matrix);
+        cairo_set_matrix(m_cr.get(), &m_state->m_mask.matrix);
+        cairo_mask(m_cr.get(), m_state->m_mask.pattern.get());
+        cairo_set_matrix(m_cr.get(), &matrix);
     }
 
     m_stateStack.removeLast();
@@ -105,11 +87,13 @@
     // We must call savePlatformState at least once before we can use image masking,
     // since we actually apply the mask in restorePlatformState.
     ASSERT(!m_stateStack.isEmpty());
-    m_state->m_imageMaskInformation.update(surface, rect);
+    m_state->m_mask.pattern = adoptRef(cairo_pattern_create_for_surface(surface));
+    cairo_get_matrix(m_cr.get(), &m_state->m_mask.matrix);
 
-    // Cairo doesn't support the notion of an image clip, so we push a group here
-    // and then paint it to the surface with an image mask (which is an immediate
-    // operation) during restorePlatformState.
+    cairo_matrix_t matrix;
+    cairo_matrix_init_translate(&matrix, -rect.x(), -rect.y());
+    cairo_pattern_set_matrix(m_state->m_mask.pattern.get(), &matrix);
+
     cairo_push_group(m_cr.get());
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to