├── src
├── soname.txt
├── .clang-tidy
├── makefile
└── svgren
│ ├── config.hxx
│ ├── surface.cpp
│ ├── surface.hxx
│ ├── filter_applier.hxx
│ ├── render.hpp
│ ├── util.hxx
│ ├── render.cpp
│ ├── renderer.hxx
│ └── util.cpp
├── .gitignore
├── .clang-tidy
├── .clang-format
├── config
├── default.mk
├── dev.mk
├── asan.mk
├── lint.mk
├── dbg.mk
├── gcov.mk
├── emsc.mk
├── base
│ └── base.mk
└── rel.mk
├── makefile
├── .gitattributes
├── wiki
├── camera.png
├── building.adoc
├── features.adoc
├── usages.adoc
├── main.adoc
└── usage.adoc
├── tests
├── makefile
├── unit
│ ├── samples_data
│ │ ├── expected
│ │ │ ├── 1.png
│ │ │ ├── 3.png
│ │ │ ├── arc.png
│ │ │ ├── car.png
│ │ │ ├── use.png
│ │ │ ├── 0.451.png
│ │ │ ├── 3.072.png
│ │ │ ├── back.png
│ │ │ ├── lines.png
│ │ │ ├── mouse.png
│ │ │ ├── test2.png
│ │ │ ├── tiger.png
│ │ │ ├── 3color.png
│ │ │ ├── FW5-24V.png
│ │ │ ├── caltrain.png
│ │ │ ├── camera.png
│ │ │ ├── circle.png
│ │ │ ├── circle1.png
│ │ │ ├── ellipse.png
│ │ │ ├── gradtest.png
│ │ │ ├── granddad.png
│ │ │ ├── masking.png
│ │ │ ├── opacity.png
│ │ │ ├── sample1.png
│ │ │ ├── sample2.png
│ │ │ ├── sample3.png
│ │ │ ├── sample4.png
│ │ │ ├── six_ball.png
│ │ │ ├── SPHERE_GSP.png
│ │ │ ├── VOLUME_GSP.png
│ │ │ ├── composite.png
│ │ │ ├── cover_test.png
│ │ │ ├── defs_style.png
│ │ │ ├── instagram.png
│ │ │ ├── menue-cut.png
│ │ │ ├── quadratic.png
│ │ │ ├── rectangle.png
│ │ │ ├── visibility.png
│ │ │ ├── SPHERE_S_GSP.png
│ │ │ ├── css_simple0.png
│ │ │ ├── cubic_smooth.png
│ │ │ ├── dashoffset1.png
│ │ │ ├── default_black.png
│ │ │ ├── defs_style_2.png
│ │ │ ├── group_opacity.png
│ │ │ ├── menue-search.png
│ │ │ ├── rgb_percent.png
│ │ │ ├── invisible_rect.png
│ │ │ ├── linear_gradient.png
│ │ │ ├── radial_gradient.png
│ │ │ ├── dropshadowfilter.png
│ │ │ ├── gauge_arrow_shadow.png
│ │ │ ├── interface-ethernet.png
│ │ │ ├── radial_gradient_2.png
│ │ │ ├── Customs-Ground_Level.png
│ │ │ ├── Turntable-Active-NEW5.png
│ │ │ ├── machupicchu_collection_01.png
│ │ │ ├── machupicchu_collection_02.png
│ │ │ ├── machupicchu_collection_04.png
│ │ │ ├── machupicchu_collection_06.png
│ │ │ ├── tiger_with_smooth_cubic_curves.png
│ │ │ ├── gradient-transform-rotate-compare.png
│ │ │ ├── percentage_dimensions_and_viewbox.png
│ │ │ └── Pioneer_all_vector_720_wo_bg_inkscape.png
│ │ ├── circle.svg
│ │ ├── ellipse.svg
│ │ ├── circle1.svg
│ │ ├── group_opacity.svg
│ │ ├── opacity.svg
│ │ ├── rectangle.svg
│ │ ├── 3color.svg
│ │ ├── css_simple0.svg
│ │ ├── masking.svg
│ │ ├── 3.svg
│ │ ├── six_ball.svg
│ │ ├── use.svg
│ │ ├── sample2.svg
│ │ ├── default_black.svg
│ │ ├── invisible_rect.svg
│ │ ├── percentage_dimensions_and_viewbox.svg
│ │ ├── lines.svg
│ │ ├── defs_style.svg
│ │ ├── dashoffset1.svg
│ │ ├── arc.svg
│ │ ├── cubic_smooth.svg
│ │ ├── rgb_percent.svg
│ │ ├── defs_style_2.svg
│ │ ├── gradtest.svg
│ │ ├── radial_gradient_2.svg
│ │ ├── gradient-transform-rotate-compare.svg
│ │ ├── caltrain.svg
│ │ ├── menue-cut.svg
│ │ ├── visibility.svg
│ │ ├── menue-search.svg
│ │ ├── linear_gradient.svg
│ │ ├── quadratic.svg
│ │ ├── sample3.svg
│ │ ├── radial_gradient.svg
│ │ ├── interface-ethernet.svg
│ │ ├── gauge_arrow_shadow.svg
│ │ ├── mouse.svg
│ │ ├── instagram.svg
│ │ ├── dropshadowfilter.svg
│ │ ├── composite.svg
│ │ ├── sample1.svg
│ │ ├── sample4.svg
│ │ ├── cover_test.svg
│ │ └── SPHERE_S_GSP.svg
│ ├── render_dims.cpp
│ ├── makefile
│ └── samples.cpp
├── async
│ ├── makefile
│ └── main.cpp
└── render
│ ├── makefile
│ └── main.cpp
├── .github
└── FUNDING.yml
├── .gitmodules
├── pkg-config
├── makefile
└── svgren.pc.in
├── doc
└── makefile
├── README.adoc
├── LICENSE
└── .vscode
├── launch.json
└── tasks.json
/src/soname.txt:
--------------------------------------------------------------------------------
1 | 0
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/out/*
2 |
--------------------------------------------------------------------------------
/.clang-tidy:
--------------------------------------------------------------------------------
1 | tool-configs/clang-tidy/.clang-tidy
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | tool-configs/clang-format/.clang-format
--------------------------------------------------------------------------------
/config/default.mk:
--------------------------------------------------------------------------------
1 | $(eval $(call prorab-config-default, rel))
2 |
--------------------------------------------------------------------------------
/makefile:
--------------------------------------------------------------------------------
1 | include prorab.mk
2 |
3 | $(eval $(prorab-include-subdirs))
4 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # disable line endings conversion for all files
2 | * -text
3 |
--------------------------------------------------------------------------------
/wiki/camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/wiki/camera.png
--------------------------------------------------------------------------------
/tests/makefile:
--------------------------------------------------------------------------------
1 | include prorab.mk
2 |
3 | $(eval $(prorab-include-subdirs))
4 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [igagis]
2 | patreon: igagis
3 | custom: ["https://paypal.me/igagis"]
4 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "tool-configs"]
2 | path = tool-configs
3 | url = ../tool-configs
4 | branch = main
5 |
--------------------------------------------------------------------------------
/config/dev.mk:
--------------------------------------------------------------------------------
1 | include $(config_dir)base/base.mk
2 |
3 | this_cxxflags += -DDEBUG
4 | this_cxxflags += -O0
5 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/1.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/3.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/arc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/arc.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/car.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/use.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/use.png
--------------------------------------------------------------------------------
/config/asan.mk:
--------------------------------------------------------------------------------
1 | include $(config_dir)rel.mk
2 |
3 | this_cxxflags += -fsanitize=address
4 | this_ldflags += -fsanitize=address
5 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/0.451.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/0.451.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/3.072.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/3.072.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/back.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/lines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/lines.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/mouse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/mouse.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/test2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/test2.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/tiger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/tiger.png
--------------------------------------------------------------------------------
/config/lint.mk:
--------------------------------------------------------------------------------
1 | include $(config_dir)dev.mk
2 |
3 | this_lint_cmd = $(prorab_lint_cmd_clang_tidy)
4 | this_no_format_test := false
5 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/3color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/3color.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/FW5-24V.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/FW5-24V.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/caltrain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/caltrain.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/camera.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/circle.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/circle1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/circle1.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/ellipse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/ellipse.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/gradtest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/gradtest.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/granddad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/granddad.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/masking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/masking.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/opacity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/opacity.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/sample1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/sample1.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/sample2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/sample2.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/sample3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/sample3.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/sample4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/sample4.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/six_ball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/six_ball.png
--------------------------------------------------------------------------------
/src/.clang-tidy:
--------------------------------------------------------------------------------
1 | # TODO: remove when moved to C++20
2 | Checks: |
3 | -modernize-use-designated-initializers
4 | InheritParentConfig: true
5 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/SPHERE_GSP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/SPHERE_GSP.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/VOLUME_GSP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/VOLUME_GSP.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/composite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/composite.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/cover_test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/cover_test.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/defs_style.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/defs_style.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/instagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/instagram.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/menue-cut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/menue-cut.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/quadratic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/quadratic.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/rectangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/rectangle.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/visibility.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/visibility.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/SPHERE_S_GSP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/SPHERE_S_GSP.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/css_simple0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/css_simple0.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/cubic_smooth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/cubic_smooth.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/dashoffset1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/dashoffset1.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/default_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/default_black.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/defs_style_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/defs_style_2.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/group_opacity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/group_opacity.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/menue-search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/menue-search.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/rgb_percent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/rgb_percent.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/invisible_rect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/invisible_rect.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/linear_gradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/linear_gradient.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/radial_gradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/radial_gradient.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/dropshadowfilter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/dropshadowfilter.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/gauge_arrow_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/gauge_arrow_shadow.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/interface-ethernet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/interface-ethernet.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/radial_gradient_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/radial_gradient_2.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/Customs-Ground_Level.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/Customs-Ground_Level.png
--------------------------------------------------------------------------------
/pkg-config/makefile:
--------------------------------------------------------------------------------
1 | include prorab.mk
2 | include prorab-pkg-config.mk
3 |
4 | this_version := $(shell myci-deb-version.sh)
5 |
6 | $(eval $(prorab-pkg-config))
7 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/Turntable-Active-NEW5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/Turntable-Active-NEW5.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/machupicchu_collection_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/machupicchu_collection_01.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/machupicchu_collection_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/machupicchu_collection_02.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/machupicchu_collection_04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/machupicchu_collection_04.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/machupicchu_collection_06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/machupicchu_collection_06.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/tiger_with_smooth_cubic_curves.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/tiger_with_smooth_cubic_curves.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/gradient-transform-rotate-compare.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/gradient-transform-rotate-compare.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/percentage_dimensions_and_viewbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/percentage_dimensions_and_viewbox.png
--------------------------------------------------------------------------------
/tests/unit/samples_data/expected/Pioneer_all_vector_720_wo_bg_inkscape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cppfw/svgren/HEAD/tests/unit/samples_data/expected/Pioneer_all_vector_720_wo_bg_inkscape.png
--------------------------------------------------------------------------------
/doc/makefile:
--------------------------------------------------------------------------------
1 | include prorab.mk
2 | include prorab-doxygen.mk
3 |
4 | this_out_dir := out
5 | this_name := svgren
6 | this_version := $(shell myci-deb-version.sh)
7 |
8 | $(eval $(prorab-build-doxygen))
9 |
--------------------------------------------------------------------------------
/config/dbg.mk:
--------------------------------------------------------------------------------
1 | include $(config_dir)base/base.mk
2 |
3 | this_cxxflags += -DDEBUG
4 | this_cxxflags += -O0
5 |
6 | this_dbg := -dbg
7 |
8 | # do not install headers
9 | this_install_hdrs := $(prorab_space)
10 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/circle.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/ellipse.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/pkg-config/svgren.pc.in:
--------------------------------------------------------------------------------
1 | Name: svgren # human-readable name
2 | Description: SVG rendering C++ library # human-readable description
3 | Version: $(version)
4 | URL: https://github.com/cppfw/svgren
5 | Requires:
6 | Conflicts:
7 | Libs: -lsvgren
8 | Libs.private:
9 | Cflags:
10 |
--------------------------------------------------------------------------------
/config/gcov.mk:
--------------------------------------------------------------------------------
1 | include $(config_dir)base/base.mk
2 |
3 | # no optimization to avoid mismamtch of actual code to source lines,
4 | # otherwise coverage report will not be accurate
5 | this_cxxflags += -O0
6 |
7 | this_cxxflags += -ftest-coverage
8 | this_cxxflags += -fprofile-arcs
9 |
10 | this_ldflags += --coverage
11 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/circle1.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wiki/building.adoc:
--------------------------------------------------------------------------------
1 | = Building in Linux
2 |
3 | == Installing build dependencies
4 |
5 | First of all one needs to install all the software packages needed for building.
6 | The list of needed packages can be seen in `build/debian/control.in` files's `Build-Depends:` section.
7 |
8 | == Building
9 |
10 | Building is easy, just use `make`.
11 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/group_opacity.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/opacity.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/wiki/features.adoc:
--------------------------------------------------------------------------------
1 | = SVG features
2 |
3 | **svgren** is supposed to conform to https://www.w3.org/TR/SVG11/[SVG 1.1] specification except some features.
4 |
5 | == Features not planned to support
6 |
7 | - Animation
8 | - Interactivity
9 |
10 | == List of some supported features
11 |
12 | - all gradient kinds (linear, radial)
13 | - group opacity
14 | - all shape kinds
15 | - all path elements
16 | - gaussian blur effect
17 | - masking
18 | - built-in CSS
19 |
--------------------------------------------------------------------------------
/wiki/usages.adoc:
--------------------------------------------------------------------------------
1 | = Projects using svgren
2 |
3 | . link:https://www.sae-it.com/en/products/software/setit-configuration-tool.html[setIT configuration tool] by link:https://www.sae-it.com[SAE it-systems]
4 | . link:https://play.google.com/store/apps/details?id=com.symbolicone.ouille[Speech therapy app] for Android.
5 | . link:https://transitapp.com[Commuting trip planning app] for iOS.
6 | . link:https://www.image-line.com/fl-studio/[Fruity Loops Studio] for Windows and MacOS.
7 | . Add your project
8 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/rectangle.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/config/emsc.mk:
--------------------------------------------------------------------------------
1 | include $(config_dir)base/base.mk
2 |
3 | this_cxxflags += -O3
4 |
5 | this_cxx := em++
6 | this_cc := emcc
7 | this_ar := emar
8 |
9 | this_static_lib_only := true
10 |
11 | # TODO: remove the warning suppression when the PR is merged
12 | # Suppress version-check warning due to https://github.com/conan-io/conan-center-index/pull/26247
13 | this_cxxflags += -Wno-version-check
14 |
15 | this_cxxflags += -fwasm-exceptions
16 | this_ldflags += -fwasm-exceptions
17 |
18 | this_cxxflags += -pthread
19 | this_ldflags += -pthread
--------------------------------------------------------------------------------
/tests/unit/samples_data/3color.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/css_simple0.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/masking.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/config/base/base.mk:
--------------------------------------------------------------------------------
1 | this_cxxflags += -Wall # enable all warnings
2 | this_cxxflags += -Wnon-virtual-dtor # warn if base class has non-virtual destructor
3 | this_cxxflags += -Werror # warnings as errors
4 | this_cxxflags += -Wfatal-errors # stop on first error encountered
5 | this_cxxflags += -fstrict-aliasing # in order to comply with the c++ standard more strictly
6 | this_cxxflags += -std=c++17
7 | this_cxxflags += -g
8 | this_cxxflags += -fPIC
9 |
10 | this_ldlibs += -lstdc++
11 |
12 | this_no_format_test := true
13 |
14 | ifeq ($(gprof), true)
15 | this_cxxflags += -pg
16 | this_ldflags += -pg
17 | endif
18 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/3.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/six_ball.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/use.svg:
--------------------------------------------------------------------------------
1 |
2 |
19 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/sample2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/default_black.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/invisible_rect.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/percentage_dimensions_and_viewbox.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/tests/async/makefile:
--------------------------------------------------------------------------------
1 | include prorab.mk
2 | include prorab-test.mk
3 |
4 | $(eval $(call prorab-config, ../../config))
5 |
6 | this_name := tests
7 |
8 | this_srcs += main.cpp
9 |
10 | this_ldlibs += -l svgdom$(this_dbg)
11 | this_ldlibs += -l fsif$(this_dbg)
12 | this_ldlibs += -l utki$(this_dbg)
13 | this_ldlibs += -l png
14 | this_ldlibs += -l pthread
15 |
16 | this_ldlibs += ../../src/out/$(c)/libsvgren$(this_dbg)$(dot_so)
17 |
18 | this_no_install := true
19 |
20 | $(eval $(prorab-build-app))
21 |
22 | this_test_cmd := $(prorab_this_name) $(shell ls $(d)../unit/samples_data/*.svg)
23 | this_test_deps := $(prorab_this_name)
24 | this_test_ld_path := ../../src/out/$(c)
25 | $(eval $(prorab-test))
26 |
27 | $(eval $(call prorab-include, ../../src/makefile))
28 |
--------------------------------------------------------------------------------
/tests/unit/render_dims.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 |
6 | #include "../../src/svgren/render.hpp"
7 |
8 | #ifdef assert
9 | # undef assert
10 | #endif
11 |
12 | namespace{
13 | const tst::set set("render_dims", [](tst::suite& suite){
14 | suite.add(
15 | "requested_dimensions",
16 | [](){
17 | auto dom = svgdom::load(fsif::native_file("samples_data/camera.svg"));
18 |
19 | utki::assert(dom, SL);
20 |
21 | svgren::parameters p;
22 | // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
23 | p.dims_request = decltype(p.dims_request){10, 10};
24 | auto res = svgren::rasterize(*dom, p);
25 |
26 | utki::assert(res.dims() == p.dims_request, SL);
27 | }
28 | );
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/wiki/main.adoc:
--------------------------------------------------------------------------------
1 | = WiKi main page
2 |
3 | == Supported/unsupported SVG features
4 | See link:features.adoc[Features] page.
5 |
6 | == Installation
7 | :package_name: svgren
8 |
9 | . Setup your OS-preferred package system repo following link:https://github.com/cppfw/wiki/blob/main/enable_repo/enable_repo.adoc[this manual]
10 | . Install package
11 | +
12 | - **vcpkg** (multi-OS): `{package_name}`
13 | - **conan** (multi-OS): `{package_name}`
14 | - **deb** (Linux): `lib{package_name}-dev`
15 | - **homebrew** (MacOS X): `lib{package_name}`
16 | - **android**: `io.github.cppfw:{package_name}`
17 | - **msys2** (Windows): `mingw-w64-i686-{package_name}`, `mingw-w64-x86_64-{package_name}`
18 |
19 | == Tutorials
20 | - link:usage.adoc[Basic usage tutorial]
21 |
22 | == Building
23 | - link:building.adoc[Linux]
24 |
--------------------------------------------------------------------------------
/config/rel.mk:
--------------------------------------------------------------------------------
1 | include $(config_dir)base/base.mk
2 |
3 | # TODO: use -O3 when https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105651 is fixed in debian bookworm
4 | this_cxxflags += -O2
5 |
6 | # WORKAROUND: on ubuntu jammy dpkg-buildpackage passes -ffat-lto-objects compilation flag
7 | # which is not supported by clang and clang-tidy complains about it:
8 | # error: optimization flag '-ffat-lto-objects' is not supported [clang-diagnostic-ignored-optimization-argument]
9 | # Thus, suppress this warning.
10 | this_cxxflags += -Wno-ignored-optimization-argument
11 |
12 | ifeq ($(os),macosx)
13 | # WORKAROUND:
14 | # clang-tidy on macos doesn't use /usr/local/include as default place to
15 | # search for header files, so we add it explicitly
16 | this_cxxflags += -isystem /usr/local/include
17 | endif
18 |
--------------------------------------------------------------------------------
/src/makefile:
--------------------------------------------------------------------------------
1 | include prorab.mk
2 | include prorab-license.mk
3 | include prorab-clang-format.mk
4 | include prorab-install-dbgsrc.mk
5 |
6 | $(eval $(call prorab-config, ../config))
7 |
8 | this_src_dir := svgren
9 |
10 | this_name := $(this_src_dir)$(this_dbg)
11 |
12 | this_soname := $(shell cat $(d)soname.txt)
13 |
14 | this_srcs := $(call prorab-src-dir, $(this_src_dir))
15 |
16 | # this_cxxflags += -D SVGREN_BACKGROUND=0xffffffff
17 | # this_cxxflags += -D SVGREN_BACKGROUND=0xff00ffff
18 |
19 | this_ldlibs += -l veg$(this_dbg)
20 | this_ldlibs += -l svgdom$(this_dbg)
21 | this_ldlibs += -l utki$(this_dbg)
22 |
23 | this_ldlibs += -l m
24 |
25 | $(eval $(prorab-build-lib))
26 |
27 | this_license_file := ../LICENSE
28 | $(eval $(prorab-license))
29 |
30 | $(eval $(prorab-clang-format))
31 |
32 | $(eval $(prorab-install-dbgsrc))
33 |
--------------------------------------------------------------------------------
/tests/unit/makefile:
--------------------------------------------------------------------------------
1 | include prorab.mk
2 | include prorab-test.mk
3 |
4 | $(eval $(call prorab-config, ../../config))
5 |
6 | this_name := tests
7 |
8 | this_srcs += $(call prorab-src-dir, .)
9 |
10 | this_ldlibs += -l svgdom$(this_dbg)
11 | this_ldlibs += -l fsif$(this_dbg)
12 | this_ldlibs += -l utki$(this_dbg)
13 | this_ldlibs += -l tst$(this_dbg)
14 | this_ldlibs += -l rasterimage$(this_dbg)
15 |
16 | this_ldlibs += ../../src/out/$(c)/libsvgren$(this_dbg)$(dot_so)
17 |
18 | this_ldlibs += -l png
19 | this_ldlibs += -l m
20 |
21 | this_no_install := true
22 |
23 | $(eval $(prorab-build-app))
24 |
25 | this_test_cmd := $(prorab_this_name) --junit-out=out/$(c)/junit.xml
26 | this_test_deps := $(prorab_this_name)
27 | this_test_ld_path := ../../src/out/$(c)
28 | $(eval $(prorab-test))
29 |
30 | $(eval $(call prorab-include, ../../src/makefile))
31 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/lines.svg:
--------------------------------------------------------------------------------
1 |
27 |
--------------------------------------------------------------------------------
/README.adoc:
--------------------------------------------------------------------------------
1 | :name: svgren
2 |
3 | = {name}
4 |
5 | |====
6 | | link:https://github.com/cppfw/{name}/releases[image:https://img.shields.io/github/tag/cppfw/{name}.svg[releases]] | link:https://github.com/cppfw/{name}/actions[image:https://github.com/cppfw/{name}/workflows/ci/badge.svg[ci status]] | link:https://codecov.io/gh/cppfw/{name}/tree/main[image:https://codecov.io/gh/cppfw/{name}/branch/main/graph/badge.svg?token=vwqhr1CujV[codecov.io]]
7 | |====
8 |
9 | SVG renderer library in C++.
10 |
11 | image:wiki/camera.png[image sample]
12 |
13 | **{name}** uses **link:https://github.com/cppfw/svgdom[svgdom]** to read the SVG file and **link:http://github.com/cppfw/agg[AGG]** to render graphics.
14 |
15 | = Installation and Tutorials
16 | Read link:wiki/main.adoc[WiKi] for installation instructions and tutorials.
17 |
18 | = Projects using {name}
19 | link:wiki/usages.adoc[See list here].
20 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/defs_style.svg:
--------------------------------------------------------------------------------
1 |
2 |
18 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/dashoffset1.svg:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/arc.svg:
--------------------------------------------------------------------------------
1 |
2 |
24 |
--------------------------------------------------------------------------------
/tests/async/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "../../src/svgren/render.hpp"
5 |
6 | #include
7 |
8 | // NOLINTNEXTLINE(bugprone-exception-escape, "we need exceptions from main() to indicate test failure")
9 | int main(int argc, const char** argv) {
10 | if(argc < 2){
11 | std::cerr << "at least 1 argument expected (SVG filename)" << std::endl;
12 | return 1;
13 | }
14 |
15 | std::vector> svgs;
16 |
17 | for(const char* arg : utki::make_span(std::next(argv), argc - 1)){
18 | svgs.push_back(svgdom::load(fsif::native_file(arg)));
19 | }
20 |
21 | std::vector threads;
22 |
23 | for(auto& svg : svgs){
24 | decltype(svg.get()) s = svg.get();
25 | threads.emplace_back(
26 | [s](){
27 | auto res = svgren::rasterize(*s);
28 | utki::log([&](auto&o){o << "rendered, width = " << res.dims().x() << std::endl;});
29 | }
30 | );
31 | }
32 |
33 | for(auto& t : threads){
34 | t.join();
35 | }
36 |
37 | return 0;
38 | }
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015-2024 Ivan Gagis
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/cubic_smooth.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
24 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/rgb_percent.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/defs_style_2.svg:
--------------------------------------------------------------------------------
1 |
2 |
22 |
--------------------------------------------------------------------------------
/tests/render/makefile:
--------------------------------------------------------------------------------
1 | include prorab.mk
2 | include prorab-test.mk
3 |
4 | $(eval $(call prorab-config, ../../config))
5 |
6 | this_name := tests
7 |
8 | this_srcs += main.cpp
9 |
10 | this_ldlibs += -l svgdom$(this_dbg)
11 | this_ldlibs += -l rasterimage$(this_dbg)
12 | this_ldlibs += -l fsif$(this_dbg)
13 | this_ldlibs += -l utki$(this_dbg)
14 |
15 | this_ldlibs += -l png
16 | this_ldlibs += -l m
17 |
18 | this_ldlibs += ../../src/out/$(c)/libsvgren$(this_dbg)$(dot_so)
19 |
20 | ifeq ($(os), macosx)
21 | else ifeq ($(os),windows)
22 | else
23 | this_ldlibs += -l X11
24 | endif
25 |
26 | this_no_install := true
27 |
28 | $(eval $(prorab-build-app))
29 |
30 | # TODO: use prorab-run
31 | ifeq ($(os),windows)
32 | this_run_cmd := $(a)cp $(d)../../src/out/$(c)/libsvgren$(dot_so) $(d) && $$^)
33 | else
34 | this_run_cmd := $(a)(cd $(d); LD_LIBRARY_PATH=../../src/out/$(c) $$^)
35 | endif
36 |
37 | define this_rules
38 | run:: $(prorab_this_name)
39 | $(.RECIPEPREFIX)@echo running $$^...
40 | $(.RECIPEPREFIX)$(a)cp $(d)../../src/out/$(c)/libsvgren$(dot_so) . || true
41 | $(.RECIPEPREFIX)$(a)LD_LIBRARY_PATH=$(d)../../src/out/$(c) $(d)out/$(c)/tests $(d)../samples/testdata/tiger.svg $(d)out.png
42 | endef
43 | $(eval $(this_rules))
44 |
45 | $(eval $(call prorab-include, ../../src/makefile))
46 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/gradtest.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wiki/usage.adoc:
--------------------------------------------------------------------------------
1 | = Basic usage tutorial
2 |
3 | Please note, that **svgren** uses C++'17 features.
4 |
5 | First of all we need to include the **svgren** header file
6 |
7 | [source,c++]
8 | ....
9 | #include
10 | #include // we will need this to load the SVG file
11 | ....
12 |
13 | Then we need to load the SVG file and create the document object model (DOM), let's load the file called **camera.svg**
14 |
15 | [source,c++]
16 | ....
17 | auto dom = svgdom::load(fsif::native_file("camera.svg"));
18 | ....
19 |
20 | Then we just render the SVG into a memory buffer
21 |
22 | [source,c++]
23 | ....
24 | auto result = svgren::render(*dom);
25 | // returned 'result.pixels' is a std::vector holding array of RGBA values.
26 | ....
27 |
28 | If SVG document specifies any coordiantes or lengthes in physical units, like milimeters or centimeters or inches,
29 | we have to supply the dots per inch (DPI) value of our physical display to the svgren::render() function. This is done using the `svgren::parameters` structure
30 |
31 | [source,c++]
32 | ....
33 | svgren::parameters p;
34 | p.dpi = 240; // pixel density of target physical display is 240 dpi
35 | p.dims_request.x() = 0; // 0 means use width from SVG document
36 | p.dims_request.y() = 0; // 0 means use height from SVG document
37 | auto result = svgren::render(*dom, p);
38 | ....
39 |
40 | After that one can use the rendered image data to display it on any physical display or whatever.
41 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/radial_gradient_2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
34 |
--------------------------------------------------------------------------------
/src/svgren/config.hxx:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2024 Ivan Gagis
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | */
25 |
26 | /* ================ LICENSE END ================ */
27 |
28 | #pragma once
29 |
30 | #include
31 | #include
32 |
33 | namespace svgren {
34 |
35 | using real = svgdom::real;
36 |
37 | // TODO: take these types from veg
38 | using image_type = rasterimage::image;
39 | using image_span_type = decltype(std::declval().span());
40 |
41 | } // namespace svgren
42 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/gradient-transform-rotate-compare.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/caltrain.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Page 1
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/menue-cut.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/visibility.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/menue-search.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/svgren/surface.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2024 Ivan Gagis
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | */
25 |
26 | /* ================ LICENSE END ================ */
27 |
28 | #include "surface.hxx"
29 |
30 | #include
31 |
32 | using namespace svgren;
33 |
34 | surface surface::intersection(const r4::rectangle& r)
35 | {
36 | auto ret_rect = r4::rectangle(this->rect()).intersect(r);
37 |
38 | ASSERT(ret_rect.d.y() <= r.d.y(), [&](auto& o) {
39 | o << "ret_rect = " << ret_rect << " this->rect() = " << this->rect() << " r = " << r;
40 | })
41 |
42 | if (ret_rect.d.is_any_zero()) {
43 | // resulting surface is of zero size
44 | return {};
45 | }
46 |
47 | ASSERT(this->rect().contains(ret_rect))
48 |
49 | return {
50 | ret_rect.p, //
51 | this->image_span.subspan({ret_rect.p - this->position, ret_rect.d})
52 | };
53 | }
54 |
--------------------------------------------------------------------------------
/src/svgren/surface.hxx:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2024 Ivan Gagis
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | */
25 |
26 | /* ================ LICENSE END ================ */
27 |
28 | #pragma once
29 |
30 | #include
31 |
32 | #include
33 | #include
34 | #include
35 |
36 | #include "config.hxx"
37 |
38 | namespace svgren {
39 |
40 | struct surface {
41 | r4::vector2 position = 0;
42 | image_span_type image_span;
43 |
44 | surface() = default;
45 |
46 | surface(image_span_type image_span) :
47 | position(0),
48 | image_span(image_span)
49 | {}
50 |
51 | surface(r4::vector2 position, image_span_type image_span) :
52 | position(position),
53 | image_span(image_span)
54 | {}
55 |
56 | r4::rectangle rect() const noexcept
57 | {
58 | return {this->position, this->image_span.dims()};
59 | }
60 |
61 | surface intersection(const r4::rectangle& r);
62 | };
63 |
64 | } // namespace svgren
65 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/linear_gradient.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 | Example lingrad01 - fill a rectangle using a
7 | linear gradient paint server
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
31 |
32 |
34 |
36 |
38 |
40 |
41 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/quadratic.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 | Example quad01 - quadratic Bézier commands in path data
7 | Picture showing a "Q" a "T" command,
8 | along with annotations showing the control points
9 | and end points
10 |
12 |
13 |
15 |
16 |
18 |
19 |
21 |
22 |
24 |
25 |
27 |
28 |
30 |
31 |
33 |
34 |
36 |
37 |
39 |
40 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
61 |
62 |
--------------------------------------------------------------------------------
/src/svgren/filter_applier.hxx:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2024 Ivan Gagis
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | */
25 |
26 | /* ================ LICENSE END ================ */
27 |
28 | #pragma once
29 |
30 | #include
31 |
32 | #include "renderer.hxx"
33 |
34 | namespace svgren {
35 |
36 | struct filter_result {
37 | image_type image;
38 | svgren::surface surface;
39 |
40 | filter_result(r4::rectangle surface_rect) :
41 | image(surface_rect.d),
42 | surface(
43 | surface_rect.p, //
44 | this->image.span()
45 | )
46 | {}
47 | };
48 |
49 | class filter_applier : public svgdom::const_visitor
50 | {
51 | renderer& r;
52 |
53 | // TODO: naming convention
54 | decltype(svgdom::filter_element::primitive_units) primitiveUnits = svgdom::coordinate_units::user_space_on_use;
55 |
56 | r4::rectangle filterRegion = {0, std::numeric_limits::max()};
57 |
58 | std::map results;
59 |
60 | filter_result* lastResult = nullptr;
61 |
62 | surface get_source(const std::string& in);
63 | void set_result(const std::string& name, filter_result&& result);
64 |
65 | surface get_source_graphic();
66 |
67 | public:
68 | surface get_last_result();
69 |
70 | filter_applier(renderer& r) :
71 | r(r)
72 | {}
73 |
74 | void visit(const svgdom::filter_element& e) override;
75 |
76 | void visit(const svgdom::fe_gaussian_blur_element& e) override;
77 | void visit(const svgdom::fe_color_matrix_element& e) override;
78 | void visit(const svgdom::fe_blend_element& e) override;
79 | void visit(const svgdom::fe_composite_element& e) override;
80 | };
81 |
82 | } // namespace svgren
83 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/sample3.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/svgren/render.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2024 Ivan Gagis
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | */
25 |
26 | /* ================ LICENSE END ================ */
27 |
28 | #pragma once
29 |
30 | #include
31 | #include
32 | #include
33 |
34 | namespace svgren {
35 |
36 | using image_type = rasterimage::image;
37 |
38 | /**
39 | * @brief SVG render parameters.
40 | */
41 | struct parameters {
42 | /**
43 | * @brief Width and height request for the resulting raster image.
44 | * If width request is set to 0 then the width will be adjusted to preserve
45 | * aspect ratio of the SVG image or determined from the SVG root element if
46 | * height request is also set to zero. Same works for height request.
47 | */
48 | r4::vector2 dims_request = 0;
49 |
50 | constexpr static auto default_dpi = 96;
51 |
52 | /**
53 | * @brief Dots per inch to use for unit conversion to pixels.
54 | */
55 | unsigned dpi = default_dpi;
56 | };
57 |
58 | /**
59 | * @brief SVG image rendering result.
60 | */
61 | struct result {
62 | /**
63 | * @brief Array of pixels.
64 | */
65 | std::vector pixels;
66 |
67 | /**
68 | * @brief Resulting width and height of the raster image.
69 | */
70 | r4::vector2 dims = 0;
71 | };
72 |
73 | /**
74 | * @brief Render SVG image to raster image.
75 | * @param svg - the SVG document object model to render.
76 | * @param p - render parameters.
77 | * @return Rendering result.
78 | */
79 | [[deprecated("use rasterize()")]] result render(const svgdom::svg_element& svg, const parameters& p = parameters());
80 |
81 | /**
82 | * @brief Create raster image from given SVG DOM.
83 | * @param svg - SVG DOM to rasterize.
84 | * @param params - rasterization parameters.
85 | * @return Raster image of the SVG.
86 | */
87 | image_type rasterize(const svgdom::svg_element& svg, const parameters& params = parameters());
88 |
89 | } // namespace svgren
90 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/radial_gradient.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/interface-ethernet.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/gauge_arrow_shadow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
21 |
29 |
33 |
34 |
35 |
58 |
60 |
61 |
63 | image/svg+xml
64 |
66 |
67 |
68 |
69 |
70 |
75 |
82 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/mouse.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/svgren/util.hxx:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2024 Ivan Gagis
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | */
25 |
26 | /* ================ LICENSE END ================ */
27 |
28 | #pragma once
29 |
30 | #include
31 | #include
32 |
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 |
40 | #include "veg/util.hpp"
41 |
42 | #include "config.hxx"
43 | #include "surface.hxx"
44 |
45 | namespace svgren {
46 |
47 | real percent_to_fraction(const svgdom::length& l);
48 |
49 | class renderer_viewport_push
50 | {
51 | class renderer& r;
52 | r4::vector2 old_viewport;
53 |
54 | public:
55 | renderer_viewport_push(renderer& r, const decltype(old_viewport)& viewport);
56 |
57 | renderer_viewport_push(const renderer_viewport_push&) = delete;
58 | renderer_viewport_push& operator=(const renderer_viewport_push&) = delete;
59 |
60 | renderer_viewport_push(renderer_viewport_push&&) = delete;
61 | renderer_viewport_push& operator=(renderer_viewport_push&&) = delete;
62 |
63 | ~renderer_viewport_push() noexcept;
64 | };
65 |
66 | class common_element_push
67 | {
68 | bool group_pushed;
69 | surface old_background;
70 | class svgren::renderer& renderer;
71 |
72 | real opacity = real(1);
73 |
74 | const svgdom::element* mask_element = nullptr;
75 |
76 | veg::canvas_matrix_push matrix_push;
77 |
78 | r4::segment2 old_device_space_bounding_box;
79 |
80 | public:
81 | common_element_push(svgren::renderer& renderer, bool is_container);
82 |
83 | common_element_push(const common_element_push&) = delete;
84 | common_element_push& operator=(const common_element_push&) = delete;
85 |
86 | common_element_push(common_element_push&&) = delete;
87 | common_element_push& operator=(common_element_push&&) = delete;
88 |
89 | ~common_element_push() noexcept;
90 |
91 | bool is_group_pushed() const noexcept
92 | {
93 | return this->group_pushed;
94 | }
95 | };
96 |
97 | struct gradient_caster : public svgdom::const_visitor {
98 | const svgdom::linear_gradient_element* linear = nullptr;
99 | const svgdom::radial_gradient_element* radial = nullptr;
100 | const svgdom::gradient* gradient = nullptr;
101 |
102 | void visit(const svgdom::linear_gradient_element& e) override
103 | {
104 | this->gradient = &e;
105 | this->linear = &e;
106 | }
107 |
108 | void visit(const svgdom::radial_gradient_element& e) override
109 | {
110 | this->gradient = &e;
111 | this->radial = &e;
112 | }
113 | };
114 |
115 | } // namespace svgren
116 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "debug render_dims",
9 | "type": "cppdbg",
10 | "request": "launch",
11 | "program": "${workspaceFolder}/tests/render_dims/out/dbg_agg/tests",
12 | "args": [],
13 | "stopAtEntry": false,
14 | "cwd": "${workspaceFolder}/tests/render_dims",
15 | "environment": [{"name": "LD_LIBRARY_PATH", "value": "../../src/out/dbg_agg"}],
16 | "externalConsole": false,
17 | "MIMode": "gdb",
18 | "setupCommands": [
19 | {
20 | "description": "Enable pretty-printing for gdb",
21 | "text": "-enable-pretty-printing",
22 | "ignoreFailures": true
23 | }
24 | ],
25 | "preLaunchTask": "build_debug_agg"
26 | },
27 | {
28 | "name": "debug render",
29 | "type": "cppdbg",
30 | "request": "launch",
31 | "program": "${workspaceFolder}/tests/render/out/dbg_agg/tests",
32 | "args": ["${workspaceFolder}/tests/unit/samples_data/Customs-Ground_Level.svg", "${workspaceFolder}/out.png"],
33 | "stopAtEntry": false,
34 | "cwd": "${workspaceFolder}/tests/render",
35 | "environment": [{"name": "LD_LIBRARY_PATH", "value": "../../src/out/dbg_agg"}],
36 | "externalConsole": false,
37 | "MIMode": "gdb",
38 | "setupCommands": [
39 | {
40 | "description": "Enable pretty-printing for gdb",
41 | "text": "-enable-pretty-printing",
42 | "ignoreFailures": true
43 | }
44 | ],
45 | "preLaunchTask": "build_dbg_agg"
46 | },
47 | {
48 | "name": "debug unit tests",
49 | "type": "cppdbg",
50 | "request": "launch",
51 | "program": "${workspaceFolder}/tests/unit/out/dbg_agg/tests",
52 | "args": [],
53 | "stopAtEntry": false,
54 | "cwd": "${workspaceFolder}/tests/unit",
55 | "environment": [{"name": "LD_LIBRARY_PATH", "value": "../../src/out/dbg_agg"}],
56 | "externalConsole": false,
57 | "MIMode": "gdb",
58 | "setupCommands": [
59 | {
60 | "description": "Enable pretty-printing for gdb",
61 | "text": "-enable-pretty-printing",
62 | "ignoreFailures": true
63 | }
64 | ],
65 | "preLaunchTask": "build_dbg_agg"
66 | },
67 | {
68 | "name": "debug checksvg",
69 | "type": "cppdbg",
70 | "request": "launch",
71 | "program": "${workspaceFolder}/tests/samples/checksvg",
72 | "args": ["${workspaceFolder}/tests/samples/testdata/mouse.svg", "${workspaceFolder}/tests/samples/testdata/mouse.png"],
73 | "stopAtEntry": false,
74 | "cwd": "${workspaceFolder}/tests/render",
75 | "environment": [{"name": "LD_LIBRARY_PATH", "value": "../../src/build"}],
76 | "externalConsole": false,
77 | "MIMode": "gdb",
78 | "setupCommands": [
79 | {
80 | "description": "Enable pretty-printing for gdb",
81 | "text": "-enable-pretty-printing",
82 | "ignoreFailures": true
83 | }
84 | ],
85 | "preLaunchTask": "build_debug"
86 | }
87 | ]
88 | }
--------------------------------------------------------------------------------
/src/svgren/render.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2024 Ivan Gagis
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | */
25 |
26 | /* ================ LICENSE END ================ */
27 |
28 | #include "render.hpp"
29 |
30 | #include
31 |
32 | #include
33 | #include
34 | #include
35 |
36 | #include "config.hxx"
37 | #include "renderer.hxx"
38 |
39 | using namespace svgren;
40 |
41 | result svgren::render(const svgdom::svg_element& svg, const parameters& p)
42 | {
43 | result ret;
44 |
45 | auto im = rasterize(svg, p);
46 |
47 | ret.dims = im.dims();
48 |
49 | ret.pixels.resize(im.pixels().size());
50 |
51 | // This deprecated render() function uses the rasterize() and then just reinterprets the result,
52 | // so it is OK to use reinterpret_cast here.
53 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
54 | auto span = utki::make_span(reinterpret_cast(im.pixels().data()), im.pixels().size());
55 |
56 | std::copy(span.begin(), span.end(), ret.pixels.begin());
57 |
58 | return ret;
59 | }
60 |
61 | image_type svgren::rasterize(const svgdom::svg_element& svg, const parameters& params)
62 | {
63 | auto svg_dims = svg.get_dimensions(svgdom::real(params.dpi));
64 |
65 | if (!svg_dims.is_positive()) {
66 | return {};
67 | }
68 |
69 | image_type::dimensions_type raster_dims;
70 |
71 | if (params.dims_request.is_zero()) {
72 | using std::ceil;
73 | raster_dims = ceil(svg_dims).to();
74 | } else {
75 | real aspect_ratio = svg.aspect_ratio(svgdom::real(params.dpi));
76 | if (aspect_ratio == 0) {
77 | return {};
78 | }
79 | ASSERT(aspect_ratio > 0)
80 | using std::round;
81 | using std::max;
82 | if (params.dims_request.x() == 0 && params.dims_request.y() != 0) {
83 | raster_dims.x() = unsigned(round(aspect_ratio * real(params.dims_request.y())));
84 | raster_dims.x() = max(raster_dims.x(), unsigned(1)); // we don't want zero width
85 | raster_dims.y() = params.dims_request.y();
86 | } else if (params.dims_request.x() != 0 && params.dims_request.y() == 0) {
87 | raster_dims.y() = unsigned(round(real(params.dims_request.x()) / aspect_ratio));
88 | raster_dims.y() = max(raster_dims.y(), unsigned(1)); // we don't want zero height
89 | raster_dims.x() = params.dims_request.x();
90 | } else {
91 | ASSERT(params.dims_request.is_positive())
92 | raster_dims = params.dims_request;
93 | }
94 | }
95 |
96 | ASSERT(raster_dims.is_positive())
97 | ASSERT(svg_dims.is_positive())
98 |
99 | veg::canvas canvas(raster_dims);
100 |
101 | canvas.scale(raster_dims.to().comp_div(svg_dims.to()));
102 |
103 | renderer r(canvas, params.dpi, svg_dims, svg);
104 |
105 | svg.accept(r);
106 |
107 | return canvas.release();
108 | }
109 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/instagram.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/dropshadowfilter.svg:
--------------------------------------------------------------------------------
1 |
2 |
15 |
17 |
18 |
20 | image/svg+xml
21 |
23 |
24 |
25 |
26 |
46 |
48 |
50 |
54 |
55 |
57 |
61 |
62 |
69 |
72 |
73 |
75 |
80 |
81 |
83 |
87 |
88 |
89 |
91 |
93 |
98 |
103 |
104 |
108 |
110 |
115 |
116 |
118 |
124 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/composite.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 | Example feComposite - Examples of feComposite operations
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | Render the examples using the filters that draw on top of
49 | an opaque white surface, thus obliterating the background.
50 |
51 | Render the examples using the filters that do not obliterate
52 | the background, thus sometimes causing the background to continue
53 | to appear in some cases, and in other cases the background
54 | image blends into itself ("double-counting").
55 | opacity 1.0
56 | (without feFlood)
57 | opacity 0.5
58 | (without feFlood)
59 |
60 |
61 |
62 |
63 | over
64 |
65 |
66 |
67 |
68 | in
69 |
70 |
71 |
72 |
73 | out
74 |
75 |
76 |
77 |
78 | atop
79 |
80 |
81 |
82 |
83 | xor
84 |
85 |
86 |
87 |
88 | arithmetic
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/sample1.svg:
--------------------------------------------------------------------------------
1 |
2 |
13 |
15 |
17 |
18 |
20 | image/svg+xml
21 |
23 |
24 |
25 |
26 |
27 |
30 |
33 |
37 |
40 |
46 |
52 |
58 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/tests/render/main.cpp:
--------------------------------------------------------------------------------
1 | #include "../../src/svgren/render.hpp"
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | #include
10 |
11 | #include
12 |
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include
19 |
20 | #if CFG_OS == CFG_OS_LINUX
21 | # include
22 | # include
23 | #endif
24 |
25 | #ifdef assert
26 | # undef assert
27 | #endif
28 |
29 | // NOLINTNEXTLINE(bugprone-exception-escape): fatal exceptions are not caught
30 | int main(int argc, char **argv){
31 | std::string filename;
32 | std::string out_filename;
33 | switch(argc){
34 | case 0:
35 | case 1:
36 | std::cout << "Warning: 2 arguments expected: " << std::endl;
37 | std::cout << "\t Got 0 arguments, assume =tiger.svg =tiger.png" << std::endl;
38 | filename = "tiger.svg";
39 | out_filename = "tiger.png";
40 | break;
41 | case 2:
42 | std::cout << "Warning: 2 arguments expected: " << std::endl;
43 | // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
44 | filename = argv[1];
45 | {
46 | auto dot_index = filename.find_last_of(".", filename.size());
47 | if(dot_index == std::string::npos){
48 | dot_index = filename.size();
49 | }
50 | out_filename = filename.substr(0, dot_index) + ".png";
51 | }
52 | std::cout << "\t Got 1 argument, assume =" << filename << " =" << out_filename << std::endl;
53 | break;
54 | default:
55 | // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
56 | filename = argv[1];
57 | // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
58 | out_filename = argv[2];
59 | break;
60 | }
61 |
62 | #ifdef DEBUG
63 | auto load_start = utki::get_ticks_ms();
64 | #endif
65 |
66 | auto dom = svgdom::load(fsif::native_file(filename));
67 | utki::assert(dom, SL);
68 |
69 | LOG([&](auto&o){o << "SVG loaded in " << float(utki::get_ticks_ms() - load_start) / float(std::milli::den) << " sec." << std::endl;})
70 |
71 | auto render_start_ms = utki::get_ticks_ms();
72 |
73 | auto image = rasterimage::image_variant(svgren::rasterize(*dom));
74 |
75 | const auto& img = image.get();
76 |
77 | // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
78 | utki::log([&](auto&o){o << "SVG rendered in " << float(utki::get_ticks_ms() - render_start_ms) / 1000.0f << " sec." << std::endl;});
79 |
80 | utki::log([&](auto&o){o << "img.dims = " << img.dims() << " img.pixels.size() = " << img.pixels().size() << std::endl;});
81 |
82 | image.write_png(fsif::native_file(out_filename));
83 |
84 | #if CFG_OS == CFG_OS_LINUX
85 | auto width = int(img.dims().x() + 2);
86 | auto height = int(img.dims().y() + 2);
87 |
88 | Display *display = XOpenDisplay(nullptr);
89 |
90 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast, cppcoreguidelines-pro-bounds-pointer-arithmetic)
91 | Visual *visual = DefaultVisual(display, 0);
92 |
93 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast, cppcoreguidelines-pro-bounds-pointer-arithmetic)
94 | Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0, width, height, 1, 0, 0);
95 |
96 | if(visual->c_class != TrueColor){
97 | utki::log([](auto&o){o << "Cannot handle non true color visual ...\n" << std::endl;});
98 | return 1;
99 | }
100 |
101 | XSelectInput(display, window, ButtonPressMask|ExposureMask|KeyPressMask);
102 |
103 | XMapWindow(display, window);
104 |
105 | while(true){
106 | XEvent ev;
107 | XNextEvent(display, &ev);
108 | switch(ev.type){
109 | default:
110 | break;
111 | case Expose:
112 | {
113 | int dummy_int = 0;
114 | unsigned dummy_unsigned = 0;
115 | Window dummy_window = 0;
116 | unsigned win_width = 0;
117 | unsigned win_height = 0;
118 |
119 | XGetGeometry(display, window, &dummy_window, &dummy_int, &dummy_int, &win_width, &win_height, &dummy_unsigned, &dummy_unsigned);
120 |
121 | using std::max;
122 |
123 | svgren::parameters p;
124 | p.dpi = svgren::parameters::default_dpi;
125 | p.dims_request.x() = max(int(win_width) - 2, 0);
126 | p.dims_request.y() = max(int(win_height) - 2, 0);
127 | auto img = svgren::rasterize(*dom, p);
128 |
129 | img.span().swap_red_blue();
130 |
131 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
132 | auto ximage = XCreateImage(display, visual, utki::byte_bits * 3, ZPixmap, 0, reinterpret_cast(img.pixels().data()), img.dims().x(), img.dims().y(), utki::byte_bits, 0);
133 | utki::scope_exit scope_exit([ximage](){
134 | ximage->data = nullptr; // Xlib will try to deallocate data which is owned by 'img' variable.
135 | XDestroyImage(ximage);
136 | });
137 |
138 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast, cppcoreguidelines-pro-bounds-pointer-arithmetic)
139 | XPutImage(display, window, DefaultGC(display, 0), ximage, 0, 0, 1, 1, img.dims().x(), img.dims().y());
140 | }
141 | break;
142 | case KeyPress:
143 | case ButtonPress:
144 | exit(0);
145 | break;
146 | }
147 | }
148 | #endif
149 |
150 | utki::log([](auto&o){o << "[PASSED]" << std::endl;});
151 | }
152 |
--------------------------------------------------------------------------------
/src/svgren/renderer.hxx:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2024 Ivan Gagis
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | */
25 |
26 | /* ================ LICENSE END ================ */
27 |
28 | #pragma once
29 |
30 | #include
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 |
40 | #include "config.hxx"
41 | #include "surface.hxx"
42 | #include "util.hxx"
43 |
44 | namespace svgren {
45 |
46 | class renderer : public svgdom::const_visitor
47 | {
48 | public:
49 | veg::canvas& canvas;
50 |
51 | svgdom::finder_by_id finder_by_id;
52 | svgdom::style_stack_cache style_stack_cache;
53 |
54 | const real dpi;
55 |
56 | bool is_outermost_element = true;
57 |
58 | r4::vector2 viewport;
59 |
60 | // this bounding box is used for gradients
61 | r4::rectangle user_space_bounding_box{};
62 |
63 | // this bounding box is used for filter region calculation.
64 | r4::segment2 device_space_bounding_box{};
65 |
66 | svgdom::style_stack style_stack;
67 |
68 | surface background; // for accessing background image from filter effects
69 |
70 | void blit(const surface& s);
71 |
72 | real length_to_px(const svgdom::length& l) const noexcept;
73 | r4::vector2 length_to_px(const svgdom::length& x, const svgdom::length& y) const noexcept;
74 |
75 | void apply_transformation(const svgdom::transformable::transformation& t);
76 |
77 | void apply_transformations(const decltype(svgdom::transformable::transformations)& transformations);
78 |
79 | void set_gradient_properties(
80 | veg::gradient& gradient, //
81 | const svgdom::gradient& g,
82 | const svgdom::style_stack& ss
83 | );
84 |
85 | void set_gradient(const std::string& id);
86 |
87 | void apply_filter(const std::string& id);
88 | void apply_filter();
89 |
90 | void update_bounding_box();
91 |
92 | void render_shape(bool is_group_pushed);
93 |
94 | void apply_viewbox(const svgdom::view_boxed& e, const svgdom::aspect_ratioed& ar);
95 |
96 | void render_svg_element(
97 | const svgdom::container& c,
98 | const svgdom::styleable& s,
99 | const svgdom::view_boxed& v,
100 | const svgdom::aspect_ratioed& a,
101 | const svgdom::length& x,
102 | const svgdom::length& y,
103 | const svgdom::length& width,
104 | const svgdom::length& height
105 | );
106 |
107 | const decltype(svgdom::transformable::transformations)& gradient_get_transformations(const svgdom::gradient& g);
108 | svgdom::coordinate_units gradient_get_units(const svgdom::gradient& g);
109 |
110 | svgdom::length gradient_get_x1(const svgdom::linear_gradient_element& g);
111 | svgdom::length gradient_get_y1(const svgdom::linear_gradient_element& g);
112 | svgdom::length gradient_get_x2(const svgdom::linear_gradient_element& g);
113 | svgdom::length gradient_get_y2(const svgdom::linear_gradient_element& g);
114 |
115 | svgdom::length gradient_get_cx(const svgdom::radial_gradient_element& g);
116 | svgdom::length gradient_get_cy(const svgdom::radial_gradient_element& g);
117 | svgdom::length gradient_get_r(const svgdom::radial_gradient_element& g);
118 | svgdom::length gradient_get_fx(const svgdom::radial_gradient_element& g);
119 | svgdom::length gradient_get_fy(const svgdom::radial_gradient_element& g);
120 |
121 | const decltype(svgdom::container::children)& gradient_get_stops(const svgdom::gradient& g);
122 | const decltype(svgdom::styleable::styles)& gradient_get_styles(const svgdom::gradient& g);
123 | const decltype(svgdom::styleable::classes)& gradient_get_classes(const svgdom::gradient& g);
124 | svgdom::gradient::spread_method gradient_get_spread_method(const svgdom::gradient& g);
125 |
126 | decltype(svgdom::styleable::presentation_attributes) //
127 | gradient_get_presentation_attributes(const svgdom::gradient& g);
128 |
129 | bool is_invisible();
130 | bool is_group_invisible();
131 |
132 | public:
133 | renderer(
134 | veg::canvas& canvas, //
135 | unsigned dpi,
136 | r4::vector2 viewport,
137 | const svgdom::svg_element& root
138 | );
139 |
140 | // declare public method which calls protected one.
141 | void relay_accept(const svgdom::container& e)
142 | {
143 | this->const_visitor::relay_accept(e);
144 | }
145 |
146 | void visit(const svgdom::g_element& e) override;
147 | void visit(const svgdom::use_element& e) override;
148 | void visit(const svgdom::svg_element& e) override;
149 | void visit(const svgdom::path_element& e) override;
150 | void visit(const svgdom::circle_element& e) override;
151 | void visit(const svgdom::polyline_element& e) override;
152 | void visit(const svgdom::polygon_element& e) override;
153 | void visit(const svgdom::line_element& e) override;
154 | void visit(const svgdom::ellipse_element& e) override;
155 | void visit(const svgdom::rect_element& e) override;
156 | void visit(const svgdom::style_element& e) override;
157 | void visit(const svgdom::defs_element& e) override;
158 |
159 | void default_visit(const svgdom::element& e, const svgdom::container& c) override
160 | {
161 | // do nothing by default
162 | }
163 | };
164 |
165 | } // namespace svgren
166 |
--------------------------------------------------------------------------------
/tests/unit/samples.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include
13 | #include
14 |
15 | #include "../../src/svgren/render.hpp"
16 |
17 | namespace{
18 | const unsigned tolerance = 10;
19 |
20 | const std::string data_dir = "samples_data/";
21 |
22 | const std::string expected_dir = "expected";
23 | }
24 |
25 | namespace{
26 | const tst::set set("samples", [](tst::suite& suite){
27 | std::vector files;
28 |
29 | {
30 | const std::regex suffix_regex("^.*\\.svg$");
31 | auto all_files = fsif::native_file(data_dir).list_dir();
32 |
33 | std::copy_if(
34 | all_files.begin(),
35 | all_files.end(),
36 | std::back_inserter(files),
37 | [&suffix_regex](auto& f){
38 | return std::regex_match(f, suffix_regex);
39 | }
40 | );
41 | }
42 |
43 | suite.add(
44 | "sample__deprecated_render",
45 | {
46 | #if CFG_CPU_BITS != 64
47 | tst::flag::disabled
48 | #endif
49 | },
50 | files,
51 | [](const auto& p){
52 | fsif::native_file in_file(data_dir + p);
53 |
54 | auto dom = svgdom::load(in_file);
55 |
56 | #if CFG_COMPILER == CFG_COMPILER_GCC || CFG_COMPILER == CFG_COMPILER_CLANG
57 | # pragma GCC diagnostic push
58 | # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
59 | #endif
60 | #if CFG_COMPILER == CFG_COMPILER_MSVC
61 | # pragma warning(disable : 4996)
62 | #endif
63 | // NOLINTNEXTLINE(clang-diagnostic-deprecated-declarations, "false positive")
64 | auto res = svgren::render(*dom);
65 | #if CFG_COMPILER == CFG_COMPILER_MSVC
66 | # pragma warning(enable: 4996)
67 | #endif
68 | #if CFG_COMPILER == CFG_COMPILER_GCC
69 | # pragma GCC diagnostic pop
70 | #endif
71 |
72 | auto& img = res.pixels;
73 |
74 | fsif::native_file png_file(data_dir + expected_dir + "/" + fsif::not_suffix(in_file.not_dir()) + ".png");
75 |
76 | auto png_var = rasterimage::read_png(png_file);
77 |
78 | tst::check(!png_var.empty(), SL);
79 |
80 | tst::check(png_var.get_format() == rasterimage::format::rgba, SL) << "Error: PNG color format is not rgba: " << unsigned(png_var.get_format());
81 | tst::check(png_var.get_depth() == rasterimage::depth::uint_8_bit, SL) << "Error: PNG color depth is not 8 bit: " << unsigned(png_var.get_depth());;
82 |
83 | tst::check(res.dims == png_var.dims(), SL) << "Error: svg dims " << res.dims << " did not match PNG dims " << png_var.dims();
84 |
85 | tst::check(img.size() == png_var.buffer_size(), SL) << "Error: svg pixel buffer size (" << img.size() << ") did not match PNG pixel buffer size(" << png_var.buffer_size() << ")";
86 |
87 | const auto& png = png_var.get();
88 |
89 | for(size_t i = 0; i != img.size(); ++i){
90 | std::array rgba = rasterimage::from_32bit_pixel(img[i]);
91 |
92 | for(unsigned j = 0; j != rgba.size(); ++j){
93 | // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
94 | auto c1 = rgba[j];
95 | auto c2 = png.pixels()[i][j];
96 | if(c1 > c2){
97 | std::swap(c1, c2);
98 | }
99 |
100 | if(unsigned(c2 - c1) > tolerance){
101 | auto png_px = png.pixels()[i];
102 |
103 | uint32_t pixel = rasterimage::to_32bit_pixel(png_px);
104 |
105 | tst::check(false, SL) << "Error: PNG pixel #" << std::dec << i << " [" << (i % res.dims.x()) << ", " << (i / res.dims.y()) << "]" << " (0x" << std::hex << pixel << ") did not match SVG pixel (0x" << img[i] << ")" << ", png_file = " << png_file.path();
106 | }
107 | }
108 | }
109 | }
110 | );
111 |
112 | suite.add(
113 | "sample",
114 | {
115 | #if CFG_CPU_BITS != 64
116 | tst::flag::disabled
117 | #endif
118 | },
119 | files,
120 | [](const auto& p){
121 | fsif::native_file in_file(data_dir + p);
122 |
123 | auto dom = svgdom::load(in_file);
124 |
125 | auto im = svgren::rasterize(*dom);
126 |
127 | fsif::native_file png_file(data_dir + expected_dir + "/" + fsif::not_suffix(in_file.not_dir()) + ".png");
128 |
129 | auto png_var = rasterimage::read_png(png_file);
130 |
131 | tst::check(!png_var.empty(), SL);
132 |
133 | tst::check(png_var.get_format() == rasterimage::format::rgba, SL) << "Error: PNG color format is not rgba: " << unsigned(png_var.get_format());
134 | tst::check(png_var.get_depth() == rasterimage::depth::uint_8_bit, SL) << "Error: PNG color depth is not 8 bit: " << unsigned(png_var.get_depth());;
135 |
136 | tst::check(im.dims() == png_var.dims(), SL) << "Error: svg dims " << im.dims() << " did not match PNG dims " << png_var.dims();
137 |
138 | tst::check(im.pixels().size() == png_var.buffer_size(), SL) << "Error: svg pixel buffer size (" << im.pixels().size() << ") did not match PNG pixel buffer size(" << png_var.buffer_size() << ")";
139 |
140 | const auto& png = png_var.get();
141 |
142 | for(size_t i = 0; i != im.pixels().size(); ++i){
143 | auto rgba = im.pixels()[i];
144 | auto png_px = png.pixels()[i];
145 |
146 | for(unsigned j = 0; j != rgba.size(); ++j){
147 | auto c1 = rgba[j];
148 | auto c2 = png_px[j];
149 | if(c1 > c2){
150 | std::swap(c1, c2);
151 | }
152 |
153 | if(unsigned(c2 - c1) > tolerance){
154 | uint32_t png_pixel = rasterimage::to_32bit_pixel(png_px);
155 | uint32_t svg_pixel = rasterimage::to_32bit_pixel(rgba);
156 |
157 | tst::check(false, SL) << "Error: PNG pixel #" << std::dec << i << " [" << (i % im.dims().x()) << ", " << (i / im.dims().y()) << "]" << " (0x" << std::hex << png_pixel << ") did not match SVG pixel (0x" << svg_pixel << ")" << ", png_file = " << png_file.path();
158 | }
159 | }
160 | }
161 | }
162 | );
163 | });
164 | }
165 |
--------------------------------------------------------------------------------
/src/svgren/util.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2024 Ivan Gagis
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | */
25 |
26 | /* ================ LICENSE END ================ */
27 |
28 | #include "util.hxx"
29 |
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | #include
36 | #include
37 | #include
38 |
39 | #include "renderer.hxx"
40 |
41 | using namespace svgren;
42 |
43 | real svgren::percent_to_fraction(const svgdom::length& l)
44 | {
45 | if (l.is_percent()) {
46 | return l.value / real(std::centi::den);
47 | }
48 | if (l.unit == svgdom::length_unit::number) {
49 | return l.value;
50 | }
51 | return 0;
52 | }
53 |
54 | renderer_viewport_push::renderer_viewport_push(renderer& r, const decltype(old_viewport)& viewport) :
55 | r(r),
56 | old_viewport(r.viewport)
57 | {
58 | this->r.viewport = viewport;
59 | }
60 |
61 | renderer_viewport_push::~renderer_viewport_push() noexcept
62 | {
63 | this->r.viewport = this->old_viewport;
64 | }
65 |
66 | common_element_push::common_element_push(svgren::renderer& renderer, bool is_container) :
67 | renderer(renderer),
68 | matrix_push(this->renderer.canvas),
69 | old_device_space_bounding_box(renderer.device_space_bounding_box)
70 | {
71 | // old device space bounding box is saved, set current one to empty
72 | this->renderer.device_space_bounding_box.set_empty_bounding_box();
73 |
74 | auto background_prop = this->renderer.style_stack.get_style_property(svgdom::style_property::enable_background);
75 |
76 | if (background_prop && std::holds_alternative(*background_prop) &&
77 | std::get_if(background_prop)->value ==
78 | svgdom::enable_background::new_background)
79 | {
80 | this->old_background = this->renderer.background;
81 | }
82 |
83 | auto filter_prop = this->renderer.style_stack.get_style_property(svgdom::style_property::filter);
84 |
85 | if (auto mask_prop = this->renderer.style_stack.get_style_property(svgdom::style_property::mask)) {
86 | if (std::holds_alternative(*mask_prop)) {
87 | if (auto ei = this->renderer.finder_by_id.find(svgdom::get_local_id_from_iri(*mask_prop))) {
88 | this->mask_element = ei;
89 | }
90 | }
91 | }
92 |
93 | this->group_pushed = filter_prop || this->mask_element || !this->old_background.image_span.empty();
94 |
95 | auto opacity = svgdom::real(1);
96 | {
97 | auto stroke_prop = this->renderer.style_stack.get_style_property(svgdom::style_property::stroke);
98 | auto fill_prop = this->renderer.style_stack.get_style_property(svgdom::style_property::fill);
99 |
100 | // OPTIMIZATION: if opacity is set on an element then push group only in case it is a container element, like
101 | // 'g' or 'svg', or in case the fill or stroke is a non-solid color, like gradient or pattern, or both fill and
102 | // stroke are non-none. If element is non-container and one of stroke or fill is solid color and other one is
103 | // none, then opacity will be applied later without pushing group.
104 | if (this->group_pushed || is_container || (stroke_prop && std::holds_alternative(*stroke_prop)) ||
105 | (fill_prop && std::holds_alternative(*fill_prop)) ||
106 | (fill_prop && stroke_prop && !svgdom::is_none(*fill_prop) && !svgdom::is_none(*stroke_prop)))
107 | {
108 | auto p = this->renderer.style_stack.get_style_property(svgdom::style_property::opacity);
109 | if (p && std::holds_alternative(*p)) {
110 | opacity = *std::get_if(p);
111 | this->group_pushed = this->group_pushed || opacity < 1;
112 | }
113 | }
114 | }
115 |
116 | if (this->group_pushed) {
117 | // TRACE(<< "setting temp context" << std::endl)
118 | this->renderer.canvas.push_group();
119 |
120 | this->opacity = opacity;
121 | }
122 |
123 | if (!this->old_background.image_span.empty()) {
124 | this->renderer.background = surface(this->renderer.canvas.get_image_span());
125 | }
126 | }
127 |
128 | common_element_push::~common_element_push() noexcept
129 | {
130 | // restore device space bounding box
131 | this->old_device_space_bounding_box.unite(this->renderer.device_space_bounding_box);
132 | this->renderer.device_space_bounding_box = this->old_device_space_bounding_box;
133 |
134 | if (!this->group_pushed) {
135 | return;
136 | }
137 |
138 | if (this->mask_element) {
139 | // render mask
140 | try {
141 | this->renderer.canvas.push_group();
142 |
143 | utki::scope_exit scope_exit([this]() {
144 | this->renderer.canvas.pop_group(1);
145 | });
146 |
147 | // TODO: setup the correct coordinate system based on maskContentUnits value
148 | // (userSpaceOnUse/objectBoundingBox)
149 | // Currently nothing on that is done which is equivalent to userSpaceOnUse
150 |
151 | class mask_renderer : public svgdom::const_visitor
152 | {
153 | svgren::renderer& r;
154 |
155 | public:
156 | mask_renderer(svgren::renderer& r) :
157 | r(r)
158 | {}
159 |
160 | void visit(const svgdom::mask_element& e) override
161 | {
162 | svgdom::style_stack::push push_styles(this->r.style_stack, e);
163 |
164 | this->r.relay_accept(e);
165 | }
166 | } mr(this->renderer);
167 |
168 | this->mask_element->accept(mr);
169 |
170 | scope_exit.release();
171 |
172 | this->renderer.canvas.pop_mask_and_group();
173 | // NOLINTNEXTLINE(bugprone-empty-catch)
174 | } catch (...) {
175 | // rendering mask failed, just ignore it
176 | }
177 | } else {
178 | this->renderer.canvas.pop_group(this->opacity);
179 | }
180 |
181 | // restore background if it was pushed
182 | if (!this->old_background.image_span.empty()) {
183 | this->renderer.background = this->old_background;
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/sample4.svg:
--------------------------------------------------------------------------------
1 |
2 |
13 |
15 |
17 |
18 |
20 | image/svg+xml
21 |
23 |
24 |
25 |
26 |
27 |
30 |
32 |
36 |
41 |
42 |
46 |
50 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/cover_test.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
14 |
16 |
18 |
19 |
20 |
21 |
22 |
24 |
26 |
28 |
30 |
31 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
52 |
54 |
55 |
56 |
57 |
58 |
60 |
62 |
64 |
66 |
67 |
68 |
70 |
72 |
74 |
76 |
78 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
88 |
90 |
92 |
93 |
94 |
95 |
96 |
98 |
100 |
102 |
104 |
106 |
108 |
109 |
110 |
112 |
114 |
116 |
118 |
120 |
122 |
123 |
124 |
126 |
128 |
130 |
132 |
134 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
144 |
146 |
148 |
149 |
150 |
151 |
152 |
154 |
156 |
158 |
160 |
162 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
172 |
174 |
175 |
176 |
177 |
178 |
180 |
182 |
184 |
186 |
188 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "label": "build",
8 | "type": "shell",
9 | "command": "make config=rel",
10 | "problemMatcher": [
11 | "$gcc"
12 | ],
13 | "group": {
14 | "kind": "build",
15 | "isDefault": true
16 | }
17 | },
18 | {
19 | "label": "build-dev",
20 | "type": "shell",
21 | "command": "make config=dev",
22 | "problemMatcher": [
23 | "$gcc"
24 | ],
25 | "group": {
26 | "kind": "build",
27 | "isDefault": true
28 | }
29 | },
30 | {
31 | "label": "build-dev_bg",
32 | "type": "shell",
33 | "command": "make config=dev CXXFLAGS=-DSVGREN_BACKGROUND=0xffffffff",
34 | "problemMatcher": [
35 | "$gcc"
36 | ],
37 | "group": {
38 | "kind": "build",
39 | "isDefault": true
40 | }
41 | },
42 | {
43 | "label": "run",
44 | "type": "shell",
45 | "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/rel out/rel/tests ../unit/samples_data/defs_style_2.svg ../unit/samples_data/agg/defs_style_2.png)",
46 | "problemMatcher": [],
47 | "dependsOn": "build",
48 | "group": {
49 | "kind": "build",
50 | "isDefault": true
51 | }
52 | },
53 | {
54 | "label": "run-dev",
55 | "type": "shell",
56 | "dependsOn": "build-dev",
57 | // "dependsOn": "build-dev_bg",
58 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/Customs-Ground_Level.svg out.png)",
59 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/rgb_percent.svg out.png)",
60 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/defs_style_2.svg out.png)",
61 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/defs_style.svg out.png)",
62 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/opacity.svg out.png)",
63 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/ready_test.svg out.png)",
64 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/shadow_test.svg out.png)",
65 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/car.svg out.png)",
66 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/Turntable-Active-NEW5.svg out.png)",
67 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/machupicchu_collection_06.svg out.png)",
68 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/machupicchu_collection_04.svg out.png)",
69 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/machupicchu_collection_02.svg out.png)",
70 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/machupicchu_collection_01.svg out.png)",
71 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/test2.svg out.png)",
72 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/rectangle.svg out.png)",
73 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/dropshadowfilter.svg out.png)",
74 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/six_ball.svg out.png)",
75 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/granddad.svg out.png)",
76 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/3.072.svg out.png)",
77 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/0.451.svg out.png)",
78 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/gradtest.svg out.png)",
79 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/radial_gradient.svg out.png)",
80 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/car.svg out.png)",
81 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/VOLUME_GSP.svg out.png)",
82 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/visibility.svg out.png)",
83 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/use.svg out.png)",
84 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/tiger_with_smooth_cubic_curves.svg out.png)",
85 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/SPHERE_S_GSP.svg out.png)",
86 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/SPHERE_GSP.svg out.png)",
87 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/sample4.svg out.png)",
88 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/sample3.svg out.png)",
89 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/sample2.svg out.png)",
90 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/sample1.svg out.png)",
91 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/quadratic.svg out.png)",
92 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/percentage_dimensions_and_viewbox.svg out.png)",
93 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/mouse.svg out.png)",
94 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/menue-cut.svg out.png)",
95 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/lines.svg out.png)",
96 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/linear_gradient.svg out.png)",
97 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/invisible_rect.svg out.png)",
98 | "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/interface-ethernet.svg out.png)",
99 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/gauge_arrow_shadow.svg out.png)",
100 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/FW5-24V.svg out.png)",
101 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/ellipse.svg out.png)",
102 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/default_black.svg out.png)",
103 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/cubic_smooth.svg out.png)",
104 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/css_simple0.svg out.png)",
105 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/composite.svg out.png)",
106 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/circle.svg out.png)",
107 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/circle1.svg out.png)",
108 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/caltrain.svg out.png)",
109 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/arc.svg out.png)",
110 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/1.svg out.png)",
111 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/group_opacity.svg out.png)",
112 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/masking.svg out.png)",
113 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/camera.svg out.png)",
114 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/back.svg out.png)",
115 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/tiger.svg out.png)",
116 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/radial_gradient_2.svg out.png)",
117 | // "command": "(cd ${workspaceFolder}/tests/render && LD_LIBRARY_PATH=../../src/out/dev out/dev/tests ../unit/samples_data/gradient-transform-rotate-compare.svg out.png)",
118 | "problemMatcher": [],
119 | "group": {
120 | "kind": "build",
121 | "isDefault": true
122 | }
123 | },
124 | {
125 | "label": "clean-all",
126 | "type": "shell",
127 | "command": "make clean-all",
128 | "problemMatcher": [],
129 | "group": {
130 | "kind": "build",
131 | "isDefault": true
132 | }
133 | },
134 | {
135 | "label": "clean",
136 | "type": "shell",
137 | "command": "make clean config=rel",
138 | "problemMatcher": [],
139 | "group": {
140 | "kind": "build",
141 | "isDefault": true
142 | }
143 | },
144 | {
145 | "label": "rebuild",
146 | "type": "shell",
147 | "command": "make re",
148 | "dependsOn": [
149 | "clean",
150 | "build"
151 | ],
152 | "problemMatcher": [],
153 | "group": {
154 | "kind": "build",
155 | "isDefault": true
156 | }
157 | },
158 | {
159 | "label": "test_",
160 | "type": "shell",
161 | "command": "make test config=rel",
162 | "problemMatcher": [],
163 | "group": {
164 | "kind": "build",
165 | "isDefault": true
166 | }
167 | },
168 | {
169 | "label": "test-dev",
170 | "type": "shell",
171 | "command": "make test config=dev",
172 | "problemMatcher": [],
173 | "group": {
174 | "kind": "build",
175 | "isDefault": true
176 | }
177 | },
178 | {
179 | "label": "format",
180 | "type": "shell",
181 | "command": "make format",
182 | "problemMatcher": [],
183 | "group": {
184 | "kind": "build",
185 | "isDefault": true
186 | }
187 | }
188 | ]
189 | }
190 |
--------------------------------------------------------------------------------
/tests/unit/samples_data/SPHERE_S_GSP.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
25 |
42 |
45 |
47 |
50 |
53 |
56 |
58 |
60 |
63 |
66 |
73 |
76 |
83 |
89 |
95 |
101 |
108 |
119 |
126 |
134 |
138 |
142 |
150 |
158 |
165 |
172 |
178 |
184 |
190 |
191 |
192 |
193 |
194 |
201 |
207 |
208 |
209 |
--------------------------------------------------------------------------------