renderer: code refactoring. (#29)
[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 TvgRenderPath::TvgRenderPath()
8 {
9    this->m_Shape = tvg::Shape::gen().release();
10 }
11
12 TvgRenderPath::~TvgRenderPath()
13 {
14    delete(m_Shape);
15 }
16
17 void TvgRenderPath::fillRule(FillRule value)
18 {
19    switch (value)
20    {
21       case FillRule::evenOdd:
22          m_Shape->fill(tvg::FillRule::EvenOdd);
23          break;
24       case FillRule::nonZero:
25          m_Shape->fill(tvg::FillRule::Winding);
26          break;
27    }
28 }
29
30 Point applyTransform(const Vec2D &vec, const Mat2D &mat)
31 {
32    Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1};
33    m.e11 = mat[0];
34    m.e12 = mat[2];
35    m.e13 = mat[4];
36    m.e21 = mat[1];
37    m.e22 = mat[3];
38    m.e23 = mat[5];
39
40    return {vec[0] * m.e11 + vec[1] * m.e12 + m.e13, vec[0] * m.e21 + vec[1] * m.e22 + m.e23};
41 }
42
43 void TvgRenderPath::reset()
44 {
45    m_Shape->reset();
46    m_PathType.clear();
47    m_PathPoints.clear();
48 }
49
50 void TvgRenderPath::addRenderPath(RenderPath* path, const Mat2D& transform)
51 {
52    m_PathType = static_cast<TvgRenderPath*>(path)->m_PathType;
53    /* OPTIMIZE ME: Should avoid data copy here */
54    auto srcPathPoints = static_cast<TvgRenderPath*>(path)->m_PathPoints;
55    m_PathPoints.resize(srcPathPoints.size());
56    std::copy(srcPathPoints.begin(), srcPathPoints.end(), m_PathPoints.begin());
57
58    /* OPTIMIZE ME: Should avoid data copy in loop... */
59    int index = 0;
60
61    for (size_t i = 0; i < m_PathType.size(); i++)
62    {
63       /* OPTIMIZE ME: apply transform only when it's not identity */
64       switch(m_PathType[i])
65       {
66          case PathCommand::MoveTo:
67          {
68             auto pt = applyTransform(m_PathPoints[index], transform);
69             m_PathPoints[index] = {pt.x, pt.y};
70             m_Shape->moveTo(pt.x, pt.y);
71             index += 1;
72             break;
73          }
74          case PathCommand::LineTo:
75          {
76             auto pt = applyTransform(m_PathPoints[index], transform);
77             m_PathPoints[index] = {pt.x, pt.y};
78             m_Shape->lineTo(pt.x, pt.y);
79             index += 1;
80             break;
81          }
82          case PathCommand::CubicTo:
83          {
84             auto pt1 = applyTransform(m_PathPoints[index], transform);
85             auto pt2 = applyTransform(m_PathPoints[index + 1], transform);
86             auto pt3 = applyTransform(m_PathPoints[index + 2], transform);
87             m_PathPoints[index] = {pt1.x, pt1.y};
88             m_PathPoints[index + 1] = {pt2.x, pt2.y};
89             m_PathPoints[index + 2] = {pt3.x, pt3.y};
90             m_Shape->cubicTo(pt1.x, pt1.y, pt2.x, pt2.y, pt3.x, pt3.y);
91             index += 3;
92             break;
93          }
94          case PathCommand::Close:
95          {
96             m_Shape->close();
97             index += 1;
98             break;
99          }
100       }
101    }
102 }
103
104 void TvgRenderPath::moveTo(float x, float y)
105 {
106    m_PathType.push_back(PathCommand::MoveTo);
107    m_PathPoints.push_back({x, y});
108    m_Shape->moveTo(x, y);
109 }
110
111 void TvgRenderPath::lineTo(float x, float y)
112 {
113    m_PathType.push_back(PathCommand::LineTo);
114    m_PathPoints.push_back({x, y});
115    m_Shape->lineTo(x, y);
116 }
117
118 void TvgRenderPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y)
119 {
120    m_PathType.push_back(PathCommand::CubicTo);
121    m_PathPoints.push_back({ox, oy});
122    m_PathPoints.push_back({ix, iy});
123    m_PathPoints.push_back({x, y});
124    m_Shape->cubicTo(ox, oy, ix, iy, x, y);
125 }
126
127 void TvgRenderPath::close()
128 {
129    m_PathType.push_back(PathCommand::Close);
130    m_Shape->close();
131 }
132
133 TvgRenderPaint::TvgRenderPaint()
134 {
135
136 }
137
138 void TvgRenderPaint::style(RenderPaintStyle style)
139 {
140    m_Paint.style = style;
141 }
142
143 void TvgRenderPaint::color(unsigned int value)
144 {
145    m_Paint.color[0] = value >> 16 & 255;
146    m_Paint.color[1] = value >> 8 & 255;
147    m_Paint.color[2] = value >> 0 & 255;
148    m_Paint.color[3] = value >> 24 & 255;
149 }
150
151 void TvgRenderPaint::thickness(float value)
152 {
153    m_Paint.thickness = value;
154 }
155
156 void TvgRenderPaint::join(StrokeJoin value)
157 {
158    switch (value)
159    {
160       case rive::StrokeJoin::round:
161          m_Paint.join = tvg::StrokeJoin::Round;
162          break;
163       case rive::StrokeJoin::bevel:
164          m_Paint.join = tvg::StrokeJoin::Bevel;
165          break;
166       case rive::StrokeJoin::miter:
167          m_Paint.join = tvg::StrokeJoin::Miter;
168          break;
169    }
170 }
171
172 void TvgRenderPaint::cap(StrokeCap value)
173 {
174    switch (value)
175    {
176       case rive::StrokeCap::butt:
177          m_Paint.cap = tvg::StrokeCap::Butt;
178          break;
179       case rive::StrokeCap::round:
180          m_Paint.cap = tvg::StrokeCap::Round;
181          break;
182       case rive::StrokeCap::square:
183          m_Paint.cap = tvg::StrokeCap::Square;
184          break;
185    }
186 }
187
188 void TvgRenderPaint::linearGradient(float sx, float sy, float ex, float ey)
189 {
190    m_GradientBuilder = new TvgLinearGradientBuilder(sx, sy, ex, ey);
191 }
192
193 void TvgRenderPaint::radialGradient(float sx, float sy, float ex, float ey)
194 {
195    m_GradientBuilder = new TvgRadialGradientBuilder(sx, sy, ex, ey);
196 }
197
198 void TvgRenderPaint::addStop(unsigned int color, float stop)
199 {
200    m_GradientBuilder->stops.emplace_back(GradientStop(color, stop));
201 }
202
203 void TvgRenderPaint::completeGradient()
204 {
205    m_GradientBuilder->make(&m_Paint);
206    delete m_GradientBuilder;
207 }
208
209 void TvgRenderPaint::blendMode(BlendMode value)
210 {
211
212 }
213
214 void TvgRadialGradientBuilder::make(TvgPaint* paint)
215 {
216    paint->isGradient = true;
217    int numStops = stops.size();
218
219    paint->gradientFill = tvg::RadialGradient::gen().release();
220    float radius = Vec2D::distance(Vec2D(sx, sy), Vec2D(ex, ey));
221    static_cast<RadialGradient*>(paint->gradientFill)->radial(sx, sy, radius);
222
223    tvg::Fill::ColorStop colorStops[numStops];
224    for (int i = 0; i < numStops; i++)
225    {
226       unsigned int value = stops[i].color;
227       uint8_t r = value >> 16 & 255;
228       uint8_t g = value >> 8 & 255;
229       uint8_t b = value >> 0 & 255;
230       uint8_t a = value >> 24 & 255;
231
232       colorStops[i] = {stops[i].stop, r, g, b, a};
233    }
234
235    static_cast<RadialGradient*>(paint->gradientFill)->colorStops(colorStops, numStops);
236 }
237
238 void TvgLinearGradientBuilder::make(TvgPaint* paint)
239 {
240    paint->isGradient = true;
241    int numStops = stops.size();
242
243    paint->gradientFill = tvg::LinearGradient::gen().release();
244    static_cast<LinearGradient*>(paint->gradientFill)->linear(sx, sy, ex, ey);
245
246    tvg::Fill::ColorStop colorStops[numStops];
247    for (int i = 0; i < numStops; i++)
248    {
249       unsigned int value = stops[i].color;
250       uint8_t r = value >> 16 & 255;
251       uint8_t g = value >> 8 & 255;
252       uint8_t b = value >> 0 & 255;
253       uint8_t a = value >> 24 & 255;
254
255       colorStops[i] = {stops[i].stop, r, g, b, a};
256    }
257
258    static_cast<LinearGradient*>(paint->gradientFill)->colorStops(colorStops, numStops);
259 }
260
261 void TvgRenderer::save()
262 {
263    m_SaveTransform = m_Transform;
264 }
265
266 void TvgRenderer::restore()
267 {
268    m_Transform = m_SaveTransform;
269 }
270
271 void TvgRenderer::transform(const Mat2D& transform)
272 {
273    m_Transform = m_Transform * transform;
274 }
275
276 void TvgRenderer::drawPath(RenderPath* path, RenderPaint* paint)
277 {
278    auto shape = static_cast<TvgRenderPath*>(path)->shape();
279    auto tvgPaint = static_cast<TvgRenderPaint*>(paint)->paint();
280
281    /* OPTIMIZE ME: Stroke / Fill Paints required to draw separately.
282       thorvg doesn't need to handle both, we can avoid one of them rendering... */
283
284    if (tvgPaint->style == RenderPaintStyle::fill)
285    {
286       if (tvgPaint->isGradient == false)
287          shape->fill(tvgPaint->color[0], tvgPaint->color[1], tvgPaint->color[2], tvgPaint->color[3]);
288       else
289       {
290          if (tvgPaint->gradientApplied == false)
291          {
292             shape->fill(unique_ptr<tvg::Fill>(tvgPaint->gradientFill));
293             tvgPaint->gradientApplied = true;
294          }
295       }
296    }
297    else if (tvgPaint->style == RenderPaintStyle::stroke)
298    {
299       shape->stroke(tvgPaint->cap);
300       shape->stroke(tvgPaint->join);
301       shape->stroke(tvgPaint->thickness);
302
303       if (tvgPaint->isGradient == false)
304          shape->stroke(tvgPaint->color[0], tvgPaint->color[1], tvgPaint->color[2], tvgPaint->color[3]);
305       else
306       {
307         if (tvgPaint->gradientApplied == false)
308         {
309           shape->stroke(unique_ptr<tvg::Fill>(tvgPaint->gradientFill));
310           tvgPaint->gradientApplied = true;
311         }
312       }
313    }
314
315    if (m_ClipPath)
316    {
317       m_ClipPath->fill(255, 255, 255, 255);
318       shape->composite(unique_ptr<Shape>(static_cast<Shape*>(m_ClipPath->duplicate())), tvg::CompositeMethod::ClipPath);
319       m_ClipPath = nullptr;
320    }
321
322    shape->transform({m_Transform[0], m_Transform[2], m_Transform[4], m_Transform[1], m_Transform[3], m_Transform[5], 0, 0, 1});
323    m_Canvas->push(unique_ptr<Paint>(shape->duplicate()));
324 }
325
326
327 void TvgRenderer::clipPath(RenderPath* path)
328 {
329    //Note: ClipPath transform matrix is calculated by transfrom matrix in addRenderPath function
330    m_ClipPath = static_cast<TvgRenderPath*>(path)->shape();
331    m_ClipPath->transform({m_Transform[0], m_Transform[2], m_Transform[4], m_Transform[1], m_Transform[3], m_Transform[5], 0, 0, 1});
332 }
333
334 namespace rive
335 {
336    RenderPath* makeRenderPath() { return new TvgRenderPath();}
337    RenderPaint* makeRenderPaint() { return new TvgRenderPaint();}
338 }