tvgRender.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to deal
  5. * in the Software without restriction, including without limitation the rights
  6. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. * copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. * The above copyright notice and this permission notice shall be included in all
  10. * copies or substantial portions of the Software.
  11. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. * SOFTWARE.
  18. */
  19. #ifndef _TVG_RENDER_H_
  20. #define _TVG_RENDER_H_
  21. #include "tvgCommon.h"
  22. #include "tvgArray.h"
  23. namespace tvg
  24. {
  25. using RenderData = void*;
  26. using pixel_t = uint32_t;
  27. enum RenderUpdateFlag : uint8_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, Blend = 128, All = 255};
  28. struct Surface;
  29. enum ColorSpace
  30. {
  31. ABGR8888 = 0, //The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied.
  32. ARGB8888, //The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied.
  33. ABGR8888S, //The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied.
  34. ARGB8888S, //The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied.
  35. Grayscale8, //One single channel data.
  36. Unsupported //TODO: Change to the default, At the moment, we put it in the last to align with SwCanvas::Colorspace.
  37. };
  38. struct Surface
  39. {
  40. union {
  41. pixel_t* data; //system based data pointer
  42. uint32_t* buf32; //for explicit 32bits channels
  43. uint8_t* buf8; //for explicit 8bits grayscale
  44. };
  45. uint32_t stride;
  46. uint32_t w, h;
  47. ColorSpace cs;
  48. uint8_t channelSize;
  49. bool premultiplied; //Alpha-premultiplied
  50. bool owner; //Only owner could modify the buffer
  51. };
  52. struct Compositor
  53. {
  54. CompositeMethod method;
  55. uint8_t opacity;
  56. };
  57. struct RenderMesh
  58. {
  59. Polygon* triangles = nullptr;
  60. uint32_t triangleCnt = 0;
  61. ~RenderMesh()
  62. {
  63. free(triangles);
  64. }
  65. };
  66. struct RenderRegion
  67. {
  68. int32_t x, y, w, h;
  69. void intersect(const RenderRegion& rhs)
  70. {
  71. auto x1 = x + w;
  72. auto y1 = y + h;
  73. auto x2 = rhs.x + rhs.w;
  74. auto y2 = rhs.y + rhs.h;
  75. x = (x > rhs.x) ? x : rhs.x;
  76. y = (y > rhs.y) ? y : rhs.y;
  77. w = ((x1 < x2) ? x1 : x2) - x;
  78. h = ((y1 < y2) ? y1 : y2) - y;
  79. if (w < 0) w = 0;
  80. if (h < 0) h = 0;
  81. }
  82. void add(const RenderRegion& rhs)
  83. {
  84. if (rhs.x < x) {
  85. w += (x - rhs.x);
  86. x = rhs.x;
  87. }
  88. if (rhs.y < y) {
  89. h += (y - rhs.y);
  90. y = rhs.y;
  91. }
  92. if (rhs.x + rhs.w > x + w) w = (rhs.x + rhs.w) - x;
  93. if (rhs.y + rhs.h > y + h) h = (rhs.y + rhs.h) - y;
  94. }
  95. };
  96. struct RenderTransform
  97. {
  98. Matrix m; //3x3 Matrix Elements
  99. float x = 0.0f;
  100. float y = 0.0f;
  101. float degree = 0.0f; //rotation degree
  102. float scale = 1.0f; //scale factor
  103. bool overriding = false; //user transform?
  104. void update();
  105. void override(const Matrix& m);
  106. RenderTransform() {}
  107. RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
  108. };
  109. struct RenderStroke
  110. {
  111. float width = 0.0f;
  112. uint8_t color[4] = {0, 0, 0, 0};
  113. Fill *fill = nullptr;
  114. float* dashPattern = nullptr;
  115. uint32_t dashCnt = 0;
  116. float dashOffset = 0.0f;
  117. StrokeCap cap = StrokeCap::Square;
  118. StrokeJoin join = StrokeJoin::Bevel;
  119. float miterlimit = 4.0f;
  120. bool strokeFirst = false;
  121. struct {
  122. float begin = 0.0f;
  123. float end = 1.0f;
  124. } trim;
  125. ~RenderStroke()
  126. {
  127. free(dashPattern);
  128. delete(fill);
  129. }
  130. };
  131. struct RenderShape
  132. {
  133. struct
  134. {
  135. Array<PathCommand> cmds;
  136. Array<Point> pts;
  137. } path;
  138. Fill *fill = nullptr;
  139. RenderStroke *stroke = nullptr;
  140. uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
  141. FillRule rule = FillRule::Winding;
  142. ~RenderShape()
  143. {
  144. delete(fill);
  145. delete(stroke);
  146. }
  147. void fillColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const
  148. {
  149. if (r) *r = color[0];
  150. if (g) *g = color[1];
  151. if (b) *b = color[2];
  152. if (a) *a = color[3];
  153. }
  154. float strokeWidth() const
  155. {
  156. if (!stroke) return 0;
  157. return stroke->width;
  158. }
  159. bool strokeTrim() const
  160. {
  161. if (!stroke) return false;
  162. if (stroke->trim.begin == 0.0f && stroke->trim.end == 1.0f) return false;
  163. if (stroke->trim.begin == 1.0f && stroke->trim.end == 0.0f) return false;
  164. return true;
  165. }
  166. bool strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const
  167. {
  168. if (!stroke) return false;
  169. if (r) *r = stroke->color[0];
  170. if (g) *g = stroke->color[1];
  171. if (b) *b = stroke->color[2];
  172. if (a) *a = stroke->color[3];
  173. return true;
  174. }
  175. const Fill* strokeFill() const
  176. {
  177. if (!stroke) return nullptr;
  178. return stroke->fill;
  179. }
  180. uint32_t strokeDash(const float** dashPattern, float* offset) const
  181. {
  182. if (!stroke) return 0;
  183. if (dashPattern) *dashPattern = stroke->dashPattern;
  184. if (offset) *offset = stroke->dashOffset;
  185. return stroke->dashCnt;
  186. }
  187. StrokeCap strokeCap() const
  188. {
  189. if (!stroke) return StrokeCap::Square;
  190. return stroke->cap;
  191. }
  192. StrokeJoin strokeJoin() const
  193. {
  194. if (!stroke) return StrokeJoin::Bevel;
  195. return stroke->join;
  196. }
  197. float strokeMiterlimit() const
  198. {
  199. if (!stroke) return 4.0f;
  200. return stroke->miterlimit;;
  201. }
  202. };
  203. class RenderMethod
  204. {
  205. public:
  206. virtual ~RenderMethod() {}
  207. virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) = 0;
  208. virtual RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) = 0;
  209. virtual RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) = 0;
  210. virtual bool preRender() = 0;
  211. virtual bool renderShape(RenderData data) = 0;
  212. virtual bool renderImage(RenderData data) = 0;
  213. virtual bool postRender() = 0;
  214. virtual bool dispose(RenderData data) = 0;
  215. virtual RenderRegion region(RenderData data) = 0;
  216. virtual RenderRegion viewport() = 0;
  217. virtual bool viewport(const RenderRegion& vp) = 0;
  218. virtual bool blend(BlendMethod method) = 0;
  219. virtual ColorSpace colorSpace() = 0;
  220. virtual bool clear() = 0;
  221. virtual bool sync() = 0;
  222. virtual Compositor* target(const RenderRegion& region, ColorSpace cs) = 0;
  223. virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity) = 0;
  224. virtual bool endComposite(Compositor* cmp) = 0;
  225. };
  226. static inline bool MASK_REGION_MERGING(CompositeMethod method)
  227. {
  228. switch(method) {
  229. case CompositeMethod::AlphaMask:
  230. case CompositeMethod::InvAlphaMask:
  231. case CompositeMethod::LumaMask:
  232. case CompositeMethod::InvLumaMask:
  233. case CompositeMethod::SubtractMask:
  234. case CompositeMethod::IntersectMask:
  235. return false;
  236. //these might expand the rendering region
  237. case CompositeMethod::AddMask:
  238. case CompositeMethod::DifferenceMask:
  239. return true;
  240. default:
  241. TVGERR("RENDERER", "Unsupported Composite Method! = %d", (int)method);
  242. return false;
  243. }
  244. }
  245. static inline uint8_t CHANNEL_SIZE(ColorSpace cs)
  246. {
  247. switch(cs) {
  248. case ColorSpace::ABGR8888:
  249. case ColorSpace::ABGR8888S:
  250. case ColorSpace::ARGB8888:
  251. case ColorSpace::ARGB8888S:
  252. return sizeof(uint32_t);
  253. case ColorSpace::Grayscale8:
  254. return sizeof(uint8_t);
  255. case ColorSpace::Unsupported:
  256. default:
  257. TVGERR("RENDERER", "Unsupported Channel Size! = %d", (int)cs);
  258. return 0;
  259. }
  260. }
  261. static inline ColorSpace COMPOSITE_TO_COLORSPACE(RenderMethod& renderer, CompositeMethod method)
  262. {
  263. switch(method) {
  264. case CompositeMethod::AlphaMask:
  265. case CompositeMethod::InvAlphaMask:
  266. case CompositeMethod::AddMask:
  267. case CompositeMethod::DifferenceMask:
  268. case CompositeMethod::SubtractMask:
  269. case CompositeMethod::IntersectMask:
  270. return ColorSpace::Grayscale8;
  271. //TODO: Optimize Luma/InvLuma colorspace to Grayscale8
  272. case CompositeMethod::LumaMask:
  273. case CompositeMethod::InvLumaMask:
  274. return renderer.colorSpace();
  275. default:
  276. TVGERR("RENDERER", "Unsupported Composite Size! = %d", (int)method);
  277. return ColorSpace::Unsupported;
  278. }
  279. }
  280. static inline uint8_t MULTIPLY(uint8_t c, uint8_t a)
  281. {
  282. return (((c) * (a) + 0xff) >> 8);
  283. }
  284. }
  285. #endif //_TVG_RENDER_H_