From e9d6bd7833232e754d751cb7fcaf5407eb5a1295 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Wed, 24 Jun 2020 19:35:40 +0900 Subject: [PATCH 01/16] SvgLoader: Implement SvgSceneBuilder using SvgNode SvgSceneBuilder builds Scene using SvgNode tree. build(root node) function return the root scene. Following SVG tags are supported. Polygon, Polyline, Circle, Rect, Line Change-Id: I8c9b8c28d9a4799af6ddc45c35f77a75f696b2a5 --- src/loaders/svg_loader/meson.build | 2 + src/loaders/svg_loader/tvgSvgLoader.cpp | 4 +- src/loaders/svg_loader/tvgSvgLoader.h | 4 + src/loaders/svg_loader/tvgSvgSceneBuilder.cpp | 188 ++++++++++++++++++++++++++ src/loaders/svg_loader/tvgSvgSceneBuilder.h | 42 ++++++ 5 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 src/loaders/svg_loader/tvgSvgSceneBuilder.cpp create mode 100644 src/loaders/svg_loader/tvgSvgSceneBuilder.h diff --git a/src/loaders/svg_loader/meson.build b/src/loaders/svg_loader/meson.build index 88fd37a..21967af 100644 --- a/src/loaders/svg_loader/meson.build +++ b/src/loaders/svg_loader/meson.build @@ -2,8 +2,10 @@ source_file = [ 'tvgSimpleXmlParser.h', 'tvgSvgLoader.h', 'tvgSvgLoaderCommon.h', + 'tvgSvgSceneBuilder.h', 'tvgSimpleXmlParser.cpp', 'tvgSvgLoader.cpp', + 'tvgSvgSceneBuilder.cpp', ] svgloader_dep = declare_dependency( diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index 4db8200..4dd5fd4 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -2289,6 +2289,8 @@ bool SvgLoader::read() } } + root = builder.build(loaderData.doc); + if (!res) return false; return true; } @@ -2304,7 +2306,7 @@ bool SvgLoader::close() unique_ptr SvgLoader::data() { - return nullptr; + return move(root); } #endif //_TVG_SVG_LOADER_CPP_ diff --git a/src/loaders/svg_loader/tvgSvgLoader.h b/src/loaders/svg_loader/tvgSvgLoader.h index 13441f3..eba74c3 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.h +++ b/src/loaders/svg_loader/tvgSvgLoader.h @@ -18,12 +18,16 @@ #define _TVG_SVG_LOADER_H_ #include "tvgSvgLoaderCommon.h" +#include "tvgSvgSceneBuilder.h" + class SvgLoader : public Loader { private: string content; SvgLoaderData loaderData; + SvgSceneBuilder builder; + unique_ptr root; public: SvgLoader(); diff --git a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp new file mode 100644 index 0000000..601ed0c --- /dev/null +++ b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _TVG_SVG_SCENE_BUILDER_CPP_ +#define _TVG_SVG_SCENE_BUILDER_CPP_ + + +#include "tvgSvgSceneBuilder.h" + + +unique_ptr _applyProperty(SvgNode* node, unique_ptr vg) +{ + SvgStyleProperty* style = node->style; + + //Apply the transformation + if (node->transform) vg->transform(*node->transform); + + if (node->type == SvgNodeType::Doc) return vg; + + //If fill property is nullptr then do nothing + if (style->fill.paint.none) { + //Do nothing + } else if (style->fill.paint.gradient) { + //TODO: Support gradient style + } else if (style->fill.paint.curColor) { + //Apply the current style color + float fa = ((float)style->fill.opacity / 255.0); + vg->fill(((float)style->r) * fa, ((float)style->g) * fa, ((float)style->b) * fa, style->fill.opacity); + } else { + //Apply the fill color + float fa = ((float)style->fill.opacity / 255.0); + vg->fill(((float)style->fill.paint.r) * fa, ((float)style->fill.paint.g) * fa, ((float)style->fill.paint.b) * fa, style->fill.opacity); + } + + //Apply node opacity + if (style->opacity < 255) { + uint8_t r, g, b, a; + vg->fill(&r, &g, &b, &a); + float fa = ((float)style->opacity / 255.0); + vg->fill(((float)r) * fa, ((float)g) * fa, ((float)b) * fa, ((float)a) * fa); + } + + if (node->type == SvgNodeType::G) return vg; + + //Apply the stroke style property + vg->stroke(style->stroke.width); + vg->stroke(style->stroke.cap); + vg->stroke(style->stroke.join); + + + //If stroke property is nullptr then do nothing + if (style->stroke.paint.none) { + //Do nothing + } else if (style->stroke.paint.gradient) { + //TODO: Support gradient style + } else if (style->stroke.paint.url) { + //TODO: Apply the color pointed by url + } else if (style->stroke.paint.curColor) { + //Apply the current style color + vg->stroke(style->r, style->g, style->b, style->stroke.opacity); + + } else { + //Apply the stroke color + vg->stroke(style->stroke.paint.r, style->stroke.paint.g, style->stroke.paint.b, style->stroke.opacity); + } + + //Apply node opacity to stroke color + if (style->opacity < 255) { + uint8_t r, g, b, a; + vg->strokeColor(&r, &g, &b, &a); + float fa = ((float)style->opacity / 255.0); + vg->stroke(((float)r) * fa, ((float)g) * fa, ((float)b) * fa, ((float)a) * fa); + } + return vg; +} + + +unique_ptr _shapeBuildHelper(SvgNode* node) +{ + auto shape = tvg::Shape::gen(); + switch (node->type) { + case SvgNodeType::Path: { + //TODO: Support path + break; + } + case SvgNodeType::Ellipse: { + //TODO: Support ellipse + break; + } + case SvgNodeType::Polygon: { + if (node->node.polygon.pointsCount < 2) break; + shape->moveTo(node->node.polygon.points[0], node->node.polygon.points[1]); + for (int i = 2; i < node->node.polygon.pointsCount; i += 2) { + shape->lineTo(node->node.polygon.points[i], node->node.polygon.points[i + 1]); + } + shape->close(); + break; + } + case SvgNodeType::Polyline: { + if (node->node.polygon.pointsCount < 2) break; + shape->moveTo(node->node.polygon.points[0], node->node.polygon.points[1]); + for (int i = 2; i < node->node.polygon.pointsCount; i += 2) { + shape->lineTo(node->node.polygon.points[i], node->node.polygon.points[i + 1]); + } + break; + } + case SvgNodeType::Circle: { + shape->appendCircle(node->node.circle.cx, node->node.circle.cy, node->node.circle.r, node->node.circle.r); + break; + } + case SvgNodeType::Rect: { + if (node->node.rect.rx == node->node.rect.ry) { + shape->appendRect(node->node.rect.x, node->node.rect.y, node->node.rect.w, node->node.rect.h, node->node.rect.rx); + } + else { + //TODO: Support rounded rectangle + } + break; + } + case SvgNodeType::Line: { + shape->moveTo(node->node.line.x1, node->node.line.y1); + shape->lineTo(node->node.line.x2, node->node.line.y2); + break; + } + default: { + break; + } + } + shape = move(_applyProperty(node, move(shape))); + return shape; +} + + +unique_ptr _sceneBuildHelper(SvgNode* node) +{ + if (node->type == SvgNodeType::Doc || node->type == SvgNodeType::G) { + auto scene = tvg::Scene::gen(); + if (node->transform) scene->transform(*node->transform); + + for (vector::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) { + SvgNode* child = *itrChild; + if (child->type == SvgNodeType::Doc || child->type == SvgNodeType::G) scene->push(_sceneBuildHelper(*itrChild)); + else scene->push(_shapeBuildHelper(*itrChild)); + } + return move(scene); + } + return nullptr; +} + + +SvgSceneBuilder::SvgSceneBuilder() +{ +} + + +SvgSceneBuilder::~SvgSceneBuilder() +{ +} + + +unique_ptr SvgSceneBuilder::build(SvgNode* node) +{ + if (!node || (node->type != SvgNodeType::Doc)) return nullptr; + + viewBox.x = node->node.doc.vx; + viewBox.y = node->node.doc.vy; + viewBox.w = node->node.doc.vw; + viewBox.h = node->node.doc.vh; + preserveAspect = node->node.doc.preserveAspect; + staticViewBox = true; + return _sceneBuildHelper(node); +} + + +#endif //_TVG_SVG_SCENE_BUILDER_CPP_ diff --git a/src/loaders/svg_loader/tvgSvgSceneBuilder.h b/src/loaders/svg_loader/tvgSvgSceneBuilder.h new file mode 100644 index 0000000..20a41a7 --- /dev/null +++ b/src/loaders/svg_loader/tvgSvgSceneBuilder.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _TVG_SVG_SCENE_BUILDER_H_ +#define _TVG_SVG_SCENE_BUILDER_H_ + +#include "tvgSvgLoaderCommon.h" + +class SvgSceneBuilder +{ +private: + struct { + int x, y; + uint32_t w, h; + } viewBox; + int ref; + uint32_t w, h; //Default size + bool staticViewBox; + bool preserveAspect; //Used in SVG + bool shareable; + +public: + SvgSceneBuilder(); + ~SvgSceneBuilder(); + + unique_ptr build(SvgNode* node); +}; + +#endif //_TVG_SVG_SCENE_BUILDER_H_ -- 2.7.4 From 3fe2eedd897faed9e7ce259e44418c2e404a8225 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Fri, 26 Jun 2020 18:51:36 +0900 Subject: [PATCH 02/16] SvgLoader: Implement svgpath draw Convert Svg path in string to tvg::PathCommand. Draw converted data by adding it as path to shape. Following tags are supported. Move, Line, Cubic, SCubic, Vertical, Horizontal and Close. Change-Id: I3cb31e05bcb233b4c187e0c9e7eef8cdadf84695 --- src/loaders/svg_loader/meson.build | 2 + src/loaders/svg_loader/tvgSvgPath.cpp | 297 ++++++++++++++++++++++++++ src/loaders/svg_loader/tvgSvgPath.h | 8 + src/loaders/svg_loader/tvgSvgSceneBuilder.cpp | 5 +- src/loaders/svg_loader/tvgSvgSceneBuilder.h | 1 + 5 files changed, 312 insertions(+), 1 deletion(-) create mode 100644 src/loaders/svg_loader/tvgSvgPath.cpp create mode 100644 src/loaders/svg_loader/tvgSvgPath.h diff --git a/src/loaders/svg_loader/meson.build b/src/loaders/svg_loader/meson.build index 21967af..de7adf7 100644 --- a/src/loaders/svg_loader/meson.build +++ b/src/loaders/svg_loader/meson.build @@ -2,9 +2,11 @@ source_file = [ 'tvgSimpleXmlParser.h', 'tvgSvgLoader.h', 'tvgSvgLoaderCommon.h', + 'tvgSvgPath.h', 'tvgSvgSceneBuilder.h', 'tvgSimpleXmlParser.cpp', 'tvgSvgLoader.cpp', + 'tvgSvgPath.cpp', 'tvgSvgSceneBuilder.cpp', ] diff --git a/src/loaders/svg_loader/tvgSvgPath.cpp b/src/loaders/svg_loader/tvgSvgPath.cpp new file mode 100644 index 0000000..70058e0 --- /dev/null +++ b/src/loaders/svg_loader/tvgSvgPath.cpp @@ -0,0 +1,297 @@ +#ifndef __TVG_SVG_PATH_CPP_ +#define __TVG_SVG_PATH_CPP_ + +#include "tvgSvgPath.h" + + +static char* _skipComma(const char* content) +{ + while (*content && isspace(*content)) { + content++; + } + if (*content == ',') return (char*)content + 1; + return (char*)content; +} + + +static inline bool _parseNumber(char** content, float* number) +{ + char* end = NULL; + *number = strtof(*content, &end); + //If the start of string is not number + if ((*content) == end) return false; + //Skip comma if any + *content = _skipComma(end); + return true; +} + + +static inline bool _parseLong(char** content, int* number) +{ + char* end = NULL; + *number = strtol(*content, &end, 10) ? 1 : 0; + //If the start of string is not number + if ((*content) == end) return false; + *content = _skipComma(end); + return true; +} + + +static int _numberCount(char cmd) +{ + int count = 0; + switch (cmd) { + case 'M': + case 'm': + case 'L': + case 'l': { + count = 2; + break; + } + case 'C': + case 'c': + case 'E': + case 'e': { + count = 6; + break; + } + case 'H': + case 'h': + case 'V': + case 'v': { + count = 1; + break; + } + case 'S': + case 's': + case 'Q': + case 'q': + case 'T': + case 't': { + count = 4; + break; + } + case 'A': + case 'a': { + count = 7; + break; + } + default: + break; + } + return count; +} + + +static void _processCommand(vector* cmds, vector* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl) +{ + int i; + switch (cmd) { + case 'm': + case 'l': + case 'c': + case 's': + case 'q': + case 't': { + for (i = 0; i < count - 1; i += 2) { + arr[i] = arr[i] + cur->x; + arr[i + 1] = arr[i + 1] + cur->y; + } + break; + } + case 'h': { + arr[0] = arr[0] + cur->x; + break; + } + case 'v': { + arr[0] = arr[0] + cur->y; + break; + } + case 'a': { + arr[5] = arr[5] + cur->x; + arr[6] = arr[6] + cur->y; + break; + } + default: { + break; + } + } + + switch (cmd) { + case 'm': + case 'M': { + Point p = {arr[0], arr[1]}; + cmds->push_back(PathCommand::MoveTo); + pts->push_back(p); + *cur = {arr[0] ,arr[1]}; + break; + } + case 'l': + case 'L': { + Point p = {arr[0], arr[1]}; + cmds->push_back(PathCommand::LineTo); + pts->push_back(p); + *cur = {arr[0] ,arr[1]}; + break; + } + case 'c': + case 'C': { + Point p[3]; + cmds->push_back(PathCommand::CubicTo); + p[0] = {arr[0], arr[1]}; + p[1] = {arr[2], arr[3]}; + p[2] = {arr[4], arr[5]}; + pts->push_back(p[0]); + pts->push_back(p[1]); + pts->push_back(p[2]); + *curCtl = p[1]; + *cur = p[2]; + break; + } + case 's': + case 'S': { + Point p[3], ctrl; + if ((cmds->size() > 1) && (cmds->at(cmds->size() - 2) == PathCommand::CubicTo)) { + ctrl.x = 2 * cur->x - curCtl->x; + ctrl.y = 2 * cur->x - curCtl->y; + } else { + ctrl = *cur; + } + cmds->push_back(PathCommand::CubicTo); + p[0] = ctrl; + p[1] = {arr[0], arr[1]}; + p[2] = {arr[2], arr[3]}; + pts->push_back(p[0]); + pts->push_back(p[1]); + pts->push_back(p[2]); + *curCtl = p[1]; + *cur = p[2]; + break; + } + case 'q': + case 'Q': { + //TODO: Implement quadratic_to + break; + } + case 't': + case 'T': { + Point p = {arr[0], arr[1]}; + cmds->push_back(PathCommand::MoveTo); + pts->push_back(p); + *cur = {arr[0] ,arr[1]}; + break; + } + case 'h': + case 'H': { + Point p = {arr[0], cur->y}; + cmds->push_back(PathCommand::LineTo); + pts->push_back(p); + cur->x = arr[0]; + break; + } + case 'v': + case 'V': { + Point p = {cur->x, arr[0]}; + cmds->push_back(PathCommand::LineTo); + pts->push_back(p); + cur->y = arr[0]; + break; + } + case 'z': + case 'Z': { + cmds->push_back(PathCommand::Close); + break; + } + case 'a': + case 'A': { + //TODO: Implement arc_to + break; + } + case 'E': + case 'e': { + //TODO: Implement arc + break; + } + default: { + break; + } + } +} + + +static char* _nextCommand(char* path, char* cmd, float* arr, int* count) +{ + int i = 0, large, sweep; + + path = _skipComma(path); + if (isalpha(*path)) { + *cmd = *path; + path++; + *count = _numberCount(*cmd); + } else { + if (*cmd == 'm') *cmd = 'l'; + else if (*cmd == 'M') *cmd = 'L'; + } + if (*count == 7) { + //Special case for arc command + if (_parseNumber(&path, &arr[0])) { + if (_parseNumber(&path, &arr[1])) { + if (_parseNumber(&path, &arr[2])) { + if (_parseLong(&path, &large)) { + if (_parseLong(&path, &sweep)) { + if (_parseNumber(&path, &arr[5])) { + if (_parseNumber(&path, &arr[6])) { + arr[3] = large; + arr[4] = sweep; + return path; + } + } + } + } + } + } + } + *count = 0; + return NULL; + } + for (i = 0; i < *count; i++) { + if (!_parseNumber(&path, &arr[i])) { + *count = 0; + return NULL; + } + path = _skipComma(path); + } + return path; +} + + +tuple, vector> svgPathToTvgPath(const char* svgPath) +{ + vector cmds; + vector pts; + + float numberArray[7]; + int numberCount = 0; + Point cur = { 0, 0 }; + Point curCtl = { 0, 0 }; + char cmd = 0; + char* path = (char*)svgPath; + char* curLocale; + + curLocale = setlocale(LC_NUMERIC, NULL); + if (curLocale) curLocale = strdup(curLocale); + setlocale(LC_NUMERIC, "POSIX"); + + while ((path[0] != '\0')) { + path = _nextCommand(path, &cmd, numberArray, &numberCount); + if (!path) break; + _processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl); + } + + setlocale(LC_NUMERIC, curLocale); + if (curLocale) free(curLocale); + + return make_tuple(cmds, pts); +} + +#endif //__TVG_SVG_PATH_CPP_ diff --git a/src/loaders/svg_loader/tvgSvgPath.h b/src/loaders/svg_loader/tvgSvgPath.h new file mode 100644 index 0000000..47a35d8 --- /dev/null +++ b/src/loaders/svg_loader/tvgSvgPath.h @@ -0,0 +1,8 @@ +#ifndef _TVG_SVG_PATH_H_ +#define _TVG_SVG_PATH_H_ + +#include "tvgCommon.h" + +tuple, vector> svgPathToTvgPath(const char* svg_path_data); + +#endif //_TVG_SVG_PATH_H_ diff --git a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp index 601ed0c..b3fe81d 100644 --- a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp @@ -93,7 +93,10 @@ unique_ptr _shapeBuildHelper(SvgNode* node) auto shape = tvg::Shape::gen(); switch (node->type) { case SvgNodeType::Path: { - //TODO: Support path + if (node->node.path.path) { + auto pathResult = svgPathToTvgPath(node->node.path.path->c_str()); + shape->appendPath(get<0>(pathResult).data(), get<0>(pathResult).size(), get<1>(pathResult).data(), get<1>(pathResult).size()); + } break; } case SvgNodeType::Ellipse: { diff --git a/src/loaders/svg_loader/tvgSvgSceneBuilder.h b/src/loaders/svg_loader/tvgSvgSceneBuilder.h index 20a41a7..1bd779b 100644 --- a/src/loaders/svg_loader/tvgSvgSceneBuilder.h +++ b/src/loaders/svg_loader/tvgSvgSceneBuilder.h @@ -18,6 +18,7 @@ #define _TVG_SVG_SCENE_BUILDER_H_ #include "tvgSvgLoaderCommon.h" +#include "tvgSvgPath.h" class SvgSceneBuilder { -- 2.7.4 From 0a562a4ae26e5f6c3d6dffc4d45982b7dc1e625b Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 29 Jun 2020 16:26:02 +0900 Subject: [PATCH 03/16] test: print current backend engine name Change-Id: Iaafa521556a614b47994914c09228b8e8ae9c9e9 --- test/testShape.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/testShape.cpp b/test/testShape.cpp index e32142f..cd1bab1 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -1,4 +1,5 @@ #include +#include #include using namespace std; @@ -107,6 +108,9 @@ int main(int argc, char **argv) if (!strcmp(argv[1], "gl")) swEngine = false; } + if (swEngine) cout << "engine: software" << endl; + else cout << "engine: opengl" << endl; + elm_init(argc, argv); //Show the result using EFL... -- 2.7.4 From be6615d93e0488f239edf62b61dd6ed33a9a36c5 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Mon, 29 Jun 2020 16:35:21 +0900 Subject: [PATCH 04/16] SvgLoader: Supports Path's quadratic_to draw Convert quadratic bezier to cubic Change-Id: I885138dcdfb9f0e85bf3ca1ca5c9fc4eb0d8f1f8 --- src/loaders/svg_loader/tvgSvgPath.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/loaders/svg_loader/tvgSvgPath.cpp b/src/loaders/svg_loader/tvgSvgPath.cpp index 70058e0..c3d3cac 100644 --- a/src/loaders/svg_loader/tvgSvgPath.cpp +++ b/src/loaders/svg_loader/tvgSvgPath.cpp @@ -170,7 +170,20 @@ static void _processCommand(vector* cmds, vector* pts, char } case 'q': case 'Q': { - //TODO: Implement quadratic_to + tvg::Point p[3]; + float ctrl_x0 = (cur->x + 2 * arr[0]) * (1.0 / 3.0); + float ctrl_y0 = (cur->y + 2 * arr[1]) * (1.0 / 3.0); + float ctrl_x1 = (arr[2] + 2 * arr[0]) * (1.0 / 3.0); + float ctrl_y1 = (arr[3] + 2 * arr[1]) * (1.0 / 3.0); + cmds->push_back(tvg::PathCommand::CubicTo); + p[0] = {ctrl_x0, ctrl_y0}; + p[1] = {ctrl_x1, ctrl_y1}; + p[2] = {arr[2], arr[3]}; + pts->push_back(p[0]); + pts->push_back(p[1]); + pts->push_back(p[2]); + *curCtl = p[1]; + *cur = p[2]; break; } case 't': -- 2.7.4 From 9ba6bd654e310f5c3896a8043df1fcb3fbb753f9 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Mon, 29 Jun 2020 19:24:54 +0900 Subject: [PATCH 05/16] SvgLoader: Fix typo rect types w, h -> width, height Change-Id: I5e85360644d9b8c2b2d84f182a0de16fefe9edbf --- src/loaders/svg_loader/tvgSvgLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index 4dd5fd4..99bb689 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -1218,8 +1218,8 @@ static constexpr struct } rectTags[] = { RECT_DEF(x, x, SvgParserLengthType::Horizontal), RECT_DEF(y, y, SvgParserLengthType::Vertical), - RECT_DEF(w, w, SvgParserLengthType::Horizontal), - RECT_DEF(h, h, SvgParserLengthType::Vertical), + RECT_DEF(width, w, SvgParserLengthType::Horizontal), + RECT_DEF(height, h, SvgParserLengthType::Vertical), RECT_DEF(rx, rx, SvgParserLengthType::Horizontal), RECT_DEF(ry, ry, SvgParserLengthType::Vertical) }; -- 2.7.4 From 654299d0ab6b3eeb0a5c21aafba036b93f1e995e Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Mon, 29 Jun 2020 19:30:29 +0900 Subject: [PATCH 06/16] test: Improve svg test Displays svg files located in "./svgs" dir. Change-Id: I4b9a281dc31fefb28c969780fa28adb74a5f5c02 --- test/svgs/bojo.svg | 15 ++++++++++++++ test/svgs/bzrfeed.svg | 23 +++++++++++++++++++++ test/svgs/cartman.svg | 11 ++++++++++ test/svgs/dst.svg | 15 ++++++++++++++ test/svgs/shape.svg | 18 ++++++++++++++++ test/testSvg.cpp | 57 +++++++++++++++++++++++++++++++++++---------------- 6 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 test/svgs/bojo.svg create mode 100644 test/svgs/bzrfeed.svg create mode 100644 test/svgs/cartman.svg create mode 100644 test/svgs/dst.svg create mode 100644 test/svgs/shape.svg diff --git a/test/svgs/bojo.svg b/test/svgs/bojo.svg new file mode 100644 index 0000000..fe62615 --- /dev/null +++ b/test/svgs/bojo.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/test/svgs/bzrfeed.svg b/test/svgs/bzrfeed.svg new file mode 100644 index 0000000..e5d210f --- /dev/null +++ b/test/svgs/bzrfeed.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/svgs/cartman.svg b/test/svgs/cartman.svg new file mode 100644 index 0000000..d4b2740 --- /dev/null +++ b/test/svgs/cartman.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/svgs/dst.svg b/test/svgs/dst.svg new file mode 100644 index 0000000..bce75d8 --- /dev/null +++ b/test/svgs/dst.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/test/svgs/shape.svg b/test/svgs/shape.svg new file mode 100644 index 0000000..a0b3677 --- /dev/null +++ b/test/svgs/shape.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/test/testSvg.cpp b/test/testSvg.cpp index b7671b8..1ae4fe0 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -8,36 +8,54 @@ using namespace std; static uint32_t buffer[WIDTH * HEIGHT]; -void tvgtest() -{ - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); +unique_ptr canvas = nullptr; +int count = 0; +static const int numberPerLine = 3; + +static int x = 30; +static int y = 30; - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - // Create a SVG scene, request the original size, +void svgDirCallback(const char* name, const char* path, void* data) +{ auto scene = tvg::Scene::gen(); - scene->load("sample.svg"); + char buf[255]; + sprintf(buf,"%s/%s", path, name); + scene->load(buf); + printf("SVG Load : %s\n", buf); + scene->translate(((WIDTH - (x * 2)) / numberPerLine) * (count % numberPerLine) + x, ((HEIGHT - (y * 2))/ numberPerLine) * (int)((float)count / (float)numberPerLine) + y); canvas->push(move(scene)); - - canvas->draw(); - canvas->sync(); - - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); + count++; } -void win_del(void *data, Evas_Object *o, void *ev) + +void win_del(void* data, Evas_Object* o, void* ev) { elm_exit(); } -int main(int argc, char **argv) +int main(int argc, char** argv) { - tvgtest(); + //Initialize ThorVG Engine + tvg::Initializer::init(tvg::CanvasEngine::Sw); + + //Create a Canvas + canvas = tvg::SwCanvas::gen(); + canvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + //Draw white background + auto scene = tvg::Scene::gen(); + auto shape1 = tvg::Shape::gen(); + shape1->appendRect(0, 0, WIDTH, HEIGHT, 0); + shape1->fill(255, 255, 255, 255); + scene->push(move(shape1)); + canvas->push(move(scene)); + + eina_file_dir_list("./svgs", EINA_TRUE, svgDirCallback, NULL); + + canvas->draw(); + canvas->sync(); //Show the result using EFL... elm_init(argc, argv); @@ -57,4 +75,7 @@ int main(int argc, char **argv) elm_run(); elm_shutdown(); + + //Terminate ThorVG Engine + tvg::Initializer::term(tvg::CanvasEngine::Sw); } -- 2.7.4 From 918b6c69d837bb6c181aa62d4e325bfe32454837 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 29 Jun 2020 17:35:04 +0900 Subject: [PATCH 07/16] test: unify test code for supporting gl engine from all test cases. now you can launch tests with gl engine by "gl" option ex) $ testTransform gl $ testScene gl Change-Id: Idb720ed369a2fbfb908c977fdaebd7289986fb6f --- test/testAsync.cpp | 142 ++++++++++++++++++++++++++------------ test/testBlending.cpp | 130 +++++++++++++++++++++++++---------- test/testBoundary.cpp | 129 +++++++++++++++++++++++++---------- test/testCommon.h | 70 +++++++++++++++++++ test/testComposition.cpp | 35 ---------- test/testCustomTransform.cpp | 147 ++++++++++++++++++++++++++++----------- test/testDirectUpdate.cpp | 148 ++++++++++++++++++++++++++++------------ test/testGradient.cpp | 52 -------------- test/testGradientTransform.cpp | 147 ++++++++++++++++++++++++++++----------- test/testLinearGradient.cpp | 130 +++++++++++++++++++++++++---------- test/testMultiShapes.cpp | 130 +++++++++++++++++++++++++---------- test/testPath.cpp | 129 +++++++++++++++++++++++++---------- test/testPathCopy.cpp | 129 +++++++++++++++++++++++++---------- test/testRadialGradient.cpp | 130 +++++++++++++++++++++++++---------- test/testScene.cpp | 130 +++++++++++++++++++++++++---------- test/testSceneTransform.cpp | 147 ++++++++++++++++++++++++++++----------- test/testShape.cpp | 117 ++++++++++++------------------- test/testStroke.cpp | 130 +++++++++++++++++++++++++---------- test/testStrokeLine.cpp | 131 +++++++++++++++++++++++++---------- test/testSvg.cpp | 151 +++++++++++++++++++++++++++++------------ test/testTransform.cpp | 147 ++++++++++++++++++++++++++++----------- test/testUpdate.cpp | 147 ++++++++++++++++++++++++++++----------- 22 files changed, 1893 insertions(+), 855 deletions(-) create mode 100644 test/testCommon.h delete mode 100644 test/testComposition.cpp delete mode 100644 test/testGradient.cpp diff --git a/test/testAsync.cpp b/test/testAsync.cpp index 7172dd9..a8ac2b0 100644 --- a/test/testAsync.cpp +++ b/test/testAsync.cpp @@ -1,25 +1,14 @@ -#include -#include +#include "testCommon.h" -using namespace std; - -#define WIDTH 1920 -#define HEIGHT 1080 +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ #define COUNT 50 -static uint32_t buffer[WIDTH * HEIGHT]; -unique_ptr canvas = nullptr; static double t1, t2, t3, t4; static unsigned cnt = 0; -void tvgtest() -{ - //Create a Canvas - canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); -} - -Eina_Bool anim_cb(void *data) +bool tvgUpdateCmds(tvg::Canvas* canvas) { auto t = ecore_time_get(); @@ -27,7 +16,7 @@ Eina_Bool anim_cb(void *data) if (canvas->clear() != tvg::Result::Success) { //Logically wrong! Probably, you missed to call sync() before. - return ECORE_CALLBACK_RENEW; + return false; } t1 = t; @@ -38,8 +27,8 @@ Eina_Bool anim_cb(void *data) float x = rand() % (WIDTH/2); float y = rand() % (HEIGHT/2); - float w = 1 + rand() % 1200; - float h = 1 + rand() % 800; + float w = 1 + rand() % (int)(WIDTH * 1.3 / 2); + float h = 1 + rand() % (int)(HEIGHT * 1.3 / 2); shape->appendRect(x, y, w, h, rand() % 400); @@ -61,8 +50,29 @@ Eina_Bool anim_cb(void *data) t3 = ecore_time_get(); + return true; +} + + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); +} + +Eina_Bool animSwCb(void* data) +{ + if (!tvgUpdateCmds(swCanvas.get())) return ECORE_CALLBACK_RENEW; + //Drawing task can be performed asynchronously. - canvas->draw(); + swCanvas->draw(); //Update Efl Canvas Eo* img = (Eo*) data; @@ -72,50 +82,96 @@ Eina_Bool anim_cb(void *data) return ECORE_CALLBACK_RENEW; } -void render_cb(void* data, Eo* obj) +void drawSwView(void* data, Eo* obj) { //Make it guarantee finishing drawing task. - canvas->sync(); + swCanvas->sync(); t4 = ecore_time_get(); printf("[%5d]: total[%fms] = clear[%fms], update[%fms], render[%fms]\n", ++cnt, t4 - t1, t2 - t1, t3 - t2, t4 - t3); } -void win_del(void *data, Evas_Object *o, void *ev) + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); +} + +void drawGLview(Evas_Object *obj) { - elm_exit(); + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->sync(); } +Eina_Bool animGlCb(void* data) +{ + if (!tvgUpdateCmds(glCanvas.get())) return ECORE_CALLBACK_RENEW; + + //Drawing task can be performed asynchronously. + glCanvas->draw(); + + return ECORE_CALLBACK_RENEW; +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - tvgtest(); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - //Show the result using EFL... - elm_init(argc, argv); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_image_pixels_get_callback_set(img, render_cb, nullptr); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_init(argc, argv); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + elm_config_accel_preference_set("gl"); - ecore_animator_add(anim_cb, img); + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + evas_object_image_pixels_get_callback_set(view, drawSwView, nullptr); + ecore_animator_add(animSwCb, view); + } else { + auto view = createGlView(); + ecore_animator_add(animGlCb, view); + } elm_run(); elm_shutdown(); //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); -} + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testBlending.cpp b/test/testBlending.cpp index 82aa32d..7794689 100644 --- a/test/testBlending.cpp +++ b/test/testBlending.cpp @@ -1,21 +1,11 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); canvas->reserve(5); //Prepare Round Rectangle @@ -57,40 +47,108 @@ void tvgtest() shape5->appendCircle(600, 650, 200, 150); shape5->fill(0, 0, 255, 255); canvas->push(move(shape5)); +} - //Draw the Shapes onto the Canvas - canvas->draw(); - canvas->sync(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); } -void win_del(void *data, Evas_Object *o, void *ev) +void drawSwView(void* data, Eo* obj) { - elm_exit(); + swCanvas->draw(); + swCanvas->sync(); } + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - tvgtest(); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - //Show the result using EFL... - elm_init(argc, argv); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); + + elm_init(argc, argv); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_config_accel_preference_set("gl"); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testBoundary.cpp b/test/testBoundary.cpp index d7cb8fa..e74ac5e 100644 --- a/test/testBoundary.cpp +++ b/test/testBoundary.cpp @@ -1,21 +1,11 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); canvas->reserve(5); //reserve 5 shape nodes (optional) //Prepare Shape1 @@ -47,40 +37,107 @@ void tvgtest() shape5->appendCircle(200, 650, 250, 200); shape5->fill(0, 0, 0, 255); canvas->push(move(shape5)); +} - //Draw the Shapes onto the Canvas - canvas->draw(); - canvas->sync(); +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); } -void win_del(void *data, Evas_Object *o, void *ev) +void drawGLview(Evas_Object *obj) { - elm_exit(); + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); } + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - tvgtest(); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - //Show the result using EFL... - elm_init(argc, argv); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); + + elm_init(argc, argv); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_config_accel_preference_set("gl"); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testCommon.h b/test/testCommon.h new file mode 100644 index 0000000..c47723a --- /dev/null +++ b/test/testCommon.h @@ -0,0 +1,70 @@ +#include +#include +#include + +using namespace std; + +#define WIDTH 800 +#define HEIGHT 800 + +/************************************************************************/ +/* Common Infrastructure Code */ +/************************************************************************/ + +void tvgSwTest(uint32_t* buffer); + +void win_del(void *data, Evas_Object *o, void *ev) +{ + elm_exit(); +} + +void drawSwView(void* data, Eo* obj); + +static Eo* createSwView() +{ + static uint32_t buffer[WIDTH * HEIGHT]; + + Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); + evas_object_smart_callback_add(win, "delete,request", win_del, 0); + + Eo* view = evas_object_image_filled_add(evas_object_evas_get(win)); + evas_object_image_size_set(view, WIDTH, HEIGHT); + evas_object_image_data_set(view, buffer); + evas_object_image_pixels_get_callback_set(view, drawSwView, nullptr); + evas_object_image_pixels_dirty_set(view, EINA_TRUE); + evas_object_image_data_update_add(view, 0, 0, WIDTH, HEIGHT); + evas_object_size_hint_weight_set(view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(view); + + elm_win_resize_object_add(win, view); + evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); + evas_object_show(win); + + tvgSwTest(buffer); + + return view; +} + +void initGLview(Evas_Object *obj); +void drawGLview(Evas_Object *obj); + +static Eo* createGlView() +{ + Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); + evas_object_smart_callback_add(win, "delete,request", win_del, 0); + + Eo* view = elm_glview_add(win); + evas_object_size_hint_weight_set(view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_glview_mode_set(view, ELM_GLVIEW_ALPHA); + elm_glview_resize_policy_set(view, ELM_GLVIEW_RESIZE_POLICY_RECREATE); + elm_glview_render_policy_set(view, ELM_GLVIEW_RENDER_POLICY_ON_DEMAND); + elm_glview_init_func_set(view, initGLview); + elm_glview_render_func_set(view, drawGLview); + evas_object_show(view); + + elm_win_resize_object_add(win, view); + evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); + evas_object_show(win); + + return view; +} diff --git a/test/testComposition.cpp b/test/testComposition.cpp deleted file mode 100644 index 6230dc0..0000000 --- a/test/testComposition.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include - -using namespace std; - -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -int main(int argc, char **argv) -{ - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Composition Source Canvas - auto canvas1 = tvg::SwCanvas::gen(buffer, WIDTH, HEIGHT); - - //Draw something onto the Canvas and leaving sync to the target. - canvas1->draw(); - - //Create a Main Canvas - auto canvas2 = tvg::SwCanvas::gen(buffer, WIDTH, HEIGHT); - - //Create a Shape - auto shape = tvg::Shape::gen(); - shape->composite(canvas, tvg::CompMaskAdd); - - //Draw the Scene onto the Canvas - canvas2->push(move(shape)); - canvas2->draw(); - canvas2->sync(); - - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); -} diff --git a/test/testCustomTransform.cpp b/test/testCustomTransform.cpp index c57d4d4..1109a21 100644 --- a/test/testCustomTransform.cpp +++ b/test/testCustomTransform.cpp @@ -1,21 +1,12 @@ -#include -#include +#include "testCommon.h" -using namespace std; - -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; -unique_ptr canvas = nullptr; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ tvg::Shape* pShape = nullptr; -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Create a Canvas - canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - //Shape1 auto shape = tvg::Shape::gen(); @@ -36,13 +27,9 @@ void tvgtest() shape->close(); shape->fill(0, 0, 255, 255); canvas->push(move(shape)); - - //Draw first frame - canvas->draw(); - canvas->sync(); } -void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +void tvgUpdateCmds(tvg::Canvas* canvas, float progress) { /* Update shape directly. You can update only necessary properties of this shape, @@ -86,46 +73,124 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres //Update shape for drawing (this may work asynchronously) canvas->update(pShape); +} + + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; - //Draw Next frames - canvas->draw(); - canvas->sync(); +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +{ + tvgUpdateCmds(swCanvas.get(), progress); //Update Efl Canvas Eo* img = (Eo*) effect; evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT); + evas_object_image_pixels_dirty_set(img, EINA_TRUE); +} + +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); } -void win_del(void *data, Evas_Object *o, void *ev) +void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) { - elm_exit(); + tvgUpdateCmds(glCanvas.get(), progress); } + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; + + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } - tvgtest(); + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); - //Show the result using EFL... elm_init(argc, argv); - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + elm_config_accel_preference_set("gl"); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + Elm_Transit *transit = elm_transit_add(); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - Elm_Transit *transit = elm_transit_add(); - elm_transit_effect_add(transit, transit_cb, img, nullptr); elm_transit_duration_set(transit, 2); elm_transit_repeat_times_set(transit, -1); elm_transit_auto_reverse_set(transit, EINA_TRUE); @@ -135,5 +200,5 @@ int main(int argc, char **argv) elm_shutdown(); //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); -} + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testDirectUpdate.cpp b/test/testDirectUpdate.cpp index 4dbc26b..93b2dfb 100644 --- a/test/testDirectUpdate.cpp +++ b/test/testDirectUpdate.cpp @@ -1,21 +1,12 @@ -#include -#include +#include "testCommon.h" -using namespace std; - -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; -unique_ptr canvas = nullptr; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ tvg::Shape* pShape = nullptr; -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Create a Canvas - canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - //Shape auto shape = tvg::Shape::gen(); @@ -31,13 +22,9 @@ void tvgtest() shape->stroke(1); canvas->push(move(shape)); - - //Draw first frame - canvas->draw(); - canvas->sync(); } -void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +void tvgUpdateCmds(tvg::Canvas* canvas, float progress) { /* Update shape directly. You can update only necessary properties of this shape, @@ -50,47 +37,124 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres //Update shape for drawing (this may work asynchronously) canvas->update(pShape); +} + + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; - //Draw Next frames - canvas->draw(); - canvas->sync(); +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +{ + tvgUpdateCmds(swCanvas.get(), progress); //Update Efl Canvas Eo* img = (Eo*) effect; evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT); + evas_object_image_pixels_dirty_set(img, EINA_TRUE); +} + +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); } -void -win_del(void *data, Evas_Object *o, void *ev) +void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) { - elm_exit(); + tvgUpdateCmds(glCanvas.get(), progress); } + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; + + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } - tvgtest(); + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); - //Show the result using EFL... elm_init(argc, argv); - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + elm_config_accel_preference_set("gl"); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + Elm_Transit *transit = elm_transit_add(); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - Elm_Transit *transit = elm_transit_add(); - elm_transit_effect_add(transit, transit_cb, img, nullptr); elm_transit_duration_set(transit, 2); elm_transit_repeat_times_set(transit, -1); elm_transit_auto_reverse_set(transit, EINA_TRUE); @@ -100,5 +164,5 @@ int main(int argc, char **argv) elm_shutdown(); //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); -} + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testGradient.cpp b/test/testGradient.cpp deleted file mode 100644 index d20cce9..0000000 --- a/test/testGradient.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include - -using namespace std; - -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -int main(int argc, char **argv) -{ - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(buffer, WIDTH, HEIGHT); - - //Prepare a Shape - auto shape1 = tvg::Shape::gen(); - shape1->rect(0, 0, 400, 400, 0.1); //x, y, w, h, corner_radius - - //Linear Gradient Fill - auto fill1 = tvg::LinearFill::gen(); - fill1->range(fill1, 0, 0, 400, 400); //from(x, y), to(x, y) - fill1->color(0, 255, 0, 0, 255); //color Stop 0: Red - fill1->color(0.5, 0, 255, 0, 255); //color Stop 1: Green - fill1->color(1, 0, 0, 255, 255); //color Stop 2: Blue - shape1.fill(fill1); - - canvas->push(move(shape1)); - - //Prepare Circle - auto shape2 = tvg::Shape::gen(); - shape2->circle(400, 400, 200); //cx, cy, radius - - //Radial Gradient Fill - auto fill2 = tvg::RadialFill::gen(); - fill2->range(400, 400, 200); //center(x, y), radius - fill2->color(0, 255, 0, 0, 255); //color Stop 0: Red - fill2->color(0.5, 0, 255, 0, 255); //color Stop 1: Green - fill2->color(1, 0, 0, 255, 255); //color Stop 2: Blue - shape2.fill(fill2); - - canvas->push(move(shape2)); - - //Draw the Shapes onto the Canvas - canvas->draw(); - canvas->sync(); - - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); -} diff --git a/test/testGradientTransform.cpp b/test/testGradientTransform.cpp index 1b5137b..b77062b 100644 --- a/test/testGradientTransform.cpp +++ b/test/testGradientTransform.cpp @@ -1,23 +1,14 @@ -#include -#include +#include "testCommon.h" -using namespace std; - -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; -unique_ptr canvas = nullptr; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ tvg::Shape* pShape = nullptr; tvg::Shape* pShape2 = nullptr; tvg::Shape* pShape3 = nullptr; -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Create a Canvas - canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - //Shape1 auto shape = tvg::Shape::gen(); @@ -88,13 +79,9 @@ void tvgtest() shape3->fill(move(fill3)); shape3->translate(400, 400); canvas->push(move(shape3)); - - //Draw first frame - canvas->draw(); - canvas->sync(); } -void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +void tvgUpdateCmds(tvg::Canvas* canvas, float progress) { /* Update shape directly. You can update only necessary properties of this shape, @@ -116,46 +103,124 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres pShape3->rotate(-360 * progress); pShape3->scale(0.5 + progress); canvas->update(pShape3); +} + + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; - //Draw Next frames - canvas->draw(); - canvas->sync(); +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +{ + tvgUpdateCmds(swCanvas.get(), progress); //Update Efl Canvas Eo* img = (Eo*) effect; evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT); + evas_object_image_pixels_dirty_set(img, EINA_TRUE); +} + +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); } -void win_del(void *data, Evas_Object *o, void *ev) +void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) { - elm_exit(); + tvgUpdateCmds(glCanvas.get(), progress); } + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; + + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } - tvgtest(); + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); - //Show the result using EFL... elm_init(argc, argv); - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + elm_config_accel_preference_set("gl"); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + Elm_Transit *transit = elm_transit_add(); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - Elm_Transit *transit = elm_transit_add(); - elm_transit_effect_add(transit, transit_cb, img, nullptr); elm_transit_duration_set(transit, 2); elm_transit_repeat_times_set(transit, -1); elm_transit_auto_reverse_set(transit, EINA_TRUE); @@ -165,5 +230,5 @@ int main(int argc, char **argv) elm_shutdown(); //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); -} + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testLinearGradient.cpp b/test/testLinearGradient.cpp index ed0d31d..36251f5 100644 --- a/test/testLinearGradient.cpp +++ b/test/testLinearGradient.cpp @@ -1,21 +1,11 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); canvas->reserve(3); //reserve 3 shape nodes (optional) //Prepare Round Rectangle @@ -75,40 +65,108 @@ void tvgtest() shape3->fill(move(fill3)); canvas->push(move(shape3)); +} - //Draw the Shapes onto the Canvas - canvas->draw(); - canvas->sync(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); } -void win_del(void *data, Evas_Object *o, void *ev) +void drawSwView(void* data, Eo* obj) { - elm_exit(); + swCanvas->draw(); + swCanvas->sync(); } + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - tvgtest(); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - //Show the result using EFL... - elm_init(argc, argv); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); + + elm_init(argc, argv); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_config_accel_preference_set("gl"); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testMultiShapes.cpp b/test/testMultiShapes.cpp index 02101ed..195547d 100644 --- a/test/testMultiShapes.cpp +++ b/test/testMultiShapes.cpp @@ -1,21 +1,11 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); canvas->reserve(3); //reserve 3 shape nodes (optional) //Prepare Round Rectangle @@ -35,40 +25,108 @@ void tvgtest() shape3->appendCircle(600, 600, 150, 100); //cx, cy, radiusW, radiusH shape3->fill(0, 255, 255, 255); //r, g, b, a canvas->push(move(shape3)); +} - //Draw the Shapes onto the Canvas - canvas->draw(); - canvas->sync(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); } -void win_del(void *data, Evas_Object *o, void *ev) +void drawSwView(void* data, Eo* obj) { - elm_exit(); + swCanvas->draw(); + swCanvas->sync(); } + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - tvgtest(); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - //Show the result using EFL... - elm_init(argc, argv); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); + + elm_init(argc, argv); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_config_accel_preference_set("gl"); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testPath.cpp b/test/testPath.cpp index a5bdc9e..49bd738 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -1,22 +1,11 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - //Star auto shape1 = tvg::Shape::gen(); @@ -51,39 +40,107 @@ void tvgtest() shape2->cubicTo(cx - radius, cy - halfRadius, cx - halfRadius, cy - radius, cx, cy - radius); shape2->fill(255, 0, 0, 255); canvas->push(move(shape2)); +} - canvas->draw(); - canvas->sync(); +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); } -void win_del(void *data, Evas_Object *o, void *ev) +void drawSwView(void* data, Eo* obj) { - elm_exit(); + swCanvas->draw(); + swCanvas->sync(); } + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - tvgtest(); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - //Show the result using EFL... - elm_init(argc, argv); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); + + elm_init(argc, argv); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_config_accel_preference_set("gl"); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testPathCopy.cpp b/test/testPathCopy.cpp index fc3395e..b619f78 100644 --- a/test/testPathCopy.cpp +++ b/test/testPathCopy.cpp @@ -1,22 +1,11 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - /* Star */ //Prepare Path Commands @@ -91,39 +80,107 @@ void tvgtest() shape2->appendPath(cmds2, 6, pts2, 13); //copy path data shape2->fill(255, 255, 0, 255); canvas->push(move(shape2)); +} - canvas->draw(); - canvas->sync(); +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); } -void win_del(void *data, Evas_Object *o, void *ev) +void drawSwView(void* data, Eo* obj) { - elm_exit(); + swCanvas->draw(); + swCanvas->sync(); } + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - tvgtest(); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - //Show the result using EFL... - elm_init(argc, argv); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); + + elm_init(argc, argv); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_config_accel_preference_set("gl"); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testRadialGradient.cpp b/test/testRadialGradient.cpp index 841c6e1..f12777c 100644 --- a/test/testRadialGradient.cpp +++ b/test/testRadialGradient.cpp @@ -1,21 +1,11 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); canvas->reserve(3); //reserve 3 shape nodes (optional) //Prepare Round Rectangle @@ -75,40 +65,108 @@ void tvgtest() shape3->fill(move(fill3)); canvas->push(move(shape3)); +} - //Draw the Shapes onto the Canvas - canvas->draw(); - canvas->sync(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); } -void win_del(void *data, Evas_Object *o, void *ev) +void drawSwView(void* data, Eo* obj) { - elm_exit(); + swCanvas->draw(); + swCanvas->sync(); } + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - tvgtest(); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - //Show the result using EFL... - elm_init(argc, argv); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); + + elm_init(argc, argv); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_config_accel_preference_set("gl"); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testScene.cpp b/test/testScene.cpp index c5672c7..e16772a 100644 --- a/test/testScene.cpp +++ b/test/testScene.cpp @@ -1,22 +1,11 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - //Create a Scene auto scene = tvg::Scene::gen(); scene->reserve(3); //reserve 3 shape nodes (optional) @@ -83,39 +72,108 @@ void tvgtest() //Draw the Scene onto the Canvas canvas->push(move(scene)); - canvas->draw(); - canvas->sync(); +} - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); } -void win_del(void *data, Evas_Object *o, void *ev) +void drawGLview(Evas_Object *obj) { - elm_exit(); + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); } +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - tvgtest(); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - //Show the result using EFL... - elm_init(argc, argv); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); + + elm_init(argc, argv); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_config_accel_preference_set("gl"); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index 07879c1..7bd8b41 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -1,22 +1,13 @@ -#include -#include +#include "testCommon.h" -using namespace std; - -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; -unique_ptr canvas = nullptr; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ tvg::Scene* pScene1 = nullptr; tvg::Scene* pScene2 = nullptr; -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Create a Canvas - canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - //Create a Scene1 auto scene = tvg::Scene::gen(); pScene1 = scene.get(); @@ -94,12 +85,9 @@ void tvgtest() //Draw the Scene onto the Canvas canvas->push(move(scene)); - - canvas->draw(); - canvas->sync(); } -void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +void tvgUpdateCmds(tvg::Canvas* canvas, float progress) { /* Update scene directly. You can update only necessary properties of this scene, @@ -110,53 +98,132 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres //Update shape for drawing (this may work asynchronously) canvas->update(pScene1); +} + + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; - //Draw Next frames - canvas->draw(); - canvas->sync(); +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +{ + tvgUpdateCmds(swCanvas.get(), progress); //Update Efl Canvas Eo* img = (Eo*) effect; evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT); + evas_object_image_pixels_dirty_set(img, EINA_TRUE); +} + +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); } -void win_del(void *data, Evas_Object *o, void *ev) +void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) { - elm_exit(); + tvgUpdateCmds(glCanvas.get(), progress); } + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; + + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } - tvgtest(); + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); - //Show the result using EFL... elm_init(argc, argv); - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + elm_config_accel_preference_set("gl"); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + Elm_Transit *transit = elm_transit_add(); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - Elm_Transit *transit = elm_transit_add(); - elm_transit_effect_add(transit, transit_cb, img, nullptr); elm_transit_duration_set(transit, 2); elm_transit_repeat_times_set(transit, -1); + elm_transit_auto_reverse_set(transit, EINA_TRUE); elm_transit_go(transit); elm_run(); elm_shutdown(); //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); -} + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testShape.cpp b/test/testShape.cpp index cd1bab1..9aa284d 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -1,13 +1,10 @@ -#include -#include -#include +#include "testCommon.h" -using namespace std; - -#define WIDTH 800 -#define HEIGHT 800 +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -unique_ptr tvgDrawCmds() +void tvgDrawCmds(tvg::Canvas* canvas) { //Prepare a Shape (Rectangle + Rectangle + Circle + Circle) auto shape1 = tvg::Shape::gen(); @@ -17,62 +14,55 @@ unique_ptr tvgDrawCmds() shape1->appendCircle(400, 500, 170, 100); //cx, cy, radiusW, radiusH shape1->fill(255, 255, 0, 255); //r, g, b, a - return move(shape1); + canvas->push(move(shape1)); } + /************************************************************************/ /* Sw Engine Test Code */ /************************************************************************/ +static unique_ptr swCanvas; + void tvgSwTest(uint32_t* buffer) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare internal data asynchronously for coming rendering. Canvas keeps this shape node unless user call canvas->clear() */ - canvas->push(tvgDrawCmds()); - canvas->draw(); - canvas->sync(); + tvgDrawCmds(swCanvas.get()); +} - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); } + /************************************************************************/ /* GL Engine Test Code */ /************************************************************************/ -static unique_ptr canvas; +static unique_ptr glCanvas; void initGLview(Evas_Object *obj) { static constexpr auto BPP = 4; - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Gl); - //Create a Canvas - canvas = tvg::GlCanvas::gen(); - canvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare internal data asynchronously for coming rendering. Canvas keeps this shape node unless user call canvas->clear() */ - canvas->push(tvgDrawCmds()); -} - -void delGLview(Evas_Object *obj) -{ - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Gl); + tvgDrawCmds(glCanvas.get()); } void drawGLview(Evas_Object *obj) @@ -87,65 +77,46 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - canvas->draw(); - canvas->sync(); + glCanvas->draw(); + glCanvas->sync(); } + /************************************************************************/ -/* Common Infrastructure Code */ +/* Main Code */ /************************************************************************/ -void win_del(void *data, Evas_Object *o, void *ev) -{ - elm_exit(); -} - int main(int argc, char **argv) { - bool swEngine = true; + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; if (argc > 1) { - if (!strcmp(argv[1], "gl")) swEngine = false; + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; } - if (swEngine) cout << "engine: software" << endl; - else cout << "engine: opengl" << endl; + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); elm_init(argc, argv); - //Show the result using EFL... elm_config_accel_preference_set("gl"); - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); - - Eo* viewer; - - if (swEngine) { - static uint32_t buffer[WIDTH * HEIGHT]; - viewer = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(viewer, WIDTH, HEIGHT); - evas_object_image_data_set(viewer, buffer); - evas_object_size_hint_weight_set(viewer, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(viewer); - tvgSwTest(buffer); - //GlEngine + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); } else { - viewer = elm_glview_add(win); - evas_object_size_hint_weight_set(viewer, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_glview_mode_set(viewer, ELM_GLVIEW_ALPHA); - elm_glview_resize_policy_set(viewer, ELM_GLVIEW_RESIZE_POLICY_RECREATE); - elm_glview_render_policy_set(viewer, ELM_GLVIEW_RENDER_POLICY_ON_DEMAND); - elm_glview_init_func_set(viewer, initGLview); - elm_glview_del_func_set(viewer, delGLview); - elm_glview_render_func_set(viewer, drawGLview); - evas_object_show(viewer); + createGlView(); } - elm_win_resize_object_add(win, viewer); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); - elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testStroke.cpp b/test/testStroke.cpp index bc50dca..493bbde 100644 --- a/test/testStroke.cpp +++ b/test/testStroke.cpp @@ -1,23 +1,11 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - //Shape 1 auto shape1 = tvg::Shape::gen(); shape1->appendRect(50, 50, 200, 200, 0); @@ -74,40 +62,108 @@ void tvgtest() shape6->stroke(4); canvas->push(move(shape6)); +} - canvas->draw(); - canvas->sync(); +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); } -void win_del(void *data, Evas_Object *o, void *ev) +void drawGLview(Evas_Object *obj) { - elm_exit(); + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); } + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - tvgtest(); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - //Show the result using EFL... - elm_init(argc, argv); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); + + elm_init(argc, argv); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_config_accel_preference_set("gl"); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testStrokeLine.cpp b/test/testStrokeLine.cpp index 559479d..d57bf1f 100644 --- a/test/testStrokeLine.cpp +++ b/test/testStrokeLine.cpp @@ -1,22 +1,11 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); - - //Create a Canvas - auto canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - //Test for Stroke Width for (int i = 0; i < 10; ++i) { auto shape = tvg::Shape::gen(); @@ -28,7 +17,6 @@ void tvgtest() canvas->push(move(shape)); } - //Test for StrokeJoin & StrokeCap auto shape1 = tvg::Shape::gen(); shape1->moveTo(20, 350); @@ -111,39 +99,108 @@ void tvgtest() float dashPattern3[2] = {10, 10}; shape6->stroke(dashPattern3, 2); canvas->push(move(shape6)); +} - canvas->draw(); - canvas->sync(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); } -void win_del(void *data, Evas_Object *o, void *ev) +void drawGLview(Evas_Object *obj) { - elm_exit(); + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); } + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { - tvgtest(); + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - //Show the result using EFL... - elm_init(argc, argv); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + elm_init(argc, argv); + + elm_config_accel_preference_set("gl"); + + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); -} + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testSvg.cpp b/test/testSvg.cpp index 1ae4fe0..938d37a 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -1,77 +1,140 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 +#define NUM_PER_LINE 3 -static uint32_t buffer[WIDTH * HEIGHT]; - -unique_ptr canvas = nullptr; +int x = 30; +int y = 30; int count = 0; -static const int numberPerLine = 3; - -static int x = 30; -static int y = 30; - void svgDirCallback(const char* name, const char* path, void* data) { + tvg::Canvas* canvas = static_cast(data); + auto scene = tvg::Scene::gen(); + char buf[255]; sprintf(buf,"%s/%s", path, name); + scene->load(buf); - printf("SVG Load : %s\n", buf); - scene->translate(((WIDTH - (x * 2)) / numberPerLine) * (count % numberPerLine) + x, ((HEIGHT - (y * 2))/ numberPerLine) * (int)((float)count / (float)numberPerLine) + y); + scene->translate(((WIDTH - (x * 2)) / NUM_PER_LINE) * (count % NUM_PER_LINE) + x, ((HEIGHT - (y * 2))/ NUM_PER_LINE) * (int)((float)count / (float)NUM_PER_LINE) + y); canvas->push(move(scene)); + count++; + + cout << "SVG: " << buf << endl; } +void tvgDrawCmds(tvg::Canvas* canvas) +{ + auto shape1 = tvg::Shape::gen(); + shape1->appendRect(0, 0, WIDTH, HEIGHT, 0); //x, y, w, h, cornerRadius + shape1->fill(255, 255, 255, 255); //r, g, b, a -void win_del(void* data, Evas_Object* o, void* ev) + canvas->push(move(shape1)); + + eina_file_dir_list("./svgs", EINA_TRUE, svgDirCallback, canvas); +} + + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) { - elm_exit(); + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); } +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} -int main(int argc, char** argv) + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) { - //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); + static constexpr auto BPP = 4; //Create a Canvas - canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} - //Draw white background - auto scene = tvg::Scene::gen(); - auto shape1 = tvg::Shape::gen(); - shape1->appendRect(0, 0, WIDTH, HEIGHT, 0); - shape1->fill(255, 255, 255, 255); - scene->push(move(shape1)); - canvas->push(move(scene)); +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); +} - eina_file_dir_list("./svgs", EINA_TRUE, svgDirCallback, NULL); - canvas->draw(); - canvas->sync(); +/************************************************************************/ +/* Main Code */ +/************************************************************************/ - //Show the result using EFL... - elm_init(argc, argv); +int main(int argc, char **argv) +{ + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); + + elm_init(argc, argv); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + elm_config_accel_preference_set("gl"); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } elm_run(); elm_shutdown(); diff --git a/test/testTransform.cpp b/test/testTransform.cpp index dd3423a..c017f24 100644 --- a/test/testTransform.cpp +++ b/test/testTransform.cpp @@ -1,23 +1,14 @@ -#include -#include +#include "testCommon.h" -using namespace std; - -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; -unique_ptr canvas = nullptr; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ tvg::Shape* pShape = nullptr; tvg::Shape* pShape2 = nullptr; tvg::Shape* pShape3 = nullptr; -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Create a Canvas - canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - //Shape1 auto shape = tvg::Shape::gen(); @@ -51,13 +42,9 @@ void tvgtest() shape3->fill(255, 0, 255, 255); shape3->translate(400, 400); canvas->push(move(shape3)); - - //Draw first frame - canvas->draw(); - canvas->sync(); } -void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +void tvgUpdateCmds(tvg::Canvas* canvas, float progress) { /* Update shape directly. You can update only necessary properties of this shape, @@ -79,46 +66,124 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres pShape3->rotate(-360 * progress); pShape3->scale(0.5 + progress); canvas->update(pShape3); +} + + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; - //Draw Next frames - canvas->draw(); - canvas->sync(); +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +{ + tvgUpdateCmds(swCanvas.get(), progress); //Update Efl Canvas Eo* img = (Eo*) effect; evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT); + evas_object_image_pixels_dirty_set(img, EINA_TRUE); +} + +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); } -void win_del(void *data, Evas_Object *o, void *ev) +void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) { - elm_exit(); + tvgUpdateCmds(glCanvas.get(), progress); } + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; + + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } - tvgtest(); + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); - //Show the result using EFL... elm_init(argc, argv); - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + elm_config_accel_preference_set("gl"); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + Elm_Transit *transit = elm_transit_add(); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - Elm_Transit *transit = elm_transit_add(); - elm_transit_effect_add(transit, transit_cb, img, nullptr); elm_transit_duration_set(transit, 2); elm_transit_repeat_times_set(transit, -1); elm_transit_auto_reverse_set(transit, EINA_TRUE); @@ -128,5 +193,5 @@ int main(int argc, char **argv) elm_shutdown(); //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); -} + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file diff --git a/test/testUpdate.cpp b/test/testUpdate.cpp index 3a39913..d28207a 100644 --- a/test/testUpdate.cpp +++ b/test/testUpdate.cpp @@ -1,32 +1,19 @@ -#include -#include +#include "testCommon.h" -using namespace std; +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ -#define WIDTH 800 -#define HEIGHT 800 - -static uint32_t buffer[WIDTH * HEIGHT]; -unique_ptr canvas = nullptr; - -void tvgtest() +void tvgDrawCmds(tvg::Canvas* canvas) { - //Create a Canvas - canvas = tvg::SwCanvas::gen(); - canvas->target(buffer, WIDTH, WIDTH, HEIGHT); - //Shape auto shape = tvg::Shape::gen(); shape->appendRect(-100, -100, 200, 200, 0); shape->fill(255, 255, 255, 255); canvas->push(move(shape)); - - //Draw first frame - canvas->draw(); - canvas->sync(); } -void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +void tvgUpdateCmds(tvg::Canvas* canvas, float progress) { //Explicitly clear all retained paint nodes. canvas->clear(); @@ -40,46 +27,124 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres shape->rotate(360 * progress); canvas->push(move(shape)); +} + + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; - //Draw Next frames - canvas->draw(); - canvas->sync(); +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) +{ + tvgUpdateCmds(swCanvas.get(), progress); //Update Efl Canvas Eo* img = (Eo*) effect; evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT); + evas_object_image_pixels_dirty_set(img, EINA_TRUE); +} + +void drawSwView(void* data, Eo* obj) +{ + swCanvas->draw(); + swCanvas->sync(); +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + int w, h; + elm_glview_size_get(obj, &w, &h); + gl->glViewport(0, 0, w, h); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + gl->glEnable(GL_BLEND); + + glCanvas->draw(); + glCanvas->sync(); } -void win_del(void *data, Evas_Object *o, void *ev) +void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) { - elm_exit(); + tvgUpdateCmds(glCanvas.get(), progress); } + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + int main(int argc, char **argv) { + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; + + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + //Initialize ThorVG Engine - tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } - tvgtest(); + //Initialize ThorVG Engine + tvg::Initializer::init(tvgEngine); - //Show the result using EFL... elm_init(argc, argv); - Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); - evas_object_smart_callback_add(win, "delete,request", win_del, 0); + elm_config_accel_preference_set("gl"); - Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); - evas_object_image_size_set(img, WIDTH, HEIGHT); - evas_object_image_data_set(img, buffer); - evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(img); + Elm_Transit *transit = elm_transit_add(); - elm_win_resize_object_add(win, img); - evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); - evas_object_show(win); + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - Elm_Transit *transit = elm_transit_add(); - elm_transit_effect_add(transit, transit_cb, img, nullptr); elm_transit_duration_set(transit, 2); elm_transit_repeat_times_set(transit, -1); elm_transit_auto_reverse_set(transit, EINA_TRUE); @@ -89,5 +154,5 @@ int main(int argc, char **argv) elm_shutdown(); //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); -} + tvg::Initializer::term(tvgEngine); +} \ No newline at end of file -- 2.7.4 From 8bb8710815d37302b3821514d5d03efb021e718e Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 30 Jun 2020 10:24:56 +0900 Subject: [PATCH 08/16] test svg: remove white trailings Change-Id: Ie23ffdd420eb9742b21350dfffd5b29ae0515be3 --- test/testSvg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testSvg.cpp b/test/testSvg.cpp index 938d37a..4da0349 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -20,7 +20,7 @@ void svgDirCallback(const char* name, const char* path, void* data) sprintf(buf,"%s/%s", path, name); scene->load(buf); - scene->translate(((WIDTH - (x * 2)) / NUM_PER_LINE) * (count % NUM_PER_LINE) + x, ((HEIGHT - (y * 2))/ NUM_PER_LINE) * (int)((float)count / (float)NUM_PER_LINE) + y); + scene->translate(((WIDTH - (x * 2)) / NUM_PER_LINE) * (count % NUM_PER_LINE) + x, ((HEIGHT - (y * 2))/ NUM_PER_LINE) * (int)((float)count / (float)NUM_PER_LINE) + y); canvas->push(move(scene)); count++; -- 2.7.4 From 4bc0b584f3a50540042ddaec39f930e3e52575db Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 30 Jun 2020 12:38:01 +0900 Subject: [PATCH 09/16] sw_engine: flush all processing data when clear() is requested. there was a missing point which occured corrupted data in multi-processing. Change-Id: Ifb28ee82852e488d23d45b4b75f0a6c70bb428b2 --- src/lib/sw_engine/tvgSwRenderer.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index ac5464e..4f09c60 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -47,16 +47,16 @@ static RenderInitializer renderInit; SwRenderer::~SwRenderer() { - if (progress.valid()) progress.get(); + flush(); } bool SwRenderer::clear() { - if (progress.valid()) return false; - return true; + return flush(); } + bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) { if (!buffer || stride == 0 || w == 0 || h == 0) return false; @@ -117,11 +117,15 @@ void SwRenderer::doRender() bool SwRenderer::flush() { - if (progress.valid()) { - progress.get(); - return true; + while (prepareTasks.size() > 0) { + auto task = prepareTasks.front(); + if (task->progress.valid()) task->progress.get(); + prepareTasks.pop(); } - return false; + + if (progress.valid()) progress.get(); + + return true; } -- 2.7.4 From 61cb144122f381c2bb32e44ff6a41f162ad96ea4 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 30 Jun 2020 13:08:09 +0900 Subject: [PATCH 10/16] test: revise sample. this patch adds the showcase how to handle exceptional cases. Change-Id: Ic8e3c740bbf613f4dccace511b6c8d93b987a10c --- test/testAsync.cpp | 18 ++++++++++-------- test/testBlending.cpp | 20 +++++++++++--------- test/testBoundary.cpp | 20 +++++++++++--------- test/testCustomTransform.cpp | 12 +++++++----- test/testDirectUpdate.cpp | 25 ++++++++++++++----------- test/testGradientTransform.cpp | 22 ++++++++++++---------- test/testLinearGradient.cpp | 16 +++++++++------- test/testMultiShapes.cpp | 16 +++++++++------- test/testPath.cpp | 16 ++++++++++------ test/testPathCopy.cpp | 16 +++++++++------- test/testRadialGradient.cpp | 16 +++++++++------- test/testScene.cpp | 10 ++++++---- test/testSceneTransform.cpp | 10 ++++++---- test/testShape.cpp | 10 ++++++---- test/testStroke.cpp | 22 ++++++++++++---------- test/testStrokeLine.cpp | 24 +++++++++++++----------- test/testSvg.cpp | 24 ++++++++++++++---------- test/testTransform.cpp | 22 ++++++++++++---------- test/testUpdate.cpp | 12 +++++++----- 19 files changed, 187 insertions(+), 144 deletions(-) diff --git a/test/testAsync.cpp b/test/testAsync.cpp index a8ac2b0..666e7bb 100644 --- a/test/testAsync.cpp +++ b/test/testAsync.cpp @@ -13,11 +13,10 @@ bool tvgUpdateCmds(tvg::Canvas* canvas) auto t = ecore_time_get(); //Explicitly clear all retained paint nodes. - if (canvas->clear() != tvg::Result::Success) - { - //Logically wrong! Probably, you missed to call sync() before. - return false; - } + if (canvas->clear() != tvg::Result::Success) { + //Logically wrong! Probably, you missed to call sync() before. + return false; + } t1 = t; t2 = ecore_time_get(); @@ -45,7 +44,10 @@ bool tvgUpdateCmds(tvg::Canvas* canvas) fill->colorStops(colorStops, 3); shape->fill(move(fill)); - canvas->push(move(shape)); + if (canvas->push(move(shape)) != tvg::Result::Success) { + //Did you call clear()? Make it sure if canvas is on rendering + break; + } } t3 = ecore_time_get(); @@ -72,7 +74,7 @@ Eina_Bool animSwCb(void* data) if (!tvgUpdateCmds(swCanvas.get())) return ECORE_CALLBACK_RENEW; //Drawing task can be performed asynchronously. - swCanvas->draw(); + if (swCanvas->draw() != tvg::Result::Success) return false; //Update Efl Canvas Eo* img = (Eo*) data; @@ -174,4 +176,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testBlending.cpp b/test/testBlending.cpp index 7794689..733e60b 100644 --- a/test/testBlending.cpp +++ b/test/testBlending.cpp @@ -12,19 +12,19 @@ void tvgDrawCmds(tvg::Canvas* canvas) auto shape1 = tvg::Shape::gen(); shape1->appendRect(0, 0, 400, 400, 50); //x, y, w, h, cornerRadius shape1->fill(0, 255, 0, 255); //r, g, b, a - canvas->push(move(shape1)); + if (canvas->push(move(shape1)) != tvg::Result::Success) return; //Prepare Circle auto shape2 = tvg::Shape::gen(); shape2->appendCircle(400, 400, 200, 200); //cx, cy, radiusW, radiusH shape2->fill(170, 170, 0, 170); //r, g, b, a - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; //Prepare Ellipse auto shape3 = tvg::Shape::gen(); shape3->appendCircle(400, 400, 250, 100); //cx, cy, radiusW, radiusH shape3->fill(100, 100, 100, 100); //r, g, b, a - canvas->push(move(shape3)); + if (canvas->push(move(shape3)) != tvg::Result::Success) return; //Prepare Star auto shape4 = tvg::Shape::gen(); @@ -40,13 +40,13 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape4->lineTo(146, 343); shape4->close(); shape4->fill(200, 0, 200, 200); - canvas->push(move(shape4)); + if (canvas->push(move(shape4)) != tvg::Result::Success) return; //Prepare Opaque Ellipse auto shape5 = tvg::Shape::gen(); shape5->appendCircle(600, 650, 200, 150); shape5->fill(0, 0, 255, 255); - canvas->push(move(shape5)); + if (canvas->push(move(shape5)) != tvg::Result::Success) return; } @@ -71,8 +71,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -109,8 +110,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testBoundary.cpp b/test/testBoundary.cpp index e74ac5e..fcfcd68 100644 --- a/test/testBoundary.cpp +++ b/test/testBoundary.cpp @@ -12,31 +12,31 @@ void tvgDrawCmds(tvg::Canvas* canvas) auto shape1 = tvg::Shape::gen(); shape1->appendRect(-100, -100, 1000, 1000, 50); shape1->fill(255, 255, 255, 255); - canvas->push(move(shape1)); + if (canvas->push(move(shape1)) != tvg::Result::Success) return; //Prepare Shape2 auto shape2 = tvg::Shape::gen(); shape2->appendRect(-100, -100, 250, 250, 50); shape2->fill(0, 0, 255, 255); - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; //Prepare Shape3 auto shape3 = tvg::Shape::gen(); shape3->appendRect(500, 500, 550, 550, 0); shape3->fill(0, 255, 255, 255); - canvas->push(move(shape3)); + if (canvas->push(move(shape3)) != tvg::Result::Success) return; //Prepare Shape4 auto shape4 = tvg::Shape::gen(); shape4->appendCircle(800, 100, 200, 200); shape4->fill(255, 255, 0, 255); - canvas->push(move(shape4)); + if (canvas->push(move(shape4)) != tvg::Result::Success) return; //Prepare Shape5 auto shape5 = tvg::Shape::gen(); shape5->appendCircle(200, 650, 250, 200); shape5->fill(0, 0, 0, 255); - canvas->push(move(shape5)); + if (canvas->push(move(shape5)) != tvg::Result::Success) return; } /************************************************************************/ @@ -60,8 +60,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -98,8 +99,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testCustomTransform.cpp b/test/testCustomTransform.cpp index 1109a21..d87b481 100644 --- a/test/testCustomTransform.cpp +++ b/test/testCustomTransform.cpp @@ -26,7 +26,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape->lineTo(-53, -5.5); shape->close(); shape->fill(0, 0, 255, 255); - canvas->push(move(shape)); + if (canvas->push(move(shape)) != tvg::Result::Success) return; } void tvgUpdateCmds(tvg::Canvas* canvas, float progress) @@ -107,8 +107,9 @@ void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progre void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -145,8 +146,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) diff --git a/test/testDirectUpdate.cpp b/test/testDirectUpdate.cpp index 93b2dfb..529e067 100644 --- a/test/testDirectUpdate.cpp +++ b/test/testDirectUpdate.cpp @@ -21,7 +21,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape->stroke(0, 0, 255, 255); shape->stroke(1); - canvas->push(move(shape)); + if (canvas->push(move(shape)) != tvg::Result::Success) return; } void tvgUpdateCmds(tvg::Canvas* canvas, float progress) @@ -30,13 +30,14 @@ void tvgUpdateCmds(tvg::Canvas* canvas, float progress) You can update only necessary properties of this shape, while retaining other properties. */ - pShape->reset(); //reset path + //Reset Shape + if (pShape->reset() == tvg::Result::Success) { + pShape->appendRect(-100 + (800 * progress), -100 + (800 * progress), 200, 200, (100 * progress)); + pShape->stroke(30 * progress); - pShape->appendRect(-100 + (800 * progress), -100 + (800 * progress), 200, 200, (100 * progress)); - pShape->stroke(30 * progress); - - //Update shape for drawing (this may work asynchronously) - canvas->update(pShape); + //Update shape for drawing (this may work asynchronously) + canvas->update(pShape); + } } @@ -71,8 +72,9 @@ void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progre void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -109,8 +111,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) diff --git a/test/testGradientTransform.cpp b/test/testGradientTransform.cpp index b77062b..3edb5d8 100644 --- a/test/testGradientTransform.cpp +++ b/test/testGradientTransform.cpp @@ -34,7 +34,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) fill->colorStops(colorStops, 3); shape->fill(move(fill)); shape->translate(385, 400); - canvas->push(move(shape)); + if (canvas->push(move(shape)) != tvg::Result::Success) return; //Shape2 auto shape2 = tvg::Shape::gen(); @@ -53,7 +53,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) fill2->colorStops(colorStops2, 2); shape2->fill(move(fill2)); - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; //Shape3 auto shape3 = tvg::Shape::gen(); @@ -78,7 +78,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape3->fill(move(fill3)); shape3->translate(400, 400); - canvas->push(move(shape3)); + if (canvas->push(move(shape3)) != tvg::Result::Success) return; } void tvgUpdateCmds(tvg::Canvas* canvas, float progress) @@ -92,17 +92,17 @@ void tvgUpdateCmds(tvg::Canvas* canvas, float progress) pShape->rotate(360 * progress); //Update shape for drawing (this may work asynchronously) - canvas->update(pShape); + if (canvas->update(pShape) != tvg::Result::Success) return; //Update Shape2 pShape2->rotate(360 * progress); pShape2->translate(400 + progress * 300, 400); - canvas->update(pShape2); + if (canvas->update(pShape2) != tvg::Result::Success) return; //Update Shape3 pShape3->rotate(-360 * progress); pShape3->scale(0.5 + progress); - canvas->update(pShape3); + if (canvas->update(pShape3) != tvg::Result::Success) return; } @@ -137,8 +137,9 @@ void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progre void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -175,8 +176,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) diff --git a/test/testLinearGradient.cpp b/test/testLinearGradient.cpp index 36251f5..63e690a 100644 --- a/test/testLinearGradient.cpp +++ b/test/testLinearGradient.cpp @@ -24,7 +24,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) fill->colorStops(colorStops, 2); shape1->fill(move(fill)); - canvas->push(move(shape1)); + if (canvas->push(move(shape1)) != tvg::Result::Success) return; //Prepare Circle auto shape2 = tvg::Shape::gen(); @@ -43,7 +43,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) fill2->colorStops(colorStops2, 3); shape2->fill(move(fill2)); - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; //Prepare Ellipse @@ -64,7 +64,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) fill3->colorStops(colorStops3, 4); shape3->fill(move(fill3)); - canvas->push(move(shape3)); + if (canvas->push(move(shape3)) != tvg::Result::Success) return; } @@ -89,8 +89,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -127,8 +128,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testMultiShapes.cpp b/test/testMultiShapes.cpp index 195547d..73992b6 100644 --- a/test/testMultiShapes.cpp +++ b/test/testMultiShapes.cpp @@ -12,19 +12,19 @@ void tvgDrawCmds(tvg::Canvas* canvas) auto shape1 = tvg::Shape::gen(); shape1->appendRect(0, 0, 400, 400, 50); //x, y, w, h, cornerRadius shape1->fill(0, 255, 0, 255); //r, g, b, a - canvas->push(move(shape1)); + if (canvas->push(move(shape1)) != tvg::Result::Success) return; //Prepare Circle auto shape2 = tvg::Shape::gen(); shape2->appendCircle(400, 400, 200, 200); //cx, cy, radiusW, radiusH shape2->fill(255, 255, 0, 255); //r, g, b, a - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; //Prepare Ellipse auto shape3 = tvg::Shape::gen(); shape3->appendCircle(600, 600, 150, 100); //cx, cy, radiusW, radiusH shape3->fill(0, 255, 255, 255); //r, g, b, a - canvas->push(move(shape3)); + if (canvas->push(move(shape3)) != tvg::Result::Success) return; } @@ -49,8 +49,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -87,8 +88,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testPath.cpp b/test/testPath.cpp index 49bd738..3fbb834 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -22,7 +22,8 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape1->lineTo(146, 143); shape1->close(); shape1->fill(0, 0, 255, 255); - canvas->push(move(shape1)); + if (canvas->push(move(shape1)) != tvg::Result::Success) return; + //Circle auto shape2 = tvg::Shape::gen(); @@ -39,7 +40,8 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape2->cubicTo(cx - halfRadius, cy + radius, cx - radius, cy + halfRadius, cx - radius, cy); shape2->cubicTo(cx - radius, cy - halfRadius, cx - halfRadius, cy - radius, cx, cy - radius); shape2->fill(255, 0, 0, 255); - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; + } /************************************************************************/ @@ -63,8 +65,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -101,8 +104,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testPathCopy.cpp b/test/testPathCopy.cpp index b619f78..3407f92 100644 --- a/test/testPathCopy.cpp +++ b/test/testPathCopy.cpp @@ -38,8 +38,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) auto shape1 = tvg::Shape::gen(); shape1->appendPath(cmds, 11, pts, 10); //copy path data shape1->fill(0, 255, 0, 255); - canvas->push(move(shape1)); - + if (canvas->push(move(shape1)) != tvg::Result::Success) return; /* Circle */ auto cx = 550.0f; @@ -79,7 +78,8 @@ void tvgDrawCmds(tvg::Canvas* canvas) auto shape2 = tvg::Shape::gen(); shape2->appendPath(cmds2, 6, pts2, 13); //copy path data shape2->fill(255, 255, 0, 255); - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; + } /************************************************************************/ @@ -103,8 +103,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -141,8 +142,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testRadialGradient.cpp b/test/testRadialGradient.cpp index f12777c..ffec5fa 100644 --- a/test/testRadialGradient.cpp +++ b/test/testRadialGradient.cpp @@ -24,7 +24,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) fill->colorStops(colorStops, 2); shape1->fill(move(fill)); - canvas->push(move(shape1)); + if (canvas->push(move(shape1)) != tvg::Result::Success) return; //Prepare Circle auto shape2 = tvg::Shape::gen(); @@ -43,7 +43,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) fill2->colorStops(colorStops2, 3); shape2->fill(move(fill2)); - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; //Prepare Ellipse @@ -64,7 +64,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) fill3->colorStops(colorStops3, 4); shape3->fill(move(fill3)); - canvas->push(move(shape3)); + if (canvas->push(move(shape3)) != tvg::Result::Success) return; } @@ -89,8 +89,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -127,8 +128,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testScene.cpp b/test/testScene.cpp index e16772a..5a6b25f 100644 --- a/test/testScene.cpp +++ b/test/testScene.cpp @@ -96,8 +96,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -134,8 +135,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index 7bd8b41..8c0898f 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -132,8 +132,9 @@ void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progre void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -170,8 +171,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) diff --git a/test/testShape.cpp b/test/testShape.cpp index 9aa284d..406b369 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -39,8 +39,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -77,8 +78,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testStroke.cpp b/test/testStroke.cpp index 493bbde..c7f95df 100644 --- a/test/testStroke.cpp +++ b/test/testStroke.cpp @@ -14,7 +14,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape1->stroke(tvg::StrokeJoin::Bevel); //default is Bevel shape1->stroke(10); //width: 10px - canvas->push(move(shape1)); + if (canvas->push(move(shape1)) != tvg::Result::Success) return; //Shape 2 auto shape2 = tvg::Shape::gen(); @@ -24,7 +24,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape2->stroke(tvg::StrokeJoin::Round); shape2->stroke(10); - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; //Shape 3 auto shape3 = tvg::Shape::gen(); @@ -34,7 +34,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape3->stroke(tvg::StrokeJoin::Miter); shape3->stroke(10); - canvas->push(move(shape3)); + if (canvas->push(move(shape3)) != tvg::Result::Success) return; //Shape 4 auto shape4 = tvg::Shape::gen(); @@ -43,7 +43,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape4->stroke(255, 255, 255, 255); shape4->stroke(1); - canvas->push(move(shape4)); + if (canvas->push(move(shape4)) != tvg::Result::Success) return; //Shape 5 auto shape5 = tvg::Shape::gen(); @@ -52,7 +52,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape5->stroke(255, 255, 255, 255); shape5->stroke(2); - canvas->push(move(shape5)); + if (canvas->push(move(shape5)) != tvg::Result::Success) return; //Shape 6 auto shape6 = tvg::Shape::gen(); @@ -61,7 +61,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape6->stroke(255, 255, 255, 255); shape6->stroke(4); - canvas->push(move(shape6)); + if (canvas->push(move(shape6)) != tvg::Result::Success) return; } @@ -86,8 +86,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -124,8 +125,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testStrokeLine.cpp b/test/testStrokeLine.cpp index d57bf1f..31e670e 100644 --- a/test/testStrokeLine.cpp +++ b/test/testStrokeLine.cpp @@ -14,7 +14,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape->stroke(255, 255, 255, 255); //color: r, g, b, a shape->stroke(i + 1); //stroke width shape->stroke(tvg::StrokeCap::Round); //default is Square - canvas->push(move(shape)); + if (canvas->push(move(shape)) != tvg::Result::Success) return; } //Test for StrokeJoin & StrokeCap @@ -28,7 +28,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape1->stroke(10); shape1->stroke(tvg::StrokeJoin::Round); shape1->stroke(tvg::StrokeCap::Round); - canvas->push(move(shape1)); + if (canvas->push(move(shape1)) != tvg::Result::Success) return; auto shape2 = tvg::Shape::gen(); shape2->moveTo(270, 350); @@ -40,7 +40,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape2->stroke(10); shape2->stroke(tvg::StrokeJoin::Bevel); shape2->stroke(tvg::StrokeCap::Square); - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; auto shape3 = tvg::Shape::gen(); shape3->moveTo(520, 350); @@ -52,7 +52,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape3->stroke(10); shape3->stroke(tvg::StrokeJoin::Miter); shape3->stroke(tvg::StrokeCap::Butt); - canvas->push(move(shape3)); + if (canvas->push(move(shape3)) != tvg::Result::Success) return; //Test for Stroke Dash auto shape4 = tvg::Shape::gen(); @@ -68,7 +68,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) float dashPattern1[2] = {10, 10}; shape4->stroke(dashPattern1, 2); - canvas->push(move(shape4)); + if (canvas->push(move(shape4)) != tvg::Result::Success) return; auto shape5 = tvg::Shape::gen(); shape5->moveTo(270, 600); @@ -83,7 +83,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) float dashPattern2[4] = {10, 10}; shape5->stroke(dashPattern2, 4); - canvas->push(move(shape5)); + if (canvas->push(move(shape5)) != tvg::Result::Success) return; auto shape6 = tvg::Shape::gen(); shape6->moveTo(520, 600); @@ -98,7 +98,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) float dashPattern3[2] = {10, 10}; shape6->stroke(dashPattern3, 2); - canvas->push(move(shape6)); + if (canvas->push(move(shape6)) != tvg::Result::Success) return; } @@ -123,8 +123,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -161,8 +162,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testSvg.cpp b/test/testSvg.cpp index 4da0349..13f3e4c 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -16,10 +16,11 @@ void svgDirCallback(const char* name, const char* path, void* data) auto scene = tvg::Scene::gen(); - char buf[255]; + char buf[PATH_MAX]; sprintf(buf,"%s/%s", path, name); - scene->load(buf); + if (scene->load(buf) != tvg::Result::Success) return; + scene->translate(((WIDTH - (x * 2)) / NUM_PER_LINE) * (count % NUM_PER_LINE) + x, ((HEIGHT - (y * 2))/ NUM_PER_LINE) * (int)((float)count / (float)NUM_PER_LINE) + y); canvas->push(move(scene)); @@ -30,11 +31,12 @@ void svgDirCallback(const char* name, const char* path, void* data) void tvgDrawCmds(tvg::Canvas* canvas) { - auto shape1 = tvg::Shape::gen(); - shape1->appendRect(0, 0, WIDTH, HEIGHT, 0); //x, y, w, h, cornerRadius - shape1->fill(255, 255, 255, 255); //r, g, b, a + //Background + auto shape = tvg::Shape::gen(); + shape->appendRect(0, 0, WIDTH, HEIGHT, 0); //x, y, w, h, cornerRadius + shape->fill(255, 255, 255, 255); //r, g, b, a - canvas->push(move(shape1)); + if (canvas->push(move(shape)) != tvg::Result::Success) return; eina_file_dir_list("./svgs", EINA_TRUE, svgDirCallback, canvas); } @@ -61,8 +63,9 @@ void tvgSwTest(uint32_t* buffer) void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -99,8 +102,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } diff --git a/test/testTransform.cpp b/test/testTransform.cpp index c017f24..7376f97 100644 --- a/test/testTransform.cpp +++ b/test/testTransform.cpp @@ -22,7 +22,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape->appendCircle(115, 200, 170, 100); shape->fill(255, 255, 255, 255); shape->translate(385, 400); - canvas->push(move(shape)); + if (canvas->push(move(shape)) != tvg::Result::Success) return; //Shape2 auto shape2 = tvg::Shape::gen(); @@ -30,7 +30,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape2->appendRect(-50, -50, 100, 100, 0); shape2->fill(0, 255, 255, 255); shape2->translate(400, 400); - canvas->push(move(shape2)); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; //Shape3 auto shape3 = tvg::Shape::gen(); @@ -41,7 +41,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape3->appendRect(100, 100, 150, 50, 20); shape3->fill(255, 0, 255, 255); shape3->translate(400, 400); - canvas->push(move(shape3)); + if (canvas->push(move(shape3)) != tvg::Result::Success) return; } void tvgUpdateCmds(tvg::Canvas* canvas, float progress) @@ -55,17 +55,17 @@ void tvgUpdateCmds(tvg::Canvas* canvas, float progress) pShape->rotate(360 * progress); //Update shape for drawing (this may work asynchronously) - canvas->update(pShape); + if (canvas->update(pShape) != tvg::Result::Success) return; //Update Shape2 pShape2->rotate(360 * progress); pShape2->translate(400 + progress * 300, 400); - canvas->update(pShape2); + if (canvas->update(pShape2) != tvg::Result::Success) return; //Update Shape3 pShape3->rotate(-360 * progress); pShape3->scale(0.5 + progress); - canvas->update(pShape3); + if (canvas->update(pShape3) != tvg::Result::Success) return; } @@ -100,8 +100,9 @@ void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progre void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -138,8 +139,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) diff --git a/test/testUpdate.cpp b/test/testUpdate.cpp index d28207a..e1b0212 100644 --- a/test/testUpdate.cpp +++ b/test/testUpdate.cpp @@ -16,7 +16,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) void tvgUpdateCmds(tvg::Canvas* canvas, float progress) { //Explicitly clear all retained paint nodes. - canvas->clear(); + if (canvas->clear() != tvg::Result::Success) return; //Shape auto shape = tvg::Shape::gen(); @@ -61,8 +61,9 @@ void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progre void drawSwView(void* data, Eo* obj) { - swCanvas->draw(); - swCanvas->sync(); + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } } @@ -99,8 +100,9 @@ void drawGLview(Evas_Object *obj) gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); gl->glEnable(GL_BLEND); - glCanvas->draw(); - glCanvas->sync(); + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } } void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) -- 2.7.4 From f377f339935f60eb276a0eee7648863746413a59 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 30 Jun 2020 16:57:31 +0900 Subject: [PATCH 11/16] sw_engine: fix to update stroking transform when shape doesn't have fill color, stroking is missed in update. this fixs that issue. Change-Id: I49292475e56caa834e79497a16db705b965bcf5f --- src/lib/sw_engine/tvgSwRenderer.cpp | 17 ++++++++++------- src/lib/sw_engine/tvgSwShape.cpp | 5 ++++- test/testCustomTransform.cpp | 4 +++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 4f09c60..f6fc88b 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -175,12 +175,19 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* task->flags = flags; auto asyncTask = [](SwTask* task) { + + //Valid Stroking? + uint8_t strokeAlpha = 0; + if (task->sdata->strokeWidth() > FLT_EPSILON) { + task->sdata->strokeColor(nullptr, nullptr, nullptr, &strokeAlpha); + } + //Shape if (task->flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) { shapeReset(task->shape); uint8_t alpha = 0; task->sdata->fill(nullptr, nullptr, nullptr, &alpha); - if (alpha > 0 || task->sdata->fill()) { + if (alpha > 0 || task->sdata->fill() || strokeAlpha > 0) { if (!shapeGenRle(task->shape, task->sdata, task->clip, task->transform)) return; } } @@ -197,13 +204,9 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* } //Stroke if (task->flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { - if (task->sdata->strokeWidth() > FLT_EPSILON) { + if (strokeAlpha > 0) { shapeResetStroke(task->shape, task->sdata); - uint8_t alpha = 0; - task->sdata->strokeColor(nullptr, nullptr, nullptr, &alpha); - if (alpha > 0) { - if (!shapeGenStrokeRle(task->shape, task->sdata, task->clip)) return; - } + if (!shapeGenStrokeRle(task->shape, task->sdata, task->clip)) return; } else { shapeDelStroke(task->shape); } diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index 29ecf27..a4c811a 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -211,7 +211,7 @@ static bool _updateBBox(SwOutline* outline, SwBBox& bbox) bbox.min.y = yMin >> 6; bbox.max.y = (yMax + 63) >> 6; - if (xMax - xMin < 1 || yMax - yMin < 1) return false; + if (xMax - xMin < 1 && yMax - yMin < 1) return false; return true; } @@ -451,6 +451,9 @@ bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, const M if (!_checkValid(shape.outline, shape.bbox, clip)) goto end; + //Case: Stroke Line + if (shape.outline->opened) return true; + shape.rle = rleRender(shape.outline, shape.bbox, clip); end: if (shape.rle) return true; diff --git a/test/testCustomTransform.cpp b/test/testCustomTransform.cpp index d87b481..27e3c6e 100644 --- a/test/testCustomTransform.cpp +++ b/test/testCustomTransform.cpp @@ -26,6 +26,8 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape->lineTo(-53, -5.5); shape->close(); shape->fill(0, 0, 255, 255); + shape->stroke(3); + shape->stroke(255, 255, 255, 255); if (canvas->push(move(shape)) != tvg::Result::Success) return; } @@ -203,4 +205,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} -- 2.7.4 From 5faa94340f9abe6cefe2d52d41742ce2fc7b79ea Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 1 Jul 2020 12:53:01 +0900 Subject: [PATCH 12/16] sw_engine: fix a regression bug. Shape must have closed path for filling color. if closed is skipped, it would take it's a line. Change-Id: Ie1dcde9edbfc6501a34d6cb9ce54184ade6864db --- src/lib/sw_engine/tvgSwShape.cpp | 5 +++++ test/testPath.cpp | 3 ++- test/testSceneTransform.cpp | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index a4c811a..4c99fb1 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -528,11 +528,14 @@ bool shapeGenOutline(SwShape& shape, const Shape* sdata) _growOutlinePoint(*outline, outlinePtsCnt); _growOutlineContour(*outline, outlineCntrsCnt); + auto closed = false; + //Generate Outlines while (cmdCnt-- > 0) { switch(*cmds) { case PathCommand::Close: { _outlineClose(*outline); + closed = true; break; } case PathCommand::MoveTo: { @@ -556,6 +559,8 @@ bool shapeGenOutline(SwShape& shape, const Shape* sdata) _outlineEnd(*outline); + if (closed) outline->opened = false; + //FIXME: //outline->flags = SwOutline::FillRule::Winding; diff --git a/test/testPath.cpp b/test/testPath.cpp index 3fbb834..8c79848 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -39,6 +39,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape2->cubicTo(cx + radius, cy + halfRadius, cx + halfRadius, cy + radius, cx, cy+ radius); shape2->cubicTo(cx - halfRadius, cy + radius, cx - radius, cy + halfRadius, cx - radius, cy); shape2->cubicTo(cx - radius, cy - halfRadius, cx - halfRadius, cy - radius, cx, cy - radius); + shape2->close(); shape2->fill(255, 0, 0, 255); if (canvas->push(move(shape2)) != tvg::Result::Success) return; @@ -147,4 +148,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index 8c0898f..fc088a5 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -75,6 +75,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape5->cubicTo(cx + radius, cy + halfRadius, cx + halfRadius, cy + radius, cx, cy+ radius); shape5->cubicTo(cx - halfRadius, cy + radius, cx - radius, cy + halfRadius, cx - radius, cy); shape5->cubicTo(cx - radius, cy - halfRadius, cx - halfRadius, cy - radius, cx, cy - radius); + shape5->close(); shape5->fill(127, 0, 0, 127); scene2->push(move(shape5)); @@ -228,4 +229,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} -- 2.7.4 From 8c815e95c8b4a08d55ad30df8e4b110715e693d7 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Wed, 1 Jul 2020 13:44:12 +0900 Subject: [PATCH 13/16] SvgLoader: Don't use custom transform Change-Id: Ia7cd0992bbb8d5ee117806ee62b35604ffd91e16 --- src/loaders/svg_loader/tvgSvgSceneBuilder.cpp | 36 ++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp index b3fe81d..b79a3eb 100644 --- a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp @@ -21,12 +21,37 @@ #include "tvgSvgSceneBuilder.h" +static void _getTransformationData(Matrix* m, float* tx, float* ty, float* s, float* z) +{ + float rz, si, cs, zcs, zsi; + + *tx = m->e13; + *ty = m->e23; + + cs = m->e11; + si = m->e12; + rz = atan2(si, cs); + *z = rz * (180.0 / M_PI); + zcs = cosf(rz); + zsi = sinf(rz); + m->e11 = m->e11 * zcs + m->e12 * zsi; + m->e22 = m->e21 * (-1 * zsi) + m->e22 * zcs; + *s = m->e11 > m->e22 ? m->e11 : m->e22; +} + + unique_ptr _applyProperty(SvgNode* node, unique_ptr vg) { SvgStyleProperty* style = node->style; //Apply the transformation - if (node->transform) vg->transform(*node->transform); + if (node->transform) { + float tx = 0, ty = 0, s = 0, z = 0; + _getTransformationData(node->transform, &tx, &ty, &s, &z); + vg->scale(s); + vg->rotate(z); + vg->translate(tx, ty); + } if (node->type == SvgNodeType::Doc) return vg; @@ -151,8 +176,13 @@ unique_ptr _sceneBuildHelper(SvgNode* node) { if (node->type == SvgNodeType::Doc || node->type == SvgNodeType::G) { auto scene = tvg::Scene::gen(); - if (node->transform) scene->transform(*node->transform); - + if (node->transform) { + float tx = 0, ty = 0, s = 0, z = 0; + _getTransformationData(node->transform, &tx, &ty, &s, &z); + scene->scale(s); + scene->rotate(z); + scene->translate(tx, ty); + } for (vector::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) { SvgNode* child = *itrChild; if (child->type == SvgNodeType::Doc || child->type == SvgNodeType::G) scene->push(_sceneBuildHelper(*itrChild)); -- 2.7.4 From 0d5adb2f033588bfe11a9b75aba2ad509bccbdfa Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 1 Jul 2020 14:25:53 +0900 Subject: [PATCH 14/16] test: enable gl window only on gl backend. Change-Id: Iafd790b7fc1df8a58bdce2f18c39029cc0d74945 --- test/testAsync.cpp | 2 -- test/testBlending.cpp | 2 -- test/testBoundary.cpp | 2 -- test/testCommon.h | 2 ++ test/testCustomTransform.cpp | 2 -- test/testDirectUpdate.cpp | 2 -- test/testGradientTransform.cpp | 2 -- test/testLinearGradient.cpp | 2 -- test/testMultiShapes.cpp | 2 -- test/testPath.cpp | 2 -- test/testPathCopy.cpp | 2 -- test/testRadialGradient.cpp | 2 -- test/testScene.cpp | 2 -- test/testSceneTransform.cpp | 2 -- test/testShape.cpp | 2 -- test/testStroke.cpp | 2 -- test/testStrokeLine.cpp | 2 -- test/testSvg.cpp | 2 -- test/testTransform.cpp | 2 -- test/testUpdate.cpp | 2 -- 20 files changed, 2 insertions(+), 38 deletions(-) diff --git a/test/testAsync.cpp b/test/testAsync.cpp index 666e7bb..9ae7113 100644 --- a/test/testAsync.cpp +++ b/test/testAsync.cpp @@ -160,8 +160,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { auto view = createSwView(); evas_object_image_pixels_get_callback_set(view, drawSwView, nullptr); diff --git a/test/testBlending.cpp b/test/testBlending.cpp index 733e60b..14bc9ac 100644 --- a/test/testBlending.cpp +++ b/test/testBlending.cpp @@ -140,8 +140,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testBoundary.cpp b/test/testBoundary.cpp index fcfcd68..ca598e4 100644 --- a/test/testBoundary.cpp +++ b/test/testBoundary.cpp @@ -129,8 +129,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testCommon.h b/test/testCommon.h index c47723a..f176956 100644 --- a/test/testCommon.h +++ b/test/testCommon.h @@ -50,6 +50,8 @@ void drawGLview(Evas_Object *obj); static Eo* createGlView() { + elm_config_accel_preference_set("gl"); + Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); evas_object_smart_callback_add(win, "delete,request", win_del, 0); diff --git a/test/testCustomTransform.cpp b/test/testCustomTransform.cpp index 27e3c6e..08075d2 100644 --- a/test/testCustomTransform.cpp +++ b/test/testCustomTransform.cpp @@ -183,8 +183,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - Elm_Transit *transit = elm_transit_add(); if (tvgEngine == tvg::CanvasEngine::Sw) { diff --git a/test/testDirectUpdate.cpp b/test/testDirectUpdate.cpp index 529e067..24fae64 100644 --- a/test/testDirectUpdate.cpp +++ b/test/testDirectUpdate.cpp @@ -146,8 +146,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - Elm_Transit *transit = elm_transit_add(); if (tvgEngine == tvg::CanvasEngine::Sw) { diff --git a/test/testGradientTransform.cpp b/test/testGradientTransform.cpp index 3edb5d8..ddc9c88 100644 --- a/test/testGradientTransform.cpp +++ b/test/testGradientTransform.cpp @@ -211,8 +211,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - Elm_Transit *transit = elm_transit_add(); if (tvgEngine == tvg::CanvasEngine::Sw) { diff --git a/test/testLinearGradient.cpp b/test/testLinearGradient.cpp index 63e690a..d6f04e4 100644 --- a/test/testLinearGradient.cpp +++ b/test/testLinearGradient.cpp @@ -158,8 +158,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testMultiShapes.cpp b/test/testMultiShapes.cpp index 73992b6..b5c6d42 100644 --- a/test/testMultiShapes.cpp +++ b/test/testMultiShapes.cpp @@ -118,8 +118,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testPath.cpp b/test/testPath.cpp index 8c79848..d74b89d 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -135,8 +135,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testPathCopy.cpp b/test/testPathCopy.cpp index 3407f92..ebf900c 100644 --- a/test/testPathCopy.cpp +++ b/test/testPathCopy.cpp @@ -172,8 +172,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testRadialGradient.cpp b/test/testRadialGradient.cpp index ffec5fa..de93d46 100644 --- a/test/testRadialGradient.cpp +++ b/test/testRadialGradient.cpp @@ -158,8 +158,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testScene.cpp b/test/testScene.cpp index 5a6b25f..ec1ed4a 100644 --- a/test/testScene.cpp +++ b/test/testScene.cpp @@ -165,8 +165,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index fc088a5..c1b1662 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -207,8 +207,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - Elm_Transit *transit = elm_transit_add(); if (tvgEngine == tvg::CanvasEngine::Sw) { diff --git a/test/testShape.cpp b/test/testShape.cpp index 406b369..5bf9e65 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -108,8 +108,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testStroke.cpp b/test/testStroke.cpp index c7f95df..b9cfb4c 100644 --- a/test/testStroke.cpp +++ b/test/testStroke.cpp @@ -155,8 +155,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testStrokeLine.cpp b/test/testStrokeLine.cpp index 31e670e..1856453 100644 --- a/test/testStrokeLine.cpp +++ b/test/testStrokeLine.cpp @@ -192,8 +192,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testSvg.cpp b/test/testSvg.cpp index 13f3e4c..e023274 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -132,8 +132,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - if (tvgEngine == tvg::CanvasEngine::Sw) { createSwView(); } else { diff --git a/test/testTransform.cpp b/test/testTransform.cpp index 7376f97..35b237c 100644 --- a/test/testTransform.cpp +++ b/test/testTransform.cpp @@ -174,8 +174,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - Elm_Transit *transit = elm_transit_add(); if (tvgEngine == tvg::CanvasEngine::Sw) { diff --git a/test/testUpdate.cpp b/test/testUpdate.cpp index e1b0212..051a581 100644 --- a/test/testUpdate.cpp +++ b/test/testUpdate.cpp @@ -135,8 +135,6 @@ int main(int argc, char **argv) elm_init(argc, argv); - elm_config_accel_preference_set("gl"); - Elm_Transit *transit = elm_transit_add(); if (tvgEngine == tvg::CanvasEngine::Sw) { -- 2.7.4 From 322174d778d695be5153db574c6cb20fe251188b Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 1 Jul 2020 11:33:50 +0900 Subject: [PATCH 15/16] sw_engine: optimize othogonal rectangle drawing. if the rectangle is not transformed, we don't need to use rle method. we can directly raster pixels onto the bounding box. Change-Id: I4e8b57149c0bcd78124d09388bf5115093a43bee --- src/lib/sw_engine/tvgSwCommon.h | 2 + src/lib/sw_engine/tvgSwRaster.cpp | 147 ++++++++++++++++++++++++++++++++++---- src/lib/sw_engine/tvgSwShape.cpp | 28 +++++++- test/testAsync.cpp | 2 +- 4 files changed, 162 insertions(+), 17 deletions(-) diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 72fa700..88686b5 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -198,6 +198,8 @@ struct SwShape SwRleData* rle; SwRleData* strokeRle; SwBBox bbox; + + bool rect; //Fast Track: Othogonal rectangle? }; diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 05429f3..5a14822 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -24,17 +24,58 @@ /* Internal Class Implementation */ /************************************************************************/ +static SwBBox _clipRegion(Surface& surface, SwBBox& in) +{ + auto bbox = in; + + if (bbox.min.x < 0) bbox.min.x = 0; + if (bbox.min.y < 0) bbox.min.y = 0; + if (bbox.max.x > surface.w) bbox.max.x = surface.w; + if (bbox.max.y > surface.h) bbox.max.y = surface.h; + + return bbox; +} + +static bool _rasterTranslucentRect(Surface& surface, const SwBBox& region, uint32_t color) +{ + auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x; + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + auto ialpha = 255 - COLOR_ALPHA(color); + + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface.stride]; + for (uint32_t x = 0; x < w; ++x) { + dst[x] = color + COLOR_ALPHA_BLEND(dst[x], ialpha); + } + } + return true; +} + + +static bool _rasterSolidRect(Surface& surface, const SwBBox& region, uint32_t color) +{ + auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x; + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface.stride]; + COLOR_SET(dst, color, w); + } + return true; +} + static bool _rasterTranslucentRle(Surface& surface, SwRleData* rle, uint32_t color) { if (!rle) return false; auto span = rle->spans; - auto stride = surface.stride; uint32_t src; for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * stride + span->x]; + auto dst = &surface.buffer[span->y * surface.stride + span->x]; if (span->coverage < 255) src = COLOR_ALPHA_BLEND(color, span->coverage); else src = color; auto ialpha = 255 - COLOR_ALPHA(src); @@ -52,10 +93,9 @@ static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color) if (!rle) return false; auto span = rle->spans; - auto stride = surface.stride; for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * stride + span->x]; + auto dst = &surface.buffer[span->y * surface.stride + span->x]; if (span->coverage == 255) { COLOR_SET(dst, color, span->len); } else { @@ -71,6 +111,70 @@ static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color) } +static bool _rasterLinearGradientRect(Surface& surface, const SwBBox& region, const SwFill* fill) +{ + if (!fill) return false; + + auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x; + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + + //Translucent Gradient + if (fill->translucent) { + + auto tmpBuf = static_cast(alloca(surface.w * sizeof(uint32_t))); + if (!tmpBuf) return false; + + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface.stride]; + fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, w); + for (uint32_t x = 0; x < w; ++x) { + dst[x] = tmpBuf[x] + COLOR_ALPHA_BLEND(dst[x], 255 - COLOR_ALPHA(tmpBuf[x])); + } + } + //Opaque Gradient + } else { + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface.stride]; + fillFetchLinear(fill, dst, region.min.y + y, region.min.x, w); + } + } + return true; +} + + +static bool _rasterRadialGradientRect(Surface& surface, const SwBBox& region, const SwFill* fill) +{ + if (!fill) return false; + + auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x; + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + + //Translucent Gradient + if (fill->translucent) { + + auto tmpBuf = static_cast(alloca(surface.w * sizeof(uint32_t))); + if (!tmpBuf) return false; + + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface.stride]; + fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w); + for (uint32_t x = 0; x < w; ++x) { + dst[x] = tmpBuf[x] + COLOR_ALPHA_BLEND(dst[x], 255 - COLOR_ALPHA(tmpBuf[x])); + } + } + //Opaque Gradient + } else { + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface.stride]; + fillFetchRadial(fill, dst, region.min.y + y, region.min.x, w); + } + } + return true; +} + + static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwFill* fill) { if (!rle || !fill) return false; @@ -79,12 +183,11 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF if (!buf) return false; auto span = rle->spans; - auto stride = surface.stride; //Translucent Gradient if (fill->translucent) { for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * stride + span->x]; + auto dst = &surface.buffer[span->y * surface.stride + span->x]; fillFetchLinear(fill, buf, span->y, span->x, span->len); if (span->coverage == 255) { for (uint32_t i = 0; i < span->len; ++i) { @@ -101,7 +204,7 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF //Opaque Gradient } else { for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * stride + span->x]; + auto dst = &surface.buffer[span->y * surface.stride + span->x]; if (span->coverage == 255) { fillFetchLinear(fill, dst, span->y, span->x, span->len); } else { @@ -126,12 +229,11 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF if (!buf) return false; auto span = rle->spans; - auto stride = surface.stride; //Translucent Gradient if (fill->translucent) { for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * stride + span->x]; + auto dst = &surface.buffer[span->y * surface.stride + span->x]; fillFetchRadial(fill, buf, span->y, span->x, span->len); if (span->coverage == 255) { for (uint32_t i = 0; i < span->len; ++i) { @@ -148,7 +250,7 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF //Opaque Gradient } else { for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * stride + span->x]; + auto dst = &surface.buffer[span->y * surface.stride + span->x]; if (span->coverage == 255) { fillFetchRadial(fill, dst, span->y, span->x, span->len); } else { @@ -171,15 +273,31 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF bool rasterGradientShape(Surface& surface, SwShape& shape, unsigned id) { - if (id == FILL_ID_LINEAR) return _rasterLinearGradientRle(surface, shape.rle, shape.fill); - return _rasterRadialGradientRle(surface, shape.rle, shape.fill); + //Fast Track + if (shape.rect) { + auto region = _clipRegion(surface, shape.bbox); + if (id == FILL_ID_LINEAR) return _rasterLinearGradientRect(surface, region, shape.fill); + return _rasterRadialGradientRect(surface, region, shape.fill); + } else { + if (id == FILL_ID_LINEAR) return _rasterLinearGradientRle(surface, shape.rle, shape.fill); + return _rasterRadialGradientRle(surface, shape.rle, shape.fill); + } + return false; } bool rasterSolidShape(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - if (a == 255) return _rasterSolidRle(surface, shape.rle, COLOR_ARGB_JOIN(r, g, b, a)); - return _rasterTranslucentRle(surface, shape.rle, COLOR_ARGB_JOIN(r, g, b, a)); + //Fast Track + if (shape.rect) { + auto region = _clipRegion(surface, shape.bbox); + if (a == 255) return _rasterSolidRect(surface, region, COLOR_ARGB_JOIN(r, g, b, a)); + return _rasterTranslucentRect(surface, region, COLOR_ARGB_JOIN(r, g, b, a)); + } else{ + if (a == 255) return _rasterSolidRle(surface, shape.rle, COLOR_ARGB_JOIN(r, g, b, a)); + return _rasterTranslucentRle(surface, shape.rle, COLOR_ARGB_JOIN(r, g, b, a)); + } + return false; } @@ -204,5 +322,4 @@ bool rasterClear(Surface& surface) return true; } - #endif /* _TVG_SW_RASTER_CPP_ */ \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index 4c99fb1..1c0a09e 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -241,7 +241,7 @@ static void _transformOutline(SwOutline* outline, const Matrix* transform) auto dy = static_cast(outline->pts[i].y >> 6); auto tx = dx * transform->e11 + dy * transform->e12 + transform->e31; auto ty = dx * transform->e21 + dy * transform->e22 + transform->e32; - auto pt = Point{tx, ty}; + auto pt = Point{round(tx), round(ty)}; outline->pts[i] = TO_SWPOINT(&pt); } } @@ -437,6 +437,28 @@ SwOutline* _genDashOutline(const Shape* sdata) } +bool _fastTrack(const SwOutline* outline) +{ + //Fast Track: Othogonal rectangle? + if (outline->ptsCnt != 5) return false; + + auto pt1 = outline->pts + 0; + auto pt2 = outline->pts + 1; + auto pt3 = outline->pts + 2; + auto pt4 = outline->pts + 3; + + auto min1 = pt1->y < pt3->y ? pt1 : pt3; + auto min2 = pt2->y < pt4->y ? pt2 : pt4; + if (min1->y != min2->y) return false; + + SwCoord len1 = pow(pt1->x - pt3->x, 2) + pow(pt1->y - pt3->y, 2); + SwCoord len2 = pow(pt2->x - pt4->x, 2) + pow(pt2->y - pt4->y, 2); + if (len1 == len2) return true; + + return false; +} + + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -451,6 +473,9 @@ bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, const M if (!_checkValid(shape.outline, shape.bbox, clip)) goto end; + //Case: Fast Track Rectangle Drawing + if ((shape.rect = _fastTrack(shape.outline))) return true; + //Case: Stroke Line if (shape.outline->opened) return true; @@ -474,6 +499,7 @@ void shapeReset(SwShape& shape) shapeDelOutline(shape); rleFree(shape.rle); shape.rle = nullptr; + shape.rect = false; _initBBox(shape.bbox); } diff --git a/test/testAsync.cpp b/test/testAsync.cpp index 9ae7113..ca1d473 100644 --- a/test/testAsync.cpp +++ b/test/testAsync.cpp @@ -29,7 +29,7 @@ bool tvgUpdateCmds(tvg::Canvas* canvas) float w = 1 + rand() % (int)(WIDTH * 1.3 / 2); float h = 1 + rand() % (int)(HEIGHT * 1.3 / 2); - shape->appendRect(x, y, w, h, rand() % 400); + shape->appendRect(x, y, w, h, 0); //LinearGradient auto fill = tvg::LinearGradient::gen(); -- 2.7.4 From add79b07cd3de40bf5a92d571224ec2ac534e30a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 1 Jul 2020 16:49:03 +0900 Subject: [PATCH 16/16] sw_engine: Draw shapes even though there is no explict closed command. This behavior is not confiremd but it's beneficial for svg spec. Change-Id: Ia711c057811ae51e472b4e164b36f3dd6af9893f --- src/lib/sw_engine/tvgSwCommon.h | 3 ++- src/lib/sw_engine/tvgSwRenderer.cpp | 8 ++++++-- src/lib/sw_engine/tvgSwShape.cpp | 24 +++++++++++++++--------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 88686b5..5db4cd7 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -264,7 +264,8 @@ SwFixed mathMean(SwFixed angle1, SwFixed angle2); void shapeReset(SwShape& shape); bool shapeGenOutline(SwShape& shape, const Shape* sdata); -bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform); +bool shapePrepare(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform); +bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip); void shapeDelOutline(SwShape& shape); void shapeResetStroke(SwShape& shape, const Shape* sdata); bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const SwSize& clip); diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index f6fc88b..b9ce7c0 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -187,8 +187,12 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* shapeReset(task->shape); uint8_t alpha = 0; task->sdata->fill(nullptr, nullptr, nullptr, &alpha); - if (alpha > 0 || task->sdata->fill() || strokeAlpha > 0) { - if (!shapeGenRle(task->shape, task->sdata, task->clip, task->transform)) return; + bool renderShape = (alpha > 0 || task->sdata->fill()); + if (renderShape || strokeAlpha > 0) { + if (!shapePrepare(task->shape, task->sdata, task->clip, task->transform)) return; + if (renderShape) { + if (!shapeGenRle(task->shape, task->sdata, task->clip)) return; + } } } //Fill diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index 1c0a09e..dbdfb6a 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -463,25 +463,31 @@ bool _fastTrack(const SwOutline* outline) /* External Class Implementation */ /************************************************************************/ -bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform) +bool shapePrepare(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform) { if (!shapeGenOutline(shape, sdata)) return false; _transformOutline(shape.outline, transform); - if (!_updateBBox(shape.outline, shape.bbox)) goto end; + if (!_updateBBox(shape.outline, shape.bbox)) return false; - if (!_checkValid(shape.outline, shape.bbox, clip)) goto end; + if (!_checkValid(shape.outline, shape.bbox, clip)) return false; + + return true; +} - //Case: Fast Track Rectangle Drawing - if ((shape.rect = _fastTrack(shape.outline))) return true; +bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip) +{ + //FIXME: Should we draw it? //Case: Stroke Line - if (shape.outline->opened) return true; + //if (shape.outline->opened) return true; + + //Case A: Fast Track Rectangle Drawing + if ((shape.rect = _fastTrack(shape.outline))) return true; + //Case B: Normale Shape RLE Drawing + if ((shape.rle = rleRender(shape.outline, shape.bbox, clip))) return true; - shape.rle = rleRender(shape.outline, shape.bbox, clip); -end: - if (shape.rle) return true; return false; } -- 2.7.4