Skip to content

Commit

Permalink
extension/window: Introduce tvg::Window based on GLFW
Browse files Browse the repository at this point in the history
Add an extension that uses GLFW-based tvg::Window.
This window has a canvas built into it.
The update() function receives a function that has tvg::Canvas as a parameter.
Users can build paint into the scene.
And call tvg::Window::loop().

Please refer to example/Window.cpp.

[APIs]
tvg::Window::gen(int width, int height, std::string name, tvg::CanvasEngine engine)
void close();
void resize(int width, int height);
void init(std::function<bool(tvg::Canvas*)> on_update);
void update(std::function<bool(tvg::Canvas*)> on_update);
static bool loop();
  • Loading branch information
JSUYA authored and capnm committed Jan 25, 2024
1 parent 823b945 commit f497a36
Show file tree
Hide file tree
Showing 11 changed files with 659 additions and 7 deletions.
28 changes: 21 additions & 7 deletions .github/workflows/build_ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ on:
- main
push:
branches:
- main
- "*"

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true

Expand All @@ -23,36 +23,49 @@ jobs:
sudo apt-get install libefl-all-dev
sudo apt-get install python3-pip
sudo apt-get install libturbojpeg0-dev libpng-dev libwebp-dev
sudo apt-get install libglew-dev libglfw3-dev
sudo pip3 install meson
- name: Build
run: |
meson setup build -Dlog=true -Dexamples=true -Dloaders="all" -Dsavers="all" -Dbindings="capi" -Dtools="all"
meson setup build -Dlog=true -Dexamples=true -Dloaders="all" -Dsavers="all" -Dbindings="capi" -Dtools="all" -Dwindows=true
sudo ninja -C build install
static_loaders:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true

- name: Install Packages
run: |
sudo apt-get update
sudo apt-get install ninja-build gcc-multilib g++-multilib
sudo apt-get install libglew-dev libglfw3-dev
sudo apt-get install python3-pip
sudo pip3 install meson
- name: Build
run: |
meson setup build -Dlog=true -Dloaders="all" -Dsavers="all" -Dbindings="capi" -Dtools="all" -Dstatic=true
meson setup --prefix=`pwd`/static --default-library static -Dlog=true -Dbuildtype=debug -Dstrip=false -Dloaders="all" -Dsavers="all" -Dbindings="capi" -Dtools="all" -Dstatic=true -Dwindows=true build .
sudo ninja -C build install
- name: Tar_files
run: |
mkdir ${{github.workspace}}/tar
ls -all
cd ${{github.workspace}}/static/ && tar -czvf ${{github.workspace}}/tar/thorvg_linux64_static.tgz *
- uses: actions/upload-artifact@v4
with:
name: horvg_linux64_static
path: ${{github.workspace}}/tar

unit_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true

Expand All @@ -64,14 +77,15 @@ jobs:
sudo apt-get install software-properties-common
sudo apt-get install python3-pip
sudo apt-get install libturbojpeg0-dev libpng-dev libwebp-dev
sudo apt-get install libglew-dev libglfw3-dev
sudo pip3 install meson
- name: Build
run: |
meson setup build -Dloaders="all" -Dsavers="all" -Dbindings="capi" -Dtests=true --errorlogs
sudo ninja -C build install test
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: UnitTestReport
path: build/meson-logs/testlog.txt
Expand Down
4 changes: 4 additions & 0 deletions inc/meson.build
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
header_files = ['thorvg.h']

if get_option('windows') == true
header_files += ['thorvg_window.h']
endif

install_headers(header_files)
61 changes: 61 additions & 0 deletions inc/thorvg_window.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*!
* @file thorvg_window.h
*
*/


#ifndef _THORVG_WINDOW_H_
#define _THORVG_WINDOW_H_

#include <functional>
#include <memory>
#include <string>
#include <list>
#include <thorvg.h>

