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_PICTURE_H_ 27 #define _TVG_PICTURE_H_ 28 29 #include <string> 30 #include "tvgPaint.h" 31 #include "tvgLoader.h" 32 33 34 struct PictureIterator : Iterator 35 { 36 Paint* paint = nullptr; 37 Paint* ptr = nullptr; 38 PictureIteratorPictureIterator39 PictureIterator(Paint* p) : paint(p) {} 40 nextPictureIterator41 const Paint* next() override 42 { 43 if (!ptr) ptr = paint; 44 else ptr = nullptr; 45 return ptr; 46 } 47 countPictureIterator48 uint32_t count() override 49 { 50 if (paint) return 1; 51 else return 0; 52 } 53 beginPictureIterator54 void begin() override 55 { 56 ptr = nullptr; 57 } 58 }; 59 60 61 struct Picture::Impl 62 { 63 ImageLoader* loader = nullptr; 64 65 Paint* paint = nullptr; //vector picture uses 66 RenderSurface* surface = nullptr; //bitmap picture uses 67 RenderData rd = nullptr; //engine data 68 float w = 0, h = 0; 69 Picture* picture = nullptr; 70 bool resizing = false; 71 bool needComp = false; //need composition 72 73 bool needComposition(uint8_t opacity); 74 bool render(RenderMethod* renderer); 75 bool size(float w, float h); 76 RenderRegion bounds(RenderMethod* renderer); 77 Result load(ImageLoader* ploader); 78 ImplImpl79 Impl(Picture* p) : picture(p) 80 { 81 } 82 ~ImplImpl83 ~Impl() 84 { 85 LoaderMgr::retrieve(loader); 86 if (surface) { 87 if (auto renderer = PP(picture)->renderer) { 88 renderer->dispose(rd); 89 } 90 } 91 delete(paint); 92 } 93 updateImpl94 RenderData update(RenderMethod* renderer, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper) 95 { 96 auto flag = static_cast<RenderUpdateFlag>(pFlag | load()); 97 98 if (surface) { 99 if (flag == RenderUpdateFlag::None) return rd; 100 101 //Overriding Transformation by the desired image size 102 auto sx = w / loader->w; 103 auto sy = h / loader->h; 104 auto scale = sx < sy ? sx : sy; 105 auto m = transform * Matrix{scale, 0, 0, 0, scale, 0, 0, 0, 1}; 106 107 rd = renderer->prepare(surface, rd, m, clips, opacity, flag); 108 } else if (paint) { 109 if (resizing) { 110 loader->resize(paint, w, h); 111 resizing = false; 112 } 113 needComp = needComposition(opacity) ? true : false; 114 rd = paint->pImpl->update(renderer, transform, clips, opacity, flag, false); 115 } 116 return rd; 117 } 118 boundsImpl119 bool bounds(float* x, float* y, float* w, float* h, bool stroking) 120 { 121 if (x) *x = 0; 122 if (y) *y = 0; 123 if (w) *w = this->w; 124 if (h) *h = this->h; 125 return true; 126 } 127 loadImpl128 Result load(const string& path) 129 { 130 if (paint || surface) return Result::InsufficientCondition; 131 132 bool invalid; //Invalid Path 133 auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(path, &invalid)); 134 if (!loader) { 135 if (invalid) return Result::InvalidArguments; 136 return Result::NonSupport; 137 } 138 return load(loader); 139 } 140 loadImpl141 Result load(const char* data, uint32_t size, const string& mimeType, bool copy) 142 { 143 if (paint || surface) return Result::InsufficientCondition; 144 auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(data, size, mimeType, copy)); 145 if (!loader) return Result::NonSupport; 146 return load(loader); 147 } 148 loadImpl149 Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) 150 { 151 if (paint || surface) return Result::InsufficientCondition; 152 153 auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(data, w, h, copy)); 154 if (!loader) return Result::FailedAllocation; 155 156 return load(loader); 157 } 158 duplicateImpl159 Paint* duplicate(Paint* ret) 160 { 161 if (ret) TVGERR("RENDERER", "TODO: duplicate()"); 162 163 load(); 164 165 auto picture = Picture::gen().release(); 166 auto dup = picture->pImpl; 167 168 if (paint) dup->paint = paint->duplicate(); 169 170 if (loader) { 171 dup->loader = loader; 172 ++dup->loader->sharing; 173 PP(picture)->renderFlag |= RenderUpdateFlag::Image; 174 } 175 176 dup->surface = surface; 177 dup->w = w; 178 dup->h = h; 179 dup->resizing = resizing; 180 181 return picture; 182 } 183 iteratorImpl184 Iterator* iterator() 185 { 186 load(); 187 return new PictureIterator(paint); 188 } 189 dataImpl190 uint32_t* data(uint32_t* w, uint32_t* h) 191 { 192 //Try it, If not loaded yet. 193 load(); 194 195 if (loader) { 196 if (w) *w = static_cast<uint32_t>(loader->w); 197 if (h) *h = static_cast<uint32_t>(loader->h); 198 } else { 199 if (w) *w = 0; 200 if (h) *h = 0; 201 } 202 if (surface) return surface->buf32; 203 else return nullptr; 204 } 205 206 RenderUpdateFlag load(); 207 }; 208 209 #endif //_TVG_PICTURE_H_ 210 211 #endif /* LV_USE_THORVG_INTERNAL */ 212 213