Skip to content

Commit

Permalink
Cherry-pick 68eec7e. rdar://problem/113608292
Browse files Browse the repository at this point in the history
    Cherry-pick bc52720. rdar://problem/111934640

        Path::transform() should not trigger creation of a platform path
        https://bugs.webkit.org/show_bug.cgi?id=258759
        rdar://problem/111934640

        Reviewed by Simon Fraser.

        Many paths consist only of Move/Line/Quadratic/Cubic/Close segments, which are
        all simple to apply an AffineTransform to. Transform single segment and PathStream
        based paths in place when Path::transform() is called, to avoid the overhead of
        generating a CGPath. If other segment types are in the path, continue to convert
        to a platform path first.

        Some WPT (path + transform) tests fail on GTK ports because the tests are fragile
        to floating point calculations. The tests rotate the context by 90 degree and scale
        it by 283 then they stroke a line to cover the whole canvas by the stroke color.
        If we scale by 282, the last row in the canvas will not be stroked even without
        this patch. On GKT port and with this patch, the last row is stroked but it is
        anti-aliased with the background.

        * LayoutTests/platform/glib/TestExpectations:
        * Source/WebCore/platform/graphics/Path.cpp:
        (WebCore::Path::transform):
        * Source/WebCore/platform/graphics/PathImpl.h:
        * Source/WebCore/platform/graphics/PathSegment.cpp:
        (WebCore::PathSegment::canTransform const):
        (WebCore::PathSegment::transform):
        * Source/WebCore/platform/graphics/PathSegment.h:
        * Source/WebCore/platform/graphics/PathSegmentData.cpp:
        (WebCore::PathMoveTo::transform):
        (WebCore::PathLineTo::transform):
        (WebCore::PathQuadCurveTo::transform):
        (WebCore::PathBezierCurveTo::transform):
        (WebCore::PathDataLine::transform):
        (WebCore::PathDataQuadCurve::transform):
        (WebCore::PathDataBezierCurve::transform):
        (WebCore::PathCloseSubpath::transform):
        * Source/WebCore/platform/graphics/PathSegmentData.h:
        * Source/WebCore/platform/graphics/PathStream.cpp:
        (WebCore::PathStream::transform):
        * Source/WebCore/platform/graphics/PathStream.h:
        * Source/WebCore/platform/graphics/cairo/PathCairo.cpp:
        (WebCore::PathCairo::transform):
        * Source/WebCore/platform/graphics/cairo/PathCairo.h:
        * Source/WebCore/platform/graphics/cg/PathCG.cpp:
        (WebCore::PathCG::transform):
        * Source/WebCore/platform/graphics/cg/PathCG.h:

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

    Identifier: 265870.311@safari-7616.1.27.10-branch

Canonical link: https://commits.webkit.org/265870.347@safari-7616-branch
  • Loading branch information
