Implement DisplayListRecorder::Recorder::getCTM and DisplayListRecorder::Recorder...
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Dec 2019 03:49:14 +0000 (03:49 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Dec 2019 03:49:14 +0000 (03:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=205139

Reviewed by Simon Fraser.

Source/WebCore:

Implements these two methods on Recorder, which are invoked from GraphicsContext::setCTM and
GraphicsContext::getCTM, respectively. See below for more details.

Additionally rebaselines displaylists/extent-includes-transforms.html.

* platform/graphics/displaylists/DisplayList.h:

Add a new type to represent the SetCTM display list item.

(WebCore::DisplayList::Item::isStateItemType):
* platform/graphics/displaylists/DisplayListItems.cpp:
(WebCore::DisplayList::Item::sizeInBytes):
(WebCore::DisplayList::SetCTM::SetCTM):
(WebCore::DisplayList::SetCTM::apply const):
(WebCore::DisplayList::operator<<):
* platform/graphics/displaylists/DisplayListItems.h:
(WebCore::DisplayList::SetCTM::create):
(WebCore::DisplayList::SetCTM::transform const):
(WebCore::DisplayList::SetCTM::encode const):
(WebCore::DisplayList::SetCTM::decode):
(WebCore::DisplayList::Item::encode const):
(WebCore::DisplayList::Item::decode):

Add DisplayList::SetCTM, which represents a call to set the current transformation matrix on the graphics
context. This is very similar to ConcatCTM.

* platform/graphics/displaylists/DisplayListRecorder.cpp:
(WebCore::DisplayList::Recorder::setCTM):

Set the current state's CTM to the new value. Additionally, update clipBounds by applying the inverse
transformation matrix of the inverse of the original CTM, multiplied by the new CTM. This is because setting
the CTM from to `B` from `A` is equivalent to multiplying `A` by `A_inverse * B`, so we want to map the clip
rect through the inverse of this matrix, `(A_inverse * B)_inverse`.

(WebCore::DisplayList::Recorder::getCTM):

Return the current CTM by asking the topmost state on the stack, and ignore the IncludeDeviceScale flag for the
time being.

(WebCore::DisplayList::Recorder::ContextState::setCTM):
* platform/graphics/displaylists/DisplayListRecorder.h:

LayoutTests:

* displaylists/extent-includes-transforms-expected.txt:
* platform/mac-wk1/displaylists/extent-includes-transforms-expected.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@253417 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/displaylists/extent-includes-transforms-expected.txt
LayoutTests/platform/mac-wk1/displaylists/extent-includes-transforms-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/displaylists/DisplayList.h
Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp
Source/WebCore/platform/graphics/displaylists/DisplayListItems.h
Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp
Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h

index f43367580528af0656da465a6e1abf4d5b150d06..a71945989278f0d0e6d39ab163d6187492fc69e9 100644 (file)
@@ -1,3 +1,13 @@
+2019-12-11  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Implement DisplayListRecorder::Recorder::getCTM and DisplayListRecorder::Recorder::setCTM
+        https://bugs.webkit.org/show_bug.cgi?id=205139
+
+        Reviewed by Simon Fraser.
+
+        * displaylists/extent-includes-transforms-expected.txt:
+        * platform/mac-wk1/displaylists/extent-includes-transforms-expected.txt:
+
 2019-12-11  Chris Dumez  <cdumez@apple.com>
 
         [Bindings] Cross-origin checks happen too late for overloaded methods
index 848b077545a7c680270eee1ba01fbbd1e8bcc3fc..2ed6a83cac2cfa82b412eabd0dd33405b6128449 100644 (file)
@@ -18,3 +18,5 @@
   (composite-operation source-over)
   (blend-mode normal))
 (restore)
+(set-ctm
+  (set-ctm {m=((1.00,0.00)(0.00,1.00)) t=(0.00,22.00)}))
index 5ee136cd8bfa3002a3432380fbf1eeecf91100cf..9f5788675ea051edb3be9c72a4777e7cf0777d02 100644 (file)
@@ -19,3 +19,5 @@
   (composite-operation source-over)
   (blend-mode normal))
 (restore)
