8fa337020c36603b6cb554db3c0b712b8f3116af
[platform/core/uifw/rive-tizen.git] / src / renderer / tvg_renderer.cpp
1 #include "tvg_renderer.hpp"
2 #include "math/vec2d.hpp"
3 #include "shapes/paint/color.hpp"
4
5 using namespace rive;
6
7
8 void TvgRenderPath::fillRule(FillRule value)
9 {
10    switch (value)
11    {
12       case FillRule::evenOdd:
13          tvgShape->fill(tvg::FillRule::EvenOdd);
14          break;
15       case FillRule::nonZero:
16          tvgShape->fill(tvg::FillRule::Winding);
17          break;
18    }
19 }
20
21 Point transformCoord(const Point pt, const Mat2D &transform)
22 {
23    Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1};
24    m.e11 = transform[0];
25    m.e12 = transform[2];
26    m.e13 = transform[4];
27    m.e21 = transform[1];
28    m.e22 = transform[3];
29    m.e23 = transform[5];
30
31    return {pt.x * m.e11 + pt.y * m.e12 + m.e13, pt.x * m.e21 + pt.y * m.e22 + m.e23};
32 }
33
34 void TvgRenderPath::reset()
35 {
36    tvgShape->reset();
37 }
38
39 void TvgRenderPath::addRenderPath(RenderPath* path, const Mat2D& transform)
40 {
41    const Point* pts;
42    auto ptsCnt = static_cast<TvgRenderPath*>(path)->tvgShape->pathCoords(&pts);
43    if (!pts) return;
44
45    const PathCommand* cmds;
46    auto cmdCnt = static_cast<TvgRenderPath*>(path)->tvgShape->pathCommands(&cmds);
47    if (!cmds) return;
48
49    //Capture the last coordinates
50    Point* pts2;
51    auto ptsCnt2 = tvgShape->pathCoords(const_cast<const Point**>(&pts2));
52
53    tvgShape->appendPath(cmds, cmdCnt, pts, ptsCnt);
54
55    //Immediate Transform for the newly appended
56    Point* pts3;
57    auto ptsCnt3 = tvgShape->pathCoords(const_cast<const Point**>(&pts3));
58
59    for (unsigned i = ptsCnt2; i < ptsCnt3; ++i)
60    {
61       pts3[i] = transformCoord(pts3[i], transform);
62    }
63 }
64
65 void TvgRenderPath::moveTo(float x, float y)
66 {
67    tvgShape->moveTo(x, y);
68 }
69
70 void TvgRenderPath::lineTo(float x, float y)
71 {
72    tvgShape->lineTo(x, y);
73 }
74
75 void TvgRenderPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y)
76 {
77    tvgShape->cubicTo(ox, oy, ix, iy, x, y);
78 }
79
80 void TvgRenderPath::close()
81 {
82    tvgShape->close();
83 }
84
85 void TvgRenderPaint::style(RenderPaintStyle style)
86 {
87    m_Paint.style = style;
88 }
89
90 void TvgRenderPaint::color(unsigned int value)
91 {
92    m_Paint.color[0] = value >> 16 & 255;
93    m_Paint.color[1] = value >> 8 & 255;
94    m_Paint.color[2] = value >> 0 & 255;
95    m_Paint.color[3] = value >> 24 & 255;
96 }
97
98 void TvgRenderPaint::thickness(float value)
99 {
100    m_Paint.thickness = value;
101 }
102
103 void TvgRenderPaint::join(StrokeJoin value)
104 {
105    switch (value)
106    {
107       case rive::StrokeJoin::round:
108          m_Paint.join = tvg::StrokeJoin::Round;
109          break;
110       case rive::StrokeJoin::bevel:
111          m_Paint.join = tvg::StrokeJoin::Bevel;
112          break;
113       case rive::StrokeJoin::miter:
114          m_Paint.join = tvg::StrokeJoin::Miter;
115          break;
116    }
117 }
118
119 void TvgRenderPaint::cap(StrokeCap value)
120 {
121    switch (value)
122    {
123       case rive::StrokeCap::butt:
124          m_Paint.cap = tvg::StrokeCap::Butt;
125          break;
126       case rive::StrokeCap::round:
127          m_Paint.cap = tvg::StrokeCap::Round;
128          break;
129       case rive::StrokeCap::square:
130          m_Paint.cap = tvg::StrokeCap::Square;
131          break;
132    }
133 }
134
135 void TvgRenderPaint::linearGradient(float sx, float sy, float ex, float ey)
136 {
137    m_GradientBuilder = new TvgLinearGradientBuilder(sx, sy, ex, ey);
138 }
139
140 void TvgRenderPaint::radialGradient(float sx, float sy, float ex, float ey)
141 {
142    m_GradientBuilder = new TvgRadialGradientBuilder(sx, sy, ex, ey);
143 }
144
145 void TvgRenderPaint::addStop(unsigned int color, float stop)
146 {
147    m_GradientBuilder->stops.emplace_back(GradientStop(color, stop));
148 }
149
150 void TvgRenderPaint::completeGradient()
151 {
152    m_GradientBuilder->make(&m_Paint);
153    delete m_GradientBuilder;
154 }
155
156 void TvgRenderPaint::blendMode(BlendMode value)
157 {
158
159 }
160
161 void TvgRadialGradientBuilder::make(TvgPaint* paint)
162 {
163    paint->isGradient = true;
164    int numStops = stops.size();
165
166    paint->gradientFill = tvg::RadialGradient::gen().release();
167    float radius = Vec2D::distance(Vec2D(sx, sy), Vec2D(ex, ey));
168    static_cast<RadialGradient*>(paint->gradientFill)->radial(sx, sy, radius);
169
170    tvg::Fill::ColorStop colorStops[numStops];
171    for (int i = 0; i < numStops; i++)
172    {
173       unsigned int value = stops[i].color;
174       uint8_t r = value >> 16 & 255;
175       uint8_t g = value >> 8 & 255;
176       uint8_t b = value >> 0 & 255;
177       uint8_t a = value >> 24 & 255;
178
179       colorStops[i] = {stops[i].stop, r, g, b, a};
180    }
181
182    static_cast<RadialGradient*>(paint->gradientFill)->colorStops(colorStops, numStops);
183 }
184
185 void TvgLinearGradientBuilder::make(TvgPaint* paint)
186 {
187    paint->isGradient = true;
188    int numStops = stops.size();
189
190    paint->gradientFill = tvg::LinearGradient::gen().release();
191    static_cast<LinearGradient*>(paint->gradientFill)->linear(sx, sy, ex, ey);
192
193    tvg::Fill::ColorStop colorStops[numStops];
194    for (int i = 0; i < numStops; i++)
195    {
196       unsigned int value = stops[i].color;
197       uint8_t r = value >> 16 & 255;
198       uint8_t g = value >> 8 & 255;
199       uint8_t b = value >> 0 & 255;
200       uint8_t a = value >> 24 & 255;
201
202       colorStops[i] = {stops[i].stop, r, g, b, a};
203    }
204
205    static_cast<LinearGradient*>(paint->gradientFill)->colorStops(colorStops, numStops);
206 }
207
208 void TvgRenderer::save()
209 {
210    m_SaveTransform = m_Transform;
211 }
212
213 void TvgRenderer::restore()
214 {
215    m_Transform = m_SaveTransform;
216 }
217
218 void TvgRenderer::transform(const Mat2D& transform)
219 {
220    m_Transform = m_Transform * transform;
221 }
222
223 void TvgRenderer::drawPath(RenderPath* path, RenderPaint* paint)
224 {
225    auto tvgShape = static_cast<TvgRenderPath*>(path)->tvgShape.get();
226    auto tvgPaint = static_cast<TvgRenderPaint*>(paint)->paint();
227
228    /* OPTIMIZE ME: Stroke / Fill Paints required to draw separately.
229       thorvg doesn't need to handle both, we can avoid one of them rendering... */
230
231    if (tvgPaint->style == RenderPaintStyle::fill)
232    {
233       if (!tvgPaint->isGradient)
234          tvgShape->fill(tvgPaint->color[0], tvgPaint->color[1], tvgPaint->color[2], tvgPaint->color[3]);
235       else
236       {
237          tvgShape->fill(unique_ptr<tvg::Fill>(tvgPaint->gradientFill->duplicate()));
238       }
239    }
240    else if (tvgPaint->style == RenderPaintStyle::stroke)
241    {
242       tvgShape->stroke(tvgPaint->cap);
243       tvgShape->stroke(tvgPaint->join);
244       tvgShape->stroke(tvgPaint->thickness);
245
246       if (!tvgPaint->isGradient)
247          tvgShape->stroke(tvgPaint->color[0], tvgPaint->color[1], tvgPaint->color[2], tvgPaint->color[3]);
248       else
249       {
250          tvgShape->stroke(unique_ptr<tvg::Fill>(tvgPaint->gradientFill->duplicate()));
251       }
252    }
253
254    if (m_ClipPath)
255    {
256       m_ClipPath->fill(255, 255, 255, 255);
257       tvgShape->composite(unique_ptr<Shape>(static_cast<Shape*>(m_ClipPath->duplicate())), tvg::CompositeMethod::ClipPath);
258       m_ClipPath = nullptr;
259    }
260
261    tvgShape->transform({m_Transform[0], m_Transform[2], m_Transform[4], m_Transform[1], m_Transform[3], m_Transform[5], 0, 0, 1});
262    m_Canvas->push(unique_ptr<Paint>(tvgShape->duplicate()));
263 }
264
265
266 void TvgRenderer::clipPath(RenderPath* path)
267 {
268    //Note: ClipPath transform matrix is calculated by transfrom matrix in addRenderPath function
269    m_ClipPath = static_cast<TvgRenderPath*>(path)->tvgShape.get();
270    m_ClipPath->transform({m_Transform[0], m_Transform[2], m_Transform[4], m_Transform[1], m_Transform[3], m_Transform[5], 0, 0, 1});
271 }
272
273 namespace rive
274 {
275    RenderPath* makeRenderPath() { return new TvgRenderPath();}
276    RenderPaint* makeRenderPaint() { return new TvgRenderPaint();}
277 }