heycam authored and Dan Robson committed Aug 11, 2023
1 parent cc48366 commit 3443658
Show file tree
Hide file tree
Showing 13 changed files with 216 additions and 5 deletions.
52 changes: 52 additions & 0 deletions LayoutTests/platform/glib/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -3361,6 +3361,58 @@ imported/w3c/web-platform-tests/svg/painting/reftests/marker-path-022.svg [ Fail
imported/w3c/web-platform-tests/svg/painting/reftests/marker-path-023.svg [ Failure ]
svg/W3C-SVG-1.1/painting-marker-03-f.svg [ Failure ]

# Path with transform failures
imported/w3c/web-platform-tests/html/canvas/element/path-objects/2d.path.stroke.skew.html [ Failure ]
imported/w3c/web-platform-tests/html/canvas/offscreen/path-objects/2d.path.stroke.skew.html [ Failure ]
imported/w3c/web-platform-tests/html/canvas/offscreen/path-objects/2d.path.stroke.skew.worker.html [ Failure ]

imported/w3c/web-platform-tests/preload/onerror-event.html [ DumpJSConsoleLogInStdErr ]
imported/w3c/web-platform-tests/preload/preload-time-to-fetch.https.html [ DumpJSConsoleLogInStdErr ]
imported/w3c/web-platform-tests/preload/preload-type-match.html [ DumpJSConsoleLogInStdErr ]

# Tests crashing in Debug only.
[ Debug ] css3/viewport-percentage-lengths/viewport-percentage-lengths-anonymous-block.html [ Crash ]
[ Debug ] css3/viewport-percentage-lengths/viewport-percentage-lengths-percent-size-child.html [ Crash ]
[ Debug ] css3/viewport-percentage-lengths/viewport-percentage-lengths-relative-font-size.html [ Crash ]
[ Debug ] css3/viewport-percentage-lengths/viewport-percentage-lengths-resize.html [ Crash ]
[ Debug ] editing/pasteboard/copy-paste-across-shadow-boundaries-with-style-2.html [ Crash ]
[ Debug ] fast/backgrounds/gradient-background-leakage-hidpi.html [ Crash ]
[ Debug ] fast/canvas/2d.backingStorePixelRatio.html [ Crash ]
[ Debug ] fast/canvas/canvas-as-image-hidpi.html [ Crash ]
[ Debug ] fast/canvas/canvas-resize-reset-pixelRatio.html [ Crash ]
[ Debug ] fast/css-custom-paint/simple-hidpi.html [ Crash ]
[ Debug ] fast/css-grid-layout/flex-content-sized-columns-resize.html [ Crash ]
[ Debug ] fast/dom/HTMLImageElement/sizes/image-sizes-2x.html [ Crash ]
[ Debug ] fast/dom/HTMLImageElement/sizes/image-sizes-js-change.html [ Crash ]
[ Debug ] fast/dom/HTMLImageElement/sizes/image-sizes-js-innerhtml.html [ Crash ]
[ Debug ] fast/dom/Window/window-resize-contents.html [ Crash ]
[ Debug ] fast/dom/Window/window-resize-update-scrollbars.html [ Crash ]
[ Debug ] fast/dynamic/window-resize-scrollbars-test.html [ Crash ]
[ Debug ] fast/fixed-layout/fixed-layout.html [ Crash ]
[ Debug ] fast/forms/textarea-node-removed-from-document-crash.html [ Crash ]
[ Debug ] fast/hidpi/broken-image-icon-hidpi.html [ Crash ]
[ Debug ] fast/hidpi/broken-image-icon-very-hidpi.html [ Crash ]
[ Debug ] fast/hidpi/broken-image-with-size-hidpi.html [ Crash ]
[ Debug ] fast/hidpi/clip-text-in-hidpi.html [ Crash ]
[ Debug ] fast/hidpi/device-scale-factor-paint.html [ Crash ]
[ Debug ] fast/hidpi/filters-and-image-buffer-resolution.html [ Crash ]
[ Debug ] fast/hidpi/filters-blur.html [ Crash ]
[ Debug ] fast/hidpi/filters-hue-rotate.html [ Crash ]
[ Debug ] fast/history/page-cache-closed-audiocontext.html [ Crash ]
[ Debug ] fast/media/mq-resolution.html [ Crash ]
[ Debug ] fast/picture/viewport-resize.html [ Crash ]
[ Debug ] http/tests/loading/sizes/preload-image-sizes-2x.html [ Crash ]
[ Debug ] http/wpt/dom-ranges-live-range/Range-mutations-deleteData.html [ Crash ]
[ Debug ] http/wpt/dom-ranges-live-range/Range-mutations-insertData.html [ Crash ]
[ Debug ] http/wpt/dom-ranges-live-range/Range-mutations-replaceData.html [ Crash ]
[ Debug ] imported/blink/fast/hidpi/border-background-align.html [ Crash ]
[ Debug ] imported/blink/svg/zoom/text/lowdpi-zoom-text.html [ Crash ]

# Tests timing out in Debug only.
[ Debug ] fast/css-custom-paint/out-of-memory-while-adding-worklet-module.html [ Timeout ]
[ Debug ] http/tests/xmlhttprequest/simple-cross-origin-progress-events.html [ Timeout ]
[ Debug ] imported/blink/transitions/remove-accelerated-transition.html [ Timeout ]

# End: Common failures between GTK and WPE.

#////////////////////////////////////////////////////////////////////////////////////////
Expand Down
8 changes: 8 additions & 0 deletions Source/WebCore/platform/graphics/Path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,14 @@ void Path::transform(const AffineTransform& transform)
if (transform.isIdentity() || isEmpty())
return;

auto segment = asSingle();
if (segment && segment->transform(transform))
return;

auto impl = asImpl();
if (impl && impl->transform(transform))
return;

ensurePlatformPathImpl().transform(transform);
}

Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/platform/graphics/PathImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class PathImpl {
virtual void applySegments(const PathSegmentApplier&) const = 0;
virtual void applyElements(const PathElementApplier&) const = 0;

virtual bool transform(const AffineTransform&) = 0;

virtual std::optional<PathSegment> singleSegment() const { return std::nullopt; }
virtual std::optional<PathDataLine> singleDataLine() const { return std::nullopt; }
virtual std::optional<PathArc> singleArc() const { return std::nullopt; }
Expand Down
18 changes: 18 additions & 0 deletions Source/WebCore/platform/graphics/PathSegment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,24 @@ void PathSegment::applyElements(const PathElementApplier& applier) const
});
}

bool PathSegment::canTransform() const
{
return WTF::switchOn(m_data, [&](auto& data) {
return data.canTransform;
});
}

bool PathSegment::transform(const AffineTransform& transform)
{
return WTF::switchOn(m_data, [&](auto& data) {
if constexpr (std::decay_t<decltype(data)>::canTransform) {
data.transform(transform);
return true;
}
return false;
});
}