+(set-ctm
+  (set-ctm {m=((1.00,0.00)(0.00,1.00)) t=(0.00,22.00)}))
index 43db78cea64199701bf8cfeb9deca7d7519aa481..8f32f094e2b2154700e8ec725c3f8b83486219f7 100644 (file)
@@ -1,3 +1,52 @@
+2019-12-11  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Implement DisplayListRecorder::Recorder::getCTM and DisplayListRecorder::Recorder::setCTM
+        https://bugs.webkit.org/show_bug.cgi?id=205139
+
+        Reviewed by Simon Fraser.
+
+        Implements these two methods on Recorder, which are invoked from GraphicsContext::setCTM and
+        GraphicsContext::getCTM, respectively. See below for more details.
+
+        Additionally rebaselines displaylists/extent-includes-transforms.html.
+
+        * platform/graphics/displaylists/DisplayList.h:
+
+        Add a new type to represent the SetCTM display list item.
+
+        (WebCore::DisplayList::Item::isStateItemType):
+        * platform/graphics/displaylists/DisplayListItems.cpp:
+        (WebCore::DisplayList::Item::sizeInBytes):
+        (WebCore::DisplayList::SetCTM::SetCTM):
+        (WebCore::DisplayList::SetCTM::apply const):
+        (WebCore::DisplayList::operator<<):
+        * platform/graphics/displaylists/DisplayListItems.h:
+        (WebCore::DisplayList::SetCTM::create):
+        (WebCore::DisplayList::SetCTM::transform const):
+        (WebCore::DisplayList::SetCTM::encode const):
+        (WebCore::DisplayList::SetCTM::decode):
+        (WebCore::DisplayList::Item::encode const):
+        (WebCore::DisplayList::Item::decode):
+
+        Add DisplayList::SetCTM, which represents a call to set the current transformation matrix on the graphics
+        context. This is very similar to ConcatCTM.
+
+        * platform/graphics/displaylists/DisplayListRecorder.cpp:
+        (WebCore::DisplayList::Recorder::setCTM):
+
+        Set the current state's CTM to the new value. Additionally, update clipBounds by applying the inverse
+        transformation matrix of the inverse of the original CTM, multiplied by the new CTM. This is because setting
+        the CTM from to `B` from `A` is equivalent to multiplying `A` by `A_inverse * B`, so we want to map the clip
+        rect through the inverse of this matrix, `(A_inverse * B)_inverse`.
+
+        (WebCore::DisplayList::Recorder::getCTM):
+
+        Return the current CTM by asking the topmost state on the stack, and ignore the IncludeDeviceScale flag for the
+        time being.
+
+        (WebCore::DisplayList::Recorder::ContextState::setCTM):
+        * platform/graphics/displaylists/DisplayListRecorder.h:
+
 2019-12-11  Don Olmstead  <don.olmstead@sony.com>
 
         [CMake] Add OpenJPEG find module
index 2a6ca0389208083d373bd0f0f1dc518f3e2271eb..28e2644e26edb50d025deae543a1149e3f2ae492 100644 (file)
@@ -46,6 +46,7 @@ enum class ItemType : uint8_t {
     Rotate,
     Scale,
     ConcatenateCTM,
+    SetCTM,
     SetState,
     SetLineCap,
     SetLineDash,
@@ -124,6 +125,7 @@ public:
         case ItemType::Rotate:
         case ItemType::Scale:
         case ItemType::ConcatenateCTM:
+        case ItemType::SetCTM:
         case ItemType::SetState:
         case ItemType::SetLineCap:
         case ItemType::SetLineDash:
index 7803f16209215a9790cc53c969634d3ab3756472..c90eea356fd36bc4c3e7069b2e74780243f8ce79 100644 (file)
@@ -68,6 +68,8 @@ size_t Item::sizeInBytes(const Item& item)
         return sizeof(downcast<Rotate>(item));
     case ItemType::Scale:
         return sizeof(downcast<Scale>(item));
+    case ItemType::SetCTM:
+        return sizeof(downcast<SetCTM>(item));
     case ItemType::ConcatenateCTM:
         return sizeof(downcast<ConcatenateCTM>(item));
     case ItemType::SetState:
@@ -272,6 +274,26 @@ static TextStream& operator<<(TextStream& ts, const Scale& item)
     return ts;
 }
 
+SetCTM::SetCTM(const AffineTransform& transform)
+    : Item(ItemType::SetCTM)
+    , m_transform(transform)
+{
+}
+
+SetCTM::~SetCTM() = default;
+
+void SetCTM::apply(GraphicsContext& context) const
+{
+    context.setCTM(m_transform);
+}
+
+static TextStream& operator<<(TextStream& ts, const SetCTM& item)
+{
+    ts.dumpProperty("set-ctm", item.transform());
+
+    return ts;
+}
+
 ConcatenateCTM::ConcatenateCTM(const AffineTransform& transform)
     : Item(ItemType::ConcatenateCTM)
     , m_transform(transform)
@@ -1308,6 +1330,7 @@ static TextStream& operator<<(TextStream& ts, const ItemType& type)
     case ItemType::Translate: ts << "translate"; break;
     case ItemType::Rotate: ts << "rotate"; break;
     case ItemType::Scale: ts << "scale"; break;
+    case ItemType::SetCTM: ts << "set-ctm"; break;
     case ItemType::ConcatenateCTM: ts << "concatentate-ctm"; break;
     case ItemType::SetState: ts << "set-state"; break;
     case ItemType::SetLineCap: ts << "set-line-cap"; break;
@@ -1377,6 +1400,9 @@ TextStream& operator<<(TextStream& ts, const Item& item)
     case ItemType::Scale:
         ts << downcast<Scale>(item);
         break;
+    case ItemType::SetCTM:
+        ts << downcast<SetCTM>(item);
+        break;
     case ItemType::ConcatenateCTM:
         ts << downcast<ConcatenateCTM>(item);
         break;