namespace tvg
{

/**
* @class Window
*
* @brief .
*
*
* @BETA_API
*/
class TVG_API Window final
{
public:
~Window();

void close();

bool run();

void resize(int width, int height);

void init(std::function<bool(tvg::Canvas*)> on_init);

void update(std::function<bool(tvg::Canvas*)> on_update);

/**
* @brief Creates a new Window object.
*
* @return A new Window object.
*/
static std::unique_ptr<Window> gen(int width = 1, int height = 1, std::string name = "dummy", tvg::CanvasEngine engine = tvg::CanvasEngine::Sw) noexcept;

static void loop();
private:
// hmmm ....?
Window(int width, int height, std::string name, tvg::CanvasEngine engine);
_TVG_DECLARE_PRIVATE(Window);
};


/** @}*/

} //namespace

#endif //_THORVG_WINDOW_H_
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ Summary:
Tool (Svg2Tvg): @22@
Tool (Svg2Png): @23@
Tool (Lottie2Gif): @24@
tvg::Window: @25@
'''.format(
meson.project_version(),
Expand Down Expand Up @@ -186,6 +187,7 @@ Summary:
all_tools or get_option('tools').contains('svg2tvg'),
all_tools or get_option('tools').contains('svg2png'),
all_tools or get_option('tools').contains('lottie2gif'),
get_option('windows'),
)

message(summary)
5 changes: 5 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,8 @@ option('static',
type: 'boolean',
value: false,
description: 'Force to use static linking modules in thorvg')

option('windows',
type: 'boolean',
value: false,
description: 'Enable using tvg::Window based on GLFW')
183 changes: 183 additions & 0 deletions src/examples/Window.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* Copyright (c) 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include <iostream>
#include <thread>
#include <cstring>

#include <thorvg_window.h>

using namespace std;

static uint32_t WIDTH = 800;
static uint32_t HEIGHT = 800;

static unique_ptr<tvg::Window> window;
static unique_ptr<tvg::Window> window2;
static unique_ptr<tvg::Window> window3;
static unique_ptr<tvg::Window> window4;

/************************************************************************/
/* Main Code */
/************************************************************************/

int main(int argc, char **argv)
{
//Threads Count
auto threads = std::thread::hardware_concurrency();
if (threads > 0) --threads; //Allow the designated main thread capacity

//Initialize ThorVG Engine
if (tvg::Initializer::init(threads) == tvg::Result::Success) {

window = tvg::Window::gen(WIDTH, HEIGHT, "GLFW Window Example 1 (Sw)", tvg::CanvasEngine::Sw);

window->init([](tvg::Canvas* canvas) {
auto main_scene = tvg::Scene::gen();
auto shape1 = tvg::Shape::gen();
shape1->appendRect(0, 0, 200, 200); //x, y, w, h
shape1->appendRect(100, 100, 300, 300, 100, 100); //x, y, w, h, rx, ry
shape1->appendCircle(400, 400, 100, 100); //cx, cy, radiusW, radiusH
shape1->appendCircle(400, 500, 170, 100); //cx, cy, radiusW, radiusH
shape1->fill(255, 0, 0); //r, g, b
main_scene->push(std::move(shape1));
auto picture = tvg::Picture::gen();
if (picture->load(EXAMPLE_DIR"/cartman.svg") != tvg::Result::Success) {
return false;
}
picture->translate(150, 150);
picture->size(100, 100);
main_scene->push(std::move(picture));
canvas->push(std::move(main_scene));
printf("inited 1\n");
return true;
});
/*
window->update([](tvg::Canvas* canvas) {
canvas->update();
printf("updated 1\n");
return true;
});
*/
window2 = tvg::Window::gen(WIDTH, HEIGHT, "GLFW Window Example 2 (Gl)", tvg::CanvasEngine::Gl);

window2->init([](tvg::Canvas* canvas) {
auto main_scene = tvg::Scene::gen();
auto shape1 = tvg::Shape::gen();
shape1->appendRect(0, 0, 200, 200); //x, y, w, h
shape1->appendRect(100, 100, 300, 300, 100, 100); //x, y, w, h, rx, ry
shape1->appendCircle(400, 400, 100, 100); //cx, cy, radiusW, radiusH
shape1->appendCircle(400, 500, 170, 100); //cx, cy, radiusW, radiusH
shape1->fill(0, 255, 0); //r, g, b
main_scene->push(std::move(shape1));
auto picture = tvg::Picture::gen();
if (picture->load(EXAMPLE_DIR"/tiger.svg") != tvg::Result::Success) {
return false;
}
picture->translate(150, 150);
picture->size(100, 100);
main_scene->push(std::move(picture));
canvas->push(std::move(main_scene));
printf("inited 2\n");
return true;
});
/*
window2->update([](tvg::Canvas* canvas) {
canvas->update();
printf("updated 2\n");
return true;
});
*/
window3 = tvg::Window::gen(WIDTH, HEIGHT, "GLFW Window Example 3 (Gl)", tvg::CanvasEngine::Gl);

window3->init([](tvg::Canvas* canvas) {
auto main_scene = tvg::Scene::gen();
auto shape1 = tvg::Shape::gen();
shape1->appendRect(0, 0, 200, 200); //x, y, w, h
shape1->appendRect(100, 100, 300, 300, 100, 100); //x, y, w, h, rx, ry
shape1->appendCircle(400, 400, 100, 100); //cx, cy, radiusW, radiusH
shape1->appendCircle(400, 500, 170, 100); //cx, cy, radiusW, radiusH
shape1->fill(0, 255, 0); //r, g, b
main_scene->push(std::move(shape1));

auto picture = tvg::Picture::gen();
if (picture->load(EXAMPLE_DIR"/logo.svg") != tvg::Result::Success) {
return false;
}
picture->translate(150, 150);
picture->size(400, 400);
main_scene->push(std::move(picture));
canvas->push(std::move(main_scene));
printf("inited 3\n");
return true;
});
/* window3->update([](tvg::Canvas* canvas) {
canvas->update();
printf("updated 3\n");
return true;
});
*/
window4 = tvg::Window::gen(WIDTH, HEIGHT, "GLFW Window Example 4 (Sw)", tvg::CanvasEngine::Sw);

auto ani = tvg::Animation::gen();
auto animation = ani.get();//tvg::Animation::gen();
window4->init([=](tvg::Canvas* canvas) {
auto main_scene = tvg::Scene::gen();
auto shape1 = tvg::Shape::gen();
shape1->appendRect(0, 0, 200, 200); //x, y, w, h
shape1->appendRect(100, 100, 300, 300, 100, 100); //x, y, w, h, rx, ry
shape1->appendCircle(400, 400, 100, 100); //cx, cy, radiusW, radiusH
shape1->appendCircle(400, 500, 170, 100); //cx, cy, radiusW, radiusH
shape1->fill(0, 255, 0); //r, g, b
main_scene->push(std::move(shape1));

auto picture = animation->picture();
if (picture->load(EXAMPLE_DIR"/alien.json") != tvg::Result::Success) {
return false;
}
picture->translate(150, 150);
picture->size(400, 400);
canvas->push(std::move(main_scene));
canvas->push(tvg::cast<tvg::Picture>(animation->picture()));
printf("inited 4\n");
return true;
});

window4->update([=](tvg::Canvas* canvas) {
uint32_t cur = animation->curFrame();
cur = (cur + 1) % (uint32_t)animation->totalFrame();
animation->frame(cur);
canvas->update(animation->picture());
//printf("updated 4\n");
return true;
});

tvg::Window::loop();

tvg::Initializer::term();

} else {
cout << "engine is not supported" << endl;
}
return 0;
}
6 changes: 6 additions & 0 deletions src/examples/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ source_file = [
'Update.cpp',
]

if get_option('windows') == true
source_file += [
'Window.cpp',
]
endif

foreach current_file : source_file
name = current_file.split('.')[0]
executable(name, current_file,
Expand Down
7 changes: 7 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ if get_option('threads') == true and host_machine.system() != 'windows' and host
thorvg_lib_dep += [thread_dep]
endif

if get_option('windows') == true
subdir('windows')
if windows_dep.found()
thorvg_lib_dep += windows_dep
endif
endif

subdir('bindings')

thorvg_lib = library(
Expand Down
Loading

0 comments on commit f497a36

Please sign in to comment.