[Tizen] Implements CanvasRenderer that can draw Vector Primitives using ThorVG
[platform/core/uifw/dali-adaptor.git] / dali / internal / canvas-renderer / ubuntu / shape-impl-ubuntu.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/canvas-renderer/ubuntu/shape-impl-ubuntu.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/object/type-registry.h>
24
25 namespace Dali
26 {
27 namespace Internal
28 {
29 namespace Adaptor
30 {
31 namespace // unnamed namespace
32 {
33 // Type Registration
34 Dali::BaseHandle Create()
35 {
36   return Dali::BaseHandle();
37 }
38
39 Dali::TypeRegistration type(typeid(Dali::CanvasRenderer::Shape), typeid(Dali::BaseHandle), Create);
40
41 } // unnamed namespace
42
43 ShapeUbuntu* ShapeUbuntu::New()
44 {
45   return new ShapeUbuntu();
46 }
47
48 ShapeUbuntu::ShapeUbuntu()
49 #ifdef THORVG_SUPPORT
50 : mTvgShape(nullptr)
51 #endif
52 {
53   Initialize();
54 }
55
56 ShapeUbuntu::~ShapeUbuntu()
57 {
58 }
59
60 void ShapeUbuntu::Initialize()
61 {
62 #ifdef THORVG_SUPPORT
63   mTvgShape = tvg::Shape::gen().release();
64   if(!mTvgShape)
65   {
66     DALI_LOG_ERROR("Shape is null [%p]\n", this);
67   }
68
69   Drawable::Create();
70   Drawable::SetObject(static_cast<void*>(mTvgShape));
71
72 #endif
73 }
74
75 bool ShapeUbuntu::AddRect(Rect<float> rect, Vector2 roundedCorner)
76 {
77 #ifdef THORVG_SUPPORT
78   if(!mTvgShape)
79   {
80     DALI_LOG_ERROR("Shape is null [%p]\n", this);
81     return false;
82   }
83   if(static_cast<tvg::Shape*>(mTvgShape)->appendRect(rect.x, rect.y, rect.width, rect.height, roundedCorner.x, roundedCorner.y) != tvg::Result::Success)
84   {
85     DALI_LOG_ERROR("Add Rect Fail [%p]\n", this);
86     return false;
87   }
88   Drawable::SetChanged(true);
89   return true;
90 #else
91   return false;
92 #endif
93 }
94
95 bool ShapeUbuntu::AddCircle(Vector2 center, Vector2 radius)
96 {
97 #ifdef THORVG_SUPPORT
98   if(!mTvgShape)
99   {
100     DALI_LOG_ERROR("Shape is null [%p]\n", this);
101     return false;
102   }
103   if(static_cast<tvg::Shape*>(mTvgShape)->appendCircle(center.x, center.y, radius.x, radius.y) != tvg::Result::Success)
104   {
105     DALI_LOG_ERROR("Add Circle Fail [%p]\n", this);
106     return false;
107   }
108   Drawable::SetChanged(true);
109   return true;
110 #else
111   return false;
112 #endif
113 }
114
115 bool ShapeUbuntu::AddArc(Vector2 center, float radius, float startAngle, float sweep, bool pie)
116 {
117 #ifdef THORVG_SUPPORT
118   if(!mTvgShape)
119   {
120     DALI_LOG_ERROR("Shape is null\n");
121     return false;
122   }
123
124   if(static_cast<tvg::Shape*>(mTvgShape)->appendArc(center.x, center.y, radius, startAngle, sweep, pie) != tvg::Result::Success)
125   {
126     DALI_LOG_ERROR("Add arc fail.\n");
127     return false;
128   }
129   Drawable::SetChanged(true);
130   return true;
131 #else
132   return false;
133 #endif
134 }
135
136 bool ShapeUbuntu::AddMoveTo(Vector2 point)
137 {
138 #ifdef THORVG_SUPPORT
139   if(!mTvgShape)
140   {
141     DALI_LOG_ERROR("Shape is null\n");
142     return false;
143   }
144
145   if(static_cast<tvg::Shape*>(mTvgShape)->moveTo(point.x, point.y) != tvg::Result::Success)
146   {
147     DALI_LOG_ERROR("AddMoveTo() fail.\n");
148     return false;
149   }
150   Drawable::SetChanged(true);
151   return true;
152 #else
153   return false;
154 #endif
155 }
156
157 bool ShapeUbuntu::AddLineTo(Vector2 line)
158 {
159 #ifdef THORVG_SUPPORT
160   if(!mTvgShape)
161   {
162     DALI_LOG_ERROR("Shape is null\n");
163     return false;
164   }
165
166   if(static_cast<tvg::Shape*>(mTvgShape)->lineTo(line.x, line.y) != tvg::Result::Success)
167   {
168     DALI_LOG_ERROR("AddLineTo() fail.\n");
169     return false;
170   }
171   Drawable::SetChanged(true);
172   return true;
173 #else
174   return false;
175 #endif
176 }
177
178 bool ShapeUbuntu::AddCubicTo(Vector2 controlPoint1, Vector2 controlPoint2, Vector2 endPoint)
179 {
180 #ifdef THORVG_SUPPORT
181   if(!mTvgShape)
182   {
183     DALI_LOG_ERROR("Shape is null\n");
184     return false;
185   }
186
187   if(static_cast<tvg::Shape*>(mTvgShape)->cubicTo(controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y) != tvg::Result::Success)
188   {
189     DALI_LOG_ERROR("cubicTo() fail.\n");
190     return false;
191   }
192   Drawable::SetChanged(true);
193   return true;
194 #else
195   return false;
196 #endif
197 }
198
199 bool ShapeUbuntu::Close()
200 {
201 #ifdef THORVG_SUPPORT
202   if(!mTvgShape)
203   {
204     DALI_LOG_ERROR("Shape is null\n");
205     return false;
206   }
207
208   if(static_cast<tvg::Shape*>(mTvgShape)->close() != tvg::Result::Success)
209   {
210     DALI_LOG_ERROR("close() fail.\n");
211     return false;
212   }
213   Drawable::SetChanged(true);
214   return true;
215 #else
216   return false;
217 #endif
218 }
219
220 bool ShapeUbuntu::SetFillColor(Vector4 color)
221 {
222 #ifdef THORVG_SUPPORT
223   if(!mTvgShape)
224   {
225     DALI_LOG_ERROR("Shape is null [%p]\n", this);
226     return false;
227   }
228
229   if(static_cast<tvg::Shape*>(mTvgShape)->fill((uint8_t)(color.r * 255.f), (uint8_t)(color.g * 255.f), (uint8_t)(color.b * 255.f), (uint8_t)(color.a * 255.f)) != tvg::Result::Success)
230   {
231     DALI_LOG_ERROR("SetFillColor fail [%p]\n", this);
232     return false;
233   }
234   Drawable::SetChanged(true);
235   return true;
236 #else
237   return false;
238 #endif
239 }
240
241 Vector4 ShapeUbuntu::GetFillColor() const
242 {
243 #ifdef THORVG_SUPPORT
244   if(!mTvgShape)
245   {
246     DALI_LOG_ERROR("Shape is null [%p]\n", this);
247     return Vector4(0, 0, 0, 0);
248   }
249   uint8_t r, g, b, a;
250
251   if(static_cast<tvg::Shape*>(mTvgShape)->fillColor(&r, &g, &b, &a) != tvg::Result::Success)
252   {
253     DALI_LOG_ERROR("GetFillColor fail [%p]\n", this);
254     return Vector4(0, 0, 0, 0);
255   }
256   return Vector4(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
257 #else
258   return Vector4(0, 0, 0, 0);
259 #endif
260 }
261
262 bool ShapeUbuntu::SetFillRule(Dali::CanvasRenderer::Shape::FillRule rule)
263 {
264 #ifdef THORVG_SUPPORT
265   if(!mTvgShape)
266   {
267     DALI_LOG_ERROR("Shape is null\n");
268     return false;
269   }
270   if(static_cast<tvg::Shape*>(mTvgShape)->fill(static_cast<tvg::FillRule>(rule)) != tvg::Result::Success)
271   {
272     DALI_LOG_ERROR("SetFillRule fail.\n");
273     return false;
274   }
275   Drawable::SetChanged(true);
276   return true;
277 #else
278   return false;
279 #endif
280 }
281
282 Dali::CanvasRenderer::Shape::FillRule ShapeUbuntu::GetFillRule() const
283 {
284 #ifdef THORVG_SUPPORT
285   if(!mTvgShape)
286   {
287     DALI_LOG_ERROR("Shape is null\n");
288     return Dali::CanvasRenderer::Shape::FillRule::WINDING;
289   }
290
291   tvg::FillRule rule = static_cast<tvg::Shape*>(mTvgShape)->fillRule();
292
293   return static_cast<Dali::CanvasRenderer::Shape::FillRule>(rule);
294 #endif
295   return Dali::CanvasRenderer::Shape::FillRule::WINDING;
296 }
297
298 bool ShapeUbuntu::SetStrokeWidth(float width)
299 {
300 #ifdef THORVG_SUPPORT
301   if(!mTvgShape)
302   {
303     DALI_LOG_ERROR("Shape is null\n");
304     return false;
305   }
306
307   if(static_cast<tvg::Shape*>(mTvgShape)->stroke(width) != tvg::Result::Success)
308   {
309     DALI_LOG_ERROR("SetStrokeWidth fail.\n");
310     return false;
311   }
312   Drawable::SetChanged(true);
313   return true;
314 #else
315   return false;
316 #endif
317 }
318
319 float ShapeUbuntu::GetStrokeWidth() const
320 {
321 #ifdef THORVG_SUPPORT
322   if(!mTvgShape)
323   {
324     DALI_LOG_ERROR("Shape is null\n");
325     return false;
326   }
327   return static_cast<tvg::Shape*>(mTvgShape)->strokeWidth();
328 #else
329   return false;
330 #endif
331 }
332
333 bool ShapeUbuntu::SetStrokeColor(Vector4 color)
334 {
335 #ifdef THORVG_SUPPORT
336   if(!mTvgShape)
337   {
338     DALI_LOG_ERROR("Shape is null\n");
339     return false;
340   }
341
342   if(static_cast<tvg::Shape*>(mTvgShape)->stroke(color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a * 255.f) != tvg::Result::Success)
343   {
344     DALI_LOG_ERROR("SetStrokeColor fail.\n");
345     return false;
346   }
347   Drawable::SetChanged(true);
348   return true;
349 #else
350   return false;
351 #endif
352 }
353
354 Vector4 ShapeUbuntu::GetStrokeColor() const
355 {
356 #ifdef THORVG_SUPPORT
357   if(!mTvgShape)
358   {
359     DALI_LOG_ERROR("Shape is null\n");
360     return Vector4(0, 0, 0, 0);
361   }
362
363   uint8_t r, g, b, a;
364
365   if(static_cast<tvg::Shape*>(mTvgShape)->strokeColor(&r, &g, &b, &a) != tvg::Result::Success)
366   {
367     DALI_LOG_ERROR("GetStrokeColor fail.\n");
368     return Vector4(0, 0, 0, 0);
369   }
370   return Vector4(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
371 #else
372   return Vector4(0, 0, 0, 0);
373 #endif
374 }
375
376 bool ShapeUbuntu::SetStrokeDash(const Dali::Vector<float> dashPattern)
377 {
378 #ifdef THORVG_SUPPORT
379   if(!mTvgShape)
380   {
381     DALI_LOG_ERROR("Shape is null\n");
382     return false;
383   }
384
385   float* tvgDashPattern = (float*)alloca(sizeof(float) * dashPattern.Count());
386
387   for(unsigned int i = 0u; i < dashPattern.Count(); ++i)
388   {
389     tvgDashPattern[i] = dashPattern[i];
390   }
391
392   if(static_cast<tvg::Shape*>(mTvgShape)->stroke(tvgDashPattern, dashPattern.Count()) != tvg::Result::Success)
393   {
394     DALI_LOG_ERROR("SetStrokeDash fail.\n");
395     return false;
396   }
397   Drawable::SetChanged(true);
398   return true;
399 #else
400   return false;
401 #endif
402 }
403
404 Dali::Vector<float> ShapeUbuntu::GetStrokeDash() const
405 {
406 #ifdef THORVG_SUPPORT
407   if(!mTvgShape)
408   {
409     DALI_LOG_ERROR("Shape is null\n");
410     return Vector<float>();
411   }
412   const float* tvgDashPattern = nullptr;
413   uint32_t     count          = 0;
414
415   count = static_cast<tvg::Shape*>(mTvgShape)->strokeDash(&tvgDashPattern);
416   if(!tvgDashPattern || count <= 0)
417   {
418     DALI_LOG_ERROR("GetStrokeDash() fail.\n");
419     return Vector<float>();
420   }
421
422   Dali::Vector<float> dashPattern;
423
424   dashPattern.Reserve(count);
425
426   for(unsigned int i = 0u; i < count; ++i)
427   {
428     dashPattern.PushBack(tvgDashPattern[i]);
429   }
430   return dashPattern;
431 #else
432   return Vector<float>();
433 #endif
434 }
435
436 bool ShapeUbuntu::SetStrokeCap(Dali::CanvasRenderer::Shape::StrokeCap cap)
437 {
438 #ifdef THORVG_SUPPORT
439   if(!mTvgShape)
440   {
441     DALI_LOG_ERROR("Shape is null\n");
442     return false;
443   }
444   if(static_cast<tvg::Shape*>(mTvgShape)->stroke(static_cast<tvg::StrokeCap>(cap)) != tvg::Result::Success)
445   {
446     DALI_LOG_ERROR("SetStrokeCap fail.\n");
447     return false;
448   }
449   Drawable::SetChanged(true);
450   return true;
451 #else
452   return false;
453 #endif
454 }
455
456 Dali::CanvasRenderer::Shape::StrokeCap ShapeUbuntu::GetStrokeCap() const
457 {
458 #ifdef THORVG_SUPPORT
459   if(!mTvgShape)
460   {
461     DALI_LOG_ERROR("Shape is null\n");
462     return Dali::CanvasRenderer::Shape::StrokeCap::SQUARE;
463   }
464
465   tvg::StrokeCap cap = static_cast<tvg::Shape*>(mTvgShape)->strokeCap();
466
467   return static_cast<Dali::CanvasRenderer::Shape::StrokeCap>(cap);
468 #endif
469   return Dali::CanvasRenderer::Shape::StrokeCap::SQUARE;
470 }
471
472 bool ShapeUbuntu::SetStrokeJoin(Dali::CanvasRenderer::Shape::StrokeJoin join)
473 {
474 #ifdef THORVG_SUPPORT
475   if(!mTvgShape)
476   {
477     DALI_LOG_ERROR("Shape is null\n");
478     return false;
479   }
480
481   if(static_cast<tvg::Shape*>(mTvgShape)->stroke(static_cast<tvg::StrokeJoin>(join)) != tvg::Result::Success)
482   {
483     DALI_LOG_ERROR("SetStrokejoin fail.\n");
484     return false;
485   }
486   Drawable::SetChanged(true);
487   return true;
488 #else
489   return false;
490 #endif
491 }
492
493 Dali::CanvasRenderer::Shape::StrokeJoin ShapeUbuntu::GetStrokeJoin() const
494 {
495 #ifdef THORVG_SUPPORT
496   if(!mTvgShape)
497   {
498     DALI_LOG_ERROR("Shape is null\n");
499     return Dali::CanvasRenderer::Shape::StrokeJoin::BEVEL;
500   }
501
502   tvg::StrokeJoin join = static_cast<tvg::Shape*>(mTvgShape)->strokeJoin();
503
504   return static_cast<Dali::CanvasRenderer::Shape::StrokeJoin>(join);
505 #endif
506   return Dali::CanvasRenderer::Shape::StrokeJoin::BEVEL;
507 }
508
509 } // namespace Adaptor
510
511 } // namespace Internal
512
513 } // namespace Dali