1 /*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 
8 #ifndef SkMatrixProvider_DEFINED
9 #define SkMatrixProvider_DEFINED
10 
11 #include "include/core/SkM44.h"
12 #include "include/core/SkMatrix.h"
13 
14 class SkMatrixProvider {
15 public:
SkMatrixProvider(const SkMatrix & localToDevice)16     SkMatrixProvider(const SkMatrix& localToDevice)
17         : fLocalToDevice(localToDevice)
18         , fLocalToDevice33(localToDevice) {}
19 
SkMatrixProvider(const SkM44 & localToDevice)20     SkMatrixProvider(const SkM44& localToDevice)
21         : fLocalToDevice(localToDevice)
22         , fLocalToDevice33(localToDevice.asM33()) {}
23 
~SkMatrixProvider()24     virtual ~SkMatrixProvider() {}
25 
26     // These should return the "same" matrix, as either a 3x3 or 4x4. Most sites in Skia still
27     // call localToDevice, and operate on SkMatrix.
localToDevice()28     const SkMatrix& localToDevice() const { return fLocalToDevice33; }
localToDevice44()29     const SkM44& localToDevice44() const { return fLocalToDevice; }
30 
31     virtual bool getLocalToMarker(uint32_t id, SkM44* localToMarker) const = 0;
32 
33     virtual bool localToDeviceHitsPixelCenters() const = 0;
34 
35 private:
36     friend class SkBaseDevice;
37 
38     SkM44    fLocalToDevice;
39     SkMatrix fLocalToDevice33;  // Cached SkMatrix version of above, for legacy usage
40 };
41 
42 class SkOverrideDeviceMatrixProvider : public SkMatrixProvider {
43 public:
SkOverrideDeviceMatrixProvider(const SkMatrixProvider & parent,const SkMatrix & localToDevice)44     SkOverrideDeviceMatrixProvider(const SkMatrixProvider& parent, const SkMatrix& localToDevice)
45         : SkMatrixProvider(localToDevice)
46         , fParent(parent) {}
47 
getLocalToMarker(uint32_t id,SkM44 * localToMarker)48     bool getLocalToMarker(uint32_t id, SkM44* localToMarker) const override {
49         return fParent.getLocalToMarker(id, localToMarker);
50     }
51 
52     // We've replaced parent's localToDevice matrix,
53     // so we can't guarantee localToDevice() hits pixel centers anymore.
localToDeviceHitsPixelCenters()54     bool localToDeviceHitsPixelCenters() const override { return false; }
55 
56 private:
57     const SkMatrixProvider& fParent;
58 };
59 
60 class SkPostTranslateMatrixProvider : public SkMatrixProvider {
61 public:
SkPostTranslateMatrixProvider(const SkMatrixProvider & parent,SkScalar dx,SkScalar dy)62     SkPostTranslateMatrixProvider(const SkMatrixProvider& parent, SkScalar dx, SkScalar dy)
63             : SkMatrixProvider(SkM44::Translate(dx, dy) * parent.localToDevice44())
64             , fParent(parent) {}
65 
66     // Assume that the post-translation doesn't apply to any marked matrices
getLocalToMarker(uint32_t id,SkM44 * localToMarker)67     bool getLocalToMarker(uint32_t id, SkM44* localToMarker) const override {
68         return fParent.getLocalToMarker(id, localToMarker);
69     }
70 
71     // parent.localToDevice() is folded into our localToDevice().
localToDeviceHitsPixelCenters()72     bool localToDeviceHitsPixelCenters() const override { return true; }
73 
74 private:
75     const SkMatrixProvider& fParent;
76 };
77 
78 class SkPreConcatMatrixProvider : public SkMatrixProvider {
79 public:
SkPreConcatMatrixProvider(const SkMatrixProvider & parent,const SkMatrix & preMatrix)80     SkPreConcatMatrixProvider(const SkMatrixProvider& parent, const SkMatrix& preMatrix)
81             : SkMatrixProvider(parent.localToDevice44() * SkM44(preMatrix))
82             , fParent(parent)
83             , fPreMatrix(preMatrix) {}
84 
getLocalToMarker(uint32_t id,SkM44 * localToMarker)85     bool getLocalToMarker(uint32_t id, SkM44* localToMarker) const override {
86         if (fParent.getLocalToMarker(id, localToMarker)) {
87             if (localToMarker) {
88                 localToMarker->preConcat(fPreMatrix);
89             }
90             return true;
91         }
92         return false;
93     }
94 
95     // parent.localToDevice() is folded into our localToDevice().
localToDeviceHitsPixelCenters()96     bool localToDeviceHitsPixelCenters() const override { return true; }
97 
98 private:
99     const SkMatrixProvider& fParent;
100     const SkMatrix          fPreMatrix;
101 };
102 
103 class SkSimpleMatrixProvider : public SkMatrixProvider {
104 public:
SkSimpleMatrixProvider(const SkMatrix & localToDevice)105     SkSimpleMatrixProvider(const SkMatrix& localToDevice)
106         : SkMatrixProvider(localToDevice) {}
107 
getLocalToMarker(uint32_t,SkM44 *)108     bool getLocalToMarker(uint32_t, SkM44*) const override { return false; }
109 
110     // No trickiness to reason about here... we take this case to be axiomatically true.
localToDeviceHitsPixelCenters()111     bool localToDeviceHitsPixelCenters() const override { return true; }
112 };
113 
114 #endif
115