TextStream& operator<<(TextStream& ts, const PathSegment& segment)
{
return WTF::switchOn(segment.data(), [&](auto& data) -> TextStream& {
Expand Down
3 changes: 3 additions & 0 deletions Source/WebCore/platform/graphics/PathSegment.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ class PathSegment {
void addToImpl(PathImpl&) const;
void applyElements(const PathElementApplier&) const;

bool canTransform() const;
bool transform(const AffineTransform&);

private:
Data m_data;
};
Expand Down
48 changes: 48 additions & 0 deletions Source/WebCore/platform/graphics/PathSegmentData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ void PathMoveTo::applyElements(const PathElementApplier& applier) const
applier({ PathElement::Type::MoveToPoint, { point } });
}

void PathMoveTo::transform(const AffineTransform& transform)
{
point = transform.mapPoint(point);
}

WTF::TextStream& operator<<(WTF::TextStream& ts, const PathMoveTo& data)
{
ts << "move to " << data.point;
Expand Down Expand Up @@ -88,6 +93,11 @@ void PathLineTo::applyElements(const PathElementApplier& applier) const
applier({ PathElement::Type::AddLineToPoint, { point } });
}

void PathLineTo::transform(const AffineTransform& transform)
{
point = transform.mapPoint(point);
}

WTF::TextStream& operator<<(WTF::TextStream& ts, const PathLineTo& data)
{
ts << "add line to " << data.point;
Expand Down Expand Up @@ -158,6 +168,12 @@ void PathQuadCurveTo::applyElements(const PathElementApplier& applier) const
applier({ PathElement::Type::AddQuadCurveToPoint, { controlPoint, endPoint } });
}

void PathQuadCurveTo::transform(const AffineTransform& transform)
{
controlPoint = transform.mapPoint(controlPoint);
endPoint = transform.mapPoint(endPoint);
}

WTF::TextStream& operator<<(WTF::TextStream& ts, const PathQuadCurveTo& data)
{
ts << "add quad curve to " << data.controlPoint << " " << data.endPoint;
Expand Down Expand Up @@ -265,6 +281,13 @@ void PathBezierCurveTo::applyElements(const PathElementApplier& applier) const
applier({ PathElement::Type::AddCurveToPoint, { controlPoint1, controlPoint2, endPoint } });
}

void PathBezierCurveTo::transform(const AffineTransform& transform)
{
controlPoint1 = transform.mapPoint(controlPoint1);
controlPoint2 = transform.mapPoint(controlPoint2);
endPoint = transform.mapPoint(endPoint);
}

WTF::TextStream& operator<<(WTF::TextStream& ts, const PathBezierCurveTo& data)
{
ts << "add curve to " << data.controlPoint1 << " " << data.controlPoint2 << " " << data.endPoint;
Expand Down Expand Up @@ -561,6 +584,12 @@ void PathDataLine::applyElements(const PathElementApplier& applier) const
applier({ PathElement::Type::AddLineToPoint, { end } });
}

void PathDataLine::transform(const AffineTransform& transform)
{
start = transform.mapPoint(start);
end = transform.mapPoint(end);
}

WTF::TextStream& operator<<(WTF::TextStream& ts, const PathDataLine& data)
{
ts << "move to " << data.start;
Expand Down Expand Up @@ -602,6 +631,13 @@ void PathDataQuadCurve::applyElements(const PathElementApplier& applier) const
applier({ PathElement::Type::AddQuadCurveToPoint, { controlPoint, endPoint } });
}

void PathDataQuadCurve::transform(const AffineTransform& transform)
{
start = transform.mapPoint(start);
controlPoint = transform.mapPoint(controlPoint);
endPoint = transform.mapPoint(endPoint);
}

WTF::TextStream& operator<<(WTF::TextStream& ts, const PathDataQuadCurve& data)
{
ts << "move to " << data.start;
Expand Down Expand Up @@ -645,6 +681,14 @@ void PathDataBezierCurve::applyElements(const PathElementApplier& applier) const
applier({ PathElement::Type::AddCurveToPoint, { controlPoint1, controlPoint2, endPoint } });
}

void PathDataBezierCurve::transform(const AffineTransform& transform)
{
start = transform.mapPoint(start);
controlPoint1 = transform.mapPoint(controlPoint1);
controlPoint2 = transform.mapPoint(controlPoint2);
endPoint = transform.mapPoint(endPoint);
}

WTF::TextStream& operator<<(WTF::TextStream& ts, const PathDataBezierCurve& data)
{
ts << "move to " << data.start;
Expand Down Expand Up @@ -712,6 +756,10 @@ void PathCloseSubpath::applyElements(const PathElementApplier& applier) const
applier({ PathElement::Type::CloseSubpath, { } });
}

void PathCloseSubpath::transform(const AffineTransform&)
{
}

WTF::TextStream& operator<<(WTF::TextStream& ts, const PathCloseSubpath&)
{
ts << "close subpath";
Expand Down
Loading

0 comments on commit 3443658

Please sign in to comment.