Changeset 284888 in webkit
- Timestamp:
- Oct 26, 2021, 12:42:43 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp (modified) (7 diffs)
-
Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h (modified) (1 diff)
-
Source/WebCore/platform/graphics/displaylists/DisplayListRecorderImpl.cpp (modified) (1 diff)
-
Source/WebCore/platform/graphics/transforms/AffineTransform.h (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebCore/cg/BifurcatedGraphicsContextTestsCG.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r284883 r284888 1 2021-10-26 Tim Horton <timothy_horton@apple.com> 2 3 DisplayList::Recorder's clipBounds() becomes empty if a flip is applied to the CTM 4 https://bugs.webkit.org/show_bug.cgi?id=232134 5 6 Reviewed by Darin Adler. 7 8 New test: BifurcatedGraphicsContextTests.TransformedClip 9 10 * platform/graphics/displaylists/DisplayListRecorder.cpp: 11 (WebCore::DisplayList::Recorder::clip): 12 (WebCore::DisplayList::Recorder::clipPath): 13 (WebCore::DisplayList::Recorder::clipBounds const): 14 Instead of updating clipBounds any time the CTM changes, store 15 clipBounds in base coordinates and map through the CTM when retrieved. 16 17 This matches CG's behavior and makes the clipBounds much sturdier. 18 For example, previously, applying a `scale(1, -1)` to the context 19 would immediately result in the clipBounds' height becoming negative, 20 making the bounds empty and confusing anything that reads from it. 21 22 (WebCore::DisplayList::Recorder::ContextState::translate): 23 (WebCore::DisplayList::Recorder::ContextState::rotate): 24 (WebCore::DisplayList::Recorder::ContextState::scale): 25 (WebCore::DisplayList::Recorder::ContextState::setCTM): 26 (WebCore::DisplayList::Recorder::ContextState::concatCTM): 27 Stop updating the clipBounds when the CTM changes, this is no longer necessary. 28 29 * platform/graphics/displaylists/DisplayListRecorderImpl.cpp: 30 (WebCore::DisplayList::RecorderImpl::extentFromLocalBounds): 31 Since the clipBounds is now in base space, map the display list 32 item bounds to base space /before/ intersecting it with clipBounds. 33 34 * platform/graphics/displaylists/DisplayListRecorder.h: 35 Drive-by add a default parameter so getCTM can be called on the subclass the same way it can on GraphicsContext. 36 37 * platform/graphics/transforms/AffineTransform.h: Fix a typo. 38 1 39 2021-10-26 Chris Dumez <cdumez@apple.com> 2 40 -
trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp
r284003 r284888 425 425 void Recorder::clip(const FloatRect& rect) 426 426 { 427 currentState().clipBounds.intersect( rect);427 currentState().clipBounds.intersect(currentState().ctm.mapRect(rect)); 428 428 recordClip(rect); 429 429 } … … 441 441 void Recorder::clipPath(const Path& path, WindRule windRule) 442 442 { 443 currentState().clipBounds.intersect( path.fastBoundingRect());443 currentState().clipBounds.intersect(currentState().ctm.mapRect(path.fastBoundingRect())); 444 444 recordClipPath(path, windRule); 445 445 } … … 447 447 IntRect Recorder::clipBounds() const 448 448 { 449 if (auto inverse = currentState().ctm.inverse()) 450 return enclosingIntRect(inverse->mapRect(currentState().clipBounds)); 451 452 // If the CTM is not invertible, return the original rect. 453 // This matches CGRectApplyInverseAffineTransform behavior. 449 454 return enclosingIntRect(currentState().clipBounds); 450 455 } … … 522 527 { 523 528 ctm.translate(x, y); 524 clipBounds.move(-x, -y);525 529 } 526 530 … … 532 536 AffineTransform rotation; 533 537 rotation.rotate(angleInDegrees); 534 535 if (std::optional<AffineTransform> inverse = rotation.inverse())536 clipBounds = inverse.value().mapRect(clipBounds);537 538 } 538 539 … … 540 541 { 541 542 ctm.scale(size); 542 clipBounds.scale(1 / size.width(), 1 / size.height());543 543 } 544 544 545 545 void Recorder::ContextState::setCTM(const AffineTransform& matrix) 546 546 { 547 std::optional<AffineTransform> inverseTransformForClipBounds;548 if (auto originalCTMInverse = ctm.inverse())549 inverseTransformForClipBounds = originalCTMInverse->multiply(matrix).inverse();550 551 547 ctm = matrix; 552 553 if (inverseTransformForClipBounds)554 clipBounds = inverseTransformForClipBounds->mapRect(clipBounds);555 548 } 556 549 … … 558 551 { 559 552 ctm *= matrix; 560 561 if (std::optional<AffineTransform> inverse = matrix.inverse())562 clipBounds = inverse.value().mapRect(clipBounds);563 553 } 564 554 -
trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h
r284858 r284888 256 256 WEBCORE_EXPORT void concatCTM(const AffineTransform&) final; 257 257 WEBCORE_EXPORT void setCTM(const AffineTransform&) final; 258 WEBCORE_EXPORT AffineTransform getCTM(GraphicsContext::IncludeDeviceScale ) const final;258 WEBCORE_EXPORT AffineTransform getCTM(GraphicsContext::IncludeDeviceScale = PossiblyIncludeDeviceScale) const final; 259 259 260 260 WEBCORE_EXPORT void beginTransparencyLayer(float opacity) final; -
trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorderImpl.cpp
r284858 r284888 459 459 } 460 460 461 FloatRect clippedExtent = intersection(state.clipBounds, bounds); 462 return state.ctm.mapRect(clippedExtent); 461 return intersection(state.clipBounds, state.ctm.mapRect(bounds)); 463 462 } 464 463 -
trunk/Source/WebCore/platform/graphics/transforms/AffineTransform.h
r284600 r284888 133 133 WEBCORE_EXPORT double yScale() const; 134 134 135 bool isInvertible() const; // If you call this this, you're probably doing it wrong.135 bool isInvertible() const; // If you call this, you're probably doing it wrong. 136 136 WEBCORE_EXPORT std::optional<AffineTransform> inverse() const; 137 137 -
trunk/Tools/ChangeLog
r284887 r284888 1 2021-10-26 Tim Horton <timothy_horton@apple.com> 2 3 DisplayList::Recorder's clipBounds() becomes empty if a flip is applied to the CTM 4 https://bugs.webkit.org/show_bug.cgi?id=232134 5 6 Reviewed by Darin Adler. 7 8 * TestWebKitAPI/Tests/WebCore/cg/BifurcatedGraphicsContextTestsCG.cpp: 9 (TestWebKitAPI::TEST): 10 Add a test ensuring that our clipBounds and CG's match through a series 11 of simple transforms. 12 1 13 2021-10-26 Brady Eidson <beidson@apple.com> 2 14 -
trunk/Tools/TestWebKitAPI/Tests/WebCore/cg/BifurcatedGraphicsContextTestsCG.cpp
r284003 r284888 220 220 } 221 221 222 TEST(BifurcatedGraphicsContextTests, TransformedClip) 223 { 224 auto colorSpace = DestinationColorSpace::SRGB(); 225 auto primaryCGContext = adoptCF(CGBitmapContextCreate(nullptr, 100, 100, 8, 4 * 100, colorSpace.platformColorSpace(), kCGImageAlphaPremultipliedLast)); 226 227 GraphicsContextCG primaryContextCG(primaryCGContext.get()); 228 GraphicsContext& primaryContext = primaryContextCG; 229 230 InMemoryDisplayList displayList; 231 RecorderImpl secondaryContextDL(displayList, { }, FloatRect(0, 0, 100, 100), { }); 232 GraphicsContext& secondaryContext = secondaryContextDL; 233 234 BifurcatedGraphicsContext ctx(primaryContext, secondaryContext); 235 236 ctx.clip(FloatRect(25, 25, 50, 50)); 237 238 EXPECT_EQ(primaryContext.clipBounds(), secondaryContext.clipBounds()); 239 EXPECT_EQ(primaryContext.clipBounds(), FloatRect(25, 25, 50, 50)); 240 241 ctx.scale({ 1, -1 }); 242 ctx.translate(0, -100); 243 244 EXPECT_EQ(primaryContext.clipBounds(), secondaryContext.clipBounds()); 245 EXPECT_EQ(primaryContext.clipBounds(), FloatRect(25, 25, 50, 50)); 246 247 ctx.scale(2); 248 249 EXPECT_EQ(primaryContext.clipBounds(), secondaryContext.clipBounds()); 250 EXPECT_EQ(primaryContext.clipBounds(), FloatRect(12, 12, 26, 26)); 251 252 { 253 GraphicsContextStateSaver saver(ctx); 254 255 ctx.translate(12, 12); 256 257 EXPECT_EQ(primaryContext.clipBounds(), secondaryContext.clipBounds()); 258 EXPECT_EQ(primaryContext.clipBounds(), FloatRect(0, 0, 26, 26)); 259 260 ctx.clip(FloatRect(0, 0, 10, 10)); 261 262 EXPECT_EQ(primaryContext.clipBounds(), secondaryContext.clipBounds()); 263 EXPECT_EQ(primaryContext.clipBounds(), FloatRect(0, 0, 10, 10)); 264 265 ctx.rotate(M_PI / 6); 266 267 EXPECT_EQ(primaryContext.clipBounds(), secondaryContext.clipBounds()); 268 EXPECT_EQ(primaryContext.clipBounds(), FloatRect(0, -5, 14, 14)); 269 } 270 271 EXPECT_EQ(primaryContext.clipBounds(), secondaryContext.clipBounds()); 272 EXPECT_EQ(primaryContext.clipBounds(), FloatRect(12, 12, 26, 26)); 273 274 // Make the CTM non-invertible. 275 ctx.scale({ 0, 1 }); 276 277 EXPECT_EQ(primaryContext.clipBounds(), secondaryContext.clipBounds()); 278 EXPECT_EQ(primaryContext.clipBounds(), FloatRect(25, 25, 50, 50)); 279 } 280 222 281 } // namespace TestWebKitAPI 223 282
Note:
See TracChangeset
for help on using the changeset viewer.