index ece98d898450c52e2981ab0161d8a30b9ecfdb29..d274360e0ea4e4ad4d260eeae21af05898213d7d 100644 (file)
@@ -264,6 +264,45 @@ Optional<Ref<Scale>> Scale::decode(Decoder& decoder)
     return Scale::create(*scale);
 }
 
+class SetCTM : public Item {
+public:
+    static Ref<SetCTM> create(const AffineTransform& matrix)
+    {
+        return adoptRef(*new SetCTM(matrix));
+    }
+
+    WEBCORE_EXPORT virtual ~SetCTM();
+
+    const AffineTransform& transform() const { return m_transform; }
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static Optional<Ref<SetCTM>> decode(Decoder&);
+
+private:
+    WEBCORE_EXPORT SetCTM(const AffineTransform&);
+
+    void apply(GraphicsContext&) const override;
+
+    AffineTransform m_transform;
+};
+
+template<class Encoder>
+void SetCTM::encode(Encoder& encoder) const
+{
+    encoder << m_transform;
+}
+
+template<class Decoder>
+Optional<Ref<SetCTM>> SetCTM::decode(Decoder& decoder)
+{
+    Optional<AffineTransform> transform;
+    decoder >> transform;
+    if (!transform)
+        return WTF::nullopt;
+
+    return SetCTM::create(*transform);
+}
+
 class ConcatenateCTM : public Item {
 public:
     static Ref<ConcatenateCTM> create(const AffineTransform& matrix)
@@ -2590,6 +2629,9 @@ void Item::encode(Encoder& encoder) const
     case ItemType::Scale:
         encoder << downcast<Scale>(*this);
         break;
+    case ItemType::SetCTM:
+        encoder << downcast<SetCTM>(*this);
+        break;
     case ItemType::ConcatenateCTM:
         encoder << downcast<ConcatenateCTM>(*this);
         break;
@@ -2752,6 +2794,10 @@ Optional<Ref<Item>> Item::decode(Decoder& decoder)
         if (auto item = Scale::decode(decoder))
             return static_reference_cast<Item>(WTFMove(*item));
         break;
+    case ItemType::SetCTM:
+        if (auto item = SetCTM::decode(decoder))
+            return static_reference_cast<Item>(WTFMove(*item));
+        break;
     case ItemType::ConcatenateCTM:
         if (auto item = ConcatenateCTM::decode(decoder))
             return static_reference_cast<Item>(WTFMove(*item));
@@ -2948,6 +2994,7 @@ SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(Restore)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(Translate)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(Rotate)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(Scale)
+SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(SetCTM)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(ConcatenateCTM)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(SetState)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(SetLineCap)
index a25353209d09fc0ef85e7bcf4dadbab54857b75c..3cad188610fca01ff857d32cf6d6ee52b6baa33e 100644 (file)
@@ -196,15 +196,16 @@ void Recorder::concatCTM(const AffineTransform& transform)
     appendItem(ConcatenateCTM::create(transform));
 }
 
-void Recorder::setCTM(const AffineTransform&)
+void Recorder::setCTM(const AffineTransform& transform)
 {
-    WTFLogAlways("GraphicsContext::setCTM() is not compatible with DisplayList::Recorder.");
+    currentState().setCTM(transform);
+    appendItem(SetCTM::create(transform));
 }
 
 AffineTransform Recorder::getCTM(GraphicsContext::IncludeDeviceScale)
 {
-    WTFLogAlways("GraphicsContext::getCTM() is not yet compatible with DisplayList::Recorder.");
-    return { };
+    // FIXME: Respect the given value of IncludeDeviceScale.
+    return currentState().ctm;
 }
 
 void Recorder::beginTransparencyLayer(float opacity)
@@ -483,6 +484,18 @@ void Recorder::ContextState::scale(const FloatSize& size)
     clipBounds.scale(1 / size.width(), 1 / size.height());
 }
 
+void Recorder::ContextState::setCTM(const AffineTransform& matrix)
+{
+    Optional<AffineTransform> inverseTransformForClipBounds;
+    if (auto originalCTMInverse = ctm.inverse())
+        inverseTransformForClipBounds = originalCTMInverse->multiply(matrix).inverse();
+
+    ctm = matrix;
+
+    if (inverseTransformForClipBounds)
+        clipBounds = inverseTransformForClipBounds->mapRect(clipBounds);
+}
+
 void Recorder::ContextState::concatCTM(const AffineTransform& matrix)
 {
     ctm *= matrix;
index a4e68861cf30ecbae3962bbb344e9bd8787f4aee..bf6ca55a9ca5e14361413affe2a38c0989df347d 100644 (file)
@@ -166,6 +166,7 @@ private:
         void rotate(float angleInRadians);
         void scale(const FloatSize&);
         void concatCTM(const AffineTransform&);
+        void setCTM(const AffineTransform&);
     };
     
     const ContextState& currentState() const;