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