1 #include "tvg_renderer.hpp"
2 #include "math/vec2d.hpp"
3 #include "shapes/paint/color.hpp"
8 void TvgRenderPath::fillRule(FillRule value)
12 case FillRule::evenOdd:
13 tvgShape->fill(tvg::FillRule::EvenOdd);
15 case FillRule::nonZero:
16 tvgShape->fill(tvg::FillRule::Winding);
21 Point transformCoord(const Point pt, const Mat2D &transform)
23 Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1};
31 return {pt.x * m.e11 + pt.y * m.e12 + m.e13, pt.x * m.e21 + pt.y * m.e22 + m.e23};
34 void TvgRenderPath::reset()
39 void TvgRenderPath::addRenderPath(RenderPath* path, const Mat2D& transform)
42 auto ptsCnt = static_cast<TvgRenderPath*>(path)->tvgShape->pathCoords(&pts);
45 const PathCommand* cmds;
46 auto cmdCnt = static_cast<TvgRenderPath*>(path)->tvgShape->pathCommands(&cmds);
49 //Capture the last coordinates
51 auto ptsCnt2 = tvgShape->pathCoords(const_cast<const Point**>(&pts2));
53 tvgShape->appendPath(cmds, cmdCnt, pts, ptsCnt);
55 //Immediate Transform for the newly appended
57 auto ptsCnt3 = tvgShape->pathCoords(const_cast<const Point**>(&pts3));
59 for (unsigned i = ptsCnt2; i < ptsCnt3; ++i)
61 pts3[i] = transformCoord(pts3[i], transform);
65 void TvgRenderPath::moveTo(float x, float y)
67 tvgShape->moveTo(x, y);
70 void TvgRenderPath::lineTo(float x, float y)
72 tvgShape->lineTo(x, y);
75 void TvgRenderPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y)
77 tvgShape->cubicTo(ox, oy, ix, iy, x, y);
80 void TvgRenderPath::close()
85 void TvgRenderPaint::style(RenderPaintStyle style)
87 m_Paint.style = style;
90 void TvgRenderPaint::color(unsigned int value)
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;
98 void TvgRenderPaint::thickness(float value)
100 m_Paint.thickness = value;
103 void TvgRenderPaint::join(StrokeJoin value)
107 case rive::StrokeJoin::round:
108 m_Paint.join = tvg::StrokeJoin::Round;
110 case rive::StrokeJoin::bevel:
111 m_Paint.join = tvg::StrokeJoin::Bevel;
113 case rive::StrokeJoin::miter:
114 m_Paint.join = tvg::StrokeJoin::Miter;
119 void TvgRenderPaint::cap(StrokeCap value)
123 case rive::StrokeCap::butt:
124 m_Paint.cap = tvg::StrokeCap::Butt;
126 case rive::StrokeCap::round:
127 m_Paint.cap = tvg::StrokeCap::Round;
129 case rive::StrokeCap::square:
130 m_Paint.cap = tvg::StrokeCap::Square;
135 void TvgRenderPaint::linearGradient(float sx, float sy, float ex, float ey)
137 m_GradientBuilder = new TvgLinearGradientBuilder(sx, sy, ex, ey);
140 void TvgRenderPaint::radialGradient(float sx, float sy, float ex, float ey)
142 m_GradientBuilder = new TvgRadialGradientBuilder(sx, sy, ex, ey);
145 void TvgRenderPaint::addStop(unsigned int color, float stop)
147 m_GradientBuilder->stops.emplace_back(GradientStop(color, stop));
150 void TvgRenderPaint::completeGradient()
152 m_GradientBuilder->make(&m_Paint);
153 delete m_GradientBuilder;
156 void TvgRenderPaint::blendMode(BlendMode value)
161 void TvgRadialGradientBuilder::make(TvgPaint* paint)
163 paint->isGradient = true;
164 int numStops = stops.size();
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);
170 tvg::Fill::ColorStop colorStops[numStops];
171 for (int i = 0; i < numStops; i++)
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;
179 colorStops[i] = {stops[i].stop, r, g, b, a};
182 static_cast<RadialGradient*>(paint->gradientFill)->colorStops(colorStops, numStops);
185 void TvgLinearGradientBuilder::make(TvgPaint* paint)
187 paint->isGradient = true;
188 int numStops = stops.size();
190 paint->gradientFill = tvg::LinearGradient::gen().release();
191 static_cast<LinearGradient*>(paint->gradientFill)->linear(sx, sy, ex, ey);
193 tvg::Fill::ColorStop colorStops[numStops];
194 for (int i = 0; i < numStops; i++)
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;
202 colorStops[i] = {stops[i].stop, r, g, b, a};
205 static_cast<LinearGradient*>(paint->gradientFill)->colorStops(colorStops, numStops);
208 void TvgRenderer::save()
210 m_SaveTransform = m_Transform;
213 void TvgRenderer::restore()
215 m_Transform = m_SaveTransform;
218 void TvgRenderer::transform(const Mat2D& transform)
220 m_Transform = m_Transform * transform;
223 void TvgRenderer::drawPath(RenderPath* path, RenderPaint* paint)
225 auto tvgShape = static_cast<TvgRenderPath*>(path)->tvgShape.get();
226 auto tvgPaint = static_cast<TvgRenderPaint*>(paint)->paint();
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... */
231 if (tvgPaint->style == RenderPaintStyle::fill)
233 if (!tvgPaint->isGradient)
234 tvgShape->fill(tvgPaint->color[0], tvgPaint->color[1], tvgPaint->color[2], tvgPaint->color[3]);
237 tvgShape->fill(unique_ptr<tvg::Fill>(tvgPaint->gradientFill->duplicate()));
240 else if (tvgPaint->style == RenderPaintStyle::stroke)
242 tvgShape->stroke(tvgPaint->cap);
243 tvgShape->stroke(tvgPaint->join);
244 tvgShape->stroke(tvgPaint->thickness);
246 if (!tvgPaint->isGradient)
247 tvgShape->stroke(tvgPaint->color[0], tvgPaint->color[1], tvgPaint->color[2], tvgPaint->color[3]);
250 tvgShape->stroke(unique_ptr<tvg::Fill>(tvgPaint->gradientFill->duplicate()));
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;
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()));
266 void TvgRenderer::clipPath(RenderPath* path)
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});
275 RenderPath* makeRenderPath() { return new TvgRenderPath();}
276 RenderPaint* makeRenderPaint() { return new TvgRenderPaint();}