testRadialGradient
testGradientTransform
testSvg
+testSvg2
testAsync
testCapi
testArc
~Picture();
Result load(const std::string& path) noexcept;
+ Result load(const char* data, uint32_t size) noexcept;
Result viewbox(float* x, float* y, float* w, float* h) const noexcept;
static std::unique_ptr<Picture> gen() noexcept;
virtual ~Loader() {}
virtual bool open(const char* path) = 0;
+ virtual bool open(const char* data, uint32_t size) = 0;
virtual bool read() = 0;
virtual bool close() = 0;
virtual unique_ptr<Scene> data() = 0;
return true;
}
-unique_ptr<Loader> LoaderMgr::loader(const char* path)
+unique_ptr<Loader> LoaderMgr::loader()
{
#ifdef THORVG_SVG_LOADER_SUPPORT
return unique_ptr<SvgLoader>(new SvgLoader);
#endif
- cout << "Non supported format: " << path << endl;
return nullptr;
}
{
static bool init();
static bool term();
- static unique_ptr<Loader> loader(const char* path);
+ static unique_ptr<Loader> loader();
};
#endif //_TVG_LOADER_MGR_H_
\ No newline at end of file
}
+Result Picture::load(const char* data, uint32_t size) noexcept
+{
+ if (!data || size <= 0) return Result::InvalidArguments;
+
+ return IMPL->load(data, size);
+}
+
+
Result Picture::viewbox(float* x, float* y, float* w, float* h) const noexcept
{
if (IMPL->viewbox(x, y, w, h)) return Result::Success;
Result load(const string& path)
{
if (loader) loader->close();
- loader = LoaderMgr::loader(path.c_str());
- if (!loader || !loader->open(path.c_str())) return Result::NonSupport;
+ loader = LoaderMgr::loader();
+ if (!loader || !loader->open(path.c_str())) {
+ cout << "Non supported format: " << path.c_str() << endl;
+ return Result::NonSupport;
+ }
+ if (!loader->read()) return Result::Unknown;
+ return Result::Success;
+ }
+
+ Result load(const char* data, uint32_t size)
+ {
+ if (loader) loader->close();
+ loader = LoaderMgr::loader();
+ if (!loader || !loader->open(data, size)) {
+ cout << "Non supported load data" << endl;
+ return Result::NonSupport;
+ }
if (!loader->read()) return Result::Unknown;
return Result::Success;
}
typedef SvgStyleGradient* (*GradientFactoryMethod)(SvgLoaderData* loader, const char* buf, unsigned bufLength);
static void _freeNode(SvgNode* node);
+
static char* _skipSpace(const char* str, const char* end)
{
while (((end != nullptr && str < end) || (end == nullptr && *str != '\0')) && isspace(*str))
}
-bool SvgLoader::open(const char* path)
+bool SvgLoader::header()
{
- ifstream f;
- f.open(path);
-
- if (!f.is_open())
- {
- cout << "ERROR: Failed to open file = " << path;
- return false;
- } else {
- getline(f, content, '\0');
- f.close();
-
- if (content.empty()) return false;
- }
-
//For valid check, only <svg> tag is parsed first.
//If the <svg> tag is found, the loaded file is valid and stores viewbox information.
//After that, the remaining content data is parsed in order with async.
loaderData.svgParse = (SvgParser*)malloc(sizeof(SvgParser));
if (!loaderData.svgParse) return false;
- simpleXmlParse(content.c_str(), content.size(), true, _svgLoaderParserForValidCheck, &(loaderData));
+ simpleXmlParse(content, size, true, _svgLoaderParserForValidCheck, &(loaderData));
if (loaderData.doc && loaderData.doc->type == SvgNodeType::Doc) {
//Return the brief resource info such as viewbox:
this->vy = loaderData.doc->node.doc.vy;
this->vw = loaderData.doc->node.doc.vw;
this->vh = loaderData.doc->node.doc.vh;
-
} else {
cout << "ERROR : No SVG File. There is no <svg/>" <<endl;
return false;
}
+bool SvgLoader::open(const char* data, uint32_t size)
+{
+ this->content = data;
+ this->size = size;
+
+ return header();
+}
+
+
+bool SvgLoader::open(const char* path)
+{
+ ifstream f;
+ f.open(path);
+
+ if (!f.is_open())
+ {
+ cout << "ERROR: Failed to open file = " << path;
+ return false;
+ } else {
+ getline(f, filePath, '\0');
+ f.close();
+
+ if (filePath.empty()) return false;
+
+ this->content = filePath.c_str();
+ this->size = filePath.size();
+ }
+
+ return header();
+}
+
+
bool SvgLoader::read()
{
- if (content.empty()) return false;
+ if (!content || size == 0) return false;
loaderData = {vector<SvgNode*>(),
nullptr,
loaderData.svgParse = (SvgParser*)malloc(sizeof(SvgParser));
- if (!simpleXmlParse(content.c_str(), content.size(), true, _svgLoaderParser, &loaderData)) return false;
+ if (!simpleXmlParse(content, size, true, _svgLoaderParser, &loaderData)) return false;
if (loaderData.doc) {
_updateStyle(loaderData.doc, nullptr);
class SvgLoader : public Loader
{
private:
- string content;
+ string filePath;
+ const char* content = nullptr;
+ uint32_t size = 0;
+
SvgLoaderData loaderData;
SvgSceneBuilder builder;
unique_ptr<Scene> root;
~SvgLoader();
bool open(const char* path) override;
+ bool open(const char* data, uint32_t size) override;
+ bool header();
bool read() override;
bool close() override;
unique_ptr<Scene> data() override;
gcc -o testRadialGradient testRadialGradient.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
gcc -o testGradientTransform testGradientTransform.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
gcc -o testSvg testSvg.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
+ gcc -o testSvg2 testSvg2.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
gcc -o testAsync testAsync.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
gcc -o testArc testArc.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
gcc -o testCapi testCapi.c -g `pkg-config --cflags --libs elementary thorvg`
--- /dev/null
+#include "testCommon.h"
+
+/************************************************************************/
+/* Drawing Commands */
+/************************************************************************/
+
+static const char* svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" stroke-linejoin=\"round\" viewBox=\"50 -100 500 500\"><path fill=\"none\" stroke=\"black\" stroke-width=\"10\" d=\"M 212,220 C 197,171 156,153 123,221 109,157 120,109 159,63.6 190,114 234,115 254,89.8 260,82.3 268,69.6 270,60.3 273,66.5 275,71.6 280,75.6 286,79.5 294,79.8 300,79.8 306,79.8 314,79.5 320,75.6 325,71.6 327,66.5 330,60.3 332,69.6 340,82.3 346,89.8 366,115 410,114 441,63.6 480,109 491,157 477,221 444,153 403,171 388,220 366,188 316,200 300,248 284,200 234,188 212,220 Z\"/></svg>";
+
+
+void tvgDrawCmds(tvg::Canvas* canvas)
+{
+ if (!canvas) return;
+
+ //Background
+ auto shape = tvg::Shape::gen();
+ shape->appendRect(0, 0, WIDTH, HEIGHT, 0, 0); //x, y, w, h, rx, ry
+ shape->fill(255, 255, 255, 255); //r, g, b, a
+
+ if (canvas->push(move(shape)) != tvg::Result::Success) return;
+
+ auto picture = tvg::Picture::gen();
+ if (picture->load(svg, strlen(svg)) != tvg::Result::Success) return;
+
+ float x, y, w, h;
+ picture->viewbox(&x, &y, &w, &h);
+
+ float rate = (WIDTH/(w > h ? w : h));
+ picture->scale(rate);
+
+ x *= rate;
+ y *= rate;
+ w *= rate;
+ h *= rate;
+
+ //Center Align ?
+ if (w > h) {
+ y -= (WIDTH - h) * 0.5f;
+ } else {
+ x -= (WIDTH - w) * 0.5f;
+ }
+
+ picture->translate(-x, -y);
+
+ canvas->push(move(picture));
+}
+
+
+/************************************************************************/
+/* Sw Engine Test Code */
+/************************************************************************/
+
+static unique_ptr<tvg::SwCanvas> 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)
+{
+ if (swCanvas->draw() == tvg::Result::Success) {
+ swCanvas->sync();
+ }
+}
+
+
+/************************************************************************/
+/* GL Engine Test Code */
+/************************************************************************/
+
+static unique_ptr<tvg::GlCanvas> 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);
+ gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ gl->glClear(GL_COLOR_BUFFER_BIT);
+
+ if (glCanvas->draw() == tvg::Result::Success) {
+ glCanvas->sync();
+ }
+}
+
+
+/************************************************************************/
+/* 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
+ if (tvgEngine == tvg::CanvasEngine::Sw) {
+ cout << "tvg engine: software" << endl;
+ } else {
+ cout << "tvg engine: opengl" << endl;
+ }
+
+ //Initialize ThorVG Engine
+ if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+
+ elm_init(argc, argv);
+
+ if (tvgEngine == tvg::CanvasEngine::Sw) {
+ createSwView();
+ } else {
+ createGlView();
+ }
+
+ elm_run();
+ elm_shutdown();
+
+ //Terminate ThorVG Engine
+ tvg::Initializer::term(tvg::CanvasEngine::Sw);
+
+ } else {
+ cout << "engine is not supported" << endl;
+ }
+ return 0;
+}