1 /*
2  * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
3 
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10 
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13 
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 
23 #include "../../lv_conf_internal.h"
24 #if LV_USE_THORVG_INTERNAL
25 
26 #ifndef _TVG_PAINT_H_
27 #define _TVG_PAINT_H_
28 
29 #include "tvgRender.h"
30 #include "tvgMath.h"
31 
32 namespace tvg
33 {
34     enum ContextFlag : uint8_t {Invalid = 0, FastTrack = 1};
35 
36     struct Iterator
37     {
~IteratorIterator38         virtual ~Iterator() {}
39         virtual const Paint* next() = 0;
40         virtual uint32_t count() = 0;
41         virtual void begin() = 0;
42     };
43 
44     struct Composite
45     {
46         Paint* target;
47         Paint* source;
48         CompositeMethod method;
49     };
50 
51     struct Paint::Impl
52     {
53         Paint* paint = nullptr;
54         Composite* compData = nullptr;
55         Paint* clipper = nullptr;
56         RenderMethod* renderer = nullptr;
57         struct {
58             Matrix m;                 //input matrix
59             Matrix cm;                //multipled parents matrix
60             float degree;             //rotation degree
61             float scale;              //scale factor
62             bool overriding;          //user transform?
63 
updateImpl::__anon823084ac010864             void update()
65             {
66                 if (overriding) return;
67                 m.e11 = 1.0f;
68                 m.e12 = 0.0f;
69                 m.e21 = 0.0f;
70                 m.e22 = 1.0f;
71                 m.e31 = 0.0f;
72                 m.e32 = 0.0f;
73                 m.e33 = 1.0f;
74                 tvg::scale(&m, scale, scale);
75                 tvg::rotate(&m, degree);
76             }
77         } tr;
78         BlendMethod blendMethod;
79         uint8_t renderFlag;
80         uint8_t ctxFlag;
81         uint8_t opacity;
82         uint8_t refCnt = 0;                              //reference count
83 
ImplImpl84         Impl(Paint* pnt) : paint(pnt)
85         {
86             reset();
87         }
88 
~ImplImpl89         ~Impl()
90         {
91             if (compData) {
92                 if (P(compData->target)->unref() == 0) delete(compData->target);
93                 free(compData);
94             }
95             if (clipper && P(clipper)->unref() == 0) delete(clipper);
96             if (renderer && (renderer->unref() == 0)) delete(renderer);
97         }
98 
refImpl99         uint8_t ref()
100         {
101             if (refCnt == 255) TVGERR("RENDERER", "Corrupted reference count!");
102             return ++refCnt;
103         }
104 
unrefImpl105         uint8_t unref()
106         {
107             if (refCnt == 0) TVGERR("RENDERER", "Corrupted reference count!");
108             return --refCnt;
109         }
110 
transformImpl111         bool transform(const Matrix& m)
112         {
113             if (&tr.m != &m) tr.m = m;
114             tr.overriding = true;
115             renderFlag |= RenderUpdateFlag::Transform;
116 
117             return true;
118         }
119 
120         Matrix& transform(bool origin = false)
121         {
122             //update transform
123             if (renderFlag & RenderUpdateFlag::Transform) tr.update();
124             if (origin) return tr.cm;
125             return tr.m;
126         }
127 
clipImpl128         void clip(Paint* clp)
129         {
130             if (this->clipper) {
131                 P(this->clipper)->unref();
132                 if (this->clipper != clp && P(this->clipper)->refCnt == 0) {
133                     delete(this->clipper);
134                 }
135             }
136             this->clipper = clp;
137             if (!clp) return;
138 
139             P(clipper)->ref();
140         }
141 
compositeImpl142         bool composite(Paint* source, Paint* target, CompositeMethod method)
143         {
144             //Invalid case
145             if ((!target && method != CompositeMethod::None) || (target && method == CompositeMethod::None)) return false;
146 
147             if (compData) {
148                 P(compData->target)->unref();
149                 if ((compData->target != target) && P(compData->target)->refCnt == 0) {
150                     delete(compData->target);
151                 }
152                 //Reset scenario
153                 if (!target && method == CompositeMethod::None) {
154                     free(compData);
155                     compData = nullptr;
156                     return true;
157                 }
158             } else {
159                 if (!target && method == CompositeMethod::None) return true;
160                 compData = static_cast<Composite*>(calloc(1, sizeof(Composite)));
161             }
162             P(target)->ref();
163             compData->target = target;
164             compData->source = source;
165             compData->method = method;
166             return true;
167         }
168 
169         RenderRegion bounds(RenderMethod* renderer) const;
170         Iterator* iterator();
171         bool rotate(float degree);
172         bool scale(float factor);
173         bool translate(float x, float y);
174         bool bounds(float* x, float* y, float* w, float* h, bool transformed, bool stroking, bool origin = false);
175         RenderData update(RenderMethod* renderer, const Matrix& pm, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper = false);
176         bool render(RenderMethod* renderer);
177         Paint* duplicate(Paint* ret = nullptr);
178         void reset();
179     };
180 }
181 
182 #endif //_TVG_PAINT_H_
183 
184 #endif /* LV_USE_THORVG_INTERNAL */
185 
186