summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--COPYRIGHT.txt2
-rw-r--r--SConstruct12
-rw-r--r--core/input/input.cpp1
-rw-r--r--core/math/color.cpp85
-rw-r--r--core/math/color.h8
-rw-r--r--core/math/convex_hull.cpp20
-rw-r--r--core/math/static_raycaster.h16
-rw-r--r--core/object/object.h2
-rw-r--r--core/object/worker_thread_pool.cpp22
-rw-r--r--core/object/worker_thread_pool.h4
-rw-r--r--core/os/os.h1
-rw-r--r--core/os/time.cpp8
-rw-r--r--core/register_core_types.cpp12
-rw-r--r--core/variant/variant_call.cpp1
-rw-r--r--core/variant/variant_setget.cpp4
-rw-r--r--core/variant/variant_setget.h4
-rw-r--r--doc/classes/@GlobalScope.xml50
-rw-r--r--doc/classes/Color.xml27
-rw-r--r--doc/classes/ItemList.xml10
-rw-r--r--doc/classes/NavigationRegion2D.xml3
-rw-r--r--doc/classes/NavigationRegion3D.xml3
-rw-r--r--doc/classes/NavigationServer2D.xml30
-rw-r--r--doc/classes/NavigationServer3D.xml30
-rw-r--r--doc/classes/ProjectSettings.xml6
-rw-r--r--drivers/gl_context/SCsub6
-rw-r--r--drivers/gles3/storage/light_storage.cpp1
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp4
-rw-r--r--drivers/unix/file_access_unix.cpp12
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp5
-rw-r--r--editor/debugger/script_editor_debugger.cpp2
-rw-r--r--editor/editor_audio_buses.cpp12
-rw-r--r--editor/editor_node.cpp1
-rw-r--r--editor/icons/BusVuActive.svg (renamed from editor/icons/BusVuFull.svg)0
-rw-r--r--editor/icons/BusVuEmpty.svg1
-rw-r--r--editor/import/collada.cpp1008
-rw-r--r--editor/import/collada.h72
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/node_3d_editor_plugin.h8
-rw-r--r--main/main.cpp13
-rw-r--r--modules/astcenc/SCsub1
-rw-r--r--modules/csg/csg.cpp36
-rw-r--r--modules/csg/csg.h4
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.cpp4
-rw-r--r--modules/mbedtls/crypto_mbedtls.cpp29
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs3
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs161
-rw-r--r--modules/navigation/godot_navigation_server.cpp28
-rw-r--r--modules/navigation/godot_navigation_server.h6
-rw-r--r--modules/navigation/nav_base.h5
-rw-r--r--modules/navigation/nav_map.cpp12
-rw-r--r--modules/navigation/nav_map.h6
-rw-r--r--modules/navigation/nav_region.cpp7
-rw-r--r--modules/navigation/nav_region.h7
-rw-r--r--modules/text_server_adv/SCsub6
-rw-r--r--modules/text_server_fb/SCsub6
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java38
-rw-r--r--platform/android/java_godot_wrapper.cpp12
-rw-r--r--platform/android/java_godot_wrapper.h2
-rw-r--r--platform/android/os_android.cpp4
-rw-r--r--platform/android/os_android.h1
-rw-r--r--platform/ios/ios.mm18
-rw-r--r--platform/linuxbsd/freedesktop_portal_desktop.cpp5
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.cpp5
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp40
-rw-r--r--platform/linuxbsd/os_linuxbsd.h2
-rw-r--r--platform/linuxbsd/x11/detect_prime_x11.cpp3
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp22
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h2
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.cpp3
-rw-r--r--platform/macos/detect.py2
-rw-r--r--platform/macos/display_server_macos.mm10
-rw-r--r--platform/macos/os_macos.h2
-rw-r--r--platform/macos/os_macos.mm29
-rw-r--r--platform/windows/detect.py2
-rw-r--r--platform/windows/os_windows.cpp35
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--scene/2d/navigation_region_2d.cpp20
-rw-r--r--scene/2d/navigation_region_2d.h5
-rw-r--r--scene/3d/lightmapper.h16
-rw-r--r--scene/3d/navigation_region_3d.cpp25
-rw-r--r--scene/3d/navigation_region_3d.h5
-rw-r--r--scene/gui/item_list.cpp14
-rw-r--r--scene/gui/item_list.h2
-rw-r--r--scene/main/node.cpp30
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/resources/audio_stream_wav.cpp56
-rw-r--r--scene/resources/audio_stream_wav.h2
-rw-r--r--scene/resources/world_2d.cpp1
-rw-r--r--scene/resources/world_3d.cpp1
-rw-r--r--servers/navigation_server_2d.cpp10
-rw-r--r--servers/navigation_server_2d.h6
-rw-r--r--servers/navigation_server_3d.cpp6
-rw-r--r--servers/navigation_server_3d.h6
-rw-r--r--servers/navigation_server_3d_dummy.h4
-rw-r--r--servers/rendering/shader_compiler.cpp36
-rw-r--r--servers/rendering/shader_language.cpp114
-rw-r--r--servers/rendering/shader_language.h48
-rw-r--r--tests/core/math/test_color.h14
-rw-r--r--tests/test_main.cpp2
-rw-r--r--thirdparty/README.md8
-rw-r--r--thirdparty/astcenc/astcenc.h18
-rw-r--r--thirdparty/astcenc/astcenc_averages_and_directions.cpp59
-rw-r--r--thirdparty/astcenc/astcenc_block_sizes.cpp20
-rw-r--r--thirdparty/astcenc/astcenc_color_quantize.cpp142
-rw-r--r--thirdparty/astcenc/astcenc_compress_symbolic.cpp14
-rw-r--r--thirdparty/astcenc/astcenc_diagnostic_trace.cpp19
-rw-r--r--thirdparty/astcenc/astcenc_entry.cpp88
-rw-r--r--thirdparty/astcenc/astcenc_find_best_partitioning.cpp28
-rw-r--r--thirdparty/astcenc/astcenc_internal.h79
-rw-r--r--thirdparty/astcenc/astcenc_platform_isa_detection.cpp166
-rw-r--r--thirdparty/astcenc/astcenc_quantization.cpp891
-rw-r--r--thirdparty/astcenc/astcenc_symbolic_physical.cpp79
-rw-r--r--thirdparty/astcenc/astcenc_weight_align.cpp6
-rw-r--r--thirdparty/doctest/LICENSE.txt2
-rw-r--r--thirdparty/doctest/doctest.h149
-rw-r--r--thirdparty/thorvg/AUTHORS7
-rw-r--r--thirdparty/thorvg/LICENSE2
-rw-r--r--thirdparty/thorvg/inc/config.h2
-rw-r--r--thirdparty/thorvg/inc/thorvg.h185
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h40
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwFill.cpp5
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp55
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwMath.cpp5
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwMemPool.cpp11
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp688
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h22
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterC.h90
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterNeon.h24
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h141
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h21
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp341
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h15
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRle.cpp180
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp45
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp24
-rw-r--r--thirdparty/thorvg/src/lib/tvgAccessor.cpp19
-rw-r--r--thirdparty/thorvg/src/lib/tvgArray.h3
-rw-r--r--thirdparty/thorvg/src/lib/tvgBezier.cpp5
-rw-r--r--thirdparty/thorvg/src/lib/tvgBezier.h3
-rw-r--r--thirdparty/thorvg/src/lib/tvgBinaryDesc.h6
-rw-r--r--thirdparty/thorvg/src/lib/tvgCanvas.cpp15
-rw-r--r--thirdparty/thorvg/src/lib/tvgCanvasImpl.h3
-rw-r--r--thirdparty/thorvg/src/lib/tvgCommon.h13
-rw-r--r--thirdparty/thorvg/src/lib/tvgFill.cpp3
-rw-r--r--thirdparty/thorvg/src/lib/tvgFill.h3
-rw-r--r--thirdparty/thorvg/src/lib/tvgGlCanvas.cpp3
-rw-r--r--thirdparty/thorvg/src/lib/tvgInitializer.cpp16
-rw-r--r--thirdparty/thorvg/src/lib/tvgIteratorAccessor.h5
-rw-r--r--thirdparty/thorvg/src/lib/tvgLinearGradient.cpp3
-rw-r--r--thirdparty/thorvg/src/lib/tvgLoadModule.h9
-rw-r--r--thirdparty/thorvg/src/lib/tvgLoader.cpp3
-rw-r--r--thirdparty/thorvg/src/lib/tvgLoader.h3
-rw-r--r--thirdparty/thorvg/src/lib/tvgLzw.cpp6
-rw-r--r--thirdparty/thorvg/src/lib/tvgLzw.h3
-rw-r--r--thirdparty/thorvg/src/lib/tvgMath.h5
-rw-r--r--thirdparty/thorvg/src/lib/tvgPaint.cpp75
-rw-r--r--thirdparty/thorvg/src/lib/tvgPaint.h13
-rw-r--r--thirdparty/thorvg/src/lib/tvgPicture.cpp23
-rw-r--r--thirdparty/thorvg/src/lib/tvgPictureImpl.h116
-rw-r--r--thirdparty/thorvg/src/lib/tvgRadialGradient.cpp3
-rw-r--r--thirdparty/thorvg/src/lib/tvgRender.cpp3
-rw-r--r--thirdparty/thorvg/src/lib/tvgRender.h185
-rw-r--r--thirdparty/thorvg/src/lib/tvgSaveModule.h5
-rw-r--r--thirdparty/thorvg/src/lib/tvgSaver.cpp3
-rw-r--r--thirdparty/thorvg/src/lib/tvgScene.cpp3
-rw-r--r--thirdparty/thorvg/src/lib/tvgSceneImpl.h34
-rw-r--r--thirdparty/thorvg/src/lib/tvgShape.cpp168
-rw-r--r--thirdparty/thorvg/src/lib/tvgShapeImpl.h364
-rw-r--r--thirdparty/thorvg/src/lib/tvgSwCanvas.cpp5
-rw-r--r--thirdparty/thorvg/src/lib/tvgTaskScheduler.cpp12
-rw-r--r--thirdparty/thorvg/src/lib/tvgTaskScheduler.h11
-rw-r--r--thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp62
-rw-r--r--thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h5
-rw-r--r--thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp38
-rw-r--r--thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h5
-rw-r--r--thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp34
-rw-r--r--thirdparty/thorvg/src/loaders/jpg/tvgJpgd.h2
-rw-r--r--thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp37
-rw-r--r--thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h5
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp75
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp1120
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h5
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h110
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp11
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp61
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h4
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp6
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h2
-rw-r--r--thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp55
-rw-r--r--thirdparty/thorvg/src/loaders/tvg/tvgTvgCommon.h2
-rw-r--r--thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.cpp3
-rw-r--r--thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.h2
-rw-r--r--thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp25
-rw-r--r--thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.h3
-rwxr-xr-xthirdparty/thorvg/update-thorvg.sh4
200 files changed, 5133 insertions, 3874 deletions
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 6c157c32f4..c8bfc1c8d2 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -169,7 +169,7 @@ License: Expat
Files: ./thirdparty/doctest/
Comment: doctest
-Copyright: 2016-2021, Viktor Kirilov
+Copyright: 2016-2023, Viktor Kirilov
License: Expat
Files: ./thirdparty/embree/
diff --git a/SConstruct b/SConstruct
index f4d27a2134..68329f331e 100644
--- a/SConstruct
+++ b/SConstruct
@@ -217,7 +217,11 @@ opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and be
opts.Add("build_profile", "Path to a file containing a feature build profile", "")
opts.Add(BoolVariable("modules_enabled_by_default", "If no, disable all modules except ones explicitly enabled", True))
opts.Add(BoolVariable("no_editor_splash", "Don't use the custom splash screen for the editor", True))
-opts.Add("system_certs_path", "Use this path as SSL certificates default for editor (for package maintainers)", "")
+opts.Add(
+ "system_certs_path",
+ "Use this path as TLS certificates default for editor and Linux/BSD export templates (for package maintainers)",
+ "",
+)
opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise epsilon (debug option)", False))
# Thirdparty libraries
@@ -698,7 +702,8 @@ if selected_platform in platform_list:
if env["warnings"] == "extra":
env.Append(CCFLAGS=["/W4"])
elif env["warnings"] == "all":
- env.Append(CCFLAGS=["/W3"])
+ # C4458 is like -Wshadow. Part of /W4 but let's apply it for the default /W3 too.
+ env.Append(CCFLAGS=["/W3", "/w4458"])
elif env["warnings"] == "moderate":
env.Append(CCFLAGS=["/W2"])
# Disable warnings which we don't plan to fix.
@@ -727,7 +732,7 @@ if selected_platform in platform_list:
common_warnings = []
if methods.using_gcc(env):
- common_warnings += ["-Wshadow-local", "-Wno-misleading-indentation"]
+ common_warnings += ["-Wshadow", "-Wno-misleading-indentation"]
if cc_version_major == 7: # Bogus warning fixed in 8+.
common_warnings += ["-Wno-strict-overflow"]
if cc_version_major < 11:
@@ -737,6 +742,7 @@ if selected_platform in platform_list:
if cc_version_major >= 12: # False positives in our error macros, see GH-58747.
common_warnings += ["-Wno-return-type"]
elif methods.using_clang(env) or methods.using_emcc(env):
+ common_warnings += ["-Wshadow-field-in-constructor", "-Wshadow-uncaptured-local"]
# We often implement `operator<` for structs of pointers as a requirement
# for putting them in `Set` or `Map`. We don't mind about unreliable ordering.
common_warnings += ["-Wno-ordered-compare-function-pointers"]
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 5aef9a9039..2b3e0b56e4 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -847,6 +847,7 @@ bool Input::is_emulating_touch_from_mouse() const {
// Calling this whenever the game window is focused helps unsticking the "touch mouse"
// if the OS or its abstraction class hasn't properly reported that touch pointers raised
void Input::ensure_touch_mouse_raised() {
+ _THREAD_SAFE_METHOD_
if (mouse_from_touch_index != -1) {
mouse_from_touch_index = -1;
diff --git a/core/math/color.cpp b/core/math/color.cpp
index f4b8903157..0d9325f236 100644
--- a/core/math/color.cpp
+++ b/core/math/color.cpp
@@ -188,32 +188,6 @@ float Color::get_v() const {
return max;
}
-float Color::get_hsl_h() const {
- return get_h();
-}
-
-float Color::get_hsl_s() const {
- float min = MIN(MIN(r, g), b);
- float max = MAX(MAX(r, g), b);
-
- float mid = (min + max) / 2.0f;
-
- if (mid == 0.0f || mid == 1.0f) {
- return 0.0f;
- }
-
- float delta = max - min;
-
- return delta / (1.0f - Math::abs(2.0f * mid - 1.0f));
-}
-
-float Color::get_hsl_l() const {
- float min = MIN(MIN(r, g), b);
- float max = MAX(MAX(r, g), b);
-
- return (min + max) / 2.0f;
-}
-
void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
int i;
float f, p, q, t;
@@ -268,59 +242,6 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
}
}
-void Color::set_hsl(float p_h, float p_s, float p_l, float p_alpha) {
- a = p_alpha;
-
- if (p_s == 0.0f) {
- // Achromatic (gray)
- r = g = b = p_l;
- return;
- }
-
- p_h *= 6.0f;
- p_h = Math::fmod(p_h, 6.0f);
-
- float c = (1.0f - Math::abs(2.0f * p_l - 1.0f)) * p_s;
- float x = c * (1.0f - Math::abs(Math::fmod(p_h, 2.0f) - 1.0f));
- float m = p_l - c / 2.0f;
-
- c += m;
- x += m;
-
- switch ((int)p_h) {
- case 0: // Red is the dominant color
- r = c;
- g = x;
- b = m;
- break;
- case 1: // Green is the dominant color
- r = x;
- g = c;
- b = m;
- break;
- case 2:
- r = m;
- g = c;
- b = x;
- break;
- case 3: // Blue is the dominant color
- r = m;
- g = x;
- b = c;
- break;
- case 4:
- r = x;
- g = m;
- b = c;
- break;
- default: // (5) Red is the dominant color
- r = c;
- g = m;
- b = x;
- break;
- }
-}
-
void Color::set_ok_hsl(float p_h, float p_s, float p_l, float p_alpha) {
ok_color::HSL hsl;
hsl.h = p_h;
@@ -547,12 +468,6 @@ Color Color::from_hsv(float p_h, float p_s, float p_v, float p_alpha) {
return c;
}
-Color Color::from_hsl(float p_h, float p_s, float p_l, float p_alpha) {
- Color c;
- c.set_hsl(p_h, p_s, p_l, p_alpha);
- return c;
-}
-
Color Color::from_rgbe9995(uint32_t p_rgbe) {
float r = p_rgbe & 0x1ff;
float g = (p_rgbe >> 9) & 0x1ff;
diff --git a/core/math/color.h b/core/math/color.h
index 4a056335c1..65d7377c1c 100644
--- a/core/math/color.h
+++ b/core/math/color.h
@@ -57,10 +57,6 @@ struct _NO_DISCARD_ Color {
float get_s() const;
float get_v() const;
void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0f);
- float get_hsl_h() const;
- float get_hsl_s() const;
- float get_hsl_l() const;
- void set_hsl(float p_h, float p_s, float p_l, float p_alpha = 1.0f);
float get_ok_hsl_h() const;
float get_ok_hsl_s() const;
float get_ok_hsl_l() const;
@@ -202,7 +198,6 @@ struct _NO_DISCARD_ Color {
static Color get_named_color(int p_idx);
static Color from_string(const String &p_string, const Color &p_default);
static Color from_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0f);
- static Color from_hsl(float p_h, float p_s, float p_l, float p_alpha = 1.0f);
static Color from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha = 1.0f);
static Color from_rgbe9995(uint32_t p_rgbe);
@@ -222,9 +217,6 @@ struct _NO_DISCARD_ Color {
_FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v(), a); }
_FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v(), a); }
_FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v, a); }
- _FORCE_INLINE_ void set_hsl_h(float p_h) { set_hsl(p_h, get_hsl_s(), get_hsl_l(), a); }
- _FORCE_INLINE_ void set_hsl_s(float p_s) { set_hsl(get_hsl_h(), p_s, get_hsl_l(), a); }
- _FORCE_INLINE_ void set_hsl_l(float p_l) { set_hsl(get_hsl_h(), get_hsl_s(), p_l, a); }
_FORCE_INLINE_ void set_ok_hsl_h(float p_h) { set_ok_hsl(p_h, get_ok_hsl_s(), get_ok_hsl_l(), a); }
_FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); }
_FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); }
diff --git a/core/math/convex_hull.cpp b/core/math/convex_hull.cpp
index a03438a339..76b3062944 100644
--- a/core/math/convex_hull.cpp
+++ b/core/math/convex_hull.cpp
@@ -596,9 +596,9 @@ private:
}
};
- enum Orientation { NONE,
- CLOCKWISE,
- COUNTER_CLOCKWISE };
+ enum Orientation { ORIENTATION_NONE,
+ ORIENTATION_CLOCKWISE,
+ ORIENTATION_COUNTER_CLOCKWISE };
Vector3 scaling;
Vector3 center;
@@ -1140,13 +1140,13 @@ ConvexHullInternal::Orientation ConvexHullInternal::get_orientation(const Edge *
CHULL_ASSERT(!m.is_zero());
int64_t dot = n.dot(m);
CHULL_ASSERT(dot != 0);
- return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
+ return (dot > 0) ? ORIENTATION_COUNTER_CLOCKWISE : ORIENTATION_CLOCKWISE;
}
- return COUNTER_CLOCKWISE;
+ return ORIENTATION_COUNTER_CLOCKWISE;
} else if (p_prev->prev == p_next) {
- return CLOCKWISE;
+ return ORIENTATION_CLOCKWISE;
} else {
- return NONE;
+ return ORIENTATION_NONE;
}
}
@@ -1176,7 +1176,7 @@ ConvexHullInternal::Edge *ConvexHullInternal::find_max_angle(bool p_ccw, const V
} else if ((cmp = cot.compare(p_min_cot)) < 0) {
p_min_cot = cot;
min_edge = e;
- } else if ((cmp == 0) && (p_ccw == (get_orientation(min_edge, e, p_s, t) == COUNTER_CLOCKWISE))) {
+ } else if ((cmp == 0) && (p_ccw == (get_orientation(min_edge, e, p_s, t) == ORIENTATION_COUNTER_CLOCKWISE))) {
min_edge = e;
}
}
@@ -1375,7 +1375,7 @@ void ConvexHullInternal::merge(IntermediateHull &p_h0, IntermediateHull &p_h1) {
int64_t dot = (*e->target - *c0).dot(normal);
CHULL_ASSERT(dot <= 0);
if ((dot == 0) && ((*e->target - *c0).dot(t) > 0)) {
- if (!start0 || (get_orientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE)) {
+ if (!start0 || (get_orientation(start0, e, s, Point32(0, 0, -1)) == ORIENTATION_CLOCKWISE)) {
start0 = e;
}
}
@@ -1390,7 +1390,7 @@ void ConvexHullInternal::merge(IntermediateHull &p_h0, IntermediateHull &p_h1) {
int64_t dot = (*e->target - *c1).dot(normal);
CHULL_ASSERT(dot <= 0);
if ((dot == 0) && ((*e->target - *c1).dot(t) > 0)) {
- if (!start1 || (get_orientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE)) {
+ if (!start1 || (get_orientation(start1, e, s, Point32(0, 0, -1)) == ORIENTATION_COUNTER_CLOCKWISE)) {
start1 = e;
}
}
diff --git a/core/math/static_raycaster.h b/core/math/static_raycaster.h
index 1bafc29c57..c53868e12d 100644
--- a/core/math/static_raycaster.h
+++ b/core/math/static_raycaster.h
@@ -59,15 +59,15 @@ public:
/*! Constructs a ray from origin, direction, and ray segment. Near
* has to be smaller than far. */
- _FORCE_INLINE_ Ray(const Vector3 &org,
- const Vector3 &dir,
- float tnear = 0.0f,
- float tfar = INFINITY) :
- org(org),
- tnear(tnear),
- dir(dir),
+ _FORCE_INLINE_ Ray(const Vector3 &p_org,
+ const Vector3 &p_dir,
+ float p_tnear = 0.0f,
+ float p_tfar = INFINITY) :
+ org(p_org),
+ tnear(p_tnear),
+ dir(p_dir),
time(0.0f),
- tfar(tfar),
+ tfar(p_tfar),
mask(-1),
u(0.0),
v(0.0),
diff --git a/core/object/object.h b/core/object/object.h
index c633208d7c..ae22851c15 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -61,7 +61,6 @@ enum PropertyHint {
PROPERTY_HINT_LAYERS_3D_RENDER,
PROPERTY_HINT_LAYERS_3D_PHYSICS,
PROPERTY_HINT_LAYERS_3D_NAVIGATION,
- PROPERTY_HINT_LAYERS_AVOIDANCE,
PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
PROPERTY_HINT_DIR, ///< a directory path must be passed
PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
@@ -86,6 +85,7 @@ enum PropertyHint {
PROPERTY_HINT_NODE_TYPE, ///< a node object type
PROPERTY_HINT_HIDE_QUATERNION_EDIT, /// Only Node3D::transform should hide the quaternion editor.
PROPERTY_HINT_PASSWORD,
+ PROPERTY_HINT_LAYERS_AVOIDANCE,
PROPERTY_HINT_MAX,
};
diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp
index 721c8d0a10..3dca6b73a6 100644
--- a/core/object/worker_thread_pool.cpp
+++ b/core/object/worker_thread_pool.cpp
@@ -140,9 +140,9 @@ void WorkerThreadPool::_process_task(Task *p_task) {
task_queue.add_last(&low_prio_task->task_elem);
post = true;
} else {
- low_priority_threads_used.decrement();
+ low_priority_threads_used--;
}
- task_mutex.lock();
+ task_mutex.unlock();
if (post) {
task_available_semaphore.post();
}
@@ -152,7 +152,7 @@ void WorkerThreadPool::_process_task(Task *p_task) {
void WorkerThreadPool::_thread_function(void *p_user) {
while (true) {
singleton->task_available_semaphore.wait();
- if (singleton->exit_threads.is_set()) {
+ if (singleton->exit_threads) {
break;
}
singleton->_process_task_queue();
@@ -168,14 +168,13 @@ void WorkerThreadPool::_post_task(Task *p_task, bool p_high_priority) {
task_mutex.lock();
p_task->low_priority = !p_high_priority;
if (!p_high_priority && use_native_low_priority_threads) {
- task_mutex.unlock();
p_task->low_priority_thread = native_thread_allocator.alloc();
+ task_mutex.unlock();
p_task->low_priority_thread->start(_native_low_priority_thread_function, p_task); // Pask task directly to thread.
-
- } else if (p_high_priority || low_priority_threads_used.get() < max_low_priority_threads) {
+ } else if (p_high_priority || low_priority_threads_used < max_low_priority_threads) {
task_queue.add_last(&p_task->task_elem);
if (!p_high_priority) {
- low_priority_threads_used.increment();
+ low_priority_threads_used++;
}
task_mutex.unlock();
task_available_semaphore.post();
@@ -251,6 +250,8 @@ void WorkerThreadPool::wait_for_task_completion(TaskID p_task_id) {
if (use_native_low_priority_threads && task->low_priority) {
task->low_priority_thread->wait_to_finish();
+
+ task_mutex.lock();
native_thread_allocator.free(task->low_priority_thread);
} else {
int *index = thread_ids.getptr(Thread::get_caller_id());
@@ -272,9 +273,10 @@ void WorkerThreadPool::wait_for_task_completion(TaskID p_task_id) {
} else {
task->done_semaphore.wait();
}
+
+ task_mutex.lock();
}
- task_mutex.lock();
tasks.erase(p_task_id);
task_allocator.free(task);
task_mutex.unlock();
@@ -379,8 +381,8 @@ void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
if (group->low_priority_native_tasks.size() > 0) {
for (Task *task : group->low_priority_native_tasks) {
task->low_priority_thread->wait_to_finish();
- native_thread_allocator.free(task->low_priority_thread);
task_mutex.lock();
+ native_thread_allocator.free(task->low_priority_thread);
task_allocator.free(task);
task_mutex.unlock();
}
@@ -443,7 +445,7 @@ void WorkerThreadPool::finish() {
}
task_mutex.unlock();
- exit_threads.set_to(true);
+ exit_threads = true;
for (uint32_t i = 0; i < threads.size(); i++) {
task_available_semaphore.post();
diff --git a/core/object/worker_thread_pool.h b/core/object/worker_thread_pool.h
index c62e05fc28..d47c6ad714 100644
--- a/core/object/worker_thread_pool.h
+++ b/core/object/worker_thread_pool.h
@@ -107,7 +107,7 @@ private:
};
TightLocalVector<ThreadData> threads;
- SafeFlag exit_threads;
+ bool exit_threads = false;
HashMap<Thread::ID, int> thread_ids;
HashMap<TaskID, Task *> tasks;
@@ -115,7 +115,7 @@ private:
bool use_native_low_priority_threads = false;
uint32_t max_low_priority_threads = 0;
- SafeNumeric<uint32_t> low_priority_threads_used;
+ uint32_t low_priority_threads_used = 0;
uint64_t last_task = 1;
diff --git a/core/os/os.h b/core/os/os.h
index db1f1f13c9..1652c1ed90 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -137,6 +137,7 @@ public:
virtual String get_stdin_string() = 0;
virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) = 0; // Should return cryptographically-safe random bytes.
+ virtual String get_system_ca_certificates() { return ""; } // Concatenated certificates in PEM format.
virtual PackedStringArray get_connected_midi_inputs();
virtual void open_midi_inputs();
diff --git a/core/os/time.cpp b/core/os/time.cpp
index 12e6f08525..038e4adc03 100644
--- a/core/os/time.cpp
+++ b/core/os/time.cpp
@@ -382,10 +382,10 @@ String Time::get_time_string_from_system(bool p_utc) const {
Dictionary Time::get_time_zone_from_system() const {
OS::TimeZoneInfo info = OS::get_singleton()->get_time_zone_info();
- Dictionary timezone;
- timezone["bias"] = info.bias;
- timezone["name"] = info.name;
- return timezone;
+ Dictionary ret_timezone;
+ ret_timezone["bias"] = info.bias;
+ ret_timezone["name"] = info.name;
+ return ret_timezone;
}
double Time::get_unix_time_from_system() const {
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index a374e7c009..b8b8119618 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -302,15 +302,9 @@ void register_core_settings() {
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "network/limits/packet_peer_stream/max_buffer_po2", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), (16));
GLOBAL_DEF(PropertyInfo(Variant::STRING, "network/tls/certificate_bundle_override", PROPERTY_HINT_FILE, "*.crt"), "");
- int worker_threads = GLOBAL_DEF("threading/worker_pool/max_threads", -1);
- bool low_priority_use_system_threads = GLOBAL_DEF("threading/worker_pool/use_system_threads_for_low_priority_tasks", true);
- float low_property_ratio = GLOBAL_DEF("threading/worker_pool/low_priority_thread_ratio", 0.3);
-
- if (Engine::get_singleton()->is_editor_hint() || Engine::get_singleton()->is_project_manager_hint()) {
- worker_thread_pool->init();
- } else {
- worker_thread_pool->init(worker_threads, low_priority_use_system_threads, low_property_ratio);
- }
+ GLOBAL_DEF("threading/worker_pool/max_threads", -1);
+ GLOBAL_DEF("threading/worker_pool/use_system_threads_for_low_priority_tasks", true);
+ GLOBAL_DEF("threading/worker_pool/low_priority_thread_ratio", 0.3);
}
void register_core_singletons() {
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index e22970ef5c..0a836c125a 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -2002,7 +2002,6 @@ static void _register_variant_builtin_methods() {
bind_static_method(Color, html_is_valid, sarray("color"), varray());
bind_static_method(Color, from_string, sarray("str", "default"), varray());
bind_static_method(Color, from_hsv, sarray("h", "s", "v", "alpha"), varray(1.0));
- bind_static_method(Color, from_hsl, sarray("h", "s", "l", "alpha"), varray(1.0));
bind_static_method(Color, from_ok_hsl, sarray("h", "s", "l", "alpha"), varray(1.0));
bind_static_method(Color, from_rgbe9995, sarray("rgbe"), varray());
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index ce035f5f7a..30fb5d0e9f 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -139,10 +139,6 @@ void register_named_setters_getters() {
REGISTER_MEMBER(Color, h);
REGISTER_MEMBER(Color, s);
REGISTER_MEMBER(Color, v);
-
- REGISTER_MEMBER(Color, hsl_h);
- REGISTER_MEMBER(Color, hsl_s);
- REGISTER_MEMBER(Color, hsl_l);
}
void unregister_named_setters_getters() {
diff --git a/core/variant/variant_setget.h b/core/variant/variant_setget.h
index db6e273817..176967344f 100644
--- a/core/variant/variant_setget.h
+++ b/core/variant/variant_setget.h
@@ -344,10 +344,6 @@ SETGET_NUMBER_STRUCT_FUNC(Color, double, h, set_h, get_h)
SETGET_NUMBER_STRUCT_FUNC(Color, double, s, set_s, get_s)
SETGET_NUMBER_STRUCT_FUNC(Color, double, v, set_v, get_v)
-SETGET_NUMBER_STRUCT_FUNC(Color, double, hsl_h, set_hsl_h, get_hsl_h)
-SETGET_NUMBER_STRUCT_FUNC(Color, double, hsl_s, set_hsl_s, get_hsl_s)
-SETGET_NUMBER_STRUCT_FUNC(Color, double, hsl_l, set_hsl_l, get_hsl_l)
-
SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_h, set_ok_hsl_h, get_ok_hsl_h)
SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_s, set_ok_hsl_s, get_ok_hsl_s)
SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_l, set_ok_hsl_l, get_ok_hsl_l)
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index 1ca44db11c..ad68d2f818 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -2695,39 +2695,39 @@
<constant name="PROPERTY_HINT_LAYERS_3D_NAVIGATION" value="12" enum="PropertyHint">
Hints that an [int] property is a bitmask using the optionally named 3D navigation layers.
</constant>
- <constant name="PROPERTY_HINT_LAYERS_AVOIDANCE" value="13" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LAYERS_AVOIDANCE" value="37" enum="PropertyHint">
Hints that an integer property is a bitmask using the optionally named avoidance layers.
</constant>
- <constant name="PROPERTY_HINT_FILE" value="14" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_FILE" value="13" enum="PropertyHint">
Hints that a [String] property is a path to a file. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code].
</constant>
- <constant name="PROPERTY_HINT_DIR" value="15" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_DIR" value="14" enum="PropertyHint">
Hints that a [String] property is a path to a directory. Editing it will show a file dialog for picking the path.
</constant>
- <constant name="PROPERTY_HINT_GLOBAL_FILE" value="16" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_GLOBAL_FILE" value="15" enum="PropertyHint">
Hints that a [String] property is an absolute path to a file outside the project folder. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards, like [code]"*.png,*.jpg"[/code].
</constant>
- <constant name="PROPERTY_HINT_GLOBAL_DIR" value="17" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_GLOBAL_DIR" value="16" enum="PropertyHint">
Hints that a [String] property is an absolute path to a directory outside the project folder. Editing it will show a file dialog for picking the path.
</constant>
- <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="18" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="17" enum="PropertyHint">
Hints that a property is an instance of a [Resource]-derived type, optionally specified via the hint string (e.g. [code]"Texture2D"[/code]). Editing it will show a popup menu of valid resource types to instantiate.
</constant>
- <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="19" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="18" enum="PropertyHint">
Hints that a [String] property is text with line breaks. Editing it will show a text input field where line breaks can be typed.
</constant>
- <constant name="PROPERTY_HINT_EXPRESSION" value="20" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_EXPRESSION" value="19" enum="PropertyHint">
Hints that a [String] property is an [Expression].
</constant>
- <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="21" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="20" enum="PropertyHint">
Hints that a [String] property should show a placeholder text on its input field, if empty. The hint string is the placeholder text to use.
</constant>
- <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="22" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="21" enum="PropertyHint">
Hints that a [Color] property should be edited without affecting its transparency ([member Color.a] is not editable).
</constant>
- <constant name="PROPERTY_HINT_OBJECT_ID" value="23" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_OBJECT_ID" value="22" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_TYPE_STRING" value="24" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_TYPE_STRING" value="23" enum="PropertyHint">
Hint that a property represents a particular type. If a property is [constant TYPE_STRING], allows to set a type from the create dialog. If you need to create an [Array] to contain elements of a specific type, the [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code] for specifying [Resource] types. For instance:
[codeblock]
hint_string = "%s:" % [TYPE_INT] # Array of integers.
@@ -2737,34 +2737,34 @@
[/codeblock]
[b]Note:[/b] The final colon is required for properly detecting built-in types.
</constant>
- <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="25" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="24" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="26" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="25" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="27" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="26" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_SAVE_FILE" value="28" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_SAVE_FILE" value="27" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_GLOBAL_SAVE_FILE" value="29" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_GLOBAL_SAVE_FILE" value="28" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="30" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="29" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_INT_IS_POINTER" value="31" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_INT_IS_POINTER" value="30" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_ARRAY_TYPE" value="32" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_ARRAY_TYPE" value="31" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_LOCALE_ID" value="33" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LOCALE_ID" value="32" enum="PropertyHint">
Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country.
</constant>
- <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="34" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="33" enum="PropertyHint">
Hints that a dictionary property is string translation map. Dictionary keys are locale codes and, values are translated strings.
</constant>
- <constant name="PROPERTY_HINT_NODE_TYPE" value="35" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_TYPE" value="34" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_HIDE_QUATERNION_EDIT" value="36" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_HIDE_QUATERNION_EDIT" value="35" enum="PropertyHint">
Hints that a quaternion property should disable the temporary euler editor.
</constant>
- <constant name="PROPERTY_HINT_PASSWORD" value="37" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PASSWORD" value="36" enum="PropertyHint">
Hints that a string property is a password, and every character is replaced with the secret character.
</constant>
<constant name="PROPERTY_HINT_MAX" value="38" enum="PropertyHint">
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index 0592f5287b..b73ed59715 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -141,24 +141,6 @@
[/codeblocks]
</description>
</method>
- <method name="from_hsl" qualifiers="static">
- <return type="Color" />
- <param index="0" name="h" type="float" />
- <param index="1" name="s" type="float" />
- <param index="2" name="l" type="float" />
- <param index="3" name="alpha" type="float" default="1.0" />
- <description>
- Constructs a color from an [url=https://en.wikipedia.org/wiki/HSL_and_HSV]HSL profile[/url]. The hue ([param h]), saturation ([param s]), and lightness ([param l]) are typically between 0.0 and 1.0.
- [codeblocks]
- [gdscript]
- var color = Color.from_hsl(0.58, 0.5, 0.79, 0.8)
- [/gdscript]
- [csharp]
- var color = Color.FromHsl(0.58f, 0.5f, 0.79f, 0.8f);
- [/csharp]
- [/codeblocks]
- </description>
- </method>
<method name="from_hsv" qualifiers="static">
<return type="Color" />
<param index="0" name="h" type="float" />
@@ -511,15 +493,6 @@
<member name="h" type="float" setter="" getter="" default="0.0">
The HSV hue of this color, on the range 0 to 1.
</member>
- <member name="hsl_h" type="float" setter="" getter="" default="0.0">
- The HSL hue of this color, on the range 0 to 1.
- </member>
- <member name="hsl_l" type="float" setter="" getter="" default="0.0">
- The HSL lightness of this color, on the range 0 to 1.
- </member>
- <member name="hsl_s" type="float" setter="" getter="" default="0.0">
- The HSL saturation of this color, on the range 0 to 1.
- </member>
<member name="r" type="float" setter="" getter="" default="0.0">
The color's red component, typically on the range of 0 to 1.
</member>
diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml
index 2da5ad3cac..4aca92776f 100644
--- a/doc/classes/ItemList.xml
+++ b/doc/classes/ItemList.xml
@@ -64,6 +64,7 @@
<description>
Returns the item index at the given [param position].
When there is no item at that point, -1 will be returned if [param exact] is [code]true[/code], and the closest item index will be returned otherwise.
+ [b]Note:[/b] The returned value is unreliable if called right after modifying the [ItemList], before it redraws in the next frame.
</description>
</method>
<method name="get_item_custom_bg_color" qualifiers="const">
@@ -115,6 +116,15 @@
Returns the metadata value of the specified index.
</description>
</method>
+ <method name="get_item_rect" qualifiers="const">
+ <return type="Rect2" />
+ <param index="0" name="idx" type="int" />
+ <param index="1" name="expand" type="bool" default="true" />
+ <description>
+ Returns the position and size of the item with the specified index, in the coordinate system of the [ItemList] node. If [param expand] is [code]true[/code] the last column expands to fill the rest of the row.
+ [b]Note:[/b] The returned value is unreliable if called right after modifying the [ItemList], before it redraws in the next frame.
+ </description>
+ </method>
<method name="get_item_text" qualifiers="const">
<return type="String" />
<param index="0" name="idx" type="int" />
diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml
index bb5992f112..1f1c0993d5 100644
--- a/doc/classes/NavigationRegion2D.xml
+++ b/doc/classes/NavigationRegion2D.xml
@@ -76,5 +76,8 @@
<member name="travel_cost" type="float" setter="set_travel_cost" getter="get_travel_cost" default="1.0">
When pathfinding moves inside this region's navigation mesh the traveled distances are multiplied with [code]travel_cost[/code] for determining the shortest path.
</member>
+ <member name="use_edge_connections" type="bool" setter="set_use_edge_connections" getter="get_use_edge_connections" default="true">
+ If enabled the navigation region will use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin.
+ </member>
</members>
</class>
diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml
index a123381901..0988d07e8c 100644
--- a/doc/classes/NavigationRegion3D.xml
+++ b/doc/classes/NavigationRegion3D.xml
@@ -61,6 +61,9 @@
<member name="travel_cost" type="float" setter="set_travel_cost" getter="get_travel_cost" default="1.0">
When pathfinding moves inside this region's navigation mesh the traveled distances are multiplied with [code]travel_cost[/code] for determining the shortest path.
</member>
+ <member name="use_edge_connections" type="bool" setter="set_use_edge_connections" getter="get_use_edge_connections" default="true">
+ If enabled the navigation region will use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin.
+ </member>
</members>
<signals>
<signal name="bake_finished">
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index f9e6a69452..e2293f2439 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -404,6 +404,13 @@
Returns all navigation regions [RID]s that are currently assigned to the requested navigation [param map].
</description>
</method>
+ <method name="map_get_use_edge_connections" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="map" type="RID" />
+ <description>
+ Returns whether the navigation [param map] allows navigation regions to use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin.
+ </description>
+ </method>
<method name="map_is_active" qualifiers="const">
<return type="bool" />
<param index="0" name="map" type="RID" />
@@ -443,6 +450,14 @@
Set the map's link connection radius used to connect links to navigation polygons.
</description>
</method>
+ <method name="map_set_use_edge_connections">
+ <return type="void" />
+ <param index="0" name="map" type="RID" />
+ <param index="1" name="enabled" type="bool" />
+ <description>
+ Set the navigation [param map] edge connection use. If [param enabled] the navigation map allows navigation regions to use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin.
+ </description>
+ </method>
<method name="obstacle_create">
<return type="RID" />
<description>
@@ -559,6 +574,13 @@
Returns the travel cost of this [param region].
</description>
</method>
+ <method name="region_get_use_edge_connections" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="region" type="RID" />
+ <description>
+ Returns whether the navigation [param region] is set to use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin.
+ </description>
+ </method>
<method name="region_owns_point" qualifiers="const">
<return type="bool" />
<param index="0" name="region" type="RID" />
@@ -625,6 +647,14 @@
Sets the [param travel_cost] for this [param region].
</description>
</method>
+ <method name="region_set_use_edge_connections">
+ <return type="void" />
+ <param index="0" name="region" type="RID" />
+ <param index="1" name="enabled" type="bool" />
+ <description>
+ If [param enabled] the navigation [param region] will use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin.
+ </description>
+ </method>
<method name="set_debug_enabled">
<return type="void" />
<param index="0" name="enabled" type="bool" />
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 3fe0793715..cc6b3b8ca4 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -461,6 +461,13 @@
Returns the map's up direction.
</description>
</method>
+ <method name="map_get_use_edge_connections" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="map" type="RID" />
+ <description>
+ Returns true if the navigation [param map] allows navigation regions to use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin.
+ </description>
+ </method>
<method name="map_is_active" qualifiers="const">
<return type="bool" />
<param index="0" name="map" type="RID" />
@@ -508,6 +515,14 @@
Sets the map up direction.
</description>
</method>
+ <method name="map_set_use_edge_connections">
+ <return type="void" />
+ <param index="0" name="map" type="RID" />
+ <param index="1" name="enabled" type="bool" />
+ <description>
+ Set the navigation [param map] edge connection use. If [param enabled] the navigation map allows navigation regions to use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin.
+ </description>
+ </method>
<method name="obstacle_create">
<return type="RID" />
<description>
@@ -641,6 +656,13 @@
Returns the travel cost of this [param region].
</description>
</method>
+ <method name="region_get_use_edge_connections" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="region" type="RID" />
+ <description>
+ Returns true if the navigation [param region] is set to use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin.
+ </description>
+ </method>
<method name="region_owns_point" qualifiers="const">
<return type="bool" />
<param index="0" name="region" type="RID" />
@@ -707,6 +729,14 @@
Sets the [param travel_cost] for this [param region].
</description>
</method>
+ <method name="region_set_use_edge_connections">
+ <return type="void" />
+ <param index="0" name="region" type="RID" />
+ <param index="1" name="enabled" type="bool" />
+ <description>
+ If [param enabled] the navigation [param region] will use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin.
+ </description>
+ </method>
<method name="set_active">
<return type="void" />
<param index="0" name="active" type="bool" />
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 2c54e364c7..818e402067 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1915,6 +1915,9 @@
<member name="navigation/2d/default_link_connection_radius" type="int" setter="" getter="" default="4">
Default link connection radius for 2D navigation maps. See [method NavigationServer2D.map_set_link_connection_radius].
</member>
+ <member name="navigation/2d/use_edge_connections" type="bool" setter="" getter="" default="true">
+ If enabled 2D navigation regions will use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin. This setting only affects World2D default navigation maps.
+ </member>
<member name="navigation/3d/default_cell_size" type="float" setter="" getter="" default="0.25">
Default cell size for 3D navigation maps. See [method NavigationServer3D.map_set_cell_size].
</member>
@@ -1924,6 +1927,9 @@
<member name="navigation/3d/default_link_connection_radius" type="float" setter="" getter="" default="1.0">
Default link connection radius for 3D navigation maps. See [method NavigationServer3D.map_set_link_connection_radius].
</member>
+ <member name="navigation/3d/use_edge_connections" type="bool" setter="" getter="" default="true">
+ If enabled 3D navigation regions will use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin. This setting only affects World3D default navigation maps.
+ </member>
<member name="navigation/avoidance/thread_model/avoidance_use_high_priority_threads" type="bool" setter="" getter="" default="true">
If enabled and avoidance calculations use multiple threads the threads run with high priority.
</member>
diff --git a/drivers/gl_context/SCsub b/drivers/gl_context/SCsub
index 2204c486c6..91240ce3e3 100644
--- a/drivers/gl_context/SCsub
+++ b/drivers/gl_context/SCsub
@@ -10,7 +10,11 @@ if env["platform"] in ["haiku", "macos", "windows", "linuxbsd"]:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env.Prepend(CPPPATH=[thirdparty_dir])
+ # Treat glad headers as system headers to avoid raising warnings. Not supported on MSVC.
+ if not env.msvc:
+ env.Append(CPPFLAGS=["-isystem", Dir(thirdparty_dir).path])
+ else:
+ env.Prepend(CPPPATH=[thirdparty_dir])
env.Append(CPPDEFINES=["GLAD_ENABLED"])
env.Append(CPPDEFINES=["GLES_OVER_GL"])
diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp
index 026f7467a8..8da5e657cd 100644
--- a/drivers/gles3/storage/light_storage.cpp
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -76,6 +76,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
+ light.param[RS::LIGHT_PARAM_INTENSITY] = p_type == RS::LIGHT_DIRECTIONAL ? 100000.0 : 1000.0;
light_owner.initialize_rid(p_light, light);
}
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 3114be9163..ab94d8911f 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -222,8 +222,8 @@ Error AudioDriverPulseAudio::init_output_device() {
break;
}
- int latency = GLOBAL_GET("audio/driver/output_latency");
- buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
+ int tmp_latency = GLOBAL_GET("audio/driver/output_latency");
+ buffer_frames = closest_power_of_2(tmp_latency * mix_rate / 1000);
pa_buffer_size = buffer_frames * pa_map.channels;
print_verbose("PulseAudio: detected " + itos(pa_map.channels) + " output channels");
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 3c2f36c7c0..e9affe41af 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -301,11 +301,11 @@ bool FileAccessUnix::file_exists(const String &p_path) {
uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
String file = fix_path(p_file);
- struct stat flags = {};
- int err = stat(file.utf8().get_data(), &flags);
+ struct stat status = {};
+ int err = stat(file.utf8().get_data(), &status);
if (!err) {
- return flags.st_mtime;
+ return status.st_mtime;
} else {
print_verbose("Failed to get modified time for: " + p_file + "");
return 0;
@@ -314,11 +314,11 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
uint32_t FileAccessUnix::_get_unix_permissions(const String &p_file) {
String file = fix_path(p_file);
- struct stat flags = {};
- int err = stat(file.utf8().get_data(), &flags);
+ struct stat status = {};
+ int err = stat(file.utf8().get_data(), &status);
if (!err) {
- return flags.st_mode & 0x7FF; //only permissions
+ return status.st_mode & 0x7FF; //only permissions
} else {
ERR_FAIL_V_MSG(0, "Failed to get unix permissions for: " + p_file + ".");
}
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index e7dc2fabe1..69d9baf910 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -8924,6 +8924,11 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
}
}
+ for (int i = 0; i < frame_count; i++) {
+ //Reset all queries in a query pool before doing any operations with them.
+ vkCmdResetQueryPool(frames[0].setup_command_buffer, frames[i].timestamp_pool, 0, max_timestamp_query_elements);
+ }
+
staging_buffer_block_size = GLOBAL_GET("rendering/rendering_device/staging_buffer/block_size_kb");
staging_buffer_block_size = MAX(4u, staging_buffer_block_size);
staging_buffer_block_size *= 1024; // Kb -> bytes.
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index b4ca499bcf..bef34b9e73 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -1732,7 +1732,7 @@ ScriptEditorDebugger::ScriptEditorDebugger() {
{ //debugger
VBoxContainer *vbc = memnew(VBoxContainer);
- vbc->set_name(TTR("Debugger"));
+ vbc->set_name(TTR("Stack Trace"));
Control *dbg = vbc;
HBoxContainer *hbc = memnew(HBoxContainer);
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 9ed8cf7c21..93788dc8b1 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -69,11 +69,15 @@ void EditorAudioBus::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
+ Ref<Texture2D> active_bus_texture = get_theme_icon(SNAME("BusVuActive"), SNAME("EditorIcons"));
for (int i = 0; i < CHANNELS_MAX; i++) {
- channel[i].vu_l->set_under_texture(get_theme_icon(SNAME("BusVuEmpty"), SNAME("EditorIcons")));
- channel[i].vu_l->set_progress_texture(get_theme_icon(SNAME("BusVuFull"), SNAME("EditorIcons")));
- channel[i].vu_r->set_under_texture(get_theme_icon(SNAME("BusVuEmpty"), SNAME("EditorIcons")));
- channel[i].vu_r->set_progress_texture(get_theme_icon(SNAME("BusVuFull"), SNAME("EditorIcons")));
+ channel[i].vu_l->set_under_texture(active_bus_texture);
+ channel[i].vu_l->set_tint_under(Color(0.75, 0.75, 0.75));
+ channel[i].vu_l->set_progress_texture(active_bus_texture);
+
+ channel[i].vu_r->set_under_texture(active_bus_texture);
+ channel[i].vu_r->set_tint_under(Color(0.75, 0.75, 0.75));
+ channel[i].vu_r->set_progress_texture(active_bus_texture);
channel[i].prev_active = true;
}
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 6f763d59f4..16128603b5 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -3302,6 +3302,7 @@ void EditorNode::_update_addon_config() {
if (enabled_addons.size() == 0) {
ProjectSettings::get_singleton()->set("editor_plugins/enabled", Variant());
} else {
+ enabled_addons.sort();
ProjectSettings::get_singleton()->set("editor_plugins/enabled", enabled_addons);
}
diff --git a/editor/icons/BusVuFull.svg b/editor/icons/BusVuActive.svg
index 0bc00971c0..0bc00971c0 100644
--- a/editor/icons/BusVuFull.svg
+++ b/editor/icons/BusVuActive.svg
diff --git a/editor/icons/BusVuEmpty.svg b/editor/icons/BusVuEmpty.svg
deleted file mode 100644
index 88a14bc3ee..0000000000
--- a/editor/icons/BusVuEmpty.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="128" viewBox="0 0 16 128" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="926.36" y2="1050.36"><stop offset="0" stop-color="#ff5f5f"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#5fff97"/></linearGradient><g transform="translate(0 -924.36)"><path d="m3 926.36c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 5c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1z" fill="url(#a)"/><path d="m3 2c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 5c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1zm0 3c-.554 0-1 .446-1 1s.446 1 1 1h10c.554 0 1-.446 1-1s-.446-1-1-1z" fill-opacity=".19608" transform="translate(0 924.36)"/></g></svg>
diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp
index a8d746fde6..a499fc4feb 100644
--- a/editor/import/collada.cpp
+++ b/editor/import/collada.cpp
@@ -44,10 +44,10 @@
/* HELPERS */
-String Collada::Effect::get_texture_path(const String &p_source, Collada &state) const {
+String Collada::Effect::get_texture_path(const String &p_source, Collada &p_state) const {
const String &image = p_source;
- ERR_FAIL_COND_V(!state.state.image_map.has(image), "");
- return state.state.image_map[image].path;
+ ERR_FAIL_COND_V(!p_state.state.image_map.has(image), "");
+ return p_state.state.image_map[image].path;
}
Transform3D Collada::get_root_transform() const {
@@ -58,9 +58,9 @@ Transform3D Collada::get_root_transform() const {
return unit_scale_transform;
}
-void Collada::Vertex::fix_unit_scale(const Collada &state) {
+void Collada::Vertex::fix_unit_scale(const Collada &p_state) {
#ifdef COLLADA_IMPORT_SCALE_SCENE
- vertex *= state.state.unit_scale;
+ vertex *= p_state.state.unit_scale;
#endif
}
@@ -102,27 +102,27 @@ Transform3D Collada::fix_transform(const Transform3D &p_transform) {
//return state.matrix_fix * p_transform;
}
-static Transform3D _read_transform_from_array(const Vector<float> &array, int ofs = 0) {
+static Transform3D _read_transform_from_array(const Vector<float> &p_array, int p_ofs = 0) {
Transform3D tr;
// i wonder why collada matrices are transposed, given that's opposed to opengl..
- tr.basis.rows[0][0] = array[0 + ofs];
- tr.basis.rows[0][1] = array[1 + ofs];
- tr.basis.rows[0][2] = array[2 + ofs];
- tr.basis.rows[1][0] = array[4 + ofs];
- tr.basis.rows[1][1] = array[5 + ofs];
- tr.basis.rows[1][2] = array[6 + ofs];
- tr.basis.rows[2][0] = array[8 + ofs];
- tr.basis.rows[2][1] = array[9 + ofs];
- tr.basis.rows[2][2] = array[10 + ofs];
- tr.origin.x = array[3 + ofs];
- tr.origin.y = array[7 + ofs];
- tr.origin.z = array[11 + ofs];
+ tr.basis.rows[0][0] = p_array[0 + p_ofs];
+ tr.basis.rows[0][1] = p_array[1 + p_ofs];
+ tr.basis.rows[0][2] = p_array[2 + p_ofs];
+ tr.basis.rows[1][0] = p_array[4 + p_ofs];
+ tr.basis.rows[1][1] = p_array[5 + p_ofs];
+ tr.basis.rows[1][2] = p_array[6 + p_ofs];
+ tr.basis.rows[2][0] = p_array[8 + p_ofs];
+ tr.basis.rows[2][1] = p_array[9 + p_ofs];
+ tr.basis.rows[2][2] = p_array[10 + p_ofs];
+ tr.origin.x = p_array[3 + p_ofs];
+ tr.origin.y = p_array[7 + p_ofs];
+ tr.origin.z = p_array[11 + p_ofs];
return tr;
}
/* STRUCTURES */
-Transform3D Collada::Node::compute_transform(const Collada &state) const {
+Transform3D Collada::Node::compute_transform(const Collada &p_state) const {
Transform3D xform;
for (int i = 0; i < xform_list.size(); i++) {
@@ -160,7 +160,7 @@ Transform3D Collada::Node::compute_transform(const Collada &state) const {
}
#ifdef COLLADA_IMPORT_SCALE_SCENE
- xform.origin *= state.state.unit_scale;
+ xform.origin *= p_state.state.unit_scale;
#endif
return xform;
}
@@ -243,41 +243,41 @@ Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) const {
ERR_FAIL_V(Vector<float>());
}
-void Collada::_parse_asset(XMLParser &parser) {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
+void Collada::_parse_asset(XMLParser &p_parser) {
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String name = p_parser.get_node_name();
if (name == "up_axis") {
- parser.read();
- if (parser.get_node_data() == "X_UP") {
+ p_parser.read();
+ if (p_parser.get_node_data() == "X_UP") {
state.up_axis = Vector3::AXIS_X;
}
- if (parser.get_node_data() == "Y_UP") {
+ if (p_parser.get_node_data() == "Y_UP") {
state.up_axis = Vector3::AXIS_Y;
}
- if (parser.get_node_data() == "Z_UP") {
+ if (p_parser.get_node_data() == "Z_UP") {
state.up_axis = Vector3::AXIS_Z;
}
- COLLADA_PRINT("up axis: " + parser.get_node_data());
+ COLLADA_PRINT("up axis: " + p_parser.get_node_data());
} else if (name == "unit") {
- state.unit_scale = parser.get_named_attribute_value("meter").to_float();
+ state.unit_scale = p_parser.get_named_attribute_value("meter").to_float();
COLLADA_PRINT("unit scale: " + rtos(state.unit_scale));
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "asset") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "asset") {
break; //end of <asset>
}
}
}
-void Collada::_parse_image(XMLParser &parser) {
- String id = parser.get_named_attribute_value("id");
+void Collada::_parse_image(XMLParser &p_parser) {
+ String id = p_parser.get_named_attribute_value("id");
if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty()) {
- parser.skip_section();
+ if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
return;
}
@@ -286,19 +286,19 @@ void Collada::_parse_image(XMLParser &parser) {
if (state.version < State::Version(1, 4, 0)) {
/* <1.4 */
- String path = parser.get_named_attribute_value("source").strip_edges();
+ String path = p_parser.get_named_attribute_value("source").strip_edges();
if (!path.contains("://") && path.is_relative_path()) {
// path is relative to file being loaded, so convert to a resource path
image.path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().path_join(path.uri_decode()));
}
} else {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String name = p_parser.get_node_name();
if (name == "init_from") {
- parser.read();
- String path = parser.get_node_data().strip_edges().uri_decode();
+ p_parser.read();
+ String path = p_parser.get_node_data().strip_edges().uri_decode();
if (!path.contains("://") && path.is_relative_path()) {
// path is relative to file being loaded, so convert to a resource path
@@ -314,11 +314,11 @@ void Collada::_parse_image(XMLParser &parser) {
} else if (name == "data") {
ERR_PRINT("COLLADA Embedded image data not supported!");
- } else if (name == "extra" && !parser.is_empty()) {
- parser.skip_section();
+ } else if (name == "extra" && !p_parser.is_empty()) {
+ p_parser.skip_section();
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "image") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "image") {
break; //end of <asset>
}
}
@@ -327,29 +327,29 @@ void Collada::_parse_image(XMLParser &parser) {
state.image_map[id] = image;
}
-void Collada::_parse_material(XMLParser &parser) {
+void Collada::_parse_material(XMLParser &p_parser) {
if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty()) {
- parser.skip_section();
+ if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
return;
}
Material material;
- String id = parser.get_named_attribute_value("id");
- if (parser.has_attribute("name")) {
- material.name = parser.get_named_attribute_value("name");
+ String id = p_parser.get_named_attribute_value("id");
+ if (p_parser.has_attribute("name")) {
+ material.name = p_parser.get_named_attribute_value("name");
}
if (state.version < State::Version(1, 4, 0)) {
/* <1.4 */
ERR_PRINT("Collada Materials < 1.4 are not supported (yet)");
} else {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT && parser.get_node_name() == "instance_effect") {
- material.instance_effect = _uri_to_id(parser.get_named_attribute_value("url"));
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "material") {
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT && p_parser.get_node_name() == "instance_effect") {
+ material.instance_effect = _uri_to_id(p_parser.get_named_attribute_value("url"));
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "material") {
break; //end of <asset>
}
}
@@ -359,8 +359,8 @@ void Collada::_parse_material(XMLParser &parser) {
}
//! reads floats from inside of xml element until end of xml element
-Vector<float> Collada::_read_float_array(XMLParser &parser) {
- if (parser.is_empty()) {
+Vector<float> Collada::_read_float_array(XMLParser &p_parser) {
+ if (p_parser.is_empty()) {
return Vector<float>();
}
@@ -371,16 +371,16 @@ Vector<float> Collada::_read_float_array(XMLParser &parser) {
splitters.push_back("\t");
Vector<float> array;
- while (parser.read() == OK) {
+ while (p_parser.read() == OK) {
// TODO: check for comments inside the element
// and ignore them.
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
+ if (p_parser.get_node_type() == XMLParser::NODE_TEXT) {
// parse float data
- String str = parser.get_node_data();
+ String str = p_parser.get_node_data();
array = str.split_floats_mk(splitters, false);
//array=str.split_floats(" ",false);
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END) {
break; // end parsing text
}
}
@@ -388,21 +388,21 @@ Vector<float> Collada::_read_float_array(XMLParser &parser) {
return array;
}
-Vector<String> Collada::_read_string_array(XMLParser &parser) {
- if (parser.is_empty()) {
+Vector<String> Collada::_read_string_array(XMLParser &p_parser) {
+ if (p_parser.is_empty()) {
return Vector<String>();
}
Vector<String> array;
- while (parser.read() == OK) {
+ while (p_parser.read() == OK) {
// TODO: check for comments inside the element
// and ignore them.
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
+ if (p_parser.get_node_type() == XMLParser::NODE_TEXT) {
// parse String data
- String str = parser.get_node_data();
+ String str = p_parser.get_node_data();
array = str.split_spaces();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END) {
break; // end parsing text
}
}
@@ -410,21 +410,21 @@ Vector<String> Collada::_read_string_array(XMLParser &parser) {
return array;
}
-Transform3D Collada::_read_transform(XMLParser &parser) {
- if (parser.is_empty()) {
+Transform3D Collada::_read_transform(XMLParser &p_parser) {
+ if (p_parser.is_empty()) {
return Transform3D();
}
Vector<String> array;
- while (parser.read() == OK) {
+ while (p_parser.read() == OK) {
// TODO: check for comments inside the element
// and ignore them.
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
+ if (p_parser.get_node_type() == XMLParser::NODE_TEXT) {
// parse float data
- String str = parser.get_node_data();
+ String str = p_parser.get_node_data();
array = str.split_spaces();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END) {
break; // end parsing text
}
}
@@ -439,332 +439,332 @@ Transform3D Collada::_read_transform(XMLParser &parser) {
return _read_transform_from_array(farr);
}
-String Collada::_read_empty_draw_type(XMLParser &parser) {
+String Collada::_read_empty_draw_type(XMLParser &p_parser) {
String empty_draw_type = "";
- if (parser.is_empty()) {
+ if (p_parser.is_empty()) {
return empty_draw_type;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- empty_draw_type = parser.get_node_data();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_TEXT) {
+ empty_draw_type = p_parser.get_node_data();
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END) {
break; // end parsing text
}
}
return empty_draw_type;
}
-Variant Collada::_parse_param(XMLParser &parser) {
- if (parser.is_empty()) {
+Variant Collada::_parse_param(XMLParser &p_parser) {
+ if (p_parser.is_empty()) {
return Variant();
}
- String from = parser.get_node_name();
+ String from = p_parser.get_node_name();
Variant data;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "float") {
- parser.read();
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- data = parser.get_node_data().to_float();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "float") {
+ p_parser.read();
+ if (p_parser.get_node_type() == XMLParser::NODE_TEXT) {
+ data = p_parser.get_node_data().to_float();
}
- } else if (parser.get_node_name() == "float2") {
- Vector<float> v2 = _read_float_array(parser);
+ } else if (p_parser.get_node_name() == "float2") {
+ Vector<float> v2 = _read_float_array(p_parser);
if (v2.size() >= 2) {
data = Vector2(v2[0], v2[1]);
}
- } else if (parser.get_node_name() == "float3") {
- Vector<float> v3 = _read_float_array(parser);
+ } else if (p_parser.get_node_name() == "float3") {
+ Vector<float> v3 = _read_float_array(p_parser);
if (v3.size() >= 3) {
data = Vector3(v3[0], v3[1], v3[2]);
}
- } else if (parser.get_node_name() == "float4") {
- Vector<float> v4 = _read_float_array(parser);
+ } else if (p_parser.get_node_name() == "float4") {
+ Vector<float> v4 = _read_float_array(p_parser);
if (v4.size() >= 4) {
data = Color(v4[0], v4[1], v4[2], v4[3]);
}
- } else if (parser.get_node_name() == "sampler2D") {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "source") {
- parser.read();
+ } else if (p_parser.get_node_name() == "sampler2D") {
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "source") {
+ p_parser.read();
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- data = parser.get_node_data();
+ if (p_parser.get_node_type() == XMLParser::NODE_TEXT) {
+ data = p_parser.get_node_data();
}
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "sampler2D") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "sampler2D") {
break;
}
}
- } else if (parser.get_node_name() == "surface") {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "init_from") {
- parser.read();
+ } else if (p_parser.get_node_name() == "surface") {
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "init_from") {
+ p_parser.read();
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- data = parser.get_node_data();
+ if (p_parser.get_node_type() == XMLParser::NODE_TEXT) {
+ data = p_parser.get_node_data();
}
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "surface") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "surface") {
break;
}
}
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == from) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == from) {
break;
}
}
- COLLADA_PRINT("newparam ending " + parser.get_node_name());
+ COLLADA_PRINT("newparam ending " + p_parser.get_node_name());
return data;
}
-void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String &id) {
+void Collada::_parse_effect_material(XMLParser &p_parser, Effect &p_effect, String &p_id) {
if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty()) {
- parser.skip_section();
+ if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
return;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
// first come the tags we descend, but ignore the top-levels
- COLLADA_PRINT("node name: " + parser.get_node_name());
+ COLLADA_PRINT("node name: " + p_parser.get_node_name());
- if (!parser.is_empty() &&
- (parser.get_node_name() == "profile_COMMON" ||
- parser.get_node_name() == "technique" ||
- parser.get_node_name() == "extra")) {
- _parse_effect_material(parser, effect, id); // try again
+ if (!p_parser.is_empty() &&
+ (p_parser.get_node_name() == "profile_COMMON" ||
+ p_parser.get_node_name() == "technique" ||
+ p_parser.get_node_name() == "extra")) {
+ _parse_effect_material(p_parser, p_effect, p_id); // try again
- } else if (parser.get_node_name() == "newparam") {
- String name = parser.get_named_attribute_value("sid");
- Variant value = _parse_param(parser);
- effect.params[name] = value;
+ } else if (p_parser.get_node_name() == "newparam") {
+ String name = p_parser.get_named_attribute_value("sid");
+ Variant value = _parse_param(p_parser);
+ p_effect.params[name] = value;
COLLADA_PRINT("param: " + name + " value:" + String(value));
- } else if (parser.get_node_name() == "constant" ||
- parser.get_node_name() == "lambert" ||
- parser.get_node_name() == "phong" ||
- parser.get_node_name() == "blinn") {
- COLLADA_PRINT("shade model: " + parser.get_node_name());
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String what = parser.get_node_name();
+ } else if (p_parser.get_node_name() == "constant" ||
+ p_parser.get_node_name() == "lambert" ||
+ p_parser.get_node_name() == "phong" ||
+ p_parser.get_node_name() == "blinn") {
+ COLLADA_PRINT("shade model: " + p_parser.get_node_name());
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String what = p_parser.get_node_name();
if (what == "emission" ||
what == "diffuse" ||
what == "specular" ||
what == "reflective") {
// color or texture types
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "color") {
- Vector<float> colorarr = _read_float_array(parser);
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "color") {
+ Vector<float> colorarr = _read_float_array(p_parser);
COLLADA_PRINT("colorarr size: " + rtos(colorarr.size()));
if (colorarr.size() >= 3) {
// alpha strangely not alright? maybe it needs to be multiplied by value as a channel intensity
Color color(colorarr[0], colorarr[1], colorarr[2], 1.0);
if (what == "diffuse") {
- effect.diffuse.color = color;
+ p_effect.diffuse.color = color;
}
if (what == "specular") {
- effect.specular.color = color;
+ p_effect.specular.color = color;
}
if (what == "emission") {
- effect.emission.color = color;
+ p_effect.emission.color = color;
}
COLLADA_PRINT(what + " color: " + color);
}
- } else if (parser.get_node_name() == "texture") {
- String sampler = parser.get_named_attribute_value("texture");
- if (!effect.params.has(sampler)) {
- ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + id).utf8().get_data());
+ } else if (p_parser.get_node_name() == "texture") {
+ String sampler = p_parser.get_named_attribute_value("texture");
+ if (!p_effect.params.has(sampler)) {
+ ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + p_id).utf8().get_data());
} else {
- String surface = effect.params[sampler];
+ String surface = p_effect.params[sampler];
- if (!effect.params.has(surface)) {
- ERR_PRINT(String("Couldn't find surface: " + surface + " in material:" + id).utf8().get_data());
+ if (!p_effect.params.has(surface)) {
+ ERR_PRINT(String("Couldn't find surface: " + surface + " in material:" + p_id).utf8().get_data());
} else {
- String uri = effect.params[surface];
+ String uri = p_effect.params[surface];
if (what == "diffuse") {
- effect.diffuse.texture = uri;
+ p_effect.diffuse.texture = uri;
} else if (what == "specular") {
- effect.specular.texture = uri;
+ p_effect.specular.texture = uri;
} else if (what == "emission") {
- effect.emission.texture = uri;
+ p_effect.emission.texture = uri;
} else if (what == "bump") {
- if (parser.has_attribute("bumptype") && parser.get_named_attribute_value("bumptype") != "NORMALMAP") {
+ if (p_parser.has_attribute("bumptype") && p_parser.get_named_attribute_value("bumptype") != "NORMALMAP") {
WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.");
}
- effect.bump.texture = uri;
+ p_effect.bump.texture = uri;
}
COLLADA_PRINT(what + " texture: " + uri);
}
}
- } else if (!parser.is_empty()) {
- parser.skip_section();
+ } else if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == what) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == what) {
break;
}
}
} else if (what == "shininess") {
- effect.shininess = _parse_param(parser);
+ p_effect.shininess = _parse_param(p_parser);
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END &&
- (parser.get_node_name() == "constant" ||
- parser.get_node_name() == "lambert" ||
- parser.get_node_name() == "phong" ||
- parser.get_node_name() == "blinn")) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END &&
+ (p_parser.get_node_name() == "constant" ||
+ p_parser.get_node_name() == "lambert" ||
+ p_parser.get_node_name() == "phong" ||
+ p_parser.get_node_name() == "blinn")) {
break;
}
}
- } else if (parser.get_node_name() == "double_sided" || parser.get_node_name() == "show_double_sided") { // colladamax / google earth
+ } else if (p_parser.get_node_name() == "double_sided" || p_parser.get_node_name() == "show_double_sided") { // colladamax / google earth
// 3DS Max / Google Earth double sided extension
- parser.read();
- effect.found_double_sided = true;
- effect.double_sided = parser.get_node_data().to_int();
- COLLADA_PRINT("double sided: " + itos(parser.get_node_data().to_int()));
- } else if (parser.get_node_name() == "unshaded") {
- parser.read();
- effect.unshaded = parser.get_node_data().to_int();
- } else if (parser.get_node_name() == "bump") {
+ p_parser.read();
+ p_effect.found_double_sided = true;
+ p_effect.double_sided = p_parser.get_node_data().to_int();
+ COLLADA_PRINT("double sided: " + itos(p_parser.get_node_data().to_int()));
+ } else if (p_parser.get_node_name() == "unshaded") {
+ p_parser.read();
+ p_effect.unshaded = p_parser.get_node_data().to_int();
+ } else if (p_parser.get_node_name() == "bump") {
// color or texture types
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "texture") {
- String sampler = parser.get_named_attribute_value("texture");
- if (!effect.params.has(sampler)) {
- ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + id).utf8().get_data());
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "texture") {
+ String sampler = p_parser.get_named_attribute_value("texture");
+ if (!p_effect.params.has(sampler)) {
+ ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + p_id).utf8().get_data());
} else {
- String surface = effect.params[sampler];
+ String surface = p_effect.params[sampler];
- if (!effect.params.has(surface)) {
- ERR_PRINT(String("Couldn't find surface: " + surface + " in material:" + id).utf8().get_data());
+ if (!p_effect.params.has(surface)) {
+ ERR_PRINT(String("Couldn't find surface: " + surface + " in material:" + p_id).utf8().get_data());
} else {
- String uri = effect.params[surface];
+ String uri = p_effect.params[surface];
- if (parser.has_attribute("bumptype") && parser.get_named_attribute_value("bumptype") != "NORMALMAP") {
+ if (p_parser.has_attribute("bumptype") && p_parser.get_named_attribute_value("bumptype") != "NORMALMAP") {
WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.");
}
- effect.bump.texture = uri;
+ p_effect.bump.texture = uri;
COLLADA_PRINT(" bump: " + uri);
}
}
- } else if (!parser.is_empty()) {
- parser.skip_section();
+ } else if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "bump") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "bump") {
break;
}
}
- } else if (!parser.is_empty()) {
- parser.skip_section();
+ } else if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END &&
- (parser.get_node_name() == "effect" ||
- parser.get_node_name() == "profile_COMMON" ||
- parser.get_node_name() == "technique" ||
- parser.get_node_name() == "extra")) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END &&
+ (p_parser.get_node_name() == "effect" ||
+ p_parser.get_node_name() == "profile_COMMON" ||
+ p_parser.get_node_name() == "technique" ||
+ p_parser.get_node_name() == "extra")) {
break;
}
}
}
-void Collada::_parse_effect(XMLParser &parser) {
+void Collada::_parse_effect(XMLParser &p_parser) {
if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty()) {
- parser.skip_section();
+ if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
return;
}
- String id = parser.get_named_attribute_value("id");
+ String id = p_parser.get_named_attribute_value("id");
Effect effect;
- if (parser.has_attribute("name")) {
- effect.name = parser.get_named_attribute_value("name");
+ if (p_parser.has_attribute("name")) {
+ effect.name = p_parser.get_named_attribute_value("name");
}
- _parse_effect_material(parser, effect, id);
+ _parse_effect_material(p_parser, effect, id);
state.effect_map[id] = effect;
COLLADA_PRINT("Effect ID:" + id);
}
-void Collada::_parse_camera(XMLParser &parser) {
+void Collada::_parse_camera(XMLParser &p_parser) {
if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty()) {
- parser.skip_section();
+ if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
return;
}
- String id = parser.get_named_attribute_value("id");
+ String id = p_parser.get_named_attribute_value("id");
state.camera_data_map[id] = CameraData();
CameraData &camera = state.camera_data_map[id];
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String name = p_parser.get_node_name();
if (name == "perspective") {
camera.mode = CameraData::MODE_PERSPECTIVE;
} else if (name == "orthographic") {
camera.mode = CameraData::MODE_ORTHOGONAL;
} else if (name == "xfov") {
- parser.read();
- camera.perspective.x_fov = parser.get_node_data().to_float();
+ p_parser.read();
+ camera.perspective.x_fov = p_parser.get_node_data().to_float();
} else if (name == "yfov") {
- parser.read();
- camera.perspective.y_fov = parser.get_node_data().to_float();
+ p_parser.read();
+ camera.perspective.y_fov = p_parser.get_node_data().to_float();
} else if (name == "xmag") {
- parser.read();
- camera.orthogonal.x_mag = parser.get_node_data().to_float();
+ p_parser.read();
+ camera.orthogonal.x_mag = p_parser.get_node_data().to_float();
} else if (name == "ymag") {
- parser.read();
- camera.orthogonal.y_mag = parser.get_node_data().to_float();
+ p_parser.read();
+ camera.orthogonal.y_mag = p_parser.get_node_data().to_float();
} else if (name == "aspect_ratio") {
- parser.read();
- camera.aspect = parser.get_node_data().to_float();
+ p_parser.read();
+ camera.aspect = p_parser.get_node_data().to_float();
} else if (name == "znear") {
- parser.read();
- camera.z_near = parser.get_node_data().to_float();
+ p_parser.read();
+ camera.z_near = p_parser.get_node_data().to_float();
} else if (name == "zfar") {
- parser.read();
- camera.z_far = parser.get_node_data().to_float();
+ p_parser.read();
+ camera.z_far = p_parser.get_node_data().to_float();
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "camera") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "camera") {
break; //end of <asset>
}
}
@@ -772,22 +772,22 @@ void Collada::_parse_camera(XMLParser &parser) {
COLLADA_PRINT("Camera ID:" + id);
}
-void Collada::_parse_light(XMLParser &parser) {
+void Collada::_parse_light(XMLParser &p_parser) {
if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty()) {
- parser.skip_section();
+ if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
return;
}
- String id = parser.get_named_attribute_value("id");
+ String id = p_parser.get_named_attribute_value("id");
state.light_data_map[id] = LightData();
LightData &light = state.light_data_map[id];
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String name = p_parser.get_node_name();
if (name == "ambient") {
light.mode = LightData::MODE_AMBIENT;
@@ -798,8 +798,8 @@ void Collada::_parse_light(XMLParser &parser) {
} else if (name == "spot") {
light.mode = LightData::MODE_SPOT;
} else if (name == "color") {
- parser.read();
- Vector<float> colorarr = _read_float_array(parser);
+ p_parser.read();
+ Vector<float> colorarr = _read_float_array(p_parser);
COLLADA_PRINT("colorarr size: " + rtos(colorarr.size()));
if (colorarr.size() >= 4) {
@@ -809,24 +809,24 @@ void Collada::_parse_light(XMLParser &parser) {
}
} else if (name == "constant_attenuation") {
- parser.read();
- light.constant_att = parser.get_node_data().to_float();
+ p_parser.read();
+ light.constant_att = p_parser.get_node_data().to_float();
} else if (name == "linear_attenuation") {
- parser.read();
- light.linear_att = parser.get_node_data().to_float();
+ p_parser.read();
+ light.linear_att = p_parser.get_node_data().to_float();
} else if (name == "quadratic_attenuation") {
- parser.read();
- light.quad_att = parser.get_node_data().to_float();
+ p_parser.read();
+ light.quad_att = p_parser.get_node_data().to_float();
} else if (name == "falloff_angle") {
- parser.read();
- light.spot_angle = parser.get_node_data().to_float();
+ p_parser.read();
+ light.spot_angle = p_parser.get_node_data().to_float();
} else if (name == "falloff_exponent") {
- parser.read();
- light.spot_exp = parser.get_node_data().to_float();
+ p_parser.read();
+ light.spot_exp = p_parser.get_node_data().to_float();
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "light") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "light") {
break; //end of <asset>
}
}
@@ -834,10 +834,10 @@ void Collada::_parse_light(XMLParser &parser) {
COLLADA_PRINT("Light ID:" + id);
}
-void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_name) {
+void Collada::_parse_curve_geometry(XMLParser &p_parser, String p_id, String p_name) {
if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty()) {
- parser.skip_section();
+ if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
return;
}
@@ -848,7 +848,7 @@ void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_nam
CurveData &curvedata = state.curve_data_map[p_id];
curvedata.name = p_name;
- String closed = parser.get_named_attribute_value_safe("closed").to_lower();
+ String closed = p_parser.get_named_attribute_value_safe("closed").to_lower();
curvedata.closed = closed == "true" || closed == "1";
COLLADA_PRINT("curve name: " + p_name);
@@ -856,16 +856,16 @@ void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_nam
String current_source;
// handles geometry node and the curve children in this loop
// read sources with arrays and accessor for each curve
- if (parser.is_empty()) {
+ if (p_parser.is_empty()) {
return;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String section = p_parser.get_node_name();
if (section == "source") {
- String id = parser.get_named_attribute_value("id");
+ String id = p_parser.get_named_attribute_value("id");
curvedata.sources[id] = CurveData::Source();
current_source = id;
COLLADA_PRINT("source data: " + id);
@@ -873,13 +873,13 @@ void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_nam
} else if (section == "float_array" || section == "array") {
// create a new array and read it.
if (curvedata.sources.has(current_source)) {
- curvedata.sources[current_source].array = _read_float_array(parser);
+ curvedata.sources[current_source].array = _read_float_array(p_parser);
COLLADA_PRINT("section: " + current_source + " read " + itos(curvedata.sources[current_source].array.size()) + " values.");
}
} else if (section == "Name_array") {
// create a new array and read it.
if (curvedata.sources.has(current_source)) {
- curvedata.sources[current_source].sarray = _read_string_array(parser);
+ curvedata.sources[current_source].sarray = _read_string_array(p_parser);
COLLADA_PRINT("section: " + current_source + " read " + itos(curvedata.sources[current_source].array.size()) + " values.");
}
@@ -888,38 +888,38 @@ void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_nam
} else if (section == "accessor") { // child of source (below a technique tag)
if (curvedata.sources.has(current_source)) {
- curvedata.sources[current_source].stride = parser.get_named_attribute_value("stride").to_int();
+ curvedata.sources[current_source].stride = p_parser.get_named_attribute_value("stride").to_int();
COLLADA_PRINT("section: " + current_source + " stride " + itos(curvedata.sources[current_source].stride));
}
} else if (section == "control_vertices") {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_named_attribute_value("semantic");
- String source = _uri_to_id(parser.get_named_attribute_value("source"));
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "input") {
+ String semantic = p_parser.get_named_attribute_value("semantic");
+ String source = _uri_to_id(p_parser.get_named_attribute_value("source"));
curvedata.control_vertices[semantic] = source;
COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == section) {
break;
}
}
- } else if (!parser.is_empty()) {
- parser.skip_section();
+ } else if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "spline") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "spline") {
break;
}
}
}
-void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name) {
+void Collada::_parse_mesh_geometry(XMLParser &p_parser, String p_id, String p_name) {
if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty()) {
- parser.skip_section();
+ if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
return;
}
@@ -936,16 +936,16 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name
String current_source;
// handles geometry node and the mesh children in this loop
// read sources with arrays and accessor for each mesh
- if (parser.is_empty()) {
+ if (p_parser.is_empty()) {
return;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String section = p_parser.get_node_name();
if (section == "source") {
- String id = parser.get_named_attribute_value("id");
+ String id = p_parser.get_named_attribute_value("id");
meshdata.sources[id] = MeshData::Source();
current_source = id;
COLLADA_PRINT("source data: " + id);
@@ -953,7 +953,7 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name
} else if (section == "float_array" || section == "array") {
// create a new array and read it.
if (meshdata.sources.has(current_source)) {
- meshdata.sources[current_source].array = _read_float_array(parser);
+ meshdata.sources[current_source].array = _read_float_array(p_parser);
COLLADA_PRINT("section: " + current_source + " read " + itos(meshdata.sources[current_source].array.size()) + " values.");
}
} else if (section == "technique_common") {
@@ -961,19 +961,19 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name
} else if (section == "accessor") { // child of source (below a technique tag)
if (meshdata.sources.has(current_source)) {
- meshdata.sources[current_source].stride = parser.get_named_attribute_value("stride").to_int();
+ meshdata.sources[current_source].stride = p_parser.get_named_attribute_value("stride").to_int();
COLLADA_PRINT("section: " + current_source + " stride " + itos(meshdata.sources[current_source].stride));
}
} else if (section == "vertices") {
MeshData::Vertices vert;
- String id = parser.get_named_attribute_value("id");
+ String id = p_parser.get_named_attribute_value("id");
int last_ref = 0;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_named_attribute_value("semantic");
- String source = _uri_to_id(parser.get_named_attribute_value("source"));
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "input") {
+ String semantic = p_parser.get_named_attribute_value("semantic");
+ String source = _uri_to_id(p_parser.get_named_attribute_value("source"));
if (semantic == "TEXCOORD") {
semantic = "TEXCOORD" + itos(last_ref++);
@@ -983,7 +983,7 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name
COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == section) {
break;
}
}
@@ -997,23 +997,23 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name
}
MeshData::Primitives prim;
- if (parser.has_attribute("material")) {
- prim.material = parser.get_named_attribute_value("material");
+ if (p_parser.has_attribute("material")) {
+ prim.material = p_parser.get_named_attribute_value("material");
}
- prim.count = parser.get_named_attribute_value("count").to_int();
+ prim.count = p_parser.get_named_attribute_value("count").to_int();
prim.vertex_size = 0;
int last_ref = 0;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_named_attribute_value("semantic");
- String source = _uri_to_id(parser.get_named_attribute_value("source"));
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "input") {
+ String semantic = p_parser.get_named_attribute_value("semantic");
+ String source = _uri_to_id(p_parser.get_named_attribute_value("source"));
if (semantic == "TEXCOORD") {
semantic = "TEXCOORD" + itos(last_ref++);
}
- int offset = parser.get_named_attribute_value("offset").to_int();
+ int offset = p_parser.get_named_attribute_value("offset").to_int();
MeshData::Primitives::SourceRef sref;
sref.source = source;
@@ -1023,9 +1023,9 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name
COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source + " offset: " + itos(offset));
- } else if (parser.get_node_name() == "p") { //indices
+ } else if (p_parser.get_node_name() == "p") { //indices
- Vector<float> values = _read_float_array(parser);
+ Vector<float> values = _read_float_array(p_parser);
if (polygons) {
ERR_CONTINUE(prim.vertex_size == 0);
prim.polygons.push_back(values.size() / prim.vertex_size);
@@ -1041,49 +1041,49 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name
COLLADA_PRINT("read " + itos(values.size()) + " index values");
- } else if (parser.get_node_name() == "vcount") { // primitive
+ } else if (p_parser.get_node_name() == "vcount") { // primitive
- Vector<float> values = _read_float_array(parser);
+ Vector<float> values = _read_float_array(p_parser);
prim.polygons = values;
COLLADA_PRINT("read " + itos(values.size()) + " polygon values");
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == section) {
break;
}
}
meshdata.primitives.push_back(prim);
- } else if (parser.get_node_name() == "double_sided") {
- parser.read();
+ } else if (p_parser.get_node_name() == "double_sided") {
+ p_parser.read();
meshdata.found_double_sided = true;
- meshdata.double_sided = parser.get_node_data().to_int();
+ meshdata.double_sided = p_parser.get_node_data().to_int();
- } else if (parser.get_node_name() == "polygons") {
+ } else if (p_parser.get_node_name() == "polygons") {
ERR_PRINT("Primitive type \"polygons\" not supported, re-export using \"polylist\" or \"triangles\".");
- } else if (!parser.is_empty()) {
- parser.skip_section();
+ } else if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "mesh") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "mesh") {
break;
}
}
}
-void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
+void Collada::_parse_skin_controller(XMLParser &p_parser, String p_id) {
state.skin_controller_data_map[p_id] = SkinControllerData();
SkinControllerData &skindata = state.skin_controller_data_map[p_id];
- skindata.base = _uri_to_id(parser.get_named_attribute_value("source"));
+ skindata.base = _uri_to_id(p_parser.get_named_attribute_value("source"));
String current_source;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String section = p_parser.get_node_name();
if (section == "bind_shape_matrix") {
- skindata.bind_shape = _read_transform(parser);
+ skindata.bind_shape = _read_transform(p_parser);
#ifdef COLLADA_IMPORT_SCALE_SCENE
skindata.bind_shape.origin *= state.unit_scale;
@@ -1091,7 +1091,7 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
COLLADA_PRINT("skeleton bind shape transform: " + skindata.bind_shape);
} else if (section == "source") {
- String id = parser.get_named_attribute_value("id");
+ String id = p_parser.get_named_attribute_value("id");
skindata.sources[id] = SkinControllerData::Source();
current_source = id;
COLLADA_PRINT("source data: " + id);
@@ -1099,7 +1099,7 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
} else if (section == "float_array" || section == "array") {
// create a new array and read it.
if (skindata.sources.has(current_source)) {
- skindata.sources[current_source].array = _read_float_array(parser);
+ skindata.sources[current_source].array = _read_float_array(p_parser);
COLLADA_PRINT("section: " + current_source + " read " + itos(skindata.sources[current_source].array.size()) + " values.");
}
} else if (section == "Name_array" || section == "IDREF_array") {
@@ -1109,7 +1109,7 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
skindata.use_idrefs = true;
}
if (skindata.sources.has(current_source)) {
- skindata.sources[current_source].sarray = _read_string_array(parser);
+ skindata.sources[current_source].sarray = _read_string_array(p_parser);
if (section == "IDREF_array") {
Vector<String> sa = skindata.sources[current_source].sarray;
for (int i = 0; i < sa.size(); i++) {
@@ -1124,8 +1124,8 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
if (skindata.sources.has(current_source)) {
int stride = 1;
- if (parser.has_attribute("stride")) {
- stride = parser.get_named_attribute_value("stride").to_int();
+ if (p_parser.has_attribute("stride")) {
+ stride = p_parser.get_named_attribute_value("stride").to_int();
}
skindata.sources[current_source].stride = stride;
@@ -1135,17 +1135,17 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
} else if (section == "joints") {
SkinControllerData::Joints joint;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_named_attribute_value("semantic");
- String source = _uri_to_id(parser.get_named_attribute_value("source"));
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "input") {
+ String semantic = p_parser.get_named_attribute_value("semantic");
+ String source = _uri_to_id(p_parser.get_named_attribute_value("source"));
joint.sources[semantic] = source;
COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == section) {
break;
}
}
@@ -1155,15 +1155,15 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
} else if (section == "vertex_weights") {
SkinControllerData::Weights weights;
- weights.count = parser.get_named_attribute_value("count").to_int();
+ weights.count = p_parser.get_named_attribute_value("count").to_int();
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_named_attribute_value("semantic");
- String source = _uri_to_id(parser.get_named_attribute_value("source"));
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "input") {
+ String semantic = p_parser.get_named_attribute_value("semantic");
+ String source = _uri_to_id(p_parser.get_named_attribute_value("source"));
- int offset = parser.get_named_attribute_value("offset").to_int();
+ int offset = p_parser.get_named_attribute_value("offset").to_int();
SkinControllerData::Weights::SourceRef sref;
sref.source = source;
@@ -1172,26 +1172,26 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source + " offset: " + itos(offset));
- } else if (parser.get_node_name() == "v") { //indices
+ } else if (p_parser.get_node_name() == "v") { //indices
- Vector<float> values = _read_float_array(parser);
+ Vector<float> values = _read_float_array(p_parser);
weights.indices = values;
COLLADA_PRINT("read " + itos(values.size()) + " index values");
- } else if (parser.get_node_name() == "vcount") { // weightsitive
+ } else if (p_parser.get_node_name() == "vcount") { // weightsitive
- Vector<float> values = _read_float_array(parser);
+ Vector<float> values = _read_float_array(p_parser);
weights.sets = values;
COLLADA_PRINT("read " + itos(values.size()) + " polygon values");
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == section) {
break;
}
}
skindata.weights = weights;
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "skin") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "skin") {
break;
}
}
@@ -1224,20 +1224,20 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
}
}
-void Collada::_parse_morph_controller(XMLParser &parser, String p_id) {
+void Collada::_parse_morph_controller(XMLParser &p_parser, String p_id) {
state.morph_controller_data_map[p_id] = MorphControllerData();
MorphControllerData &morphdata = state.morph_controller_data_map[p_id];
- morphdata.mesh = _uri_to_id(parser.get_named_attribute_value("source"));
- morphdata.mode = parser.get_named_attribute_value("method");
+ morphdata.mesh = _uri_to_id(p_parser.get_named_attribute_value("source"));
+ morphdata.mode = p_parser.get_named_attribute_value("method");
String current_source;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String section = p_parser.get_node_name();
if (section == "source") {
- String id = parser.get_named_attribute_value("id");
+ String id = p_parser.get_named_attribute_value("id");
morphdata.sources[id] = MorphControllerData::Source();
current_source = id;
COLLADA_PRINT("source data: " + id);
@@ -1245,13 +1245,13 @@ void Collada::_parse_morph_controller(XMLParser &parser, String p_id) {
} else if (section == "float_array" || section == "array") {
// create a new array and read it.
if (morphdata.sources.has(current_source)) {
- morphdata.sources[current_source].array = _read_float_array(parser);
+ morphdata.sources[current_source].array = _read_float_array(p_parser);
COLLADA_PRINT("section: " + current_source + " read " + itos(morphdata.sources[current_source].array.size()) + " values.");
}
} else if (section == "Name_array" || section == "IDREF_array") {
// create a new array and read it.
if (morphdata.sources.has(current_source)) {
- morphdata.sources[current_source].sarray = _read_string_array(parser);
+ morphdata.sources[current_source].sarray = _read_string_array(p_parser);
COLLADA_PRINT("section: " + current_source + " read " + itos(morphdata.sources[current_source].array.size()) + " values.");
}
} else if (section == "technique_common") {
@@ -1260,8 +1260,8 @@ void Collada::_parse_morph_controller(XMLParser &parser, String p_id) {
if (morphdata.sources.has(current_source)) {
int stride = 1;
- if (parser.has_attribute("stride")) {
- stride = parser.get_named_attribute_value("stride").to_int();
+ if (p_parser.has_attribute("stride")) {
+ stride = p_parser.get_named_attribute_value("stride").to_int();
}
morphdata.sources[current_source].stride = stride;
@@ -1269,22 +1269,22 @@ void Collada::_parse_morph_controller(XMLParser &parser, String p_id) {
}
} else if (section == "targets") {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_named_attribute_value("semantic");
- String source = _uri_to_id(parser.get_named_attribute_value("source"));
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "input") {
+ String semantic = p_parser.get_named_attribute_value("semantic");
+ String source = _uri_to_id(p_parser.get_named_attribute_value("source"));
morphdata.targets[semantic] = source;
COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == section) {
break;
}
}
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "morph") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "morph") {
break;
}
}
@@ -1294,57 +1294,57 @@ void Collada::_parse_morph_controller(XMLParser &parser, String p_id) {
}
}
-void Collada::_parse_controller(XMLParser &parser) {
- String id = parser.get_named_attribute_value("id");
+void Collada::_parse_controller(XMLParser &p_parser) {
+ String id = p_parser.get_named_attribute_value("id");
- if (parser.is_empty()) {
+ if (p_parser.is_empty()) {
return;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String section = p_parser.get_node_name();
if (section == "skin") {
- _parse_skin_controller(parser, id);
+ _parse_skin_controller(p_parser, id);
} else if (section == "morph") {
- _parse_morph_controller(parser, id);
+ _parse_morph_controller(p_parser, id);
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "controller") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "controller") {
break;
}
}
}
-Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &parser) {
- String type = parser.get_node_name();
+Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &p_parser) {
+ String type = p_parser.get_node_name();
NodeGeometry *geom = memnew(NodeGeometry);
geom->controller = type == "instance_controller";
- geom->source = _uri_to_id(parser.get_named_attribute_value_safe("url"));
+ geom->source = _uri_to_id(p_parser.get_named_attribute_value_safe("url"));
- if (parser.is_empty()) { //nothing else to parse...
+ if (p_parser.is_empty()) { //nothing else to parse...
return geom;
}
// try to find also many materials and skeletons!
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "instance_material") {
- String symbol = parser.get_named_attribute_value("symbol");
- String target = _uri_to_id(parser.get_named_attribute_value("target"));
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "instance_material") {
+ String symbol = p_parser.get_named_attribute_value("symbol");
+ String target = _uri_to_id(p_parser.get_named_attribute_value("target"));
NodeGeometry::Material mat;
mat.target = target;
geom->material_map[symbol] = mat;
COLLADA_PRINT("uses material: '" + target + "' on primitive'" + symbol + "'");
- } else if (parser.get_node_name() == "skeleton") {
- parser.read();
- String uri = _uri_to_id(parser.get_node_data());
+ } else if (p_parser.get_node_name() == "skeleton") {
+ p_parser.read();
+ String uri = _uri_to_id(p_parser.get_node_data());
if (!uri.is_empty()) {
geom->skeletons.push_back(uri);
}
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == type) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == type) {
break;
}
}
@@ -1368,20 +1368,20 @@ Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &parser) {
return geom;
}
-Collada::Node *Collada::_parse_visual_instance_camera(XMLParser &parser) {
+Collada::Node *Collada::_parse_visual_instance_camera(XMLParser &p_parser) {
NodeCamera *cam = memnew(NodeCamera);
- cam->camera = _uri_to_id(parser.get_named_attribute_value_safe("url"));
+ cam->camera = _uri_to_id(p_parser.get_named_attribute_value_safe("url"));
if (state.up_axis == Vector3::AXIS_Z) { //collada weirdness
cam->post_transform.basis.rotate(Vector3(1, 0, 0), -Math_PI * 0.5);
}
- if (parser.is_empty()) { //nothing else to parse...
+ if (p_parser.is_empty()) { //nothing else to parse...
return cam;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "instance_camera") {
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "instance_camera") {
break;
}
}
@@ -1389,20 +1389,20 @@ Collada::Node *Collada::_parse_visual_instance_camera(XMLParser &parser) {
return cam;
}
-Collada::Node *Collada::_parse_visual_instance_light(XMLParser &parser) {
+Collada::Node *Collada::_parse_visual_instance_light(XMLParser &p_parser) {
NodeLight *cam = memnew(NodeLight);
- cam->light = _uri_to_id(parser.get_named_attribute_value_safe("url"));
+ cam->light = _uri_to_id(p_parser.get_named_attribute_value_safe("url"));
if (state.up_axis == Vector3::AXIS_Z) { //collada weirdness
cam->post_transform.basis.rotate(Vector3(1, 0, 0), -Math_PI * 0.5);
}
- if (parser.is_empty()) { //nothing else to parse...
+ if (p_parser.is_empty()) { //nothing else to parse...
return cam;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "instance_light") {
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "instance_light") {
break;
}
}
@@ -1410,23 +1410,23 @@ Collada::Node *Collada::_parse_visual_instance_light(XMLParser &parser) {
return cam;
}
-Collada::Node *Collada::_parse_visual_node_instance_data(XMLParser &parser) {
- String instance_type = parser.get_node_name();
+Collada::Node *Collada::_parse_visual_node_instance_data(XMLParser &p_parser) {
+ String instance_type = p_parser.get_node_name();
if (instance_type == "instance_geometry" || instance_type == "instance_controller") {
- return _parse_visual_instance_geometry(parser);
+ return _parse_visual_instance_geometry(p_parser);
} else if (instance_type == "instance_camera") {
- return _parse_visual_instance_camera(parser);
+ return _parse_visual_instance_camera(p_parser);
} else if (instance_type == "instance_light") {
- return _parse_visual_instance_light(parser);
+ return _parse_visual_instance_light(p_parser);
}
- if (parser.is_empty()) { //nothing else to parse...
+ if (p_parser.is_empty()) { //nothing else to parse...
return nullptr;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == instance_type) {
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == instance_type) {
break;
}
}
@@ -1434,10 +1434,10 @@ Collada::Node *Collada::_parse_visual_node_instance_data(XMLParser &parser) {
return nullptr;
}
-Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) {
+Collada::Node *Collada::_parse_visual_scene_node(XMLParser &p_parser) {
String name;
- String id = parser.get_named_attribute_value_safe("id");
+ String id = p_parser.get_named_attribute_value_safe("id");
bool found_name = false;
@@ -1455,25 +1455,25 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) {
Node *node = nullptr;
- name = parser.has_attribute("name") ? parser.get_named_attribute_value_safe("name") : parser.get_named_attribute_value_safe("id");
+ name = p_parser.has_attribute("name") ? p_parser.get_named_attribute_value_safe("name") : p_parser.get_named_attribute_value_safe("id");
if (name.is_empty()) {
name = id;
} else {
found_name = true;
}
- if ((parser.has_attribute("type") && parser.get_named_attribute_value("type") == "JOINT") || state.idref_joints.has(name)) {
+ if ((p_parser.has_attribute("type") && p_parser.get_named_attribute_value("type") == "JOINT") || state.idref_joints.has(name)) {
// handle a bone
NodeJoint *joint = memnew(NodeJoint);
- if (parser.has_attribute("sid")) { //bones may not have sid
- joint->sid = parser.get_named_attribute_value("sid");
+ if (p_parser.has_attribute("sid")) { //bones may not have sid
+ joint->sid = p_parser.get_named_attribute_value("sid");
//state.bone_map[joint->sid]=joint;
} else if (state.idref_joints.has(name)) {
joint->sid = name; //kind of a cheat but..
- } else if (parser.has_attribute("name")) {
- joint->sid = parser.get_named_attribute_value_safe("name");
+ } else if (p_parser.has_attribute("name")) {
+ joint->sid = p_parser.get_named_attribute_value_safe("name");
}
if (!joint->sid.is_empty()) {
@@ -1483,42 +1483,42 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) {
node = joint;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String section = p_parser.get_node_name();
if (section == "translate") {
Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id = parser.get_named_attribute_value("sid");
+ if (p_parser.has_attribute("sid")) {
+ xf.id = p_parser.get_named_attribute_value("sid");
}
xf.op = Node::XForm::OP_TRANSLATE;
- Vector<float> xlt = _read_float_array(parser);
+ Vector<float> xlt = _read_float_array(p_parser);
xf.data = xlt;
xform_list.push_back(xf);
} else if (section == "rotate") {
Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id = parser.get_named_attribute_value("sid");
+ if (p_parser.has_attribute("sid")) {
+ xf.id = p_parser.get_named_attribute_value("sid");
}
xf.op = Node::XForm::OP_ROTATE;
- Vector<float> rot = _read_float_array(parser);
+ Vector<float> rot = _read_float_array(p_parser);
xf.data = rot;
xform_list.push_back(xf);
} else if (section == "scale") {
Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id = parser.get_named_attribute_value("sid");
+ if (p_parser.has_attribute("sid")) {
+ xf.id = p_parser.get_named_attribute_value("sid");
}
xf.op = Node::XForm::OP_SCALE;
- Vector<float> scale = _read_float_array(parser);
+ Vector<float> scale = _read_float_array(p_parser);
xf.data = scale;
@@ -1526,12 +1526,12 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) {
} else if (section == "matrix") {
Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id = parser.get_named_attribute_value("sid");
+ if (p_parser.has_attribute("sid")) {
+ xf.id = p_parser.get_named_attribute_value("sid");
}
xf.op = Node::XForm::OP_MATRIX;
- Vector<float> matrix = _read_float_array(parser);
+ Vector<float> matrix = _read_float_array(p_parser);
xf.data = matrix;
String mtx;
@@ -1543,25 +1543,25 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) {
} else if (section == "visibility") {
Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id = parser.get_named_attribute_value("sid");
+ if (p_parser.has_attribute("sid")) {
+ xf.id = p_parser.get_named_attribute_value("sid");
}
xf.op = Node::XForm::OP_VISIBILITY;
- Vector<float> visible = _read_float_array(parser);
+ Vector<float> visible = _read_float_array(p_parser);
xf.data = visible;
xform_list.push_back(xf);
} else if (section == "empty_draw_type") {
- empty_draw_type = _read_empty_draw_type(parser);
+ empty_draw_type = _read_empty_draw_type(p_parser);
} else if (section == "technique" || section == "extra") {
} else if (section != "node") {
//usually what defines the type of node
if (section.begins_with("instance_")) {
if (!node) {
- node = _parse_visual_node_instance_data(parser);
+ node = _parse_visual_node_instance_data(p_parser);
} else {
ERR_PRINT("Multiple instance_* not supported.");
@@ -1571,11 +1571,11 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) {
} else {
/* Found a child node!! what to do..*/
- Node *child = _parse_visual_scene_node(parser);
+ Node *child = _parse_visual_scene_node(p_parser);
children.push_back(child);
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "node") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "node") {
break;
}
}
@@ -1608,29 +1608,29 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) {
return node;
}
-void Collada::_parse_visual_scene(XMLParser &parser) {
- String id = parser.get_named_attribute_value("id");
+void Collada::_parse_visual_scene(XMLParser &p_parser) {
+ String id = p_parser.get_named_attribute_value("id");
- if (parser.is_empty()) {
+ if (p_parser.is_empty()) {
return;
}
state.visual_scene_map[id] = VisualScene();
VisualScene &vscene = state.visual_scene_map[id];
- if (parser.has_attribute("name")) {
- vscene.name = parser.get_named_attribute_value("name");
+ if (p_parser.has_attribute("name")) {
+ vscene.name = p_parser.get_named_attribute_value("name");
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String section = p_parser.get_node_name();
if (section == "node") {
- vscene.root_nodes.push_back(_parse_visual_scene_node(parser));
+ vscene.root_nodes.push_back(_parse_visual_scene_node(p_parser));
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "visual_scene") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "visual_scene") {
break;
}
}
@@ -1638,10 +1638,10 @@ void Collada::_parse_visual_scene(XMLParser &parser) {
COLLADA_PRINT("Scene ID:" + id);
}
-void Collada::_parse_animation(XMLParser &parser) {
+void Collada::_parse_animation(XMLParser &p_parser) {
if (!(state.import_flags & IMPORT_FLAG_ANIMATION)) {
- if (!parser.is_empty()) {
- parser.skip_section();
+ if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
return;
@@ -1655,8 +1655,8 @@ void Collada::_parse_animation(XMLParser &parser) {
HashMap<String, Vector<String>> source_param_types;
String id = "";
- if (parser.has_attribute("id")) {
- id = parser.get_named_attribute_value("id");
+ if (p_parser.has_attribute("id")) {
+ id = p_parser.get_named_attribute_value("id");
}
String current_source;
@@ -1664,54 +1664,54 @@ void Collada::_parse_animation(XMLParser &parser) {
Vector<String> channel_sources;
Vector<String> channel_targets;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String name = p_parser.get_node_name();
if (name == "source") {
- current_source = parser.get_named_attribute_value("id");
+ current_source = p_parser.get_named_attribute_value("id");
source_param_names[current_source] = Vector<String>();
source_param_types[current_source] = Vector<String>();
} else if (name == "float_array") {
if (!current_source.is_empty()) {
- float_sources[current_source] = _read_float_array(parser);
+ float_sources[current_source] = _read_float_array(p_parser);
}
} else if (name == "Name_array") {
if (!current_source.is_empty()) {
- string_sources[current_source] = _read_string_array(parser);
+ string_sources[current_source] = _read_string_array(p_parser);
}
} else if (name == "accessor") {
- if (!current_source.is_empty() && parser.has_attribute("stride")) {
- source_strides[current_source] = parser.get_named_attribute_value("stride").to_int();
+ if (!current_source.is_empty() && p_parser.has_attribute("stride")) {
+ source_strides[current_source] = p_parser.get_named_attribute_value("stride").to_int();
}
} else if (name == "sampler") {
- current_sampler = parser.get_named_attribute_value("id");
+ current_sampler = p_parser.get_named_attribute_value("id");
samplers[current_sampler] = HashMap<String, String>();
} else if (name == "param") {
- if (parser.has_attribute("name")) {
- source_param_names[current_source].push_back(parser.get_named_attribute_value("name"));
+ if (p_parser.has_attribute("name")) {
+ source_param_names[current_source].push_back(p_parser.get_named_attribute_value("name"));
} else {
source_param_names[current_source].push_back("");
}
- if (parser.has_attribute("type")) {
- source_param_types[current_source].push_back(parser.get_named_attribute_value("type"));
+ if (p_parser.has_attribute("type")) {
+ source_param_types[current_source].push_back(p_parser.get_named_attribute_value("type"));
} else {
source_param_types[current_source].push_back("");
}
} else if (name == "input") {
if (!current_sampler.is_empty()) {
- samplers[current_sampler][parser.get_named_attribute_value("semantic")] = parser.get_named_attribute_value("source");
+ samplers[current_sampler][p_parser.get_named_attribute_value("semantic")] = p_parser.get_named_attribute_value("source");
}
} else if (name == "channel") {
- channel_sources.push_back(parser.get_named_attribute_value("source"));
- channel_targets.push_back(parser.get_named_attribute_value("target"));
+ channel_sources.push_back(p_parser.get_named_attribute_value("source"));
+ channel_targets.push_back(p_parser.get_named_attribute_value("target"));
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "animation") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "animation") {
break; //end of <asset>
}
}
@@ -1845,10 +1845,10 @@ void Collada::_parse_animation(XMLParser &parser) {
}
}
-void Collada::_parse_animation_clip(XMLParser &parser) {
+void Collada::_parse_animation_clip(XMLParser &p_parser) {
if (!(state.import_flags & IMPORT_FLAG_ANIMATION)) {
- if (!parser.is_empty()) {
- parser.skip_section();
+ if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
return;
@@ -1856,27 +1856,27 @@ void Collada::_parse_animation_clip(XMLParser &parser) {
AnimationClip clip;
- if (parser.has_attribute("name")) {
- clip.name = parser.get_named_attribute_value("name");
- } else if (parser.has_attribute("id")) {
- clip.name = parser.get_named_attribute_value("id");
+ if (p_parser.has_attribute("name")) {
+ clip.name = p_parser.get_named_attribute_value("name");
+ } else if (p_parser.has_attribute("id")) {
+ clip.name = p_parser.get_named_attribute_value("id");
}
- if (parser.has_attribute("start")) {
- clip.begin = parser.get_named_attribute_value("start").to_float();
+ if (p_parser.has_attribute("start")) {
+ clip.begin = p_parser.get_named_attribute_value("start").to_float();
}
- if (parser.has_attribute("end")) {
- clip.end = parser.get_named_attribute_value("end").to_float();
+ if (p_parser.has_attribute("end")) {
+ clip.end = p_parser.get_named_attribute_value("end").to_float();
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String name = p_parser.get_node_name();
if (name == "instance_animation") {
- String url = _uri_to_id(parser.get_named_attribute_value("url"));
+ String url = _uri_to_id(p_parser.get_named_attribute_value("url"));
clip.tracks.push_back(url);
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "animation_clip") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "animation_clip") {
break; //end of <asset>
}
}
@@ -1884,79 +1884,79 @@ void Collada::_parse_animation_clip(XMLParser &parser) {
state.animation_clips.push_back(clip);
}
-void Collada::_parse_scene(XMLParser &parser) {
- if (parser.is_empty()) {
+void Collada::_parse_scene(XMLParser &p_parser) {
+ if (p_parser.is_empty()) {
return;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String name = p_parser.get_node_name();
if (name == "instance_visual_scene") {
- state.root_visual_scene = _uri_to_id(parser.get_named_attribute_value("url"));
+ state.root_visual_scene = _uri_to_id(p_parser.get_named_attribute_value("url"));
} else if (name == "instance_physics_scene") {
- state.root_physics_scene = _uri_to_id(parser.get_named_attribute_value("url"));
+ state.root_physics_scene = _uri_to_id(p_parser.get_named_attribute_value("url"));
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "scene") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "scene") {
break; //end of <asset>
}
}
}
-void Collada::_parse_library(XMLParser &parser) {
- if (parser.is_empty()) {
+void Collada::_parse_library(XMLParser &p_parser) {
+ if (p_parser.is_empty()) {
return;
}
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ String name = p_parser.get_node_name();
COLLADA_PRINT("library name is: " + name);
if (name == "image") {
- _parse_image(parser);
+ _parse_image(p_parser);
} else if (name == "material") {
- _parse_material(parser);
+ _parse_material(p_parser);
} else if (name == "effect") {
- _parse_effect(parser);
+ _parse_effect(p_parser);
} else if (name == "camera") {
- _parse_camera(parser);
+ _parse_camera(p_parser);
} else if (name == "light") {
- _parse_light(parser);
+ _parse_light(p_parser);
} else if (name == "geometry") {
- String id = parser.get_named_attribute_value("id");
- String name2 = parser.get_named_attribute_value_safe("name");
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "mesh") {
+ String id = p_parser.get_named_attribute_value("id");
+ String name2 = p_parser.get_named_attribute_value_safe("name");
+ while (p_parser.read() == OK) {
+ if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+ if (p_parser.get_node_name() == "mesh") {
state.mesh_name_map[id] = (!name2.is_empty()) ? name2 : id;
- _parse_mesh_geometry(parser, id, name2);
- } else if (parser.get_node_name() == "spline") {
+ _parse_mesh_geometry(p_parser, id, name2);
+ } else if (p_parser.get_node_name() == "spline") {
state.mesh_name_map[id] = (!name2.is_empty()) ? name2 : id;
- _parse_curve_geometry(parser, id, name2);
- } else if (!parser.is_empty()) {
- parser.skip_section();
+ _parse_curve_geometry(p_parser, id, name2);
+ } else if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "geometry") {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name() == "geometry") {
break;
}
}
} else if (name == "controller") {
- _parse_controller(parser);
+ _parse_controller(p_parser);
} else if (name == "animation") {
- _parse_animation(parser);
+ _parse_animation(p_parser);
} else if (name == "animation_clip") {
- _parse_animation_clip(parser);
+ _parse_animation_clip(p_parser);
} else if (name == "visual_scene") {
COLLADA_PRINT("visual scene");
- _parse_visual_scene(parser);
- } else if (!parser.is_empty()) {
- parser.skip_section();
+ _parse_visual_scene(p_parser);
+ } else if (!p_parser.is_empty()) {
+ p_parser.skip_section();
}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name().begins_with("library_")) {
+ } else if (p_parser.get_node_type() == XMLParser::NODE_ELEMENT_END && p_parser.get_node_name().begins_with("library_")) {
break; //end of <asset>
}
}
diff --git a/editor/import/collada.h b/editor/import/collada.h
index 12b32f982d..7877b1e86d 100644
--- a/editor/import/collada.h
+++ b/editor/import/collada.h
@@ -69,7 +69,7 @@ public:
bool double_sided = true;
bool unshaded = false;
- String get_texture_path(const String &p_source, Collada &state) const;
+ String get_texture_path(const String &p_source, Collada &p_state) const;
Effect() {
diffuse.color = Color(1, 1, 1, 1);
@@ -266,7 +266,7 @@ public:
}
}
- void fix_unit_scale(const Collada &state);
+ void fix_unit_scale(const Collada &p_state);
bool operator<(const Vertex &p_vert) const {
if (uid == p_vert.uid) {
@@ -348,7 +348,7 @@ public:
Node *parent = nullptr;
- Transform3D compute_transform(const Collada &state) const;
+ Transform3D compute_transform(const Collada &p_state) const;
Transform3D get_global_transform() const;
Transform3D get_transform() const;
@@ -526,39 +526,39 @@ public:
private: // private stuff
HashMap<String, int> channel_map;
- void _parse_asset(XMLParser &parser);
- void _parse_image(XMLParser &parser);
- void _parse_material(XMLParser &parser);
- void _parse_effect_material(XMLParser &parser, Effect &effect, String &id);
- void _parse_effect(XMLParser &parser);
- void _parse_camera(XMLParser &parser);
- void _parse_light(XMLParser &parser);
- void _parse_animation_clip(XMLParser &parser);
-
- void _parse_mesh_geometry(XMLParser &parser, String p_id, String p_name);
- void _parse_curve_geometry(XMLParser &parser, String p_id, String p_name);
-
- void _parse_skin_controller(XMLParser &parser, String p_id);
- void _parse_morph_controller(XMLParser &parser, String p_id);
- void _parse_controller(XMLParser &parser);
-
- Node *_parse_visual_instance_geometry(XMLParser &parser);
- Node *_parse_visual_instance_camera(XMLParser &parser);
- Node *_parse_visual_instance_light(XMLParser &parser);
-
- Node *_parse_visual_node_instance_data(XMLParser &parser);
- Node *_parse_visual_scene_node(XMLParser &parser);
- void _parse_visual_scene(XMLParser &parser);
-
- void _parse_animation(XMLParser &parser);
- void _parse_scene(XMLParser &parser);
- void _parse_library(XMLParser &parser);
-
- Variant _parse_param(XMLParser &parser);
- Vector<float> _read_float_array(XMLParser &parser);
- Vector<String> _read_string_array(XMLParser &parser);
- Transform3D _read_transform(XMLParser &parser);
- String _read_empty_draw_type(XMLParser &parser);
+ void _parse_asset(XMLParser &p_parser);
+ void _parse_image(XMLParser &p_parser);
+ void _parse_material(XMLParser &p_parser);
+ void _parse_effect_material(XMLParser &p_parser, Effect &p_effect, String &p_id);
+ void _parse_effect(XMLParser &p_parser);
+ void _parse_camera(XMLParser &p_parser);
+ void _parse_light(XMLParser &p_parser);
+ void _parse_animation_clip(XMLParser &p_parser);
+
+ void _parse_mesh_geometry(XMLParser &p_parser, String p_id, String p_name);
+ void _parse_curve_geometry(XMLParser &p_parser, String p_id, String p_name);
+
+ void _parse_skin_controller(XMLParser &p_parser, String p_id);
+ void _parse_morph_controller(XMLParser &p_parser, String p_id);
+ void _parse_controller(XMLParser &p_parser);
+
+ Node *_parse_visual_instance_geometry(XMLParser &p_parser);
+ Node *_parse_visual_instance_camera(XMLParser &p_parser);
+ Node *_parse_visual_instance_light(XMLParser &p_parser);
+
+ Node *_parse_visual_node_instance_data(XMLParser &p_parser);
+ Node *_parse_visual_scene_node(XMLParser &p_parser);
+ void _parse_visual_scene(XMLParser &p_parser);
+
+ void _parse_animation(XMLParser &p_parser);
+ void _parse_scene(XMLParser &p_parser);
+ void _parse_library(XMLParser &p_parser);
+
+ Variant _parse_param(XMLParser &p_parser);
+ Vector<float> _read_float_array(XMLParser &p_parser);
+ Vector<String> _read_string_array(XMLParser &p_parser);
+ Transform3D _read_transform(XMLParser &p_parser);
+ String _read_empty_draw_type(XMLParser &p_parser);
void _joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner);
void _create_skeletons(Collada::Node **p_node, NodeSkeleton *p_skeleton = nullptr);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 1e577b7737..00f4af47e1 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -8382,8 +8382,6 @@ Node3DEditor::Node3DEditor() {
snap_scale->set_select_all_on_focus(true);
snap_dialog_vbc->add_margin_child(TTR("Scale Snap (%):"), snap_scale);
- _snap_update();
-
/* SETTINGS DIALOG */
settings_dialog = memnew(ConfirmationDialog);
@@ -8703,7 +8701,7 @@ void fragment() {
_load_default_preview_settings();
_preview_settings_changed();
}
- clear(); // Make sure values are initialized.
+ clear(); // Make sure values are initialized. Will call _snap_update() for us.
}
Node3DEditor::~Node3DEditor() {
memdelete(preview_node);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 24a70680b7..4db809b2cc 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -408,8 +408,8 @@ private:
Camera3D *previewing = nullptr;
Camera3D *preview = nullptr;
- bool previewing_camera;
- bool previewing_cinema;
+ bool previewing_camera = false;
+ bool previewing_cinema = false;
bool _is_node_locked(const Node *p_node);
void _preview_exited_scene();
void _toggle_camera_preview(bool);
@@ -586,8 +586,8 @@ private:
bool origin_enabled = false;
RID grid[3];
RID grid_instance[3];
- bool grid_visible[3]; //currently visible
- bool grid_enable[3]; //should be always visible if true
+ bool grid_visible[3] = { false, false, false }; //currently visible
+ bool grid_enable[3] = { false, false, false }; //should be always visible if true
bool grid_enabled = false;
bool grid_init_draw = false;
Camera3D::ProjectionType grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE;
diff --git a/main/main.cpp b/main/main.cpp
index 86de6497d0..b9f2daf020 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1454,6 +1454,19 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
#endif
}
+ // Initialize WorkerThreadPool.
+ {
+ int worker_threads = GLOBAL_GET("threading/worker_pool/max_threads");
+ bool low_priority_use_system_threads = GLOBAL_GET("threading/worker_pool/use_system_threads_for_low_priority_tasks");
+ float low_property_ratio = GLOBAL_GET("threading/worker_pool/low_priority_thread_ratio");
+
+ if (editor || project_manager) {
+ WorkerThreadPool::get_singleton()->init();
+ } else {
+ WorkerThreadPool::get_singleton()->init(worker_threads, low_priority_use_system_threads, low_property_ratio);
+ }
+ }
+
// Initialize user data dir.
OS::get_singleton()->ensure_user_data_dir();
diff --git a/modules/astcenc/SCsub b/modules/astcenc/SCsub
index 0f04f2bc28..691c74b4a7 100644
--- a/modules/astcenc/SCsub
+++ b/modules/astcenc/SCsub
@@ -29,7 +29,6 @@ thirdparty_sources = [
"astcenc_partition_tables.cpp",
"astcenc_percentile_tables.cpp",
"astcenc_pick_best_endpoint_format.cpp",
- "astcenc_platform_isa_detection.cpp",
"astcenc_quantization.cpp",
"astcenc_symbolic_physical.cpp",
"astcenc_weight_align.cpp",
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index 0bd8e5d9ad..878664bb9c 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -467,7 +467,7 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b
// Use a limit to speed up bvh and limit the depth.
#define BVH_LIMIT 8
-int CSGBrushOperation::MeshMerge::_create_bvh(FaceBVH *facebvhptr, FaceBVH **facebvhptrptr, int p_from, int p_size, int p_depth, int &r_max_depth, int &r_max_alloc) {
+int CSGBrushOperation::MeshMerge::_create_bvh(FaceBVH *r_facebvhptr, FaceBVH **r_facebvhptrptr, int p_from, int p_size, int p_depth, int &r_max_depth, int &r_max_alloc) {
if (p_depth > r_max_depth) {
r_max_depth = p_depth;
}
@@ -478,15 +478,15 @@ int CSGBrushOperation::MeshMerge::_create_bvh(FaceBVH *facebvhptr, FaceBVH **fac
if (p_size <= BVH_LIMIT) {
for (int i = 0; i < p_size - 1; i++) {
- facebvhptrptr[p_from + i]->next = facebvhptrptr[p_from + i + 1] - facebvhptr;
+ r_facebvhptrptr[p_from + i]->next = r_facebvhptrptr[p_from + i + 1] - r_facebvhptr;
}
- return facebvhptrptr[p_from] - facebvhptr;
+ return r_facebvhptrptr[p_from] - r_facebvhptr;
}
AABB aabb;
- aabb = facebvhptrptr[p_from]->aabb;
+ aabb = r_facebvhptrptr[p_from]->aabb;
for (int i = 1; i < p_size; i++) {
- aabb.merge_with(facebvhptrptr[p_from + i]->aabb);
+ aabb.merge_with(r_facebvhptrptr[p_from + i]->aabb);
}
int li = aabb.get_longest_axis_index();
@@ -494,28 +494,28 @@ int CSGBrushOperation::MeshMerge::_create_bvh(FaceBVH *facebvhptr, FaceBVH **fac
switch (li) {
case Vector3::AXIS_X: {
SortArray<FaceBVH *, FaceBVHCmpX> sort_x;
- sort_x.nth_element(0, p_size, p_size / 2, &facebvhptrptr[p_from]);
+ sort_x.nth_element(0, p_size, p_size / 2, &r_facebvhptrptr[p_from]);
//sort_x.sort(&p_bb[p_from],p_size);
} break;
case Vector3::AXIS_Y: {
SortArray<FaceBVH *, FaceBVHCmpY> sort_y;
- sort_y.nth_element(0, p_size, p_size / 2, &facebvhptrptr[p_from]);
+ sort_y.nth_element(0, p_size, p_size / 2, &r_facebvhptrptr[p_from]);
//sort_y.sort(&p_bb[p_from],p_size);
} break;
case Vector3::AXIS_Z: {
SortArray<FaceBVH *, FaceBVHCmpZ> sort_z;
- sort_z.nth_element(0, p_size, p_size / 2, &facebvhptrptr[p_from]);
+ sort_z.nth_element(0, p_size, p_size / 2, &r_facebvhptrptr[p_from]);
//sort_z.sort(&p_bb[p_from],p_size);
} break;
}
- int left = _create_bvh(facebvhptr, facebvhptrptr, p_from, p_size / 2, p_depth + 1, r_max_depth, r_max_alloc);
- int right = _create_bvh(facebvhptr, facebvhptrptr, p_from + p_size / 2, p_size - p_size / 2, p_depth + 1, r_max_depth, r_max_alloc);
+ int left = _create_bvh(r_facebvhptr, r_facebvhptrptr, p_from, p_size / 2, p_depth + 1, r_max_depth, r_max_alloc);
+ int right = _create_bvh(r_facebvhptr, r_facebvhptrptr, p_from + p_size / 2, p_size - p_size / 2, p_depth + 1, r_max_depth, r_max_alloc);
int index = r_max_alloc++;
- FaceBVH *_new = &facebvhptr[index];
+ FaceBVH *_new = &r_facebvhptr[index];
_new->aabb = aabb;
_new->center = aabb.get_center();
_new->face = -1;
@@ -535,13 +535,13 @@ void CSGBrushOperation::MeshMerge::_add_distance(List<IntersectionDistance> &r_i
return;
}
}
- IntersectionDistance IntersectionDistance;
- IntersectionDistance.is_conormal = p_is_conormal;
- IntersectionDistance.distance_squared = p_distance_squared;
- intersections.push_back(IntersectionDistance);
+ IntersectionDistance distance;
+ distance.is_conormal = p_is_conormal;
+ distance.distance_squared = p_distance_squared;
+ intersections.push_back(distance);
}
-bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_depth, int p_bvh_first, int p_face_idx) const {
+bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *r_facebvhptr, int p_max_depth, int p_bvh_first, int p_face_idx) const {
Face face = faces[p_face_idx];
Vector3 face_points[3] = {
points[face.points[0]],
@@ -575,7 +575,7 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de
while (true) {
uint32_t node = stack[level] & NODE_IDX_MASK;
- const FaceBVH *current_facebvhptr = &(facebvhptr[node]);
+ const FaceBVH *current_facebvhptr = &(r_facebvhptr[node]);
bool done = false;
switch (stack[level] >> VISITED_BIT_SHIFT) {
@@ -651,7 +651,7 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de
}
if (current_facebvhptr->next != -1) {
- current_facebvhptr = &facebvhptr[current_facebvhptr->next];
+ current_facebvhptr = &r_facebvhptr[current_facebvhptr->next];
} else {
current_facebvhptr = nullptr;
}
diff --git a/modules/csg/csg.h b/modules/csg/csg.h
index 473a23e39f..2a0831e1ce 100644
--- a/modules/csg/csg.h
+++ b/modules/csg/csg.h
@@ -155,8 +155,8 @@ struct CSGBrushOperation {
float vertex_snap = 0.0;
inline void _add_distance(List<IntersectionDistance> &r_intersectionsA, List<IntersectionDistance> &r_intersectionsB, bool p_from_B, real_t p_distance, bool p_is_conormal) const;
- inline bool _bvh_inside(FaceBVH *facebvhptr, int p_max_depth, int p_bvh_first, int p_face_idx) const;
- inline int _create_bvh(FaceBVH *facebvhptr, FaceBVH **facebvhptrptr, int p_from, int p_size, int p_depth, int &r_max_depth, int &r_max_alloc);
+ inline bool _bvh_inside(FaceBVH *r_facebvhptr, int p_max_depth, int p_bvh_first, int p_face_idx) const;
+ inline int _create_bvh(FaceBVH *r_facebvhptr, FaceBVH **r_facebvhptrptr, int p_from, int p_size, int p_depth, int &r_max_depth, int &r_max_alloc);
void add_face(const Vector3 p_points[3], const Vector2 p_uvs[3], bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b);
void mark_inside_faces();
diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp
index 2efaaa7d4d..91271da331 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.cpp
+++ b/modules/gltf/editor/editor_scene_importer_blend.cpp
@@ -466,8 +466,8 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() {
}
bool found = false;
- for (const String &path : mdfind_paths) {
- found = _autodetect_path(path.path_join("Contents/MacOS"));
+ for (const String &found_path : mdfind_paths) {
+ found = _autodetect_path(found_path.path_join("Contents/MacOS"));
if (found) {
break;
}
diff --git a/modules/mbedtls/crypto_mbedtls.cpp b/modules/mbedtls/crypto_mbedtls.cpp
index 6ae36daffe..68b213d79e 100644
--- a/modules/mbedtls/crypto_mbedtls.cpp
+++ b/modules/mbedtls/crypto_mbedtls.cpp
@@ -36,6 +36,7 @@
#include "core/config/project_settings.h"
#include "core/io/certs_compressed.gen.h"
#include "core/io/compression.h"
+#include "core/os/os.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_settings.h"
@@ -337,20 +338,26 @@ void CryptoMbedTLS::load_default_certificates(String p_path) {
if (!p_path.is_empty()) {
// Use certs defined in project settings.
default_certs->load(p_path);
- }
+ } else {
+ // Try to use system certs otherwise.
+ String system_certs = OS::get_singleton()->get_system_ca_certificates();
+ if (!system_certs.is_empty()) {
+ CharString cs = system_certs.utf8();
+ default_certs->load_from_memory((const uint8_t *)cs.get_data(), cs.size());
+ print_verbose("Loaded system CA certificates");
+ }
#ifdef BUILTIN_CERTS_ENABLED
- else {
- // Use builtin certs only if user did not override it in project settings.
- PackedByteArray out;
- out.resize(_certs_uncompressed_size + 1);
- Compression::decompress(out.ptrw(), _certs_uncompressed_size, _certs_compressed, _certs_compressed_size, Compression::MODE_DEFLATE);
- out.write[_certs_uncompressed_size] = 0; // Make sure it ends with string terminator
-#ifdef DEBUG_ENABLED
- print_verbose("Loaded builtin certs");
+ else {
+ // Use builtin certs if there are no system certs.
+ PackedByteArray certs;
+ certs.resize(_certs_uncompressed_size + 1);
+ Compression::decompress(certs.ptrw(), _certs_uncompressed_size, _certs_compressed, _certs_compressed_size, Compression::MODE_DEFLATE);
+ certs.write[_certs_uncompressed_size] = 0; // Make sure it ends with string terminator
+ default_certs->load_from_memory(certs.ptr(), certs.size());
+ print_verbose("Loaded builtin CA certificates");
+ }
#endif
- default_certs->load_from_memory(out.ptr(), out.size());
}
-#endif
}
Ref<CryptoKey> CryptoMbedTLS::generate_rsa(int p_bytes) {
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
index b30c8c240e..834beaa131 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
@@ -86,7 +86,8 @@ namespace Godot.SourceGenerators
NodeType = 34,
HideQuaternionEdit = 35,
Password = 36,
- Max = 37
+ LayersAvoidance = 37,
+ Max = 38
}
[Flags]
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
index 98e2556dbb..555811bab2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
@@ -188,69 +188,6 @@ namespace Godot
}
/// <summary>
- /// The HSL hue of this color, on the range 0 to 1.
- /// </summary>
- /// <value>Getting is a long process, refer to the source code for details. Setting uses <see cref="FromHsl"/>.</value>
- public float HslH
- {
- readonly get
- {
- return H;
- }
- set
- {
- this = FromHsl(value, HslS, HslL, A);
- }
- }
-
- /// <summary>
- /// The HSL saturation of this color, on the range 0 to 1.
- /// </summary>
- /// <value>Getting is equivalent to the ratio between the min and max RGB value. Setting uses <see cref="FromHsl"/>.</value>
- public float HslS
- {
- readonly get
- {
- float max = Math.Max(R, Math.Max(G, B));
- float min = Math.Min(R, Math.Min(G, B));
-
- float mid = (max + min) / 2.0f;
-
- if (mid == 0.0f || mid == 1.0f)
- {
- return 0.0f;
- }
-
- float delta = max - min;
-
- return delta / (1.0f - Math.Abs(2.0f * mid - 1.0f));
- }
- set
- {
- this = FromHsl(HslH, value, HslL, A);
- }
- }
-
- /// <summary>
- /// The HSL lightness of this color, on the range 0 to 1.
- /// </summary>
- /// <value>Getting is equivalent to using <see cref="Math.Max(float, float)"/> on the RGB components. Setting uses <see cref="FromHsl"/>.</value>
- public float HslL
- {
- readonly get
- {
- float max = Math.Max(R, Math.Max(G, B));
- float min = Math.Min(R, Math.Min(G, B));
-
- return (max + min) / 2.0f;
- }
- set
- {
- this = FromHsl(HslH, HslS, value, A);
- }
- }
-
- /// <summary>
/// Returns the light intensity of the color, as a value between 0.0 and 1.0 (inclusive).
/// This is useful when determining light or dark color. Colors with a luminance smaller
/// than 0.5 can be generally considered dark.
@@ -940,104 +877,6 @@ namespace Godot
value = max;
}
- /// <summary>
- /// Constructs a color from an HSL profile. The <paramref name="hue"/>,
- /// <paramref name="saturation"/>, and <paramref name="lightness"/> are typically
- /// between 0.0 and 1.0.
- /// </summary>
- /// <param name="hue">The HSL hue, typically on the range of 0 to 1.</param>
- /// <param name="saturation">The HSL saturation, typically on the range of 0 to 1.</param>
- /// <param name="lightness">The HSL lightness, typically on the range of 0 to 1.</param>
- /// <param name="alpha">The alpha (transparency) value, typically on the range of 0 to 1.</param>
- /// <returns>The constructed color.</returns>
- public static Color FromHsl(float hue, float saturation, float lightness, float alpha = 1.0f)
- {
- if (saturation == 0.0f)
- {
- // Achromatic (gray)
- return new Color(lightness, lightness, lightness, alpha);
- }
-
- hue *= 6.0f;
- hue %= 6.0f;
-
- float c = (1.0f - Math.Abs(2.0f * lightness - 1.0f)) * saturation;
- float x = c * (1.0f - Math.Abs(hue % 2.0f - 1.0f));
- float m = lightness - c / 2.0f;
-
- c += m;
- x += m;
-
- switch ((int)hue)
- {
- case 0: // Red is the dominant color
- return new Color(c, x, m, alpha);
- case 1: // Green is the dominant color
- return new Color(x, c, m, alpha);
- case 2:
- return new Color(m, c, x, alpha);
- case 3: // Blue is the dominant color
- return new Color(m, x, c, alpha);
- case 4:
- return new Color(x, m, c, alpha);
- default: // (5) Red is the dominant color
- return new Color(c, m, x, alpha);
- }
- }
-
- /// <summary>
- /// Converts a color to HSL values. This is equivalent to using each of
- /// the <c>h</c>/<c>s</c>/<c>l</c> properties, but much more efficient.
- /// </summary>
- /// <param name="hue">Output parameter for the HSL hue.</param>
- /// <param name="saturation">Output parameter for the HSL saturation.</param>
- /// <param name="lightness">Output parameter for the HSL lightness.</param>
- public readonly void ToHsl(out float hue, out float saturation, out float lightness)
- {
- float max = (float)Mathf.Max(R, Mathf.Max(G, B));
- float min = (float)Mathf.Min(R, Mathf.Min(G, B));
-
- float delta = max - min;
-
- if (delta == 0.0f)
- {
- hue = 0.0f;
- }
- else
- {
- if (R == max)
- {
- hue = (G - B) / delta; // Between yellow & magenta
- }
- else if (G == max)
- {
- hue = 2.0f + ((B - R) / delta); // Between cyan & yellow
- }
- else
- {
- hue = 4.0f + ((R - G) / delta); // Between magenta & cyan
- }
-
- hue /= 6.0f;
-
- if (hue < 0.0f)
- {
- hue += 1.0f;
- }
- }
-
- lightness = (max + min) / 2.0f;
-
- if (lightness == 0.0f || lightness == 1.0f)
- {
- saturation = 0.0f;
- }
- else
- {
- saturation = delta / (1.0f - Math.Abs(2.0f * lightness - 1.0f));
- }
- }
-
private static int ParseCol4(ReadOnlySpan<char> str, int index)
{
char character = str[index];
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index 63423e655c..b0b52a6732 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -166,6 +166,20 @@ real_t GodotNavigationServer::map_get_cell_size(RID p_map) const {
return map->get_cell_size();
}
+COMMAND_2(map_set_use_edge_connections, RID, p_map, bool, p_enabled) {
+ NavMap *map = map_owner.get_or_null(p_map);
+ ERR_FAIL_COND(map == nullptr);
+
+ map->set_use_edge_connections(p_enabled);
+}
+
+bool GodotNavigationServer::map_get_use_edge_connections(RID p_map) const {
+ NavMap *map = map_owner.get_or_null(p_map);
+ ERR_FAIL_COND_V(map == nullptr, false);
+
+ return map->get_use_edge_connections();
+}
+
COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin) {
NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND(map == nullptr);
@@ -312,6 +326,20 @@ RID GodotNavigationServer::region_create() {
return rid;
}
+COMMAND_2(region_set_use_edge_connections, RID, p_region, bool, p_enabled) {
+ NavRegion *region = region_owner.get_or_null(p_region);
+ ERR_FAIL_COND(region == nullptr);
+
+ region->set_use_edge_connections(p_enabled);
+}
+
+bool GodotNavigationServer::region_get_use_edge_connections(RID p_region) const {
+ NavRegion *region = region_owner.get_or_null(p_region);
+ ERR_FAIL_COND_V(region == nullptr, false);
+
+ return region->get_use_edge_connections();
+}
+
COMMAND_2(region_set_map, RID, p_region, RID, p_map) {
NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND(region == nullptr);
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index ee9b1f05b7..5d68844a9b 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -107,6 +107,9 @@ public:
COMMAND_2(map_set_cell_size, RID, p_map, real_t, p_cell_size);
virtual real_t map_get_cell_size(RID p_map) const override;
+ COMMAND_2(map_set_use_edge_connections, RID, p_map, bool, p_enabled);
+ virtual bool map_get_use_edge_connections(RID p_map) const override;
+
COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin);
virtual real_t map_get_edge_connection_margin(RID p_map) const override;
@@ -129,6 +132,9 @@ public:
virtual RID region_create() override;
+ COMMAND_2(region_set_use_edge_connections, RID, p_region, bool, p_enabled);
+ virtual bool region_get_use_edge_connections(RID p_region) const override;
+
COMMAND_2(region_set_enter_cost, RID, p_region, real_t, p_enter_cost);
virtual real_t region_get_enter_cost(RID p_region) const override;
COMMAND_2(region_set_travel_cost, RID, p_region, real_t, p_travel_cost);
diff --git a/modules/navigation/nav_base.h b/modules/navigation/nav_base.h
index d4354f929d..b5cdc117f2 100644
--- a/modules/navigation/nav_base.h
+++ b/modules/navigation/nav_base.h
@@ -48,6 +48,9 @@ protected:
public:
NavigationUtilities::PathSegmentType get_type() const { return type; }
+ virtual void set_use_edge_connections(bool p_enabled) {}
+ virtual bool get_use_edge_connections() const { return false; }
+
void set_navigation_layers(uint32_t p_navigation_layers) { navigation_layers = p_navigation_layers; }
uint32_t get_navigation_layers() const { return navigation_layers; }
@@ -59,6 +62,8 @@ public:
void set_owner_id(ObjectID p_owner_id) { owner_id = p_owner_id; }
ObjectID get_owner_id() const { return owner_id; }
+
+ virtual ~NavBase(){};
};
#endif // NAV_BASE_H
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 57d702e846..37e0f232e5 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -69,6 +69,14 @@ void NavMap::set_cell_size(real_t p_cell_size) {
regenerate_polygons = true;
}
+void NavMap::set_use_edge_connections(bool p_enabled) {
+ if (use_edge_connections == p_enabled) {
+ return;
+ }
+ use_edge_connections = p_enabled;
+ regenerate_links = true;
+}
+
void NavMap::set_edge_connection_margin(real_t p_edge_connection_margin) {
if (edge_connection_margin == p_edge_connection_margin) {
return;
@@ -751,7 +759,9 @@ void NavMap::sync() {
_new_pm_edge_merge_count += 1;
} else {
CRASH_COND_MSG(E.value.size() != 1, vformat("Number of connection != 1. Found: %d", E.value.size()));
- free_edges.push_back(E.value[0]);
+ if (use_edge_connections && E.value[0].polygon->owner->get_use_edge_connections()) {
+ free_edges.push_back(E.value[0]);
+ }
}
}
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index 343f53760b..2bd9459626 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -57,6 +57,7 @@ class NavMap : public NavRid {
/// each cell has the following cell_size.
real_t cell_size = 0.25;
+ bool use_edge_connections = true;
/// This value is used to detect the near edges to connect.
real_t edge_connection_margin = 0.25;
@@ -130,6 +131,11 @@ public:
return cell_size;
}
+ void set_use_edge_connections(bool p_enabled);
+ bool get_use_edge_connections() const {
+ return use_edge_connections;
+ }
+
void set_edge_connection_margin(real_t p_edge_connection_margin);
real_t get_edge_connection_margin() const {
return edge_connection_margin;
diff --git a/modules/navigation/nav_region.cpp b/modules/navigation/nav_region.cpp
index bcee6ed751..d0f055874e 100644
--- a/modules/navigation/nav_region.cpp
+++ b/modules/navigation/nav_region.cpp
@@ -43,6 +43,13 @@ void NavRegion::set_map(NavMap *p_map) {
}
}
+void NavRegion::set_use_edge_connections(bool p_enabled) {
+ if (use_edge_connections != p_enabled) {
+ use_edge_connections = p_enabled;
+ polygons_dirty = true;
+ }
+}
+
void NavRegion::set_transform(Transform3D p_transform) {
if (transform == p_transform) {
return;
diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h
index 0942aa22f0..72299e8874 100644
--- a/modules/navigation/nav_region.h
+++ b/modules/navigation/nav_region.h
@@ -42,6 +42,8 @@ class NavRegion : public NavBase {
Ref<NavigationMesh> mesh;
Vector<gd::Edge::Connection> connections;
+ bool use_edge_connections = true;
+
bool polygons_dirty = true;
/// Cache
@@ -61,6 +63,11 @@ public:
return map;
}
+ void set_use_edge_connections(bool p_enabled);
+ bool get_use_edge_connections() const {
+ return use_edge_connections;
+ }
+
void set_transform(Transform3D transform);
const Transform3D &get_transform() const {
return transform;
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index 73c0851dc7..49b15c7a90 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -520,7 +520,11 @@ if env["builtin_icu4c"]:
module_obj = []
if env["builtin_msdfgen"] and msdfgen_enabled:
- env_text_server_adv.Prepend(CPPPATH=["#thirdparty/msdfgen"])
+ # Treat msdfgen headers as system headers to avoid raising warnings. Not supported on MSVC.
+ if not env.msvc:
+ env_text_server_adv.Append(CPPFLAGS=["-isystem", Dir("#thirdparty/msdfgen").path])
+ else:
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/msdfgen"])
if env["builtin_freetype"] and freetype_enabled:
env_text_server_adv.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
diff --git a/modules/text_server_fb/SCsub b/modules/text_server_fb/SCsub
index f1d57ec4d3..582e622147 100644
--- a/modules/text_server_fb/SCsub
+++ b/modules/text_server_fb/SCsub
@@ -12,7 +12,11 @@ if "svg" in env.module_list:
env_text_server_fb.Prepend(CPPPATH=["#thirdparty/thorvg/inc", "#thirdparty/thorvg/src/lib"])
if env["builtin_msdfgen"] and msdfgen_enabled:
- env_text_server_fb.Prepend(CPPPATH=["#thirdparty/msdfgen"])
+ # Treat msdfgen headers as system headers to avoid raising warnings. Not supported on MSVC.
+ if not env.msvc:
+ env_text_server_fb.Append(CPPFLAGS=["-isystem", Dir("#thirdparty/msdfgen").path])
+ else:
+ env_text_server_fb.Prepend(CPPPATH=["#thirdparty/msdfgen"])
if env["builtin_freetype"] and freetype_enabled:
env_text_server_fb.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index e111bd18ca..99527ccf3a 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -1044,6 +1044,11 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
return PermissionsUtil.getGrantedPermissions(getActivity());
}
+ @Keep
+ private String getCACertificates() {
+ return GodotNetUtils.getCACertificates();
+ }
+
/**
* The download state should trigger changes in the UI --- it may be useful
* to show the state as being indeterminate at times. This sample can be
diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java b/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java
index 401c105cd7..c31d56a3e1 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java
@@ -33,11 +33,17 @@ package org.godotengine.godot.utils;
import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
+import android.util.Base64;
import android.util.Log;
+import java.io.StringWriter;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+
/**
* This class handles Android-specific networking functions.
- * For now, it only provides access to WifiManager.MulticastLock, which is needed on some devices
+ * It provides access to the CA certificates KeyStore, and the WifiManager.MulticastLock, which is needed on some devices
* to receive broadcast and multicast packets.
*/
public class GodotNetUtils {
@@ -79,4 +85,34 @@ public class GodotNetUtils {
Log.e("Godot", "Exception during multicast lock release: " + e);
}
}
+
+ /**
+ * Retrieves the list of trusted CA certificates from the "AndroidCAStore" and returns them in PRM format.
+ * @see https://developer.android.com/reference/java/security/KeyStore .
+ * @return A string of concatenated X509 certificates in PEM format.
+ */
+ public static String getCACertificates() {
+ try {
+ KeyStore ks = KeyStore.getInstance("AndroidCAStore");
+ StringBuilder writer = new StringBuilder();
+
+ if (ks != null) {
+ ks.load(null, null);
+ Enumeration<String> aliases = ks.aliases();
+
+ while (aliases.hasMoreElements()) {
+ String alias = (String)aliases.nextElement();
+
+ X509Certificate cert = (X509Certificate)ks.getCertificate(alias);
+ writer.append("-----BEGIN CERTIFICATE-----\n");
+ writer.append(Base64.encodeToString(cert.getEncoded(), Base64.DEFAULT));
+ writer.append("-----END CERTIFICATE-----\n");
+ }
+ }
+ return writer.toString();
+ } catch (Exception e) {
+ Log.e("Godot", "Exception while reading CA certificates: " + e);
+ return "";
+ }
+ }
}
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index 9d9d087896..2b504ad69b 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -70,6 +70,7 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_
_request_permission = p_env->GetMethodID(godot_class, "requestPermission", "(Ljava/lang/String;)Z");
_request_permissions = p_env->GetMethodID(godot_class, "requestPermissions", "()Z");
_get_granted_permissions = p_env->GetMethodID(godot_class, "getGrantedPermissions", "()[Ljava/lang/String;");
+ _get_ca_certificates = p_env->GetMethodID(godot_class, "getCACertificates", "()Ljava/lang/String;");
_init_input_devices = p_env->GetMethodID(godot_class, "initInputDevices", "()V");
_get_surface = p_env->GetMethodID(godot_class, "getSurface", "()Landroid/view/Surface;");
_is_activity_resumed = p_env->GetMethodID(godot_class, "isActivityResumed", "()Z");
@@ -310,6 +311,17 @@ Vector<String> GodotJavaWrapper::get_granted_permissions() const {
return permissions_list;
}
+String GodotJavaWrapper::get_ca_certificates() const {
+ if (_get_ca_certificates) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL_V(env, String());
+ jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_ca_certificates);
+ return jstring_to_string(s, env);
+ } else {
+ return String();
+ }
+}
+
void GodotJavaWrapper::init_input_devices() {
if (_init_input_devices) {
JNIEnv *env = get_jni_env();
diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h
index 1bd79584d8..05144380e6 100644
--- a/platform/android/java_godot_wrapper.h
+++ b/platform/android/java_godot_wrapper.h
@@ -60,6 +60,7 @@ private:
jmethodID _request_permission = nullptr;
jmethodID _request_permissions = nullptr;
jmethodID _get_granted_permissions = nullptr;
+ jmethodID _get_ca_certificates = nullptr;
jmethodID _init_input_devices = nullptr;
jmethodID _get_surface = nullptr;
jmethodID _is_activity_resumed = nullptr;
@@ -98,6 +99,7 @@ public:
bool request_permission(const String &p_name);
bool request_permissions();
Vector<String> get_granted_permissions() const;
+ String get_ca_certificates() const;
void init_input_devices();
jobject get_surface();
bool is_activity_resumed();
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 1ea742dc6d..73081e35e7 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -757,6 +757,10 @@ Error OS_Android::kill(const ProcessID &p_pid) {
return OS_Unix::kill(p_pid);
}
+String OS_Android::get_system_ca_certificates() {
+ return godot_java->get_ca_certificates();
+}
+
Error OS_Android::setup_remote_filesystem(const String &p_server_host, int p_port, const String &p_password, String &r_project_path) {
r_project_path = get_user_data_dir();
Error err = OS_Unix::setup_remote_filesystem(p_server_host, p_port, p_password, r_project_path);
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 902712d69e..f1d08b7cfe 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -160,6 +160,7 @@ public:
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
virtual Error kill(const ProcessID &p_pid) override;
+ virtual String get_system_ca_certificates() override;
virtual Error setup_remote_filesystem(const String &p_server_host, int p_port, const String &p_password, String &r_project_path) override;
diff --git a/platform/ios/ios.mm b/platform/ios/ios.mm
index 1065f5fd2a..c911a512a5 100644
--- a/platform/ios/ios.mm
+++ b/platform/ios/ios.mm
@@ -72,8 +72,8 @@ CHHapticEngine *iOS::get_haptic_engine_instance() API_AVAILABLE(ios(13)) {
void iOS::vibrate_haptic_engine(float p_duration_seconds) API_AVAILABLE(ios(13)) {
if (@available(iOS 13, *)) { // We need the @available check every time to make the compiler happy...
if (supports_haptic_engine()) {
- CHHapticEngine *haptic_engine = get_haptic_engine_instance();
- if (haptic_engine) {
+ CHHapticEngine *cur_haptic_engine = get_haptic_engine_instance();
+ if (cur_haptic_engine) {
NSDictionary *hapticDict = @{
CHHapticPatternKeyPattern : @[
@{CHHapticPatternKeyEvent : @{
@@ -88,7 +88,7 @@ void iOS::vibrate_haptic_engine(float p_duration_seconds) API_AVAILABLE(ios(13))
NSError *error;
CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithDictionary:hapticDict error:&error];
- [[haptic_engine createPlayerWithPattern:pattern error:&error] startAtTime:0 error:&error];
+ [[cur_haptic_engine createPlayerWithPattern:pattern error:&error] startAtTime:0 error:&error];
NSLog(@"Could not vibrate using haptic engine: %@", error);
}
@@ -103,9 +103,9 @@ void iOS::vibrate_haptic_engine(float p_duration_seconds) API_AVAILABLE(ios(13))
void iOS::start_haptic_engine() {
if (@available(iOS 13, *)) {
if (supports_haptic_engine()) {
- CHHapticEngine *haptic_engine = get_haptic_engine_instance();
- if (haptic_engine) {
- [haptic_engine startWithCompletionHandler:^(NSError *returnedError) {
+ CHHapticEngine *cur_haptic_engine = get_haptic_engine_instance();
+ if (cur_haptic_engine) {
+ [cur_haptic_engine startWithCompletionHandler:^(NSError *returnedError) {
if (returnedError) {
NSLog(@"Could not start haptic engine: %@", returnedError);
}
@@ -122,9 +122,9 @@ void iOS::start_haptic_engine() {
void iOS::stop_haptic_engine() {
if (@available(iOS 13, *)) {
if (supports_haptic_engine()) {
- CHHapticEngine *haptic_engine = get_haptic_engine_instance();
- if (haptic_engine) {
- [haptic_engine stopWithCompletionHandler:^(NSError *returnedError) {
+ CHHapticEngine *cur_haptic_engine = get_haptic_engine_instance();
+ if (cur_haptic_engine) {
+ [cur_haptic_engine stopWithCompletionHandler:^(NSError *returnedError) {
if (returnedError) {
NSLog(@"Could not stop haptic engine: %@", returnedError);
}
diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp
index b45b7e676d..6dfa8ed93c 100644
--- a/platform/linuxbsd/freedesktop_portal_desktop.cpp
+++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp
@@ -138,6 +138,11 @@ FreeDesktopPortalDesktop::FreeDesktopPortalDesktop() {
#else
unsupported = false;
#endif
+
+ if (unsupported) {
+ return;
+ }
+
bool ver_ok = false;
int version_major = 0;
int version_minor = 0;
diff --git a/platform/linuxbsd/freedesktop_screensaver.cpp b/platform/linuxbsd/freedesktop_screensaver.cpp
index 78f2337599..cf179b5735 100644
--- a/platform/linuxbsd/freedesktop_screensaver.cpp
+++ b/platform/linuxbsd/freedesktop_screensaver.cpp
@@ -141,6 +141,11 @@ FreeDesktopScreenSaver::FreeDesktopScreenSaver() {
#else
unsupported = false;
#endif
+
+ if (unsupported) {
+ return;
+ }
+
bool ver_ok = false;
int version_major = 0;
int version_minor = 0;
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 82500f83cb..8d8c8ce27b 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -30,6 +30,7 @@
#include "os_linuxbsd.h"
+#include "core/io/certs_compressed.gen.h"
#include "core/io/dir_access.h"
#include "main/main.h"
#include "servers/display_server.h"
@@ -494,6 +495,11 @@ bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
return true;
}
+ // Match against the specific OS (linux, freebsd, etc).
+ if (p_feature == get_name().to_lower()) {
+ return true;
+ }
+
return false;
}
@@ -1080,6 +1086,40 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
return OK;
}
+String OS_LinuxBSD::get_system_ca_certificates() {
+ String certfile;
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ // Compile time preferred certificates path.
+ if (!String(_SYSTEM_CERTS_PATH).is_empty() && da->file_exists(_SYSTEM_CERTS_PATH)) {
+ certfile = _SYSTEM_CERTS_PATH;
+ } else if (da->file_exists("/etc/ssl/certs/ca-certificates.crt")) {
+ // Debian/Ubuntu
+ certfile = "/etc/ssl/certs/ca-certificates.crt";
+ } else if (da->file_exists("/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem")) {
+ // Fedora
+ certfile = "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem";
+ } else if (da->file_exists("/etc/ca-certificates/extracted/tls-ca-bundle.pem")) {
+ // Arch Linux
+ certfile = "/etc/ca-certificates/extracted/tls-ca-bundle.pem";
+ } else if (da->file_exists("/var/lib/ca-certificates/ca-bundle.pem")) {
+ // openSUSE
+ certfile = "/var/lib/ca-certificates/ca-bundle.pem";
+ } else if (da->file_exists("/etc/ssl/cert.pem")) {
+ // FreeBSD/OpenBSD
+ certfile = "/etc/ssl/cert.pem";
+ }
+
+ if (certfile.is_empty()) {
+ return "";
+ }
+
+ Ref<FileAccess> f = FileAccess::open(certfile, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), "", vformat("Failed to open system CA certificates file: '%s'", certfile));
+
+ return f->get_as_text();
+}
+
OS_LinuxBSD::OS_LinuxBSD() {
main_loop = nullptr;
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index 8dda06b6df..c1e735b0d4 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -133,6 +133,8 @@ public:
virtual Error move_to_trash(const String &p_path) override;
+ virtual String get_system_ca_certificates() override;
+
OS_LinuxBSD();
~OS_LinuxBSD();
};
diff --git a/platform/linuxbsd/x11/detect_prime_x11.cpp b/platform/linuxbsd/x11/detect_prime_x11.cpp
index 3d07be1c76..78778a8b56 100644
--- a/platform/linuxbsd/x11/detect_prime_x11.cpp
+++ b/platform/linuxbsd/x11/detect_prime_x11.cpp
@@ -60,6 +60,9 @@
typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
+// To prevent shadowing warnings
+#undef glGetString
+
struct vendor {
const char *glxvendor = nullptr;
int priority = 0;
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 043a18349f..13f261aa43 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -2725,8 +2725,8 @@ void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu
XcursorImageDestroy(cursor_image);
} else {
// Reset to default system cursor
- if (img[p_shape]) {
- cursors[p_shape] = XcursorImageLoadCursor(x11_display, img[p_shape]);
+ if (cursor_img[p_shape]) {
+ cursors[p_shape] = XcursorImageLoadCursor(x11_display, cursor_img[p_shape]);
}
CursorShape c = current_cursor;
@@ -5360,7 +5360,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
for (int i = 0; i < CURSOR_MAX; i++) {
cursors[i] = None;
- img[i] = nullptr;
+ cursor_img[i] = nullptr;
}
XInitThreads(); //always use threads
@@ -5717,8 +5717,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
"question_arrow"
};
- img[i] = XcursorLibraryLoadImage(cursor_file[i], cursor_theme, cursor_size);
- if (!img[i]) {
+ cursor_img[i] = XcursorLibraryLoadImage(cursor_file[i], cursor_theme, cursor_size);
+ if (!cursor_img[i]) {
const char *fallback = nullptr;
switch (i) {
@@ -5756,7 +5756,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
fallback = "bd_double_arrow";
break;
case CURSOR_MOVE:
- img[i] = img[CURSOR_DRAG];
+ cursor_img[i] = cursor_img[CURSOR_DRAG];
break;
case CURSOR_VSPLIT:
fallback = "sb_v_double_arrow";
@@ -5769,11 +5769,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
break;
}
if (fallback != nullptr) {
- img[i] = XcursorLibraryLoadImage(fallback, cursor_theme, cursor_size);
+ cursor_img[i] = XcursorLibraryLoadImage(fallback, cursor_theme, cursor_size);
}
}
- if (img[i]) {
- cursors[i] = XcursorImageLoadCursor(x11_display, img[i]);
+ if (cursor_img[i]) {
+ cursors[i] = XcursorImageLoadCursor(x11_display, cursor_img[i]);
} else {
print_verbose("Failed loading custom cursor: " + String(cursor_file[i]));
}
@@ -5912,8 +5912,8 @@ DisplayServerX11::~DisplayServerX11() {
if (cursors[i] != None) {
XFreeCursor(x11_display, cursors[i]);
}
- if (img[i] != nullptr) {
- XcursorImageDestroy(img[i]);
+ if (cursor_img[i] != nullptr) {
+ XcursorImageDestroy(cursor_img[i]);
}
}
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index 67fa21c75f..6d343be3ab 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -306,7 +306,7 @@ class DisplayServerX11 : public DisplayServer {
const char *cursor_theme = nullptr;
int cursor_size = 0;
- XcursorImage *img[CURSOR_MAX];
+ XcursorImage *cursor_img[CURSOR_MAX];
Cursor cursors[CURSOR_MAX];
Cursor null_cursor;
CursorShape current_cursor = CURSOR_ARROW;
diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp
index ee767dfa80..1e579c9f01 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.cpp
+++ b/platform/linuxbsd/x11/gl_manager_x11.cpp
@@ -44,6 +44,9 @@
typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
+// To prevent shadowing warnings
+#undef glXCreateContextAttribsARB
+
struct GLManager_X11_Private {
::GLXContext glx_context;
};
diff --git a/platform/macos/detect.py b/platform/macos/detect.py
index 1fefdb3c68..7b8d3fd853 100644
--- a/platform/macos/detect.py
+++ b/platform/macos/detect.py
@@ -235,6 +235,8 @@ def configure(env: "Environment"):
"CoreMedia",
"-framework",
"QuartzCore",
+ "-framework",
+ "Security",
]
)
env.Append(LIBS=["pthread", "z"])
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 5a7c309448..32f9441484 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -1840,9 +1840,9 @@ Error DisplayServerMacOS::dialog_show(String p_title, String p_description, Vect
if (!p_callback.is_null()) {
Variant button = button_pressed;
Variant *buttonp = &button;
- Variant ret;
+ Variant fun_ret;
Callable::CallError ce;
- p_callback.callp((const Variant **)&buttonp, 1, ret, ce);
+ p_callback.callp((const Variant **)&buttonp, 1, fun_ret, ce);
}
return OK;
@@ -1872,9 +1872,9 @@ Error DisplayServerMacOS::dialog_input_text(String p_title, String p_description
if (!p_callback.is_null()) {
Variant text = ret;
Variant *textp = &text;
- Variant ret;
+ Variant fun_ret;
Callable::CallError ce;
- p_callback.callp((const Variant **)&textp, 1, ret, ce);
+ p_callback.callp((const Variant **)&textp, 1, fun_ret, ce);
}
return OK;
@@ -1897,7 +1897,7 @@ void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) {
bool previously_shown = (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED);
if (show_cursor && !previously_shown) {
- WindowID window_id = get_window_at_screen_position(mouse_get_position());
+ window_id = get_window_at_screen_position(mouse_get_position());
if (window_id != INVALID_WINDOW_ID) {
send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER);
}
diff --git a/platform/macos/os_macos.h b/platform/macos/os_macos.h
index eb7a30203a..07bae479be 100644
--- a/platform/macos/os_macos.h
+++ b/platform/macos/os_macos.h
@@ -119,6 +119,8 @@ public:
virtual Error move_to_trash(const String &p_path) override;
+ virtual String get_system_ca_certificates() override;
+
void run();
OS_MacOS();
diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm
index 74cdef6f25..838ae742fd 100644
--- a/platform/macos/os_macos.mm
+++ b/platform/macos/os_macos.mm
@@ -30,6 +30,7 @@
#include "os_macos.h"
+#include "core/crypto/crypto_core.h"
#include "core/version_generated.gen.h"
#include "main/main.h"
@@ -671,6 +672,34 @@ Error OS_MacOS::move_to_trash(const String &p_path) {
return OK;
}
+String OS_MacOS::get_system_ca_certificates() {
+ CFArrayRef result;
+ SecCertificateRef item;
+ CFDataRef der;
+
+ OSStatus ret = SecTrustCopyAnchorCertificates(&result);
+ ERR_FAIL_COND_V(ret != noErr, "");
+
+ CFIndex l = CFArrayGetCount(result);
+ String certs;
+ PackedByteArray pba;
+ for (CFIndex i = 0; i < l; i++) {
+ item = (SecCertificateRef)CFArrayGetValueAtIndex(result, i);
+ der = SecCertificateCopyData(item);
+ int derlen = CFDataGetLength(der);
+ if (pba.size() < derlen * 3) {
+ pba.resize(derlen * 3);
+ }
+ size_t b64len = 0;
+ Error err = CryptoCore::b64_encode(pba.ptrw(), pba.size(), &b64len, (unsigned char *)CFDataGetBytePtr(der), derlen);
+ CFRelease(der);
+ ERR_CONTINUE(err != OK);
+ certs += "-----BEGIN CERTIFICATE-----\n" + String((char *)pba.ptr(), b64len) + "\n-----END CERTIFICATE-----\n";
+ }
+ CFRelease(result);
+ return certs;
+}
+
void OS_MacOS::run() {
if (!main_loop) {
return;
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index cd6d461a93..963f533d67 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -413,6 +413,7 @@ def configure_msvc(env, vcvars_msvc_config):
"dxguid",
"imm32",
"bcrypt",
+ "Crypt32",
"Avrt",
"dwmapi",
"dwrite",
@@ -592,6 +593,7 @@ def configure_mingw(env):
"ksuser",
"imm32",
"bcrypt",
+ "crypt32",
"avrt",
"uuid",
"dwmapi",
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index a13d6ed986..bd7d9f178a 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -55,6 +55,7 @@
#include <regstr.h>
#include <shlobj.h>
#include <wbemcli.h>
+#include <wincrypt.h>
#ifdef DEBUG_ENABLED
#pragma pack(push, before_imagehlp, 8)
@@ -435,8 +436,6 @@ String OS_Windows::get_distribution_name() const {
}
String OS_Windows::get_version() const {
- typedef LONG NTSTATUS;
- typedef NTSTATUS(WINAPI * RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
RtlGetVersionPtr version_ptr = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
if (version_ptr != nullptr) {
RTL_OSVERSIONINFOW fow;
@@ -554,9 +553,9 @@ OS::DateTime OS_Windows::get_datetime(bool p_utc) const {
//Get DST information from Windows, but only if p_utc is false.
TIME_ZONE_INFORMATION info;
- bool daylight = false;
+ bool is_daylight = false;
if (!p_utc && GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) {
- daylight = true;
+ is_daylight = true;
}
DateTime dt;
@@ -567,20 +566,20 @@ OS::DateTime OS_Windows::get_datetime(bool p_utc) const {
dt.hour = systemtime.wHour;
dt.minute = systemtime.wMinute;
dt.second = systemtime.wSecond;
- dt.dst = daylight;
+ dt.dst = is_daylight;
return dt;
}
OS::TimeZoneInfo OS_Windows::get_time_zone_info() const {
TIME_ZONE_INFORMATION info;
- bool daylight = false;
+ bool is_daylight = false;
if (GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) {
- daylight = true;
+ is_daylight = true;
}
// Daylight Bias needs to be added to the bias if DST is in effect, or else it will not properly update.
TimeZoneInfo ret;
- if (daylight) {
+ if (is_daylight) {
ret.name = info.DaylightName;
ret.bias = info.Bias + info.DaylightBias;
} else {
@@ -1677,6 +1676,26 @@ Error OS_Windows::move_to_trash(const String &p_path) {
return OK;
}
+String OS_Windows::get_system_ca_certificates() {
+ HCERTSTORE cert_store = CertOpenSystemStoreA(0, "ROOT");
+ ERR_FAIL_COND_V_MSG(!cert_store, "", "Failed to read the root certificate store.");
+
+ String certs;
+ PCCERT_CONTEXT curr = CertEnumCertificatesInStore(cert_store, nullptr);
+ while (curr) {
+ DWORD size = 0;
+ bool success = CryptBinaryToStringA(curr->pbCertEncoded, curr->cbCertEncoded, CRYPT_STRING_BASE64HEADER | CRYPT_STRING_NOCR, nullptr, &size);
+ ERR_CONTINUE(!success);
+ PackedByteArray pba;
+ pba.resize(size);
+ CryptBinaryToStringA(curr->pbCertEncoded, curr->cbCertEncoded, CRYPT_STRING_BASE64HEADER | CRYPT_STRING_NOCR, (char *)pba.ptrw(), &size);
+ certs += String((char *)pba.ptr(), size);
+ curr = CertEnumCertificatesInStore(cert_store, curr);
+ }
+ CertCloseStore(cert_store, 0);
+ return certs;
+}
+
OS_Windows::OS_Windows(HINSTANCE _hInstance) {
hInstance = _hInstance;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 960c3f30a9..c5f95870b3 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -226,6 +226,8 @@ public:
virtual Error move_to_trash(const String &p_path) override;
+ virtual String get_system_ca_certificates() override;
+
void set_main_window(HWND p_main_window) { main_window = p_main_window; }
HINSTANCE get_hinstance() { return hInstance; }
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index cbcdb9f88e..c14fb29353 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -67,6 +67,20 @@ bool NavigationRegion2D::is_enabled() const {
return enabled;
}
+void NavigationRegion2D::set_use_edge_connections(bool p_enabled) {
+ if (use_edge_connections == p_enabled) {
+ return;
+ }
+
+ use_edge_connections = p_enabled;
+
+ NavigationServer2D::get_singleton()->region_set_use_edge_connections(region, use_edge_connections);
+}
+
+bool NavigationRegion2D::get_use_edge_connections() const {
+ return use_edge_connections;
+}
+
void NavigationRegion2D::set_navigation_layers(uint32_t p_navigation_layers) {
if (navigation_layers == p_navigation_layers) {
return;
@@ -210,7 +224,7 @@ void NavigationRegion2D::_notification(int p_what) {
bool enabled_geometry_face_random_color = ns2d->get_debug_navigation_enable_geometry_face_random_color();
bool enabled_edge_lines = ns2d->get_debug_navigation_enable_edge_lines();
- bool enable_edge_connections = ns2d->get_debug_navigation_enable_edge_connections();
+ bool enable_edge_connections = use_edge_connections && ns2d->get_debug_navigation_enable_edge_connections() && ns2d->map_get_use_edge_connections(get_world_2d()->get_navigation_map());
Color debug_face_color = ns2d->get_debug_navigation_geometry_face_color();
Color debug_edge_color = ns2d->get_debug_navigation_geometry_edge_color();
@@ -340,6 +354,9 @@ void NavigationRegion2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion2D::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_use_edge_connections", "enabled"), &NavigationRegion2D::set_use_edge_connections);
+ ClassDB::bind_method(D_METHOD("get_use_edge_connections"), &NavigationRegion2D::get_use_edge_connections);
+
ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationRegion2D::set_navigation_layers);
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationRegion2D::get_navigation_layers);
@@ -365,6 +382,7 @@ void NavigationRegion2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navigation_polygon", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_edge_connections"), "set_use_edge_connections", "get_use_edge_connections");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h
index bd7bdc28eb..39de0a0004 100644
--- a/scene/2d/navigation_region_2d.h
+++ b/scene/2d/navigation_region_2d.h
@@ -37,6 +37,8 @@ class NavigationRegion2D : public Node2D {
GDCLASS(NavigationRegion2D, Node2D);
bool enabled = true;
+ bool use_edge_connections = true;
+
RID region;
uint32_t navigation_layers = 1;
real_t enter_cost = 0.0;
@@ -71,6 +73,9 @@ public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
+ void set_use_edge_connections(bool p_enabled);
+ bool get_use_edge_connections() const;
+
void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers() const;
diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h
index 018ed9485d..5a390eaede 100644
--- a/scene/3d/lightmapper.h
+++ b/scene/3d/lightmapper.h
@@ -71,15 +71,15 @@ public:
/*! Constructs a ray from origin, direction, and ray segment. Near
* has to be smaller than far. */
- _FORCE_INLINE_ Ray(const Vector3 &org,
- const Vector3 &dir,
- float tnear = 0.0f,
- float tfar = INFINITY) :
- org(org),
- tnear(tnear),
- dir(dir),
+ _FORCE_INLINE_ Ray(const Vector3 &p_org,
+ const Vector3 &p_dir,
+ float p_tnear = 0.0f,
+ float p_tfar = INFINITY) :
+ org(p_org),
+ tnear(p_tnear),
+ dir(p_dir),
time(0.0f),
- tfar(tfar),
+ tfar(p_tfar),
mask(-1),
u(0.0),
v(0.0),
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index b775ef94cb..165d44436c 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -81,6 +81,20 @@ bool NavigationRegion3D::is_enabled() const {
return enabled;
}
+void NavigationRegion3D::set_use_edge_connections(bool p_enabled) {
+ if (use_edge_connections == p_enabled) {
+ return;
+ }
+
+ use_edge_connections = p_enabled;
+
+ NavigationServer3D::get_singleton()->region_set_use_edge_connections(region, use_edge_connections);
+}
+
+bool NavigationRegion3D::get_use_edge_connections() const {
+ return use_edge_connections;
+}
+
void NavigationRegion3D::set_navigation_layers(uint32_t p_navigation_layers) {
if (navigation_layers == p_navigation_layers) {
return;
@@ -307,6 +321,9 @@ void NavigationRegion3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion3D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion3D::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_use_edge_connections", "enabled"), &NavigationRegion3D::set_use_edge_connections);
+ ClassDB::bind_method(D_METHOD("get_use_edge_connections"), &NavigationRegion3D::get_use_edge_connections);
+
ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationRegion3D::set_navigation_layers);
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationRegion3D::get_navigation_layers);
@@ -326,6 +343,7 @@ void NavigationRegion3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navigation_mesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_edge_connections"), "set_use_edge_connections", "get_use_edge_connections");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
@@ -602,6 +620,13 @@ void NavigationRegion3D::_update_debug_edge_connections_mesh() {
return;
}
+ if (!use_edge_connections || !NavigationServer3D::get_singleton()->map_get_use_edge_connections(get_world_3d()->get_navigation_map())) {
+ if (debug_edge_connections_instance.is_valid()) {
+ RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
+ }
+ return;
+ }
+
if (!navigation_mesh.is_valid()) {
if (debug_edge_connections_instance.is_valid()) {
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h
index 4732c340ba..fd6deebd63 100644
--- a/scene/3d/navigation_region_3d.h
+++ b/scene/3d/navigation_region_3d.h
@@ -38,6 +38,8 @@ class NavigationRegion3D : public Node3D {
GDCLASS(NavigationRegion3D, Node3D);
bool enabled = true;
+ bool use_edge_connections = true;
+
RID region;
uint32_t navigation_layers = 1;
real_t enter_cost = 0.0;
@@ -75,6 +77,9 @@ public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
+ void set_use_edge_connections(bool p_enabled);
+ bool get_use_edge_connections() const;
+
void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers() const;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index cafc7c5e51..594276a428 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -294,6 +294,18 @@ Color ItemList::get_item_custom_fg_color(int p_idx) const {
return items[p_idx].custom_fg;
}
+Rect2 ItemList::get_item_rect(int p_idx, bool p_expand) const {
+ ERR_FAIL_INDEX_V(p_idx, items.size(), Rect2());
+
+ Rect2 ret = items[p_idx].rect_cache;
+ ret.position += theme_cache.panel_style->get_offset();
+
+ if (p_expand && p_idx % current_columns == current_columns - 1) {
+ ret.size.width = get_size().width - ret.position.x;
+ }
+ return ret;
+}
+
void ItemList::set_item_tag_icon(int p_idx, const Ref<Texture2D> &p_tag_icon) {
if (p_idx < 0) {
p_idx += get_item_count();
@@ -1778,6 +1790,8 @@ void ItemList::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_custom_fg_color", "idx", "custom_fg_color"), &ItemList::set_item_custom_fg_color);
ClassDB::bind_method(D_METHOD("get_item_custom_fg_color", "idx"), &ItemList::get_item_custom_fg_color);
+ ClassDB::bind_method(D_METHOD("get_item_rect", "idx", "expand"), &ItemList::get_item_rect, DEFVAL(true));
+
ClassDB::bind_method(D_METHOD("set_item_tooltip_enabled", "idx", "enable"), &ItemList::set_item_tooltip_enabled);
ClassDB::bind_method(D_METHOD("is_item_tooltip_enabled", "idx"), &ItemList::is_item_tooltip_enabled);
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index cd91f97410..ced04f8718 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -211,6 +211,8 @@ public:
void set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_color);
Color get_item_custom_fg_color(int p_idx) const;
+ Rect2 get_item_rect(int p_idx, bool p_expand = true) const;
+
void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior);
TextServer::OverrunBehavior get_text_overrun_behavior() const;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 3aaafeae30..11f2a6af66 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -202,6 +202,10 @@ void Node::_notification(int p_notification) {
return;
}
+ if (data.owner) {
+ _clean_up_owner();
+ }
+
if (data.parent) {
data.parent->remove_child(this);
}
@@ -301,11 +305,7 @@ void Node::_propagate_after_exit_tree() {
}
if (!found) {
- if (data.unique_name_in_owner) {
- _release_unique_name_in_owner();
- }
- data.owner->data.owned.erase(data.OW);
- data.owner = nullptr;
+ _clean_up_owner();
}
}
@@ -1876,12 +1876,7 @@ bool Node::is_unique_name_in_owner() const {
void Node::set_owner(Node *p_owner) {
ERR_MAIN_THREAD_GUARD
if (data.owner) {
- if (data.unique_name_in_owner) {
- _release_unique_name_in_owner();
- }
- data.owner->data.owned.erase(data.OW);
- data.OW = nullptr;
- data.owner = nullptr;
+ _clean_up_owner();
}
ERR_FAIL_COND(p_owner == this);
@@ -1915,6 +1910,17 @@ Node *Node::get_owner() const {
return data.owner;
}
+void Node::_clean_up_owner() {
+ ERR_FAIL_NULL(data.owner); // Sanity check.
+
+ if (data.unique_name_in_owner) {
+ _release_unique_name_in_owner();
+ }
+ data.owner->data.owned.erase(data.OW);
+ data.owner = nullptr;
+ data.OW = nullptr;
+}
+
Node *Node::find_common_parent_with(const Node *p_node) const {
if (this == p_node) {
return const_cast<Node *>(p_node);
@@ -2747,6 +2753,8 @@ void Node::replace_by(Node *p_node, bool p_keep_groups) {
for (int i = 0; i < get_child_count(); i++) {
find_owned_by(data.owner, get_child(i), &owned_by_owner);
}
+
+ _clean_up_owner();
}
Node *parent = data.parent;
diff --git a/scene/main/node.h b/scene/main/node.h
index 0b242eaf97..ad19a1b694 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -236,6 +236,8 @@ private:
void _release_unique_name_in_owner();
void _acquire_unique_name_in_owner();
+ void _clean_up_owner();
+
_FORCE_INLINE_ void _update_children_cache() const {
if (unlikely(data.children_cache_dirty)) {
_update_children_cache_impl();
diff --git a/scene/resources/audio_stream_wav.cpp b/scene/resources/audio_stream_wav.cpp
index f331e3a22c..669b455f89 100644
--- a/scene/resources/audio_stream_wav.cpp
+++ b/scene/resources/audio_stream_wav.cpp
@@ -87,21 +87,21 @@ void AudioStreamPlaybackWAV::seek(double p_time) {
}
template <class Depth, bool is_stereo, bool is_ima_adpcm>
-void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm) {
+void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm) {
// this function will be compiled branchless by any decent compiler
int32_t final, final_r, next, next_r;
- while (amount) {
- amount--;
- int64_t pos = offset >> MIX_FRAC_BITS;
+ while (p_amount) {
+ p_amount--;
+ int64_t pos = p_offset >> MIX_FRAC_BITS;
if (is_stereo && !is_ima_adpcm) {
pos <<= 1;
}
if (is_ima_adpcm) {
- int64_t sample_pos = pos + ima_adpcm[0].window_ofs;
+ int64_t sample_pos = pos + p_ima_adpcm[0].window_ofs;
- while (sample_pos > ima_adpcm[0].last_nibble) {
+ while (sample_pos > p_ima_adpcm[0].last_nibble) {
static const int16_t _ima_adpcm_step_table[89] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
@@ -122,20 +122,20 @@ void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst,
for (int i = 0; i < (is_stereo ? 2 : 1); i++) {
int16_t nibble, diff, step;
- ima_adpcm[i].last_nibble++;
+ p_ima_adpcm[i].last_nibble++;
const uint8_t *src_ptr = (const uint8_t *)base->data;
src_ptr += AudioStreamWAV::DATA_PAD;
- uint8_t nbb = src_ptr[(ima_adpcm[i].last_nibble >> 1) * (is_stereo ? 2 : 1) + i];
- nibble = (ima_adpcm[i].last_nibble & 1) ? (nbb >> 4) : (nbb & 0xF);
- step = _ima_adpcm_step_table[ima_adpcm[i].step_index];
+ uint8_t nbb = src_ptr[(p_ima_adpcm[i].last_nibble >> 1) * (is_stereo ? 2 : 1) + i];
+ nibble = (p_ima_adpcm[i].last_nibble & 1) ? (nbb >> 4) : (nbb & 0xF);
+ step = _ima_adpcm_step_table[p_ima_adpcm[i].step_index];
- ima_adpcm[i].step_index += _ima_adpcm_index_table[nibble];
- if (ima_adpcm[i].step_index < 0) {
- ima_adpcm[i].step_index = 0;
+ p_ima_adpcm[i].step_index += _ima_adpcm_index_table[nibble];
+ if (p_ima_adpcm[i].step_index < 0) {
+ p_ima_adpcm[i].step_index = 0;
}
- if (ima_adpcm[i].step_index > 88) {
- ima_adpcm[i].step_index = 88;
+ if (p_ima_adpcm[i].step_index > 88) {
+ p_ima_adpcm[i].step_index = 88;
}
diff = step >> 3;
@@ -152,26 +152,26 @@ void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst,
diff = -diff;
}
- ima_adpcm[i].predictor += diff;
- if (ima_adpcm[i].predictor < -0x8000) {
- ima_adpcm[i].predictor = -0x8000;
- } else if (ima_adpcm[i].predictor > 0x7FFF) {
- ima_adpcm[i].predictor = 0x7FFF;
+ p_ima_adpcm[i].predictor += diff;
+ if (p_ima_adpcm[i].predictor < -0x8000) {
+ p_ima_adpcm[i].predictor = -0x8000;
+ } else if (p_ima_adpcm[i].predictor > 0x7FFF) {
+ p_ima_adpcm[i].predictor = 0x7FFF;
}
/* store loop if there */
- if (ima_adpcm[i].last_nibble == ima_adpcm[i].loop_pos) {
- ima_adpcm[i].loop_step_index = ima_adpcm[i].step_index;
- ima_adpcm[i].loop_predictor = ima_adpcm[i].predictor;
+ if (p_ima_adpcm[i].last_nibble == p_ima_adpcm[i].loop_pos) {
+ p_ima_adpcm[i].loop_step_index = p_ima_adpcm[i].step_index;
+ p_ima_adpcm[i].loop_predictor = p_ima_adpcm[i].predictor;
}
- //printf("%i - %i - pred %i\n",int(ima_adpcm[i].last_nibble),int(nibble),int(ima_adpcm[i].predictor));
+ //printf("%i - %i - pred %i\n",int(p_ima_adpcm[i].last_nibble),int(nibble),int(p_ima_adpcm[i].predictor));
}
}
- final = ima_adpcm[0].predictor;
+ final = p_ima_adpcm[0].predictor;
if (is_stereo) {
- final_r = ima_adpcm[1].predictor;
+ final_r = p_ima_adpcm[1].predictor;
}
} else {
@@ -201,7 +201,7 @@ void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst,
}
}
- int32_t frac = int64_t(offset & MIX_FRAC_MASK);
+ int32_t frac = int64_t(p_offset & MIX_FRAC_MASK);
final = final + ((next - final) * frac >> MIX_FRAC_BITS);
if (is_stereo) {
@@ -217,7 +217,7 @@ void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst,
p_dst->r = final_r / 32767.0;
p_dst++;
- offset += increment;
+ p_offset += p_increment;
}
}
diff --git a/scene/resources/audio_stream_wav.h b/scene/resources/audio_stream_wav.h
index bea273720c..f150a17d21 100644
--- a/scene/resources/audio_stream_wav.h
+++ b/scene/resources/audio_stream_wav.h
@@ -61,7 +61,7 @@ class AudioStreamPlaybackWAV : public AudioStreamPlayback {
Ref<AudioStreamWAV> base;
template <class Depth, bool is_stereo, bool is_ima_adpcm>
- void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm);
+ void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm);
public:
virtual void start(double p_from_pos = 0.0) override;
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index c7304da358..f371703cba 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -59,6 +59,7 @@ RID World2D::get_navigation_map() const {
navigation_map = NavigationServer2D::get_singleton()->map_create();
NavigationServer2D::get_singleton()->map_set_active(navigation_map, true);
NavigationServer2D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_GET("navigation/2d/default_cell_size"));
+ NavigationServer2D::get_singleton()->map_set_use_edge_connections(navigation_map, GLOBAL_GET("navigation/2d/use_edge_connections"));
NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_GET("navigation/2d/default_edge_connection_margin"));
NavigationServer2D::get_singleton()->map_set_link_connection_radius(navigation_map, GLOBAL_GET("navigation/2d/default_link_connection_radius"));
}
diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp
index 82c056d5ee..cc961941cf 100644
--- a/scene/resources/world_3d.cpp
+++ b/scene/resources/world_3d.cpp
@@ -67,6 +67,7 @@ RID World3D::get_navigation_map() const {
navigation_map = NavigationServer3D::get_singleton()->map_create();
NavigationServer3D::get_singleton()->map_set_active(navigation_map, true);
NavigationServer3D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_GET("navigation/3d/default_cell_size"));
+ NavigationServer3D::get_singleton()->map_set_use_edge_connections(navigation_map, GLOBAL_GET("navigation/3d/use_edge_connections"));
NavigationServer3D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_GET("navigation/3d/default_edge_connection_margin"));
NavigationServer3D::get_singleton()->map_set_link_connection_radius(navigation_map, GLOBAL_GET("navigation/3d/default_link_connection_radius"));
}
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 706718be19..c2dddb0627 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -371,6 +371,8 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer2D::map_is_active);
ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer2D::map_set_cell_size);
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size);
+ ClassDB::bind_method(D_METHOD("map_set_use_edge_connections", "map", "enabled"), &NavigationServer2D::map_set_use_edge_connections);
+ ClassDB::bind_method(D_METHOD("map_get_use_edge_connections", "map"), &NavigationServer2D::map_get_use_edge_connections);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_set_link_connection_radius", "map", "radius"), &NavigationServer2D::map_set_link_connection_radius);
@@ -389,6 +391,8 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("query_path", "parameters", "result"), &NavigationServer2D::query_path);
ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create);
+ ClassDB::bind_method(D_METHOD("region_set_use_edge_connections", "region", "enabled"), &NavigationServer2D::region_set_use_edge_connections);
+ ClassDB::bind_method(D_METHOD("region_get_use_edge_connections", "region"), &NavigationServer2D::region_get_use_edge_connections);
ClassDB::bind_method(D_METHOD("region_set_enter_cost", "region", "enter_cost"), &NavigationServer2D::region_set_enter_cost);
ClassDB::bind_method(D_METHOD("region_get_enter_cost", "region"), &NavigationServer2D::region_get_enter_cost);
ClassDB::bind_method(D_METHOD("region_set_travel_cost", "region", "travel_cost"), &NavigationServer2D::region_set_travel_cost);
@@ -508,6 +512,9 @@ void NavigationServer2D::map_force_update(RID p_map) {
void FORWARD_2(map_set_cell_size, RID, p_map, real_t, p_cell_size, rid_to_rid, real_to_real);
real_t FORWARD_1_C(map_get_cell_size, RID, p_map, rid_to_rid);
+void FORWARD_2(map_set_use_edge_connections, RID, p_map, bool, p_enabled, rid_to_rid, bool_to_bool);
+bool FORWARD_1_C(map_get_use_edge_connections, RID, p_map, rid_to_rid);
+
void FORWARD_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin, rid_to_rid, real_to_real);
real_t FORWARD_1_C(map_get_edge_connection_margin, RID, p_map, rid_to_rid);
@@ -521,6 +528,9 @@ RID FORWARD_2_C(map_get_closest_point_owner, RID, p_map, const Vector2 &, p_poin
RID FORWARD_0(region_create);
+void FORWARD_2(region_set_use_edge_connections, RID, p_region, bool, p_enabled, rid_to_rid, bool_to_bool);
+bool FORWARD_1_C(region_get_use_edge_connections, RID, p_region, rid_to_rid);
+
void FORWARD_2(region_set_enter_cost, RID, p_region, real_t, p_enter_cost, rid_to_rid, real_to_real);
real_t FORWARD_1_C(region_get_enter_cost, RID, p_region, rid_to_rid);
void FORWARD_2(region_set_travel_cost, RID, p_region, real_t, p_travel_cost, rid_to_rid, real_to_real);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index d6e84d73b6..88246019b9 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -70,6 +70,9 @@ public:
/// Returns the map cell size.
virtual real_t map_get_cell_size(RID p_map) const;
+ virtual void map_set_use_edge_connections(RID p_map, bool p_enabled);
+ virtual bool map_get_use_edge_connections(RID p_map) const;
+
/// Set the map edge connection margin used to weld the compatible region edges.
virtual void map_set_edge_connection_margin(RID p_map, real_t p_connection_margin);
@@ -98,6 +101,9 @@ public:
/// Creates a new region.
virtual RID region_create();
+ virtual void region_set_use_edge_connections(RID p_region, bool p_enabled);
+ virtual bool region_get_use_edge_connections(RID p_region) const;
+
/// Set the enter_cost of a region
virtual void region_set_enter_cost(RID p_region, real_t p_enter_cost);
virtual real_t region_get_enter_cost(RID p_region) const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index e2da97b18a..7888a28b7b 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -43,6 +43,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_up", "map"), &NavigationServer3D::map_get_up);
ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer3D::map_set_cell_size);
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size);
+ ClassDB::bind_method(D_METHOD("map_set_use_edge_connections", "map", "enabled"), &NavigationServer3D::map_set_use_edge_connections);
+ ClassDB::bind_method(D_METHOD("map_get_use_edge_connections", "map"), &NavigationServer3D::map_get_use_edge_connections);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_set_link_connection_radius", "map", "radius"), &NavigationServer3D::map_set_link_connection_radius);
@@ -63,6 +65,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("query_path", "parameters", "result"), &NavigationServer3D::query_path);
ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create);
+ ClassDB::bind_method(D_METHOD("region_set_use_edge_connections", "region", "enabled"), &NavigationServer3D::region_set_use_edge_connections);
+ ClassDB::bind_method(D_METHOD("region_get_use_edge_connections", "region"), &NavigationServer3D::region_get_use_edge_connections);
ClassDB::bind_method(D_METHOD("region_set_enter_cost", "region", "enter_cost"), &NavigationServer3D::region_set_enter_cost);
ClassDB::bind_method(D_METHOD("region_get_enter_cost", "region"), &NavigationServer3D::region_get_enter_cost);
ClassDB::bind_method(D_METHOD("region_set_travel_cost", "region", "travel_cost"), &NavigationServer3D::region_set_travel_cost);
@@ -165,10 +169,12 @@ NavigationServer3D::NavigationServer3D() {
singleton = this;
GLOBAL_DEF_BASIC("navigation/2d/default_cell_size", 1);
+ GLOBAL_DEF("navigation/2d/use_edge_connections", true);
GLOBAL_DEF_BASIC("navigation/2d/default_edge_connection_margin", 1);
GLOBAL_DEF_BASIC("navigation/2d/default_link_connection_radius", 4);
GLOBAL_DEF_BASIC("navigation/3d/default_cell_size", 0.25);
+ GLOBAL_DEF("navigation/3d/use_edge_connections", true);
GLOBAL_DEF_BASIC("navigation/3d/default_edge_connection_margin", 0.25);
GLOBAL_DEF_BASIC("navigation/3d/default_link_connection_radius", 1.0);
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index eb8fc59041..73698581e9 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -80,6 +80,9 @@ public:
/// Returns the map cell size.
virtual real_t map_get_cell_size(RID p_map) const = 0;
+ virtual void map_set_use_edge_connections(RID p_map, bool p_enabled) = 0;
+ virtual bool map_get_use_edge_connections(RID p_map) const = 0;
+
/// Set the map edge connection margin used to weld the compatible region edges.
virtual void map_set_edge_connection_margin(RID p_map, real_t p_connection_margin) = 0;
@@ -110,6 +113,9 @@ public:
/// Creates a new region.
virtual RID region_create() = 0;
+ virtual void region_set_use_edge_connections(RID p_region, bool p_enabled) = 0;
+ virtual bool region_get_use_edge_connections(RID p_region) const = 0;
+
/// Set the enter_cost of a region
virtual void region_set_enter_cost(RID p_region, real_t p_enter_cost) = 0;
virtual real_t region_get_enter_cost(RID p_region) const = 0;
diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h
index c6c0eb4b34..98dc38990e 100644
--- a/servers/navigation_server_3d_dummy.h
+++ b/servers/navigation_server_3d_dummy.h
@@ -45,6 +45,8 @@ public:
Vector3 map_get_up(RID p_map) const override { return Vector3(); }
void map_set_cell_size(RID p_map, real_t p_cell_size) override {}
real_t map_get_cell_size(RID p_map) const override { return 0; }
+ void map_set_use_edge_connections(RID p_map, bool p_enabled) override {}
+ bool map_get_use_edge_connections(RID p_map) const override { return false; }
void map_set_edge_connection_margin(RID p_map, real_t p_connection_margin) override {}
real_t map_get_edge_connection_margin(RID p_map) const override { return 0; }
void map_set_link_connection_radius(RID p_map, real_t p_connection_radius) override {}
@@ -60,6 +62,8 @@ public:
TypedArray<RID> map_get_obstacles(RID p_map) const override { return TypedArray<RID>(); }
void map_force_update(RID p_map) override {}
RID region_create() override { return RID(); }
+ void region_set_use_edge_connections(RID p_region, bool p_enabled) override {}
+ bool region_get_use_edge_connections(RID p_region) const override { return false; }
void region_set_enter_cost(RID p_region, real_t p_enter_cost) override {}
real_t region_get_enter_cost(RID p_region) const override { return 0; }
void region_set_travel_cost(RID p_region, real_t p_travel_cost) override {}
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index af4ccdf6e3..4ea06afe79 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -436,7 +436,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
String code;
switch (p_node->type) {
- case SL::Node::TYPE_SHADER: {
+ case SL::Node::NODE_TYPE_SHADER: {
SL::ShaderNode *pnode = (SL::ShaderNode *)p_node;
for (int i = 0; i < pnode->render_modes.size(); i++) {
@@ -781,11 +781,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
//code+=dump_node_code(pnode->body,p_level);
} break;
- case SL::Node::TYPE_STRUCT: {
+ case SL::Node::NODE_TYPE_STRUCT: {
} break;
- case SL::Node::TYPE_FUNCTION: {
+ case SL::Node::NODE_TYPE_FUNCTION: {
} break;
- case SL::Node::TYPE_BLOCK: {
+ case SL::Node::NODE_TYPE_BLOCK: {
SL::BlockNode *bnode = (SL::BlockNode *)p_node;
//variables
@@ -796,7 +796,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
for (int i = 0; i < bnode->statements.size(); i++) {
String scode = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement) {
+ if (bnode->statements[i]->type == SL::Node::NODE_TYPE_CONTROL_FLOW || bnode->single_statement) {
code += scode; //use directly
if (bnode->use_comma_between_statements && i + 1 < bnode->statements.size()) {
code += ",";
@@ -810,7 +810,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
} break;
- case SL::Node::TYPE_VARIABLE_DECLARATION: {
+ case SL::Node::NODE_TYPE_VARIABLE_DECLARATION: {
SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node;
String declaration;
@@ -868,7 +868,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
code += declaration;
} break;
- case SL::Node::TYPE_VARIABLE: {
+ case SL::Node::NODE_TYPE_VARIABLE: {
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
bool use_fragment_varying = false;
@@ -961,7 +961,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
} break;
- case SL::Node::TYPE_ARRAY_CONSTRUCT: {
+ case SL::Node::NODE_TYPE_ARRAY_CONSTRUCT: {
SL::ArrayConstructNode *acnode = (SL::ArrayConstructNode *)p_node;
int sz = acnode->initializer.size();
if (acnode->datatype == SL::TYPE_STRUCT) {
@@ -981,7 +981,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
code += ")";
} break;
- case SL::Node::TYPE_ARRAY: {
+ case SL::Node::NODE_TYPE_ARRAY: {
SL::ArrayNode *anode = (SL::ArrayNode *)p_node;
bool use_fragment_varying = false;
@@ -1072,7 +1072,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
} break;
- case SL::Node::TYPE_CONSTANT: {
+ case SL::Node::NODE_TYPE_CONSTANT: {
SL::ConstantNode *cnode = (SL::ConstantNode *)p_node;
if (cnode->array_size == 0) {
@@ -1099,7 +1099,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
} break;
- case SL::Node::TYPE_OPERATOR: {
+ case SL::Node::NODE_TYPE_OPERATOR: {
SL::OperatorNode *onode = (SL::OperatorNode *)p_node;
switch (onode->op) {
@@ -1130,7 +1130,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
case SL::OP_CALL:
case SL::OP_STRUCT:
case SL::OP_CONSTRUCT: {
- ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::TYPE_VARIABLE, String());
+ ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::NODE_TYPE_VARIABLE, String());
const SL::VariableNode *vnode = static_cast<const SL::VariableNode *>(onode->arguments[0]);
const SL::FunctionNode *func = nullptr;
const bool is_internal_func = internal_functions.has(vnode->name);
@@ -1200,12 +1200,12 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
bool done = false;
do {
switch (node->type) {
- case SL::Node::TYPE_VARIABLE: {
+ case SL::Node::NODE_TYPE_VARIABLE: {
name = static_cast<const SL::VariableNode *>(node)->name;
done = true;
found = true;
} break;
- case SL::Node::TYPE_MEMBER: {
+ case SL::Node::NODE_TYPE_MEMBER: {
node = static_cast<const SL::MemberNode *>(node)->owner;
} break;
default: {
@@ -1227,12 +1227,12 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
bool correct_texture_uniform = false;
switch (onode->arguments[i]->type) {
- case SL::Node::TYPE_VARIABLE: {
+ case SL::Node::NODE_TYPE_VARIABLE: {
const SL::VariableNode *varnode = static_cast<const SL::VariableNode *>(onode->arguments[i]);
texture_uniform = varnode->name;
correct_texture_uniform = true;
} break;
- case SL::Node::TYPE_ARRAY: {
+ case SL::Node::NODE_TYPE_ARRAY: {
const SL::ArrayNode *anode = static_cast<const SL::ArrayNode *>(onode->arguments[i]);
texture_uniform = anode->name;
correct_texture_uniform = true;
@@ -1361,7 +1361,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
} break;
- case SL::Node::TYPE_CONTROL_FLOW: {
+ case SL::Node::NODE_TYPE_CONTROL_FLOW: {
SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node;
if (cfnode->flow_op == SL::FLOW_OP_IF) {
code += _mktab(p_level) + "if (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n";
@@ -1413,7 +1413,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
} break;
- case SL::Node::TYPE_MEMBER: {
+ case SL::Node::NODE_TYPE_MEMBER: {
SL::MemberNode *mnode = (SL::MemberNode *)p_node;
code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name;
if (mnode->index_expression != nullptr) {
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 12e99ba606..3df22903c3 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -3063,7 +3063,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
Vector<StringName> args2;
Vector<int> args3;
- ERR_FAIL_COND_V(p_func->arguments[0]->type != Node::TYPE_VARIABLE, false);
+ ERR_FAIL_COND_V(p_func->arguments[0]->type != Node::NODE_TYPE_VARIABLE, false);
StringName name = static_cast<VariableNode *>(p_func->arguments[0])->name.operator String();
@@ -3117,14 +3117,14 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
failed_builtin = true;
bool fail = false;
for (int i = 0; i < argcount; i++) {
- if (p_func->arguments[i + 1]->type == Node::TYPE_ARRAY) {
+ if (p_func->arguments[i + 1]->type == Node::NODE_TYPE_ARRAY) {
const ArrayNode *anode = static_cast<const ArrayNode *>(p_func->arguments[i + 1]);
if (anode->call_expression == nullptr && !anode->is_indexed()) {
fail = true;
break;
}
}
- if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) {
+ if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::NODE_TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) {
//all good, but needs implicit conversion later
} else if (args[i] != builtin_func_defs[idx].args[i]) {
fail = true;
@@ -3160,7 +3160,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
int max = builtin_func_const_args[constarg_idx].max;
bool error = false;
- if (p_func->arguments[arg]->type == Node::TYPE_VARIABLE) {
+ if (p_func->arguments[arg]->type == Node::NODE_TYPE_VARIABLE) {
const VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg]);
bool is_const = false;
@@ -3172,7 +3172,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
error = true;
}
} else {
- if (p_func->arguments[arg]->type == Node::TYPE_CONSTANT) {
+ if (p_func->arguments[arg]->type == Node::NODE_TYPE_CONSTANT) {
const ConstantNode *cn = static_cast<ConstantNode *>(p_func->arguments[arg]);
if (cn->get_datatype() == TYPE_INT && cn->values.size() == 1) {
@@ -3207,17 +3207,17 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
break;
}
if (arg_idx < argcount) {
- if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) {
+ if (p_func->arguments[arg_idx + 1]->type != Node::NODE_TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::NODE_TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::NODE_TYPE_ARRAY) {
_set_error(vformat(RTR("Argument %d of function '%s' is not a variable, array, or member."), arg_idx + 1, String(name)));
return false;
}
- if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
+ if (p_func->arguments[arg_idx + 1]->type == Node::NODE_TYPE_ARRAY) {
ArrayNode *mn = static_cast<ArrayNode *>(p_func->arguments[arg_idx + 1]);
if (mn->is_const) {
fail = true;
}
- } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
+ } else if (p_func->arguments[arg_idx + 1]->type == Node::NODE_TYPE_MEMBER) {
MemberNode *mn = static_cast<MemberNode *>(p_func->arguments[arg_idx + 1]);
if (mn->basetype_const) {
fail = true;
@@ -3250,18 +3250,18 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
StringName var_name;
- if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
+ if (p_func->arguments[arg_idx + 1]->type == Node::NODE_TYPE_ARRAY) {
var_name = static_cast<const ArrayNode *>(p_func->arguments[arg_idx + 1])->name;
- } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
+ } else if (p_func->arguments[arg_idx + 1]->type == Node::NODE_TYPE_MEMBER) {
Node *n = static_cast<const MemberNode *>(p_func->arguments[arg_idx + 1])->owner;
- while (n->type == Node::TYPE_MEMBER) {
+ while (n->type == Node::NODE_TYPE_MEMBER) {
n = static_cast<const MemberNode *>(n)->owner;
}
- if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) {
+ if (n->type != Node::NODE_TYPE_VARIABLE && n->type != Node::NODE_TYPE_ARRAY) {
_set_error(vformat(RTR("Argument %d of function '%s' is not a variable, array, or member."), arg_idx + 1, String(name)));
return false;
}
- if (n->type == Node::TYPE_VARIABLE) {
+ if (n->type == Node::NODE_TYPE_VARIABLE) {
var_name = static_cast<const VariableNode *>(n)->name;
} else { // TYPE_ARRAY
var_name = static_cast<const ArrayNode *>(n)->name;
@@ -3298,7 +3298,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
//implicitly convert values if possible
for (int i = 0; i < argcount; i++) {
- if (get_scalar_type(args[i]) != args[i] || args[i] == builtin_func_defs[idx].args[i] || p_func->arguments[i + 1]->type != Node::TYPE_CONSTANT) {
+ if (get_scalar_type(args[i]) != args[i] || args[i] == builtin_func_defs[idx].args[i] || p_func->arguments[i + 1]->type != Node::NODE_TYPE_CONSTANT) {
//can't do implicit conversion here
continue;
}
@@ -3422,7 +3422,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
bool fail = false;
for (int j = 0; j < args.size(); j++) {
- if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && args3[j] == 0 && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) {
+ if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::NODE_TYPE_CONSTANT && args3[j] == 0 && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) {
//all good, but it needs implicit conversion later
} else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str) || args3[j] != pfunc->arguments[j].array_size) {
String func_arg_name;
@@ -3457,7 +3457,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
if (!fail) {
//implicitly convert values if possible
for (int k = 0; k < args.size(); k++) {
- if (get_scalar_type(args[k]) != args[k] || args[k] == pfunc->arguments[k].type || p_func->arguments[k + 1]->type != Node::TYPE_CONSTANT) {
+ if (get_scalar_type(args[k]) != args[k] || args[k] == pfunc->arguments[k].type || p_func->arguments[k + 1]->type != Node::NODE_TYPE_CONSTANT) {
//can't do implicit conversion here
continue;
}
@@ -3565,7 +3565,7 @@ bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Functio
return false;
}
- if (is_const_decl && arg->type == Node::TYPE_VARIABLE) {
+ if (is_const_decl && arg->type == Node::NODE_TYPE_VARIABLE) {
const VariableNode *var = static_cast<const VariableNode *>(arg);
if (!var->is_const) {
_set_error(RTR("Expected constant expression."));
@@ -4531,7 +4531,7 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
switch (p_node->type) {
- case Node::TYPE_OPERATOR: {
+ case Node::NODE_TYPE_OPERATOR: {
const OperatorNode *op_node = static_cast<const OperatorNode *>(p_node);
for (int i = int(op_node->op == OP_CALL); i < op_node->arguments.size(); i++) {
if (!_check_node_constness(op_node->arguments[i])) {
@@ -4539,15 +4539,15 @@ bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
}
}
} break;
- case Node::TYPE_CONSTANT:
+ case Node::NODE_TYPE_CONSTANT:
break;
- case Node::TYPE_VARIABLE: {
+ case Node::NODE_TYPE_VARIABLE: {
const VariableNode *var_node = static_cast<const VariableNode *>(p_node);
if (!var_node->is_const) {
return false;
}
} break;
- case Node::TYPE_ARRAY: {
+ case Node::NODE_TYPE_ARRAY: {
const ArrayNode *arr_node = static_cast<const ArrayNode *>(p_node);
if (!arr_node->is_const) {
return false;
@@ -4560,7 +4560,7 @@ bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
}
bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message) {
- if (p_node->type == Node::TYPE_OPERATOR) {
+ if (p_node->type == Node::NODE_TYPE_OPERATOR) {
OperatorNode *op = static_cast<OperatorNode *>(p_node);
if (op->op == OP_INDEX) {
@@ -4577,7 +4577,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
return false;
}
- } else if (p_node->type == Node::TYPE_MEMBER) {
+ } else if (p_node->type == Node::NODE_TYPE_MEMBER) {
MemberNode *member = static_cast<MemberNode *>(p_node);
if (member->has_swizzling_duplicates) {
@@ -4589,7 +4589,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
return _validate_assign(member->owner, p_function_info, r_message);
- } else if (p_node->type == Node::TYPE_VARIABLE) {
+ } else if (p_node->type == Node::NODE_TYPE_VARIABLE) {
VariableNode *var = static_cast<VariableNode *>(p_node);
if (shader->uniforms.has(var->name)) {
@@ -4609,7 +4609,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
if (!(p_function_info.built_ins.has(var->name) && p_function_info.built_ins[var->name].constant)) {
return true;
}
- } else if (p_node->type == Node::TYPE_ARRAY) {
+ } else if (p_node->type == Node::NODE_TYPE_ARRAY) {
ArrayNode *arr = static_cast<ArrayNode *>(p_node);
if (shader->constants.has(arr->name) || arr->is_const) {
@@ -4727,7 +4727,7 @@ Error ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo &
_set_tkpos(pos);
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
if (n) {
- if (n->type == Node::TYPE_VARIABLE) {
+ if (n->type == Node::NODE_TYPE_VARIABLE) {
VariableNode *vn = static_cast<VariableNode *>(n);
if (vn) {
ConstantNode::Value v;
@@ -4750,7 +4750,7 @@ Error ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo &
}
}
}
- } else if (n->type == Node::TYPE_OPERATOR) {
+ } else if (n->type == Node::NODE_TYPE_OPERATOR) {
_set_error(vformat(RTR("Array size expressions are not supported.")));
return ERR_PARSE_ERROR;
}
@@ -5296,10 +5296,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ArgumentQualifier arg_qual = call_function->arguments[i].qualifier;
bool is_out_arg = arg_qual != ArgumentQualifier::ARGUMENT_QUALIFIER_IN;
- if (n->type == Node::TYPE_VARIABLE || n->type == Node::TYPE_ARRAY) {
+ if (n->type == Node::NODE_TYPE_VARIABLE || n->type == Node::NODE_TYPE_ARRAY) {
StringName varname;
- if (n->type == Node::TYPE_VARIABLE) {
+ if (n->type == Node::NODE_TYPE_VARIABLE) {
VariableNode *vn = static_cast<VariableNode *>(n);
varname = vn->name;
} else { // TYPE_ARRAY
@@ -5347,23 +5347,23 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (is_const_arg || is_out_arg) {
StringName varname;
- if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR || n->type == Node::TYPE_ARRAY_CONSTRUCT) {
+ if (n->type == Node::NODE_TYPE_CONSTANT || n->type == Node::NODE_TYPE_OPERATOR || n->type == Node::NODE_TYPE_ARRAY_CONSTRUCT) {
if (!is_const_arg) {
error = true;
}
- } else if (n->type == Node::TYPE_ARRAY) {
+ } else if (n->type == Node::NODE_TYPE_ARRAY) {
ArrayNode *an = static_cast<ArrayNode *>(n);
if (!is_const_arg && (an->call_expression != nullptr || an->is_const)) {
error = true;
}
varname = an->name;
- } else if (n->type == Node::TYPE_VARIABLE) {
+ } else if (n->type == Node::NODE_TYPE_VARIABLE) {
VariableNode *vn = static_cast<VariableNode *>(n);
if (vn->is_const && !is_const_arg) {
error = true;
}
varname = vn->name;
- } else if (n->type == Node::TYPE_MEMBER) {
+ } else if (n->type == Node::NODE_TYPE_MEMBER) {
MemberNode *mn = static_cast<MemberNode *>(n);
if (mn->basetype_const && is_out_arg) {
error = true;
@@ -5389,7 +5389,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (is_sampler_type(call_function->arguments[i].type)) {
//let's see where our argument comes from
- ERR_CONTINUE(n->type != Node::TYPE_VARIABLE); //bug? this should always be a variable
+ ERR_CONTINUE(n->type != Node::NODE_TYPE_VARIABLE); //bug? this should always be a variable
VariableNode *vn = static_cast<VariableNode *>(n);
StringName varname = vn->name;
if (shader->uniforms.has(varname)) {
@@ -5599,7 +5599,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
- if (index_expression->type == Node::TYPE_CONSTANT) {
+ if (index_expression->type == Node::NODE_TYPE_CONSTANT) {
ConstantNode *cnode = static_cast<ConstantNode *>(index_expression);
if (cnode) {
if (!cnode->values.is_empty()) {
@@ -6064,7 +6064,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
- if (index_expression->type == Node::TYPE_CONSTANT) {
+ if (index_expression->type == Node::NODE_TYPE_CONSTANT) {
ConstantNode *cnode = static_cast<ConstantNode *>(index_expression);
if (cnode) {
if (!cnode->values.is_empty()) {
@@ -6118,7 +6118,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
String member_struct_name;
if (expr->get_array_size() > 0) {
- if (index->type == Node::TYPE_CONSTANT) {
+ if (index->type == Node::NODE_TYPE_CONSTANT) {
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= (uint32_t)expr->get_array_size()) {
_set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, expr->get_array_size() - 1));
@@ -6136,7 +6136,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC2:
case TYPE_UVEC2:
case TYPE_MAT2:
- if (index->type == Node::TYPE_CONSTANT) {
+ if (index->type == Node::NODE_TYPE_CONSTANT) {
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= 2) {
_set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, 1));
@@ -6170,7 +6170,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC3:
case TYPE_UVEC3:
case TYPE_MAT3:
- if (index->type == Node::TYPE_CONSTANT) {
+ if (index->type == Node::NODE_TYPE_CONSTANT) {
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= 3) {
_set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, 2));
@@ -6203,7 +6203,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC4:
case TYPE_UVEC4:
case TYPE_MAT4:
- if (index->type == Node::TYPE_CONSTANT) {
+ if (index->type == Node::NODE_TYPE_CONSTANT) {
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= 4) {
_set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, 3));
@@ -6702,7 +6702,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node) {
- if (p_node->type != Node::TYPE_OPERATOR) {
+ if (p_node->type != Node::NODE_TYPE_OPERATOR) {
return p_node;
}
@@ -6710,7 +6710,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
OperatorNode *op = static_cast<OperatorNode *>(p_node);
if (op->op == OP_CONSTRUCT) {
- ERR_FAIL_COND_V(op->arguments[0]->type != Node::TYPE_VARIABLE, p_node);
+ ERR_FAIL_COND_V(op->arguments[0]->type != Node::NODE_TYPE_VARIABLE, p_node);
DataType type = op->get_datatype();
DataType base = get_scalar_type(type);
@@ -6720,7 +6720,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
for (int i = 1; i < op->arguments.size(); i++) {
op->arguments.write[i] = _reduce_expression(p_block, op->arguments[i]);
- if (op->arguments[i]->type == Node::TYPE_CONSTANT) {
+ if (op->arguments[i]->type == Node::NODE_TYPE_CONSTANT) {
ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[i]);
if (get_scalar_type(cn->datatype) == base) {
@@ -6772,7 +6772,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
return cn;
} else if (op->op == OP_NEGATE) {
op->arguments.write[0] = _reduce_expression(p_block, op->arguments[0]);
- if (op->arguments[0]->type == Node::TYPE_CONSTANT) {
+ if (op->arguments[0]->type == Node::NODE_TYPE_CONSTANT) {
ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[0]);
DataType base = get_scalar_type(cn->datatype);
@@ -7179,7 +7179,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- if (is_const && n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
+ if (is_const && n->type == Node::NODE_TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
_set_error(RTR("Expected a constant expression."));
return ERR_PARSE_ERROR;
}
@@ -7235,7 +7235,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!n) {
return ERR_PARSE_ERROR;
}
- if (is_const && n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
+ if (is_const && n->type == Node::NODE_TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
OperatorNode *op = static_cast<OperatorNode *>(n);
for (int i = 1; i < op->arguments.size(); i++) {
if (!_check_node_constness(op->arguments[i])) {
@@ -7245,7 +7245,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
}
- if (n->type == Node::TYPE_CONSTANT) {
+ if (n->type == Node::NODE_TYPE_CONSTANT) {
ConstantNode *const_node = static_cast<ConstantNode *>(n);
if (const_node && const_node->values.size() == 1) {
var.value = const_node->values[0];
@@ -7412,7 +7412,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ControlFlowNode *flow = static_cast<ControlFlowNode *>(switch_block->statements[i]);
if (flow) {
if (flow->flow_op == FLOW_OP_CASE) {
- if (flow->expressions[0]->type == Node::TYPE_CONSTANT) {
+ if (flow->expressions[0]->type == Node::NODE_TYPE_CONSTANT) {
ConstantNode *cn = static_cast<ConstantNode *>(flow->expressions[0]);
if (!cn || cn->values.is_empty()) {
return ERR_PARSE_ERROR;
@@ -7422,7 +7422,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
constants.insert(cn->values[0].sint);
- } else if (flow->expressions[0]->type == Node::TYPE_VARIABLE) {
+ } else if (flow->expressions[0]->type == Node::NODE_TYPE_VARIABLE) {
VariableNode *vn = static_cast<VariableNode *>(flow->expressions[0]);
if (!vn) {
return ERR_PARSE_ERROR;
@@ -7852,9 +7852,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!expr) {
return ERR_PARSE_ERROR;
}
- is_condition = expr->type == Node::TYPE_OPERATOR && expr->get_datatype() == TYPE_BOOL;
+ is_condition = expr->type == Node::NODE_TYPE_OPERATOR && expr->get_datatype() == TYPE_BOOL;
- if (expr->type == Node::TYPE_OPERATOR) {
+ if (expr->type == Node::NODE_TYPE_OPERATOR) {
OperatorNode *op = static_cast<OperatorNode *>(expr);
if (op->op == OP_EMPTY) {
is_var_init = true;
@@ -8916,7 +8916,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
if (!expr) {
return ERR_PARSE_ERROR;
}
- if (expr->type != Node::TYPE_CONSTANT) {
+ if (expr->type != Node::NODE_TYPE_CONSTANT) {
_set_error(RTR("Expected constant expression after '='."));
return ERR_PARSE_ERROR;
}
@@ -9276,7 +9276,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
}
- if (n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
+ if (n->type == Node::NODE_TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
_set_error(RTR("Expected constant expression."));
return ERR_PARSE_ERROR;
}
@@ -9343,7 +9343,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
keyword_completion_context = CF_GLOBAL_SPACE;
}
#endif // DEBUG_ENABLED
- if (expr->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(expr)->op == OP_CALL) {
+ if (expr->type == Node::NODE_TYPE_OPERATOR && static_cast<OperatorNode *>(expr)->op == OP_CALL) {
OperatorNode *op = static_cast<OperatorNode *>(expr);
for (int i = 1; i < op->arguments.size(); i++) {
if (!_check_node_constness(op->arguments[i])) {
@@ -9756,7 +9756,7 @@ Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOper
bool found = false;
for (int i = p_flow->blocks.size() - 1; i >= 0; i--) {
- if (p_flow->blocks[i]->type == Node::TYPE_BLOCK) {
+ if (p_flow->blocks[i]->type == Node::NODE_TYPE_BLOCK) {
BlockNode *last_block = static_cast<BlockNode *>(p_flow->blocks[i]);
if (_find_last_flow_op_in_block(last_block, p_op) == OK) {
found = true;
@@ -9774,7 +9774,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat
bool found = false;
for (int i = p_block->statements.size() - 1; i >= 0; i--) {
- if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) {
+ if (p_block->statements[i]->type == Node::NODE_TYPE_CONTROL_FLOW) {
ControlFlowNode *flow = static_cast<ControlFlowNode *>(p_block->statements[i]);
if (flow->flow_op == p_op) {
found = true;
@@ -9785,7 +9785,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat
break;
}
}
- } else if (p_block->statements[i]->type == Node::TYPE_BLOCK) {
+ } else if (p_block->statements[i]->type == Node::NODE_TYPE_BLOCK) {
BlockNode *block = static_cast<BlockNode *>(p_block->statements[i]);
if (_find_last_flow_op_in_block(block, p_op) == OK) {
found = true;
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 220160e5fd..0ddd27f028 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -357,18 +357,18 @@ public:
Node *next = nullptr;
enum Type {
- TYPE_SHADER,
- TYPE_FUNCTION,
- TYPE_BLOCK,
- TYPE_VARIABLE,
- TYPE_VARIABLE_DECLARATION,
- TYPE_CONSTANT,
- TYPE_OPERATOR,
- TYPE_CONTROL_FLOW,
- TYPE_MEMBER,
- TYPE_ARRAY,
- TYPE_ARRAY_CONSTRUCT,
- TYPE_STRUCT,
+ NODE_TYPE_SHADER,
+ NODE_TYPE_FUNCTION,
+ NODE_TYPE_BLOCK,
+ NODE_TYPE_VARIABLE,
+ NODE_TYPE_VARIABLE_DECLARATION,
+ NODE_TYPE_CONSTANT,
+ NODE_TYPE_OPERATOR,
+ NODE_TYPE_CONTROL_FLOW,
+ NODE_TYPE_MEMBER,
+ NODE_TYPE_ARRAY,
+ NODE_TYPE_ARRAY_CONSTRUCT,
+ NODE_TYPE_STRUCT,
};
Type type;
@@ -407,7 +407,7 @@ public:
virtual bool is_indexed() const override { return op == OP_INDEX; }
OperatorNode() :
- Node(TYPE_OPERATOR) {}
+ Node(NODE_TYPE_OPERATOR) {}
};
struct VariableNode : public Node {
@@ -421,7 +421,7 @@ public:
virtual String get_datatype_name() const override { return String(struct_name); }
VariableNode() :
- Node(TYPE_VARIABLE) {}
+ Node(NODE_TYPE_VARIABLE) {}
};
struct VariableDeclarationNode : public Node {
@@ -442,7 +442,7 @@ public:
virtual DataType get_datatype() const override { return datatype; }
VariableDeclarationNode() :
- Node(TYPE_VARIABLE_DECLARATION) {}
+ Node(NODE_TYPE_VARIABLE_DECLARATION) {}
};
struct ArrayNode : public Node {
@@ -462,7 +462,7 @@ public:
virtual bool is_indexed() const override { return index_expression != nullptr; }
ArrayNode() :
- Node(TYPE_ARRAY) {}
+ Node(NODE_TYPE_ARRAY) {}
};
struct ArrayConstructNode : public Node {
@@ -475,7 +475,7 @@ public:
virtual int get_array_size() const override { return initializer.size(); }
ArrayConstructNode() :
- Node(TYPE_ARRAY_CONSTRUCT) {}
+ Node(NODE_TYPE_ARRAY_CONSTRUCT) {}
};
struct ConstantNode : public Node {
@@ -498,7 +498,7 @@ public:
virtual int get_array_size() const override { return array_size; }
ConstantNode() :
- Node(TYPE_CONSTANT) {}
+ Node(NODE_TYPE_CONSTANT) {}
};
struct FunctionNode;
@@ -536,7 +536,7 @@ public:
bool use_comma_between_statements = false;
BlockNode() :
- Node(TYPE_BLOCK) {}
+ Node(NODE_TYPE_BLOCK) {}
};
struct ControlFlowNode : public Node {
@@ -545,7 +545,7 @@ public:
Vector<BlockNode *> blocks;
ControlFlowNode() :
- Node(TYPE_CONTROL_FLOW) {}
+ Node(NODE_TYPE_CONTROL_FLOW) {}
};
struct MemberNode : public Node {
@@ -569,13 +569,13 @@ public:
virtual bool is_indexed() const override { return index_expression != nullptr || call_expression != nullptr; }
MemberNode() :
- Node(TYPE_MEMBER) {}
+ Node(NODE_TYPE_MEMBER) {}
};
struct StructNode : public Node {
List<MemberNode *> members;
StructNode() :
- Node(TYPE_STRUCT) {}
+ Node(NODE_TYPE_STRUCT) {}
};
struct FunctionNode : public Node {
@@ -611,7 +611,7 @@ public:
virtual int get_array_size() const override { return return_array_size; }
FunctionNode() :
- Node(TYPE_FUNCTION) {}
+ Node(NODE_TYPE_FUNCTION) {}
};
struct ShaderNode : public Node {
@@ -718,7 +718,7 @@ public:
Vector<Struct> vstructs;
ShaderNode() :
- Node(TYPE_SHADER) {}
+ Node(NODE_TYPE_SHADER) {}
};
struct UniformOrderComparator {
diff --git a/tests/core/math/test_color.h b/tests/core/math/test_color.h
index 398c2da175..bd2d4f40e5 100644
--- a/tests/core/math/test_color.h
+++ b/tests/core/math/test_color.h
@@ -63,14 +63,10 @@ TEST_CASE("[Color] Constructor methods") {
const Color green_rgba = Color(0, 1, 0, 0.25);
const Color green_hsva = Color(0, 0, 0).from_hsv(120 / 360.0, 1, 1, 0.25);
- const Color green_hsla = Color(0, 0, 0).from_hsl(120 / 360.0, 1, 0.5, 0.25);
CHECK_MESSAGE(
green_rgba.is_equal_approx(green_hsva),
"Creation with HSV notation should result in components approximately equal to the default constructor.");
- CHECK_MESSAGE(
- green_rgba.is_equal_approx(green_hsla),
- "Creation with HSL notation should result in components approximately equal to the default constructor.");
}
TEST_CASE("[Color] Operators") {
@@ -113,16 +109,6 @@ TEST_CASE("[Color] Reading methods") {
CHECK_MESSAGE(
dark_blue.get_v() == doctest::Approx(0.5f),
"The returned HSV value should match the expected value.");
-
- CHECK_MESSAGE(
- dark_blue.get_hsl_h() == doctest::Approx(240.0f / 360.0f),
- "The returned HSL hue should match the expected value.");
- CHECK_MESSAGE(
- dark_blue.get_hsl_s() == doctest::Approx(1.0f),
- "The returned HSL saturation should match the expected value.");
- CHECK_MESSAGE(
- dark_blue.get_hsl_l() == doctest::Approx(0.25f),
- "The returned HSL lightness should match the expected value.");
}
TEST_CASE("[Color] Conversion methods") {
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index e2808f3aac..6b6257e25d 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -135,6 +135,8 @@ int test_main(int argc, char *argv[]) {
OS::get_singleton()->set_cmdline("", args, List<String>());
DisplayServerMock::register_mock_driver();
+ WorkerThreadPool::get_singleton()->init();
+
// Run custom test tools.
if (test_commands) {
for (const KeyValue<String, TestFunc> &E : (*test_commands)) {
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 1d4883bb7a..7c6c738c56 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -20,7 +20,7 @@ Files extracted from upstream source:
## astcenc
- Upstream: https://github.com/ARM-software/astc-encoder
-- Version: 4.3.0 (ec83dda79fcefe07f69cdae7ed980d169bf2c4d4, 2023)
+- Version: 4.4.0 (5a5b5a1ef60dd47c27c28c66c118d22c40e3197e, 2023)
- License: Apache 2.0
Files extracted from upstream source:
@@ -82,7 +82,7 @@ in the `patches/` folder when syncing on newer upstream commits.
## doctest
- Upstream: https://github.com/onqtam/doctest
-- Version: 2.4.9 (b7c21ec5ceeadb4951b00396fc1e4642dd347e5f, 2022)
+- Version: 2.4.11 (ae7a13539fb71f270b87eb2e874fbac80bc8dda2, 2023)
- License: MIT
Files extracted from upstream source:
@@ -700,8 +700,8 @@ instead of `miniz.h` as an external dependency.
## thorvg
-- Upstream: https://github.com/Samsung/thorvg
-- Version: 0.8.4 (b0b7f207c6235691d694fc3f76e0b96e4858e606, 2023)
+- Upstream: https://github.com/thorvg/thorvg
+- Version: 0.9.0 (a744006aa1edb918bacf0a415d0a57ca058e25f4, 2023)
- License: MIT
Files extracted from upstream source:
diff --git a/thirdparty/astcenc/astcenc.h b/thirdparty/astcenc/astcenc.h
index 70ae783373..dbf4599841 100644
--- a/thirdparty/astcenc/astcenc.h
+++ b/thirdparty/astcenc/astcenc.h
@@ -43,6 +43,14 @@
* for faster processing. The caller is responsible for creating the worker threads, and
* synchronizing between images.
*
+ * Extended instruction set support
+ * ================================
+ *
+ * This library supports use of extended instruction sets, such as SSE4.1 and AVX2. These are
+ * enabled at compile time when building the library. There is no runtime checking in the core
+ * library that the instruction sets used are actually available. Checking compatibility is the
+ * responsibility of the calling code.
+ *
* Threading
* =========
*
@@ -191,8 +199,6 @@ enum astcenc_error {
ASTCENC_ERR_OUT_OF_MEM,
/** @brief The call failed due to the build using fast math. */
ASTCENC_ERR_BAD_CPU_FLOAT,
- /** @brief The call failed due to the build using an unsupported ISA. */
- ASTCENC_ERR_BAD_CPU_ISA,
/** @brief The call failed due to an out-of-spec parameter. */
ASTCENC_ERR_BAD_PARAM,
/** @brief The call failed due to an out-of-spec block size. */
@@ -472,7 +478,7 @@ struct astcenc_config
/**
* @brief The number of trial candidates per mode search (-candidatelimit).
*
- * Valid values are between 1 and TUNE_MAX_TRIAL_CANDIDATES (default 4).
+ * Valid values are between 1 and TUNE_MAX_TRIAL_CANDIDATES.
*/
unsigned int tune_candidate_limit;
@@ -520,21 +526,21 @@ struct astcenc_config
*
* This option is further scaled for normal maps, so it skips less often.
*/
- float tune_2_partition_early_out_limit_factor;
+ float tune_2partition_early_out_limit_factor;
/**
* @brief The threshold for skipping 4.1 trials (-3partitionlimitfactor).
*
* This option is further scaled for normal maps, so it skips less often.
*/
- float tune_3_partition_early_out_limit_factor;
+ float tune_3partition_early_out_limit_factor;
/**
* @brief The threshold for skipping two weight planes (-2planelimitcorrelation).
*
* This option is ineffective for normal maps.
*/
- float tune_2_plane_early_out_limit_correlation;
+ float tune_2plane_early_out_limit_correlation;
#if defined(ASTCENC_DIAGNOSTICS)
/**
diff --git a/thirdparty/astcenc/astcenc_averages_and_directions.cpp b/thirdparty/astcenc/astcenc_averages_and_directions.cpp
index d1f003844a..dcff0d224b 100644
--- a/thirdparty/astcenc/astcenc_averages_and_directions.cpp
+++ b/thirdparty/astcenc/astcenc_averages_and_directions.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
-// Copyright 2011-2022 Arm Limited
+// Copyright 2011-2023 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
@@ -725,8 +725,7 @@ void compute_error_squared_rgba(
const image_block& blk,
const processed_line4 uncor_plines[BLOCK_MAX_PARTITIONS],
const processed_line4 samec_plines[BLOCK_MAX_PARTITIONS],
- float uncor_lengths[BLOCK_MAX_PARTITIONS],
- float samec_lengths[BLOCK_MAX_PARTITIONS],
+ float line_lengths[BLOCK_MAX_PARTITIONS],
float& uncor_error,
float& samec_error
) {
@@ -740,12 +739,6 @@ void compute_error_squared_rgba(
{
const uint8_t *texel_indexes = pi.texels_of_partition[partition];
- float uncor_loparam = 1e10f;
- float uncor_hiparam = -1e10f;
-
- float samec_loparam = 1e10f;
- float samec_hiparam = -1e10f;
-
processed_line4 l_uncor = uncor_plines[partition];
processed_line4 l_samec = samec_plines[partition];
@@ -773,9 +766,6 @@ void compute_error_squared_rgba(
vfloat uncor_loparamv(1e10f);
vfloat uncor_hiparamv(-1e10f);
- vfloat samec_loparamv(1e10f);
- vfloat samec_hiparamv(-1e10f);
-
vfloat ew_r(blk.channel_weight.lane<0>());
vfloat ew_g(blk.channel_weight.lane<1>());
vfloat ew_b(blk.channel_weight.lane<2>());
@@ -825,9 +815,6 @@ void compute_error_squared_rgba(
+ (data_b * l_samec_bs2)
+ (data_a * l_samec_bs3);
- samec_loparamv = min(samec_param, samec_loparamv);
- samec_hiparamv = max(samec_param, samec_hiparamv);
-
vfloat samec_dist0 = samec_param * l_samec_bs0 - data_r;
vfloat samec_dist1 = samec_param * l_samec_bs1 - data_g;
vfloat samec_dist2 = samec_param * l_samec_bs2 - data_b;
@@ -843,18 +830,9 @@ void compute_error_squared_rgba(
lane_ids += vint(ASTCENC_SIMD_WIDTH);
}
- uncor_loparam = hmin_s(uncor_loparamv);
- uncor_hiparam = hmax_s(uncor_hiparamv);
-
- samec_loparam = hmin_s(samec_loparamv);
- samec_hiparam = hmax_s(samec_hiparamv);
-
- float uncor_linelen = uncor_hiparam - uncor_loparam;
- float samec_linelen = samec_hiparam - samec_loparam;
-
// Turn very small numbers and NaNs into a small number
- uncor_lengths[partition] = astc::max(uncor_linelen, 1e-7f);
- samec_lengths[partition] = astc::max(samec_linelen, 1e-7f);
+ float uncor_linelen = hmax_s(uncor_hiparamv) - hmin_s(uncor_loparamv);
+ line_lengths[partition] = astc::max(uncor_linelen, 1e-7f);
}
uncor_error = hadd_s(uncor_errorsumv);
@@ -882,19 +860,9 @@ void compute_error_squared_rgb(
unsigned int texel_count = pi.partition_texel_count[partition];
promise(texel_count > 0);
- float uncor_loparam = 1e10f;
- float uncor_hiparam = -1e10f;
-
- float samec_loparam = 1e10f;
- float samec_hiparam = -1e10f;
-
processed_line3 l_uncor = pl.uncor_pline;
processed_line3 l_samec = pl.samec_pline;
- // This implementation is an example vectorization of this function.
- // It works for - the codec is a 2-4% faster than not vectorizing - but
- // the benefit is limited by the use of gathers and register pressure
-
// Vectorize some useful scalar inputs
vfloat l_uncor_bs0(l_uncor.bs.lane<0>());
vfloat l_uncor_bs1(l_uncor.bs.lane<1>());
@@ -913,9 +881,6 @@ void compute_error_squared_rgb(
vfloat uncor_loparamv(1e10f);
vfloat uncor_hiparamv(-1e10f);
- vfloat samec_loparamv(1e10f);
- vfloat samec_hiparamv(-1e10f);
-
vfloat ew_r(blk.channel_weight.lane<0>());
vfloat ew_g(blk.channel_weight.lane<1>());
vfloat ew_b(blk.channel_weight.lane<2>());
@@ -958,9 +923,6 @@ void compute_error_squared_rgb(
+ (data_g * l_samec_bs1)
+ (data_b * l_samec_bs2);
- samec_loparamv = min(samec_param, samec_loparamv);
- samec_hiparamv = max(samec_param, samec_hiparamv);
-
vfloat samec_dist0 = samec_param * l_samec_bs0 - data_r;
vfloat samec_dist1 = samec_param * l_samec_bs1 - data_g;
vfloat samec_dist2 = samec_param * l_samec_bs2 - data_b;
@@ -974,18 +936,9 @@ void compute_error_squared_rgb(
lane_ids += vint(ASTCENC_SIMD_WIDTH);
}
- uncor_loparam = hmin_s(uncor_loparamv);
- uncor_hiparam = hmax_s(uncor_hiparamv);
-
- samec_loparam = hmin_s(samec_loparamv);
- samec_hiparam = hmax_s(samec_hiparamv);
-
- float uncor_linelen = uncor_hiparam - uncor_loparam;
- float samec_linelen = samec_hiparam - samec_loparam;
-
// Turn very small numbers and NaNs into a small number
- pl.uncor_line_len = astc::max(uncor_linelen, 1e-7f);
- pl.samec_line_len = astc::max(samec_linelen, 1e-7f);
+ float uncor_linelen = hmax_s(uncor_hiparamv) - hmin_s(uncor_loparamv);
+ pl.line_length = astc::max(uncor_linelen, 1e-7f);
}
uncor_error = hadd_s(uncor_errorsumv);
diff --git a/thirdparty/astcenc/astcenc_block_sizes.cpp b/thirdparty/astcenc/astcenc_block_sizes.cpp
index 1c22d06a5c..17e51dfc3f 100644
--- a/thirdparty/astcenc/astcenc_block_sizes.cpp
+++ b/thirdparty/astcenc/astcenc_block_sizes.cpp
@@ -776,8 +776,8 @@ static void construct_dt_entry_2d(
assert(maxprec_1plane >= 0 || maxprec_2planes >= 0);
bsd.decimation_modes[index].maxprec_1plane = static_cast<int8_t>(maxprec_1plane);
bsd.decimation_modes[index].maxprec_2planes = static_cast<int8_t>(maxprec_2planes);
- bsd.decimation_modes[index].refprec_1_plane = 0;
- bsd.decimation_modes[index].refprec_2_planes = 0;
+ bsd.decimation_modes[index].refprec_1plane = 0;
+ bsd.decimation_modes[index].refprec_2planes = 0;
}
/**
@@ -934,11 +934,11 @@ static void construct_block_size_descriptor_2d(
if (is_dual_plane)
{
- dm.set_ref_2_plane(bm.get_weight_quant_mode());
+ dm.set_ref_2plane(bm.get_weight_quant_mode());
}
else
{
- dm.set_ref_1_plane(bm.get_weight_quant_mode());
+ dm.set_ref_1plane(bm.get_weight_quant_mode());
}
bsd.block_mode_packed_index[i] = static_cast<uint16_t>(packed_bm_idx);
@@ -969,8 +969,8 @@ static void construct_block_size_descriptor_2d(
{
bsd.decimation_modes[i].maxprec_1plane = -1;
bsd.decimation_modes[i].maxprec_2planes = -1;
- bsd.decimation_modes[i].refprec_1_plane = 0;
- bsd.decimation_modes[i].refprec_2_planes = 0;
+ bsd.decimation_modes[i].refprec_1plane = 0;
+ bsd.decimation_modes[i].refprec_2planes = 0;
}
// Determine the texels to use for kmeans clustering.
@@ -1055,8 +1055,8 @@ static void construct_block_size_descriptor_3d(
bsd.decimation_modes[decimation_mode_count].maxprec_1plane = static_cast<int8_t>(maxprec_1plane);
bsd.decimation_modes[decimation_mode_count].maxprec_2planes = static_cast<int8_t>(maxprec_2planes);
- bsd.decimation_modes[decimation_mode_count].refprec_1_plane = maxprec_1plane == -1 ? 0 : 0xFFFF;
- bsd.decimation_modes[decimation_mode_count].refprec_2_planes = maxprec_2planes == -1 ? 0 : 0xFFFF;
+ bsd.decimation_modes[decimation_mode_count].refprec_1plane = maxprec_1plane == -1 ? 0 : 0xFFFF;
+ bsd.decimation_modes[decimation_mode_count].refprec_2planes = maxprec_2planes == -1 ? 0 : 0xFFFF;
decimation_mode_count++;
}
}
@@ -1067,8 +1067,8 @@ static void construct_block_size_descriptor_3d(
{
bsd.decimation_modes[i].maxprec_1plane = -1;
bsd.decimation_modes[i].maxprec_2planes = -1;
- bsd.decimation_modes[i].refprec_1_plane = 0;
- bsd.decimation_modes[i].refprec_2_planes = 0;
+ bsd.decimation_modes[i].refprec_1plane = 0;
+ bsd.decimation_modes[i].refprec_2planes = 0;
}
bsd.decimation_mode_count_always = 0; // Skipped for 3D modes
diff --git a/thirdparty/astcenc/astcenc_color_quantize.cpp b/thirdparty/astcenc/astcenc_color_quantize.cpp
index edcfe4f853..b0fec7a74c 100644
--- a/thirdparty/astcenc/astcenc_color_quantize.cpp
+++ b/thirdparty/astcenc/astcenc_color_quantize.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
-// Copyright 2011-2021 Arm Limited
+// Copyright 2011-2023 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
@@ -44,17 +44,43 @@
* @brief Determine the quantized value given a quantization level.
*
* @param quant_level The quantization level to use.
- * @param value The value to convert. This may be outside of the 0-255 range and will be
- * clamped before the value is looked up.
+ * @param value The value to convert. This must be in the 0-255 range.
*
- * @return The encoded quantized value. These are not necessarily in order; the compressor
- * scrambles the values slightly to make hardware implementation easier.
+ * @return The unpacked quantized value, returned in 0-255 range.
*/
static inline uint8_t quant_color(
quant_method quant_level,
int value
) {
- return color_unquant_to_uquant_tables[quant_level - QUANT_6][value];
+ int index = value * 2 + 1;
+ return color_unquant_to_uquant_tables[quant_level - QUANT_6][index];
+}
+
+/**
+ * @brief Determine the quantized value given a quantization level and residual.
+ *
+ * @param quant_level The quantization level to use.
+ * @param value The value to convert. This must be in the 0-255 range.
+ * @param valuef The original value before rounding, used to compute a residual.
+ *
+ * @return The unpacked quantized value, returned in 0-255 range.
+ */
+static inline uint8_t quant_color(
+ quant_method quant_level,
+ int value,
+ float valuef
+) {
+ int index = value * 2;
+
+ // Compute the residual to determine if we should round down or up ties.
+ // Test should be residual >= 0, but empirical testing shows small bias helps.
+ float residual = valuef - static_cast<float>(value);
+ if (residual >= -0.1f)
+ {
+ index++;
+ }
+
+ return color_unquant_to_uquant_tables[quant_level - QUANT_6][index];
}
/**
@@ -86,16 +112,16 @@ static void quantize_rgb(
float b1 = astc::clamp255f(color1.lane<2>() * scale);
int ri0, gi0, bi0, ri1, gi1, bi1;
- float rgb0_addon = 0.5f;
- float rgb1_addon = 0.5f;
+ float rgb0_addon = 0.0f;
+ float rgb1_addon = 0.0f;
do
{
- ri0 = quant_color(quant_level, astc::max(astc::flt2int_rd(r0 + rgb0_addon), 0));
- gi0 = quant_color(quant_level, astc::max(astc::flt2int_rd(g0 + rgb0_addon), 0));
- bi0 = quant_color(quant_level, astc::max(astc::flt2int_rd(b0 + rgb0_addon), 0));
- ri1 = quant_color(quant_level, astc::min(astc::flt2int_rd(r1 + rgb1_addon), 255));
- gi1 = quant_color(quant_level, astc::min(astc::flt2int_rd(g1 + rgb1_addon), 255));
- bi1 = quant_color(quant_level, astc::min(astc::flt2int_rd(b1 + rgb1_addon), 255));
+ ri0 = quant_color(quant_level, astc::max(astc::flt2int_rtn(r0 + rgb0_addon), 0), r0 + rgb0_addon);
+ gi0 = quant_color(quant_level, astc::max(astc::flt2int_rtn(g0 + rgb0_addon), 0), g0 + rgb0_addon);
+ bi0 = quant_color(quant_level, astc::max(astc::flt2int_rtn(b0 + rgb0_addon), 0), b0 + rgb0_addon);
+ ri1 = quant_color(quant_level, astc::min(astc::flt2int_rtn(r1 + rgb1_addon), 255), r1 + rgb1_addon);
+ gi1 = quant_color(quant_level, astc::min(astc::flt2int_rtn(g1 + rgb1_addon), 255), g1 + rgb1_addon);
+ bi1 = quant_color(quant_level, astc::min(astc::flt2int_rtn(b1 + rgb1_addon), 255), b1 + rgb1_addon);
rgb0_addon -= 0.2f;
rgb1_addon += 0.2f;
@@ -133,8 +159,8 @@ static void quantize_rgba(
float a0 = astc::clamp255f(color0.lane<3>() * scale);
float a1 = astc::clamp255f(color1.lane<3>() * scale);
- output[6] = quant_color(quant_level, astc::flt2int_rtn(a0));
- output[7] = quant_color(quant_level, astc::flt2int_rtn(a1));
+ output[6] = quant_color(quant_level, astc::flt2int_rtn(a0), a0);
+ output[7] = quant_color(quant_level, astc::flt2int_rtn(a1), a1);
quantize_rgb(color0, color1, output, quant_level);
}
@@ -180,13 +206,13 @@ static bool try_quantize_rgb_blue_contract(
}
// Quantize the inverse-blue-contracted color
- int ri0 = quant_color(quant_level, astc::flt2int_rtn(r0));
- int gi0 = quant_color(quant_level, astc::flt2int_rtn(g0));
- int bi0 = quant_color(quant_level, astc::flt2int_rtn(b0));
+ int ri0 = quant_color(quant_level, astc::flt2int_rtn(r0), r0);
+ int gi0 = quant_color(quant_level, astc::flt2int_rtn(g0), g0);
+ int bi0 = quant_color(quant_level, astc::flt2int_rtn(b0), b0);
- int ri1 = quant_color(quant_level, astc::flt2int_rtn(r1));
- int gi1 = quant_color(quant_level, astc::flt2int_rtn(g1));
- int bi1 = quant_color(quant_level, astc::flt2int_rtn(b1));
+ int ri1 = quant_color(quant_level, astc::flt2int_rtn(r1), r1);
+ int gi1 = quant_color(quant_level, astc::flt2int_rtn(g1), g1);
+ int bi1 = quant_color(quant_level, astc::flt2int_rtn(b1), b1);
// If color #1 is not larger than color #0 then blue-contraction cannot be used. Note that
// blue-contraction and quantization change this order, which is why we must test afterwards.
@@ -217,7 +243,7 @@ static bool try_quantize_rgb_blue_contract(
*
* @return Returns @c false on failure, @c true on success.
*/
-static int try_quantize_rgba_blue_contract(
+static bool try_quantize_rgba_blue_contract(
vfloat4 color0,
vfloat4 color1,
uint8_t output[8],
@@ -228,8 +254,8 @@ static int try_quantize_rgba_blue_contract(
float a0 = astc::clamp255f(color0.lane<3>() * scale);
float a1 = astc::clamp255f(color1.lane<3>() * scale);
- output[6] = quant_color(quant_level, astc::flt2int_rtn(a1));
- output[7] = quant_color(quant_level, astc::flt2int_rtn(a0));
+ output[6] = quant_color(quant_level, astc::flt2int_rtn(a1), a1);
+ output[7] = quant_color(quant_level, astc::flt2int_rtn(a0), a0);
return try_quantize_rgb_blue_contract(color0, color1, output, quant_level);
}
@@ -433,7 +459,7 @@ static bool try_quantize_rgb_delta_blue_contract(
g1d |= (g0b & 0x100) >> 1;
b1d |= (b0b & 0x100) >> 1;
- // Then quantize and unquantize; if this causes any of the top two bits to flip,
+ // Then quantize and unquantize; if this causes any of the top two bits to flip,
// then encoding fails, since we have then corrupted either the top bit of the base
// or the sign bit of the offset.
int r1de = quant_color(quant_level, r1d);
@@ -728,9 +754,9 @@ static void quantize_rgbs(
float g = astc::clamp255f(color.lane<1>() * scale);
float b = astc::clamp255f(color.lane<2>() * scale);
- int ri = quant_color(quant_level, astc::flt2int_rtn(r));
- int gi = quant_color(quant_level, astc::flt2int_rtn(g));
- int bi = quant_color(quant_level, astc::flt2int_rtn(b));
+ int ri = quant_color(quant_level, astc::flt2int_rtn(r), r);
+ int gi = quant_color(quant_level, astc::flt2int_rtn(g), g);
+ int bi = quant_color(quant_level, astc::flt2int_rtn(b), b);
float oldcolorsum = hadd_rgb_s(color) * scale;
float newcolorsum = static_cast<float>(ri + gi + bi);
@@ -764,8 +790,8 @@ static void quantize_rgbs_alpha(
float a0 = astc::clamp255f(color0.lane<3>() * scale);
float a1 = astc::clamp255f(color1.lane<3>() * scale);
- output[4] = quant_color(quant_level, astc::flt2int_rtn(a0));
- output[5] = quant_color(quant_level, astc::flt2int_rtn(a1));
+ output[4] = quant_color(quant_level, astc::flt2int_rtn(a0), a0);
+ output[5] = quant_color(quant_level, astc::flt2int_rtn(a1), a1);
quantize_rgbs(color, output, quant_level);
}
@@ -799,8 +825,8 @@ static void quantize_luminance(
lum1 = avg;
}
- output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0));
- output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1));
+ output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0), lum0);
+ output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1), lum1);
}
/**
@@ -828,48 +854,10 @@ static void quantize_luminance_alpha(
float a0 = astc::clamp255f(color0.lane<3>());
float a1 = astc::clamp255f(color1.lane<3>());
- // If endpoints are close then pull apart slightly; this gives > 8 bit normal map precision.
- if (quant_level > 18)
- {
- if (fabsf(lum0 - lum1) < 3.0f)
- {
- if (lum0 < lum1)
- {
- lum0 -= 0.5f;
- lum1 += 0.5f;
- }
- else
- {
- lum0 += 0.5f;
- lum1 -= 0.5f;
- }
-
- lum0 = astc::clamp255f(lum0);
- lum1 = astc::clamp255f(lum1);
- }
-
- if (fabsf(a0 - a1) < 3.0f)
- {
- if (a0 < a1)
- {
- a0 -= 0.5f;
- a1 += 0.5f;
- }
- else
- {
- a0 += 0.5f;
- a1 -= 0.5f;
- }
-
- a0 = astc::clamp255f(a0);
- a1 = astc::clamp255f(a1);
- }
- }
-
- output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0));
- output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1));
- output[2] = quant_color(quant_level, astc::flt2int_rtn(a0));
- output[3] = quant_color(quant_level, astc::flt2int_rtn(a1));
+ output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0), lum0);
+ output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1), lum1);
+ output[2] = quant_color(quant_level, astc::flt2int_rtn(a0), a0);
+ output[3] = quant_color(quant_level, astc::flt2int_rtn(a1), a1);
}
/**
@@ -1661,8 +1649,8 @@ static void quantize_hdr_rgb_ldr_alpha(
float a0 = astc::clamp255f(color0.lane<3>() * scale);
float a1 = astc::clamp255f(color1.lane<3>() * scale);
- output[6] = quant_color(quant_level, astc::flt2int_rtn(a0));
- output[7] = quant_color(quant_level, astc::flt2int_rtn(a1));
+ output[6] = quant_color(quant_level, astc::flt2int_rtn(a0), a0);
+ output[7] = quant_color(quant_level, astc::flt2int_rtn(a1), a1);
quantize_hdr_rgb(color0, color1, output, quant_level);
}
diff --git a/thirdparty/astcenc/astcenc_compress_symbolic.cpp b/thirdparty/astcenc/astcenc_compress_symbolic.cpp
index afb76246e7..41a8558267 100644
--- a/thirdparty/astcenc/astcenc_compress_symbolic.cpp
+++ b/thirdparty/astcenc/astcenc_compress_symbolic.cpp
@@ -391,7 +391,7 @@ static float compress_symbolic_block_for_partition_1plane(
for (unsigned int i = 0; i < max_decimation_modes; i++)
{
const auto& dm = bsd.get_decimation_mode(i);
- if (!dm.is_ref_1_plane(static_cast<quant_method>(max_weight_quant)))
+ if (!dm.is_ref_1plane(static_cast<quant_method>(max_weight_quant)))
{
continue;
}
@@ -561,7 +561,7 @@ static float compress_symbolic_block_for_partition_1plane(
workscb.color_formats_matched = 0;
if (partition_count >= 2 && all_same)
{
- uint8_t colorvals[BLOCK_MAX_PARTITIONS][12];
+ uint8_t colorvals[BLOCK_MAX_PARTITIONS][8];
uint8_t color_formats_mod[BLOCK_MAX_PARTITIONS] { 0 };
bool all_same_mod = true;
for (unsigned int j = 0; j < partition_count; j++)
@@ -743,7 +743,7 @@ static float compress_symbolic_block_for_partition_2planes(
for (unsigned int i = 0; i < bsd.decimation_mode_count_selected; i++)
{
const auto& dm = bsd.get_decimation_mode(i);
- if (!dm.is_ref_2_plane(static_cast<quant_method>(max_weight_quant)))
+ if (!dm.is_ref_2plane(static_cast<quant_method>(max_weight_quant)))
{
continue;
}
@@ -1263,8 +1263,8 @@ void compress_block(
float exit_thresholds_for_pcount[BLOCK_MAX_PARTITIONS] {
0.0f,
- ctx.config.tune_2_partition_early_out_limit_factor,
- ctx.config.tune_3_partition_early_out_limit_factor,
+ ctx.config.tune_2partition_early_out_limit_factor,
+ ctx.config.tune_3partition_early_out_limit_factor,
0.0f
};
@@ -1318,7 +1318,7 @@ void compress_block(
lowest_correl = prepare_block_statistics(bsd.texel_count, blk);
#endif
- block_skip_two_plane = lowest_correl > ctx.config.tune_2_plane_early_out_limit_correlation;
+ block_skip_two_plane = lowest_correl > ctx.config.tune_2plane_early_out_limit_correlation;
// Test the four possible 1-partition, 2-planes modes. Do this in reverse, as
// alpha is the most likely to be non-correlated if it is present in the data.
@@ -1331,7 +1331,7 @@ void compress_block(
if (block_skip_two_plane)
{
- trace_add_data("skip", "tune_2_plane_early_out_limit_correlation");
+ trace_add_data("skip", "tune_2plane_early_out_limit_correlation");
continue;
}
diff --git a/thirdparty/astcenc/astcenc_diagnostic_trace.cpp b/thirdparty/astcenc/astcenc_diagnostic_trace.cpp
index 7fa7ab1a8b..bcd6fa72a5 100644
--- a/thirdparty/astcenc/astcenc_diagnostic_trace.cpp
+++ b/thirdparty/astcenc/astcenc_diagnostic_trace.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
-// Copyright 2021-2022 Arm Limited
+// Copyright 2021-2023 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
@@ -24,6 +24,8 @@
#include <cassert>
#include <cstdarg>
#include <cstdio>
+#include <cmath>
+#include <limits>
#include <string>
#include "astcenc_diagnostic_trace.h"
@@ -203,7 +205,20 @@ void trace_add_data(
const char* key,
float value
) {
- char buffer[256];
+ // Turn infinities into parseable values
+ if (std::isinf(value))
+ {
+ if (value > 0.0f)
+ {
+ value = std::numeric_limits<float>::max();
+ }
+ else
+ {
+ value = -std::numeric_limits<float>::max();
+ }
+ }
+
+ char buffer[256];
sprintf(buffer, "%.20g", (double)value);
TraceNode* node = g_TraceLog->get_current_leaf();
node->add_attrib("float", key, buffer);
diff --git a/thirdparty/astcenc/astcenc_entry.cpp b/thirdparty/astcenc/astcenc_entry.cpp
index e59f1fe61a..e53762c26a 100644
--- a/thirdparty/astcenc/astcenc_entry.cpp
+++ b/thirdparty/astcenc/astcenc_entry.cpp
@@ -52,9 +52,9 @@ struct astcenc_preset_config
float tune_db_limit_a_base;
float tune_db_limit_b_base;
float tune_mse_overshoot;
- float tune_2_partition_early_out_limit_factor;
- float tune_3_partition_early_out_limit_factor;
- float tune_2_plane_early_out_limit_correlation;
+ float tune_2partition_early_out_limit_factor;
+ float tune_3partition_early_out_limit_factor;
+ float tune_2plane_early_out_limit_correlation;
};
/**
@@ -158,48 +158,6 @@ static astcenc_error validate_cpu_float()
}
/**
- * @brief Validate CPU ISA support meets the requirements of this build of the library.
- *
- * Each library build is statically compiled for a particular set of CPU ISA features, such as the
- * SIMD support or other ISA extensions such as POPCNT. This function checks that the host CPU
- * actually supports everything this build needs.
- *
- * @return Return @c ASTCENC_SUCCESS if validated, otherwise an error on failure.
- */
-static astcenc_error validate_cpu_isa()
-{
- #if ASTCENC_SSE >= 41
- if (!cpu_supports_sse41())
- {
- return ASTCENC_ERR_BAD_CPU_ISA;
- }
- #endif
-
- #if ASTCENC_POPCNT >= 1
- if (!cpu_supports_popcnt())
- {
- return ASTCENC_ERR_BAD_CPU_ISA;
- }
- #endif
-
- #if ASTCENC_F16C >= 1
- if (!cpu_supports_f16c())
- {
- return ASTCENC_ERR_BAD_CPU_ISA;
- }
- #endif
-
- #if ASTCENC_AVX >= 2
- if (!cpu_supports_avx2())
- {
- return ASTCENC_ERR_BAD_CPU_ISA;
- }
- #endif
-
- return ASTCENC_SUCCESS;
-}
-
-/**
* @brief Validate config profile.
*
* @param profile The profile to check.
@@ -439,9 +397,9 @@ static astcenc_error validate_config(
config.tune_4partitioning_candidate_limit = astc::clamp(config.tune_4partitioning_candidate_limit, 1u, TUNE_MAX_PARTITIONING_CANDIDATES);
config.tune_db_limit = astc::max(config.tune_db_limit, 0.0f);
config.tune_mse_overshoot = astc::max(config.tune_mse_overshoot, 1.0f);
- config.tune_2_partition_early_out_limit_factor = astc::max(config.tune_2_partition_early_out_limit_factor, 0.0f);
- config.tune_3_partition_early_out_limit_factor = astc::max(config.tune_3_partition_early_out_limit_factor, 0.0f);
- config.tune_2_plane_early_out_limit_correlation = astc::max(config.tune_2_plane_early_out_limit_correlation, 0.0f);
+ config.tune_2partition_early_out_limit_factor = astc::max(config.tune_2partition_early_out_limit_factor, 0.0f);
+ config.tune_3partition_early_out_limit_factor = astc::max(config.tune_3partition_early_out_limit_factor, 0.0f);
+ config.tune_2plane_early_out_limit_correlation = astc::max(config.tune_2plane_early_out_limit_correlation, 0.0f);
// Specifying a zero weight color component is not allowed; force to small value
float max_weight = astc::max(astc::max(config.cw_r_weight, config.cw_g_weight),
@@ -475,14 +433,6 @@ astcenc_error astcenc_config_init(
) {
astcenc_error status;
- // Check basic library compatibility options here so they are checked early. Note, these checks
- // are repeated in context_alloc for cases where callers use a manually defined config struct
- status = validate_cpu_isa();
- if (status != ASTCENC_SUCCESS)
- {
- return status;
- }
-
status = validate_cpu_float();
if (status != ASTCENC_SUCCESS)
{
@@ -563,9 +513,9 @@ astcenc_error astcenc_config_init(
config.tune_mse_overshoot = (*preset_configs)[start].tune_mse_overshoot;
- config.tune_2_partition_early_out_limit_factor = (*preset_configs)[start].tune_2_partition_early_out_limit_factor;
- config.tune_3_partition_early_out_limit_factor =(*preset_configs)[start].tune_3_partition_early_out_limit_factor;
- config.tune_2_plane_early_out_limit_correlation = (*preset_configs)[start].tune_2_plane_early_out_limit_correlation;
+ config.tune_2partition_early_out_limit_factor = (*preset_configs)[start].tune_2partition_early_out_limit_factor;
+ config.tune_3partition_early_out_limit_factor = (*preset_configs)[start].tune_3partition_early_out_limit_factor;
+ config.tune_2plane_early_out_limit_correlation = (*preset_configs)[start].tune_2plane_early_out_limit_correlation;
}
// Start and end node are not the same - so interpolate between them
else
@@ -605,9 +555,9 @@ astcenc_error astcenc_config_init(
config.tune_mse_overshoot = LERP(tune_mse_overshoot);
- config.tune_2_partition_early_out_limit_factor = LERP(tune_2_partition_early_out_limit_factor);
- config.tune_3_partition_early_out_limit_factor = LERP(tune_3_partition_early_out_limit_factor);
- config.tune_2_plane_early_out_limit_correlation = LERP(tune_2_plane_early_out_limit_correlation);
+ config.tune_2partition_early_out_limit_factor = LERP(tune_2partition_early_out_limit_factor);
+ config.tune_3partition_early_out_limit_factor = LERP(tune_3partition_early_out_limit_factor);
+ config.tune_2plane_early_out_limit_correlation = LERP(tune_2plane_early_out_limit_correlation);
#undef LERP
#undef LERPI
#undef LERPUI
@@ -656,9 +606,9 @@ astcenc_error astcenc_config_init(
config.cw_g_weight = 0.0f;
config.cw_b_weight = 0.0f;
- config.tune_2_partition_early_out_limit_factor *= 1.5f;
- config.tune_3_partition_early_out_limit_factor *= 1.5f;
- config.tune_2_plane_early_out_limit_correlation = 0.99f;
+ config.tune_2partition_early_out_limit_factor *= 1.5f;
+ config.tune_3partition_early_out_limit_factor *= 1.5f;
+ config.tune_2plane_early_out_limit_correlation = 0.99f;
// Normals are prone to blocking artifacts on smooth curves
// so force compressor to try harder here ...
@@ -702,12 +652,6 @@ astcenc_error astcenc_context_alloc(
astcenc_error status;
const astcenc_config& config = *configp;
- status = validate_cpu_isa();
- if (status != ASTCENC_SUCCESS)
- {
- return status;
- }
-
status = validate_cpu_float();
if (status != ASTCENC_SUCCESS)
{
@@ -1399,8 +1343,6 @@ const char* astcenc_get_error_string(
return "ASTCENC_ERR_OUT_OF_MEM";
case ASTCENC_ERR_BAD_CPU_FLOAT:
return "ASTCENC_ERR_BAD_CPU_FLOAT";
- case ASTCENC_ERR_BAD_CPU_ISA:
- return "ASTCENC_ERR_BAD_CPU_ISA";
case ASTCENC_ERR_BAD_PARAM:
return "ASTCENC_ERR_BAD_PARAM";
case ASTCENC_ERR_BAD_BLOCK_SIZE:
diff --git a/thirdparty/astcenc/astcenc_find_best_partitioning.cpp b/thirdparty/astcenc/astcenc_find_best_partitioning.cpp
index ffde3c7060..789c3964ef 100644
--- a/thirdparty/astcenc/astcenc_find_best_partitioning.cpp
+++ b/thirdparty/astcenc/astcenc_find_best_partitioning.cpp
@@ -604,8 +604,7 @@ unsigned int find_best_partition_candidates(
processed_line4 uncor_plines[BLOCK_MAX_PARTITIONS];
processed_line4 samec_plines[BLOCK_MAX_PARTITIONS];
- float uncor_line_lens[BLOCK_MAX_PARTITIONS];
- float samec_line_lens[BLOCK_MAX_PARTITIONS];
+ float line_lengths[BLOCK_MAX_PARTITIONS];
for (unsigned int j = 0; j < partition_count; j++)
{
@@ -631,8 +630,7 @@ unsigned int find_best_partition_candidates(
blk,
uncor_plines,
samec_plines,
- uncor_line_lens,
- samec_line_lens,
+ line_lengths,
uncor_error,
samec_error);
@@ -651,8 +649,8 @@ unsigned int find_best_partition_candidates(
float tpp = static_cast<float>(pi.partition_texel_count[j]);
vfloat4 error_weights(tpp * weight_imprecision_estim);
- vfloat4 uncor_vector = uncor_lines[j].b * uncor_line_lens[j];
- vfloat4 samec_vector = samec_lines[j].b * samec_line_lens[j];
+ vfloat4 uncor_vector = uncor_lines[j].b * line_lengths[j];
+ vfloat4 samec_vector = samec_lines[j].b * line_lengths[j];
uncor_error += dot_s(uncor_vector * uncor_vector, error_weights);
samec_error += dot_s(samec_vector * samec_vector, error_weights);
@@ -719,8 +717,8 @@ unsigned int find_best_partition_candidates(
float tpp = static_cast<float>(pi.partition_texel_count[j]);
vfloat4 error_weights(tpp * weight_imprecision_estim);
- vfloat4 uncor_vector = pl.uncor_line.b * pl.uncor_line_len;
- vfloat4 samec_vector = pl.samec_line.b * pl.samec_line_len;
+ vfloat4 uncor_vector = pl.uncor_line.b * pl.line_length;
+ vfloat4 samec_vector = pl.samec_line.b * pl.line_length;
uncor_error += dot3_s(uncor_vector * uncor_vector, error_weights);
samec_error += dot3_s(samec_vector * samec_vector, error_weights);
@@ -731,21 +729,11 @@ unsigned int find_best_partition_candidates(
}
}
- bool best_is_uncor = uncor_best_partitions[0] > samec_best_partitions[0];
-
unsigned int interleave[2 * TUNE_MAX_PARTITIONING_CANDIDATES];
for (unsigned int i = 0; i < requested_candidates; i++)
{
- if (best_is_uncor)
- {
- interleave[2 * i] = bsd.get_raw_partition_info(partition_count, uncor_best_partitions[i]).partition_index;
- interleave[2 * i + 1] = bsd.get_raw_partition_info(partition_count, samec_best_partitions[i]).partition_index;
- }
- else
- {
- interleave[2 * i] = bsd.get_raw_partition_info(partition_count, samec_best_partitions[i]).partition_index;
- interleave[2 * i + 1] = bsd.get_raw_partition_info(partition_count, uncor_best_partitions[i]).partition_index;
- }
+ interleave[2 * i] = bsd.get_raw_partition_info(partition_count, uncor_best_partitions[i]).partition_index;
+ interleave[2 * i + 1] = bsd.get_raw_partition_info(partition_count, samec_best_partitions[i]).partition_index;
}
uint64_t bitmasks[1024/64] { 0 };
diff --git a/thirdparty/astcenc/astcenc_internal.h b/thirdparty/astcenc/astcenc_internal.h
index 0aa8fa0f81..63bbf8af53 100644
--- a/thirdparty/astcenc/astcenc_internal.h
+++ b/thirdparty/astcenc/astcenc_internal.h
@@ -293,11 +293,13 @@ struct partition_lines3
/** @brief Post-processed line for correlated chroma, passing though the origin. */
processed_line3 samec_pline;
- /** @brief The length of the line for uncorrelated chroma. */
- float uncor_line_len;
-
- /** @brief The length of the line for correlated chroma. */
- float samec_line_len;
+ /**
+ * @brief The length of the line for uncorrelated chroma.
+ *
+ * This is used for both the uncorrelated and same chroma lines - they are normally very similar
+ * and only used for the relative ranking of partitionings against one another.
+ */
+ float line_length;
};
/**
@@ -319,8 +321,8 @@ struct partition_info
/**
* @brief The number of texels in each partition.
*
- * Note that some seeds result in zero texels assigned to a partition are valid, but are skipped
- * by this compressor as there is no point spending bits encoding an unused color endpoint.
+ * Note that some seeds result in zero texels assigned to a partition. These are valid, but are
+ * skipped by this compressor as there is no point spending bits encoding an unused endpoints.
*/
uint8_t partition_texel_count[BLOCK_MAX_PARTITIONS];
@@ -455,23 +457,23 @@ struct decimation_mode
*
* Bit 0 = QUANT_2, Bit 1 = QUANT_3, etc.
*/
- uint16_t refprec_1_plane;
+ uint16_t refprec_1plane;
/**
* @brief Bitvector indicating weight quant methods used by active 2 plane block modes.
*
* Bit 0 = QUANT_2, Bit 1 = QUANT_3, etc.
*/
- uint16_t refprec_2_planes;
+ uint16_t refprec_2planes;
/**
* @brief Set a 1 plane weight quant as active.
*
* @param weight_quant The quant method to set.
*/
- void set_ref_1_plane(quant_method weight_quant)
+ void set_ref_1plane(quant_method weight_quant)
{
- refprec_1_plane |= (1 << weight_quant);
+ refprec_1plane |= (1 << weight_quant);
}
/**
@@ -479,10 +481,10 @@ struct decimation_mode
*
* @param max_weight_quant The max quant method to test.
*/
- bool is_ref_1_plane(quant_method max_weight_quant) const
+ bool is_ref_1plane(quant_method max_weight_quant) const
{
uint16_t mask = static_cast<uint16_t>((1 << (max_weight_quant + 1)) - 1);
- return (refprec_1_plane & mask) != 0;
+ return (refprec_1plane & mask) != 0;
}
/**
@@ -490,9 +492,9 @@ struct decimation_mode
*
* @param weight_quant The quant method to set.
*/
- void set_ref_2_plane(quant_method weight_quant)
+ void set_ref_2plane(quant_method weight_quant)
{
- refprec_2_planes |= static_cast<uint16_t>(1 << weight_quant);
+ refprec_2planes |= static_cast<uint16_t>(1 << weight_quant);
}
/**
@@ -500,10 +502,10 @@ struct decimation_mode
*
* @param max_weight_quant The max quant method to test.
*/
- bool is_ref_2_plane(quant_method max_weight_quant) const
+ bool is_ref_2plane(quant_method max_weight_quant) const
{
uint16_t mask = static_cast<uint16_t>((1 << (max_weight_quant + 1)) - 1);
- return (refprec_2_planes & mask) != 0;
+ return (refprec_2planes & mask) != 0;
}
};
@@ -1336,9 +1338,14 @@ bool is_legal_3d_block_size(
* Converts unquant value in 0-255 range into quant value in 0-255 range.
* No BISE scrambling is applied at this stage.
*
- * Indexed by [quant_mode - 4][data_value].
+ * The BISE encoding results in ties where available quant<256> values are
+ * equidistant the available quant<BISE> values. This table stores two values
+ * for each input - one for use with a negative residual, and one for use with
+ * a positive residual.
+ *
+ * Indexed by [quant_mode - 4][data_value * 2 + residual].
*/
-extern const uint8_t color_unquant_to_uquant_tables[17][256];
+extern const uint8_t color_unquant_to_uquant_tables[17][512];
/**
* @brief The precomputed table for packing quantized color values.
@@ -1528,8 +1535,7 @@ void compute_error_squared_rgb(
* @param blk The image block color data to be compressed.
* @param uncor_plines Processed uncorrelated partition lines for each partition.
* @param samec_plines Processed same chroma partition lines for each partition.
- * @param[out] uncor_lengths The length of each components deviation from the line.
- * @param[out] samec_lengths The length of each components deviation from the line.
+ * @param[out] line_lengths The length of each components deviation from the line.
* @param[out] uncor_error The cumulative error for using the uncorrelated line.
* @param[out] samec_error The cumulative error for using the same chroma line.
*/
@@ -1538,8 +1544,7 @@ void compute_error_squared_rgba(
const image_block& blk,
const processed_line4 uncor_plines[BLOCK_MAX_PARTITIONS],
const processed_line4 samec_plines[BLOCK_MAX_PARTITIONS],
- float uncor_lengths[BLOCK_MAX_PARTITIONS],
- float samec_lengths[BLOCK_MAX_PARTITIONS],
+ float line_lengths[BLOCK_MAX_PARTITIONS],
float& uncor_error,
float& samec_error);
@@ -2121,34 +2126,6 @@ void physical_to_symbolic(
Platform-specific functions.
============================================================================ */
/**
- * @brief Run-time detection if the host CPU supports the POPCNT extension.
- *
- * @return @c true if supported, @c false if not.
- */
-bool cpu_supports_popcnt();
-
-/**
- * @brief Run-time detection if the host CPU supports F16C extension.
- *
- * @return @c true if supported, @c false if not.
- */
-bool cpu_supports_f16c();
-
-/**
- * @brief Run-time detection if the host CPU supports SSE 4.1 extension.
- *
- * @return @c true if supported, @c false if not.
- */
-bool cpu_supports_sse41();
-
-/**
- * @brief Run-time detection if the host CPU supports AVX 2 extension.
- *
- * @return @c true if supported, @c false if not.
- */
-bool cpu_supports_avx2();
-
-/**
* @brief Allocate an aligned memory buffer.
*
* Allocated memory must be freed by aligned_free;
diff --git a/thirdparty/astcenc/astcenc_platform_isa_detection.cpp b/thirdparty/astcenc/astcenc_platform_isa_detection.cpp
deleted file mode 100644
index 8ed98437ea..0000000000
--- a/thirdparty/astcenc/astcenc_platform_isa_detection.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-// ----------------------------------------------------------------------------
-// Copyright 2020-2022 Arm Limited
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy
-// of the License at:
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-// ----------------------------------------------------------------------------
-
-/**
- * @brief Platform-specific function implementations.
- *
- * This module contains functions for querying the host extended ISA support.
- */
-
-// Include before the defines below to pick up any auto-setup based on compiler
-// built-in config, if not being set explicitly by the build system
-#include "astcenc_internal.h"
-
-#if (ASTCENC_SSE > 0) || (ASTCENC_AVX > 0) || \
- (ASTCENC_POPCNT > 0) || (ASTCENC_F16C > 0)
-
-static bool g_init { false };
-
-/** Does this CPU support SSE 4.1? Set to -1 if not yet initialized. */
-static bool g_cpu_has_sse41 { false };
-
-/** Does this CPU support AVX2? Set to -1 if not yet initialized. */
-static bool g_cpu_has_avx2 { false };
-
-/** Does this CPU support POPCNT? Set to -1 if not yet initialized. */
-static bool g_cpu_has_popcnt { false };
-
-/** Does this CPU support F16C? Set to -1 if not yet initialized. */
-static bool g_cpu_has_f16c { false };
-
-/* ============================================================================
- Platform code for Visual Studio
-============================================================================ */
-#if !defined(__clang__) && defined(_MSC_VER)
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <intrin.h>
-
-/**
- * @brief Detect platform CPU ISA support and update global trackers.
- */
-static void detect_cpu_isa()
-{
- int data[4];
-
- __cpuid(data, 0);
- int num_id = data[0];
-
- if (num_id >= 1)
- {
- __cpuidex(data, 1, 0);
- // SSE41 = Bank 1, ECX, bit 19
- g_cpu_has_sse41 = data[2] & (1 << 19) ? true : false;
- // POPCNT = Bank 1, ECX, bit 23
- g_cpu_has_popcnt = data[2] & (1 << 23) ? true : false;
- // F16C = Bank 1, ECX, bit 29
- g_cpu_has_f16c = data[2] & (1 << 29) ? true : false;
- }
-
- if (num_id >= 7)
- {
- __cpuidex(data, 7, 0);
- // AVX2 = Bank 7, EBX, bit 5
- g_cpu_has_avx2 = data[1] & (1 << 5) ? true : false;
- }
-
- // Ensure state bits are updated before init flag is updated
- MemoryBarrier();
- g_init = true;
-}
-
-/* ============================================================================
- Platform code for GCC and Clang
-============================================================================ */
-#else
-#include <cpuid.h>
-
-/**
- * @brief Detect platform CPU ISA support and update global trackers.
- */
-static void detect_cpu_isa()
-{
- unsigned int data[4];
-
- if (__get_cpuid_count(1, 0, &data[0], &data[1], &data[2], &data[3]))
- {
- // SSE41 = Bank 1, ECX, bit 19
- g_cpu_has_sse41 = data[2] & (1 << 19) ? true : false;
- // POPCNT = Bank 1, ECX, bit 23
- g_cpu_has_popcnt = data[2] & (1 << 23) ? true : false;
- // F16C = Bank 1, ECX, bit 29
- g_cpu_has_f16c = data[2] & (1 << 29) ? true : false;
- }
-
- g_cpu_has_avx2 = 0;
- if (__get_cpuid_count(7, 0, &data[0], &data[1], &data[2], &data[3]))
- {
- // AVX2 = Bank 7, EBX, bit 5
- g_cpu_has_avx2 = data[1] & (1 << 5) ? true : false;
- }
-
- // Ensure state bits are updated before init flag is updated
- __sync_synchronize();
- g_init = true;
-}
-#endif
-
-/* See header for documentation. */
-bool cpu_supports_popcnt()
-{
- if (!g_init)
- {
- detect_cpu_isa();
- }
-
- return g_cpu_has_popcnt;
-}
-
-/* See header for documentation. */
-bool cpu_supports_f16c()
-{
- if (!g_init)
- {
- detect_cpu_isa();
- }
-
- return g_cpu_has_f16c;
-}
-
-/* See header for documentation. */
-bool cpu_supports_sse41()
-{
- if (!g_init)
- {
- detect_cpu_isa();
- }
-
- return g_cpu_has_sse41;
-}
-
-/* See header for documentation. */
-bool cpu_supports_avx2()
-{
- if (!g_init)
- {
- detect_cpu_isa();
- }
-
- return g_cpu_has_avx2;
-}
-
-#endif
diff --git a/thirdparty/astcenc/astcenc_quantization.cpp b/thirdparty/astcenc/astcenc_quantization.cpp
index 478a21ead7..84d758dbfa 100644
--- a/thirdparty/astcenc/astcenc_quantization.cpp
+++ b/thirdparty/astcenc/astcenc_quantization.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
-// Copyright 2011-2021 Arm Limited
+// Copyright 2011-2023 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
@@ -23,321 +23,320 @@
#if !defined(ASTCENC_DECOMPRESS_ONLY)
-// Starts from QUANT_6
-// Not scrambled
-const uint8_t color_unquant_to_uquant_tables[17][256] {
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 102, 102, 102,
- 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
- 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
- 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
- 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
- 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
- 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
- 153, 153, 153, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
- 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
- 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
- 204, 204, 204, 204, 204, 204, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
- },
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 109, 109, 109, 109,
- 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109,
- 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109,
- 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
- 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
- 146, 146, 146, 146, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
- 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
- 182, 182, 182, 182, 182, 182, 182, 182, 182, 219, 219, 219, 219, 219, 219, 219,
- 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
- 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
- },
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28,
- 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 171, 171, 171,
- 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171,
- 171, 171, 171, 171, 171, 171, 171, 171, 171, 199, 199, 199, 199, 199, 199, 199,
- 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
- 199, 199, 199, 199, 199, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227,
- 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227,
- 227, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
- },
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 116, 116, 116, 116, 116, 116, 116,
- 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
- 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
- 139, 139, 139, 139, 139, 139, 139, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 186,
- 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
- 186, 186, 186, 186, 186, 186, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 232, 232, 232,
- 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
- 232, 232, 232, 232, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
- },
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 102, 102,
- 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 119,
- 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
- 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
- 136, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
- 153, 153, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
- 170, 170, 170, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
- 187, 187, 187, 187, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
- 204, 204, 204, 204, 204, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
- 221, 221, 221, 221, 221, 221, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 255, 255, 255, 255, 255, 255, 255, 255, 255
- },
- {
- 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 94, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
- 107, 107, 107, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
- 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 148, 148, 148,
- 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 161, 161, 161, 161, 161,
- 161, 161, 161, 161, 161, 161, 161, 161, 175, 175, 175, 175, 175, 175, 175, 175,
- 175, 175, 175, 175, 175, 175, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188,
- 188, 188, 188, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
- 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 228, 228,
- 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 242, 242, 242, 242, 242,
- 242, 242, 242, 242, 242, 242, 242, 242, 242, 255, 255, 255, 255, 255, 255, 255
- },
- {
- 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 44, 44, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 66, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 110, 110, 110, 110, 110, 110, 110,
- 110, 110, 110, 110, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
- 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 178, 178, 178,
- 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189,
- 189, 189, 189, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 211, 211,
- 211, 211, 211, 211, 211, 211, 211, 211, 211, 222, 222, 222, 222, 222, 222, 222,
- 222, 222, 222, 222, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 244,
- 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 255, 255, 255, 255, 255, 255
- },
- {
- 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16,
- 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 41, 41, 41, 41, 41, 41, 41, 41, 49, 49,
- 49, 49, 49, 49, 49, 49, 57, 57, 57, 57, 57, 57, 57, 57, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 74, 74, 74, 74, 74, 74, 74, 74, 82,
- 82, 82, 82, 82, 82, 82, 82, 90, 90, 90, 90, 90, 90, 90, 90, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 107, 107, 107, 107, 107, 107, 107, 107,
- 115, 115, 115, 115, 115, 115, 115, 115, 123, 123, 123, 123, 123, 123, 123, 123,
- 132, 132, 132, 132, 132, 132, 132, 132, 140, 140, 140, 140, 140, 140, 140, 140,
- 148, 148, 148, 148, 148, 148, 148, 148, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 165, 165, 165, 165, 165, 165, 165, 165, 173, 173, 173, 173, 173, 173, 173,
- 173, 181, 181, 181, 181, 181, 181, 181, 181, 189, 189, 189, 189, 189, 189, 189,
- 189, 189, 198, 198, 198, 198, 198, 198, 198, 198, 206, 206, 206, 206, 206, 206,
- 206, 206, 214, 214, 214, 214, 214, 214, 214, 214, 222, 222, 222, 222, 222, 222,
- 222, 222, 222, 231, 231, 231, 231, 231, 231, 231, 231, 239, 239, 239, 239, 239,
- 239, 239, 239, 247, 247, 247, 247, 247, 247, 247, 247, 255, 255, 255, 255, 255
- },
- {
- 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 13, 13, 13, 13, 13, 13,
- 13, 19, 19, 19, 19, 19, 19, 26, 26, 26, 26, 26, 26, 26, 32, 32,
- 32, 32, 32, 32, 39, 39, 39, 39, 39, 39, 39, 45, 45, 45, 45, 45,
- 45, 52, 52, 52, 52, 52, 52, 52, 58, 58, 58, 58, 58, 58, 65, 65,
- 65, 65, 65, 65, 65, 71, 71, 71, 71, 71, 71, 78, 78, 78, 78, 78,
- 78, 78, 84, 84, 84, 84, 84, 84, 91, 91, 91, 91, 91, 91, 91, 97,
- 97, 97, 97, 97, 97, 104, 104, 104, 104, 104, 104, 104, 110, 110, 110, 110,
- 110, 110, 117, 117, 117, 117, 117, 117, 117, 123, 123, 123, 123, 123, 123, 123,
- 132, 132, 132, 132, 132, 132, 132, 138, 138, 138, 138, 138, 138, 138, 145, 145,
- 145, 145, 145, 145, 151, 151, 151, 151, 151, 151, 151, 158, 158, 158, 158, 158,
- 158, 164, 164, 164, 164, 164, 164, 164, 171, 171, 171, 171, 171, 171, 177, 177,
- 177, 177, 177, 177, 177, 184, 184, 184, 184, 184, 184, 190, 190, 190, 190, 190,
- 190, 190, 197, 197, 197, 197, 197, 197, 203, 203, 203, 203, 203, 203, 203, 210,
- 210, 210, 210, 210, 210, 216, 216, 216, 216, 216, 216, 216, 223, 223, 223, 223,
- 223, 223, 229, 229, 229, 229, 229, 229, 229, 236, 236, 236, 236, 236, 236, 242,
- 242, 242, 242, 242, 242, 242, 249, 249, 249, 249, 249, 249, 255, 255, 255, 255
- },
- {
- 0, 0, 0, 5, 5, 5, 5, 5, 5, 11, 11, 11, 11, 11, 16, 16,
- 16, 16, 16, 21, 21, 21, 21, 21, 21, 27, 27, 27, 27, 27, 32, 32,
- 32, 32, 32, 32, 38, 38, 38, 38, 38, 43, 43, 43, 43, 43, 48, 48,
- 48, 48, 48, 48, 54, 54, 54, 54, 54, 59, 59, 59, 59, 59, 59, 65,
- 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 76, 76, 76, 76, 76, 81,
- 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 92, 92, 92, 92, 92, 97,
- 97, 97, 97, 97, 97, 103, 103, 103, 103, 103, 108, 108, 108, 108, 108, 113,
- 113, 113, 113, 113, 113, 119, 119, 119, 119, 119, 124, 124, 124, 124, 124, 124,
- 131, 131, 131, 131, 131, 131, 136, 136, 136, 136, 136, 142, 142, 142, 142, 142,
- 142, 147, 147, 147, 147, 147, 152, 152, 152, 152, 152, 158, 158, 158, 158, 158,
- 158, 163, 163, 163, 163, 163, 169, 169, 169, 169, 169, 169, 174, 174, 174, 174,
- 174, 179, 179, 179, 179, 179, 185, 185, 185, 185, 185, 185, 190, 190, 190, 190,
- 190, 196, 196, 196, 196, 196, 196, 201, 201, 201, 201, 201, 207, 207, 207, 207,
- 207, 207, 212, 212, 212, 212, 212, 217, 217, 217, 217, 217, 223, 223, 223, 223,
- 223, 223, 228, 228, 228, 228, 228, 234, 234, 234, 234, 234, 234, 239, 239, 239,
- 239, 239, 244, 244, 244, 244, 244, 250, 250, 250, 250, 250, 250, 255, 255, 255
- },
- {
- 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12, 16,
- 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 24, 28, 28, 28, 28, 32,
- 32, 32, 32, 36, 36, 36, 36, 40, 40, 40, 40, 44, 44, 44, 44, 48,
- 48, 48, 48, 52, 52, 52, 52, 56, 56, 56, 56, 60, 60, 60, 60, 65,
- 65, 65, 65, 65, 69, 69, 69, 69, 73, 73, 73, 73, 77, 77, 77, 77,
- 81, 81, 81, 81, 85, 85, 85, 85, 89, 89, 89, 89, 93, 93, 93, 93,
- 97, 97, 97, 97, 101, 101, 101, 101, 105, 105, 105, 105, 109, 109, 109, 109,
- 113, 113, 113, 113, 117, 117, 117, 117, 121, 121, 121, 121, 125, 125, 125, 125,
- 130, 130, 130, 130, 134, 134, 134, 134, 138, 138, 138, 138, 142, 142, 142, 142,
- 146, 146, 146, 146, 150, 150, 150, 150, 154, 154, 154, 154, 158, 158, 158, 158,
- 162, 162, 162, 162, 166, 166, 166, 166, 170, 170, 170, 170, 174, 174, 174, 174,
- 178, 178, 178, 178, 182, 182, 182, 182, 186, 186, 186, 186, 190, 190, 190, 190,
- 190, 195, 195, 195, 195, 199, 199, 199, 199, 203, 203, 203, 203, 207, 207, 207,
- 207, 211, 211, 211, 211, 215, 215, 215, 215, 219, 219, 219, 219, 223, 223, 223,
- 223, 227, 227, 227, 227, 231, 231, 231, 231, 235, 235, 235, 235, 239, 239, 239,
- 239, 243, 243, 243, 243, 247, 247, 247, 247, 251, 251, 251, 251, 255, 255, 255
- },
- {
- 0, 0, 3, 3, 3, 6, 6, 6, 9, 9, 9, 9, 13, 13, 13, 16,
- 16, 16, 19, 19, 19, 22, 22, 22, 25, 25, 25, 25, 29, 29, 29, 32,
- 32, 32, 35, 35, 35, 38, 38, 38, 38, 42, 42, 42, 45, 45, 45, 48,
- 48, 48, 51, 51, 51, 54, 54, 54, 54, 58, 58, 58, 61, 61, 61, 64,
- 64, 64, 67, 67, 67, 67, 71, 71, 71, 74, 74, 74, 77, 77, 77, 80,
- 80, 80, 83, 83, 83, 83, 87, 87, 87, 90, 90, 90, 93, 93, 93, 96,
- 96, 96, 96, 100, 100, 100, 103, 103, 103, 106, 106, 106, 109, 109, 109, 112,
- 112, 112, 112, 116, 116, 116, 119, 119, 119, 122, 122, 122, 125, 125, 125, 125,
- 130, 130, 130, 130, 133, 133, 133, 136, 136, 136, 139, 139, 139, 143, 143, 143,
- 143, 146, 146, 146, 149, 149, 149, 152, 152, 152, 155, 155, 155, 159, 159, 159,
- 159, 162, 162, 162, 165, 165, 165, 168, 168, 168, 172, 172, 172, 172, 175, 175,
- 175, 178, 178, 178, 181, 181, 181, 184, 184, 184, 188, 188, 188, 188, 191, 191,
- 191, 194, 194, 194, 197, 197, 197, 201, 201, 201, 201, 204, 204, 204, 207, 207,
- 207, 210, 210, 210, 213, 213, 213, 217, 217, 217, 217, 220, 220, 220, 223, 223,
- 223, 226, 226, 226, 230, 230, 230, 230, 233, 233, 233, 236, 236, 236, 239, 239,
- 239, 242, 242, 242, 246, 246, 246, 246, 249, 249, 249, 252, 252, 252, 255, 255
- },
- {
- 0, 0, 2, 2, 5, 5, 5, 8, 8, 8, 10, 10, 13, 13, 13, 16,
- 16, 16, 18, 18, 21, 21, 21, 24, 24, 24, 26, 26, 29, 29, 29, 32,
- 32, 32, 35, 35, 35, 37, 37, 40, 40, 40, 43, 43, 43, 45, 45, 48,
- 48, 48, 51, 51, 51, 53, 53, 56, 56, 56, 59, 59, 59, 61, 61, 64,
- 64, 64, 67, 67, 67, 70, 70, 70, 72, 72, 75, 75, 75, 78, 78, 78,
- 80, 80, 83, 83, 83, 86, 86, 86, 88, 88, 91, 91, 91, 94, 94, 94,
- 96, 96, 99, 99, 99, 102, 102, 102, 104, 104, 107, 107, 107, 110, 110, 110,
- 112, 112, 115, 115, 115, 118, 118, 118, 120, 120, 123, 123, 123, 126, 126, 126,
- 129, 129, 129, 132, 132, 132, 135, 135, 137, 137, 137, 140, 140, 140, 143, 143,
- 145, 145, 145, 148, 148, 148, 151, 151, 153, 153, 153, 156, 156, 156, 159, 159,
- 161, 161, 161, 164, 164, 164, 167, 167, 169, 169, 169, 172, 172, 172, 175, 175,
- 177, 177, 177, 180, 180, 180, 183, 183, 185, 185, 185, 188, 188, 188, 191, 191,
- 191, 194, 194, 196, 196, 196, 199, 199, 199, 202, 202, 204, 204, 204, 207, 207,
- 207, 210, 210, 212, 212, 212, 215, 215, 215, 218, 218, 220, 220, 220, 223, 223,
- 223, 226, 226, 226, 229, 229, 231, 231, 231, 234, 234, 234, 237, 237, 239, 239,
- 239, 242, 242, 242, 245, 245, 247, 247, 247, 250, 250, 250, 253, 253, 255, 255
- },
- {
- 0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14,
- 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 30,
- 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46,
- 48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62,
- 64, 64, 66, 66, 68, 68, 70, 70, 72, 72, 74, 74, 76, 76, 78, 78,
- 80, 80, 82, 82, 84, 84, 86, 86, 88, 88, 90, 90, 92, 92, 94, 94,
- 96, 96, 98, 98, 100, 100, 102, 102, 104, 104, 106, 106, 108, 108, 110, 110,
- 112, 112, 114, 114, 116, 116, 118, 118, 120, 120, 122, 122, 124, 124, 126, 126,
- 129, 129, 131, 131, 133, 133, 135, 135, 137, 137, 139, 139, 141, 141, 143, 143,
- 145, 145, 147, 147, 149, 149, 151, 151, 153, 153, 155, 155, 157, 157, 159, 159,
- 161, 161, 163, 163, 165, 165, 167, 167, 169, 169, 171, 171, 173, 173, 175, 175,
- 177, 177, 179, 179, 181, 181, 183, 183, 185, 185, 187, 187, 189, 189, 191, 191,
- 193, 193, 195, 195, 197, 197, 199, 199, 201, 201, 203, 203, 205, 205, 207, 207,
- 209, 209, 211, 211, 213, 213, 215, 215, 217, 217, 219, 219, 221, 221, 223, 223,
- 225, 225, 227, 227, 229, 229, 231, 231, 233, 233, 235, 235, 237, 237, 239, 239,
- 241, 241, 243, 243, 245, 245, 247, 247, 249, 249, 251, 251, 253, 253, 255, 255
- },
- {
- 0, 1, 1, 3, 4, 4, 6, 6, 8, 9, 9, 11, 12, 12, 14, 14,
- 16, 17, 17, 19, 20, 20, 22, 22, 24, 25, 25, 27, 28, 28, 30, 30,
- 32, 33, 33, 35, 36, 36, 38, 38, 40, 41, 41, 43, 44, 44, 46, 46,
- 48, 49, 49, 51, 52, 52, 54, 54, 56, 57, 57, 59, 60, 60, 62, 62,
- 64, 65, 65, 67, 68, 68, 70, 70, 72, 73, 73, 75, 76, 76, 78, 78,
- 80, 81, 81, 83, 84, 84, 86, 86, 88, 89, 89, 91, 92, 92, 94, 94,
- 96, 97, 97, 99, 100, 100, 102, 102, 104, 105, 105, 107, 108, 108, 110, 110,
- 112, 113, 113, 115, 116, 116, 118, 118, 120, 121, 121, 123, 124, 124, 126, 126,
- 129, 129, 131, 131, 132, 134, 134, 135, 137, 137, 139, 139, 140, 142, 142, 143,
- 145, 145, 147, 147, 148, 150, 150, 151, 153, 153, 155, 155, 156, 158, 158, 159,
- 161, 161, 163, 163, 164, 166, 166, 167, 169, 169, 171, 171, 172, 174, 174, 175,
- 177, 177, 179, 179, 180, 182, 182, 183, 185, 185, 187, 187, 188, 190, 190, 191,
- 193, 193, 195, 195, 196, 198, 198, 199, 201, 201, 203, 203, 204, 206, 206, 207,
- 209, 209, 211, 211, 212, 214, 214, 215, 217, 217, 219, 219, 220, 222, 222, 223,
- 225, 225, 227, 227, 228, 230, 230, 231, 233, 233, 235, 235, 236, 238, 238, 239,
- 241, 241, 243, 243, 244, 246, 246, 247, 249, 249, 251, 251, 252, 254, 254, 255
- },
- {
- 0, 1, 2, 2, 4, 5, 6, 6, 8, 9, 10, 10, 12, 13, 14, 14,
- 16, 17, 18, 18, 20, 21, 22, 22, 24, 25, 26, 26, 28, 29, 30, 30,
- 32, 33, 34, 34, 36, 37, 38, 38, 40, 41, 42, 42, 44, 45, 46, 46,
- 48, 49, 50, 50, 52, 53, 54, 54, 56, 57, 58, 58, 60, 61, 62, 62,
- 64, 65, 66, 66, 68, 69, 70, 70, 72, 73, 74, 74, 76, 77, 78, 78,
- 80, 81, 82, 82, 84, 85, 86, 86, 88, 89, 90, 90, 92, 93, 94, 94,
- 96, 97, 98, 98, 100, 101, 102, 102, 104, 105, 106, 106, 108, 109, 110, 110,
- 112, 113, 114, 114, 116, 117, 118, 118, 120, 121, 122, 122, 124, 125, 126, 126,
- 129, 129, 130, 131, 133, 133, 134, 135, 137, 137, 138, 139, 141, 141, 142, 143,
- 145, 145, 146, 147, 149, 149, 150, 151, 153, 153, 154, 155, 157, 157, 158, 159,
- 161, 161, 162, 163, 165, 165, 166, 167, 169, 169, 170, 171, 173, 173, 174, 175,
- 177, 177, 178, 179, 181, 181, 182, 183, 185, 185, 186, 187, 189, 189, 190, 191,
- 193, 193, 194, 195, 197, 197, 198, 199, 201, 201, 202, 203, 205, 205, 206, 207,
- 209, 209, 210, 211, 213, 213, 214, 215, 217, 217, 218, 219, 221, 221, 222, 223,
- 225, 225, 226, 227, 229, 229, 230, 231, 233, 233, 234, 235, 237, 237, 238, 239,
- 241, 241, 242, 243, 245, 245, 246, 247, 249, 249, 250, 251, 253, 253, 254, 255
- },
- {
- 0, 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, 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, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
- 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
- 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
- 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
- 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
- }
+// Not scrambled, starts from QUANT_6
+const uint8_t color_unquant_to_uquant_tables[17][512] {
+ { // QUANT_6
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
+ 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
+ 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
+ 153, 153, 153, 153, 153, 153, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
+ },
+ { // QUANT_8
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 109, 109, 109, 109, 109, 109, 109, 109, 109,
+ 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109,
+ 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109,
+ 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
+ 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
+ 146, 146, 146, 146, 146, 146, 146, 146, 146, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
+ 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
+ 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
+ },
+ { // QUANT_10
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
+ 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 171, 171, 171, 171, 171, 171,
+ 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171,
+ 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
+ 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
+ 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227,
+ 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227,
+ 227, 227, 227, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
+ },
+ { // QUANT_12
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
+ 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
+ 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 186, 186,
+ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
+ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
+ },
+ { // QUANT_16
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
+ 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
+ 136, 136, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
+ 153, 153, 153, 153, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
+ 170, 170, 170, 170, 170, 170, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ 187, 187, 187, 187, 187, 187, 187, 187, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
+ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
+ },
+ { // QUANT_20
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
+ 107, 107, 107, 107, 107, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
+ 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 148, 148, 148, 148, 148,
+ 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188,
+ 188, 188, 188, 188, 188, 188, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
+ 201, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 228, 228, 228, 228,
+ 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 242, 242, 242, 242, 242, 242, 242, 242, 242,
+ 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
+ },
+ { // QUANT_24
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
+ 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 178, 178, 178, 178, 178, 178,
+ 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189,
+ 189, 189, 189, 189, 189, 189, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 211, 211, 211, 211,
+ 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222,
+ 222, 222, 222, 222, 222, 222, 222, 222, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 244, 244,
+ 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
+ },
+ { // QUANT_32
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 82, 82, 82,
+ 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 115,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
+ 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
+ 173, 173, 173, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189,
+ 189, 189, 189, 189, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222,
+ 222, 222, 222, 222, 222, 222, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 239, 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255
+ },
+ { // QUANT_40
+ 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
+ 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 145, 145, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
+ 158, 158, 158, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 177, 177, 177,
+ 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 190, 190, 190, 190, 190, 190, 190, 190, 190,
+ 190, 190, 190, 190, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 210, 210,
+ 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 223, 223, 223, 223, 223, 223, 223, 223,
+ 223, 223, 223, 223, 223, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 242,
+ 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 255, 255, 255, 255, 255, 255, 255
+ },
+ { // QUANT_48
+ 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 113, 113,
+ 113, 113, 113, 113, 113, 113, 113, 113, 113, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 158, 158, 158, 158, 158, 158, 158, 158, 158,
+ 158, 158, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 190, 190, 190, 190, 190, 190, 190, 190,
+ 190, 190, 190, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 223, 223, 223, 223, 223, 223, 223,
+ 223, 223, 223, 223, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 255, 255, 255, 255, 255, 255
+ },
+ { // QUANT_64
+ 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16,
+ 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 24, 24, 24, 24, 24, 24, 24, 24, 28, 28, 28, 28, 28, 28, 28, 28, 32, 32, 32,
+ 32, 32, 32, 32, 32, 36, 36, 36, 36, 36, 36, 36, 36, 40, 40, 40, 40, 40, 40, 40, 40, 44, 44, 44, 44, 44, 44, 44, 44, 48, 48, 48,
+ 48, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 56, 56, 56, 56, 56, 56, 56, 56, 60, 60, 60, 60, 60, 60, 60, 60, 60, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 69, 69, 69, 69, 69, 69, 69, 69, 73, 73, 73, 73, 73, 73, 73, 73, 77, 77, 77, 77, 77, 77, 77, 77, 81,
+ 81, 81, 81, 81, 81, 81, 81, 85, 85, 85, 85, 85, 85, 85, 85, 89, 89, 89, 89, 89, 89, 89, 89, 93, 93, 93, 93, 93, 93, 93, 93, 97,
+ 97, 97, 97, 97, 97, 97, 97, 101, 101, 101, 101, 101, 101, 101, 101, 105, 105, 105, 105, 105, 105, 105, 105, 109, 109, 109, 109, 109, 109, 109, 109, 113,
+ 113, 113, 113, 113, 113, 113, 113, 117, 117, 117, 117, 117, 117, 117, 117, 121, 121, 121, 121, 121, 121, 121, 121, 125, 125, 125, 125, 125, 125, 125, 125, 125,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 134, 134, 134, 134, 134, 134, 134, 134, 138, 138, 138, 138, 138, 138, 138, 138, 142, 142, 142, 142, 142, 142, 142,
+ 142, 146, 146, 146, 146, 146, 146, 146, 146, 150, 150, 150, 150, 150, 150, 150, 150, 154, 154, 154, 154, 154, 154, 154, 154, 158, 158, 158, 158, 158, 158, 158,
+ 158, 162, 162, 162, 162, 162, 162, 162, 162, 166, 166, 166, 166, 166, 166, 166, 166, 170, 170, 170, 170, 170, 170, 170, 170, 174, 174, 174, 174, 174, 174, 174,
+ 174, 178, 178, 178, 178, 178, 178, 178, 178, 182, 182, 182, 182, 182, 182, 182, 182, 186, 186, 186, 186, 186, 186, 186, 186, 190, 190, 190, 190, 190, 190, 190,
+ 190, 190, 195, 195, 195, 195, 195, 195, 195, 195, 195, 199, 199, 199, 199, 199, 199, 199, 199, 203, 203, 203, 203, 203, 203, 203, 203, 207, 207, 207, 207, 207,
+ 207, 207, 207, 211, 211, 211, 211, 211, 211, 211, 211, 215, 215, 215, 215, 215, 215, 215, 215, 219, 219, 219, 219, 219, 219, 219, 219, 223, 223, 223, 223, 223,
+ 223, 223, 223, 227, 227, 227, 227, 227, 227, 227, 227, 231, 231, 231, 231, 231, 231, 231, 231, 235, 235, 235, 235, 235, 235, 235, 235, 239, 239, 239, 239, 239,
+ 239, 239, 239, 243, 243, 243, 243, 243, 243, 243, 243, 247, 247, 247, 247, 247, 247, 247, 247, 251, 251, 251, 251, 251, 251, 251, 251, 255, 255, 255, 255, 255
+ },
+ { // QUANT_80
+ 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 9, 9, 9, 9, 9, 9, 9, 13, 13, 13, 13, 13, 13, 13, 16, 16,
+ 16, 16, 16, 16, 19, 19, 19, 19, 19, 19, 22, 22, 22, 22, 22, 22, 25, 25, 25, 25, 25, 25, 25, 29, 29, 29, 29, 29, 29, 29, 32, 32,
+ 32, 32, 32, 32, 35, 35, 35, 35, 35, 35, 38, 38, 38, 38, 38, 38, 38, 42, 42, 42, 42, 42, 42, 42, 45, 45, 45, 45, 45, 45, 48, 48,
+ 48, 48, 48, 48, 51, 51, 51, 51, 51, 51, 54, 54, 54, 54, 54, 54, 54, 58, 58, 58, 58, 58, 58, 58, 61, 61, 61, 61, 61, 61, 64, 64,
+ 64, 64, 64, 64, 67, 67, 67, 67, 67, 67, 67, 71, 71, 71, 71, 71, 71, 71, 74, 74, 74, 74, 74, 74, 77, 77, 77, 77, 77, 77, 80, 80,
+ 80, 80, 80, 80, 83, 83, 83, 83, 83, 83, 83, 87, 87, 87, 87, 87, 87, 87, 90, 90, 90, 90, 90, 90, 93, 93, 93, 93, 93, 93, 96, 96,
+ 96, 96, 96, 96, 96, 100, 100, 100, 100, 100, 100, 100, 103, 103, 103, 103, 103, 103, 106, 106, 106, 106, 106, 106, 109, 109, 109, 109, 109, 109, 112, 112,
+ 112, 112, 112, 112, 112, 116, 116, 116, 116, 116, 116, 116, 119, 119, 119, 119, 119, 119, 122, 122, 122, 122, 122, 122, 125, 125, 125, 125, 125, 125, 125, 125,
+ 130, 130, 130, 130, 130, 130, 130, 130, 133, 133, 133, 133, 133, 133, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 143, 143, 143, 143, 143,
+ 143, 143, 146, 146, 146, 146, 146, 146, 149, 149, 149, 149, 149, 149, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 159, 159, 159, 159, 159,
+ 159, 159, 162, 162, 162, 162, 162, 162, 165, 165, 165, 165, 165, 165, 168, 168, 168, 168, 168, 168, 168, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175,
+ 175, 175, 178, 178, 178, 178, 178, 178, 181, 181, 181, 181, 181, 181, 184, 184, 184, 184, 184, 184, 184, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191,
+ 191, 191, 194, 194, 194, 194, 194, 194, 197, 197, 197, 197, 197, 197, 197, 201, 201, 201, 201, 201, 201, 201, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207,
+ 207, 207, 210, 210, 210, 210, 210, 210, 213, 213, 213, 213, 213, 213, 213, 217, 217, 217, 217, 217, 217, 217, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223,
+ 223, 223, 226, 226, 226, 226, 226, 226, 226, 230, 230, 230, 230, 230, 230, 230, 233, 233, 233, 233, 233, 233, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239,
+ 239, 239, 242, 242, 242, 242, 242, 242, 242, 246, 246, 246, 246, 246, 246, 246, 249, 249, 249, 249, 249, 249, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255
+ },
+ { // QUANT_96
+ 0, 0, 0, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 16, 16,
+ 16, 16, 16, 18, 18, 18, 18, 18, 21, 21, 21, 21, 21, 21, 24, 24, 24, 24, 24, 26, 26, 26, 26, 26, 29, 29, 29, 29, 29, 29, 32, 32,
+ 32, 32, 32, 32, 35, 35, 35, 35, 35, 37, 37, 37, 37, 37, 40, 40, 40, 40, 40, 40, 43, 43, 43, 43, 43, 45, 45, 45, 45, 45, 48, 48,
+ 48, 48, 48, 48, 51, 51, 51, 51, 51, 53, 53, 53, 53, 53, 56, 56, 56, 56, 56, 56, 59, 59, 59, 59, 59, 61, 61, 61, 61, 61, 64, 64,
+ 64, 64, 64, 64, 67, 67, 67, 67, 67, 67, 70, 70, 70, 70, 70, 72, 72, 72, 72, 72, 75, 75, 75, 75, 75, 75, 78, 78, 78, 78, 78, 80,
+ 80, 80, 80, 80, 83, 83, 83, 83, 83, 83, 86, 86, 86, 86, 86, 88, 88, 88, 88, 88, 91, 91, 91, 91, 91, 91, 94, 94, 94, 94, 94, 96,
+ 96, 96, 96, 96, 99, 99, 99, 99, 99, 99, 102, 102, 102, 102, 102, 104, 104, 104, 104, 104, 107, 107, 107, 107, 107, 107, 110, 110, 110, 110, 110, 112,
+ 112, 112, 112, 112, 115, 115, 115, 115, 115, 115, 118, 118, 118, 118, 118, 120, 120, 120, 120, 120, 123, 123, 123, 123, 123, 123, 126, 126, 126, 126, 126, 126,
+ 129, 129, 129, 129, 129, 129, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 137, 137, 137, 137, 137, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143,
+ 143, 145, 145, 145, 145, 145, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 153, 153, 153, 153, 153, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159,
+ 159, 161, 161, 161, 161, 161, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 169, 169, 169, 169, 169, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175,
+ 175, 177, 177, 177, 177, 177, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 185, 185, 185, 185, 185, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191,
+ 191, 191, 194, 194, 194, 194, 194, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 202, 202, 202, 202, 202, 204, 204, 204, 204, 204, 207, 207, 207, 207,
+ 207, 207, 210, 210, 210, 210, 210, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 218, 218, 218, 218, 218, 220, 220, 220, 220, 220, 223, 223, 223, 223,
+ 223, 223, 226, 226, 226, 226, 226, 226, 229, 229, 229, 229, 229, 231, 231, 231, 231, 231, 234, 234, 234, 234, 234, 234, 237, 237, 237, 237, 237, 239, 239, 239,
+ 239, 239, 242, 242, 242, 242, 242, 242, 245, 245, 245, 245, 245, 247, 247, 247, 247, 247, 250, 250, 250, 250, 250, 250, 253, 253, 253, 253, 253, 255, 255, 255
+ },
+ { // QUANT_128
+ 0, 0, 0, 2, 2, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, 14, 14, 16,
+ 16, 16, 16, 18, 18, 18, 18, 20, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 24, 26, 26, 26, 26, 28, 28, 28, 28, 30, 30, 30, 30, 32,
+ 32, 32, 32, 34, 34, 34, 34, 36, 36, 36, 36, 38, 38, 38, 38, 40, 40, 40, 40, 42, 42, 42, 42, 44, 44, 44, 44, 46, 46, 46, 46, 48,
+ 48, 48, 48, 50, 50, 50, 50, 52, 52, 52, 52, 54, 54, 54, 54, 56, 56, 56, 56, 58, 58, 58, 58, 60, 60, 60, 60, 62, 62, 62, 62, 64,
+ 64, 64, 64, 66, 66, 66, 66, 68, 68, 68, 68, 70, 70, 70, 70, 72, 72, 72, 72, 74, 74, 74, 74, 76, 76, 76, 76, 78, 78, 78, 78, 80,
+ 80, 80, 80, 82, 82, 82, 82, 84, 84, 84, 84, 86, 86, 86, 86, 88, 88, 88, 88, 90, 90, 90, 90, 92, 92, 92, 92, 94, 94, 94, 94, 96,
+ 96, 96, 96, 98, 98, 98, 98, 100, 100, 100, 100, 102, 102, 102, 102, 104, 104, 104, 104, 106, 106, 106, 106, 108, 108, 108, 108, 110, 110, 110, 110, 112,
+ 112, 112, 112, 114, 114, 114, 114, 116, 116, 116, 116, 118, 118, 118, 118, 120, 120, 120, 120, 122, 122, 122, 122, 124, 124, 124, 124, 126, 126, 126, 126, 126,
+ 129, 129, 129, 129, 129, 131, 131, 131, 131, 133, 133, 133, 133, 135, 135, 135, 135, 137, 137, 137, 137, 139, 139, 139, 139, 141, 141, 141, 141, 143, 143, 143,
+ 143, 145, 145, 145, 145, 147, 147, 147, 147, 149, 149, 149, 149, 151, 151, 151, 151, 153, 153, 153, 153, 155, 155, 155, 155, 157, 157, 157, 157, 159, 159, 159,
+ 159, 161, 161, 161, 161, 163, 163, 163, 163, 165, 165, 165, 165, 167, 167, 167, 167, 169, 169, 169, 169, 171, 171, 171, 171, 173, 173, 173, 173, 175, 175, 175,
+ 175, 177, 177, 177, 177, 179, 179, 179, 179, 181, 181, 181, 181, 183, 183, 183, 183, 185, 185, 185, 185, 187, 187, 187, 187, 189, 189, 189, 189, 191, 191, 191,
+ 191, 193, 193, 193, 193, 195, 195, 195, 195, 197, 197, 197, 197, 199, 199, 199, 199, 201, 201, 201, 201, 203, 203, 203, 203, 205, 205, 205, 205, 207, 207, 207,
+ 207, 209, 209, 209, 209, 211, 211, 211, 211, 213, 213, 213, 213, 215, 215, 215, 215, 217, 217, 217, 217, 219, 219, 219, 219, 221, 221, 221, 221, 223, 223, 223,
+ 223, 225, 225, 225, 225, 227, 227, 227, 227, 229, 229, 229, 229, 231, 231, 231, 231, 233, 233, 233, 233, 235, 235, 235, 235, 237, 237, 237, 237, 239, 239, 239,
+ 239, 241, 241, 241, 241, 243, 243, 243, 243, 245, 245, 245, 245, 247, 247, 247, 247, 249, 249, 249, 249, 251, 251, 251, 251, 253, 253, 253, 253, 255, 255, 255
+ },
+ { // QUANT_160
+ 0, 0, 1, 1, 1, 3, 3, 3, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 9, 9, 9, 11, 11, 11, 12, 12, 12, 14, 14, 14, 14, 16,
+ 16, 16, 17, 17, 17, 19, 19, 19, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 25, 25, 25, 27, 27, 27, 28, 28, 28, 30, 30, 30, 30, 32,
+ 32, 32, 33, 33, 33, 35, 35, 35, 36, 36, 36, 38, 38, 38, 38, 40, 40, 40, 41, 41, 41, 43, 43, 43, 44, 44, 44, 46, 46, 46, 46, 48,
+ 48, 48, 49, 49, 49, 51, 51, 51, 52, 52, 52, 54, 54, 54, 54, 56, 56, 56, 57, 57, 57, 59, 59, 59, 60, 60, 60, 62, 62, 62, 62, 64,
+ 64, 64, 65, 65, 65, 67, 67, 67, 68, 68, 68, 70, 70, 70, 70, 72, 72, 72, 73, 73, 73, 75, 75, 75, 76, 76, 76, 78, 78, 78, 78, 80,
+ 80, 80, 81, 81, 81, 83, 83, 83, 84, 84, 84, 86, 86, 86, 86, 88, 88, 88, 89, 89, 89, 91, 91, 91, 92, 92, 92, 94, 94, 94, 94, 96,
+ 96, 96, 97, 97, 97, 99, 99, 99, 100, 100, 100, 102, 102, 102, 102, 104, 104, 104, 105, 105, 105, 107, 107, 107, 108, 108, 108, 110, 110, 110, 110, 112,
+ 112, 112, 113, 113, 113, 115, 115, 115, 116, 116, 116, 118, 118, 118, 118, 120, 120, 120, 121, 121, 121, 123, 123, 123, 124, 124, 124, 126, 126, 126, 126, 126,
+ 129, 129, 129, 129, 129, 131, 131, 131, 132, 132, 132, 134, 134, 134, 135, 135, 135, 137, 137, 137, 137, 139, 139, 139, 140, 140, 140, 142, 142, 142, 143, 143,
+ 143, 145, 145, 145, 145, 147, 147, 147, 148, 148, 148, 150, 150, 150, 151, 151, 151, 153, 153, 153, 153, 155, 155, 155, 156, 156, 156, 158, 158, 158, 159, 159,
+ 159, 161, 161, 161, 161, 163, 163, 163, 164, 164, 164, 166, 166, 166, 167, 167, 167, 169, 169, 169, 169, 171, 171, 171, 172, 172, 172, 174, 174, 174, 175, 175,
+ 175, 177, 177, 177, 177, 179, 179, 179, 180, 180, 180, 182, 182, 182, 183, 183, 183, 185, 185, 185, 185, 187, 187, 187, 188, 188, 188, 190, 190, 190, 191, 191,
+ 191, 193, 193, 193, 193, 195, 195, 195, 196, 196, 196, 198, 198, 198, 199, 199, 199, 201, 201, 201, 201, 203, 203, 203, 204, 204, 204, 206, 206, 206, 207, 207,
+ 207, 209, 209, 209, 209, 211, 211, 211, 212, 212, 212, 214, 214, 214, 215, 215, 215, 217, 217, 217, 217, 219, 219, 219, 220, 220, 220, 222, 222, 222, 223, 223,
+ 223, 225, 225, 225, 225, 227, 227, 227, 228, 228, 228, 230, 230, 230, 231, 231, 231, 233, 233, 233, 233, 235, 235, 235, 236, 236, 236, 238, 238, 238, 239, 239,
+ 239, 241, 241, 241, 241, 243, 243, 243, 244, 244, 244, 246, 246, 246, 247, 247, 247, 249, 249, 249, 249, 251, 251, 251, 252, 252, 252, 254, 254, 254, 255, 255
+ },
+ { // QUANT_192
+ 0, 0, 1, 1, 2, 2, 2, 4, 4, 4, 5, 5, 6, 6, 6, 8, 8, 8, 9, 9, 10, 10, 10, 12, 12, 12, 13, 13, 14, 14, 14, 16,
+ 16, 16, 17, 17, 18, 18, 18, 20, 20, 20, 21, 21, 22, 22, 22, 24, 24, 24, 25, 25, 26, 26, 26, 28, 28, 28, 29, 29, 30, 30, 30, 32,
+ 32, 32, 33, 33, 34, 34, 34, 36, 36, 36, 37, 37, 38, 38, 38, 40, 40, 40, 41, 41, 42, 42, 42, 44, 44, 44, 45, 45, 46, 46, 46, 48,
+ 48, 48, 49, 49, 50, 50, 50, 52, 52, 52, 53, 53, 54, 54, 54, 56, 56, 56, 57, 57, 58, 58, 58, 60, 60, 60, 61, 61, 62, 62, 62, 64,
+ 64, 64, 65, 65, 66, 66, 66, 68, 68, 68, 69, 69, 70, 70, 70, 72, 72, 72, 73, 73, 74, 74, 74, 76, 76, 76, 77, 77, 78, 78, 78, 80,
+ 80, 80, 81, 81, 82, 82, 82, 84, 84, 84, 85, 85, 86, 86, 86, 88, 88, 88, 89, 89, 90, 90, 90, 92, 92, 92, 93, 93, 94, 94, 94, 96,
+ 96, 96, 97, 97, 98, 98, 98, 100, 100, 100, 101, 101, 102, 102, 102, 104, 104, 104, 105, 105, 106, 106, 106, 108, 108, 108, 109, 109, 110, 110, 110, 112,
+ 112, 112, 113, 113, 114, 114, 114, 116, 116, 116, 117, 117, 118, 118, 118, 120, 120, 120, 121, 121, 122, 122, 122, 124, 124, 124, 125, 125, 126, 126, 126, 126,
+ 129, 129, 129, 129, 130, 130, 131, 131, 131, 133, 133, 133, 134, 134, 135, 135, 135, 137, 137, 137, 138, 138, 139, 139, 139, 141, 141, 141, 142, 142, 143, 143,
+ 143, 145, 145, 145, 146, 146, 147, 147, 147, 149, 149, 149, 150, 150, 151, 151, 151, 153, 153, 153, 154, 154, 155, 155, 155, 157, 157, 157, 158, 158, 159, 159,
+ 159, 161, 161, 161, 162, 162, 163, 163, 163, 165, 165, 165, 166, 166, 167, 167, 167, 169, 169, 169, 170, 170, 171, 171, 171, 173, 173, 173, 174, 174, 175, 175,
+ 175, 177, 177, 177, 178, 178, 179, 179, 179, 181, 181, 181, 182, 182, 183, 183, 183, 185, 185, 185, 186, 186, 187, 187, 187, 189, 189, 189, 190, 190, 191, 191,
+ 191, 193, 193, 193, 194, 194, 195, 195, 195, 197, 197, 197, 198, 198, 199, 199, 199, 201, 201, 201, 202, 202, 203, 203, 203, 205, 205, 205, 206, 206, 207, 207,
+ 207, 209, 209, 209, 210, 210, 211, 211, 211, 213, 213, 213, 214, 214, 215, 215, 215, 217, 217, 217, 218, 218, 219, 219, 219, 221, 221, 221, 222, 222, 223, 223,
+ 223, 225, 225, 225, 226, 226, 227, 227, 227, 229, 229, 229, 230, 230, 231, 231, 231, 233, 233, 233, 234, 234, 235, 235, 235, 237, 237, 237, 238, 238, 239, 239,
+ 239, 241, 241, 241, 242, 242, 243, 243, 243, 245, 245, 245, 246, 246, 247, 247, 247, 249, 249, 249, 250, 250, 251, 251, 251, 253, 253, 253, 254, 254, 255, 255
+ },
+ { // QUANT_256
+ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15,
+ 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
+ 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47,
+ 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63,
+ 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79,
+ 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91, 92, 92, 93, 93, 94, 94, 95, 95,
+ 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111,
+ 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 127, 127,
+ 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 133, 134, 134, 135, 135, 136, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141, 142, 142, 143, 143,
+ 144, 144, 145, 145, 146, 146, 147, 147, 148, 148, 149, 149, 150, 150, 151, 151, 152, 152, 153, 153, 154, 154, 155, 155, 156, 156, 157, 157, 158, 158, 159, 159,
+ 160, 160, 161, 161, 162, 162, 163, 163, 164, 164, 165, 165, 166, 166, 167, 167, 168, 168, 169, 169, 170, 170, 171, 171, 172, 172, 173, 173, 174, 174, 175, 175,
+ 176, 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, 181, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186, 187, 187, 188, 188, 189, 189, 190, 190, 191, 191,
+ 192, 192, 193, 193, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 206, 207, 207,
+ 208, 208, 209, 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223,
+ 224, 224, 225, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 239,
+ 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255
+ },
};
// Starts from QUANT_6
// Scrambled
const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
- {
+ { // QUANT_6
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -355,13 +354,13 @@ const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
},
- {
+ { // QUANT_8
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
@@ -373,35 +372,35 @@ const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
},
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ { // QUANT_10
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
},
- {
+ { // QUANT_12
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 10, 10, 10, 10, 10, 10, 10,
+ 6, 6, 6, 6, 6, 6, 6, 6, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 11, 11, 11, 11, 11, 11, 11, 11, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
@@ -409,7 +408,7 @@ const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
},
- {
+ { // QUANT_16
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
@@ -427,25 +426,25 @@ const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15
},
- {
+ { // QUANT_20
0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 10, 10, 10, 10, 10, 10, 10, 10,
+ 6, 6, 6, 6, 6, 6, 6, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 15, 15, 15,
+ 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 7, 7, 7, 7, 7, 7, 7, 7,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5,
+ 17, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1
},
- {
+ { // QUANT_24
0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10,
@@ -463,15 +462,15 @@ const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
3, 3, 3, 3, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1
},
- {
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
- 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
- 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10,
- 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13,
- 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ { // QUANT_32
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
+ 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
+ 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
+ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8,
+ 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10,
+ 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12,
+ 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14,
+ 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15,
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,
18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19,
19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21,
@@ -481,51 +480,51 @@ const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29,
29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31
},
- {
- 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16,
- 16, 24, 24, 24, 24, 24, 24, 32, 32, 32, 32, 32, 32, 32, 2, 2,
- 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 18, 18, 18, 18, 18,
- 18, 26, 26, 26, 26, 26, 26, 26, 34, 34, 34, 34, 34, 34, 4, 4,
- 4, 4, 4, 4, 4, 12, 12, 12, 12, 12, 12, 20, 20, 20, 20, 20,
- 20, 20, 28, 28, 28, 28, 28, 28, 36, 36, 36, 36, 36, 36, 36, 6,
- 6, 6, 6, 6, 6, 14, 14, 14, 14, 14, 14, 14, 22, 22, 22, 22,
- 22, 22, 30, 30, 30, 30, 30, 30, 30, 38, 38, 38, 38, 38, 38, 38,
- 39, 39, 39, 39, 39, 39, 39, 31, 31, 31, 31, 31, 31, 31, 23, 23,
- 23, 23, 23, 23, 15, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7,
- 7, 37, 37, 37, 37, 37, 37, 37, 29, 29, 29, 29, 29, 29, 21, 21,
- 21, 21, 21, 21, 21, 13, 13, 13, 13, 13, 13, 5, 5, 5, 5, 5,
- 5, 5, 35, 35, 35, 35, 35, 35, 27, 27, 27, 27, 27, 27, 27, 19,
- 19, 19, 19, 19, 19, 11, 11, 11, 11, 11, 11, 11, 3, 3, 3, 3,
- 3, 3, 33, 33, 33, 33, 33, 33, 33, 25, 25, 25, 25, 25, 25, 17,
- 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1
- },
- {
- 0, 0, 0, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 2, 2,
- 2, 2, 2, 18, 18, 18, 18, 18, 18, 34, 34, 34, 34, 34, 4, 4,
- 4, 4, 4, 4, 20, 20, 20, 20, 20, 36, 36, 36, 36, 36, 6, 6,
- 6, 6, 6, 6, 22, 22, 22, 22, 22, 38, 38, 38, 38, 38, 38, 8,
- 8, 8, 8, 8, 24, 24, 24, 24, 24, 24, 40, 40, 40, 40, 40, 10,
- 10, 10, 10, 10, 26, 26, 26, 26, 26, 26, 42, 42, 42, 42, 42, 12,
- 12, 12, 12, 12, 12, 28, 28, 28, 28, 28, 44, 44, 44, 44, 44, 14,
- 14, 14, 14, 14, 14, 30, 30, 30, 30, 30, 46, 46, 46, 46, 46, 46,
- 47, 47, 47, 47, 47, 47, 31, 31, 31, 31, 31, 15, 15, 15, 15, 15,
- 15, 45, 45, 45, 45, 45, 29, 29, 29, 29, 29, 13, 13, 13, 13, 13,
- 13, 43, 43, 43, 43, 43, 27, 27, 27, 27, 27, 27, 11, 11, 11, 11,
- 11, 41, 41, 41, 41, 41, 25, 25, 25, 25, 25, 25, 9, 9, 9, 9,
- 9, 39, 39, 39, 39, 39, 39, 23, 23, 23, 23, 23, 7, 7, 7, 7,
- 7, 7, 37, 37, 37, 37, 37, 21, 21, 21, 21, 21, 5, 5, 5, 5,
- 5, 5, 35, 35, 35, 35, 35, 19, 19, 19, 19, 19, 19, 3, 3, 3,
- 3, 3, 33, 33, 33, 33, 33, 17, 17, 17, 17, 17, 17, 1, 1, 1
- },
- {
- 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4,
- 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8,
- 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12,
- 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16,
- 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19,
- 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,
- 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27,
- 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31,
+ { // QUANT_40
+ 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16,
+ 24, 24, 24, 24, 24, 24, 24, 32, 32, 32, 32, 32, 32, 32, 2, 2,
+ 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 18, 18, 18, 18, 18, 18,
+ 18, 26, 26, 26, 26, 26, 26, 34, 34, 34, 34, 34, 34, 34, 4, 4,
+ 4, 4, 4, 4, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 20, 20,
+ 20, 28, 28, 28, 28, 28, 28, 28, 36, 36, 36, 36, 36, 36, 36, 6,
+ 6, 6, 6, 6, 6, 14, 14, 14, 14, 14, 14, 22, 22, 22, 22, 22,
+ 22, 22, 30, 30, 30, 30, 30, 30, 38, 38, 38, 38, 38, 38, 38, 38,
+ 39, 39, 39, 39, 39, 39, 39, 39, 31, 31, 31, 31, 31, 31, 23, 23,
+ 23, 23, 23, 23, 23, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7,
+ 7, 37, 37, 37, 37, 37, 37, 37, 29, 29, 29, 29, 29, 29, 29, 21,
+ 21, 21, 21, 21, 21, 13, 13, 13, 13, 13, 13, 13, 5, 5, 5, 5,
+ 5, 5, 35, 35, 35, 35, 35, 35, 35, 27, 27, 27, 27, 27, 27, 19,
+ 19, 19, 19, 19, 19, 19, 11, 11, 11, 11, 11, 11, 3, 3, 3, 3,
+ 3, 3, 33, 33, 33, 33, 33, 33, 33, 25, 25, 25, 25, 25, 25, 25,
+ 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1
+ },
+ { // QUANT_48
+ 0, 0, 0, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 2, 2,
+ 2, 2, 2, 18, 18, 18, 18, 18, 34, 34, 34, 34, 34, 34, 4, 4,
+ 4, 4, 4, 20, 20, 20, 20, 20, 20, 36, 36, 36, 36, 36, 6, 6,
+ 6, 6, 6, 22, 22, 22, 22, 22, 22, 38, 38, 38, 38, 38, 38, 8,
+ 8, 8, 8, 8, 24, 24, 24, 24, 24, 40, 40, 40, 40, 40, 40, 10,
+ 10, 10, 10, 10, 26, 26, 26, 26, 26, 42, 42, 42, 42, 42, 42, 12,
+ 12, 12, 12, 12, 28, 28, 28, 28, 28, 28, 44, 44, 44, 44, 44, 14,
+ 14, 14, 14, 14, 30, 30, 30, 30, 30, 30, 46, 46, 46, 46, 46, 46,
+ 47, 47, 47, 47, 47, 47, 31, 31, 31, 31, 31, 31, 15, 15, 15, 15,
+ 15, 45, 45, 45, 45, 45, 29, 29, 29, 29, 29, 29, 13, 13, 13, 13,
+ 13, 43, 43, 43, 43, 43, 43, 27, 27, 27, 27, 27, 11, 11, 11, 11,
+ 11, 41, 41, 41, 41, 41, 41, 25, 25, 25, 25, 25, 9, 9, 9, 9,
+ 9, 39, 39, 39, 39, 39, 39, 23, 23, 23, 23, 23, 23, 7, 7, 7,
+ 7, 7, 37, 37, 37, 37, 37, 21, 21, 21, 21, 21, 21, 5, 5, 5,
+ 5, 5, 35, 35, 35, 35, 35, 35, 19, 19, 19, 19, 19, 3, 3, 3,
+ 3, 3, 33, 33, 33, 33, 33, 33, 17, 17, 17, 17, 17, 1, 1, 1
+ },
+ { // QUANT_64
+ 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
+ 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8,
+ 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12,
+ 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16,
+ 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20,
+ 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24,
+ 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28,
+ 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 31,
32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35,
36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39,
40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43,
@@ -535,29 +534,29 @@ const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59,
59, 60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63
},
- {
- 0, 0, 16, 16, 16, 32, 32, 32, 48, 48, 48, 48, 64, 64, 64, 2,
- 2, 2, 18, 18, 18, 34, 34, 34, 50, 50, 50, 50, 66, 66, 66, 4,
- 4, 4, 20, 20, 20, 36, 36, 36, 36, 52, 52, 52, 68, 68, 68, 6,
- 6, 6, 22, 22, 22, 38, 38, 38, 38, 54, 54, 54, 70, 70, 70, 8,
- 8, 8, 24, 24, 24, 24, 40, 40, 40, 56, 56, 56, 72, 72, 72, 10,
- 10, 10, 26, 26, 26, 26, 42, 42, 42, 58, 58, 58, 74, 74, 74, 12,
- 12, 12, 12, 28, 28, 28, 44, 44, 44, 60, 60, 60, 76, 76, 76, 14,
- 14, 14, 14, 30, 30, 30, 46, 46, 46, 62, 62, 62, 78, 78, 78, 78,
- 79, 79, 79, 79, 63, 63, 63, 47, 47, 47, 31, 31, 31, 15, 15, 15,
- 15, 77, 77, 77, 61, 61, 61, 45, 45, 45, 29, 29, 29, 13, 13, 13,
- 13, 75, 75, 75, 59, 59, 59, 43, 43, 43, 27, 27, 27, 27, 11, 11,
- 11, 73, 73, 73, 57, 57, 57, 41, 41, 41, 25, 25, 25, 25, 9, 9,
- 9, 71, 71, 71, 55, 55, 55, 39, 39, 39, 39, 23, 23, 23, 7, 7,
- 7, 69, 69, 69, 53, 53, 53, 37, 37, 37, 37, 21, 21, 21, 5, 5,
- 5, 67, 67, 67, 51, 51, 51, 51, 35, 35, 35, 19, 19, 19, 3, 3,
- 3, 65, 65, 65, 49, 49, 49, 49, 33, 33, 33, 17, 17, 17, 1, 1
- },
- {
- 0, 0, 32, 32, 64, 64, 64, 2, 2, 2, 34, 34, 66, 66, 66, 4,
- 4, 4, 36, 36, 68, 68, 68, 6, 6, 6, 38, 38, 70, 70, 70, 8,
- 8, 8, 40, 40, 40, 72, 72, 10, 10, 10, 42, 42, 42, 74, 74, 12,
- 12, 12, 44, 44, 44, 76, 76, 14, 14, 14, 46, 46, 46, 78, 78, 16,
+ { // QUANT_80
+ 0, 0, 16, 16, 16, 32, 32, 32, 48, 48, 48, 64, 64, 64, 64, 2,
+ 2, 2, 18, 18, 18, 34, 34, 34, 50, 50, 50, 66, 66, 66, 66, 4,
+ 4, 4, 20, 20, 20, 36, 36, 36, 52, 52, 52, 52, 68, 68, 68, 6,
+ 6, 6, 22, 22, 22, 38, 38, 38, 54, 54, 54, 54, 70, 70, 70, 8,
+ 8, 8, 24, 24, 24, 40, 40, 40, 40, 56, 56, 56, 72, 72, 72, 10,
+ 10, 10, 26, 26, 26, 42, 42, 42, 42, 58, 58, 58, 74, 74, 74, 12,
+ 12, 12, 28, 28, 28, 28, 44, 44, 44, 60, 60, 60, 76, 76, 76, 14,
+ 14, 14, 30, 30, 30, 30, 46, 46, 46, 62, 62, 62, 78, 78, 78, 78,
+ 79, 79, 79, 79, 63, 63, 63, 47, 47, 47, 31, 31, 31, 31, 15, 15,
+ 15, 77, 77, 77, 61, 61, 61, 45, 45, 45, 29, 29, 29, 29, 13, 13,
+ 13, 75, 75, 75, 59, 59, 59, 43, 43, 43, 43, 27, 27, 27, 11, 11,
+ 11, 73, 73, 73, 57, 57, 57, 41, 41, 41, 41, 25, 25, 25, 9, 9,
+ 9, 71, 71, 71, 55, 55, 55, 55, 39, 39, 39, 23, 23, 23, 7, 7,
+ 7, 69, 69, 69, 53, 53, 53, 53, 37, 37, 37, 21, 21, 21, 5, 5,
+ 5, 67, 67, 67, 67, 51, 51, 51, 35, 35, 35, 19, 19, 19, 3, 3,
+ 3, 65, 65, 65, 65, 49, 49, 49, 33, 33, 33, 17, 17, 17, 1, 1
+ },
+ { // QUANT_96
+ 0, 32, 32, 32, 64, 64, 64, 2, 2, 34, 34, 34, 66, 66, 66, 4,
+ 4, 36, 36, 36, 68, 68, 68, 6, 6, 38, 38, 38, 70, 70, 70, 8,
+ 8, 8, 40, 40, 72, 72, 72, 10, 10, 10, 42, 42, 74, 74, 74, 12,
+ 12, 12, 44, 44, 76, 76, 76, 14, 14, 14, 46, 46, 78, 78, 78, 16,
16, 16, 48, 48, 48, 80, 80, 80, 18, 18, 50, 50, 50, 82, 82, 82,
20, 20, 52, 52, 52, 84, 84, 84, 22, 22, 54, 54, 54, 86, 86, 86,
24, 24, 56, 56, 56, 88, 88, 88, 26, 26, 58, 58, 58, 90, 90, 90,
@@ -566,20 +565,20 @@ const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
91, 91, 91, 59, 59, 59, 27, 27, 89, 89, 89, 57, 57, 57, 25, 25,
87, 87, 87, 55, 55, 55, 23, 23, 85, 85, 85, 53, 53, 53, 21, 21,
83, 83, 83, 51, 51, 51, 19, 19, 81, 81, 81, 49, 49, 49, 17, 17,
- 17, 79, 79, 47, 47, 47, 15, 15, 15, 77, 77, 45, 45, 45, 13, 13,
- 13, 75, 75, 43, 43, 43, 11, 11, 11, 73, 73, 41, 41, 41, 9, 9,
- 9, 71, 71, 71, 39, 39, 7, 7, 7, 69, 69, 69, 37, 37, 5, 5,
- 5, 67, 67, 67, 35, 35, 3, 3, 3, 65, 65, 65, 33, 33, 1, 1
- },
- {
- 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
- 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15,
- 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
- 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
- 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
- 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47,
- 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55,
- 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63,
+ 17, 79, 79, 79, 47, 47, 15, 15, 15, 77, 77, 77, 45, 45, 13, 13,
+ 13, 75, 75, 75, 43, 43, 11, 11, 11, 73, 73, 73, 41, 41, 9, 9,
+ 9, 71, 71, 71, 39, 39, 39, 7, 7, 69, 69, 69, 37, 37, 37, 5,
+ 5, 67, 67, 67, 35, 35, 35, 3, 3, 65, 65, 65, 33, 33, 33, 1
+ },
+ { // QUANT_128
+ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
+ 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,
+ 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24,
+ 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32,
+ 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40,
+ 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48,
+ 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56,
+ 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 63,
64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71,
72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79,
80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87,
@@ -589,25 +588,25 @@ const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119,
120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 127, 127
},
- {
- 0, 32, 32, 64, 96, 96, 128, 128, 2, 34, 34, 66, 98, 98, 130, 130,
- 4, 36, 36, 68, 100, 100, 132, 132, 6, 38, 38, 70, 102, 102, 134, 134,
- 8, 40, 40, 72, 104, 104, 136, 136, 10, 42, 42, 74, 106, 106, 138, 138,
- 12, 44, 44, 76, 108, 108, 140, 140, 14, 46, 46, 78, 110, 110, 142, 142,
- 16, 48, 48, 80, 112, 112, 144, 144, 18, 50, 50, 82, 114, 114, 146, 146,
- 20, 52, 52, 84, 116, 116, 148, 148, 22, 54, 54, 86, 118, 118, 150, 150,
- 24, 56, 56, 88, 120, 120, 152, 152, 26, 58, 58, 90, 122, 122, 154, 154,
- 28, 60, 60, 92, 124, 124, 156, 156, 30, 62, 62, 94, 126, 126, 158, 158,
- 159, 159, 127, 127, 95, 63, 63, 31, 157, 157, 125, 125, 93, 61, 61, 29,
- 155, 155, 123, 123, 91, 59, 59, 27, 153, 153, 121, 121, 89, 57, 57, 25,
- 151, 151, 119, 119, 87, 55, 55, 23, 149, 149, 117, 117, 85, 53, 53, 21,
- 147, 147, 115, 115, 83, 51, 51, 19, 145, 145, 113, 113, 81, 49, 49, 17,
- 143, 143, 111, 111, 79, 47, 47, 15, 141, 141, 109, 109, 77, 45, 45, 13,
- 139, 139, 107, 107, 75, 43, 43, 11, 137, 137, 105, 105, 73, 41, 41, 9,
- 135, 135, 103, 103, 71, 39, 39, 7, 133, 133, 101, 101, 69, 37, 37, 5,
- 131, 131, 99, 99, 67, 35, 35, 3, 129, 129, 97, 97, 65, 33, 33, 1
- },
- {
+ { // QUANT_160
+ 0, 32, 64, 64, 96, 128, 128, 128, 2, 34, 66, 66, 98, 130, 130, 130,
+ 4, 36, 68, 68, 100, 132, 132, 132, 6, 38, 70, 70, 102, 134, 134, 134,
+ 8, 40, 72, 72, 104, 136, 136, 136, 10, 42, 74, 74, 106, 138, 138, 138,
+ 12, 44, 76, 76, 108, 140, 140, 140, 14, 46, 78, 78, 110, 142, 142, 142,
+ 16, 48, 80, 80, 112, 144, 144, 144, 18, 50, 82, 82, 114, 146, 146, 146,
+ 20, 52, 84, 84, 116, 148, 148, 148, 22, 54, 86, 86, 118, 150, 150, 150,
+ 24, 56, 88, 88, 120, 152, 152, 152, 26, 58, 90, 90, 122, 154, 154, 154,
+ 28, 60, 92, 92, 124, 156, 156, 156, 30, 62, 94, 94, 126, 158, 158, 158,
+ 159, 159, 159, 127, 95, 95, 63, 31, 157, 157, 157, 125, 93, 93, 61, 29,
+ 155, 155, 155, 123, 91, 91, 59, 27, 153, 153, 153, 121, 89, 89, 57, 25,
+ 151, 151, 151, 119, 87, 87, 55, 23, 149, 149, 149, 117, 85, 85, 53, 21,
+ 147, 147, 147, 115, 83, 83, 51, 19, 145, 145, 145, 113, 81, 81, 49, 17,
+ 143, 143, 143, 111, 79, 79, 47, 15, 141, 141, 141, 109, 77, 77, 45, 13,
+ 139, 139, 139, 107, 75, 75, 43, 11, 137, 137, 137, 105, 73, 73, 41, 9,
+ 135, 135, 135, 103, 71, 71, 39, 7, 133, 133, 133, 101, 69, 69, 37, 5,
+ 131, 131, 131, 99, 67, 67, 35, 3, 129, 129, 129, 97, 65, 65, 33, 1
+ },
+ { // QUANT_192
0, 64, 128, 128, 2, 66, 130, 130, 4, 68, 132, 132, 6, 70, 134, 134,
8, 72, 136, 136, 10, 74, 138, 138, 12, 76, 140, 140, 14, 78, 142, 142,
16, 80, 144, 144, 18, 82, 146, 146, 20, 84, 148, 148, 22, 86, 150, 150,
@@ -625,7 +624,7 @@ const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] {
143, 143, 79, 15, 141, 141, 77, 13, 139, 139, 75, 11, 137, 137, 73, 9,
135, 135, 71, 7, 133, 133, 69, 5, 131, 131, 67, 3, 129, 129, 65, 1
},
- {
+ { // QUANT_256
0, 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, 43, 44, 45, 46, 47,
diff --git a/thirdparty/astcenc/astcenc_symbolic_physical.cpp b/thirdparty/astcenc/astcenc_symbolic_physical.cpp
index 80221a6013..49a8a1504b 100644
--- a/thirdparty/astcenc/astcenc_symbolic_physical.cpp
+++ b/thirdparty/astcenc/astcenc_symbolic_physical.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
-// Copyright 2011-2021 Arm Limited
+// Copyright 2011-2023 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
@@ -24,36 +24,21 @@
#include <cassert>
/**
- * @brief Write up to 8 bits at an arbitrary bit offset.
- *
- * The stored value is at most 8 bits, but can be stored at an offset of between 0 and 7 bits so
- * may span two separate bytes in memory.
+ * @brief Reverse bits in a byte.
*
- * @param value The value to write.
- * @param bitcount The number of bits to write, starting from LSB.
- * @param bitoffset The bit offset to store at, between 0 and 7.
- * @param[in,out] ptr The data pointer to write to.
+ * @param p The value to reverse.
+ *
+ * @return The reversed result.
*/
-static inline void write_bits(
- int value,
- int bitcount,
- int bitoffset,
- uint8_t* ptr
-) {
- int mask = (1 << bitcount) - 1;
- value &= mask;
- ptr += bitoffset >> 3;
- bitoffset &= 7;
- value <<= bitoffset;
- mask <<= bitoffset;
- mask = ~mask;
-
- ptr[0] &= mask;
- ptr[0] |= value;
- ptr[1] &= mask >> 8;
- ptr[1] |= value >> 8;
+static inline int bitrev8(int p)
+{
+ p = ((p & 0x0F) << 4) | ((p >> 4) & 0x0F);
+ p = ((p & 0x33) << 2) | ((p >> 2) & 0x33);
+ p = ((p & 0x55) << 1) | ((p >> 1) & 0x55);
+ return p;
}
+
/**
* @brief Read up to 8 bits at an arbitrary bit offset.
*
@@ -80,19 +65,37 @@ static inline int read_bits(
return value;
}
+#if !defined(ASTCENC_DECOMPRESS_ONLY)
+
/**
- * @brief Reverse bits in a byte.
+ * @brief Write up to 8 bits at an arbitrary bit offset.
*
- * @param p The value to reverse.
- *
- * @return The reversed result.
+ * The stored value is at most 8 bits, but can be stored at an offset of between 0 and 7 bits so
+ * may span two separate bytes in memory.
+ *
+ * @param value The value to write.
+ * @param bitcount The number of bits to write, starting from LSB.
+ * @param bitoffset The bit offset to store at, between 0 and 7.
+ * @param[in,out] ptr The data pointer to write to.
*/
-static inline int bitrev8(int p)
-{
- p = ((p & 0x0F) << 4) | ((p >> 4) & 0x0F);
- p = ((p & 0x33) << 2) | ((p >> 2) & 0x33);
- p = ((p & 0x55) << 1) | ((p >> 1) & 0x55);
- return p;
+static inline void write_bits(
+ int value,
+ int bitcount,
+ int bitoffset,
+ uint8_t* ptr
+) {
+ int mask = (1 << bitcount) - 1;
+ value &= mask;
+ ptr += bitoffset >> 3;
+ bitoffset &= 7;
+ value <<= bitoffset;
+ mask <<= bitoffset;
+ mask = ~mask;
+
+ ptr[0] &= mask;
+ ptr[0] |= value;
+ ptr[1] &= mask >> 8;
+ ptr[1] |= value >> 8;
}
/* See header for documentation. */
@@ -282,6 +285,8 @@ void symbolic_to_physical(
scb.partition_count == 1 ? 17 : 19 + PARTITION_INDEX_BITS);
}
+#endif
+
/* See header for documentation. */
void physical_to_symbolic(
const block_size_descriptor& bsd,
diff --git a/thirdparty/astcenc/astcenc_weight_align.cpp b/thirdparty/astcenc/astcenc_weight_align.cpp
index e40a318cf5..aa6ab61fa1 100644
--- a/thirdparty/astcenc/astcenc_weight_align.cpp
+++ b/thirdparty/astcenc/astcenc_weight_align.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
-// Copyright 2011-2022 Arm Limited
+// Copyright 2011-2023 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
@@ -353,7 +353,7 @@ void compute_angular_endpoints_1plane(
for (unsigned int i = 0; i < max_decimation_modes; i++)
{
const decimation_mode& dm = bsd.decimation_modes[i];
- if (!dm.is_ref_1_plane(static_cast<quant_method>(max_weight_quant)))
+ if (!dm.is_ref_1plane(static_cast<quant_method>(max_weight_quant)))
{
continue;
}
@@ -422,7 +422,7 @@ void compute_angular_endpoints_2planes(
for (unsigned int i = 0; i < bsd.decimation_mode_count_selected; i++)
{
const decimation_mode& dm = bsd.decimation_modes[i];
- if (!dm.is_ref_2_plane(static_cast<quant_method>(max_weight_quant)))
+ if (!dm.is_ref_2plane(static_cast<quant_method>(max_weight_quant)))
{
continue;
}
diff --git a/thirdparty/doctest/LICENSE.txt b/thirdparty/doctest/LICENSE.txt
index d67bb64f9d..5ae0eb1052 100644
--- a/thirdparty/doctest/LICENSE.txt
+++ b/thirdparty/doctest/LICENSE.txt
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2016-2021 Viktor Kirilov
+Copyright (c) 2016-2023 Viktor Kirilov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/doctest/doctest.h b/thirdparty/doctest/doctest.h
index aa2724c738..5c754cde08 100644
--- a/thirdparty/doctest/doctest.h
+++ b/thirdparty/doctest/doctest.h
@@ -4,7 +4,7 @@
//
// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
//
-// Copyright (c) 2016-2021 Viktor Kirilov
+// Copyright (c) 2016-2023 Viktor Kirilov
//
// Distributed under the MIT Software License
// See accompanying file LICENSE.txt or copy at
@@ -48,7 +48,7 @@
#define DOCTEST_VERSION_MAJOR 2
#define DOCTEST_VERSION_MINOR 4
-#define DOCTEST_VERSION_PATCH 9
+#define DOCTEST_VERSION_PATCH 11
// util we need here
#define DOCTEST_TOSTR_IMPL(x) #x
@@ -85,12 +85,15 @@
DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000)
#endif // MSVC
#endif // MSVC
-#if defined(__clang__) && defined(__clang_minor__)
+#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
#define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__)
#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \
!defined(__INTEL_COMPILER)
#define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#endif // GCC
+#if defined(__INTEL_COMPILER)
+#define DOCTEST_ICC DOCTEST_COMPILER(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
+#endif // ICC
#ifndef DOCTEST_MSVC
#define DOCTEST_MSVC 0
@@ -101,12 +104,15 @@
#ifndef DOCTEST_GCC
#define DOCTEST_GCC 0
#endif // DOCTEST_GCC
+#ifndef DOCTEST_ICC
+#define DOCTEST_ICC 0
+#endif // DOCTEST_ICC
// =================================================================================================
// == COMPILER WARNINGS HELPERS ====================================================================
// =================================================================================================
-#if DOCTEST_CLANG
+#if DOCTEST_CLANG && !DOCTEST_ICC
#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push")
#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w)
@@ -152,7 +158,7 @@
// =================================================================================================
// both the header and the implementation suppress all of these,
-// so it only makes sense to aggregrate them like so
+// so it only makes sense to aggregate them like so
#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \
@@ -178,7 +184,7 @@
DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \
DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \
DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \
- /* */ \
+ /* common ones */ \
DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \
DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \
DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \
@@ -192,6 +198,7 @@
DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \
DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \
/* static analysis */ \
DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \
DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \
@@ -236,7 +243,8 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define
DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \
DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \
- DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */
+ DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */
#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP
@@ -352,6 +360,12 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define
#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x)))
#endif
+#ifdef DOCTEST_CONFIG_NO_CONTRADICTING_INLINE
+#define DOCTEST_INLINE_NOINLINE inline
+#else
+#define DOCTEST_INLINE_NOINLINE inline DOCTEST_NOINLINE
+#endif
+
#ifndef DOCTEST_NORETURN
#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
#define DOCTEST_NORETURN
@@ -378,6 +392,14 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define
#endif // DOCTEST_MSVC
#endif // DOCTEST_CONSTEXPR
+#ifndef DOCTEST_NO_SANITIZE_INTEGER
+#if DOCTEST_CLANG >= DOCTEST_COMPILER(3, 7, 0)
+#define DOCTEST_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
+#else
+#define DOCTEST_NO_SANITIZE_INTEGER
+#endif
+#endif // DOCTEST_NO_SANITIZE_INTEGER
+
// =================================================================================================
// == FEATURE DETECTION END ========================================================================
// =================================================================================================
@@ -475,12 +497,13 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP
// https://github.com/doctest/doctest/issues/356
#if DOCTEST_CLANG
#include <ciso646>
+#endif // clang
+
#ifdef _LIBCPP_VERSION
#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
#define DOCTEST_CONFIG_USE_STD_HEADERS
#endif
#endif // _LIBCPP_VERSION
-#endif // clang
#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
@@ -970,7 +993,7 @@ namespace detail {
struct deferred_false : types::false_type { };
// MSVS 2015 :(
-#if defined(_MSC_VER) && _MSC_VER <= 1900
+#if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900
template <typename T, typename = void>
struct has_global_insertion_operator : types::false_type { };
@@ -1000,8 +1023,13 @@ namespace detail {
struct has_insertion_operator : types::false_type { };
#endif
-template <typename T>
-struct has_insertion_operator<T, decltype(operator<<(declval<std::ostream&>(), declval<const T&>()), void())> : types::true_type { };
+ template <typename T>
+ struct has_insertion_operator<T, decltype(operator<<(declval<std::ostream&>(), declval<const T&>()), void())> : types::true_type { };
+
+ template <typename T>
+ struct should_stringify_as_underlying_type {
+ static DOCTEST_CONSTEXPR bool value = detail::types::is_enum<T>::value && !doctest::detail::has_insertion_operator<T>::value;
+ };
DOCTEST_INTERFACE std::ostream* tlssPush();
DOCTEST_INTERFACE String tlssPop();
@@ -1063,7 +1091,7 @@ struct StringMaker : public detail::StringMakerBase<
template <typename T>
String toString() {
-#if DOCTEST_MSVC >= 0 && DOCTEST_CLANG == 0 && DOCTEST_GCC == 0
+#if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0
String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString<TYPE>(void)
String::size_type beginPos = ret.find('<');
return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast<String::size_type>(sizeof(">(void)")));
@@ -1074,7 +1102,7 @@ String toString() {
#endif
}
-template <typename T, typename detail::types::enable_if<!detail::types::is_enum<T>::value, bool>::type = true>
+template <typename T, typename detail::types::enable_if<!detail::should_stringify_as_underlying_type<T>::value, bool>::type = true>
String toString(const DOCTEST_REF_WRAP(T) value) {
return StringMaker<T>::convert(value);
}
@@ -1110,7 +1138,7 @@ DOCTEST_INTERFACE String toString(long unsigned in);
DOCTEST_INTERFACE String toString(long long in);
DOCTEST_INTERFACE String toString(long long unsigned in);
-template <typename T, typename detail::types::enable_if<detail::types::is_enum<T>::value, bool>::type = true>
+template <typename T, typename detail::types::enable_if<detail::should_stringify_as_underlying_type<T>::value, bool>::type = true>
String toString(const DOCTEST_REF_WRAP(T) value) {
using UT = typename detail::types::underlying_type<T>::type;
return (DOCTEST_STRINGIFY(static_cast<UT>(value)));
@@ -1162,8 +1190,18 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP
template <typename T>
struct filldata<T*> {
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180)
static void fill(std::ostream* stream, const T* in) {
- filldata<const void*>::fill(stream, in);
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast")
+ filldata<const void*>::fill(stream,
+#if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
+ reinterpret_cast<const void*>(in)
+#else
+ *reinterpret_cast<const void* const*>(&in)
+#endif
+ );
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
}
};
}
@@ -1275,9 +1313,9 @@ namespace detail {
template<class T, unsigned N> struct decay_array<T[N]> { using type = T*; };
template<class T> struct decay_array<T[]> { using type = T*; };
- template<class T> struct not_char_pointer { static DOCTEST_CONSTEXPR value = 1; };
- template<> struct not_char_pointer<char*> { static DOCTEST_CONSTEXPR value = 0; };
- template<> struct not_char_pointer<const char*> { static DOCTEST_CONSTEXPR value = 0; };
+ template<class T> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; };
+ template<> struct not_char_pointer<char*> { static DOCTEST_CONSTEXPR int value = 0; };
+ template<> struct not_char_pointer<const char*> { static DOCTEST_CONSTEXPR int value = 0; };
template<class T> struct can_use_op : public not_char_pointer<typename decay_array<T>::type> {};
#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
@@ -1326,7 +1364,11 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
// If not it doesn't find the operator or if the operator at global scope is defined after
// this template, the template won't be instantiated due to SFINAE. Once the template is not
// instantiated it can look for global operator using normal conversions.
+#ifdef __NVCC__
+#define SFINAE_OP(ret,op) ret
+#else
#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval<L>() op doctest::detail::declval<R>()),ret{})
+#endif
#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \
template <typename R> \
@@ -2129,13 +2171,13 @@ int registerReporter(const char* name, int priority, bool isReporter) {
{ \
void f(); \
}; \
- static inline DOCTEST_NOINLINE void func() { \
+ static DOCTEST_INLINE_NOINLINE void func() { \
der v; \
v.f(); \
} \
DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \
} \
- inline DOCTEST_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers)
+ DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers)
#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \
static void f(); \
@@ -3119,7 +3161,9 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#include <utility>
#include <fstream>
#include <sstream>
+#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
#include <iostream>
+#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
#include <algorithm>
#include <iomanip>
#include <vector>
@@ -3156,9 +3200,11 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
// defines for a leaner windows.h
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
+#define DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
#endif // WIN32_LEAN_AND_MEAN
#ifndef NOMINMAX
#define NOMINMAX
+#define DOCTEST_UNDEF_NOMINMAX
#endif // NOMINMAX
// not sure what AfxWin.h is for - here I do what Catch does
@@ -3239,8 +3285,14 @@ namespace {
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
throw e;
#else // DOCTEST_CONFIG_NO_EXCEPTIONS
+#ifdef DOCTEST_CONFIG_HANDLE_EXCEPTION
+ DOCTEST_CONFIG_HANDLE_EXCEPTION(e);
+#else // DOCTEST_CONFIG_HANDLE_EXCEPTION
+#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
std::cerr << "doctest will terminate because it needed to throw an exception.\n"
<< "The message was: " << e.what() << '\n';
+#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+#endif // DOCTEST_CONFIG_HANDLE_EXCEPTION
std::terminate();
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
}
@@ -3315,7 +3367,7 @@ namespace detail {
namespace timer_large_integer
{
-
+
#if defined(DOCTEST_PLATFORM_WINDOWS)
using type = ULONGLONG;
#else // DOCTEST_PLATFORM_WINDOWS
@@ -3777,7 +3829,7 @@ namespace Color {
// clang-format off
const char* assertString(assertType::Enum at) {
- DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitely handled
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitly handled
#define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type
#define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \
DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \
@@ -4105,11 +4157,13 @@ namespace {
return false;
}
+ DOCTEST_NO_SANITIZE_INTEGER
unsigned long long hash(unsigned long long a, unsigned long long b) {
return (a << 5) + b;
}
// C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html
+ DOCTEST_NO_SANITIZE_INTEGER
unsigned long long hash(const char* str) {
unsigned long long hash = 5381;
char c;
@@ -4949,7 +5003,7 @@ namespace detail {
m_string = tlssPop();
logged = true;
}
-
+
DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this);
const bool isWarn = m_severity & assertType::is_warn;
@@ -5018,7 +5072,11 @@ namespace {
mutable XmlWriter* m_writer = nullptr;
};
+#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
XmlWriter( std::ostream& os = std::cout );
+#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+ XmlWriter( std::ostream& os );
+#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
~XmlWriter();
XmlWriter( XmlWriter const& ) = delete;
@@ -5500,7 +5558,7 @@ namespace {
test_case_start_impl(in);
xml.ensureTagClosed();
}
-
+
void test_case_reenter(const TestCaseData&) override {}
void test_case_end(const CurrentTestCaseStats& st) override {
@@ -5848,7 +5906,22 @@ namespace {
testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str());
}
- void log_message(const MessageData&) override {}
+ void log_message(const MessageData& mb) override {
+ if(mb.m_severity & assertType::is_warn) // report only failures
+ return;
+
+ DOCTEST_LOCK_MUTEX(mutex)
+
+ std::ostringstream os;
+ os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(")
+ << line(mb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl;
+
+ os << mb.m_string.c_str() << "\n";
+ log_contexts(os);
+
+ testCaseData.addFailure(mb.m_string.c_str(),
+ mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", os.str());
+ }
void test_case_skipped(const TestCaseData&) override {}
@@ -6188,9 +6261,9 @@ namespace {
separator_to_stream();
s << std::dec;
- auto totwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters, static_cast<unsigned>(p.numAsserts))) + 1)));
- auto passwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast<unsigned>(p.numAsserts - p.numAssertsFailed))) + 1)));
- auto failwidth = int(std::ceil(log10((std::max(p.numTestCasesFailed, static_cast<unsigned>(p.numAssertsFailed))) + 1)));
+ auto totwidth = int(std::ceil(log10(static_cast<double>(std::max(p.numTestCasesPassingFilters, static_cast<unsigned>(p.numAsserts))) + 1)));
+ auto passwidth = int(std::ceil(log10(static_cast<double>(std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast<unsigned>(p.numAsserts - p.numAssertsFailed))) + 1)));
+ auto failwidth = int(std::ceil(log10(static_cast<double>(std::max(p.numTestCasesFailed, static_cast<unsigned>(p.numAssertsFailed))) + 1)));
const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0;
s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth)
<< p.numTestCasesPassingFilters << " | "
@@ -6222,7 +6295,7 @@ namespace {
subcasesStack.clear();
currentSubcaseLevel = 0;
}
-
+
void test_case_reenter(const TestCaseData&) override {
subcasesStack.clear();
}
@@ -6739,8 +6812,12 @@ int Context::run() {
fstr.open(p->out.c_str(), std::fstream::out);
p->cout = &fstr;
} else {
+#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
// stdout by default
p->cout = &std::cout;
+#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+ return EXIT_FAILURE;
+#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
}
}
@@ -6905,7 +6982,7 @@ int Context::run() {
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc);
p->timer.start();
-
+
bool run_test = true;
do {
@@ -6946,7 +7023,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP
run_test = false;
p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts;
}
-
+
if(!p->nextSubcaseStack.empty() && run_test)
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc);
if(p->nextSubcaseStack.empty())
@@ -7017,3 +7094,13 @@ DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
#endif // DOCTEST_LIBRARY_IMPLEMENTATION
#endif // DOCTEST_CONFIG_IMPLEMENT
+
+#ifdef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
+#undef WIN32_LEAN_AND_MEAN
+#undef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
+#endif // DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
+
+#ifdef DOCTEST_UNDEF_NOMINMAX
+#undef NOMINMAX
+#undef DOCTEST_UNDEF_NOMINMAX
+#endif // DOCTEST_UNDEF_NOMINMAX
diff --git a/thirdparty/thorvg/AUTHORS b/thirdparty/thorvg/AUTHORS
index 11f3f170a5..c5f8529da9 100644
--- a/thirdparty/thorvg/AUTHORS
+++ b/thirdparty/thorvg/AUTHORS
@@ -1,4 +1,4 @@
-Hermet Park <hermetpark@gmail.com>
+Hermet Park <hermet@lottiefiles.com>
Prudhvi Raj Vasireddi <prudhvi.raj@samsung.com>
Junsu Choi <jsuya.choi@samsung.com>
Pranay Samanta <pranay.ks@samsung.com>
@@ -15,3 +15,8 @@ Michal Maciola <m.maciola@samsung.com>
Peter Vullings <peter@projectitis.com>
K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com>
Rémi Verschelde <rverschelde@gmail.com>
+Martin Liska <mliksa@suse.cz>
+Vincenzo Pupillo <vincenzo.pupillo@unimi.it>
+EunSik Jeong <rinechran@outlook.jp>
+Samsung Electronics Co., Ltd
+Rafał Mikrut <mikrutrafal@protonmail.com>
diff --git a/thirdparty/thorvg/LICENSE b/thirdparty/thorvg/LICENSE
index 2f0361a864..d056ff6cbf 100644
--- a/thirdparty/thorvg/LICENSE
+++ b/thirdparty/thorvg/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2020 - 2022 notice for the ThorVG Project (see AUTHORS)
+Copyright (c) 2020 - 2023 notice for the ThorVG Project (see AUTHORS)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h
index 78522d6d2d..89caf0161d 100644
--- a/thirdparty/thorvg/inc/config.h
+++ b/thirdparty/thorvg/inc/config.h
@@ -13,5 +13,5 @@
#define THORVG_JPG_LOADER_SUPPORT 1
-#define THORVG_VERSION_STRING "0.8.4"
+#define THORVG_VERSION_STRING "0.9.0"
#endif
diff --git a/thirdparty/thorvg/inc/thorvg.h b/thirdparty/thorvg/inc/thorvg.h
index b1f2e9e286..bde045f76c 100644
--- a/thirdparty/thorvg/inc/thorvg.h
+++ b/thirdparty/thorvg/inc/thorvg.h
@@ -2,11 +2,12 @@
* @file thorvg.h
*
* The main APIs enabling the TVG initialization, preparation of the canvas and provisioning of its content:
- * - drawing shapes such as line, curve, arc, rectangle, circle or user-defined
- * - drawing pictures - SVG, PNG, JPG, RAW
- * - solid or gradient filling
- * - continuous and dashed stroking
- * - clipping and masking
+ * - drawing shapes: line, arc, curve, path, polygon...
+ * - drawing pictures: tvg, svg, png, jpg, bitmap...
+ * - drawing fillings: solid, linear and radial gradient...
+ * - drawing stroking: continuous stroking with arbitrary width, join, cap, dash styles.
+ * - drawing composition: blending, masking, path clipping...
+ * - drawing scene graph & affine transformation (translation, rotation, scale, ...)
* and finally drawing the canvas and TVG termination.
*/
@@ -14,20 +15,36 @@
#ifndef _THORVG_H_
#define _THORVG_H_
+#include <functional>
#include <memory>
#include <string>
-#ifdef TVG_BUILD
- #if defined(_WIN32) && !defined(__clang__)
- #define TVG_EXPORT __declspec(dllexport)
- #define TVG_DEPRECATED __declspec(deprecated)
+#ifdef TVG_API
+ #undef TVG_API
+#endif
+
+#if defined(_WIN32) && !defined(__clang__)
+ #if TVG_BUILD
+ #if TVG_EXPORT
+ #define TVG_API __declspec(dllexport)
+ #else
+ #define TVG_API
+ #endif
#else
- #define TVG_EXPORT __attribute__ ((visibility ("default")))
- #define TVG_DEPRECATED __attribute__ ((__deprecated__))
+ #define TVG_API
#endif
+ #define TVG_DEPRECATED __declspec(deprecated)
#else
- #define TVG_EXPORT
- #define TVG_DEPRECATED
+ #if TVG_BUILD
+ #if TVG_EXPORT
+ #define TVG_API __attribute__ ((visibility ("default")))
+ #else
+ #define TVG_API
+ #endif
+ #else
+ #define TVG_API
+ #endif
+ #define TVG_DEPRECATED __attribute__ ((__deprecated__))
#endif
#ifdef __cplusplus
@@ -147,7 +164,7 @@ enum class CompositeMethod
ClipPath, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered.
AlphaMask, ///< The pixels of the source and the target are alpha blended. As a result, only the part of the source, which alpha intersects with the target is visible.
InvAlphaMask, ///< The pixels of the source and the complement to the target's pixels are alpha blended. As a result, only the part of the source which alpha is not covered by the target is visible.
- LumaMask ///< @BETA_API The source pixels are converted to the grayscale (luma value) and alpha blended with the target. As a result, only the part of the source, which intersects with the target is visible.
+ LumaMask ///< The source pixels are converted to the grayscale (luma value) and alpha blended with the target. As a result, only the part of the source, which intersects with the target is visible. @since 0.9
};
/**
@@ -183,6 +200,33 @@ struct Matrix
float e31, e32, e33;
};
+/**
+ * @brief A data structure representing a texture mesh vertex
+ *
+ * @param pt The vertex coordinate
+ * @param uv The normalized texture coordinate in the range (0.0..1.0, 0.0..1.0)
+ *
+ * @BETA_API
+ */
+struct Vertex
+{
+ Point pt;
+ Point uv;
+};
+
+
+/**
+ * @brief A data structure representing a triange in a texture mesh
+ *
+ * @param vertex The three vertices that make up the polygon
+ *
+ * @BETA_API
+ */
+struct Polygon
+{
+ Vertex vertex[3];
+};
+
/**
* @class Paint
@@ -193,7 +237,7 @@ struct Matrix
* Paint represents such a graphical object and its behaviors such as duplication, transformation and composition.
* TVG recommends the user to regard a paint as a set of volatile commands. They can prepare a Paint and then request a Canvas to run them.
*/
-class TVG_EXPORT Paint
+class TVG_API Paint
{
public:
virtual ~Paint();
@@ -263,6 +307,7 @@ public:
* @return Result::Success when succeed.
*
* @note Setting the opacity with this API may require multiple render pass for composition. It is recommended to avoid changing the opacity if possible.
+ * @note ClipPath won't use the opacity value. (see: enum class CompositeMethod::ClipPath)
*/
Result opacity(uint8_t o) noexcept;
@@ -336,27 +381,11 @@ public:
CompositeMethod composite(const Paint** target) const noexcept;
/**
- * @brief Gets the composition source object and the composition method.
- *
- * @param[out] source The paint of the composition source object.
- * @param[out] method The method used to composite the source object with the target.
- *
- * @return Result::Success when the paint object used as a composition target, Result::InsufficientCondition otherwise.
- *
- * @warning Please do not use it, this API is not official one. It could be modified in the next version.
- *
- * @BETA_API
- */
- Result composite(const Paint** source, CompositeMethod* method) const noexcept;
-
- /**
* @brief Return the unique id value of the paint instance.
*
* This method can be called for checking the current concrete instance type.
*
* @return The type id of the Paint instance.
- *
- * @BETA_API
*/
uint32_t identifier() const noexcept;
@@ -376,7 +405,7 @@ public:
* It specifies the gradient behavior in case the area defined by the gradient bounds
* is smaller than the area to be filled.
*/
-class TVG_EXPORT Fill
+class TVG_API Fill
{
public:
/**
@@ -463,8 +492,6 @@ public:
* This method can be called for checking the current concrete instance type.
*
* @return The type id of the Fill instance.
- *
- * @BETA_API
*/
uint32_t identifier() const noexcept;
@@ -482,7 +509,7 @@ public:
* @note A Canvas behavior depends on the raster engine though the final content of the buffer is expected to be identical.
* @warning The Paint objects belonging to one Canvas can't be shared among multiple Canvases.
*/
-class TVG_EXPORT Canvas
+class TVG_API Canvas
{
public:
Canvas(RenderMethod*);
@@ -578,7 +605,7 @@ public:
* Besides the APIs inherited from the Fill class, it enables setting and getting the linear gradient bounds.
* The behavior outside the gradient bounds depends on the value specified in the spread API.
*/
-class TVG_EXPORT LinearGradient final : public Fill
+class TVG_API LinearGradient final : public Fill
{
public:
~LinearGradient();
@@ -630,8 +657,6 @@ public:
* This method can be referred for identifying the LinearGradient class type.
*
* @return The type id of the LinearGradient class.
- *
- * @BETA_API
*/
static uint32_t identifier() noexcept;
@@ -645,7 +670,7 @@ public:
* @brief A class representing the radial gradient fill of the Shape object.
*
*/
-class TVG_EXPORT RadialGradient final : public Fill
+class TVG_API RadialGradient final : public Fill
{
public:
~RadialGradient();
@@ -689,8 +714,6 @@ public:
* This method can be referred for identifying the RadialGradient class type.
*
* @return The type id of the RadialGradient class.
- *
- * @BETA_API
*/
static uint32_t identifier() noexcept;
@@ -710,7 +733,7 @@ public:
* The stroke of Shape is an optional property in case the Shape needs to be represented with/without the outline borders.
* It's efficient since the shape path and the stroking path can be shared with each other. It's also convenient when controlling both in one context.
*/
-class TVG_EXPORT Shape final : public Paint
+class TVG_API Shape final : public Paint
{
public:
~Shape();
@@ -943,6 +966,7 @@ public:
* @return Result::Success when succeed.
*
* @note Either a solid color or a gradient fill is applied, depending on what was set as last.
+ * @note ClipPath won't use the fill values. (see: enum class CompositeMethod::ClipPath)
*/
Result fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept;
@@ -968,6 +992,18 @@ public:
*/
Result fill(FillRule r) noexcept;
+
+ /**
+ * @brief Sets the rendering order of the stroke and the fill.
+ *
+ * @param[in] strokeFirst If @c true the stroke is rendered before the fill, otherwise the stroke is rendered as the second one (the default option).
+ *
+ * @return Result::Success when succeed, Result::FailedAllocation otherwise.
+ * @BETA_API
+ */
+ Result order(bool strokeFirst) noexcept;
+
+
/**
* @brief Gets the commands data of the path.
*
@@ -1074,8 +1110,6 @@ public:
* This method can be referred for identifying the Shape class type.
*
* @return The type id of the Shape class.
- *
- * @BETA_API
*/
static uint32_t identifier() noexcept;
@@ -1091,7 +1125,7 @@ public:
*
* @note Supported formats are depended on the available TVG loaders.
*/
-class TVG_EXPORT Picture final : public Paint
+class TVG_API Picture final : public Paint
{
public:
~Picture();
@@ -1185,11 +1219,50 @@ public:
/**
* @brief Loads a raw data from a memory block with a given size.
*
+ * @retval Result::Success When succeed, Result::InsufficientCondition otherwise.
+ * @retval Result::FailedAllocation An internal error possibly with memory allocation.
+ *
+ * @since 0.9
+ */
+ Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept;
+
+ /**
+ * @brief Sets or removes the triangle mesh to deform the image.
+ *
+ * If a mesh is provided, the transform property of the Picture will apply to the triangle mesh, and the
+ * image data will be used as the texture.
+ *
+ * If @p triangles is @c nullptr, or @p triangleCnt is 0, the mesh will be removed.
+ *
+ * Only raster image types are supported at this time (png, jpg). Vector types like svg and tvg do not support.
+ * mesh deformation. However, if required you should be able to render a vector image to a raster image and then apply a mesh.
+ *
+ * @param[in] triangles An array of Polygons(triangles) that make up the mesh, or null to remove the mesh.
+ * @param[in] triangleCnt The number of Polygons(triangles) provided, or 0 to remove the mesh.
+ *
+ * @return Result::Success When succeed.
+ * @return Result::Unknown If fails
+ *
+ * @note The Polygons are copied internally, so modifying them after calling Mesh::mesh has no affect.
* @warning Please do not use it, this API is not official one. It could be modified in the next version.
*
* @BETA_API
*/
- Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept;
+ Result mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept;
+
+ /**
+ * @brief Return the number of triangles in the mesh, and optionally get a pointer to the array of triangles in the mesh.
+ *
+ * @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh.
+ *
+ * @return uint32_t The number of polygons in the array.
+ *
+ * @note Modifying the triangles returned by this method will modify them directly within the mesh.
+ * @warning Please do not use it, this API is not official one. It could be modified in the next version.
+ *
+ * @BETA_API
+ */
+ uint32_t mesh(const Polygon** triangles) const noexcept;
/**
* @brief Gets the position and the size of the loaded SVG picture.
@@ -1213,8 +1286,6 @@ public:
* This method can be referred for identifying the Picture class type.
*
* @return The type id of the Picture class.
- *
- * @BETA_API
*/
static uint32_t identifier() noexcept;
@@ -1233,7 +1304,7 @@ public:
* As a group, the scene can be transformed, made translucent and composited with other target paints,
* its children will be affected by the scene world.
*/
-class TVG_EXPORT Scene final : public Paint
+class TVG_API Scene final : public Paint
{
public:
~Scene();
@@ -1293,8 +1364,6 @@ public:
* This method can be referred for identifying the Scene class type.
*
* @return The type id of the Scene class.
- *
- * @BETA_API
*/
static uint32_t identifier() noexcept;
@@ -1307,7 +1376,7 @@ public:
*
* @brief A class for the rendering graphical elements with a software raster engine.
*/
-class TVG_EXPORT SwCanvas final : public Canvas
+class TVG_API SwCanvas final : public Canvas
{
public:
~SwCanvas();
@@ -1398,7 +1467,7 @@ public:
*
* @BETA_API
*/
-class TVG_EXPORT GlCanvas final : public Canvas
+class TVG_API GlCanvas final : public Canvas
{
public:
~GlCanvas();
@@ -1430,7 +1499,7 @@ public:
*
* @brief A class that enables initialization and termination of the TVG engines.
*/
-class TVG_EXPORT Initializer final
+class TVG_API Initializer final
{
public:
/**
@@ -1492,7 +1561,7 @@ public:
*
* @since 0.5
*/
-class TVG_EXPORT Saver final
+class TVG_API Saver final
{
public:
~Saver();
@@ -1562,13 +1631,13 @@ public:
*
* @BETA_API
*/
-class TVG_EXPORT Accessor final
+class TVG_API Accessor final
{
public:
~Accessor();
/**
- * @brief Access the Picture scene stree nodes.
+ * @brief Set the access function for traversing the Picture scene tree nodes.
*
* @param[in] picture The picture node to traverse the internal scene-tree.
* @param[in] func The callback function calling for every paint nodes of the Picture.
@@ -1579,7 +1648,7 @@ public:
*
* @BETA_API
*/
- std::unique_ptr<Picture> access(std::unique_ptr<Picture> picture, bool(*func)(const Paint* paint)) noexcept;
+ std::unique_ptr<Picture> set(std::unique_ptr<Picture> picture, std::function<bool(const Paint* paint)> func) noexcept;
/**
* @brief Creates a new Accessor object.
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h
index 157fdb8f82..0e9029bf73 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+/*
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_SW_COMMON_H_
#define _TVG_SW_COMMON_H_
@@ -222,11 +223,16 @@ struct SwImage
{
SwOutline* outline = nullptr;
SwRleData* rle = nullptr;
- uint32_t* data = nullptr;
+ union {
+ pixel_t* data; //system based data pointer
+ uint32_t* buf32; //for explicit 32bits channels
+ uint8_t* buf8; //for explicit 8bits grayscale
+ };
uint32_t w, h, stride;
int32_t ox = 0; //offset x
int32_t oy = 0; //offset y
float scale;
+ uint8_t channelSize;
bool direct = false; //draw image directly (with offset)
bool scaled = false; //draw scaled image
@@ -235,7 +241,7 @@ struct SwImage
struct SwBlender
{
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
- uint32_t (*lumaValue)(uint32_t c);
+ uint8_t (*luma)(uint8_t* c);
};
struct SwCompositor;
@@ -301,12 +307,12 @@ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, S
bool mathClipBBox(const SwBBox& clipper, SwBBox& clipee);
void shapeReset(SwShape* shape);
-bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite);
+bool shapePrepare(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite);
bool shapePrepared(const SwShape* shape);
-bool shapeGenRle(SwShape* shape, const Shape* sdata, bool antiAlias);
+bool shapeGenRle(SwShape* shape, const RenderShape* rshape, bool antiAlias);
void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid);
-void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform);
-bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
+void shapeResetStroke(SwShape* shape, const RenderShape* rshape, const Matrix* transform);
+bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
void shapeFree(SwShape* shape);
void shapeDelStroke(SwShape* shape);
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
@@ -316,12 +322,12 @@ void shapeResetStrokeFill(SwShape* shape);
void shapeDelFill(SwShape* shape);
void shapeDelStrokeFill(SwShape* shape);
-void strokeReset(SwStroke* stroke, const Shape* shape, const Matrix* transform);
+void strokeReset(SwStroke* stroke, const RenderShape* shape, const Matrix* transform);
bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid);
void strokeFree(SwStroke* stroke);
-bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
+bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
bool imageGenRle(SwImage* image, const SwBBox& renderRegion, bool antiAlias);
void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid);
void imageReset(SwImage* image);
@@ -334,10 +340,12 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x,
void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias);
+SwRleData* rleRender(const SwBBox* bbox);
void rleFree(SwRleData* rle);
void rleReset(SwRleData* rle);
-void rleClipPath(SwRleData *rle, const SwRleData *clip);
-void rleClipRect(SwRleData *rle, const SwBBox* clip);
+void rleMerge(SwRleData* rle, SwRleData* clip1, SwRleData* clip2);
+void rleClipPath(SwRleData* rle, const SwRleData* clip);
+void rleClipRect(SwRleData* rle, const SwBBox* clip);
SwMpool* mpoolInit(uint32_t threads);
bool mpoolTerm(SwMpool* mpool);
@@ -350,11 +358,13 @@ void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx);
bool rasterCompositor(SwSurface* surface);
bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
-bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity);
+bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& bbox, uint32_t opacity);
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id);
-bool rasterClear(SwSurface* surface);
+bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len);
-void rasterUnpremultiply(SwSurface* surface);
+void rasterUnpremultiply(Surface* surface);
+void rasterPremultiply(Surface* surface);
+bool rasterConvertCS(Surface* surface, ColorSpace to);
#endif /* _TVG_SW_COMMON_H_ */
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwFill.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwFill.cpp
index 04014a9ec3..694bc35231 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwFill.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwFill.cpp
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+/*
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgMath.h"
#include "tvgSwCommon.h"
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp
index c02e28b432..9e215dbefd 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgMath.h"
#include "tvgSwCommon.h"
@@ -33,7 +34,7 @@ static inline bool _onlyShifted(const Matrix* m)
}
-static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool, unsigned tid)
+static bool _genOutline(SwImage* image, const RenderMesh* mesh, const Matrix* transform, SwMpool* mpool, unsigned tid)
{
image->outline = mpoolReqOutline(mpool, tid);
auto outline = image->outline;
@@ -51,10 +52,50 @@ static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool,
outline->closed[0] = true;
}
- auto w = static_cast<float>(image->w);
- auto h = static_cast<float>(image->h);
+ Point to[4];
+ if (mesh->triangleCnt > 0) {
+ // TODO: Optimise me. We appear to calculate this exact min/max bounding area in multiple
+ // places. We should be able to re-use one we have already done? Also see:
+ // tvgPictureImpl.h --> bounds
+ // tvgSwRasterTexmap.h --> _rasterTexmapPolygonMesh
+ //
+ // TODO: Should we calculate the exact path(s) of the triangle mesh instead?
+ // i.e. copy tvgSwShape.capp -> _genOutline?
+ //
+ // TODO: Cntrs?
+ auto triangles = mesh->triangles;
+ auto min = triangles[0].vertex[0].pt;
+ auto max = triangles[0].vertex[0].pt;
+
+ for (uint32_t i = 0; i < mesh->triangleCnt; ++i) {
+ if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x;
+ else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x;
+ if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y;
+ else if (triangles[i].vertex[0].pt.y > max.y) max.y = triangles[i].vertex[0].pt.y;
+
+ if (triangles[i].vertex[1].pt.x < min.x) min.x = triangles[i].vertex[1].pt.x;
+ else if (triangles[i].vertex[1].pt.x > max.x) max.x = triangles[i].vertex[1].pt.x;
+ if (triangles[i].vertex[1].pt.y < min.y) min.y = triangles[i].vertex[1].pt.y;
+ else if (triangles[i].vertex[1].pt.y > max.y) max.y = triangles[i].vertex[1].pt.y;
+
+ if (triangles[i].vertex[2].pt.x < min.x) min.x = triangles[i].vertex[2].pt.x;
+ else if (triangles[i].vertex[2].pt.x > max.x) max.x = triangles[i].vertex[2].pt.x;
+ if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y;
+ else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y;
+ }
+ to[0] = {min.x, min.y};
+ to[1] = {max.x, min.y};
+ to[2] = {max.x, max.y};
+ to[3] = {min.x, max.y};
+ } else {
+ auto w = static_cast<float>(image->w);
+ auto h = static_cast<float>(image->h);
+ to[0] = {0, 0};
+ to[1] = {w, 0};
+ to[2] = {w, h};
+ to[3] = {0, h};
+ }
- Point to[4] = {{0 ,0}, {w, 0}, {w, h}, {0, h}};
for (int i = 0; i < 4; i++) {
outline->pts[outline->ptsCnt] = mathTransform(&to[i], transform);
outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT;
@@ -78,7 +119,7 @@ static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool,
/* External Class Implementation */
/************************************************************************/
-bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
+bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
{
image->direct = _onlyShifted(transform);
@@ -96,7 +137,7 @@ bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipReg
else image->scaled = false;
}
- if (!_genOutline(image, transform, mpool, tid)) return false;
+ if (!_genOutline(image, mesh, transform, mpool, tid)) return false;
return mathUpdateOutlineBBox(image->outline, clipRegion, renderRegion, image->direct);
}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwMath.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwMath.cpp
index 1027bb1f79..5a4f58d9a6 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwMath.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwMath.cpp
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+/*
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include <math.h>
#include "tvgSwCommon.h"
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwMemPool.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwMemPool.cpp
index d2962e6d8d..05ff9ddf0b 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwMemPool.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwMemPool.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgSwCommon.h"
@@ -59,16 +60,16 @@ void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx)
SwMpool* mpoolInit(unsigned threads)
{
- if (threads == 0) threads = 1;
+ auto allocSize = threads + 1;
auto mpool = static_cast<SwMpool*>(calloc(sizeof(SwMpool), 1));
- mpool->outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * threads));
+ mpool->outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * allocSize));
if (!mpool->outline) goto err;
- mpool->strokeOutline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * threads));
+ mpool->strokeOutline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * allocSize));
if (!mpool->strokeOutline) goto err;
- mpool->allocSize = threads;
+ mpool->allocSize = allocSize;
return mpool;
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp
index ffd74bdd47..1f10afd9b3 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+/*
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -37,8 +37,8 @@
/************************************************************************/
constexpr auto DOWN_SCALE_TOLERANCE = 0.5f;
-
-static inline uint32_t _multiplyAlpha(uint32_t c, uint32_t a)
+template<typename T>
+static inline T _multiply(T c, T a)
{
return ((c * a + 0xff) >> 8);
}
@@ -56,15 +56,29 @@ static inline uint32_t _ialpha(uint32_t c)
}
-static inline uint32_t _abgrLumaValue(uint32_t c)
+static inline uint8_t _alpha(uint8_t* a)
{
- return ((((c&0xff)*54) + (((c>>8)&0xff)*183) + (((c>>16)&0xff)*19))) >> 8; //0.2125*R + 0.7154*G + 0.0721*B
+ return *a;
}
-static inline uint32_t _argbLumaValue(uint32_t c)
+static inline uint8_t _ialpha(uint8_t* a)
{
- return ((((c&0xff)*19) + (((c>>8)&0xff)*183) + (((c>>16)&0xff)*54))) >> 8; //0.0721*B + 0.7154*G + 0.2125*R
+ return ~(*a);
+}
+
+
+static inline uint8_t _abgrLuma(uint8_t* c)
+{
+ auto v = *(uint32_t*)c;
+ return ((((v&0xff)*54) + (((v>>8)&0xff)*183) + (((v>>16)&0xff)*19))) >> 8; //0.2125*R + 0.7154*G + 0.0721*B
+}
+
+
+static inline uint8_t _argbLuma(uint8_t* c)
+{
+ auto v = *(uint32_t*)c;
+ return ((((v&0xff)*19) + (((v>>8)&0xff)*183) + (((v>>16)&0xff)*54))) >> 8; //0.0721*B + 0.7154*G + 0.2125*R
}
@@ -148,65 +162,95 @@ static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t
}
+void _rasterGrayscale8(uint8_t *dst, uint32_t val, uint32_t offset, int32_t len)
+{
+ cRasterPixels<uint8_t>(dst, val, offset, len);
+}
+
/************************************************************************/
/* Rect */
/************************************************************************/
-static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint32_t color, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint8_t(*blender)(uint8_t*))
{
- TVGLOG("SW_ENGINE", "Masked Rect");
-
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
-
- auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
-
- for (uint32_t y = 0; y < h; ++y) {
- auto dst = &buffer[y * surface->stride];
- auto cmp = &cbuffer[y * surface->stride];
- for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp) {
- auto tmp = ALPHA_BLEND(color, blendMethod(*cmp));
- *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
+ auto csize = surface->compositor->image.channelSize;
+ auto cbuffer = surface->compositor->image.buf8 + ((region.min.y * surface->compositor->image.stride + region.min.x) * csize); //compositor buffer
+
+ TVGLOG("SW_ENGINE", "Masked Rect [Region: %lu %lu %u %u]", region.min.x, region.min.y, w, h);
+
+ //32bits channels
+ if (surface->channelSize == sizeof(uint32_t)) {
+ auto color = surface->blender.join(r, g, b, a);
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
+ for (uint32_t y = 0; y < h; ++y) {
+ auto dst = &buffer[y * surface->stride];
+ auto cmp = &cbuffer[y * surface->stride * csize];
+ for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) {
+ auto tmp = ALPHA_BLEND(color, blender(cmp));
+ *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
+ }
+ }
+ //8bits grayscale
+ } else if (surface->channelSize == sizeof(uint8_t)) {
+ auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x;
+ for (uint32_t y = 0; y < h; ++y) {
+ auto dst = &buffer[y * surface->stride];
+ auto cmp = &cbuffer[y * surface->stride * csize];
+ for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) {
+ auto tmp = _multiply<uint8_t>(a, blender(cmp));
+ *dst = tmp + _multiply<uint8_t>(*dst, _ialpha(tmp));
+ }
}
}
return true;
}
-static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint32_t color)
+static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b)
{
- auto buffer = surface->buffer + (region.min.y * surface->stride);
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
- for (uint32_t y = 0; y < h; ++y) {
- rasterRGBA32(buffer + y * surface->stride, color, region.min.x, w);
+ //32bits channels
+ if (surface->channelSize == sizeof(uint32_t)) {
+ auto color = surface->blender.join(r, g, b, 255);
+ auto buffer = surface->buf32 + (region.min.y * surface->stride);
+ for (uint32_t y = 0; y < h; ++y) {
+ rasterRGBA32(buffer + y * surface->stride, color, region.min.x, w);
+ }
+ //8bits grayscale
+ } else if (surface->channelSize == sizeof(uint8_t)) {
+ auto buffer = surface->buf8 + (region.min.y * surface->stride);
+ for (uint32_t y = 0; y < h; ++y) {
+ _rasterGrayscale8(buffer + y * surface->stride, 255, region.min.x, w);
+ }
}
return true;
}
-static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint32_t color, uint8_t opacity)
+static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
if (_compositing(surface)) {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
- return _rasterMaskedRect(surface, region, color, _alpha);
+ return _rasterMaskedRect(surface, region, r, g, b, a, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
- return _rasterMaskedRect(surface, region, color, _ialpha);
+ return _rasterMaskedRect(surface, region, r, g, b, a, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterMaskedRect(surface, region, color, surface->blender.lumaValue);
+ return _rasterMaskedRect(surface, region, r, g, b, a, surface->blender.luma);
}
} else {
- if (opacity == 255) {
- return _rasterSolidRect(surface, region, color);
+ if (a == 255) {
+ return _rasterSolidRect(surface, region, r, g, b);
} else {
#if defined(THORVG_AVX_VECTOR_SUPPORT)
- return avxRasterTranslucentRect(surface, region, color);
+ return avxRasterTranslucentRect(surface, region, r, g, b, a);
#elif defined(THORVG_NEON_VECTOR_SUPPORT)
- return neonRasterTranslucentRect(surface, region, color);
+ return neonRasterTranslucentRect(surface, region, r, g, b, a);
#else
- return cRasterTranslucentRect(surface, region, color);
+ return cRasterTranslucentRect(surface, region, r, g, b, a);
#endif
}
}
@@ -218,41 +262,74 @@ static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint32_t color
/* Rle */
/************************************************************************/
-static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint8_t(*blender)(uint8_t*))
{
TVGLOG("SW_ENGINE", "Masked Rle");
auto span = rle->spans;
uint32_t src;
- auto cbuffer = surface->compositor->image.data;
-
- for (uint32_t i = 0; i < rle->size; ++i, ++span) {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
- if (span->coverage == 255) src = color;
- else src = ALPHA_BLEND(color, span->coverage);
- for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
- auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
- *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
+ auto cbuffer = surface->compositor->image.buf8;
+ auto csize = surface->compositor->image.channelSize;
+
+ //32bit channels
+ if (surface->channelSize == sizeof(uint32_t)) {
+ auto color = surface->blender.join(r, g, b, a);
+ for (uint32_t i = 0; i < rle->size; ++i, ++span) {
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
+ if (span->coverage == 255) src = color;
+ else src = ALPHA_BLEND(color, span->coverage);
+ for (uint32_t x = 0; x < span->len; ++x, ++dst, cmp += csize) {
+ auto tmp = ALPHA_BLEND(src, blender(cmp));
+ *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
+ }
+ }
+ //8bit grayscale
+ } else if (surface->channelSize == sizeof(uint8_t)) {
+ for (uint32_t i = 0; i < rle->size; ++i, ++span) {
+ auto dst = &surface->buf8[span->y * surface->stride + span->x];
+ auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
+ if (span->coverage == 255) src = a;
+ else src = _multiply<uint8_t>(a, span->coverage);
+ for (uint32_t x = 0; x < span->len; ++x, ++dst, cmp += csize) {
+ auto tmp = _multiply<uint8_t>(src, blender(cmp));
+ *dst = tmp + _multiply<uint8_t>(*dst, _ialpha(tmp));
+ }
}
}
return true;
}
-static bool _rasterSolidRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
+static bool _rasterSolidRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b)
{
auto span = rle->spans;
- for (uint32_t i = 0; i < rle->size; ++i, ++span) {
- if (span->coverage == 255) {
- rasterRGBA32(surface->buffer + span->y * surface->stride, color, span->x, span->len);
- } else {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto src = ALPHA_BLEND(color, span->coverage);
- auto ialpha = 255 - span->coverage;
- for (uint32_t x = 0; x < span->len; ++x, ++dst) {
- *dst = src + ALPHA_BLEND(*dst, ialpha);
+ //32bit channels
+ if (surface->channelSize == sizeof(uint32_t)) {
+ auto color = surface->blender.join(r, g, b, 255);
+ for (uint32_t i = 0; i < rle->size; ++i, ++span) {
+ if (span->coverage == 255) {
+ rasterRGBA32(surface->buf32 + span->y * surface->stride, color, span->x, span->len);
+ } else {
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto src = ALPHA_BLEND(color, span->coverage);
+ auto ialpha = 255 - span->coverage;
+ for (uint32_t x = 0; x < span->len; ++x, ++dst) {
+ *dst = src + ALPHA_BLEND(*dst, ialpha);
+ }
+ }
+ }
+ //8bit grayscale
+ } else if (surface->channelSize == sizeof(uint8_t)) {
+ for (uint32_t i = 0; i < rle->size; ++i, ++span) {
+ if (span->coverage == 255) {
+ _rasterGrayscale8(surface->buf8 + span->y * surface->stride, 255, span->x, span->len);
+ } else {
+ auto dst = &surface->buf8[span->y * surface->stride + span->x];
+ for (uint32_t x = 0; x < span->len; ++x, ++dst) {
+ *dst = span->coverage;
+ }
}
}
}
@@ -260,28 +337,28 @@ static bool _rasterSolidRle(SwSurface* surface, const SwRleData* rle, uint32_t c
}
-static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint8_t opacity)
+static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
if (!rle) return false;
if (_compositing(surface)) {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
- return _rasterMaskedRle(surface, rle, color, _alpha);
+ return _rasterMaskedRle(surface, rle, r, g, b, a, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
- return _rasterMaskedRle(surface, rle, color, _ialpha);
+ return _rasterMaskedRle(surface, rle, r, g, b, a, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterMaskedRle(surface, rle, color, surface->blender.lumaValue);
+ return _rasterMaskedRle(surface, rle, r, g, b, a, surface->blender.luma);
}
} else {
- if (opacity == 255) {
- return _rasterSolidRle(surface, rle, color);
+ if (a == 255) {
+ return _rasterSolidRle(surface, rle, r, g, b);
} else {
#if defined(THORVG_AVX_VECTOR_SUPPORT)
- return avxRasterTranslucentRle(surface, rle, color);
+ return avxRasterTranslucentRle(surface, rle, r, g, b, a);
#elif defined(THORVG_NEON_VECTOR_SUPPORT)
- return neonRasterTranslucentRle(surface, rle, color);
+ return neonRasterTranslucentRle(surface, rle, r, g, b, a);
#else
- return cRasterTranslucentRle(surface, rle, color);
+ return cRasterTranslucentRle(surface, rle, r, g, b, a);
#endif
}
}
@@ -301,7 +378,7 @@ static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, c
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, surface->blender.lumaValue);
+ return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, surface->blender.luma);
}
} else {
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, nullptr);
@@ -313,25 +390,26 @@ static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, c
/* RLE Scaled RGBA Image */
/************************************************************************/
-static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint8_t(*blender)(uint8_t*))
{
TVGLOG("SW_ENGINE", "Scaled Masked Translucent Rle Image");
auto span = image->rle->spans;
+ auto csize = surface->compositor->image.channelSize;
//Center (Down-Scaled)
if (image->scale < DOWN_SCALE_TOLERANCE) {
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue;
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
- auto alpha = _multiplyAlpha(span->coverage, opacity);
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize];
+ auto alpha = _multiply<uint32_t>(span->coverage, opacity);
+ for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), alpha);
- auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
+ auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), alpha);
+ auto tmp = ALPHA_BLEND(src, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
@@ -340,14 +418,14 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = span->y * itransform->e22 + itransform->e23;
if ((uint32_t)sy >= image->h) continue;
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
- auto alpha = _multiplyAlpha(span->coverage, opacity);
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize];
+ auto alpha = _multiply<uint32_t>(span->coverage, opacity);
+ for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha);
- auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
+ auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), alpha);
+ auto tmp = ALPHA_BLEND(src, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
@@ -356,32 +434,33 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const
}
-static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint8_t(*blender)(uint8_t*))
{
TVGLOG("SW_ENGINE", "Scaled Masked Rle Image");
auto span = image->rle->spans;
+ auto csize = surface->compositor->image.channelSize;
//Center (Down-Scaled)
if (image->scale < DOWN_SCALE_TOLERANCE) {
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue;
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize];
if (span->coverage == 255) {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
+ for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
- auto tmp = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp));
+ auto tmp = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
} else {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
+ for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), span->coverage);
- auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
+ auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), span->coverage);
+ auto tmp = ALPHA_BLEND(src, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
@@ -391,21 +470,21 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = span->y * itransform->e22 + itransform->e23;
if ((uint32_t)sy >= image->h) continue;
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize];
if (span->coverage == 255) {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
+ for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
- auto tmp = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), blendMethod(*cmp));
+ auto tmp = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
} else {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
+ for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage);
- auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
+ auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), span->coverage);
+ auto tmp = ALPHA_BLEND(src, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
@@ -424,12 +503,12 @@ static bool _rasterScaledTranslucentRleRGBAImage(SwSurface* surface, const SwIma
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue;
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto alpha = _multiplyAlpha(span->coverage, opacity);
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto alpha = _multiply<uint32_t>(span->coverage, opacity);
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), alpha);
+ auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
@@ -438,12 +517,12 @@ static bool _rasterScaledTranslucentRleRGBAImage(SwSurface* surface, const SwIma
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = span->y * itransform->e22 + itransform->e23;
if ((uint32_t)sy >= image->h) continue;
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto alpha = _multiplyAlpha(span->coverage, opacity);
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto alpha = _multiply<uint32_t>(span->coverage, opacity);
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha);
+ auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
@@ -461,19 +540,19 @@ static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image,
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue;
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
if (span->coverage == 255) {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
- auto src = _interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale);
+ auto src = _interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
} else {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), span->coverage);
+ auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), span->coverage);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
@@ -483,19 +562,19 @@ static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image,
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = span->y * itransform->e22 + itransform->e23;
if ((uint32_t)sy >= image->h) continue;
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
if (span->coverage == 255) {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
- auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy);
+ auto src = _interpUpScaler(image->buf32, image->w, image->h, sx, sy);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
} else {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage);
+ auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), span->coverage);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
@@ -522,7 +601,7 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.lumaValue);
+ return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.luma);
}
} else {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
@@ -530,7 +609,7 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.lumaValue);
+ return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.luma);
}
}
} else {
@@ -545,26 +624,27 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const
/* RLE Direct RGBA Image */
/************************************************************************/
-static bool _rasterDirectMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterDirectMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, uint8_t(*blender)(uint8_t*))
{
TVGLOG("SW_ENGINE", "Direct Masked Rle Image");
auto span = image->rle->spans;
- auto cbuffer = surface->compositor->image.data;
+ auto csize = surface->compositor->image.channelSize;
+ auto cbuffer = surface->compositor->image.buf8;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
- auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
- auto alpha = _multiplyAlpha(span->coverage, opacity);
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
+ auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox);
+ auto alpha = _multiply<uint32_t>(span->coverage, opacity);
if (alpha == 255) {
- for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) {
- auto tmp = ALPHA_BLEND(*img, blendMethod(*cmp));
+ for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*img, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
} else {
- for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) {
- auto tmp = ALPHA_BLEND(*img, _multiplyAlpha(alpha, blendMethod(*cmp)));
+ for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*img, _multiply<uint32_t>(alpha, blender(cmp)));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
@@ -573,25 +653,26 @@ static bool _rasterDirectMaskedTranslucentRleRGBAImage(SwSurface* surface, const
}
-static bool _rasterDirectMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterDirectMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, uint8_t(*blender)(uint8_t*))
{
TVGLOG("SW_ENGINE", "Direct Masked Rle Image");
auto span = image->rle->spans;
- auto cbuffer = surface->compositor->image.data;
+ auto csize = surface->compositor->image.channelSize;
+ auto cbuffer = surface->compositor->image.buf8;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
- auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
+ auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox);
if (span->coverage == 255) {
- for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) {
- auto tmp = ALPHA_BLEND(*img, blendMethod(*cmp));
+ for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*img, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
} else {
- for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) {
- auto tmp = ALPHA_BLEND(*img, _multiplyAlpha(span->coverage, blendMethod(*cmp)));
+ for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*img, _multiply<uint32_t>(span->coverage, blender(cmp)));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
@@ -605,9 +686,9 @@ static bool _rasterDirectTranslucentRleRGBAImage(SwSurface* surface, const SwIma
auto span = image->rle->spans;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
- auto alpha = _multiplyAlpha(span->coverage, opacity);
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox);
+ auto alpha = _multiply<uint32_t>(span->coverage, opacity);
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
auto src = ALPHA_BLEND(*img, alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
@@ -622,8 +703,8 @@ static bool _rasterDirectRleRGBAImage(SwSurface* surface, const SwImage* image)
auto span = image->rle->spans;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox);
if (span->coverage == 255) {
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
*dst = *img + ALPHA_BLEND(*dst, _ialpha(*img));
@@ -648,7 +729,7 @@ static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedRleRGBAImage(surface, image, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterDirectMaskedRleRGBAImage(surface, image, surface->blender.lumaValue);
+ return _rasterDirectMaskedRleRGBAImage(surface, image, surface->blender.luma);
}
} else {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
@@ -656,7 +737,7 @@ static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, surface->blender.lumaValue);
+ return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, surface->blender.luma);
}
}
} else {
@@ -679,7 +760,7 @@ static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, cons
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterTexmapPolygon(surface, image, transform, &region, opacity, surface->blender.lumaValue);
+ return _rasterTexmapPolygon(surface, image, transform, &region, opacity, surface->blender.luma);
}
} else {
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, nullptr);
@@ -687,18 +768,34 @@ static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, cons
return false;
}
+static bool _transformedRGBAImageMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity)
+{
+ if (_compositing(surface)) {
+ if (surface->compositor->method == CompositeMethod::AlphaMask) {
+ return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, _alpha);
+ } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
+ return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, surface->blender.luma);
+ }
+ } else {
+ return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, nullptr);
+ }
+ return false;
+}
+
/************************************************************************/
/*Scaled RGBA Image */
/************************************************************************/
-
-static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint8_t(*blender)(uint8_t*))
{
TVGLOG("SW_ENGINE", "Scaled Masked Image");
- auto dbuffer = surface->buffer + (region.min.y * surface->stride + region.min.x);
- auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride + region.min.x);
+ auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
+ auto csize = surface->compositor->image.channelSize;
+ auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize;
// Down-Scaled
if (image->scale < DOWN_SCALE_TOLERANCE) {
@@ -707,15 +804,15 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
if (sy >= image->h) continue;
auto dst = dbuffer;
auto cmp = cbuffer;
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
+ for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
- auto alpha = _multiplyAlpha(opacity, blendMethod(*cmp));
- auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), alpha);
+ auto alpha = _multiply<uint32_t>(opacity, blender(cmp));
+ auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
dbuffer += surface->stride;
- cbuffer += surface->compositor->image.stride;
+ cbuffer += surface->compositor->image.stride * csize;
}
// Up-Scaled
} else {
@@ -724,27 +821,28 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
if ((uint32_t)sy >= image->h) continue;
auto dst = dbuffer;
auto cmp = cbuffer;
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
+ for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
- auto alpha = _multiplyAlpha(opacity, blendMethod(*cmp));
- auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha);
+ auto alpha = _multiply<uint32_t>(opacity, blender(cmp));
+ auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
dbuffer += surface->stride;
- cbuffer += surface->compositor->image.stride;
+ cbuffer += surface->compositor->image.stride * csize;
}
}
return true;
}
-static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint8_t (*blender)(uint8_t*))
{
TVGLOG("SW_ENGINE", "Scaled Masked Image");
- auto dbuffer = surface->buffer + (region.min.y * surface->stride + region.min.x);
- auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride + region.min.x);
+ auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
+ auto csize = surface->compositor->image.channelSize;
+ auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize;
// Down-Scaled
if (image->scale < DOWN_SCALE_TOLERANCE) {
@@ -753,14 +851,14 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag
if (sy >= image->h) continue;
auto dst = dbuffer;
auto cmp = cbuffer;
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
+ for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp));
+ auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), blender(cmp));
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
dbuffer += surface->stride;
- cbuffer += surface->compositor->image.stride;
+ cbuffer += surface->compositor->image.stride * csize;
}
// Up-Scaled
} else {
@@ -769,14 +867,14 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag
if ((uint32_t)sy >= image->h) continue;
auto dst = dbuffer;
auto cmp = cbuffer;
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
+ for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), blendMethod(*cmp));
+ auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), blender(cmp));
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
dbuffer += surface->stride;
- cbuffer += surface->compositor->image.stride;
+ cbuffer += surface->compositor->image.stride * csize;
}
}
return true;
@@ -785,7 +883,7 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag
static bool _rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale)
{
- auto dbuffer = surface->buffer + (region.min.y * surface->stride + region.min.x);
+ auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
// Down-Scaled
if (image->scale < DOWN_SCALE_TOLERANCE) {
@@ -796,7 +894,7 @@ static bool _rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage*
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), opacity);
+ auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), opacity);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
@@ -809,7 +907,7 @@ static bool _rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage*
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
- auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), opacity);
+ auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), opacity);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
@@ -820,7 +918,7 @@ static bool _rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage*
static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale)
{
- auto dbuffer = surface->buffer + (region.min.y * surface->stride + region.min.x);
+ auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
// Down-Scaled
if (image->scale < DOWN_SCALE_TOLERANCE) {
@@ -831,7 +929,7 @@ static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, con
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
- auto src = _interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale);
+ auto src = _interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
@@ -844,7 +942,7 @@ static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, con
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
- auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy);
+ auto src = _interpUpScaler(image->buf32, image->w, image->h, sx, sy);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
@@ -870,7 +968,7 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.lumaValue);
+ return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.luma);
}
} else {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
@@ -878,7 +976,7 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.lumaValue);
+ return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.luma);
}
}
} else {
@@ -893,54 +991,56 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat
/* Direct RGBA Image */
/************************************************************************/
-static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t (*blender)(uint8_t*))
{
TVGLOG("SW_ENGINE", "Direct Masked Image");
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto h2 = static_cast<uint32_t>(region.max.y - region.min.y);
auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
+ auto csize = surface->compositor->image.channelSize;
- auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
- auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
+ auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
+ auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer
for (uint32_t y = 0; y < h2; ++y) {
auto dst = buffer;
auto cmp = cbuffer;
auto src = sbuffer;
- for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
- auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
+ for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*src, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
buffer += surface->stride;
- cbuffer += surface->compositor->image.stride;
+ cbuffer += surface->compositor->image.stride * csize;
sbuffer += image->stride;
}
return true;
}
-static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity, uint8_t (*blender)(uint8_t*))
{
TVGLOG("SW_ENGINE", "Direct Masked Translucent Image");
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto h2 = static_cast<uint32_t>(region.max.y - region.min.y);
auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
+ auto csize = surface->compositor->image.channelSize;
- auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
- auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
+ auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
+ auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer
for (uint32_t y = 0; y < h2; ++y) {
auto dst = buffer;
auto cmp = cbuffer;
auto src = sbuffer;
- for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
- auto tmp = ALPHA_BLEND(*src, _multiplyAlpha(opacity, blendMethod(*cmp)));
+ for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*src, _multiply<uint32_t>(opacity, blender(cmp)));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
buffer += surface->stride;
- cbuffer += surface->compositor->image.stride;
+ cbuffer += surface->compositor->image.stride * csize;
sbuffer += image->stride;
}
return true;
@@ -949,8 +1049,8 @@ static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
static bool _rasterDirectTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity)
{
- auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
- auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
+ auto dbuffer = &surface->buf32[region.min.y * surface->stride + region.min.x];
+ auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
for (auto y = region.min.y; y < region.max.y; ++y) {
auto dst = dbuffer;
@@ -968,8 +1068,8 @@ static bool _rasterDirectTranslucentRGBAImage(SwSurface* surface, const SwImage*
static bool _rasterDirectRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region)
{
- auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
- auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
+ auto dbuffer = &surface->buf32[region.min.y * surface->stride + region.min.x];
+ auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
for (auto y = region.min.y; y < region.max.y; ++y) {
auto dst = dbuffer;
@@ -994,7 +1094,7 @@ static bool _directRGBAImage(SwSurface* surface, const SwImage* image, const SwB
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedRGBAImage(surface, image, region, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterDirectMaskedRGBAImage(surface, image, region, surface->blender.lumaValue);
+ return _rasterDirectMaskedRGBAImage(surface, image, region, surface->blender.luma);
}
} else {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
@@ -1002,7 +1102,7 @@ static bool _directRGBAImage(SwSurface* surface, const SwImage* image, const SwB
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, surface->blender.lumaValue);
+ return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, surface->blender.luma);
}
}
} else {
@@ -1034,14 +1134,15 @@ static bool _rasterRGBAImage(SwSurface* surface, SwImage* image, const Matrix* t
/* Rect Linear Gradient */
/************************************************************************/
-static bool _rasterLinearGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterLinearGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint8_t (*blender)(uint8_t*))
{
if (fill->linear.len < FLT_EPSILON) return false;
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
- auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x;
+ auto csize = surface->compositor->image.channelSize;
+ auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize;
auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
if (!sbuffer) return false;
@@ -1051,12 +1152,12 @@ static bool _rasterLinearGradientMaskedRect(SwSurface* surface, const SwBBox& re
auto dst = buffer;
auto cmp = cbuffer;
auto src = sbuffer;
- for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp, ++src) {
- auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
+ for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*src, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
buffer += surface->stride;
- cbuffer += surface->stride;
+ cbuffer += surface->stride * csize;
}
return true;
}
@@ -1066,7 +1167,7 @@ static bool _rasterTranslucentLinearGradientRect(SwSurface* surface, const SwBBo
{
if (fill->linear.len < FLT_EPSILON) return false;
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
@@ -1089,7 +1190,7 @@ static bool _rasterSolidLinearGradientRect(SwSurface* surface, const SwBBox& reg
{
if (fill->linear.len < FLT_EPSILON) return false;
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
@@ -1108,7 +1209,7 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region,
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterLinearGradientMaskedRect(surface, region, fill, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterLinearGradientMaskedRect(surface, region, fill, surface->blender.lumaValue);
+ return _rasterLinearGradientMaskedRect(surface, region, fill, surface->blender.luma);
}
} else {
if (fill->translucent) return _rasterTranslucentLinearGradientRect(surface, region, fill);
@@ -1122,29 +1223,30 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region,
/* Rle Linear Gradient */
/************************************************************************/
-static bool _rasterLinearGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterLinearGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint8_t (*blender)(uint8_t*))
{
if (fill->linear.len < FLT_EPSILON) return false;
auto span = rle->spans;
- auto cbuffer = surface->compositor->image.data;
+ auto csize = surface->compositor->image.channelSize;
+ auto cbuffer = surface->compositor->image.buf8;
auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
if (!buffer) return false;
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
fillFetchLinear(fill, buffer, span->y, span->x, span->len);
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
auto src = buffer;
if (span->coverage == 255) {
- for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
- auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
+ for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*src, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
} else {
auto ialpha = 255 - span->coverage;
- for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
- auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
+ for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*src, blender(cmp));
tmp = ALPHA_BLEND(tmp, span->coverage) + ALPHA_BLEND(*dst, ialpha);
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
@@ -1163,7 +1265,7 @@ static bool _rasterTranslucentLinearGradientRle(SwSurface* surface, const SwRleD
if (!buffer) return false;
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
fillFetchLinear(fill, buffer, span->y, span->x, span->len);
if (span->coverage == 255) {
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
@@ -1191,10 +1293,10 @@ static bool _rasterSolidLinearGradientRle(SwSurface* surface, const SwRleData* r
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
if (span->coverage == 255) {
- fillFetchLinear(fill, surface->buffer + span->y * surface->stride + span->x, span->y, span->x, span->len);
+ fillFetchLinear(fill, surface->buf32 + span->y * surface->stride + span->x, span->y, span->x, span->len);
} else {
fillFetchLinear(fill, buf, span->y, span->x, span->len);
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
for (uint32_t x = 0; x < span->len; ++x) {
dst[x] = INTERPOLATE(span->coverage, buf[x], dst[x]);
}
@@ -1214,7 +1316,7 @@ static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, c
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterLinearGradientMaskedRle(surface, rle, fill, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterLinearGradientMaskedRle(surface, rle, fill, surface->blender.lumaValue);
+ return _rasterLinearGradientMaskedRle(surface, rle, fill, surface->blender.luma);
}
} else {
if (fill->translucent) return _rasterTranslucentLinearGradientRle(surface, rle, fill);
@@ -1228,14 +1330,15 @@ static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, c
/* Rect Radial Gradient */
/************************************************************************/
-static bool _rasterRadialGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterRadialGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint8_t(*blender)(uint8_t*))
{
if (fill->radial.a < FLT_EPSILON) return false;
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
- auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x;
+ auto csize = surface->compositor->image.channelSize;
+ auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize;
auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
if (!sbuffer) return false;
@@ -1245,12 +1348,12 @@ static bool _rasterRadialGradientMaskedRect(SwSurface* surface, const SwBBox& re
auto dst = buffer;
auto cmp = cbuffer;
auto src = sbuffer;
- for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp, ++src) {
- auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
+ for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*src, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
buffer += surface->stride;
- cbuffer += surface->stride;
+ cbuffer += surface->stride * csize;
}
return true;
}
@@ -1260,7 +1363,7 @@ static bool _rasterTranslucentRadialGradientRect(SwSurface* surface, const SwBBo
{
if (fill->radial.a < FLT_EPSILON) return false;
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
@@ -1283,7 +1386,7 @@ static bool _rasterSolidRadialGradientRect(SwSurface* surface, const SwBBox& reg
{
if (fill->radial.a < FLT_EPSILON) return false;
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
@@ -1303,7 +1406,7 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterRadialGradientMaskedRect(surface, region, fill, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterRadialGradientMaskedRect(surface, region, fill, surface->blender.lumaValue);
+ return _rasterRadialGradientMaskedRect(surface, region, fill, surface->blender.luma);
}
} else {
if (fill->translucent) return _rasterTranslucentRadialGradientRect(surface, region, fill);
@@ -1317,28 +1420,29 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
/* RLE Radial Gradient */
/************************************************************************/
-static bool _rasterRadialGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterRadialGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint8_t(*blender)(uint8_t*))
{
if (fill->radial.a < FLT_EPSILON) return false;
auto span = rle->spans;
- auto cbuffer = surface->compositor->image.data;
+ auto csize = surface->compositor->image.channelSize;
+ auto cbuffer = surface->compositor->image.buf8;
auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
if (!buffer) return false;
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
fillFetchRadial(fill, buffer, span->y, span->x, span->len);
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
- auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
auto src = buffer;
if (span->coverage == 255) {
- for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
- auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
+ for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src, cmp += csize) {
+ auto tmp = ALPHA_BLEND(*src, blender(cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
} else {
- for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
- auto tmp = INTERPOLATE(span->coverage, ALPHA_BLEND(*src, blendMethod(*cmp)), *dst);
+ for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src, cmp += csize) {
+ auto tmp = INTERPOLATE(span->coverage, ALPHA_BLEND(*src, blender(cmp)), *dst);
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
@@ -1356,7 +1460,7 @@ static bool _rasterTranslucentRadialGradientRle(SwSurface* surface, const SwRleD
if (!buffer) return false;
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
fillFetchRadial(fill, buffer, span->y, span->x, span->len);
if (span->coverage == 255) {
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
@@ -1383,7 +1487,7 @@ static bool _rasterSolidRadialGradientRle(SwSurface* surface, const SwRleData* r
auto span = rle->spans;
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
if (span->coverage == 255) {
fillFetchRadial(fill, dst, span->y, span->x, span->len);
} else {
@@ -1408,7 +1512,7 @@ static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, c
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterRadialGradientMaskedRle(surface, rle, fill, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
- return _rasterRadialGradientMaskedRle(surface, rle, fill, surface->blender.lumaValue);
+ return _rasterRadialGradientMaskedRle(surface, rle, fill, surface->blender.luma);
}
} else {
if (fill->translucent) _rasterTranslucentRadialGradientRle(surface, rle, fill);
@@ -1417,7 +1521,6 @@ static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, c
return false;
}
-
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
@@ -1429,47 +1532,65 @@ void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
#elif defined(THORVG_NEON_VECTOR_SUPPORT)
neonRasterRGBA32(dst, val, offset, len);
#else
- cRasterRGBA32(dst, val, offset, len);
+ cRasterPixels<uint32_t>(dst, val, offset, len);
#endif
}
bool rasterCompositor(SwSurface* surface)
{
- if (surface->cs == SwCanvas::ABGR8888 || surface->cs == SwCanvas::ABGR8888_STRAIGHT) {
+ if (surface->cs == ColorSpace::ABGR8888 || surface->cs == ColorSpace::ABGR8888S) {
surface->blender.join = _abgrJoin;
- surface->blender.lumaValue = _abgrLumaValue;
- } else if (surface->cs == SwCanvas::ARGB8888 || surface->cs == SwCanvas::ARGB8888_STRAIGHT) {
+ surface->blender.luma = _abgrLuma;
+ } else if (surface->cs == ColorSpace::ARGB8888 || surface->cs == ColorSpace::ARGB8888S) {
surface->blender.join = _argbJoin;
- surface->blender.lumaValue = _argbLumaValue;
+ surface->blender.luma = _argbLuma;
} else {
- //What Color Space ???
+ TVGERR("SW_ENGINE", "Unsupported Colorspace(%d) is expected!", surface->cs);
return false;
}
return true;
}
-bool rasterClear(SwSurface* surface)
+bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
- if (!surface || !surface->buffer || surface->stride <= 0 || surface->w <= 0 || surface->h <= 0) return false;
+ if (!surface || !surface->buf32 || surface->stride == 0 || surface->w == 0 || surface->h == 0) return false;
- if (surface->w == surface->stride) {
- rasterRGBA32(surface->buffer, 0x00000000, 0, surface->w * surface->h);
- } else {
- for (uint32_t i = 0; i < surface->h; i++) {
- rasterRGBA32(surface->buffer + surface->stride * i, 0x00000000, 0, surface->w);
+ //full clear
+ if (surface->channelSize == sizeof(uint32_t)) {
+ if (w == surface->stride) {
+ rasterRGBA32(surface->buf32 + (surface->stride * y), 0x00000000, 0, w * h);
+ } else {
+ auto buffer = surface->buf32 + (surface->stride * y + x);
+ for (uint32_t i = 0; i < h; i++) {
+ rasterRGBA32(buffer + (surface->stride * i), 0x00000000, 0, w);
+ }
+ }
+ //partial clear
+ } else if (surface->channelSize == sizeof(uint8_t)) {
+ if (w == surface->stride) {
+ _rasterGrayscale8(surface->buf8 + (surface->stride * y), 0x00, 0, w * h);
+ } else {
+ auto buffer = surface->buf8 + (surface->stride * y + x);
+ for (uint32_t i = 0; i < h; i++) {
+ _rasterGrayscale8(buffer + (surface->stride * i), 0x00, 0, w);
+ }
}
}
return true;
}
-void rasterUnpremultiply(SwSurface* surface)
+void rasterUnpremultiply(Surface* surface)
{
+ if (surface->channelSize != sizeof(uint32_t)) return;
+
+ TVGLOG("SW_ENGINE", "Unpremultiply [Size: %d x %d]", surface->w, surface->h);
+
//OPTIMIZE_ME: +SIMD
for (uint32_t y = 0; y < surface->h; y++) {
- auto buffer = surface->buffer + surface->stride * y;
+ auto buffer = surface->buf32 + surface->stride * y;
for (uint32_t x = 0; x < surface->w; ++x) {
uint8_t a = buffer[x] >> 24;
if (a == 255) {
@@ -1487,11 +1608,37 @@ void rasterUnpremultiply(SwSurface* surface)
}
}
}
+ surface->premultiplied = false;
+}
+
+
+void rasterPremultiply(Surface* surface)
+{
+ if (surface->channelSize != sizeof(uint32_t)) return;
+
+ TVGLOG("SW_ENGINE", "Premultiply [Size: %d x %d]", surface->w, surface->h);
+
+ //OPTIMIZE_ME: +SIMD
+ auto buffer = surface->buf32;
+ for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride) {
+ auto dst = buffer;
+ for (uint32_t x = 0; x < surface->w; ++x, ++dst) {
+ auto c = *dst;
+ auto a = (c >> 24);
+ *dst = (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff);
+ }
+ }
+ surface->premultiplied = true;
}
bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id)
{
+ if (surface->channelSize == sizeof(uint8_t)) {
+ TVGERR("SW_ENGINE", "Not supported grayscale gradient!");
+ return false;
+ }
+
if (!shape->fill) return false;
if (shape->fastTrack) {
@@ -1507,6 +1654,11 @@ bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id)
bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id)
{
+ if (surface->channelSize == sizeof(uint8_t)) {
+ TVGERR("SW_ENGINE", "Not supported grayscale gradient!");
+ return false;
+ }
+
if (!shape->stroke || !shape->stroke->fill || !shape->strokeRle) return false;
if (id == TVG_CLASS_ID_LINEAR) return _rasterLinearGradientRle(surface, shape->strokeRle, shape->stroke->fill);
@@ -1519,40 +1671,60 @@ bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id)
bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
if (a < 255) {
- r = _multiplyAlpha(r, a);
- g = _multiplyAlpha(g, a);
- b = _multiplyAlpha(b, a);
+ r = _multiply<uint32_t>(r, a);
+ g = _multiply<uint32_t>(g, a);
+ b = _multiply<uint32_t>(b, a);
}
- auto color = surface->blender.join(r, g, b, a);
-
- if (shape->fastTrack) return _rasterRect(surface, shape->bbox, color, a);
- else return _rasterRle(surface, shape->rle, color, a);
+ if (shape->fastTrack) return _rasterRect(surface, shape->bbox, r, g, b, a);
+ else return _rasterRle(surface, shape->rle, r, g, b, a);
}
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
if (a < 255) {
- r = _multiplyAlpha(r, a);
- g = _multiplyAlpha(g, a);
- b = _multiplyAlpha(b, a);
+ r = _multiply<uint32_t>(r, a);
+ g = _multiply<uint32_t>(g, a);
+ b = _multiply<uint32_t>(b, a);
}
- auto color = surface->blender.join(r, g, b, a);
-
- return _rasterRle(surface, shape->strokeRle, color, a);
+ return _rasterRle(surface, shape->strokeRle, r, g, b, a);
}
-bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity)
+bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& bbox, uint32_t opacity)
{
+ if (surface->channelSize == sizeof(uint8_t)) {
+ TVGERR("SW_ENGINE", "Not supported grayscale image!");
+ return false;
+ }
+
//Verify Boundary
if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= static_cast<SwCoord>(surface->w) || bbox.min.y >= static_cast<SwCoord>(surface->h)) return false;
//TOOD: switch (image->format)
- //TODO: case: _rasterRGBImage()
- //TODO: case: _rasterGrayscaleImage()
- //TODO: case: _rasterAlphaImage()
- return _rasterRGBAImage(surface, image, transform, bbox, opacity);
+ //TODO: case: _rasterRGBImageMesh()
+ //TODO: case: _rasterGrayscaleImageMesh()
+ //TODO: case: _rasterAlphaImageMesh()
+ if (mesh && mesh->triangleCnt > 0) return _transformedRGBAImageMesh(surface, image, mesh, transform, &bbox, opacity);
+ else return _rasterRGBAImage(surface, image, transform, bbox, opacity);
+}
+
+
+bool rasterConvertCS(Surface* surface, ColorSpace to)
+{
+ //TOOD: Support SIMD accelerations
+ auto from = surface->cs;
+
+ if ((from == ColorSpace::ABGR8888 && to == ColorSpace::ARGB8888) || (from == ColorSpace::ABGR8888S && to == ColorSpace::ARGB8888S)) {
+ surface->cs = to;
+ return cRasterABGRtoARGB(surface);
+ }
+ if ((from == ColorSpace::ARGB8888 && to == ColorSpace::ABGR8888) || (from == ColorSpace::ARGB8888S && to == ColorSpace::ABGR8888S)) {
+ surface->cs = to;
+ return cRasterARGBtoABGR(surface);
+ }
+
+ return false;
}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h
index 7a129a3a80..cf658a6abb 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -82,9 +82,15 @@ static void avxRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_
}
-static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
+static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
+ if (surface->channelSize != sizeof(uint32_t)) {
+ TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
+ return false;
+ }
+
+ auto color = surface->blender.join(r, g, b, a);
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
@@ -125,13 +131,19 @@ static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, u
}
-static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
+static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
+ if (surface->channelSize != sizeof(uint32_t)) {
+ TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
+ return false;
+ }
+
+ auto color = surface->blender.join(r, g, b, a);
auto span = rle->spans;
uint32_t src;
for (uint32_t i = 0; i < rle->size; ++i) {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
else src = color;
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterC.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterC.h
index de6b35fd64..ad2fc57f24 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterC.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterC.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,45 +20,95 @@
* SOFTWARE.
*/
-
-static void inline cRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
+template<typename PIXEL_T>
+static void inline cRasterPixels(PIXEL_T* dst, uint32_t val, uint32_t offset, int32_t len)
{
dst += offset;
while (len--) *dst++ = val;
}
-static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
+static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
auto span = rle->spans;
- uint32_t src;
-
- for (uint32_t i = 0; i < rle->size; ++i, ++span) {
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
-
- if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
- else src = color;
- for (uint32_t x = 0; x < span->len; ++x, ++dst) {
- *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
+ //32bit channels
+ if (surface->channelSize == sizeof(uint32_t)) {
+ auto color = surface->blender.join(r, g, b, a);
+ uint32_t src;
+ for (uint32_t i = 0; i < rle->size; ++i, ++span) {
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
+ if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
+ else src = color;
+ for (uint32_t x = 0; x < span->len; ++x, ++dst) {
+ *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
+ }
+ }
+ //8bit grayscale
+ } else if (surface->channelSize == sizeof(uint8_t)) {
+ uint8_t src;
+ for (uint32_t i = 0; i < rle->size; ++i, ++span) {
+ auto dst = &surface->buf8[span->y * surface->stride + span->x];
+ if (span->coverage < 255) src = _multiply<uint8_t>(span->coverage, a);
+ else src = a;
+ for (uint32_t x = 0; x < span->len; ++x, ++dst) {
+ *dst = src + _multiply<uint8_t>(*dst, ~src);
+ }
}
}
return true;
}
-static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
+static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
- auto ialpha = _ialpha(color);
- for (uint32_t y = 0; y < h; ++y) {
- auto dst = &buffer[y * surface->stride];
- for (uint32_t x = 0; x < w; ++x, ++dst) {
- *dst = color + ALPHA_BLEND(*dst, ialpha);
+ //32bits channels
+ if (surface->channelSize == sizeof(uint32_t)) {
+ auto color = surface->blender.join(r, g, b, a);
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
+ auto ialpha = _ialpha(color);
+ for (uint32_t y = 0; y < h; ++y) {
+ auto dst = &buffer[y * surface->stride];
+ for (uint32_t x = 0; x < w; ++x, ++dst) {
+ *dst = color + ALPHA_BLEND(*dst, ialpha);
+ }
+ }
+ //8bit grayscale
+ } else if (surface->channelSize == sizeof(uint8_t)) {
+ auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x;
+ for (uint32_t y = 0; y < h; ++y) {
+ auto dst = &buffer[y * surface->stride];
+ for (uint32_t x = 0; x < w; ++x, ++dst) {
+ *dst = a + _multiply<uint8_t>(*dst, ~a);
+ }
}
}
return true;
}
+
+
+static bool inline cRasterABGRtoARGB(Surface* surface)
+{
+ TVGLOG("SW_ENGINE", "Convert ColorSpace ABGR - ARGB [Size: %d x %d]", surface->w, surface->h);
+
+ auto buffer = surface->buf32;
+ for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride) {
+ auto dst = buffer;
+ for (uint32_t x = 0; x < surface->w; ++x, ++dst) {
+ auto c = *dst;
+ //flip Blue, Red channels
+ *dst = (c & 0xff000000) + ((c & 0x00ff0000) >> 16) + (c & 0x0000ff00) + ((c & 0x000000ff) << 16);
+ }
+ }
+ return true;
+}
+
+
+static bool inline cRasterARGBtoABGR(Surface* surface)
+{
+ //exactly same with ABGRtoARGB
+ return cRasterABGRtoARGB(surface);
+}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterNeon.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterNeon.h
index a4b3cdaeb2..33c3d181b5 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterNeon.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterNeon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -49,8 +49,14 @@ static void neonRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32
}
-static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
+static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
+ if (surface->channelSize != sizeof(uint32_t)) {
+ TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
+ return false;
+ }
+
+ auto color = surface->blender.join(r, g, b, a);
auto span = rle->spans;
uint32_t src;
uint8x8_t *vDst = nullptr;
@@ -60,7 +66,7 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, u
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
else src = color;
- auto dst = &surface->buffer[span->y * surface->stride + span->x];
+ auto dst = &surface->buf32[span->y * surface->stride + span->x];
auto ialpha = 255 - _alpha(src);
if ((((uint32_t) dst) & 0x7) != 0) {
@@ -88,9 +94,15 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, u
}
-static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
+static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
- auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
+ if (surface->channelSize != sizeof(uint32_t)) {
+ TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
+ return false;
+ }
+
+ auto color = surface->blender.join(r, g, b, a);
+ auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
auto ialpha = 255 - _alpha(color);
@@ -116,7 +128,7 @@ static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region,
for (uint32_t x = 0; x < (w - align) / 2; ++x)
vDst[x] = vadd_u8((uint8x8_t)vColor, ALPHA_BLEND(vDst[x], vIalpha));
-
+
auto leftovers = (w - align) % 2;
if (leftovers > 0) dst[w - 1] = color + ALPHA_BLEND(dst[w - 1], ialpha);
}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h
index abb57d7c45..52585162fc 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,17 +20,6 @@
* SOFTWARE.
*/
-struct Vertex
-{
- Point pt;
- Point uv;
-};
-
-struct Polygon
-{
- Vertex vertex[3];
-};
-
struct AALine
{
int32_t x[2];
@@ -80,7 +69,7 @@ static bool _arrange(const SwImage* image, const SwBBox* region, int& yStart, in
}
-static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint32_t (*blendMethod)(uint32_t), AASpans* aaSpans)
+static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
{
#define TEXMAP_TRANSLUCENT
#define TEXMAP_MASKING
@@ -90,7 +79,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
}
-static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t (*blendMethod)(uint32_t), AASpans* aaSpans)
+static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
{
#define TEXMAP_MASKING
#include "tvgSwRasterTexmapInternal.h"
@@ -113,7 +102,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
/* This mapping algorithm is based on Mikael Kalms's. */
-static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint32_t (*blendMethod)(uint32_t), AASpans* aaSpans)
+static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
{
float x[3] = {polygon.vertex[0].pt.x, polygon.vertex[1].pt.x, polygon.vertex[2].pt.x};
float y[3] = {polygon.vertex[0].pt.y, polygon.vertex[1].pt.y, polygon.vertex[2].pt.y};
@@ -201,9 +190,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
dxdyb = dxdy[0];
xb = x[0] + dy * dxdyb + (off_y * dxdyb);
- if (blendMethod) {
- if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blendMethod, aaSpans);
- else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blendMethod, aaSpans);
+ if (blender) {
+ if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blender, aaSpans);
+ else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blender, aaSpans);
} else {
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
@@ -222,9 +211,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
// Set right edge X-slope and perform subpixel pre-stepping
dxdyb = dxdy[2];
xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb);
- if (blendMethod) {
- if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blendMethod, aaSpans);
- else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blendMethod, aaSpans);
+ if (blender) {
+ if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blender, aaSpans);
+ else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blender, aaSpans);
} else {
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
@@ -251,9 +240,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
ua = u[0] + dy * dudya + (off_y * dudya);
va = v[0] + dy * dvdya + (off_y * dvdya);
- if (blendMethod) {
- if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blendMethod, aaSpans);
- else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blendMethod, aaSpans);
+ if (blender) {
+ if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blender, aaSpans);
+ else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blender, aaSpans);
} else {
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
@@ -275,9 +264,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
ua = u[1] + dy * dudya + (off_y * dudya);
va = v[1] + dy * dvdya + (off_y * dvdya);
- if (blendMethod) {
- if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blendMethod, aaSpans);
- else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blendMethod, aaSpans);
+ if (blender) {
+ if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blender, aaSpans);
+ else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blender, aaSpans);
} else {
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
@@ -287,18 +276,10 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
}
-static AASpans* _AASpans(const Vertex* vertices, const SwImage* image, const SwBBox* region)
+static AASpans* _AASpans(float ymin, float ymax, const SwImage* image, const SwBBox* region)
{
- //Initialize Y range
- float ys = FLT_MAX, ye = -1.0f;
-
- for (int i = 0; i < 4; i++) {
- if (vertices[i].pt.y < ys) ys = vertices[i].pt.y;
- if (vertices[i].pt.y > ye) ye = vertices[i].pt.y;
- }
-
- auto yStart = static_cast<int32_t>(ys);
- auto yEnd = static_cast<int32_t>(ye);
+ auto yStart = static_cast<int32_t>(ymin);
+ auto yEnd = static_cast<int32_t>(ymax);
if (!_arrange(image, region, yStart, yEnd)) return nullptr;
@@ -521,7 +502,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
auto offset = y * surface->stride;
//Left edge
- dst = surface->buffer + (offset + line->x[0]);
+ dst = surface->buf32 + (offset + line->x[0]);
if (line->x[0] > 1) pixel = *(dst - 1);
else pixel = *dst;
@@ -533,10 +514,10 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
}
//Right edge
- dst = surface->buffer + (offset + line->x[1] - 1);
+ dst = surface->buf32 + (offset + line->x[1] - 1);
if (line->x[1] < (int32_t)(surface->w - 1)) pixel = *(dst + 1);
else pixel = *dst;
-
+
pos = width;
while ((int32_t)(width - line->length[1]) < pos) {
*dst = INTERPOLATE(255 - (line->coverage[1] * (line->length[1] - (width - pos))), *dst, pixel);
@@ -562,12 +543,12 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
0 -- 1
| / |
| / |
- 3 -- 2
+ 3 -- 2
*/
-static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
+static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint8_t(*blender)(uint8_t*))
{
//Exceptions: No dedicated drawing area?
- if (!region && image->rle->size == 0) return false;
+ if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
/* Prepare vertices.
shift XY coordinates to match the sub-pixeling technique. */
@@ -577,9 +558,15 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
vertices[2] = {{float(image->w), float(image->h)}, {float(image->w), float(image->h)}};
vertices[3] = {{0.0f, float(image->h)}, {0.0f, float(image->h)}};
- for (int i = 0; i < 4; i++) mathMultiply(&vertices[i].pt, transform);
+ float ys = FLT_MAX, ye = -1.0f;
+ for (int i = 0; i < 4; i++) {
+ mathMultiply(&vertices[i].pt, transform);
- auto aaSpans = _AASpans(vertices, image, region);
+ if (vertices[i].pt.y < ys) ys = vertices[i].pt.y;
+ if (vertices[i].pt.y > ye) ye = vertices[i].pt.y;
+ }
+
+ auto aaSpans = _AASpans(ys, ye, image, region);
if (!aaSpans) return true;
Polygon polygon;
@@ -589,14 +576,72 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
polygon.vertex[1] = vertices[1];
polygon.vertex[2] = vertices[3];
- _rasterPolygonImage(surface, image, region, opacity, polygon, blendMethod, aaSpans);
+ _rasterPolygonImage(surface, image, region, opacity, polygon, blender, aaSpans);
//Draw the second polygon
polygon.vertex[0] = vertices[1];
polygon.vertex[1] = vertices[2];
polygon.vertex[2] = vertices[3];
- _rasterPolygonImage(surface, image, region, opacity, polygon, blendMethod, aaSpans);
+ _rasterPolygonImage(surface, image, region, opacity, polygon, blender, aaSpans);
return _apply(surface, aaSpans);
}
+
+
+/*
+ Provide any number of triangles to draw a mesh using the supplied image.
+ Indexes are not used, so each triangle (Polygon) vertex has to be defined, even if they copy the previous one.
+ Example:
+
+ 0 -- 1 0 -- 1 0
+ | / | --> | / / |
+ | / | | / / |
+ 2 -- 3 2 1 -- 2
+
+ Should provide two Polygons, one for each triangle.
+ // TODO: region?
+*/
+static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint8_t(*blender)(uint8_t*))
+{
+ //Exceptions: No dedicated drawing area?
+ if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
+
+ // Step polygons once to transform
+ auto transformedTris = (Polygon*)malloc(sizeof(Polygon) * mesh->triangleCnt);
+ float ys = FLT_MAX, ye = -1.0f;
+ for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
+ transformedTris[i] = mesh->triangles[i];
+ mathMultiply(&transformedTris[i].vertex[0].pt, transform);
+ mathMultiply(&transformedTris[i].vertex[1].pt, transform);
+ mathMultiply(&transformedTris[i].vertex[2].pt, transform);
+
+ if (transformedTris[i].vertex[0].pt.y < ys) ys = transformedTris[i].vertex[0].pt.y;
+ else if (transformedTris[i].vertex[0].pt.y > ye) ye = transformedTris[i].vertex[0].pt.y;
+ if (transformedTris[i].vertex[1].pt.y < ys) ys = transformedTris[i].vertex[1].pt.y;
+ else if (transformedTris[i].vertex[1].pt.y > ye) ye = transformedTris[i].vertex[1].pt.y;
+ if (transformedTris[i].vertex[2].pt.y < ys) ys = transformedTris[i].vertex[2].pt.y;
+ else if (transformedTris[i].vertex[2].pt.y > ye) ye = transformedTris[i].vertex[2].pt.y;
+
+ // Convert normalized UV coordinates to image coordinates
+ transformedTris[i].vertex[0].uv.x *= (float)image->w;
+ transformedTris[i].vertex[0].uv.y *= (float)image->h;
+ transformedTris[i].vertex[1].uv.x *= (float)image->w;
+ transformedTris[i].vertex[1].uv.y *= (float)image->h;
+ transformedTris[i].vertex[2].uv.x *= (float)image->w;
+ transformedTris[i].vertex[2].uv.y *= (float)image->h;
+ }
+
+ // Get AA spans and step polygons again to draw
+ auto aaSpans = _AASpans(ys, ye, image, region);
+ if (aaSpans) {
+ for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
+ _rasterPolygonImage(surface, image, region, opacity, transformedTris[i], blender, aaSpans);
+ }
+ // Apply to surface (note: frees the AA spans)
+ _apply(surface, aaSpans);
+ }
+ free(transformedTris);
+
+ return true;
+}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h
index 50536299b1..51685fe6e8 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,12 +19,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
{
float _dudx = dudx, _dvdx = dvdx;
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
float _xa = xa, _xb = xb, _ua = ua, _va = va;
- auto sbuf = image->data;
- auto dbuf = surface->buffer;
+ auto sbuf = image->buf32;
+ auto dbuf = surface->buf32;
int32_t sw = static_cast<int32_t>(image->stride);
int32_t sh = image->h;
int32_t dw = surface->stride;
@@ -36,7 +37,8 @@
SwSpan* span = nullptr; //used only when rle based.
#ifdef TEXMAP_MASKING
- uint32_t* cmp;
+ uint8_t* cmp;
+ auto csize = surface->compositor->image.channelSize;
#endif
if (!_arrange(image, region, yStart, yEnd)) return;
@@ -93,7 +95,7 @@
x = x1;
#ifdef TEXMAP_MASKING
- cmp = &surface->compositor->image.data[y * surface->compositor->image.stride + x1];
+ cmp = &surface->compositor->image.buf8[(y * surface->compositor->image.stride + x1) * csize];
#endif
//Draw horizontal line
while (x++ < x2) {
@@ -104,6 +106,9 @@
ab = (int)(255 * (1 - modff(v, &iptr)));
iru = uu + 1;
irv = vv + 1;
+
+ if (vv >= sh) continue;
+
px = *(sbuf + (vv * sw) + uu);
/* horizontal interpolate */
@@ -126,9 +131,9 @@
px = INTERPOLATE(ab, px, px2);
}
#if defined(TEXMAP_MASKING) && defined(TEXMAP_TRANSLUCENT)
- auto src = ALPHA_BLEND(px, _multiplyAlpha(opacity, blendMethod(*cmp)));
+ auto src = ALPHA_BLEND(px, _multiply<uint32_t>(opacity, blender(cmp)));
#elif defined(TEXMAP_MASKING)
- auto src = ALPHA_BLEND(px, blendMethod(*cmp));
+ auto src = ALPHA_BLEND(px, blender(cmp));
#elif defined(TEXMAP_TRANSLUCENT)
auto src = ALPHA_BLEND(px, opacity);
#else
@@ -137,7 +142,7 @@
*buf = src + ALPHA_BLEND(*buf, _ialpha(src));
++buf;
#ifdef TEXMAP_MASKING
- ++cmp;
+ cmp += csize;
#endif
//Step UV horizontally
u += _dudx;
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp
index a1c0032a2e..6223bc8722 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgMath.h"
#include "tvgSwCommon.h"
#include "tvgTaskScheduler.h"
@@ -60,6 +61,8 @@ struct SwTask : Task
}
virtual bool dispose() = 0;
+ virtual bool clip(SwRleData* target) = 0;
+ virtual SwRleData* rle() = 0;
virtual ~SwTask()
{
@@ -71,23 +74,39 @@ struct SwTask : Task
struct SwShapeTask : SwTask
{
SwShape shape;
- const Shape* sdata = nullptr;
+ const RenderShape* rshape = nullptr;
bool cmpStroking = false;
+ bool clipper = false;
+
+ bool clip(SwRleData* target) override
+ {
+ if (shape.fastTrack) rleClipRect(target, &bbox);
+ else if (shape.rle) rleClipPath(target, shape.rle);
+ else return false;
+
+ return true;
+ }
+
+ SwRleData* rle() override
+ {
+ if (!shape.rle && shape.fastTrack) {
+ shape.rle = rleRender(&shape.bbox);
+ }
+ return shape.rle;
+ }
void run(unsigned tid) override
{
- auto compMethod = CompositeMethod::None;
- auto usedAsClip = (sdata->composite(nullptr, &compMethod) == Result::Success) && (compMethod == CompositeMethod::ClipPath);
- if (opacity == 0 && !usedAsClip) return; //Invisible
+ if (opacity == 0 && !clipper) return; //Invisible
uint8_t strokeAlpha = 0;
auto visibleStroke = false;
bool visibleFill = false;
auto clipRegion = bbox;
- if (HALF_STROKE(sdata->strokeWidth()) > 0) {
- sdata->strokeColor(nullptr, nullptr, nullptr, &strokeAlpha);
- visibleStroke = sdata->strokeFill() || (static_cast<uint32_t>(strokeAlpha * opacity / 255) > 0);
+ if (HALF_STROKE(rshape->strokeWidth()) > 0) {
+ rshape->strokeColor(nullptr, nullptr, nullptr, &strokeAlpha);
+ visibleStroke = rshape->strokeFill() || (static_cast<uint32_t>(strokeAlpha * opacity / 255) > 0);
}
//This checks also for the case, if the invisible shape turned to visible by alpha.
@@ -97,12 +116,12 @@ struct SwShapeTask : SwTask
//Shape
if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform) || prepareShape) {
uint8_t alpha = 0;
- sdata->fillColor(nullptr, nullptr, nullptr, &alpha);
+ rshape->fillColor(nullptr, nullptr, nullptr, &alpha);
alpha = static_cast<uint8_t>(static_cast<uint32_t>(alpha) * opacity / 255);
- visibleFill = (alpha > 0 || sdata->fill());
- if (visibleFill || visibleStroke || usedAsClip) {
+ visibleFill = (alpha > 0 || rshape->fill);
+ if (visibleFill || visibleStroke || clipper) {
shapeReset(&shape);
- if (!shapePrepare(&shape, sdata, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err;
+ if (!shapePrepare(&shape, rshape, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err;
}
}
@@ -112,16 +131,16 @@ struct SwShapeTask : SwTask
//Fill
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
- if (visibleFill || usedAsClip) {
+ if (visibleFill || clipper) {
/* We assume that if stroke width is bigger than 2,
shape outline below stroke could be full covered by stroke drawing.
Thus it turns off antialising in that condition.
Also, it shouldn't be dash style. */
- auto antiAlias = (strokeAlpha == 255 && sdata->strokeWidth() > 2 && sdata->strokeDash(nullptr) == 0) ? false : true;
+ auto antiAlias = strokeAlpha < 255 || rshape->strokeWidth() <= 2 || rshape->strokeDash(nullptr) > 0 || (rshape->stroke && rshape->stroke->strokeFirst);
- if (!shapeGenRle(&shape, sdata, antiAlias)) goto err;
+ if (!shapeGenRle(&shape, rshape, antiAlias)) goto err;
}
- if (auto fill = sdata->fill()) {
+ if (auto fill = rshape->fill) {
auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
if (ctable) shapeResetFill(&shape);
if (!shapeGenFillColors(&shape, fill, transform, surface, cmpStroking ? 255 : opacity, ctable)) goto err;
@@ -133,10 +152,10 @@ struct SwShapeTask : SwTask
//Stroke
if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
if (visibleStroke) {
- shapeResetStroke(&shape, sdata, transform);
- if (!shapeGenStrokeRle(&shape, sdata, transform, clipRegion, bbox, mpool, tid)) goto err;
+ shapeResetStroke(&shape, rshape, transform);
+ if (!shapeGenStrokeRle(&shape, rshape, transform, clipRegion, bbox, mpool, tid)) goto err;
- if (auto fill = sdata->strokeFill()) {
+ if (auto fill = rshape->strokeFill()) {
auto ctable = (flags & RenderUpdateFlag::GradientStroke) ? true : false;
if (ctable) shapeResetStrokeFill(&shape);
if (!shapeGenStrokeFillColors(&shape, fill, transform, surface, cmpStroking ? 255 : opacity, ctable)) goto err;
@@ -148,27 +167,21 @@ struct SwShapeTask : SwTask
}
}
+ //Clear current task memorypool here if the clippers would use the same memory pool
+ shapeDelOutline(&shape, mpool, tid);
+
//Clip Path
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
- auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
+ auto clipper = static_cast<SwTask*>(*clip);
//Clip shape rle
- if (shape.rle) {
- if (clipper->fastTrack) rleClipRect(shape.rle, &clipper->bbox);
- else if (clipper->rle) rleClipPath(shape.rle, clipper->rle);
- else goto err;
- }
+ if (shape.rle && !clipper->clip(shape.rle)) goto err;
//Clip stroke rle
- if (shape.strokeRle) {
- if (clipper->fastTrack) rleClipRect(shape.strokeRle, &clipper->bbox);
- else if (clipper->rle) rleClipPath(shape.strokeRle, clipper->rle);
- else goto err;
- }
+ if (shape.strokeRle && !clipper->clip(shape.strokeRle)) goto err;
}
- goto end;
+ return;
err:
shapeReset(&shape);
- end:
shapeDelOutline(&shape, mpool, tid);
}
@@ -180,35 +193,116 @@ struct SwShapeTask : SwTask
};
+struct SwSceneTask : SwTask
+{
+ Array<RenderData> scene; //list of paints render data (SwTask)
+ SwRleData* sceneRle = nullptr;
+
+ bool clip(SwRleData* target) override
+ {
+ //Only one shape
+ if (scene.count == 1) {
+ return static_cast<SwTask*>(*scene.data)->clip(target);
+ }
+
+ //More than one shapes
+ if (sceneRle) rleClipPath(target, sceneRle);
+ else TVGLOG("SW_ENGINE", "No clippers in a scene?");
+
+ return true;
+ }
+
+ SwRleData* rle() override
+ {
+ return sceneRle;
+ }
+
+ void run(unsigned tid) override
+ {
+ //TODO: Skip the run if the scene hans't changed.
+ if (!sceneRle) sceneRle = static_cast<SwRleData*>(calloc(1, sizeof(SwRleData)));
+ else rleReset(sceneRle);
+
+ //Merge shapes if it has more than one shapes
+ if (scene.count > 1) {
+ //Merge first two clippers
+ auto clipper1 = static_cast<SwTask*>(*scene.data);
+ auto clipper2 = static_cast<SwTask*>(*(scene.data + 1));
+
+ rleMerge(sceneRle, clipper1->rle(), clipper2->rle());
+
+ //Unify the remained clippers
+ for (auto rd = scene.data + 2; rd < (scene.data + scene.count); ++rd) {
+ auto clipper = static_cast<SwTask*>(*rd);
+ rleMerge(sceneRle, sceneRle, clipper->rle());
+ }
+ }
+ }
+
+ bool dispose() override
+ {
+ rleFree(sceneRle);
+ return true;
+ }
+};
+
+
struct SwImageTask : SwTask
{
SwImage image;
+ Surface* source; //Image source
+ const RenderMesh* mesh = nullptr; //Should be valid ptr in action
+
+ bool clip(SwRleData* target) override
+ {
+ TVGERR("SW_ENGINE", "Image is used as ClipPath?");
+ return true;
+ }
+
+ SwRleData* rle() override
+ {
+ TVGERR("SW_ENGINE", "Image is used as Scene ClipPath?");
+ return nullptr;
+ }
void run(unsigned tid) override
{
auto clipRegion = bbox;
+ //Convert colorspace if it's not aligned.
+ if (source->owner) {
+ if (source->cs != surface->cs) rasterConvertCS(source, surface->cs);
+ if (!source->premultiplied) rasterPremultiply(source);
+ }
+
+ image.data = source->data;
+ image.w = source->w;
+ image.h = source->h;
+ image.stride = source->stride;
+ image.channelSize = source->channelSize;
+
//Invisible shape turned to visible by alpha.
if ((flags & (RenderUpdateFlag::Image | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) && (opacity > 0)) {
imageReset(&image);
if (!image.data || image.w == 0 || image.h == 0) goto end;
- if (!imagePrepare(&image, transform, clipRegion, bbox, mpool, tid)) goto end;
+ if (!imagePrepare(&image, mesh, transform, clipRegion, bbox, mpool, tid)) goto end;
- if (clips.count > 0) {
+ // TODO: How do we clip the triangle mesh? Only clip non-meshed images for now
+ if (mesh->triangleCnt == 0 && clips.count > 0) {
if (!imageGenRle(&image, bbox, false)) goto end;
if (image.rle) {
+ //Clear current task memorypool here if the clippers would use the same memory pool
+ imageDelOutline(&image, mpool, tid);
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
- auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
- if (clipper->fastTrack) rleClipRect(image.rle, &clipper->bbox);
- else if (clipper->rle) rleClipPath(image.rle, clipper->rle);
- else goto err;
+ auto clipper = static_cast<SwTask*>(*clip);
+ if (!clipper->clip(image.rle)) goto err;
}
+ return;
}
}
}
goto end;
-
err:
rleReset(image.rle);
end:
@@ -232,6 +326,31 @@ static void _termEngine()
}
+static void _renderFill(SwShapeTask* task, SwSurface* surface, uint32_t opacity)
+{
+ uint8_t r, g, b, a;
+ if (auto fill = task->rshape->fill) {
+ rasterGradientShape(surface, &task->shape, fill->identifier());
+ } else {
+ task->rshape->fillColor(&r, &g, &b, &a);
+ a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
+ if (a > 0) rasterShape(surface, &task->shape, r, g, b, a);
+ }
+}
+
+static void _renderStroke(SwShapeTask* task, SwSurface* surface, uint32_t opacity)
+{
+ uint8_t r, g, b, a;
+ if (auto strokeFill = task->rshape->strokeFill()) {
+ rasterGradientStroke(surface, &task->shape, strokeFill->identifier());
+ } else {
+ if (task->rshape->strokeColor(&r, &g, &b, &a)) {
+ a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
+ if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
+ }
+ }
+}
+
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
@@ -293,17 +412,20 @@ bool SwRenderer::viewport(const RenderRegion& vp)
}
-bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace)
+bool SwRenderer::target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs)
{
- if (!buffer || stride == 0 || w == 0 || h == 0 || w > stride) return false;
+ if (!data || stride == 0 || w == 0 || h == 0 || w > stride) return false;
if (!surface) surface = new SwSurface;
- surface->buffer = buffer;
+ surface->data = data;
surface->stride = stride;
surface->w = w;
surface->h = h;
- surface->cs = colorSpace;
+ surface->cs = cs;
+ surface->channelSize = CHANNEL_SIZE(cs);
+ surface->premultiplied = true;
+ surface->owner = true;
vport.x = vport.y = 0;
vport.w = surface->w;
@@ -315,9 +437,10 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
bool SwRenderer::preRender()
{
- return rasterClear(surface);
+ return rasterClear(surface, 0, 0, surface->w, surface->h);
}
+
void SwRenderer::clearCompositors()
{
//Free Composite Caches
@@ -333,7 +456,7 @@ void SwRenderer::clearCompositors()
bool SwRenderer::postRender()
{
//Unmultiply alpha if needed
- if (surface->cs == SwCanvas::ABGR8888_STRAIGHT || surface->cs == SwCanvas::ARGB8888_STRAIGHT) {
+ if (surface->cs == ColorSpace::ABGR8888S || surface->cs == ColorSpace::ARGB8888S) {
rasterUnpremultiply(surface);
}
@@ -354,7 +477,7 @@ bool SwRenderer::renderImage(RenderData data)
if (task->opacity == 0) return true;
- return rasterImage(surface, &task->image, task->transform, task->bbox, task->opacity);
+ return rasterImage(surface, &task->image, task->mesh, task->transform, task->bbox, task->opacity);
}
@@ -373,7 +496,7 @@ bool SwRenderer::renderShape(RenderData data)
//Do Stroking Composition
if (task->cmpStroking) {
opacity = 255;
- cmp = target(task->bounds());
+ cmp = target(task->bounds(), colorSpace());
beginComposite(cmp, CompositeMethod::None, task->opacity);
//No Stroking Composition
} else {
@@ -381,23 +504,12 @@ bool SwRenderer::renderShape(RenderData data)
}
//Main raster stage
- uint8_t r, g, b, a;
-
- if (auto fill = task->sdata->fill()) {
- rasterGradientShape(surface, &task->shape, fill->identifier());
- } else {
- task->sdata->fillColor(&r, &g, &b, &a);
- a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
- if (a > 0) rasterShape(surface, &task->shape, r, g, b, a);
- }
-
- if (auto strokeFill = task->sdata->strokeFill()) {
- rasterGradientStroke(surface, &task->shape, strokeFill->identifier());
+ if (task->rshape->stroke && task->rshape->stroke->strokeFirst) {
+ _renderStroke(task, surface, opacity);
+ _renderFill(task, surface, opacity);
} else {
- if (task->sdata->strokeColor(&r, &g, &b, &a) == Result::Success) {
- a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
- if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
- }
+ _renderFill(task, surface, opacity);
+ _renderStroke(task, surface, opacity);
}
if (task->cmpStroking) endComposite(cmp);
@@ -450,7 +562,7 @@ bool SwRenderer::mempool(bool shared)
}
-Compositor* SwRenderer::target(const RenderRegion& region)
+Compositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs)
{
auto x = region.x;
auto y = region.y;
@@ -460,13 +572,15 @@ Compositor* SwRenderer::target(const RenderRegion& region)
auto sh = static_cast<int32_t>(surface->h);
//Out of boundary
- if (x > sw || y > sh) return nullptr;
+ if (x >= sw || y >= sh || x + w < 0 || y + h < 0) return nullptr;
SwSurface* cmp = nullptr;
+ auto reqChannelSize = CHANNEL_SIZE(cs);
+
//Use cached data
for (auto p = compositors.data; p < (compositors.data + compositors.count); ++p) {
- if ((*p)->compositor->valid) {
+ if ((*p)->compositor->valid && (*p)->compositor->image.channelSize == reqChannelSize) {
cmp = *p;
break;
}
@@ -475,17 +589,16 @@ Compositor* SwRenderer::target(const RenderRegion& region)
//New Composition
if (!cmp) {
cmp = new SwSurface;
- if (!cmp) goto err;
//Inherits attributes from main surface
*cmp = *surface;
cmp->compositor = new SwCompositor;
- if (!cmp->compositor) goto err;
- //SwImage, Optimize Me: Surface size from MainSurface(WxH) to Parameter W x H
- cmp->compositor->image.data = (uint32_t*) malloc(sizeof(uint32_t) * surface->stride * surface->h);
- if (!cmp->compositor->image.data) goto err;
+ //TODO: We can optimize compositor surface size from (surface->stride x surface->h) to Parameter(w x h)
+ cmp->compositor->image.data = (pixel_t*)malloc(reqChannelSize * surface->stride * surface->h);
+ cmp->channelSize = cmp->compositor->image.channelSize = reqChannelSize;
+
compositors.push(cmp);
}
@@ -507,30 +620,16 @@ Compositor* SwRenderer::target(const RenderRegion& region)
cmp->compositor->image.h = surface->h;
cmp->compositor->image.direct = true;
- //We know partial clear region
- cmp->buffer = cmp->compositor->image.data + (cmp->stride * y + x);
- cmp->w = w;
- cmp->h = h;
-
- rasterClear(cmp);
-
- //Recover context
- cmp->buffer = cmp->compositor->image.data;
+ cmp->data = cmp->compositor->image.data;
cmp->w = cmp->compositor->image.w;
cmp->h = cmp->compositor->image.h;
+ rasterClear(cmp, x, y, w, h);
+
//Switch render target
surface = cmp;
return cmp->compositor;
-
-err:
- if (cmp) {
- if (cmp->compositor) delete(cmp->compositor);
- delete(cmp);
- }
-
- return nullptr;
}
@@ -547,13 +646,20 @@ bool SwRenderer::endComposite(Compositor* cmp)
//Default is alpha blending
if (p->method == CompositeMethod::None) {
- return rasterImage(surface, &p->image, nullptr, p->bbox, p->opacity);
+ return rasterImage(surface, &p->image, nullptr, nullptr, p->bbox, p->opacity);
}
return true;
}
+ColorSpace SwRenderer::colorSpace()
+{
+ if (surface) return surface->cs;
+ else return ColorSpace::Unsupported;
+}
+
+
bool SwRenderer::dispose(RenderData data)
{
auto task = static_cast<SwTask*>(data);
@@ -576,14 +682,15 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform,
//Finish previous task if it has duplicated request.
task->done();
- if (clips.count > 0) {
- //Guarantee composition targets get ready.
- for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
- static_cast<SwShapeTask*>(*clip)->done();
- }
- task->clips = clips;
+ //TODO: Failed threading them. It would be better if it's possible.
+ //See: https://github.com/thorvg/thorvg/issues/1409
+ //Guarantee composition targets get ready.
+ for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
+ static_cast<SwTask*>(*clip)->done();
}
+ task->clips = clips;
+
if (transform) {
if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix)));
*task->transform = transform->m;
@@ -612,44 +719,52 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform,
}
-RenderData SwRenderer::prepare(Surface* image, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
+RenderData SwRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
{
//prepare task
auto task = static_cast<SwImageTask*>(data);
- if (!task) {
- task = new SwImageTask;
- if (flags & RenderUpdateFlag::Image) {
- task->image.data = image->buffer;
- task->image.w = image->w;
- task->image.h = image->h;
- task->image.stride = image->stride;
- }
+ if (!task) task = new SwImageTask;
+ if (flags & RenderUpdateFlag::Image) {
+ task->source = surface;
+ task->mesh = mesh;
}
return prepareCommon(task, transform, opacity, clips, flags);
}
-RenderData SwRenderer::prepare(const Shape& sdata, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
+RenderData SwRenderer::prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
{
//prepare task
- auto task = static_cast<SwShapeTask*>(data);
- if (!task) {
- task = new SwShapeTask;
- task->sdata = &sdata;
+ auto task = static_cast<SwSceneTask*>(data);
+ if (!task) task = new SwSceneTask;
+ task->scene = scene;
+
+ //TODO: Failed threading them. It would be better if it's possible.
+ //See: https://github.com/thorvg/thorvg/issues/1409
+ //Guarantee composition targets get ready.
+ for (auto task = scene.data; task < (scene.data + scene.count); ++task) {
+ static_cast<SwTask*>(*task)->done();
}
return prepareCommon(task, transform, opacity, clips, flags);
}
-SwRenderer::SwRenderer():mpool(globalMpool)
+RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper)
{
+ //prepare task
+ auto task = static_cast<SwShapeTask*>(data);
+ if (!task) {
+ task = new SwShapeTask;
+ task->rshape = &rshape;
+ }
+ task->clipper = clipper;
+
+ return prepareCommon(task, transform, opacity, clips, flags);
}
-uint32_t SwRenderer::colorSpace()
+SwRenderer::SwRenderer():mpool(globalMpool)
{
- if (surface) return surface->cs;
- return tvg::SwCanvas::ARGB8888;
}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h
index cab93f9e1c..36614fa1c1 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_SW_RENDERER_H_
#define _TVG_SW_RENDERER_H_
@@ -35,8 +36,9 @@ namespace tvg
class SwRenderer : public RenderMethod
{
public:
- RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
- RenderData prepare(Surface* image, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
+ RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) override;
+ RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
+ RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
bool preRender() override;
bool renderShape(RenderData data) override;
bool renderImage(RenderData data) override;
@@ -45,19 +47,18 @@ public:
RenderRegion region(RenderData data) override;
RenderRegion viewport() override;
bool viewport(const RenderRegion& vp) override;
+ ColorSpace colorSpace() override;
bool clear() override;
bool sync() override;
- bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace);
+ bool target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs);
bool mempool(bool shared);
- Compositor* target(const RenderRegion& region) override;
+ Compositor* target(const RenderRegion& region, ColorSpace cs) override;
bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) override;
bool endComposite(Compositor* cmp) override;
void clearCompositors();
- uint32_t colorSpace() override;
-
static SwRenderer* gen();
static bool init(uint32_t threads);
static int32_t init();
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRle.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRle.cpp
index 63e7fc9447..50dec208b2 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRle.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRle.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -773,60 +773,59 @@ static int _genRle(RleWorker& rw)
}
-SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
+static SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *target, SwSpan *outSpans, uint32_t outSpansCnt)
{
auto out = outSpans;
- auto spans = targetRle->spans;
- auto end = targetRle->spans + targetRle->size;
+ auto spans = target->spans;
+ auto end = target->spans + target->size;
auto clipSpans = clip->spans;
auto clipEnd = clip->spans + clip->size;
- while (spanCnt > 0 && spans < end) {
- if (clipSpans == clipEnd) {
- spans = end;
- break;
- }
+ while (spans < end && clipSpans < clipEnd) {
+ //align y cooridnates.
if (clipSpans->y > spans->y) {
++spans;
continue;
}
- if (spans->y != clipSpans->y) {
+ if (spans->y > clipSpans->y) {
++clipSpans;
continue;
}
- auto sx1 = spans->x;
- auto sx2 = sx1 + spans->len;
- auto cx1 = clipSpans->x;
- auto cx2 = cx1 + clipSpans->len;
- if (cx1 < sx1 && cx2 < sx1) {
- ++clipSpans;
- continue;
- }
- else if (sx1 < cx1 && sx2 < cx1) {
- ++spans;
- continue;
- }
- auto x = sx1 > cx1 ? sx1 : cx1;
- auto len = (sx2 < cx2 ? sx2 : cx2) - x;
- if (len) {
- auto spansCorverage = spans->coverage;
- auto clipSpansCoverage = clipSpans->coverage;
- out->x = sx1 > cx1 ? sx1 : cx1;
- out->len = (sx2 < cx2 ? sx2 : cx2) - out->x;
- out->y = spans->y;
- out->coverage = (uint8_t)(((spansCorverage * clipSpansCoverage) + 0xff) >> 8);
- ++out;
- --spanCnt;
+ //Try clipping with all clip spans which have a same y coordinate.
+ auto temp = clipSpans;
+ while(temp < clipEnd && outSpansCnt > 0 && temp->y == clipSpans->y) {
+ auto sx1 = spans->x;
+ auto sx2 = sx1 + spans->len;
+ auto cx1 = temp->x;
+ auto cx2 = cx1 + temp->len;
+
+ //The span must be left(x1) to right(x2) direction. Not intersected.
+ if (cx2 < sx1 || sx2 < cx1) {
+ ++temp;
+ continue;
+ }
+
+ //clip span region.
+ auto x = sx1 > cx1 ? sx1 : cx1;
+ auto len = (sx2 < cx2 ? sx2 : cx2) - x;
+ if (len > 0) {
+ out->x = x;
+ out->y = temp->y;
+ out->len = len;
+ out->coverage = (uint8_t)(((spans->coverage * temp->coverage) + 0xff) >> 8);
+ ++out;
+ --outSpansCnt;
+ }
+ ++temp;
}
- if (sx2 < cx2) ++spans;
- else ++clipSpans;
+ ++spans;
}
return out;
}
-SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
+static SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSpan *outSpans, uint32_t outSpansCnt)
{
auto out = outSpans;
auto spans = targetRle->spans;
@@ -836,7 +835,7 @@ SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSp
auto maxx = minx + static_cast<int16_t>(bbox->max.x - bbox->min.x) - 1;
auto maxy = miny + static_cast<int16_t>(bbox->max.y - bbox->min.y) - 1;
- while (spanCnt && spans < end) {
+ while (outSpansCnt > 0 && spans < end) {
if (spans->y > maxy) {
spans = end;
break;
@@ -853,18 +852,58 @@ SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSp
out->x = spans->x;
out->len = spans->len < (maxx - spans->x + 1) ? spans->len : (maxx - spans->x + 1);
}
- if (out->len != 0) {
+ if (out->len > 0) {
out->y = spans->y;
out->coverage = spans->coverage;
++out;
+ --outSpansCnt;
}
++spans;
- --spanCnt;
}
return out;
}
+static SwSpan* _mergeSpansRegion(const SwRleData *clip1, const SwRleData *clip2, SwSpan *outSpans)
+{
+ auto out = outSpans;
+ auto spans1 = clip1->spans;
+ auto end1 = clip1->spans + clip1->size;
+ auto spans2 = clip2->spans;
+ auto end2 = clip2->spans + clip2->size;
+
+ //list two spans up in y order
+ //TODO: Remove duplicated regions?
+ while (spans1 < end1 && spans2 < end2) {
+ while (spans1 < end1 && spans1->y <= spans2->y) {
+ *out = *spans1;
+ ++spans1;
+ ++out;
+ }
+ if (spans1 >= end1) break;
+ while (spans2 < end2 && spans2->y <= spans1->y) {
+ *out = *spans2;
+ ++spans2;
+ ++out;
+ }
+ }
+
+ //Leftovers
+ while (spans1 < end1) {
+ *out = *spans1;
+ ++spans1;
+ ++out;
+ }
+ while (spans2 < end2) {
+ *out = *spans2;
+ ++spans2;
+ ++out;
+ }
+
+ return out;
+}
+
+
void _replaceClipSpan(SwRleData *rle, SwSpan* clippedSpans, uint32_t size)
{
free(rle->spans);
@@ -1001,6 +1040,28 @@ error:
}
+SwRleData* rleRender(const SwBBox* bbox)
+{
+ auto width = static_cast<uint16_t>(bbox->max.x - bbox->min.x);
+ auto height = static_cast<uint16_t>(bbox->max.y - bbox->min.y);
+
+ auto rle = static_cast<SwRleData*>(malloc(sizeof(SwRleData)));
+ rle->spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * height));
+ rle->size = height;
+ rle->alloc = height;
+
+ auto span = rle->spans;
+ for (uint16_t i = 0; i < height; ++i, ++span) {
+ span->x = bbox->min.x;
+ span->y = bbox->min.y + i;
+ span->len = width;
+ span->coverage = 255;
+ }
+
+ return rle;
+}
+
+
void rleReset(SwRleData* rle)
{
if (!rle) return;
@@ -1016,12 +1077,50 @@ void rleFree(SwRleData* rle)
}
+void rleMerge(SwRleData* rle, SwRleData* clip1, SwRleData* clip2)
+{
+ if (!rle || (!clip1 && !clip2)) return;
+ if (clip1 && clip1->size == 0 && clip2 && clip2->size == 0) return;
+
+ TVGLOG("SW_ENGINE", "Unifying Rle!");
+
+ //clip1 is empty, just copy clip2
+ if (!clip1 || clip1->size == 0) {
+ if (clip2) {
+ auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (clip2->size)));
+ memcpy(spans, clip2->spans, clip2->size);
+ _replaceClipSpan(rle, spans, clip2->size);
+ } else {
+ _replaceClipSpan(rle, nullptr, 0);
+ }
+ return;
+ }
+
+ //clip2 is empty, just copy clip1
+ if (!clip2 || clip2->size == 0) {
+ if (clip1) {
+ auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (clip1->size)));
+ memcpy(spans, clip1->spans, clip1->size);
+ _replaceClipSpan(rle, spans, clip1->size);
+ } else {
+ _replaceClipSpan(rle, nullptr, 0);
+ }
+ return;
+ }
+
+ auto spanCnt = clip1->size + clip2->size;
+ auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * spanCnt));
+ auto spansEnd = _mergeSpansRegion(clip1, clip2, spans);
+
+ _replaceClipSpan(rle, spans, spansEnd - spans);
+}
+
+
void rleClipPath(SwRleData *rle, const SwRleData *clip)
{
if (rle->size == 0 || clip->size == 0) return;
auto spanCnt = rle->size > clip->size ? rle->size : clip->size;
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (spanCnt)));
- if (!spans) return;
auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt);
_replaceClipSpan(rle, spans, spansEnd - spans);
@@ -1034,7 +1133,6 @@ void rleClipRect(SwRleData *rle, const SwBBox* clip)
{
if (rle->size == 0) return;
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (rle->size)));
- if (!spans) return;
auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size);
_replaceClipSpan(rle, spans, spansEnd - spans);
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp
index e5b540bcc3..7462a7b7ea 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgSwCommon.h"
#include "tvgBezier.h"
#include <float.h>
@@ -266,13 +267,13 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
}
-static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
+static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* transform)
{
- const PathCommand* cmds = nullptr;
- auto cmdCnt = sdata->pathCommands(&cmds);
+ const PathCommand* cmds = rshape->path.cmds;
+ auto cmdCnt = rshape->path.cmdCnt;
- const Point* pts = nullptr;
- auto ptsCnt = sdata->pathCoords(&pts);
+ const Point* pts = rshape->path.pts;
+ auto ptsCnt = rshape->path.ptsCnt;
//No actual shape data
if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
@@ -285,7 +286,7 @@ static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
dash.curOpGap = false;
const float* pattern;
- dash.cnt = sdata->strokeDash(&pattern);
+ dash.cnt = rshape->strokeDash(&pattern);
if (dash.cnt == 0) return nullptr;
//OPTMIZE ME: Use mempool???
@@ -380,13 +381,13 @@ static bool _axisAlignedRect(const SwOutline* outline)
-static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transform, SwMpool* mpool, unsigned tid, bool hasComposite)
+static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix* transform, SwMpool* mpool, unsigned tid, bool hasComposite)
{
- const PathCommand* cmds = nullptr;
- auto cmdCnt = sdata->pathCommands(&cmds);
+ const PathCommand* cmds = rshape->path.cmds;
+ auto cmdCnt = rshape->path.cmdCnt;
- const Point* pts = nullptr;
- auto ptsCnt = sdata->pathCoords(&pts);
+ const Point* pts = rshape->path.pts;
+ auto ptsCnt = rshape->path.ptsCnt;
//No actual shape data
if (cmdCnt == 0 || ptsCnt == 0) return false;
@@ -466,7 +467,7 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
_outlineEnd(*outline);
- outline->fillRule = sdata->fillRule();
+ outline->fillRule = rshape->rule;
shape->outline = outline;
shape->fastTrack = (!hasComposite && _axisAlignedRect(shape->outline));
@@ -478,9 +479,9 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
/* External Class Implementation */
/************************************************************************/
-bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite)
+bool shapePrepare(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite)
{
- if (!_genOutline(shape, sdata, transform, mpool, tid, hasComposite)) return false;
+ if (!_genOutline(shape, rshape, transform, mpool, tid, hasComposite)) return false;
if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion, shape->fastTrack)) return false;
//Keep it for Rasterization Region
@@ -503,7 +504,7 @@ bool shapePrepared(const SwShape* shape)
}
-bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, bool antiAlias)
+bool shapeGenRle(SwShape* shape, TVG_UNUSED const RenderShape* rshape, bool antiAlias)
{
//FIXME: Should we draw it?
//Case: Stroke Line
@@ -557,18 +558,18 @@ void shapeDelStroke(SwShape* shape)
}
-void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform)
+void shapeResetStroke(SwShape* shape, const RenderShape* rshape, const Matrix* transform)
{
if (!shape->stroke) shape->stroke = static_cast<SwStroke*>(calloc(1, sizeof(SwStroke)));
auto stroke = shape->stroke;
if (!stroke) return;
- strokeReset(stroke, sdata, transform);
+ strokeReset(stroke, rshape, transform);
rleReset(shape->strokeRle);
}
-bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
+bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
{
SwOutline* shapeOutline = nullptr;
SwOutline* strokeOutline = nullptr;
@@ -576,14 +577,14 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo
bool ret = true;
//Dash Style Stroke
- if (sdata->strokeDash(nullptr) > 0) {
- shapeOutline = _genDashOutline(sdata, transform);
+ if (rshape->strokeDash(nullptr) > 0) {
+ shapeOutline = _genDashOutline(rshape, transform);
if (!shapeOutline) return false;
freeOutline = true;
//Normal Style stroke
} else {
if (!shape->outline) {
- if (!_genOutline(shape, sdata, transform, mpool, tid, false)) return false;
+ if (!_genOutline(shape, rshape, transform, mpool, tid, false)) return false;
}
shapeOutline = shape->outline;
}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp
index fa213cc5d3..2f41d5f021 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+/*
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include <string.h>
#include <math.h>
#include "tvgSwCommon.h"
@@ -301,7 +302,7 @@ static void _inside(SwStroke& stroke, int32_t side, SwFixed lineLength)
bool intersect = false;
/* Only intersect borders if between two line_to's and both
- lines are long enough (line length is zero fur curves). */
+ lines are long enough (line length is zero for curves). */
if (border->movable && lineLength > 0) {
//compute minimum required length of lines
SwFixed minLength = abs(mathMultiply(stroke.width, mathTan(theta)));
@@ -381,9 +382,16 @@ static void _lineTo(SwStroke& stroke, const SwPoint& to)
if (delta.zero()) return;
//compute length of line
- auto lineLength = mathLength(delta);
auto angle = mathAtan(delta);
+ /* The lineLength is used to determine the intersection of strokes outlines.
+ The scale needs to be reverted since the stroke width has not been scaled.
+ An alternative option is to scale the width of the stroke properly by
+ calculating the mixture of the sx/sy rating on the stroke direction. */
+ delta.x = static_cast<SwCoord>(delta.x / stroke.sx);
+ delta.y = static_cast<SwCoord>(delta.y / stroke.sy);
+ auto lineLength = mathLength(delta);
+
delta = {static_cast<SwCoord>(stroke.width), 0};
mathRotate(delta, angle + SW_ANGLE_PI2);
SCALE(stroke, delta);
@@ -825,7 +833,7 @@ void strokeFree(SwStroke* stroke)
}
-void strokeReset(SwStroke* stroke, const Shape* sdata, const Matrix* transform)
+void strokeReset(SwStroke* stroke, const RenderShape* rshape, const Matrix* transform)
{
if (transform) {
stroke->sx = sqrtf(powf(transform->e11, 2.0f) + powf(transform->e21, 2.0f));
@@ -834,11 +842,11 @@ void strokeReset(SwStroke* stroke, const Shape* sdata, const Matrix* transform)
stroke->sx = stroke->sy = 1.0f;
}
- stroke->width = HALF_STROKE(sdata->strokeWidth());
- stroke->cap = sdata->strokeCap();
+ stroke->width = HALF_STROKE(rshape->strokeWidth());
+ stroke->cap = rshape->strokeCap();
//Save line join: it can be temporarily changed when stroking curves...
- stroke->joinSaved = stroke->join = sdata->strokeJoin();
+ stroke->joinSaved = stroke->join = rshape->strokeJoin();
stroke->borders[0].ptsCnt = 0;
stroke->borders[0].start = -1;
diff --git a/thirdparty/thorvg/src/lib/tvgAccessor.cpp b/thirdparty/thorvg/src/lib/tvgAccessor.cpp
index 5ad24f4acf..0c636979b5 100644
--- a/thirdparty/thorvg/src/lib/tvgAccessor.cpp
+++ b/thirdparty/thorvg/src/lib/tvgAccessor.cpp
@@ -1,13 +1,16 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
+
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,15 +26,15 @@
/* Internal Class Implementation */
/************************************************************************/
-static bool accessChildren(Iterator* it, bool(*func)(const Paint* paint), IteratorAccessor& itrAccessor)
+static bool accessChildren(Iterator* it, function<bool(const Paint* paint)> func)
{
while (auto child = it->next()) {
//Access the child
if (!func(child)) return false;
//Access the children of the child
- if (auto it2 = itrAccessor.iterator(child)) {
- if (!accessChildren(it2, func, itrAccessor)) {
+ if (auto it2 = IteratorAccessor::iterator(child)) {
+ if (!accessChildren(it2, func)) {
delete(it2);
return false;
}
@@ -41,12 +44,11 @@ static bool accessChildren(Iterator* it, bool(*func)(const Paint* paint), Iterat
return true;
}
-
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
-unique_ptr<Picture> Accessor::access(unique_ptr<Picture> picture, bool(*func)(const Paint* paint)) noexcept
+unique_ptr<Picture> Accessor::set(unique_ptr<Picture> picture, function<bool(const Paint* paint)> func) noexcept
{
auto p = picture.get();
if (!p || !func) return picture;
@@ -57,9 +59,8 @@ unique_ptr<Picture> Accessor::access(unique_ptr<Picture> picture, bool(*func)(co
if (!func(p)) return picture;
//Children
- IteratorAccessor itrAccessor;
- if (auto it = itrAccessor.iterator(p)) {
- accessChildren(it, func, itrAccessor);
+ if (auto it = IteratorAccessor::iterator(p)) {
+ accessChildren(it, func);
delete(it);
}
return picture;
diff --git a/thirdparty/thorvg/src/lib/tvgArray.h b/thirdparty/thorvg/src/lib/tvgArray.h
index 04ddbaee2b..8d67753ae3 100644
--- a/thirdparty/thorvg/src/lib/tvgArray.h
+++ b/thirdparty/thorvg/src/lib/tvgArray.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_ARRAY_H_
#define _TVG_ARRAY_H_
diff --git a/thirdparty/thorvg/src/lib/tvgBezier.cpp b/thirdparty/thorvg/src/lib/tvgBezier.cpp
index 95e2055943..6162252235 100644
--- a/thirdparty/thorvg/src/lib/tvgBezier.cpp
+++ b/thirdparty/thorvg/src/lib/tvgBezier.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include <float.h>
#include <math.h>
#include "tvgBezier.h"
@@ -114,7 +115,7 @@ float bezAt(const Bezier& bz, float at)
auto t = 0.5f;
//just in case to prevent an infinite loop
- if (at <= 0) return 0.0f;
+ if (at <= 0) return 0.0f;
if (at >= len) return 1.0f;
diff --git a/thirdparty/thorvg/src/lib/tvgBezier.h b/thirdparty/thorvg/src/lib/tvgBezier.h
index 7d7c84e34e..aa309b098e 100644
--- a/thirdparty/thorvg/src/lib/tvgBezier.h
+++ b/thirdparty/thorvg/src/lib/tvgBezier.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_BEZIER_H_
#define _TVG_BEZIER_H_
diff --git a/thirdparty/thorvg/src/lib/tvgBinaryDesc.h b/thirdparty/thorvg/src/lib/tvgBinaryDesc.h
index f139def470..3b44db2829 100644
--- a/thirdparty/thorvg/src/lib/tvgBinaryDesc.h
+++ b/thirdparty/thorvg/src/lib/tvgBinaryDesc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_BINARY_DESC_H_
#define _TVG_BINARY_DESC_H_
@@ -42,7 +43,7 @@ using TvgBinFlag = TvgBinByte;
#define TVG_HEADER_VERSION_LENGTH 6
#define TVG_HEADER_RESERVED_LENGTH 1 //Storing flags for extensions
#define TVG_HEADER_COMPRESS_SIZE 12 //TVG_HEADER_UNCOMPRESSED_SIZE + TVG_HEADER_COMPRESSED_SIZE + TVG_HEADER_COMPRESSED_SIZE_BITS
-//Compress Size
+//Compress Size
#define TVG_HEADER_UNCOMPRESSED_SIZE 4 //SIZE (TvgBinCounter)
#define TVG_HEADER_COMPRESSED_SIZE 4 //SIZE (TvgBinCounter)
#define TVG_HEADER_COMPRESSED_SIZE_BITS 4 //SIZE (TvgBinCounter)
@@ -92,5 +93,6 @@ using TvgBinFlag = TvgBinByte;
//Picture
#define TVG_TAG_PICTURE_RAW_IMAGE (TvgBinTag)0x70
+#define TVG_TAG_PICTURE_MESH (TvgBinTag)0x71
#endif //_TVG_BINARY_DESC_H_
diff --git a/thirdparty/thorvg/src/lib/tvgCanvas.cpp b/thirdparty/thorvg/src/lib/tvgCanvas.cpp
index e8529e47c2..95c66b94df 100644
--- a/thirdparty/thorvg/src/lib/tvgCanvas.cpp
+++ b/thirdparty/thorvg/src/lib/tvgCanvas.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgCanvasImpl.h"
/************************************************************************/
@@ -57,13 +58,21 @@ Result Canvas::clear(bool free) noexcept
Result Canvas::draw() noexcept
{
- return pImpl->draw();
+ TVGLOG("COMMON", "Draw S. -------------------------------- Canvas(%p)", this);
+ auto ret = pImpl->draw();
+ TVGLOG("COMMON", "Draw E. -------------------------------- Canvas(%p)", this);
+
+ return ret;
}
Result Canvas::update(Paint* paint) noexcept
{
- return pImpl->update(paint, false);
+ TVGLOG("COMMON", "Update S. ------------------------------ Canvas(%p)", this);
+ auto ret = pImpl->update(paint, false);
+ TVGLOG("COMMON", "Update E. ------------------------------ Canvas(%p)", this);
+
+ return ret;
}
diff --git a/thirdparty/thorvg/src/lib/tvgCanvasImpl.h b/thirdparty/thorvg/src/lib/tvgCanvasImpl.h
index 0adec8fa52..6f5760f53c 100644
--- a/thirdparty/thorvg/src/lib/tvgCanvasImpl.h
+++ b/thirdparty/thorvg/src/lib/tvgCanvasImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_CANVAS_IMPL_H_
#define _TVG_CANVAS_IMPL_H_
diff --git a/thirdparty/thorvg/src/lib/tvgCommon.h b/thirdparty/thorvg/src/lib/tvgCommon.h
index 1d66f2e1a2..1731647c00 100644
--- a/thirdparty/thorvg/src/lib/tvgCommon.h
+++ b/thirdparty/thorvg/src/lib/tvgCommon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_COMMON_H_
#define _TVG_COMMON_H_
@@ -64,8 +65,14 @@ using namespace tvg;
enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown };
#ifdef THORVG_LOG_ENABLED
- #define TVGLOG(tag, fmt, ...) fprintf(stdout, tag ": " fmt "\n", ##__VA_ARGS__) //Log Message for notifying user some useful info
- #define TVGERR(tag, fmt, ...) fprintf(stderr, tag ": " fmt "\n", ##__VA_ARGS__) //Error Message for us to fix it
+ constexpr auto ErrorColor = "\033[31m"; //red
+ constexpr auto ErrorBgColor = "\033[41m";//bg red
+ constexpr auto LogColor = "\033[32m"; //green
+ constexpr auto LogBgColor = "\033[42m"; //bg green
+ constexpr auto GreyColor = "\033[90m"; //grey
+ constexpr auto ResetColors = "\033[0m"; //default
+ #define TVGERR(tag, fmt, ...) fprintf(stderr, "%s[E]%s %s" tag "%s (%s %d): %s" fmt "\n", ErrorBgColor, ResetColors, ErrorColor, GreyColor, __FILE__, __LINE__, ResetColors, ##__VA_ARGS__)
+ #define TVGLOG(tag, fmt, ...) fprintf(stdout, "%s[L]%s %s" tag "%s (%s %d): %s" fmt "\n", LogBgColor, ResetColors, LogColor, GreyColor, __FILE__, __LINE__, ResetColors, ##__VA_ARGS__)
#else
#define TVGERR(...)
#define TVGLOG(...)
diff --git a/thirdparty/thorvg/src/lib/tvgFill.cpp b/thirdparty/thorvg/src/lib/tvgFill.cpp
index eecf239cee..cc7e1ccaed 100644
--- a/thirdparty/thorvg/src/lib/tvgFill.cpp
+++ b/thirdparty/thorvg/src/lib/tvgFill.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgFill.h"
/************************************************************************/
diff --git a/thirdparty/thorvg/src/lib/tvgFill.h b/thirdparty/thorvg/src/lib/tvgFill.h
index fff2475c4f..e90991c9df 100644
--- a/thirdparty/thorvg/src/lib/tvgFill.h
+++ b/thirdparty/thorvg/src/lib/tvgFill.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_FILL_H_
#define _TVG_FILL_H_
diff --git a/thirdparty/thorvg/src/lib/tvgGlCanvas.cpp b/thirdparty/thorvg/src/lib/tvgGlCanvas.cpp
index 56feb69541..dbbab516b2 100644
--- a/thirdparty/thorvg/src/lib/tvgGlCanvas.cpp
+++ b/thirdparty/thorvg/src/lib/tvgGlCanvas.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgCanvasImpl.h"
#ifdef THORVG_GL_RASTER_SUPPORT
diff --git a/thirdparty/thorvg/src/lib/tvgInitializer.cpp b/thirdparty/thorvg/src/lib/tvgInitializer.cpp
index 42997c3493..b7326a9fbc 100644
--- a/thirdparty/thorvg/src/lib/tvgInitializer.cpp
+++ b/thirdparty/thorvg/src/lib/tvgInitializer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgCommon.h"
#include "tvgTaskScheduler.h"
#include "tvgLoader.h"
@@ -43,6 +44,11 @@
static int _initCnt = 0;
static uint16_t _version = 0;
+//enum class operation helper
+static constexpr bool operator &(CanvasEngine a, CanvasEngine b)
+{
+ return int(a) & int(b);
+}
static bool _buildVersionInfo()
{
@@ -86,12 +92,12 @@ Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept
{
auto nonSupport = true;
- if (static_cast<uint32_t>(engine) & static_cast<uint32_t>(CanvasEngine::Sw)) {
+ if (engine & CanvasEngine::Sw) {
#ifdef THORVG_SW_RASTER_SUPPORT
if (!SwRenderer::init(threads)) return Result::FailedAllocation;
nonSupport = false;
#endif
- } else if (static_cast<uint32_t>(engine) & static_cast<uint32_t>(CanvasEngine::Gl)) {
+ } else if (engine & CanvasEngine::Gl) {
#ifdef THORVG_GL_RASTER_SUPPORT
if (!GlRenderer::init(threads)) return Result::FailedAllocation;
nonSupport = false;
@@ -120,12 +126,12 @@ Result Initializer::term(CanvasEngine engine) noexcept
auto nonSupport = true;
- if (static_cast<uint32_t>(engine) & static_cast<uint32_t>(CanvasEngine::Sw)) {
+ if (engine & CanvasEngine::Sw) {
#ifdef THORVG_SW_RASTER_SUPPORT
if (!SwRenderer::term()) return Result::InsufficientCondition;
nonSupport = false;
#endif
- } else if (static_cast<uint32_t>(engine) & static_cast<uint32_t>(CanvasEngine::Gl)) {
+ } else if (engine & CanvasEngine::Gl) {
#ifdef THORVG_GL_RASTER_SUPPORT
if (!GlRenderer::term()) return Result::InsufficientCondition;
nonSupport = false;
diff --git a/thirdparty/thorvg/src/lib/tvgIteratorAccessor.h b/thirdparty/thorvg/src/lib/tvgIteratorAccessor.h
index 8e566acb72..2347613ed8 100644
--- a/thirdparty/thorvg/src/lib/tvgIteratorAccessor.h
+++ b/thirdparty/thorvg/src/lib/tvgIteratorAccessor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_ITERATOR_ACCESSOR_H_
#define _TVG_ITERATOR_ACCESSOR_H_
@@ -31,7 +32,7 @@ class IteratorAccessor
{
public:
//Utility Method: Iterator Accessor
- Iterator* iterator(const Paint* paint)
+ static Iterator* iterator(const Paint* paint)
{
return paint->pImpl->iterator();
}
diff --git a/thirdparty/thorvg/src/lib/tvgLinearGradient.cpp b/thirdparty/thorvg/src/lib/tvgLinearGradient.cpp
index df34af3aa1..3e040c08f1 100644
--- a/thirdparty/thorvg/src/lib/tvgLinearGradient.cpp
+++ b/thirdparty/thorvg/src/lib/tvgLinearGradient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include <float.h>
#include <math.h>
#include "tvgFill.h"
diff --git a/thirdparty/thorvg/src/lib/tvgLoadModule.h b/thirdparty/thorvg/src/lib/tvgLoadModule.h
index 0a154aa47d..ee7c0c1193 100644
--- a/thirdparty/thorvg/src/lib/tvgLoadModule.h
+++ b/thirdparty/thorvg/src/lib/tvgLoadModule.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_LOAD_MODULE_H_
#define _TVG_LOAD_MODULE_H_
@@ -35,8 +36,8 @@ public:
float vy = 0;
float vw = 0;
float vh = 0;
- float w = 0, h = 0; //default image size
- uint32_t colorSpace = SwCanvas::ARGB8888;
+ float w = 0, h = 0; //default image size
+ ColorSpace cs = ColorSpace::Unsupported; //must be clarified at open()
virtual ~LoadModule() {}
@@ -49,7 +50,7 @@ public:
virtual bool read() = 0;
virtual bool close() = 0;
- virtual unique_ptr<Surface> bitmap(uint32_t colorSpace) { return nullptr; }
+ virtual unique_ptr<Surface> bitmap() { return nullptr; }
virtual unique_ptr<Paint> paint() { return nullptr; }
};
diff --git a/thirdparty/thorvg/src/lib/tvgLoader.cpp b/thirdparty/thorvg/src/lib/tvgLoader.cpp
index 991c260159..2bbe177844 100644
--- a/thirdparty/thorvg/src/lib/tvgLoader.cpp
+++ b/thirdparty/thorvg/src/lib/tvgLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgLoader.h"
#ifdef THORVG_SVG_LOADER_SUPPORT
diff --git a/thirdparty/thorvg/src/lib/tvgLoader.h b/thirdparty/thorvg/src/lib/tvgLoader.h
index ab32f89a2f..17ff9e2637 100644
--- a/thirdparty/thorvg/src/lib/tvgLoader.h
+++ b/thirdparty/thorvg/src/lib/tvgLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_LOADER_H_
#define _TVG_LOADER_H_
diff --git a/thirdparty/thorvg/src/lib/tvgLzw.cpp b/thirdparty/thorvg/src/lib/tvgLzw.cpp
index 1aaf37831a..52f4ed6716 100644
--- a/thirdparty/thorvg/src/lib/tvgLzw.cpp
+++ b/thirdparty/thorvg/src/lib/tvgLzw.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -258,8 +258,8 @@ struct Dictionary
Dictionary()
{
- /* First 256 dictionary entries are reserved to the byte/ASCII range.
- Additional entries follow for the character sequences found in the input.
+ /* First 256 dictionary entries are reserved to the byte/ASCII range.
+ Additional entries follow for the character sequences found in the input.
Up to 4096 - 256 (MaxDictEntries - FirstCode). */
size = FirstCode;
diff --git a/thirdparty/thorvg/src/lib/tvgLzw.h b/thirdparty/thorvg/src/lib/tvgLzw.h
index 8e165bdb34..bd4e783fbf 100644
--- a/thirdparty/thorvg/src/lib/tvgLzw.h
+++ b/thirdparty/thorvg/src/lib/tvgLzw.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_LZW_H_
#define _TVG_LZW_H_
diff --git a/thirdparty/thorvg/src/lib/tvgMath.h b/thirdparty/thorvg/src/lib/tvgMath.h
index 74f34fb744..9ab8291b75 100644
--- a/thirdparty/thorvg/src/lib/tvgMath.h
+++ b/thirdparty/thorvg/src/lib/tvgMath.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_MATH_H_
#define _TVG_MATH_H_
@@ -118,7 +119,7 @@ static inline void mathScale(Matrix* m, float scale)
static inline void mathTranslate(Matrix* m, float x, float y)
{
m->e13 = x;
- m->e23 = y;
+ m->e23 = y;
}
diff --git a/thirdparty/thorvg/src/lib/tvgPaint.cpp b/thirdparty/thorvg/src/lib/tvgPaint.cpp
index c90e95cd33..c7030aaccf 100644
--- a/thirdparty/thorvg/src/lib/tvgPaint.cpp
+++ b/thirdparty/thorvg/src/lib/tvgPaint.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgMath.h"
#include "tvgPaint.h"
@@ -161,16 +162,15 @@ bool Paint::Impl::render(RenderMethod& renderer)
{
Compositor* cmp = nullptr;
- //OPTIMIZE_ME: Can we replace the simple AlphaMasking with ClipPath?
-
/* Note: only ClipPath is processed in update() step.
Create a composition image. */
if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) {
auto region = smethod->bounds(renderer);
if (region.w == 0 || region.h == 0) return true;
- cmp = renderer.target(region);
- renderer.beginComposite(cmp, CompositeMethod::None, 255);
- compData->target->pImpl->render(renderer);
+ cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method));
+ if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) {
+ compData->target->pImpl->render(renderer);
+ }
}
if (cmp) renderer.beginComposite(cmp, compData->method, compData->target->pImpl->opacity);
@@ -183,7 +183,7 @@ bool Paint::Impl::render(RenderMethod& renderer)
}
-void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag)
+RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag, bool clipper)
{
if (renderFlag & RenderUpdateFlag::Transform) {
if (!rTransform) return nullptr;
@@ -194,9 +194,10 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
}
/* 1. Composition Pre Processing */
- void *tdata = nullptr;
+ RenderData trd = nullptr; //composite target render data
RenderRegion viewport;
bool compFastTrack = false;
+ bool childClipper = false;
if (compData) {
auto target = compData->target;
@@ -206,47 +207,50 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
/* If transform has no rotation factors && ClipPath / AlphaMasking is a simple rectangle,
we can avoid regular ClipPath / AlphaMasking sequence but use viewport for performance */
auto tryFastTrack = false;
- if (method == CompositeMethod::ClipPath) tryFastTrack = true;
- else if (method == CompositeMethod::AlphaMask && target->identifier() == TVG_CLASS_ID_SHAPE) {
- auto shape = static_cast<Shape*>(target);
- uint8_t a;
- shape->fillColor(nullptr, nullptr, nullptr, &a);
- if (a == 255 && shape->opacity() == 255 && !shape->fill()) tryFastTrack = true;
- }
- if (tryFastTrack) {
- RenderRegion viewport2;
- if ((compFastTrack = _compFastTrack(target, pTransform, target->pImpl->rTransform, viewport2))) {
- viewport = renderer.viewport();
- viewport2.intersect(viewport);
- renderer.viewport(viewport2);
- target->pImpl->ctxFlag |= ContextFlag::FastTrack;
+ if (target->identifier() == TVG_CLASS_ID_SHAPE) {
+ if (method == CompositeMethod::ClipPath) tryFastTrack = true;
+ else if (method == CompositeMethod::AlphaMask) {
+ auto shape = static_cast<Shape*>(target);
+ uint8_t a;
+ shape->fillColor(nullptr, nullptr, nullptr, &a);
+ if (a == 255 && shape->opacity() == 255 && !shape->fill()) tryFastTrack = true;
+ }
+ if (tryFastTrack) {
+ RenderRegion viewport2;
+ if ((compFastTrack = _compFastTrack(target, pTransform, target->pImpl->rTransform, viewport2))) {
+ viewport = renderer.viewport();
+ viewport2.intersect(viewport);
+ renderer.viewport(viewport2);
+ target->pImpl->ctxFlag |= ContextFlag::FastTrack;
+ }
}
}
if (!compFastTrack) {
- tdata = target->pImpl->update(renderer, pTransform, 255, clips, pFlag);
- if (method == CompositeMethod::ClipPath) clips.push(tdata);
+ childClipper = compData->method == CompositeMethod::ClipPath ? true : false;
+ trd = target->pImpl->update(renderer, pTransform, 255, clips, pFlag, childClipper);
+ if (childClipper) clips.push(trd);
}
}
/* 2. Main Update */
- void *edata = nullptr;
+ RenderData rd = nullptr;
auto newFlag = static_cast<RenderUpdateFlag>(pFlag | renderFlag);
renderFlag = RenderUpdateFlag::None;
opacity = (opacity * this->opacity) / 255;
if (rTransform && pTransform) {
RenderTransform outTransform(pTransform, rTransform);
- edata = smethod->update(renderer, &outTransform, opacity, clips, newFlag);
+ rd = smethod->update(renderer, &outTransform, opacity, clips, newFlag, clipper);
} else {
auto outTransform = pTransform ? pTransform : rTransform;
- edata = smethod->update(renderer, outTransform, opacity, clips, newFlag);
+ rd = smethod->update(renderer, outTransform, opacity, clips, newFlag, clipper);
}
/* 3. Composition Post Processing */
if (compFastTrack) renderer.viewport(viewport);
- else if (tdata && compData->method == CompositeMethod::ClipPath) clips.pop();
+ else if (childClipper) clips.pop();
- return edata;
+ return rd;
}
@@ -384,19 +388,6 @@ CompositeMethod Paint::composite(const Paint** target) const noexcept
}
-Result Paint::composite(const Paint** source, CompositeMethod* method) const noexcept
-{
- if (source) *source = pImpl->compSource;
- auto met = (pImpl->compSource && pImpl->compSource->pImpl->compData ?
- pImpl->compSource->pImpl->compData->method : CompositeMethod::None);
- if (method) *method = met;
-
- if (pImpl->compSource != nullptr && met != CompositeMethod::None)
- return Result::Success;
- return Result::InsufficientCondition;
-}
-
-
Result Paint::opacity(uint8_t o) noexcept
{
if (pImpl->opacity == o) return Result::Success;
diff --git a/thirdparty/thorvg/src/lib/tvgPaint.h b/thirdparty/thorvg/src/lib/tvgPaint.h
index 94239c30a1..d70490c649 100644
--- a/thirdparty/thorvg/src/lib/tvgPaint.h
+++ b/thirdparty/thorvg/src/lib/tvgPaint.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_PAINT_H_
#define _TVG_PAINT_H_
@@ -42,7 +43,7 @@ namespace tvg
virtual ~StrategyMethod() {}
virtual bool dispose(RenderMethod& renderer) = 0;
- virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag) = 0; //Return engine data if it has.
+ virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper) = 0; //Return engine data if it has.
virtual bool render(RenderMethod& renderer) = 0;
virtual bool bounds(float* x, float* y, float* w, float* h) = 0;
virtual RenderRegion bounds(RenderMethod& renderer) const = 0;
@@ -62,7 +63,6 @@ namespace tvg
StrategyMethod* smethod = nullptr;
RenderTransform* rTransform = nullptr;
Composite* compData = nullptr;
- Paint* compSource = nullptr;
uint32_t renderFlag = RenderUpdateFlag::None;
uint32_t ctxFlag = ContextFlag::Invalid;
uint32_t id;
@@ -137,7 +137,6 @@ namespace tvg
if (!target && method == CompositeMethod::None) return true;
compData = static_cast<Composite*>(calloc(1, sizeof(Composite)));
}
- target->pImpl->compSource = source;
compData->target = target;
compData->source = source;
compData->method = method;
@@ -148,7 +147,7 @@ namespace tvg
bool scale(float factor);
bool translate(float x, float y);
bool bounds(float* x, float* y, float* w, float* h, bool transformed);
- void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag);
+ RenderData update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag, bool clipper = false);
bool render(RenderMethod& renderer);
Paint* duplicate();
};
@@ -177,9 +176,9 @@ namespace tvg
return inst->dispose(renderer);
}
- void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag renderFlag) override
+ RenderData update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag renderFlag, bool clipper) override
{
- return inst->update(renderer, transform, opacity, clips, renderFlag);
+ return inst->update(renderer, transform, opacity, clips, renderFlag, clipper);
}
bool render(RenderMethod& renderer) override
diff --git a/thirdparty/thorvg/src/lib/tvgPicture.cpp b/thirdparty/thorvg/src/lib/tvgPicture.cpp
index 1e04e25435..ad9db96245 100644
--- a/thirdparty/thorvg/src/lib/tvgPicture.cpp
+++ b/thirdparty/thorvg/src/lib/tvgPicture.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -107,7 +107,7 @@ Result Picture::size(float* w, float* h) const noexcept
const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept
{
//Try it, If not loaded yet.
- pImpl->reload();
+ pImpl->load();
if (pImpl->loader) {
if (w) *w = static_cast<uint32_t>(pImpl->loader->w);
@@ -116,6 +116,23 @@ const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept
if (w) *w = 0;
if (h) *h = 0;
}
- if (pImpl->surface) return pImpl->surface->buffer;
+ if (pImpl->surface) return pImpl->surface->buf32;
else return nullptr;
}
+
+
+Result Picture::mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept
+{
+ if (!triangles && triangleCnt > 0) return Result::InvalidArguments;
+ if (triangles && triangleCnt == 0) return Result::InvalidArguments;
+
+ pImpl->mesh(triangles, triangleCnt);
+ return Result::Success;
+}
+
+
+uint32_t Picture::mesh(const Polygon** triangles) const noexcept
+{
+ if (triangles) *triangles = pImpl->rm.triangles;
+ return pImpl->rm.triangleCnt;
+}
diff --git a/thirdparty/thorvg/src/lib/tvgPictureImpl.h b/thirdparty/thorvg/src/lib/tvgPictureImpl.h
index b6bc19fa9c..6af7a732e5 100644
--- a/thirdparty/thorvg/src/lib/tvgPictureImpl.h
+++ b/thirdparty/thorvg/src/lib/tvgPictureImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_PICTURE_IMPL_H_
#define _TVG_PICTURE_IMPL_H_
@@ -63,30 +64,28 @@ struct Picture::Impl
Paint* paint = nullptr; //vector picture uses
Surface* surface = nullptr; //bitmap picture uses
- void* rdata = nullptr; //engine data
+ RenderData rd = nullptr; //engine data
float w = 0, h = 0;
+ RenderMesh rm; //mesh data
bool resizing = false;
- uint32_t rendererColorSpace = 0;
~Impl()
{
if (paint) delete(paint);
- free(surface);
+ delete(surface);
}
bool dispose(RenderMethod& renderer)
{
bool ret = true;
- if (paint) {
- ret = paint->pImpl->dispose(renderer);
- } else if (surface) {
- ret = renderer.dispose(rdata);
- rdata = nullptr;
- }
+ if (paint) ret = paint->pImpl->dispose(renderer);
+ else if (surface) ret = renderer.dispose(rd);
+ rd = nullptr;
+
return ret;
}
- uint32_t reload()
+ uint32_t load()
{
if (loader) {
if (!paint) {
@@ -94,16 +93,21 @@ struct Picture::Impl
paint = p.release();
loader->close();
if (w != loader->w || h != loader->h) {
+ if (!resizing) {
+ w = loader->w;
+ h = loader->h;
+ }
loader->resize(paint, w, h);
resizing = false;
}
if (paint) return RenderUpdateFlag::None;
}
}
- free(surface);
- if ((surface = loader->bitmap(rendererColorSpace).release())) {
- loader->close();
- return RenderUpdateFlag::Image;
+ if (!surface) {
+ if ((surface = loader->bitmap().release())) {
+ loader->close();
+ return RenderUpdateFlag::Image;
+ }
}
}
return RenderUpdateFlag::None;
@@ -123,32 +127,31 @@ struct Picture::Impl
else return RenderTransform(pTransform, &tmp);
}
- void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
+ RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
{
- rendererColorSpace = renderer.colorSpace();
- auto flag = reload();
+ auto flag = load();
if (surface) {
auto transform = resizeTransform(pTransform);
- rdata = renderer.prepare(surface, rdata, &transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
+ rd = renderer.prepare(surface, &rm, rd, &transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
} else if (paint) {
if (resizing) {
loader->resize(paint, w, h);
resizing = false;
}
- rdata = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
+ rd = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
}
- return rdata;
+ return rd;
}
bool render(RenderMethod &renderer)
{
- if (surface) return renderer.renderImage(rdata);
+ if (surface) return renderer.renderImage(rd);
else if (paint) return paint->pImpl->render(renderer);
return false;
}
- bool viewbox(float* x, float* y, float* w, float* h) const
+ bool viewbox(float* x, float* y, float* w, float* h)
{
if (!loader) return false;
if (x) *x = loader->vx;
@@ -168,17 +171,43 @@ struct Picture::Impl
bool bounds(float* x, float* y, float* w, float* h)
{
- if (x) *x = 0;
- if (y) *y = 0;
- if (w) *w = this->w;
- if (h) *h = this->h;
-
+ if (rm.triangleCnt > 0) {
+ auto triangles = rm.triangles;
+ auto min = triangles[0].vertex[0].pt;
+ auto max = triangles[0].vertex[0].pt;
+
+ for (uint32_t i = 0; i < rm.triangleCnt; ++i) {
+ if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x;
+ else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x;
+ if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y;
+ else if (triangles[i].vertex[0].pt.y > max.y) max.y = triangles[i].vertex[0].pt.y;
+
+ if (triangles[i].vertex[1].pt.x < min.x) min.x = triangles[i].vertex[1].pt.x;
+ else if (triangles[i].vertex[1].pt.x > max.x) max.x = triangles[i].vertex[1].pt.x;
+ if (triangles[i].vertex[1].pt.y < min.y) min.y = triangles[i].vertex[1].pt.y;
+ else if (triangles[i].vertex[1].pt.y > max.y) max.y = triangles[i].vertex[1].pt.y;
+
+ if (triangles[i].vertex[2].pt.x < min.x) min.x = triangles[i].vertex[2].pt.x;
+ else if (triangles[i].vertex[2].pt.x > max.x) max.x = triangles[i].vertex[2].pt.x;
+ if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y;
+ else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y;
+ }
+ if (x) *x = min.x;
+ if (y) *y = min.y;
+ if (w) *w = max.x - min.x;
+ if (h) *h = max.y - min.y;
+ } else {
+ if (x) *x = 0;
+ if (y) *y = 0;
+ if (w) *w = this->w;
+ if (h) *h = this->h;
+ }
return true;
}
RenderRegion bounds(RenderMethod& renderer)
{
- if (rdata) return renderer.region(rdata);
+ if (rd) return renderer.region(rd);
if (paint) return paint->pImpl->bounds(renderer);
return {0, 0, 0, 0};
}
@@ -216,15 +245,28 @@ struct Picture::Impl
if (paint || surface) return Result::InsufficientCondition;
if (loader) loader->close();
loader = LoaderMgr::loader(data, w, h, copy);
- if (!loader) return Result::NonSupport;
+ if (!loader) return Result::FailedAllocation;
this->w = loader->w;
this->h = loader->h;
return Result::Success;
}
+ void mesh(const Polygon* triangles, const uint32_t triangleCnt)
+ {
+ if (triangles && triangleCnt > 0) {
+ this->rm.triangleCnt = triangleCnt;
+ this->rm.triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCnt);
+ memcpy(this->rm.triangles, triangles, sizeof(Polygon) * triangleCnt);
+ } else {
+ free(this->rm.triangles);
+ this->rm.triangles = nullptr;
+ this->rm.triangleCnt = 0;
+ }
+ }
+
Paint* duplicate()
{
- reload();
+ load();
auto ret = Picture::gen();
@@ -233,19 +275,27 @@ struct Picture::Impl
dup->loader = loader;
if (surface) {
- dup->surface = static_cast<Surface*>(malloc(sizeof(Surface)));
+ dup->surface = new Surface;
*dup->surface = *surface;
+ //TODO: A dupilcation is not a proxy... it needs copy of the pixel data?
+ dup->surface->owner = false;
}
dup->w = w;
dup->h = h;
dup->resizing = resizing;
+ if (rm.triangleCnt > 0) {
+ dup->rm.triangleCnt = rm.triangleCnt;
+ dup->rm.triangles = (Polygon*)malloc(sizeof(Polygon) * rm.triangleCnt);
+ memcpy(dup->rm.triangles, rm.triangles, sizeof(Polygon) * rm.triangleCnt);
+ }
+
return ret.release();
}
Iterator* iterator()
{
- reload();
+ load();
return new PictureIterator(paint);
}
};
diff --git a/thirdparty/thorvg/src/lib/tvgRadialGradient.cpp b/thirdparty/thorvg/src/lib/tvgRadialGradient.cpp
index 7f4e1d7e17..a85f60e5d0 100644
--- a/thirdparty/thorvg/src/lib/tvgRadialGradient.cpp
+++ b/thirdparty/thorvg/src/lib/tvgRadialGradient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include <float.h>
#include "tvgFill.h"
diff --git a/thirdparty/thorvg/src/lib/tvgRender.cpp b/thirdparty/thorvg/src/lib/tvgRender.cpp
index 90f0917e6b..fb9270afe6 100644
--- a/thirdparty/thorvg/src/lib/tvgRender.cpp
+++ b/thirdparty/thorvg/src/lib/tvgRender.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgMath.h"
#include "tvgRender.h"
diff --git a/thirdparty/thorvg/src/lib/tvgRender.h b/thirdparty/thorvg/src/lib/tvgRender.h
index f474d87895..6270fa5316 100644
--- a/thirdparty/thorvg/src/lib/tvgRender.h
+++ b/thirdparty/thorvg/src/lib/tvgRender.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_RENDER_H_
#define _TVG_RENDER_H_
@@ -28,18 +29,38 @@
namespace tvg
{
+using RenderData = void*;
+using pixel_t = uint32_t;
+
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255};
-struct Surface
+struct Surface;
+
+enum ColorSpace
{
- //TODO: Union for multiple types
- uint32_t* buffer;
- uint32_t stride;
- uint32_t w, h;
- uint32_t cs;
+ ABGR8888 = 0, //The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied.
+ ARGB8888, //The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied.
+ ABGR8888S, //The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied.
+ ARGB8888S, //The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied.
+ Grayscale8, //One single channel data.
+ Unsupported //TODO: Change to the default, At the moment, we put it in the last to align with SwCanvas::Colorspace.
};
-using RenderData = void*;
+struct Surface
+{
+ union {
+ pixel_t* data; //system based data pointer
+ uint32_t* buf32; //for explicit 32bits channels
+ uint8_t* buf8; //for explicit 8bits grayscale
+ };
+ uint32_t stride;
+ uint32_t w, h;
+ ColorSpace cs;
+ uint8_t channelSize;
+
+ bool premultiplied; //Alpha-premultiplied
+ bool owner; //Only owner could modify the buffer
+};
struct Compositor
{
@@ -47,6 +68,17 @@ struct Compositor
uint32_t opacity;
};
+struct RenderMesh
+{
+ Polygon* triangles = nullptr;
+ uint32_t triangleCnt = 0;
+
+ ~RenderMesh()
+ {
+ free(triangles);
+ }
+};
+
struct RenderRegion
{
int32_t x, y, w, h;
@@ -84,13 +116,110 @@ struct RenderTransform
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
};
+struct RenderStroke
+{
+ float width = 0.0f;
+ uint8_t color[4] = {0, 0, 0, 0};
+ Fill *fill = nullptr;
+ float* dashPattern = nullptr;
+ uint32_t dashCnt = 0;
+ StrokeCap cap = StrokeCap::Square;
+ StrokeJoin join = StrokeJoin::Bevel;
+ bool strokeFirst = false;
+
+ ~RenderStroke()
+ {
+ free(dashPattern);
+ if (fill) delete(fill);
+ }
+};
+
+struct RenderShape
+{
+ struct
+ {
+ PathCommand* cmds = nullptr;
+ uint32_t cmdCnt = 0;
+ uint32_t reservedCmdCnt = 0;
+
+ Point *pts = nullptr;
+ uint32_t ptsCnt = 0;
+ uint32_t reservedPtsCnt = 0;
+ } path;
+
+ Fill *fill = nullptr;
+ RenderStroke *stroke = nullptr;
+ uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
+ FillRule rule = FillRule::Winding;
+
+ ~RenderShape()
+ {
+ free(path.cmds);
+ free(path.pts);
+
+ if (fill) delete(fill);
+ if (stroke) delete(stroke);
+ }
+
+ void fillColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const
+ {
+ if (r) *r = color[0];
+ if (g) *g = color[1];
+ if (b) *b = color[2];
+ if (a) *a = color[3];
+ }
+
+ float strokeWidth() const
+ {
+ if (!stroke) return 0;
+ return stroke->width;
+ }
+
+ bool strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const
+ {
+ if (!stroke) return false;
+
+ if (r) *r = stroke->color[0];
+ if (g) *g = stroke->color[1];
+ if (b) *b = stroke->color[2];
+ if (a) *a = stroke->color[3];
+
+ return true;
+ }
+
+ const Fill* strokeFill() const
+ {
+ if (!stroke) return nullptr;
+ return stroke->fill;
+ }
+
+ uint32_t strokeDash(const float** dashPattern) const
+ {
+ if (!stroke) return 0;
+ if (dashPattern) *dashPattern = stroke->dashPattern;
+ return stroke->dashCnt;
+ }
+
+ StrokeCap strokeCap() const
+ {
+ if (!stroke) return StrokeCap::Square;
+ return stroke->cap;
+ }
+
+ StrokeJoin strokeJoin() const
+ {
+ if (!stroke) return StrokeJoin::Bevel;
+ return stroke->join;
+ }
+};
class RenderMethod
{
public:
virtual ~RenderMethod() {}
- virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
- virtual RenderData prepare(Surface* image, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
+ virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) = 0;
+ virtual RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
+ virtual RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
virtual bool preRender() = 0;
virtual bool renderShape(RenderData data) = 0;
virtual bool renderImage(RenderData data) = 0;
@@ -99,17 +228,47 @@ public:
virtual RenderRegion region(RenderData data) = 0;
virtual RenderRegion viewport() = 0;
virtual bool viewport(const RenderRegion& vp) = 0;
+ virtual ColorSpace colorSpace() = 0;
virtual bool clear() = 0;
virtual bool sync() = 0;
- virtual Compositor* target(const RenderRegion& region) = 0;
+ virtual Compositor* target(const RenderRegion& region, ColorSpace cs) = 0;
virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0;
virtual bool endComposite(Compositor* cmp) = 0;
-
- virtual uint32_t colorSpace() = 0;
};
+static inline uint8_t CHANNEL_SIZE(ColorSpace cs)
+{
+ switch(cs) {
+ case ColorSpace::ABGR8888:
+ case ColorSpace::ABGR8888S:
+ case ColorSpace::ARGB8888:
+ case ColorSpace::ARGB8888S:
+ return sizeof(uint32_t);
+ case ColorSpace::Grayscale8:
+ return sizeof(uint8_t);
+ case ColorSpace::Unsupported:
+ default:
+ TVGERR("SW_ENGINE", "Unsupported Channel Size! = %d", (int)cs);
+ return 0;
+ }
+}
+
+static inline ColorSpace COMPOSITE_TO_COLORSPACE(RenderMethod& renderer, CompositeMethod method)
+{
+ switch(method) {
+ case CompositeMethod::AlphaMask:
+ case CompositeMethod::InvAlphaMask:
+ return ColorSpace::Grayscale8;
+ case CompositeMethod::LumaMask:
+ return renderer.colorSpace();
+ default:
+ TVGERR("COMMON", "Unsupported Composite Size! = %d", (int)method);
+ return ColorSpace::Unsupported;
+ }
+}
+
}
#endif //_TVG_RENDER_H_
diff --git a/thirdparty/thorvg/src/lib/tvgSaveModule.h b/thirdparty/thorvg/src/lib/tvgSaveModule.h
index 3531662fdd..a997b644a7 100644
--- a/thirdparty/thorvg/src/lib/tvgSaveModule.h
+++ b/thirdparty/thorvg/src/lib/tvgSaveModule.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_SAVE_MODULE_H_
#define _TVG_SAVE_MODULE_H_
@@ -27,7 +28,7 @@
namespace tvg
{
-class SaveModule : public IteratorAccessor
+class SaveModule
{
public:
virtual ~SaveModule() {}
diff --git a/thirdparty/thorvg/src/lib/tvgSaver.cpp b/thirdparty/thorvg/src/lib/tvgSaver.cpp
index e71953700c..85b5a37855 100644
--- a/thirdparty/thorvg/src/lib/tvgSaver.cpp
+++ b/thirdparty/thorvg/src/lib/tvgSaver.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgCommon.h"
#include "tvgSaveModule.h"
diff --git a/thirdparty/thorvg/src/lib/tvgScene.cpp b/thirdparty/thorvg/src/lib/tvgScene.cpp
index 9ed7d45d5c..feb45a9d22 100644
--- a/thirdparty/thorvg/src/lib/tvgScene.cpp
+++ b/thirdparty/thorvg/src/lib/tvgScene.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgSceneImpl.h"
/************************************************************************/
diff --git a/thirdparty/thorvg/src/lib/tvgSceneImpl.h b/thirdparty/thorvg/src/lib/tvgSceneImpl.h
index b6c68262c6..9ce4d0b37d 100644
--- a/thirdparty/thorvg/src/lib/tvgSceneImpl.h
+++ b/thirdparty/thorvg/src/lib/tvgSceneImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_SCENE_IMPL_H_
#define _TVG_SCENE_IMPL_H_
@@ -60,6 +61,7 @@ struct Scene::Impl
Array<Paint*> paints;
uint8_t opacity; //for composition
RenderMethod* renderer = nullptr; //keep it for explicit clear
+ RenderData rd = nullptr;
Scene* scene = nullptr;
Impl(Scene* s) : scene(s)
@@ -79,9 +81,11 @@ struct Scene::Impl
(*paint)->pImpl->dispose(renderer);
}
+ auto ret = renderer.dispose(rd);
this->renderer = nullptr;
+ this->rd = nullptr;
- return true;
+ return ret;
}
bool needComposition(uint32_t opacity)
@@ -101,23 +105,29 @@ struct Scene::Impl
return false;
}
- void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag)
+ RenderData update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag, bool clipper)
{
/* Overriding opacity value. If this scene is half-translucent,
It must do intermeidate composition with that opacity value. */
this->opacity = static_cast<uint8_t>(opacity);
if (needComposition(opacity)) opacity = 255;
- for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
- (*paint)->pImpl->update(renderer, transform, opacity, clips, static_cast<uint32_t>(flag));
- }
-
- /* FXIME: it requires to return list of children engine data
- This is necessary for scene composition */
-
this->renderer = &renderer;
- return nullptr;
+ if (clipper) {
+ Array<RenderData> rds;
+ rds.reserve(paints.count);
+ for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
+ rds.push((*paint)->pImpl->update(renderer, transform, opacity, clips, flag, true));
+ }
+ rd = renderer.prepare(rds, rd, transform, opacity, clips, flag);
+ return rd;
+ } else {
+ for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
+ (*paint)->pImpl->update(renderer, transform, opacity, clips, flag, false);
+ }
+ return nullptr;
+ }
}
bool render(RenderMethod& renderer)
@@ -125,7 +135,7 @@ struct Scene::Impl
Compositor* cmp = nullptr;
if (needComposition(opacity)) {
- cmp = renderer.target(bounds(renderer));
+ cmp = renderer.target(bounds(renderer), renderer.colorSpace());
renderer.beginComposite(cmp, CompositeMethod::None, opacity);
}
diff --git a/thirdparty/thorvg/src/lib/tvgShape.cpp b/thirdparty/thorvg/src/lib/tvgShape.cpp
index e57f2eafb2..a8354375c9 100644
--- a/thirdparty/thorvg/src/lib/tvgShape.cpp
+++ b/thirdparty/thorvg/src/lib/tvgShape.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,7 +32,7 @@ constexpr auto PATH_KAPPA = 0.552284f;
/* External Class Implementation */
/************************************************************************/
-Shape :: Shape() : pImpl(new Impl(this))
+Shape :: Shape() : pImpl(new Impl())
{
Paint::pImpl->id = TVG_CLASS_ID_SHAPE;
Paint::pImpl->method(new PaintMethod<Shape::Impl>(pImpl));
@@ -59,8 +59,7 @@ uint32_t Shape::identifier() noexcept
Result Shape::reset() noexcept
{
- pImpl->path.reset();
- pImpl->flag = RenderUpdateFlag::Path;
+ pImpl->reset();
return Result::Success;
}
@@ -70,9 +69,9 @@ uint32_t Shape::pathCommands(const PathCommand** cmds) const noexcept
{
if (!cmds) return 0;
- *cmds = pImpl->path.cmds;
+ *cmds = pImpl->rs.path.cmds;
- return pImpl->path.cmdCnt;
+ return pImpl->rs.path.cmdCnt;
}
@@ -80,9 +79,9 @@ uint32_t Shape::pathCoords(const Point** pts) const noexcept
{
if (!pts) return 0;
- *pts = pImpl->path.pts;
+ *pts = pImpl->rs.path.pts;
- return pImpl->path.ptsCnt;
+ return pImpl->rs.path.ptsCnt;
}
@@ -90,10 +89,8 @@ Result Shape::appendPath(const PathCommand *cmds, uint32_t cmdCnt, const Point*
{
if (cmdCnt == 0 || ptsCnt == 0 || !cmds || !pts) return Result::InvalidArguments;
- pImpl->path.grow(cmdCnt, ptsCnt);
- pImpl->path.append(cmds, cmdCnt, pts, ptsCnt);
-
- pImpl->flag |= RenderUpdateFlag::Path;
+ pImpl->grow(cmdCnt, ptsCnt);
+ pImpl->append(cmds, cmdCnt, pts, ptsCnt);
return Result::Success;
}
@@ -101,9 +98,7 @@ Result Shape::appendPath(const PathCommand *cmds, uint32_t cmdCnt, const Point*
Result Shape::moveTo(float x, float y) noexcept
{
- pImpl->path.moveTo(x, y);
-
- pImpl->flag |= RenderUpdateFlag::Path;
+ pImpl->moveTo(x, y);
return Result::Success;
}
@@ -111,9 +106,7 @@ Result Shape::moveTo(float x, float y) noexcept
Result Shape::lineTo(float x, float y) noexcept
{
- pImpl->path.lineTo(x, y);
-
- pImpl->flag |= RenderUpdateFlag::Path;
+ pImpl->lineTo(x, y);
return Result::Success;
}
@@ -121,9 +114,7 @@ Result Shape::lineTo(float x, float y) noexcept
Result Shape::cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) noexcept
{
- pImpl->path.cubicTo(cx1, cy1, cx2, cy2, x, y);
-
- pImpl->flag |= RenderUpdateFlag::Path;
+ pImpl->cubicTo(cx1, cy1, cx2, cy2, x, y);
return Result::Success;
}
@@ -131,9 +122,7 @@ Result Shape::cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float
Result Shape::close() noexcept
{
- pImpl->path.close();
-
- pImpl->flag |= RenderUpdateFlag::Path;
+ pImpl->close();
return Result::Success;
}
@@ -144,15 +133,13 @@ Result Shape::appendCircle(float cx, float cy, float rx, float ry) noexcept
auto rxKappa = rx * PATH_KAPPA;
auto ryKappa = ry * PATH_KAPPA;
- pImpl->path.grow(6, 13);
- pImpl->path.moveTo(cx, cy - ry);
- pImpl->path.cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy);
- pImpl->path.cubicTo(cx + rx, cy + ryKappa, cx + rxKappa, cy + ry, cx, cy + ry);
- pImpl->path.cubicTo(cx - rxKappa, cy + ry, cx - rx, cy + ryKappa, cx - rx, cy);
- pImpl->path.cubicTo(cx - rx, cy - ryKappa, cx - rxKappa, cy - ry, cx, cy - ry);
- pImpl->path.close();
-
- pImpl->flag |= RenderUpdateFlag::Path;
+ pImpl->grow(6, 13);
+ pImpl->moveTo(cx, cy - ry);
+ pImpl->cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy);
+ pImpl->cubicTo(cx + rx, cy + ryKappa, cx + rxKappa, cy + ry, cx, cy + ry);
+ pImpl->cubicTo(cx - rxKappa, cy + ry, cx - rx, cy + ryKappa, cx - rx, cy);
+ pImpl->cubicTo(cx - rx, cy - ryKappa, cx - rxKappa, cy - ry, cx, cy - ry);
+ pImpl->close();
return Result::Success;
}
@@ -174,10 +161,10 @@ Result Shape::appendArc(float cx, float cy, float radius, float startAngle, floa
Point start = {radius * cosf(startAngle), radius * sinf(startAngle)};
if (pie) {
- pImpl->path.moveTo(cx, cy);
- pImpl->path.lineTo(start.x + cx, start.y + cy);
+ pImpl->moveTo(cx, cy);
+ pImpl->lineTo(start.x + cx, start.y + cy);
} else {
- pImpl->path.moveTo(start.x + cx, start.y + cy);
+ pImpl->moveTo(start.x + cx, start.y + cy);
}
for (int i = 0; i < nCurves; ++i) {
@@ -204,14 +191,12 @@ Result Shape::appendArc(float cx, float cy, float radius, float startAngle, floa
Point ctrl1 = {ax - k2 * ay + cx, ay + k2 * ax + cy};
Point ctrl2 = {bx + k2 * by + cx, by - k2 * bx + cy};
- pImpl->path.cubicTo(ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y);
+ pImpl->cubicTo(ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y);
startAngle = endAngle;
}
- if (pie) pImpl->path.close();
-
- pImpl->flag |= RenderUpdateFlag::Path;
+ if (pie) pImpl->close();
return Result::Success;
}
@@ -228,48 +213,47 @@ Result Shape::appendRect(float x, float y, float w, float h, float rx, float ry)
//rectangle
if (rx == 0 && ry == 0) {
- pImpl->path.grow(5, 4);
- pImpl->path.moveTo(x, y);
- pImpl->path.lineTo(x + w, y);
- pImpl->path.lineTo(x + w, y + h);
- pImpl->path.lineTo(x, y + h);
- pImpl->path.close();
+ pImpl->grow(5, 4);
+ pImpl->moveTo(x, y);
+ pImpl->lineTo(x + w, y);
+ pImpl->lineTo(x + w, y + h);
+ pImpl->lineTo(x, y + h);
+ pImpl->close();
//circle
} else if (mathEqual(rx, halfW) && mathEqual(ry, halfH)) {
return appendCircle(x + (w * 0.5f), y + (h * 0.5f), rx, ry);
} else {
auto hrx = rx * 0.5f;
auto hry = ry * 0.5f;
- pImpl->path.grow(10, 17);
- pImpl->path.moveTo(x + rx, y);
- pImpl->path.lineTo(x + w - rx, y);
- pImpl->path.cubicTo(x + w - rx + hrx, y, x + w, y + ry - hry, x + w, y + ry);
- pImpl->path.lineTo(x + w, y + h - ry);
- pImpl->path.cubicTo(x + w, y + h - ry + hry, x + w - rx + hrx, y + h, x + w - rx, y + h);
- pImpl->path.lineTo(x + rx, y + h);
- pImpl->path.cubicTo(x + rx - hrx, y + h, x, y + h - ry + hry, x, y + h - ry);
- pImpl->path.lineTo(x, y + ry);
- pImpl->path.cubicTo(x, y + ry - hry, x + rx - hrx, y, x + rx, y);
- pImpl->path.close();
+ pImpl->grow(10, 17);
+ pImpl->moveTo(x + rx, y);
+ pImpl->lineTo(x + w - rx, y);
+ pImpl->cubicTo(x + w - rx + hrx, y, x + w, y + ry - hry, x + w, y + ry);
+ pImpl->lineTo(x + w, y + h - ry);
+ pImpl->cubicTo(x + w, y + h - ry + hry, x + w - rx + hrx, y + h, x + w - rx, y + h);
+ pImpl->lineTo(x + rx, y + h);
+ pImpl->cubicTo(x + rx - hrx, y + h, x, y + h - ry + hry, x, y + h - ry);
+ pImpl->lineTo(x, y + ry);
+ pImpl->cubicTo(x, y + ry - hry, x + rx - hrx, y, x + rx, y);
+ pImpl->close();
}
- pImpl->flag |= RenderUpdateFlag::Path;
-
return Result::Success;
}
+//TODO: kill alpha at TVG 1.0, because we also have opacity
Result Shape::fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
{
- pImpl->color[0] = r;
- pImpl->color[1] = g;
- pImpl->color[2] = b;
- pImpl->color[3] = a;
+ pImpl->rs.color[0] = r;
+ pImpl->rs.color[1] = g;
+ pImpl->rs.color[2] = b;
+ pImpl->rs.color[3] = a;
pImpl->flag |= RenderUpdateFlag::Color;
- if (pImpl->fill) {
- delete(pImpl->fill);
- pImpl->fill = nullptr;
+ if (pImpl->rs.fill) {
+ delete(pImpl->rs.fill);
+ pImpl->rs.fill = nullptr;
pImpl->flag |= RenderUpdateFlag::Gradient;
}
@@ -282,8 +266,8 @@ Result Shape::fill(unique_ptr<Fill> f) noexcept
auto p = f.release();
if (!p) return Result::MemoryCorruption;
- if (pImpl->fill && pImpl->fill != p) delete(pImpl->fill);
- pImpl->fill = p;
+ if (pImpl->rs.fill && pImpl->rs.fill != p) delete(pImpl->rs.fill);
+ pImpl->rs.fill = p;
pImpl->flag |= RenderUpdateFlag::Gradient;
return Result::Success;
@@ -292,17 +276,23 @@ Result Shape::fill(unique_ptr<Fill> f) noexcept
Result Shape::fillColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept
{
- if (r) *r = pImpl->color[0];
- if (g) *g = pImpl->color[1];
- if (b) *b = pImpl->color[2];
- if (a) *a = pImpl->color[3];
+ pImpl->rs.fillColor(r, g, b, a);
return Result::Success;
}
+
const Fill* Shape::fill() const noexcept
{
- return pImpl->fill;
+ return pImpl->rs.fill;
+}
+
+
+Result Shape::order(bool strokeFirst) noexcept
+{
+ if (!pImpl->strokeFirst(strokeFirst)) return Result::FailedAllocation;
+
+ return Result::Success;
}
@@ -316,8 +306,7 @@ Result Shape::stroke(float width) noexcept
float Shape::strokeWidth() const noexcept
{
- if (!pImpl->stroke) return 0;
- return pImpl->stroke->width;
+ return pImpl->rs.strokeWidth();
}
@@ -331,12 +320,7 @@ Result Shape::stroke(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
Result Shape::strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept
{
- if (!pImpl->stroke) return Result::InsufficientCondition;
-
- if (r) *r = pImpl->stroke->color[0];
- if (g) *g = pImpl->stroke->color[1];
- if (b) *b = pImpl->stroke->color[2];
- if (a) *a = pImpl->stroke->color[3];
+ if (!pImpl->rs.strokeColor(r, g, b, a)) return Result::InsufficientCondition;
return Result::Success;
}
@@ -350,9 +334,7 @@ Result Shape::stroke(unique_ptr<Fill> f) noexcept
const Fill* Shape::strokeFill() const noexcept
{
- if (!pImpl->stroke) return nullptr;
-
- return pImpl->stroke->fill;
+ return pImpl->rs.strokeFill();
}
@@ -373,11 +355,7 @@ Result Shape::stroke(const float* dashPattern, uint32_t cnt) noexcept
uint32_t Shape::strokeDash(const float** dashPattern) const noexcept
{
- if (!pImpl->stroke) return 0;
-
- if (dashPattern) *dashPattern = pImpl->stroke->dashPattern;
-
- return pImpl->stroke->dashCnt;
+ return pImpl->rs.strokeDash(dashPattern);
}
@@ -399,23 +377,19 @@ Result Shape::stroke(StrokeJoin join) noexcept
StrokeCap Shape::strokeCap() const noexcept
{
- if (!pImpl->stroke) return StrokeCap::Square;
-
- return pImpl->stroke->cap;
+ return pImpl->rs.strokeCap();
}
StrokeJoin Shape::strokeJoin() const noexcept
{
- if (!pImpl->stroke) return StrokeJoin::Bevel;
-
- return pImpl->stroke->join;
+ return pImpl->rs.strokeJoin();
}
Result Shape::fill(FillRule r) noexcept
{
- pImpl->rule = r;
+ pImpl->rs.rule = r;
return Result::Success;
}
@@ -423,5 +397,5 @@ Result Shape::fill(FillRule r) noexcept
FillRule Shape::fillRule() const noexcept
{
- return pImpl->rule;
+ return pImpl->rs.rule;
}
diff --git a/thirdparty/thorvg/src/lib/tvgShapeImpl.h b/thirdparty/thorvg/src/lib/tvgShapeImpl.h
index 738b21ed70..da288756fb 100644
--- a/thirdparty/thorvg/src/lib/tvgShapeImpl.h
+++ b/thirdparty/thorvg/src/lib/tvgShapeImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_SHAPE_IMPL_H_
#define _TVG_SHAPE_IMPL_H_
@@ -29,243 +30,155 @@
/* Internal Class Implementation */
/************************************************************************/
-struct ShapeStroke
+struct Shape::Impl
{
- float width;
- uint8_t color[4];
- Fill *fill;
- float* dashPattern;
- uint32_t dashCnt;
- StrokeCap cap;
- StrokeJoin join;
-
- void copy(const ShapeStroke* src)
+ RenderShape rs; //shape data
+ RenderData rd = nullptr; //engine data
+ uint32_t flag = RenderUpdateFlag::None;
+
+ bool dispose(RenderMethod& renderer)
{
- width = src->width;
- dashCnt = src->dashCnt;
- cap = src->cap;
- join = src->join;
-
- memcpy(color, src->color, sizeof(color));
- if (dashCnt > 0) {
- dashPattern = static_cast<float*>(malloc(sizeof(float) * dashCnt));
- memcpy(dashPattern, src->dashPattern, sizeof(float) * dashCnt);
- }
- if (src->fill) fill = src->fill->duplicate();
+ auto ret = renderer.dispose(rd);
+ rd = nullptr;
+ return ret;
}
- void clear()
+ bool render(RenderMethod& renderer)
{
- if (dashPattern) free(dashPattern);
- if (fill) delete(fill);
+ return renderer.renderShape(rd);
}
-};
-
-struct ShapePath
-{
- PathCommand* cmds = nullptr;
- uint32_t cmdCnt = 0;
- uint32_t reservedCmdCnt = 0;
-
- Point *pts = nullptr;
- uint32_t ptsCnt = 0;
- uint32_t reservedPtsCnt = 0;
-
- ~ShapePath()
+ RenderData update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
{
- if (cmds) free(cmds);
- if (pts) free(pts);
+ rd = renderer.prepare(rs, rd, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
+ flag = RenderUpdateFlag::None;
+ return rd;
}
- ShapePath()
+ RenderRegion bounds(RenderMethod& renderer)
{
+ return renderer.region(rd);
}
- void duplicate(const ShapePath* src)
+ bool bounds(float* x, float* y, float* w, float* h)
{
- if (src->cmdCnt == 0 || src->ptsCnt == 0) return;
-
- cmdCnt = src->cmdCnt;
- reservedCmdCnt = src->reservedCmdCnt;
- ptsCnt = src->ptsCnt;
- reservedPtsCnt = src->reservedPtsCnt;
+ //Path bounding size
+ if (rs.path.ptsCnt > 0 ) {
+ Point min = { rs.path.pts[0].x, rs.path.pts[0].y };
+ Point max = { rs.path.pts[0].x, rs.path.pts[0].y };
+
+ for (uint32_t i = 1; i < rs.path.ptsCnt; ++i) {
+ if (rs.path.pts[i].x < min.x) min.x = rs.path.pts[i].x;
+ if (rs.path.pts[i].y < min.y) min.y = rs.path.pts[i].y;
+ if (rs.path.pts[i].x > max.x) max.x = rs.path.pts[i].x;
+ if (rs.path.pts[i].y > max.y) max.y = rs.path.pts[i].y;
+ }
- cmds = static_cast<PathCommand*>(malloc(sizeof(PathCommand) * reservedCmdCnt));
- if (!cmds) return;
- memcpy(cmds, src->cmds, sizeof(PathCommand) * cmdCnt);
+ if (x) *x = min.x;
+ if (y) *y = min.y;
+ if (w) *w = max.x - min.x;
+ if (h) *h = max.y - min.y;
+ }
- pts = static_cast<Point*>(malloc(sizeof(Point) * reservedPtsCnt));
- if (!pts) {
- free(cmds);
- return;
+ //Stroke feathering
+ if (rs.stroke) {
+ if (x) *x -= rs.stroke->width * 0.5f;
+ if (y) *y -= rs.stroke->width * 0.5f;
+ if (w) *w += rs.stroke->width;
+ if (h) *h += rs.stroke->width;
}
- memcpy(pts, src->pts, sizeof(Point) * ptsCnt);
+ return rs.path.ptsCnt > 0 ? true : false;
}
void reserveCmd(uint32_t cmdCnt)
{
- if (cmdCnt <= reservedCmdCnt) return;
- reservedCmdCnt = cmdCnt;
- cmds = static_cast<PathCommand*>(realloc(cmds, sizeof(PathCommand) * reservedCmdCnt));
+ if (cmdCnt <= rs.path.reservedCmdCnt) return;
+ rs.path.reservedCmdCnt = cmdCnt;
+ rs.path.cmds = static_cast<PathCommand*>(realloc(rs.path.cmds, sizeof(PathCommand) * rs.path.reservedCmdCnt));
}
void reservePts(uint32_t ptsCnt)
{
- if (ptsCnt <= reservedPtsCnt) return;
- reservedPtsCnt = ptsCnt;
- pts = static_cast<Point*>(realloc(pts, sizeof(Point) * reservedPtsCnt));
+ if (ptsCnt <= rs.path.reservedPtsCnt) return;
+ rs.path.reservedPtsCnt = ptsCnt;
+ rs.path.pts = static_cast<Point*>(realloc(rs.path.pts, sizeof(Point) * rs.path.reservedPtsCnt));
}
void grow(uint32_t cmdCnt, uint32_t ptsCnt)
{
- reserveCmd(this->cmdCnt + cmdCnt);
- reservePts(this->ptsCnt + ptsCnt);
+ reserveCmd(rs.path.cmdCnt + cmdCnt);
+ reservePts(rs.path.ptsCnt + ptsCnt);
}
void reset()
{
- cmdCnt = 0;
- ptsCnt = 0;
- }
-
- void append(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt)
- {
- memcpy(this->cmds + this->cmdCnt, cmds, sizeof(PathCommand) * cmdCnt);
- memcpy(this->pts + this->ptsCnt, pts, sizeof(Point) * ptsCnt);
- this->cmdCnt += cmdCnt;
- this->ptsCnt += ptsCnt;
- }
+ rs.path.cmdCnt = 0;
+ rs.path.ptsCnt = 0;
- void moveTo(float x, float y)
- {
- if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
- if (ptsCnt + 2 > reservedPtsCnt) reservePts((ptsCnt + 2) * 2);
-
- cmds[cmdCnt++] = PathCommand::MoveTo;
- pts[ptsCnt++] = {x, y};
+ flag = RenderUpdateFlag::Path;
}
- void lineTo(float x, float y)
+ void append(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt)
{
- if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
- if (ptsCnt + 2 > reservedPtsCnt) reservePts((ptsCnt + 2) * 2);
+ memcpy(rs.path.cmds + rs.path.cmdCnt, cmds, sizeof(PathCommand) * cmdCnt);
+ memcpy(rs.path.pts + rs.path.ptsCnt, pts, sizeof(Point) * ptsCnt);
+ rs.path.cmdCnt += cmdCnt;
+ rs.path.ptsCnt += ptsCnt;
- cmds[cmdCnt++] = PathCommand::LineTo;
- pts[ptsCnt++] = {x, y};
+ flag |= RenderUpdateFlag::Path;
}
- void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y)
+ void moveTo(float x, float y)
{
- if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
- if (ptsCnt + 3 > reservedPtsCnt) reservePts((ptsCnt + 3) * 2);
+ if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2);
+ if (rs.path.ptsCnt + 2 > rs.path.reservedPtsCnt) reservePts((rs.path.ptsCnt + 2) * 2);
- cmds[cmdCnt++] = PathCommand::CubicTo;
- pts[ptsCnt++] = {cx1, cy1};
- pts[ptsCnt++] = {cx2, cy2};
- pts[ptsCnt++] = {x, y};
- }
+ rs.path.cmds[rs.path.cmdCnt++] = PathCommand::MoveTo;
+ rs.path.pts[rs.path.ptsCnt++] = {x, y};
- void close()
- {
- if (cmdCnt > 0 && cmds[cmdCnt - 1] == PathCommand::Close) return;
-
- if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
- cmds[cmdCnt++] = PathCommand::Close;
+ flag |= RenderUpdateFlag::Path;
}
- bool bounds(float* x, float* y, float* w, float* h) const
+ void lineTo(float x, float y)
{
- if (ptsCnt == 0) return false;
+ if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2);
+ if (rs.path.ptsCnt + 2 > rs.path.reservedPtsCnt) reservePts((rs.path.ptsCnt + 2) * 2);
- Point min = { pts[0].x, pts[0].y };
- Point max = { pts[0].x, pts[0].y };
+ rs.path.cmds[rs.path.cmdCnt++] = PathCommand::LineTo;
+ rs.path.pts[rs.path.ptsCnt++] = {x, y};
- for (uint32_t i = 1; i < ptsCnt; ++i) {
- if (pts[i].x < min.x) min.x = pts[i].x;
- if (pts[i].y < min.y) min.y = pts[i].y;
- if (pts[i].x > max.x) max.x = pts[i].x;
- if (pts[i].y > max.y) max.y = pts[i].y;
- }
-
- if (x) *x = min.x;
- if (y) *y = min.y;
- if (w) *w = max.x - min.x;
- if (h) *h = max.y - min.y;
-
- return true;
+ flag |= RenderUpdateFlag::Path;
}
-};
-
-struct Shape::Impl
-{
- ShapePath path;
- Fill *fill = nullptr;
- ShapeStroke *stroke = nullptr;
- uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
- FillRule rule = FillRule::Winding;
- RenderData rdata = nullptr; //engine data
- Shape *shape = nullptr;
- uint32_t flag = RenderUpdateFlag::None;
-
- Impl(Shape* s) : shape(s)
- {
- }
-
- ~Impl()
- {
- if (fill) delete(fill);
- if (stroke) {
- stroke->clear();
- free (stroke);
- }
- }
-
- bool dispose(RenderMethod& renderer)
+ void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y)
{
- auto ret = renderer.dispose(rdata);
- rdata = nullptr;
- return ret;
- }
+ if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2);
+ if (rs.path.ptsCnt + 3 > rs.path.reservedPtsCnt) reservePts((rs.path.ptsCnt + 3) * 2);
- bool render(RenderMethod& renderer)
- {
- return renderer.renderShape(rdata);
- }
+ rs.path.cmds[rs.path.cmdCnt++] = PathCommand::CubicTo;
+ rs.path.pts[rs.path.ptsCnt++] = {cx1, cy1};
+ rs.path.pts[rs.path.ptsCnt++] = {cx2, cy2};
+ rs.path.pts[rs.path.ptsCnt++] = {x, y};
- void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
- {
- this->rdata = renderer.prepare(*shape, this->rdata, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
- flag = RenderUpdateFlag::None;
- return this->rdata;
+ flag |= RenderUpdateFlag::Path;
}
- RenderRegion bounds(RenderMethod& renderer)
+ void close()
{
- return renderer.region(rdata);
- }
+ if (rs.path.cmdCnt > 0 && rs.path.cmds[rs.path.cmdCnt - 1] == PathCommand::Close) return;
- bool bounds(float* x, float* y, float* w, float* h)
- {
- auto ret = path.bounds(x, y, w, h);
+ if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2);
+ rs.path.cmds[rs.path.cmdCnt++] = PathCommand::Close;
- //Stroke feathering
- if (stroke) {
- if (x) *x -= stroke->width * 0.5f;
- if (y) *y -= stroke->width * 0.5f;
- if (w) *w += stroke->width;
- if (h) *h += stroke->width;
- }
- return ret;
+ flag |= RenderUpdateFlag::Path;
}
bool strokeWidth(float width)
{
//TODO: Size Exception?
- if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
- stroke->width = width;
+ if (!rs.stroke) rs.stroke = new RenderStroke();
+ rs.stroke->width = width;
flag |= RenderUpdateFlag::Stroke;
return true;
@@ -273,8 +186,8 @@ struct Shape::Impl
bool strokeCap(StrokeCap cap)
{
- if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
- stroke->cap = cap;
+ if (!rs.stroke) rs.stroke = new RenderStroke();
+ rs.stroke->cap = cap;
flag |= RenderUpdateFlag::Stroke;
return true;
@@ -282,8 +195,8 @@ struct Shape::Impl
bool strokeJoin(StrokeJoin join)
{
- if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
- stroke->join = join;
+ if (!rs.stroke) rs.stroke = new RenderStroke();
+ rs.stroke->join = join;
flag |= RenderUpdateFlag::Stroke;
return true;
@@ -291,17 +204,17 @@ struct Shape::Impl
bool strokeColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
- if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
- if (stroke->fill) {
- delete(stroke->fill);
- stroke->fill = nullptr;
+ if (!rs.stroke) rs.stroke = new RenderStroke();
+ if (rs.stroke->fill) {
+ delete(rs.stroke->fill);
+ rs.stroke->fill = nullptr;
flag |= RenderUpdateFlag::GradientStroke;
}
- stroke->color[0] = r;
- stroke->color[1] = g;
- stroke->color[2] = b;
- stroke->color[3] = a;
+ rs.stroke->color[0] = r;
+ rs.stroke->color[1] = g;
+ rs.stroke->color[2] = b;
+ rs.stroke->color[3] = a;
flag |= RenderUpdateFlag::Stroke;
@@ -313,9 +226,9 @@ struct Shape::Impl
auto p = f.release();
if (!p) return Result::MemoryCorruption;
- if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
- if (stroke->fill && stroke->fill != p) delete(stroke->fill);
- stroke->fill = p;
+ if (!rs.stroke) rs.stroke = new RenderStroke();
+ if (rs.stroke->fill && rs.stroke->fill != p) delete(rs.stroke->fill);
+ rs.stroke->fill = p;
flag |= RenderUpdateFlag::Stroke;
flag |= RenderUpdateFlag::GradientStroke;
@@ -327,23 +240,32 @@ struct Shape::Impl
{
//Reset dash
if (!pattern && cnt == 0) {
- free(stroke->dashPattern);
- stroke->dashPattern = nullptr;
+ free(rs.stroke->dashPattern);
+ rs.stroke->dashPattern = nullptr;
} else {
- if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
- if (stroke->dashCnt != cnt) {
- free(stroke->dashPattern);
- stroke->dashPattern = nullptr;
+ if (!rs.stroke) rs.stroke = new RenderStroke();
+ if (rs.stroke->dashCnt != cnt) {
+ free(rs.stroke->dashPattern);
+ rs.stroke->dashPattern = nullptr;
}
- if (!stroke->dashPattern) {
- stroke->dashPattern = static_cast<float*>(malloc(sizeof(float) * cnt));
- if (!stroke->dashPattern) return false;
+ if (!rs.stroke->dashPattern) {
+ rs.stroke->dashPattern = static_cast<float*>(malloc(sizeof(float) * cnt));
+ if (!rs.stroke->dashPattern) return false;
}
for (uint32_t i = 0; i < cnt; ++i) {
- stroke->dashPattern[i] = pattern[i];
+ rs.stroke->dashPattern[i] = pattern[i];
}
}
- stroke->dashCnt = cnt;
+ rs.stroke->dashCnt = cnt;
+ flag |= RenderUpdateFlag::Stroke;
+
+ return true;
+ }
+
+ bool strokeFirst(bool strokeFirst)
+ {
+ if (!rs.stroke) rs.stroke = new RenderStroke();
+ rs.stroke->strokeFirst = strokeFirst;
flag |= RenderUpdateFlag::Stroke;
return true;
@@ -354,29 +276,53 @@ struct Shape::Impl
auto ret = Shape::gen();
auto dup = ret.get()->pImpl;
- dup->rule = rule;
+ dup->rs.rule = rs.rule;
//Color
- memcpy(dup->color, color, sizeof(color));
+ memcpy(dup->rs.color, rs.color, sizeof(rs.color));
dup->flag = RenderUpdateFlag::Color;
//Path
- dup->path.duplicate(&path);
+ if (rs.path.cmdCnt > 0 && rs.path.ptsCnt > 0) {
+ dup->rs.path.cmdCnt = rs.path.cmdCnt;
+ dup->rs.path.reservedCmdCnt = rs.path.reservedCmdCnt;
+ dup->rs.path.ptsCnt = rs.path.ptsCnt;
+ dup->rs.path.reservedPtsCnt = rs.path.reservedPtsCnt;
+
+ dup->rs.path.cmds = static_cast<PathCommand*>(malloc(sizeof(PathCommand) * dup->rs.path.reservedCmdCnt));
+ if (dup->rs.path.cmds) memcpy(dup->rs.path.cmds, rs.path.cmds, sizeof(PathCommand) * dup->rs.path.cmdCnt);
+
+ dup->rs.path.pts = static_cast<Point*>(malloc(sizeof(Point) * dup->rs.path.reservedPtsCnt));
+ if (dup->rs.path.pts) memcpy(dup->rs.path.pts, rs.path.pts, sizeof(Point) * dup->rs.path.ptsCnt);
+ }
dup->flag |= RenderUpdateFlag::Path;
//Stroke
- if (stroke) {
- dup->stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
- dup->stroke->copy(stroke);
+ if (rs.stroke) {
+ dup->rs.stroke = new RenderStroke();
+ dup->rs.stroke->width = rs.stroke->width;
+ dup->rs.stroke->dashCnt = rs.stroke->dashCnt;
+ dup->rs.stroke->cap = rs.stroke->cap;
+ dup->rs.stroke->join = rs.stroke->join;
+ dup->rs.stroke->strokeFirst = rs.stroke->strokeFirst;
+ memcpy(dup->rs.stroke->color, rs.stroke->color, sizeof(rs.stroke->color));
+
+ if (rs.stroke->dashCnt > 0) {
+ dup->rs.stroke->dashPattern = static_cast<float*>(malloc(sizeof(float) * rs.stroke->dashCnt));
+ memcpy(dup->rs.stroke->dashPattern, rs.stroke->dashPattern, sizeof(float) * rs.stroke->dashCnt);
+ }
+
dup->flag |= RenderUpdateFlag::Stroke;
- if (stroke->fill)
+ if (rs.stroke->fill) {
+ dup->rs.stroke->fill = rs.stroke->fill->duplicate();
dup->flag |= RenderUpdateFlag::GradientStroke;
+ }
}
//Fill
- if (fill) {
- dup->fill = fill->duplicate();
+ if (rs.fill) {
+ dup->rs.fill = rs.fill->duplicate();
dup->flag |= RenderUpdateFlag::Gradient;
}
diff --git a/thirdparty/thorvg/src/lib/tvgSwCanvas.cpp b/thirdparty/thorvg/src/lib/tvgSwCanvas.cpp
index b5cae424f7..626bd51a2e 100644
--- a/thirdparty/thorvg/src/lib/tvgSwCanvas.cpp
+++ b/thirdparty/thorvg/src/lib/tvgSwCanvas.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgCanvasImpl.h"
#ifdef THORVG_SW_RASTER_SUPPORT
@@ -84,7 +85,7 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
auto renderer = static_cast<SwRenderer*>(Canvas::pImpl->renderer);
if (!renderer) return Result::MemoryCorruption;
- if (!renderer->target(buffer, stride, w, h, cs)) return Result::InvalidArguments;
+ if (!renderer->target(buffer, stride, w, h, static_cast<ColorSpace>(cs))) return Result::InvalidArguments;
//Paints must be updated again with this new target.
Canvas::pImpl->needRefresh();
diff --git a/thirdparty/thorvg/src/lib/tvgTaskScheduler.cpp b/thirdparty/thorvg/src/lib/tvgTaskScheduler.cpp
index 8c07dc3859..019468083d 100644
--- a/thirdparty/thorvg/src/lib/tvgTaskScheduler.cpp
+++ b/thirdparty/thorvg/src/lib/tvgTaskScheduler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include <deque>
#include <thread>
#include <vector>
@@ -99,13 +100,12 @@ struct TaskQueue {
};
-class TaskSchedulerImpl
+struct TaskSchedulerImpl
{
-public:
- unsigned threadCnt;
+ uint32_t threadCnt;
vector<thread> threads;
vector<TaskQueue> taskQueues;
- atomic<unsigned> idx{0};
+ atomic<uint32_t> idx{0};
TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt)
{
@@ -135,7 +135,7 @@ public:
}
if (!success && !taskQueues[i].pop(&task)) break;
- (*task)(i);
+ (*task)(i + 1);
}
}
diff --git a/thirdparty/thorvg/src/lib/tvgTaskScheduler.h b/thirdparty/thorvg/src/lib/tvgTaskScheduler.h
index 163e387f29..ce2016f561 100644
--- a/thirdparty/thorvg/src/lib/tvgTaskScheduler.h
+++ b/thirdparty/thorvg/src/lib/tvgTaskScheduler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_TASK_SCHEDULER_H_
#define _TVG_TASK_SCHEDULER_H_
@@ -44,8 +45,8 @@ struct Task
private:
mutex mtx;
condition_variable cv;
- bool ready{true};
- bool pending{false};
+ bool ready = true;
+ bool pending = false;
public:
virtual ~Task() = default;
@@ -78,11 +79,9 @@ private:
pending = true;
}
- friend class TaskSchedulerImpl;
+ friend struct TaskSchedulerImpl;
};
-
-
}
#endif //_TVG_TASK_SCHEDULER_H_
diff --git a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
index 1fb0681814..b0a9fdd579 100644
--- a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,42 +23,14 @@
#include "tvgLoader.h"
#include "tvgPngLoader.h"
-static inline uint32_t PREMULTIPLY(uint32_t c)
-{
- auto a = (c >> 24);
- return (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff);
-}
+/************************************************************************/
+/* Internal Class Implementation */
+/************************************************************************/
-static void _premultiply(uint32_t* data, uint32_t w, uint32_t h)
-{
- auto buffer = data;
- for (uint32_t y = 0; y < h; ++y, buffer += w) {
- auto src = buffer;
- for (uint32_t x = 0; x < w; ++x, ++src) {
- *src = PREMULTIPLY(*src);
- }
- }
-}
-
-
-static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
-{
- return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
-}
-
-
-static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
-{
- auto buffer = data;
- for (uint32_t y = 0; y < h; ++y, buffer += w) {
- auto src = buffer;
- for (uint32_t x = 0; x < w; ++x, ++src) {
- *src = CHANGE_COLORSPACE(*src);
- }
- }
-}
-
+/************************************************************************/
+/* External Class Implementation */
+/************************************************************************/
PngLoader::PngLoader()
{
@@ -84,6 +56,7 @@ bool PngLoader::open(const string& path)
w = (float)image->width;
h = (float)image->height;
+ cs = ColorSpace::ARGB8888;
return true;
}
@@ -96,6 +69,7 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
w = (float)image->width;
h = (float)image->height;
+ cs = ColorSpace::ARGB8888;
return true;
}
@@ -117,8 +91,6 @@ bool PngLoader::read()
}
content = reinterpret_cast<uint32_t*>(buffer);
- _premultiply(reinterpret_cast<uint32_t*>(buffer), image->width, image->height);
-
return true;
}
@@ -128,20 +100,20 @@ bool PngLoader::close()
return true;
}
-unique_ptr<Surface> PngLoader::bitmap(uint32_t colorSpace)
+unique_ptr<Surface> PngLoader::bitmap()
{
if (!content) return nullptr;
- if (this->colorSpace != colorSpace) {
- this->colorSpace = colorSpace;
- _changeColorSpace(content, w, h);
- }
- auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
- surface->buffer = content;
+ //TODO: It's better to keep this surface instance in the loader side
+ auto surface = new Surface;
+ surface->buf32 = content;
surface->stride = w;
surface->w = w;
surface->h = h;
- surface->cs = colorSpace;
+ surface->cs = cs;
+ surface->channelSize = sizeof(uint32_t);
+ surface->owner = true;
+ surface->premultiplied = false;
return unique_ptr<Surface>(surface);
}
diff --git a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h
index f8c0daa61c..5354e1bdd6 100644
--- a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h
+++ b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_PNG_LOADER_H_
#define _TVG_PNG_LOADER_H_
@@ -36,7 +37,7 @@ public:
bool read() override;
bool close() override;
- unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
+ unique_ptr<Surface> bitmap() override;
private:
png_imagep image = nullptr;
diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp
index f64b7110fe..6edda86cc1 100644
--- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,24 +28,6 @@
/* Internal Class Implementation */
/************************************************************************/
-static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
-{
- return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
-}
-
-
-static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
-{
- auto buffer = data;
- for (uint32_t y = 0; y < h; ++y, buffer += w) {
- auto src = buffer;
- for (uint32_t x = 0; x < w; ++x, ++src) {
- *src = CHANGE_COLORSPACE(*src);
- }
- }
-}
-
-
void JpgLoader::clear()
{
jpgdDelete(decoder);
@@ -79,6 +61,7 @@ bool JpgLoader::open(const string& path)
w = static_cast<float>(width);
h = static_cast<float>(height);
+ cs = ColorSpace::ARGB8888;
return true;
}
@@ -104,6 +87,7 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy)
w = static_cast<float>(width);
h = static_cast<float>(height);
+ cs = ColorSpace::ARGB8888;
return true;
}
@@ -128,22 +112,22 @@ bool JpgLoader::close()
}
-unique_ptr<Surface> JpgLoader::bitmap(uint32_t colorSpace)
+unique_ptr<Surface> JpgLoader::bitmap()
{
this->done();
if (!image) return nullptr;
- if (this->colorSpace != colorSpace) {
- this->colorSpace = colorSpace;
- _changeColorSpace(reinterpret_cast<uint32_t*>(image), w, h);
- }
- auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
- surface->buffer = reinterpret_cast<uint32_t*>(image);
+ //TODO: It's better to keep this surface instance in the loader side
+ auto surface = new Surface;
+ surface->buf8 = image;
surface->stride = static_cast<uint32_t>(w);
surface->w = static_cast<uint32_t>(w);
surface->h = static_cast<uint32_t>(h);
- surface->cs = colorSpace;
+ surface->cs = cs;
+ surface->channelSize = sizeof(uint32_t);
+ surface->premultiplied = true;
+ surface->owner = true;
return unique_ptr<Surface>(surface);
}
diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h
index c47cb6704f..6d2febe94f 100644
--- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h
+++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_JPG_LOADER_H_
#define _TVG_JPG_LOADER_H_
@@ -44,7 +45,7 @@ public:
bool read() override;
bool close() override;
- unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
+ unique_ptr<Surface> bitmap() override;
void run(unsigned tid) override;
};
diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
index 56b40acf0b..6ea2efb054 100644
--- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
+++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -80,7 +80,7 @@ enum jpgd_status
enum
{
JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4,
- JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384
+ JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384
};
// Input stream interface.
@@ -151,7 +151,7 @@ public:
// If JPGD_SUCCESS is returned you may then call decode() on each scanline.
int begin_decoding();
// Returns the next scan line.
- // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1).
+ // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1).
// Otherwise, it will always point to a buffer containing 32-bit RGBA pixels (A will always be 255, and get_bytes_per_pixel() will return 4).
// Returns JPGD_SUCCESS if a scan line has been returned.
// Returns JPGD_DONE if all scan lines have been returned.
@@ -1246,7 +1246,7 @@ void jpeg_decoder::read_sof_marker()
uint32_t num_left = get_bits(16);
if (get_bits(8) != 8) stop_decoding(JPGD_BAD_PRECISION); /* precision: sorry, only 8-bit precision is supported right now */
-
+
m_image_y_size = get_bits(16);
if ((m_image_y_size < 1) || (m_image_y_size > JPGD_MAX_HEIGHT)) stop_decoding(JPGD_BAD_HEIGHT);
@@ -1326,7 +1326,7 @@ void jpeg_decoder::read_sos_marker()
}
num_left -= 3;
- while (num_left) { /* read past whatever is num_left */
+ while (num_left) { /* read past whatever is num_left */
get_bits(8);
num_left--;
}
@@ -1411,7 +1411,7 @@ int jpeg_decoder::process_markers()
stop_decoding(JPGD_UNEXPECTED_MARKER);
break;
}
- default: { /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
+ default: { /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
skip_variable_marker();
break;
}
@@ -1441,7 +1441,7 @@ void jpeg_decoder::locate_soi_marker()
if (lastchar == 0xFF) {
if (thischar == M_SOI) break;
- else if (thischar == M_EOI) stop_decoding(JPGD_NOT_JPEG); // get_bits will keep returning M_EOI if we read past the end
+ else if (thischar == M_EOI) stop_decoding(JPGD_NOT_JPEG); // get_bits will keep returning M_EOI if we read past the end
}
}
@@ -1460,7 +1460,7 @@ void jpeg_decoder::locate_sof_marker()
switch (c) {
case M_SOF2: m_progressive_flag = true;
case M_SOF0: /* baseline DCT */
- case M_SOF1: { /* extended sequential DCT */
+ case M_SOF1: { /* extended sequential DCT */
read_sof_marker();
break;
}
@@ -1671,7 +1671,7 @@ void jpeg_decoder::transform_mcu_expand(int mcu_row)
JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] >= 1);
JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] <= 64);
- int max_zag = m_mcu_block_max_zag[mcu_block++] - 1;
+ int max_zag = m_mcu_block_max_zag[mcu_block++] - 1;
if (max_zag <= 0) max_zag = 0; // should never happen, only here to shut up static analysis
switch (s_max_rc[max_zag]) {
@@ -1789,7 +1789,7 @@ void jpeg_decoder::load_next_row()
p[0] = pDC[0];
memcpy(&p[1], &pAC[1], 63 * sizeof(jpgd_block_t));
- for (i = 63; i > 0; i--) {
+ for (i = 63; i > 0; i--) {
if (p[g_ZAG[i]]) break;
}
@@ -1809,7 +1809,7 @@ void jpeg_decoder::load_next_row()
if (++block_y_mcu_ofs == m_comp_v_samp[component_id]) {
block_y_mcu_ofs = 0;
block_x_mcu[component_id] += m_comp_h_samp[component_id];
- }
+ }
}
}
if (m_freq_domain_chroma_upsample) transform_mcu_expand(mcu_row);
@@ -1865,7 +1865,7 @@ void jpeg_decoder::process_restart()
static inline int dequantize_ac(int c, int q)
-{
+{
c *= q;
return c;
}
@@ -1910,7 +1910,7 @@ void jpeg_decoder::decode_next_row()
while (n--) p[g_ZAG[kt++]] = 0;
}
k += r;
- }
+ }
s = JPGD_HUFF_EXTEND(extra_bits, s);
JPGD_ASSERT(k < 64);
p[g_ZAG[k]] = static_cast<jpgd_block_t>(dequantize_ac(s, q[k])); //s * q[k];
@@ -2204,7 +2204,7 @@ int jpeg_decoder::decode(const void** pScan_line, uint32_t* pScan_line_len)
}
else *pScan_line = m_pScan_line_1;
break;
- }
+ }
case JPGD_YH2V1: {
H2V1Convert();
*pScan_line = m_pScan_line_0;
@@ -2609,11 +2609,11 @@ void jpeg_decoder::decode_block_ac_refine(jpeg_decoder *pD, int component_id, in
int p1 = 1 << pD->m_successive_low;
int m1 = static_cast<unsigned int>(-1) << pD->m_successive_low;
jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
-
+
JPGD_ASSERT(pD->m_spectral_end <= 63);
-
+
k = pD->m_spectral_start;
-
+
if (pD->m_eob_run == 0) {
for ( ; k <= pD->m_spectral_end; k++) {
s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]);
diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.h b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.h
index ca9cb35c32..030fdc2946 100644
--- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.h
+++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp
index 19c1dd6668..5f5e72b0dd 100644
--- a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include <fstream>
#include <string.h>
#include "tvgLoader.h"
@@ -28,22 +29,6 @@
/* Internal Class Implementation */
/************************************************************************/
-static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
-{
- return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
-}
-
-
-static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
-{
- auto buffer = data;
- for (uint32_t y = 0; y < h; ++y, buffer += w) {
- auto src = buffer;
- for (uint32_t x = 0; x < w; ++x, ++src) {
- *src = CHANGE_COLORSPACE(*src);
- }
- }
-}
/************************************************************************/
/* External Class Implementation */
@@ -73,6 +58,8 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
}
else content = const_cast<uint32_t*>(data);
+ cs = ColorSpace::ARGB8888;
+
return true;
}
@@ -89,20 +76,20 @@ bool RawLoader::close()
}
-unique_ptr<Surface> RawLoader::bitmap(uint32_t colorSpace)
+unique_ptr<Surface> RawLoader::bitmap()
{
if (!content) return nullptr;
- if (this->colorSpace != colorSpace) {
- this->colorSpace = colorSpace;
- _changeColorSpace(content, w, h);
- }
- auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
- surface->buffer = content;
+ //TODO: It's better to keep this surface instance in the loader side
+ auto surface = new Surface;
+ surface->buf32 = content;
surface->stride = static_cast<uint32_t>(w);
surface->w = static_cast<uint32_t>(w);
surface->h = static_cast<uint32_t>(h);
- surface->cs = colorSpace;
+ surface->cs = cs;
+ surface->channelSize = sizeof(uint32_t);
+ surface->premultiplied = true;
+ surface->owner = true;
return unique_ptr<Surface>(surface);
}
diff --git a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h
index 8789b0cf51..69f9bdc47a 100644
--- a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h
+++ b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_RAW_LOADER_H_
#define _TVG_RAW_LOADER_H_
@@ -35,7 +36,7 @@ public:
bool read() override;
bool close() override;
- unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
+ unique_ptr<Surface> bitmap() override;
};
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp
index 478ba5d3d1..694e6d1ebf 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2022 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,13 +32,13 @@ static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
{
if (from == nullptr) return;
//Copy the properties of 'from' only if they were explicitly set (not the default ones).
- if (from->curColorSet && !((int)to->flags & (int)SvgStyleFlags::Color)) {
+ if (from->curColorSet && !(to->flags & SvgStyleFlags::Color)) {
to->color = from->color;
to->curColorSet = true;
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Color);
+ to->flags = (to->flags | SvgStyleFlags::Color);
}
//Fill
- if (((int)from->fill.flags & (int)SvgFillFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Fill)) {
+ if ((from->fill.flags & SvgFillFlags::Paint) && !(to->flags & SvgStyleFlags::Fill)) {
to->fill.paint.color = from->fill.paint.color;
to->fill.paint.none = from->fill.paint.none;
to->fill.paint.curColor = from->fill.paint.curColor;
@@ -46,21 +46,21 @@ static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
if (to->fill.paint.url) free(to->fill.paint.url);
to->fill.paint.url = strdup(from->fill.paint.url);
}
- to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Paint);
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Fill);
+ to->fill.flags = (to->fill.flags | SvgFillFlags::Paint);
+ to->flags = (to->flags | SvgStyleFlags::Fill);
}
- if (((int)from->fill.flags & (int)SvgFillFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::FillOpacity)) {
+ if ((from->fill.flags & SvgFillFlags::Opacity) && !(to->flags & SvgStyleFlags::FillOpacity)) {
to->fill.opacity = from->fill.opacity;
- to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Opacity);
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillOpacity);
+ to->fill.flags = (to->fill.flags | SvgFillFlags::Opacity);
+ to->flags = (to->flags | SvgStyleFlags::FillOpacity);
}
- if (((int)from->fill.flags & (int)SvgFillFlags::FillRule) && !((int)to->flags & (int)SvgStyleFlags::FillRule)) {
+ if ((from->fill.flags & SvgFillFlags::FillRule) && !(to->flags & SvgStyleFlags::FillRule)) {
to->fill.fillRule = from->fill.fillRule;
- to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::FillRule);
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillRule);
+ to->fill.flags = (to->fill.flags | SvgFillFlags::FillRule);
+ to->flags = (to->flags | SvgStyleFlags::FillRule);
}
//Stroke
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Stroke)) {
+ if ((from->stroke.flags & SvgStrokeFlags::Paint) && !(to->flags & SvgStyleFlags::Stroke)) {
to->stroke.paint.color = from->stroke.paint.color;
to->stroke.paint.none = from->stroke.paint.none;
to->stroke.paint.curColor = from->stroke.paint.curColor;
@@ -68,45 +68,45 @@ static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
if (to->stroke.paint.url) free(to->stroke.paint.url);
to->stroke.paint.url = strdup(from->stroke.paint.url);
}
- to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Paint);
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Stroke);
+ to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Paint);
+ to->flags = (to->flags | SvgStyleFlags::Stroke);
}
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::StrokeOpacity)) {
+ if ((from->stroke.flags & SvgStrokeFlags::Opacity) && !(to->flags & SvgStyleFlags::StrokeOpacity)) {
to->stroke.opacity = from->stroke.opacity;
- to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Opacity);
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeOpacity);
+ to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Opacity);
+ to->flags = (to->flags | SvgStyleFlags::StrokeOpacity);
}
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Width) && !((int)to->flags & (int)SvgStyleFlags::StrokeWidth)) {
+ if ((from->stroke.flags & SvgStrokeFlags::Width) && !(to->flags & SvgStyleFlags::StrokeWidth)) {
to->stroke.width = from->stroke.width;
- to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Width);
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeWidth);
+ to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Width);
+ to->flags = (to->flags | SvgStyleFlags::StrokeWidth);
}
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Dash) && !((int)to->flags & (int)SvgStyleFlags::StrokeDashArray)) {
+ if ((from->stroke.flags & SvgStrokeFlags::Dash) && !(to->flags & SvgStyleFlags::StrokeDashArray)) {
if (from->stroke.dash.array.count > 0) {
to->stroke.dash.array.clear();
to->stroke.dash.array.reserve(from->stroke.dash.array.count);
for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) {
to->stroke.dash.array.push(from->stroke.dash.array.data[i]);
}
- to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Dash);
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeDashArray);
+ to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Dash);
+ to->flags = (to->flags | SvgStyleFlags::StrokeDashArray);
}
}
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Cap) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineCap)) {
+ if ((from->stroke.flags & SvgStrokeFlags::Cap) && !(to->flags & SvgStyleFlags::StrokeLineCap)) {
to->stroke.cap = from->stroke.cap;
- to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Cap);
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineCap);
+ to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Cap);
+ to->flags = (to->flags | SvgStyleFlags::StrokeLineCap);
}
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Join) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineJoin)) {
+ if ((from->stroke.flags & SvgStrokeFlags::Join) && !(to->flags & SvgStyleFlags::StrokeLineJoin)) {
to->stroke.join = from->stroke.join;
- to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Join);
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineJoin);
+ to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Join);
+ to->flags = (to->flags | SvgStyleFlags::StrokeLineJoin);
}
//Opacity
//TODO: it can be set to be 255 and shouldn't be changed by attribute 'opacity'
- if (from->opacity < 255 && !((int)to->flags & (int)SvgStyleFlags::Opacity)) {
+ if (from->opacity < 255 && !(to->flags & SvgStyleFlags::Opacity)) {
to->opacity = from->opacity;
- to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Opacity);
+ to->flags = (to->flags | SvgStyleFlags::Opacity);
}
}
@@ -118,11 +118,11 @@ static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
void cssCopyStyleAttr(SvgNode* to, const SvgNode* from)
{
//Copy matrix attribute
- if (from->transform && !((int)to->style->flags & (int)SvgStyleFlags::Transform)) {
+ if (from->transform && !(to->style->flags & SvgStyleFlags::Transform)) {
to->transform = (Matrix*)malloc(sizeof(Matrix));
if (to->transform) {
*to->transform = *from->transform;
- to->style->flags = (SvgStyleFlags)((int)to->style->flags | (int)SvgStyleFlags::Transform);
+ to->style->flags = (to->style->flags | SvgStyleFlags::Transform);
}
}
//Copy style attribute
@@ -155,12 +155,12 @@ SvgNode* cssFindStyleNode(const SvgNode* style, const char* title, SvgNodeType t
SvgNode* cssFindStyleNode(const SvgNode* style, const char* title)
{
- if (!style) return nullptr;
+ if (!style || !title) return nullptr;
auto child = style->child.data;
for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
if ((*child)->type == SvgNodeType::CssStyle) {
- if ((title && (*child)->id && !strcmp((*child)->id, title))) return (*child);
+ if ((*child)->id && !strcmp((*child)->id, title)) return (*child);
}
}
return nullptr;
@@ -175,9 +175,6 @@ void cssUpdateStyle(SvgNode* doc, SvgNode* style)
if (auto cssNode = cssFindStyleNode(style, nullptr, (*child)->type)) {
cssCopyStyleAttr(*child, cssNode);
}
- if (auto cssNode = cssFindStyleNode(style, nullptr)) {
- cssCopyStyleAttr(*child, cssNode);
- }
cssUpdateStyle(*child, style);
}
}
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h
index 66477c1a32..228c5996da 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2022 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
index bc350a0eb8..f9f08cdb81 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -137,11 +137,11 @@ static constexpr struct
};
-static bool _parseAspectRatio(const char** content, AspectRatioAlign* align, AspectRatioMeetOrSlice* meetOrSlice)
+static void _parseAspectRatio(const char** content, AspectRatioAlign* align, AspectRatioMeetOrSlice* meetOrSlice)
{
if (!strcmp(*content, "none")) {
*align = AspectRatioAlign::None;
- return true;
+ return;
}
for (unsigned int i = 0; i < sizeof(alignTags) / sizeof(alignTags[0]); i++) {
@@ -158,8 +158,6 @@ static bool _parseAspectRatio(const char** content, AspectRatioAlign* align, Asp
} else if (!strcmp(*content, "slice")) {
*meetOrSlice = AspectRatioMeetOrSlice::Slice;
}
-
- return true;
}
@@ -254,6 +252,36 @@ static SvgMaskType _toMaskType(const char* str)
}
+//The default rendering order: fill, stroke, markers
+//If any is omitted, will be rendered in its default order after the specified ones.
+static bool _toPaintOrder(const char* str)
+{
+ uint8_t position = 1;
+ uint8_t strokePosition = 0;
+ uint8_t fillPosition = 0;
+
+ while (*str != '\0') {
+ str = _skipSpace(str, nullptr);
+ if (!strncmp(str, "fill", 4)) {
+ fillPosition = position++;
+ str += 4;
+ } else if (!strncmp(str, "stroke", 6)) {
+ strokePosition = position++;
+ str += 6;
+ } else if (!strncmp(str, "markers", 7)) {
+ str += 7;
+ } else {
+ return _toPaintOrder("fill stroke");
+ }
+ }
+
+ if (fillPosition == 0) fillPosition = position++;
+ if (strokePosition == 0) strokePosition = position++;
+
+ return fillPosition < strokePosition;
+}
+
+
#define _PARSE_TAG(Type, Name, Name1, Tags_Array, Default) \
static Type _to##Name1(const char* str) \
{ \
@@ -833,20 +861,40 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value)
if (!strcmp(key, "width")) {
doc->w = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal);
+ if (strstr(value, "%") && !(doc->viewFlag & SvgViewFlag::Viewbox)) {
+ doc->viewFlag = (doc->viewFlag | SvgViewFlag::WidthInPercent);
+ } else {
+ doc->viewFlag = (doc->viewFlag | SvgViewFlag::Width);
+ }
} else if (!strcmp(key, "height")) {
doc->h = _toFloat(loader->svgParse, value, SvgParserLengthType::Vertical);
+ if (strstr(value, "%") && !(doc->viewFlag & SvgViewFlag::Viewbox)) {
+ doc->viewFlag = (doc->viewFlag | SvgViewFlag::HeightInPercent);
+ } else {
+ doc->viewFlag = (doc->viewFlag | SvgViewFlag::Height);
+ }
} else if (!strcmp(key, "viewBox")) {
if (_parseNumber(&value, &doc->vx)) {
if (_parseNumber(&value, &doc->vy)) {
if (_parseNumber(&value, &doc->vw)) {
- _parseNumber(&value, &doc->vh);
- loader->svgParse->global.h = doc->vh;
+ if (_parseNumber(&value, &doc->vh)) {
+ doc->viewFlag = (doc->viewFlag | SvgViewFlag::Viewbox);
+ loader->svgParse->global.h = doc->vh;
+ }
+ loader->svgParse->global.w = doc->vw;
}
- loader->svgParse->global.w = doc->vw;
+ loader->svgParse->global.y = doc->vy;
}
- loader->svgParse->global.y = doc->vy;
+ loader->svgParse->global.x = doc->vx;
+ }
+ if ((doc->viewFlag & SvgViewFlag::Viewbox) && (doc->vw < 0.0f || doc->vh < 0.0f)) {
+ doc->viewFlag = (SvgViewFlag)((uint32_t)doc->viewFlag & ~(uint32_t)SvgViewFlag::Viewbox);
+ TVGLOG("SVG", "Negative values of the <viewBox> width and/or height - the attribute invalidated.");
+ }
+ if (!(doc->viewFlag & SvgViewFlag::Viewbox)) {
+ loader->svgParse->global.x = loader->svgParse->global.y = 0.0f;
+ loader->svgParse->global.w = loader->svgParse->global.h = 1.0f;
}
- loader->svgParse->global.x = doc->vx;
} else if (!strcmp(key, "preserveAspectRatio")) {
_parseAspectRatio(&value, &doc->align, &doc->meetOrSlice);
} else if (!strcmp(key, "style")) {
@@ -890,7 +938,7 @@ static void _handleColorAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, co
static void _handleFillAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
{
SvgStyleProperty* style = node->style;
- style->fill.flags = (SvgFillFlags)((int)style->fill.flags | (int)SvgFillFlags::Paint);
+ style->fill.flags = (style->fill.flags | SvgFillFlags::Paint);
_handlePaintAttr(&style->fill.paint, value);
}
@@ -898,47 +946,47 @@ static void _handleFillAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, con
static void _handleStrokeAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
{
SvgStyleProperty* style = node->style;
- style->stroke.flags = (SvgStrokeFlags)((int)style->stroke.flags | (int)SvgStrokeFlags::Paint);
+ style->stroke.flags = (style->stroke.flags | SvgStrokeFlags::Paint);
_handlePaintAttr(&style->stroke.paint, value);
}
static void _handleStrokeOpacityAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
{
- node->style->stroke.flags = (SvgStrokeFlags)((int)node->style->stroke.flags | (int)SvgStrokeFlags::Opacity);
+ node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Opacity);
node->style->stroke.opacity = _toOpacity(value);
}
static void _handleStrokeDashArrayAttr(SvgLoaderData* loader, SvgNode* node, const char* value)
{
- node->style->stroke.flags = (SvgStrokeFlags)((int)node->style->stroke.flags | (int)SvgStrokeFlags::Dash);
+ node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Dash);
_parseDashArray(loader, value, &node->style->stroke.dash);
}
static void _handleStrokeWidthAttr(SvgLoaderData* loader, SvgNode* node, const char* value)
{
- node->style->stroke.flags = (SvgStrokeFlags)((int)node->style->stroke.flags | (int)SvgStrokeFlags::Width);
+ node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Width);
node->style->stroke.width = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal);
}
static void _handleStrokeLineCapAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
{
- node->style->stroke.flags = (SvgStrokeFlags)((int)node->style->stroke.flags | (int)SvgStrokeFlags::Cap);
+ node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Cap);
node->style->stroke.cap = _toLineCap(value);
}
static void _handleStrokeLineJoinAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
{
- node->style->stroke.flags = (SvgStrokeFlags)((int)node->style->stroke.flags | (int)SvgStrokeFlags::Join);
+ node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Join);
node->style->stroke.join = _toLineJoin(value);
}
static void _handleFillRuleAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
{
- node->style->fill.flags = (SvgFillFlags)((int)node->style->fill.flags | (int)SvgFillFlags::FillRule);
+ node->style->fill.flags = (node->style->fill.flags | SvgFillFlags::FillRule);
node->style->fill.fillRule = _toFillRule(value);
}
@@ -951,7 +999,7 @@ static void _handleOpacityAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node,
static void _handleFillOpacityAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
{
- node->style->fill.flags = (SvgFillFlags)((int)node->style->fill.flags | (int)SvgFillFlags::Opacity);
+ node->style->fill.flags = (node->style->fill.flags | SvgFillFlags::Opacity);
node->style->fill.opacity = _toOpacity(value);
}
@@ -1001,6 +1049,13 @@ static void _handleDisplayAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node,
}
+static void _handlePaintOrderAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
+{
+ node->style->flags = (node->style->flags | SvgStyleFlags::PaintOrder);
+ node->style->paintOrder = _toPaintOrder(value);
+}
+
+
static void _handleCssClassAttr(SvgLoaderData* loader, SvgNode* node, const char* value)
{
auto cssClass = &node->style->cssClass;
@@ -1051,7 +1106,8 @@ static constexpr struct
STYLE_DEF(clip-path, ClipPath, SvgStyleFlags::ClipPath),
STYLE_DEF(mask, Mask, SvgStyleFlags::Mask),
STYLE_DEF(mask-type, MaskType, SvgStyleFlags::MaskType),
- STYLE_DEF(display, Display, SvgStyleFlags::Display)
+ STYLE_DEF(display, Display, SvgStyleFlags::Display),
+ STYLE_DEF(paint-order, PaintOrder, SvgStyleFlags::PaintOrder)
};
@@ -1071,8 +1127,8 @@ static bool _parseStyleAttr(void* data, const char* key, const char* value, bool
if (styleTags[i].sz - 1 == sz && !strncmp(styleTags[i].tag, key, sz)) {
if (style) {
styleTags[i].tagHandler(loader, node, value);
- node->style->flags = (SvgStyleFlags)((int)node->style->flags | (int)styleTags[i].flag);
- } else if (!((int)node->style->flags & (int)styleTags[i].flag)) {
+ node->style->flags = (node->style->flags | styleTags[i].flag);
+ } else if (!(node->style->flags & styleTags[i].flag)) {
styleTags[i].tagHandler(loader, node, value);
}
return true;
@@ -1253,6 +1309,8 @@ static SvgNode* _createNode(SvgNode* parent, SvgNodeType type)
node->style->stroke.join = StrokeJoin::Miter;
node->style->stroke.scale = 1.0;
+ node->style->paintOrder = _toPaintOrder("fill stroke");
+
//Default display is true("inline").
node->display = true;
@@ -1291,22 +1349,22 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha
if (!loader->svgParse->node) return nullptr;
SvgDocNode* doc = &(loader->svgParse->node->node.doc);
- loader->svgParse->global.w = 0;
- loader->svgParse->global.h = 0;
+ loader->svgParse->global.w = 1.0f;
+ loader->svgParse->global.h = 1.0f;
doc->align = AspectRatioAlign::XMidYMid;
doc->meetOrSlice = AspectRatioMeetOrSlice::Meet;
+ doc->viewFlag = SvgViewFlag::None;
func(buf, bufLength, _attrParseSvgNode, loader);
- if (loader->svgParse->global.w == 0) {
- if (doc->w < FLT_EPSILON) loader->svgParse->global.w = 1;
- else loader->svgParse->global.w = doc->w;
- }
- if (loader->svgParse->global.h == 0) {
- if (doc->h < FLT_EPSILON) loader->svgParse->global.h = 1;
- else loader->svgParse->global.h = doc->h;
+ if (!(doc->viewFlag & SvgViewFlag::Viewbox)) {
+ if (doc->viewFlag & SvgViewFlag::Width) {
+ loader->svgParse->global.w = doc->w;
+ }
+ if (doc->viewFlag & SvgViewFlag::Height) {
+ loader->svgParse->global.h = doc->h;
+ }
}
-
return loader->svgParse->node;
}
@@ -1868,309 +1926,6 @@ static SvgNode* _findNodeById(SvgNode *node, const char* id)
}
-static void _cloneGradStops(Array<Fill::ColorStop>& dst, const Array<Fill::ColorStop>& src)
-{
- for (uint32_t i = 0; i < src.count; ++i) {
- dst.push(src.data[i]);
- }
-}
-
-
-static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from)
-{
- if (!from) return nullptr;
-
- auto grad = (SvgStyleGradient*)(calloc(1, sizeof(SvgStyleGradient)));
- if (!grad) return nullptr;
-
- grad->type = from->type;
- grad->id = from->id ? _copyId(from->id) : nullptr;
- grad->ref = from->ref ? _copyId(from->ref) : nullptr;
- grad->spread = from->spread;
- grad->userSpace = from->userSpace;
-
- if (from->transform) {
- grad->transform = (Matrix*)calloc(1, sizeof(Matrix));
- if (grad->transform) memcpy(grad->transform, from->transform, sizeof(Matrix));
- }
-
- if (grad->type == SvgGradientType::Linear) {
- grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient));
- if (!grad->linear) goto error_grad_alloc;
- memcpy(grad->linear, from->linear, sizeof(SvgLinearGradient));
- } else if (grad->type == SvgGradientType::Radial) {
- grad->radial = (SvgRadialGradient*)calloc(1, sizeof(SvgRadialGradient));
- if (!grad->radial) goto error_grad_alloc;
- memcpy(grad->radial, from->radial, sizeof(SvgRadialGradient));
- }
-
- _cloneGradStops(grad->stops, from->stops);
-
- return grad;
-
-error_grad_alloc:
- if (grad) {
- grad->clear();
- free(grad);
- }
- return nullptr;
-}
-
-
-static void _styleInherit(SvgStyleProperty* child, const SvgStyleProperty* parent)
-{
- if (parent == nullptr) return;
- //Inherit the property of parent if not present in child.
- if (!child->curColorSet) {
- child->color = parent->color;
- child->curColorSet = parent->curColorSet;
- }
- //Fill
- if (!((int)child->fill.flags & (int)SvgFillFlags::Paint)) {
- child->fill.paint.color = parent->fill.paint.color;
- child->fill.paint.none = parent->fill.paint.none;
- child->fill.paint.curColor = parent->fill.paint.curColor;
- if (parent->fill.paint.url) {
- if (child->fill.paint.url) free(child->fill.paint.url);
- child->fill.paint.url = _copyId(parent->fill.paint.url);
- }
- }
- if (!((int)child->fill.flags & (int)SvgFillFlags::Opacity)) {
- child->fill.opacity = parent->fill.opacity;
- }
- if (!((int)child->fill.flags & (int)SvgFillFlags::FillRule)) {
- child->fill.fillRule = parent->fill.fillRule;
- }
- //Stroke
- if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Paint)) {
- child->stroke.paint.color = parent->stroke.paint.color;
- child->stroke.paint.none = parent->stroke.paint.none;
- child->stroke.paint.curColor = parent->stroke.paint.curColor;
- if (parent->stroke.paint.url) {
- if (child->stroke.paint.url) free(child->stroke.paint.url);
- child->stroke.paint.url = _copyId(parent->stroke.paint.url);
- } else {
- child->stroke.paint.url = nullptr;
- }
- }
- if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Opacity)) {
- child->stroke.opacity = parent->stroke.opacity;
- }
- if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Width)) {
- child->stroke.width = parent->stroke.width;
- }
- if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Dash)) {
- if (parent->stroke.dash.array.count > 0) {
- child->stroke.dash.array.clear();
- child->stroke.dash.array.reserve(parent->stroke.dash.array.count);
- for (uint32_t i = 0; i < parent->stroke.dash.array.count; ++i) {
- child->stroke.dash.array.push(parent->stroke.dash.array.data[i]);
- }
- }
- }
- if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Cap)) {
- child->stroke.cap = parent->stroke.cap;
- }
- if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Join)) {
- child->stroke.join = parent->stroke.join;
- }
-}
-
-
-static void _styleCopy(SvgStyleProperty* to, const SvgStyleProperty* from)
-{
- if (from == nullptr) return;
- //Copy the properties of 'from' only if they were explicitly set (not the default ones).
- if (from->curColorSet) {
- to->color = from->color;
- to->curColorSet = true;
- }
- //Fill
- to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)from->fill.flags);
- if (((int)from->fill.flags & (int)SvgFillFlags::Paint)) {
- to->fill.paint.color = from->fill.paint.color;
- to->fill.paint.none = from->fill.paint.none;
- to->fill.paint.curColor = from->fill.paint.curColor;
- if (from->fill.paint.url) {
- if (to->fill.paint.url) free(to->fill.paint.url);
- to->fill.paint.url = _copyId(from->fill.paint.url);
- }
- }
- if (((int)from->fill.flags & (int)SvgFillFlags::Opacity)) {
- to->fill.opacity = from->fill.opacity;
- }
- if (((int)from->fill.flags & (int)SvgFillFlags::FillRule)) {
- to->fill.fillRule = from->fill.fillRule;
- }
- //Stroke
- to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)from->stroke.flags);
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Paint)) {
- to->stroke.paint.color = from->stroke.paint.color;
- to->stroke.paint.none = from->stroke.paint.none;
- to->stroke.paint.curColor = from->stroke.paint.curColor;
- if (from->stroke.paint.url) {
- if (to->stroke.paint.url) free(to->stroke.paint.url);
- to->stroke.paint.url = _copyId(from->stroke.paint.url);
- } else {
- to->stroke.paint.url = nullptr;
- }
- }
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Opacity)) {
- to->stroke.opacity = from->stroke.opacity;
- }
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Width)) {
- to->stroke.width = from->stroke.width;
- }
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Dash)) {
- if (from->stroke.dash.array.count > 0) {
- to->stroke.dash.array.clear();
- to->stroke.dash.array.reserve(from->stroke.dash.array.count);
- for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) {
- to->stroke.dash.array.push(from->stroke.dash.array.data[i]);
- }
- }
- }
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Cap)) {
- to->stroke.cap = from->stroke.cap;
- }
- if (((int)from->stroke.flags & (int)SvgStrokeFlags::Join)) {
- to->stroke.join = from->stroke.join;
- }
-}
-
-
-static void _copyAttr(SvgNode* to, const SvgNode* from)
-{
- //Copy matrix attribute
- if (from->transform) {
- to->transform = (Matrix*)malloc(sizeof(Matrix));
- if (to->transform) *to->transform = *from->transform;
- }
- //Copy style attribute
- _styleCopy(to->style, from->style);
- to->style->flags = (SvgStyleFlags)((int)to->style->flags | (int)from->style->flags);
- if (from->style->clipPath.url) {
- if (to->style->clipPath.url) free(to->style->clipPath.url);
- to->style->clipPath.url = strdup(from->style->clipPath.url);
- }
- if (from->style->mask.url) {
- if (to->style->mask.url) free(to->style->mask.url);
- to->style->mask.url = strdup(from->style->mask.url);
- }
-
- //Copy node attribute
- switch (from->type) {
- case SvgNodeType::Circle: {
- to->node.circle.cx = from->node.circle.cx;
- to->node.circle.cy = from->node.circle.cy;
- to->node.circle.r = from->node.circle.r;
- break;
- }
- case SvgNodeType::Ellipse: {
- to->node.ellipse.cx = from->node.ellipse.cx;
- to->node.ellipse.cy = from->node.ellipse.cy;
- to->node.ellipse.rx = from->node.ellipse.rx;
- to->node.ellipse.ry = from->node.ellipse.ry;
- break;
- }
- case SvgNodeType::Rect: {
- to->node.rect.x = from->node.rect.x;
- to->node.rect.y = from->node.rect.y;
- to->node.rect.w = from->node.rect.w;
- to->node.rect.h = from->node.rect.h;
- to->node.rect.rx = from->node.rect.rx;
- to->node.rect.ry = from->node.rect.ry;
- to->node.rect.hasRx = from->node.rect.hasRx;
- to->node.rect.hasRy = from->node.rect.hasRy;
- break;
- }
- case SvgNodeType::Line: {
- to->node.line.x1 = from->node.line.x1;
- to->node.line.y1 = from->node.line.y1;
- to->node.line.x2 = from->node.line.x2;
- to->node.line.y2 = from->node.line.y2;
- break;
- }
- case SvgNodeType::Path: {
- if (from->node.path.path) {
- if (to->node.path.path) free(to->node.path.path);
- to->node.path.path = strdup(from->node.path.path);
- }
- break;
- }
- case SvgNodeType::Polygon: {
- if ((to->node.polygon.pointsCount = from->node.polygon.pointsCount)) {
- to->node.polygon.points = (float*)malloc(to->node.polygon.pointsCount * sizeof(float));
- memcpy(to->node.polygon.points, from->node.polygon.points, to->node.polygon.pointsCount * sizeof(float));
- }
- break;
- }
- case SvgNodeType::Polyline: {
- if ((to->node.polyline.pointsCount = from->node.polyline.pointsCount)) {
- to->node.polyline.points = (float*)malloc(to->node.polyline.pointsCount * sizeof(float));
- memcpy(to->node.polyline.points, from->node.polyline.points, to->node.polyline.pointsCount * sizeof(float));
- }
- break;
- }
- case SvgNodeType::Image: {
- to->node.image.x = from->node.image.x;
- to->node.image.y = from->node.image.y;
- to->node.image.w = from->node.image.w;
- to->node.image.h = from->node.image.h;
- if (from->node.image.href) {
- if (to->node.image.href) free(to->node.image.href);
- to->node.image.href = strdup(from->node.image.href);
- }
- break;
- }
- default: {
- break;
- }
- }
-}
-
-
-static void _cloneNode(SvgNode* from, SvgNode* parent, int depth)
-{
- /* Exception handling: Prevent invalid SVG data input.
- The size is the arbitrary value, we need an experimental size. */
- if (depth == 8192) {
- TVGERR("SVG", "Infinite recursive call - stopped after %d calls! Svg file may be incorrectly formatted.", depth);
- return;
- }
-
- SvgNode* newNode;
- if (!from || !parent || from == parent) return;
-
- newNode = _createNode(parent, from->type);
- if (!newNode) return;
-
- _styleInherit(newNode->style, parent->style);
- _copyAttr(newNode, from);
-
- auto child = from->child.data;
- for (uint32_t i = 0; i < from->child.count; ++i, ++child) {
- _cloneNode(*child, newNode, depth + 1);
- }
-}
-
-
-static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
-{
- for (uint32_t i = 0; i < cloneNodes->count; ++i) {
- auto nodeIdPair = cloneNodes->data[i];
- auto defs = _getDefsNode(nodeIdPair.node);
- auto nodeFrom = _findNodeById(defs, nodeIdPair.id);
- if (!nodeFrom) nodeFrom = _findNodeById(doc, nodeIdPair.id);
- _cloneNode(nodeFrom, nodeIdPair.node, 0);
- if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) {
- nodeIdPair.node->node.use.symbol = nodeFrom;
- }
- free(nodeIdPair.id);
- }
-}
-
-
static constexpr struct
{
const char* tag;
@@ -2185,6 +1940,7 @@ static constexpr struct
};
+static void _cloneNode(SvgNode* from, SvgNode* parent, int depth);
static bool _attrParseUseNode(void* data, const char* key, const char* value)
{
SvgLoaderData* loader = (SvgLoaderData*)data;
@@ -2379,13 +2135,99 @@ static void _recalcRadialRAttr(SvgLoaderData* loader, SvgRadialGradient* radial,
}
+static void _recalcInheritedRadialCxAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
+{
+ if (!radial->isCxPercentage) {
+ if (userSpace) radial->cx /= loader->svgParse->global.w;
+ else radial->cx *= loader->svgParse->global.w;
+ }
+}
+
+
+static void _recalcInheritedRadialCyAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
+{
+ if (!radial->isCyPercentage) {
+ if (userSpace) radial->cy /= loader->svgParse->global.h;
+ else radial->cy *= loader->svgParse->global.h;
+ }
+}
+
+
+static void _recalcInheritedRadialFxAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
+{
+ if (!radial->isFxPercentage) {
+ if (userSpace) radial->fx /= loader->svgParse->global.w;
+ else radial->fx *= loader->svgParse->global.w;
+ }
+}
+
+
+static void _recalcInheritedRadialFyAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
+{
+ if (!radial->isFyPercentage) {
+ if (userSpace) radial->fy /= loader->svgParse->global.h;
+ else radial->fy *= loader->svgParse->global.h;
+ }
+}
+
+
+static void _recalcInheritedRadialRAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
+{
+ if (!radial->isRPercentage) {
+ if (userSpace) radial->r /= sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0);
+ else radial->r *= sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0);
+ }
+}
+
+
+static void _inheritRadialCxAttr(SvgStyleGradient* to, SvgStyleGradient* from)
+{
+ to->radial->cx = from->radial->cx;
+ to->radial->isCxPercentage = from->radial->isCxPercentage;
+ to->flags = (to->flags | SvgGradientFlags::Cx);
+}
+
+
+static void _inheritRadialCyAttr(SvgStyleGradient* to, SvgStyleGradient* from)
+{
+ to->radial->cy = from->radial->cy;
+ to->radial->isCyPercentage = from->radial->isCyPercentage;
+ to->flags = (to->flags | SvgGradientFlags::Cy);
+}
+
+
+static void _inheritRadialFxAttr(SvgStyleGradient* to, SvgStyleGradient* from)
+{
+ to->radial->fx = from->radial->fx;
+ to->radial->isFxPercentage = from->radial->isFxPercentage;
+ to->flags = (to->flags | SvgGradientFlags::Fx);
+}
+
+
+static void _inheritRadialFyAttr(SvgStyleGradient* to, SvgStyleGradient* from)
+{
+ to->radial->fy = from->radial->fy;
+ to->radial->isFyPercentage = from->radial->isFyPercentage;
+ to->flags = (to->flags | SvgGradientFlags::Fy);
+}
+
+
+static void _inheritRadialRAttr(SvgStyleGradient* to, SvgStyleGradient* from)
+{
+ to->radial->r = from->radial->r;
+ to->radial->isRPercentage = from->radial->isRPercentage;
+ to->flags = (to->flags | SvgGradientFlags::R);
+}
+
+
typedef void (*radialMethod)(SvgLoaderData* loader, SvgRadialGradient* radial, const char* value);
+typedef void (*radialInheritMethod)(SvgStyleGradient* to, SvgStyleGradient* from);
typedef void (*radialMethodRecalc)(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace);
-#define RADIAL_DEF(Name, Name1) \
+#define RADIAL_DEF(Name, Name1, Flag) \
{ \
-#Name, sizeof(#Name), _handleRadial##Name1##Attr, _recalcRadial##Name1##Attr \
+#Name, sizeof(#Name), _handleRadial##Name1##Attr, _inheritRadial##Name1##Attr, _recalcRadial##Name1##Attr, _recalcInheritedRadial##Name1##Attr, Flag \
}
@@ -2394,13 +2236,16 @@ static constexpr struct
const char* tag;
int sz;
radialMethod tagHandler;
+ radialInheritMethod tagInheritHandler;
radialMethodRecalc tagRecalc;
+ radialMethodRecalc tagInheritedRecalc;
+ SvgGradientFlags flag;
} radialTags[] = {
- RADIAL_DEF(cx, Cx),
- RADIAL_DEF(cy, Cy),
- RADIAL_DEF(fx, Fx),
- RADIAL_DEF(fy, Fy),
- RADIAL_DEF(r, R)
+ RADIAL_DEF(cx, Cx, SvgGradientFlags::Cx),
+ RADIAL_DEF(cy, Cy, SvgGradientFlags::Cy),
+ RADIAL_DEF(fx, Fx, SvgGradientFlags::Fx),
+ RADIAL_DEF(fy, Fy, SvgGradientFlags::Fy),
+ RADIAL_DEF(r, R, SvgGradientFlags::R)
};
@@ -2414,6 +2259,7 @@ static bool _attrParseRadialGradientNode(void* data, const char* key, const char
for (unsigned int i = 0; i < sizeof(radialTags) / sizeof(radialTags[0]); i++) {
if (radialTags[i].sz - 1 == sz && !strncmp(radialTags[i].tag, key, sz)) {
radialTags[i].tagHandler(loader, radial, value);
+ grad->flags = (grad->flags | radialTags[i].flag);
return true;
}
}
@@ -2423,11 +2269,13 @@ static bool _attrParseRadialGradientNode(void* data, const char* key, const char
grad->id = _copyId(value);
} else if (!strcmp(key, "spreadMethod")) {
grad->spread = _parseSpreadValue(value);
+ grad->flags = (grad->flags | SvgGradientFlags::SpreadMethod);
} else if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) {
if (grad->ref && value) free(grad->ref);
grad->ref = _idFromHref(value);
} else if (!strcmp(key, "gradientUnits")) {
if (!strcmp(value, "userSpaceOnUse")) grad->userSpace = true;
+ grad->flags = (grad->flags | SvgGradientFlags::GradientUnits);
} else if (!strcmp(key, "gradientTransform")) {
grad->transform = _parseTransformationMatrix(value);
} else {
@@ -2443,6 +2291,7 @@ static SvgStyleGradient* _createRadialGradient(SvgLoaderData* loader, const char
auto grad = (SvgStyleGradient*)(calloc(1, sizeof(SvgStyleGradient)));
loader->svgParse->styleGrad = grad;
+ grad->flags = SvgGradientFlags::None;
grad->type = SvgGradientType::Radial;
grad->userSpace = false;
grad->radial = (SvgRadialGradient*)calloc(1, sizeof(SvgRadialGradient));
@@ -2485,10 +2334,10 @@ static bool _attrParseStopsStyle(void* data, const char* key, const char* value)
if (!strcmp(key, "stop-opacity")) {
stop->a = _toOpacity(value);
- loader->svgParse->flags = (SvgStopStyleFlags)((int)loader->svgParse->flags | (int)SvgStopStyleFlags::StopOpacity);
+ loader->svgParse->flags = (loader->svgParse->flags | SvgStopStyleFlags::StopOpacity);
} else if (!strcmp(key, "stop-color")) {
_toColor(value, &stop->r, &stop->g, &stop->b, nullptr);
- loader->svgParse->flags = (SvgStopStyleFlags)((int)loader->svgParse->flags | (int)SvgStopStyleFlags::StopColor);
+ loader->svgParse->flags = (loader->svgParse->flags | SvgStopStyleFlags::StopColor);
} else {
return false;
}
@@ -2505,11 +2354,11 @@ static bool _attrParseStops(void* data, const char* key, const char* value)
if (!strcmp(key, "offset")) {
stop->offset = _toOffset(value);
} else if (!strcmp(key, "stop-opacity")) {
- if (!((int)loader->svgParse->flags & (int)SvgStopStyleFlags::StopOpacity)) {
+ if (!(loader->svgParse->flags & SvgStopStyleFlags::StopOpacity)) {
stop->a = _toOpacity(value);
}
} else if (!strcmp(key, "stop-color")) {
- if (!((int)loader->svgParse->flags & (int)SvgStopStyleFlags::StopColor)) {
+ if (!(loader->svgParse->flags & SvgStopStyleFlags::StopColor)) {
_toColor(value, &stop->r, &stop->g, &stop->b, nullptr);
}
} else if (!strcmp(key, "style")) {
@@ -2570,13 +2419,82 @@ static void _recalcLinearY2Attr(SvgLoaderData* loader, SvgLinearGradient* linear
}
+static void _recalcInheritedLinearX1Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace)
+{
+ if (!linear->isX1Percentage) {
+ if (userSpace) linear->x1 /= loader->svgParse->global.w;
+ else linear->x1 *= loader->svgParse->global.w;
+ }
+}
+
+
+static void _recalcInheritedLinearX2Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace)
+{
+ if (!linear->isX2Percentage) {
+ if (userSpace) linear->x2 /= loader->svgParse->global.w;
+ else linear->x2 *= loader->svgParse->global.w;
+ }
+}
+
+
+static void _recalcInheritedLinearY1Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace)
+{
+ if (!linear->isY1Percentage) {
+ if (userSpace) linear->y1 /= loader->svgParse->global.h;
+ else linear->y1 *= loader->svgParse->global.h;
+ }
+}
+
+
+static void _recalcInheritedLinearY2Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace)
+{
+ if (!linear->isY2Percentage) {
+ if (userSpace) linear->y2 /= loader->svgParse->global.h;
+ else linear->y2 *= loader->svgParse->global.h;
+ }
+}
+
+
+static void _inheritLinearX1Attr(SvgStyleGradient* to, SvgStyleGradient* from)
+{
+ to->linear->x1 = from->linear->x1;
+ to->linear->isX1Percentage = from->linear->isX1Percentage;
+ to->flags = (to->flags | SvgGradientFlags::X1);
+}
+
+
+static void _inheritLinearX2Attr(SvgStyleGradient* to, SvgStyleGradient* from)
+{
+ to->linear->x2 = from->linear->x2;
+ to->linear->isX2Percentage = from->linear->isX2Percentage;
+ to->flags = (to->flags | SvgGradientFlags::X2);
+}
+
+
+static void _inheritLinearY1Attr(SvgStyleGradient* to, SvgStyleGradient* from)
+{
+ to->linear->y1 = from->linear->y1;
+ to->linear->isY1Percentage = from->linear->isY1Percentage;
+ to->flags = (to->flags | SvgGradientFlags::Y1);
+}
+
+
+static void _inheritLinearY2Attr(SvgStyleGradient* to, SvgStyleGradient* from)
+{
+ to->linear->y2 = from->linear->y2;
+ to->linear->isY2Percentage = from->linear->isY2Percentage;
+ to->flags = (to->flags | SvgGradientFlags::Y2);
+}
+
+
typedef void (*Linear_Method)(SvgLoaderData* loader, SvgLinearGradient* linear, const char* value);
+typedef void (*Linear_Inherit_Method)(SvgStyleGradient* to, SvgStyleGradient* from);
typedef void (*Linear_Method_Recalc)(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace);
-#define LINEAR_DEF(Name, Name1) \
+#define LINEAR_DEF(Name, Name1, Flag) \
{ \
-#Name, sizeof(#Name), _handleLinear##Name1##Attr, _recalcLinear##Name1##Attr \
+#Name, sizeof(#Name), _handleLinear##Name1##Attr, _inheritLinear##Name1##Attr, _recalcLinear##Name1##Attr, _recalcInheritedLinear##Name1##Attr, Flag \
}
@@ -2585,12 +2503,15 @@ static constexpr struct
const char* tag;
int sz;
Linear_Method tagHandler;
+ Linear_Inherit_Method tagInheritHandler;
Linear_Method_Recalc tagRecalc;
+ Linear_Method_Recalc tagInheritedRecalc;
+ SvgGradientFlags flag;
} linear_tags[] = {
- LINEAR_DEF(x1, X1),
- LINEAR_DEF(y1, Y1),
- LINEAR_DEF(x2, X2),
- LINEAR_DEF(y2, Y2)
+ LINEAR_DEF(x1, X1, SvgGradientFlags::X1),
+ LINEAR_DEF(y1, Y1, SvgGradientFlags::Y1),
+ LINEAR_DEF(x2, X2, SvgGradientFlags::X2),
+ LINEAR_DEF(y2, Y2, SvgGradientFlags::Y2)
};
@@ -2604,6 +2525,7 @@ static bool _attrParseLinearGradientNode(void* data, const char* key, const char
for (unsigned int i = 0; i < sizeof(linear_tags) / sizeof(linear_tags[0]); i++) {
if (linear_tags[i].sz - 1 == sz && !strncmp(linear_tags[i].tag, key, sz)) {
linear_tags[i].tagHandler(loader, linear, value);
+ grad->flags = (grad->flags | linear_tags[i].flag);
return true;
}
}
@@ -2613,11 +2535,13 @@ static bool _attrParseLinearGradientNode(void* data, const char* key, const char
grad->id = _copyId(value);
} else if (!strcmp(key, "spreadMethod")) {
grad->spread = _parseSpreadValue(value);
+ grad->flags = (grad->flags | SvgGradientFlags::SpreadMethod);
} else if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) {
if (grad->ref && value) free(grad->ref);
grad->ref = _idFromHref(value);
} else if (!strcmp(key, "gradientUnits")) {
if (!strcmp(value, "userSpaceOnUse")) grad->userSpace = true;
+ grad->flags = (grad->flags | SvgGradientFlags::GradientUnits);
} else if (!strcmp(key, "gradientTransform")) {
grad->transform = _parseTransformationMatrix(value);
} else {
@@ -2633,6 +2557,7 @@ static SvgStyleGradient* _createLinearGradient(SvgLoaderData* loader, const char
auto grad = (SvgStyleGradient*)(calloc(1, sizeof(SvgStyleGradient)));
loader->svgParse->styleGrad = grad;
+ grad->flags = SvgGradientFlags::None;
grad->type = SvgGradientType::Linear;
grad->userSpace = false;
grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient));
@@ -2692,6 +2617,371 @@ static GradientFactoryMethod _findGradientFactory(const char* name)
}
+static void _cloneGradStops(Array<Fill::ColorStop>& dst, const Array<Fill::ColorStop>& src)
+{
+ for (uint32_t i = 0; i < src.count; ++i) {
+ dst.push(src.data[i]);
+ }
+}
+
+
+static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgStyleGradient* from)
+{
+ if (!to || !from) return;
+
+ if (!(to->flags & SvgGradientFlags::SpreadMethod) && (from->flags & SvgGradientFlags::SpreadMethod)) {
+ to->spread = from->spread;
+ to->flags = (to->flags | SvgGradientFlags::SpreadMethod);
+ }
+ bool gradUnitSet = (to->flags & SvgGradientFlags::GradientUnits);
+ if (!(to->flags & SvgGradientFlags::GradientUnits) && (from->flags & SvgGradientFlags::GradientUnits)) {
+ to->userSpace = from->userSpace;
+ to->flags = (to->flags | SvgGradientFlags::GradientUnits);
+ }
+
+ if (!to->transform && from->transform) {
+ to->transform = (Matrix*)malloc(sizeof(Matrix));
+ if (to->transform) memcpy(to->transform, from->transform, sizeof(Matrix));
+ }
+
+ if (to->type == SvgGradientType::Linear && from->type == SvgGradientType::Linear) {
+ for (unsigned int i = 0; i < sizeof(linear_tags) / sizeof(linear_tags[0]); i++) {
+ bool coordSet = to->flags & linear_tags[i].flag;
+ if (!(to->flags & linear_tags[i].flag) && (from->flags & linear_tags[i].flag)) {
+ linear_tags[i].tagInheritHandler(to, from);
+ }
+
+ //GradUnits not set directly, coord set
+ if (!gradUnitSet && coordSet) {
+ linear_tags[i].tagRecalc(loader, to->linear, to->userSpace);
+ }
+ //GradUnits set, coord not set directly
+ if (to->userSpace == from->userSpace) continue;
+ if (gradUnitSet && !coordSet) {
+ linear_tags[i].tagInheritedRecalc(loader, to->linear, to->userSpace);
+ }
+ }
+ } else if (to->type == SvgGradientType::Radial && from->type == SvgGradientType::Radial) {
+ for (unsigned int i = 0; i < sizeof(radialTags) / sizeof(radialTags[0]); i++) {
+ bool coordSet = (to->flags & radialTags[i].flag);
+ if (!(to->flags & radialTags[i].flag) && (from->flags & radialTags[i].flag)) {
+ radialTags[i].tagInheritHandler(to, from);
+ }
+
+ //GradUnits not set directly, coord set
+ if (!gradUnitSet && coordSet) {
+ radialTags[i].tagRecalc(loader, to->radial, to->userSpace);
+ }
+ //GradUnits set, coord not set directly
+ if (to->userSpace == from->userSpace) continue;
+ if (gradUnitSet && !coordSet) {
+ radialTags[i].tagInheritedRecalc(loader, to->radial, to->userSpace);
+ }
+ }
+ }
+
+ if (to->stops.count == 0) _cloneGradStops(to->stops, from->stops);
+}
+
+
+static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from)
+{
+ if (!from) return nullptr;
+
+ auto grad = (SvgStyleGradient*)(calloc(1, sizeof(SvgStyleGradient)));
+ if (!grad) return nullptr;
+
+ grad->type = from->type;
+ grad->id = from->id ? _copyId(from->id) : nullptr;
+ grad->ref = from->ref ? _copyId(from->ref) : nullptr;
+ grad->spread = from->spread;
+ grad->userSpace = from->userSpace;
+ grad->flags = from->flags;
+
+ if (from->transform) {
+ grad->transform = (Matrix*)calloc(1, sizeof(Matrix));
+ if (grad->transform) memcpy(grad->transform, from->transform, sizeof(Matrix));
+ }
+
+ if (grad->type == SvgGradientType::Linear) {
+ grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient));
+ if (!grad->linear) goto error_grad_alloc;
+ memcpy(grad->linear, from->linear, sizeof(SvgLinearGradient));
+ } else if (grad->type == SvgGradientType::Radial) {
+ grad->radial = (SvgRadialGradient*)calloc(1, sizeof(SvgRadialGradient));
+ if (!grad->radial) goto error_grad_alloc;
+ memcpy(grad->radial, from->radial, sizeof(SvgRadialGradient));
+ }
+
+ _cloneGradStops(grad->stops, from->stops);
+
+ return grad;
+
+ error_grad_alloc:
+ if (grad) {
+ grad->clear();
+ free(grad);
+ }
+ return nullptr;
+}
+
+
+static void _styleInherit(SvgStyleProperty* child, const SvgStyleProperty* parent)
+{
+ if (parent == nullptr) return;
+ //Inherit the property of parent if not present in child.
+ if (!child->curColorSet) {
+ child->color = parent->color;
+ child->curColorSet = parent->curColorSet;
+ }
+ if (!(child->flags & SvgStyleFlags::PaintOrder)) {
+ child->paintOrder = parent->paintOrder;
+ }
+ //Fill
+ if (!(child->fill.flags & SvgFillFlags::Paint)) {
+ child->fill.paint.color = parent->fill.paint.color;
+ child->fill.paint.none = parent->fill.paint.none;
+ child->fill.paint.curColor = parent->fill.paint.curColor;
+ if (parent->fill.paint.url) {
+ if (child->fill.paint.url) free(child->fill.paint.url);
+ child->fill.paint.url = _copyId(parent->fill.paint.url);
+ }
+ }
+ if (!(child->fill.flags & SvgFillFlags::Opacity)) {
+ child->fill.opacity = parent->fill.opacity;
+ }
+ if (!(child->fill.flags & SvgFillFlags::FillRule)) {
+ child->fill.fillRule = parent->fill.fillRule;
+ }
+ //Stroke
+ if (!(child->stroke.flags & SvgStrokeFlags::Paint)) {
+ child->stroke.paint.color = parent->stroke.paint.color;
+ child->stroke.paint.none = parent->stroke.paint.none;
+ child->stroke.paint.curColor = parent->stroke.paint.curColor;
+ if (parent->stroke.paint.url) {
+ if (child->stroke.paint.url) free(child->stroke.paint.url);
+ child->stroke.paint.url = _copyId(parent->stroke.paint.url);
+ }
+ }
+ if (!(child->stroke.flags & SvgStrokeFlags::Opacity)) {
+ child->stroke.opacity = parent->stroke.opacity;
+ }
+ if (!(child->stroke.flags & SvgStrokeFlags::Width)) {
+ child->stroke.width = parent->stroke.width;
+ }
+ if (!(child->stroke.flags & SvgStrokeFlags::Dash)) {
+ if (parent->stroke.dash.array.count > 0) {
+ child->stroke.dash.array.clear();
+ child->stroke.dash.array.reserve(parent->stroke.dash.array.count);
+ for (uint32_t i = 0; i < parent->stroke.dash.array.count; ++i) {
+ child->stroke.dash.array.push(parent->stroke.dash.array.data[i]);
+ }
+ }
+ }
+ if (!(child->stroke.flags & SvgStrokeFlags::Cap)) {
+ child->stroke.cap = parent->stroke.cap;
+ }
+ if (!(child->stroke.flags & SvgStrokeFlags::Join)) {
+ child->stroke.join = parent->stroke.join;
+ }
+}
+
+
+static void _styleCopy(SvgStyleProperty* to, const SvgStyleProperty* from)
+{
+ if (from == nullptr) return;
+ //Copy the properties of 'from' only if they were explicitly set (not the default ones).
+ if (from->curColorSet) {
+ to->color = from->color;
+ to->curColorSet = true;
+ }
+ if (from->flags & SvgStyleFlags::PaintOrder) {
+ to->paintOrder = from->paintOrder;
+ }
+ //Fill
+ to->fill.flags = (to->fill.flags | from->fill.flags);
+ if (from->fill.flags & SvgFillFlags::Paint) {
+ to->fill.paint.color = from->fill.paint.color;
+ to->fill.paint.none = from->fill.paint.none;
+ to->fill.paint.curColor = from->fill.paint.curColor;
+ if (from->fill.paint.url) {
+ if (to->fill.paint.url) free(to->fill.paint.url);
+ to->fill.paint.url = _copyId(from->fill.paint.url);
+ }
+ }
+ if (from->fill.flags & SvgFillFlags::Opacity) {
+ to->fill.opacity = from->fill.opacity;
+ }
+ if (from->fill.flags & SvgFillFlags::FillRule) {
+ to->fill.fillRule = from->fill.fillRule;
+ }
+ //Stroke
+ to->stroke.flags = (to->stroke.flags | from->stroke.flags);
+ if (from->stroke.flags & SvgStrokeFlags::Paint) {
+ to->stroke.paint.color = from->stroke.paint.color;
+ to->stroke.paint.none = from->stroke.paint.none;
+ to->stroke.paint.curColor = from->stroke.paint.curColor;
+ if (from->stroke.paint.url) {
+ if (to->stroke.paint.url) free(to->stroke.paint.url);
+ to->stroke.paint.url = _copyId(from->stroke.paint.url);
+ }
+ }
+ if (from->stroke.flags & SvgStrokeFlags::Opacity) {
+ to->stroke.opacity = from->stroke.opacity;
+ }
+ if (from->stroke.flags & SvgStrokeFlags::Width) {
+ to->stroke.width = from->stroke.width;
+ }
+ if (from->stroke.flags & SvgStrokeFlags::Dash) {
+ if (from->stroke.dash.array.count > 0) {
+ to->stroke.dash.array.clear();
+ to->stroke.dash.array.reserve(from->stroke.dash.array.count);
+ for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) {
+ to->stroke.dash.array.push(from->stroke.dash.array.data[i]);
+ }
+ }
+ }
+ if (from->stroke.flags & SvgStrokeFlags::Cap) {
+ to->stroke.cap = from->stroke.cap;
+ }
+ if (from->stroke.flags & SvgStrokeFlags::Join) {
+ to->stroke.join = from->stroke.join;
+ }
+}
+
+
+static void _copyAttr(SvgNode* to, const SvgNode* from)
+{
+ //Copy matrix attribute
+ if (from->transform) {
+ to->transform = (Matrix*)malloc(sizeof(Matrix));
+ if (to->transform) *to->transform = *from->transform;
+ }
+ //Copy style attribute
+ _styleCopy(to->style, from->style);
+ to->style->flags = (to->style->flags | from->style->flags);
+ if (from->style->clipPath.url) {
+ if (to->style->clipPath.url) free(to->style->clipPath.url);
+ to->style->clipPath.url = strdup(from->style->clipPath.url);
+ }
+ if (from->style->mask.url) {
+ if (to->style->mask.url) free(to->style->mask.url);
+ to->style->mask.url = strdup(from->style->mask.url);
+ }
+
+ //Copy node attribute
+ switch (from->type) {
+ case SvgNodeType::Circle: {
+ to->node.circle.cx = from->node.circle.cx;
+ to->node.circle.cy = from->node.circle.cy;
+ to->node.circle.r = from->node.circle.r;
+ break;
+ }
+ case SvgNodeType::Ellipse: {
+ to->node.ellipse.cx = from->node.ellipse.cx;
+ to->node.ellipse.cy = from->node.ellipse.cy;
+ to->node.ellipse.rx = from->node.ellipse.rx;
+ to->node.ellipse.ry = from->node.ellipse.ry;
+ break;
+ }
+ case SvgNodeType::Rect: {
+ to->node.rect.x = from->node.rect.x;
+ to->node.rect.y = from->node.rect.y;
+ to->node.rect.w = from->node.rect.w;
+ to->node.rect.h = from->node.rect.h;
+ to->node.rect.rx = from->node.rect.rx;
+ to->node.rect.ry = from->node.rect.ry;
+ to->node.rect.hasRx = from->node.rect.hasRx;
+ to->node.rect.hasRy = from->node.rect.hasRy;
+ break;
+ }
+ case SvgNodeType::Line: {
+ to->node.line.x1 = from->node.line.x1;
+ to->node.line.y1 = from->node.line.y1;
+ to->node.line.x2 = from->node.line.x2;
+ to->node.line.y2 = from->node.line.y2;
+ break;
+ }
+ case SvgNodeType::Path: {
+ if (from->node.path.path) {
+ if (to->node.path.path) free(to->node.path.path);
+ to->node.path.path = strdup(from->node.path.path);
+ }
+ break;
+ }
+ case SvgNodeType::Polygon: {
+ if ((to->node.polygon.pointsCount = from->node.polygon.pointsCount)) {
+ to->node.polygon.points = (float*)malloc(to->node.polygon.pointsCount * sizeof(float));
+ memcpy(to->node.polygon.points, from->node.polygon.points, to->node.polygon.pointsCount * sizeof(float));
+ }
+ break;
+ }
+ case SvgNodeType::Polyline: {
+ if ((to->node.polyline.pointsCount = from->node.polyline.pointsCount)) {
+ to->node.polyline.points = (float*)malloc(to->node.polyline.pointsCount * sizeof(float));
+ memcpy(to->node.polyline.points, from->node.polyline.points, to->node.polyline.pointsCount * sizeof(float));
+ }
+ break;
+ }
+ case SvgNodeType::Image: {
+ to->node.image.x = from->node.image.x;
+ to->node.image.y = from->node.image.y;
+ to->node.image.w = from->node.image.w;
+ to->node.image.h = from->node.image.h;
+ if (from->node.image.href) {
+ if (to->node.image.href) free(to->node.image.href);
+ to->node.image.href = strdup(from->node.image.href);
+ }
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+}
+
+
+static void _cloneNode(SvgNode* from, SvgNode* parent, int depth)
+{
+ /* Exception handling: Prevent invalid SVG data input.
+ The size is the arbitrary value, we need an experimental size. */
+ if (depth == 8192) {
+ TVGERR("SVG", "Infinite recursive call - stopped after %d calls! Svg file may be incorrectly formatted.", depth);
+ return;
+ }
+
+ SvgNode* newNode;
+ if (!from || !parent || from == parent) return;
+
+ newNode = _createNode(parent, from->type);
+ if (!newNode) return;
+
+ _styleInherit(newNode->style, parent->style);
+ _copyAttr(newNode, from);
+
+ auto child = from->child.data;
+ for (uint32_t i = 0; i < from->child.count; ++i, ++child) {
+ _cloneNode(*child, newNode, depth + 1);
+ }
+}
+
+
+static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
+{
+ for (uint32_t i = 0; i < cloneNodes->count; ++i) {
+ auto nodeIdPair = cloneNodes->data[i];
+ auto defs = _getDefsNode(nodeIdPair.node);
+ auto nodeFrom = _findNodeById(defs, nodeIdPair.id);
+ if (!nodeFrom) nodeFrom = _findNodeById(doc, nodeIdPair.id);
+ _cloneNode(nodeFrom, nodeIdPair.node, 0);
+ if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) {
+ nodeIdPair.node->node.use.symbol = nodeFrom;
+ }
+ free(nodeIdPair.id);
+ }
+}
+
+
static constexpr struct
{
const char* tag;
@@ -2738,6 +3028,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
//Parse the empty tag
attrs = content;
while ((attrs != nullptr) && *attrs != '>') attrs++;
+ if (empty) attrs--;
}
if (attrs) {
@@ -2942,7 +3233,7 @@ static void _updateStyle(SvgNode* node, SvgStyleProperty* parentStyle)
}
-static SvgStyleGradient* _gradientDup(Array<SvgStyleGradient*>* gradients, const char* id)
+static SvgStyleGradient* _gradientDup(SvgLoaderData* loader, Array<SvgStyleGradient*>* gradients, const char* id)
{
SvgStyleGradient* result = nullptr;
@@ -2960,8 +3251,7 @@ static SvgStyleGradient* _gradientDup(Array<SvgStyleGradient*>* gradients, const
gradList = gradients->data;
for (uint32_t i = 0; i < gradients->count; ++i) {
if ((*gradList)->id && !strcmp((*gradList)->id, result->ref)) {
- if (result->stops.count == 0) _cloneGradStops(result->stops, (*gradList)->stops);
- //TODO: Properly inherit other property
+ _inheritGradient(loader, result, *gradList);
break;
}
++gradList;
@@ -2972,27 +3262,33 @@ static SvgStyleGradient* _gradientDup(Array<SvgStyleGradient*>* gradients, const
}
-static void _updateGradient(SvgNode* node, Array<SvgStyleGradient*>* gradients)
+static void _updateGradient(SvgLoaderData* loader, SvgNode* node, Array<SvgStyleGradient*>* gradients)
{
if (node->child.count > 0) {
auto child = node->child.data;
for (uint32_t i = 0; i < node->child.count; ++i, ++child) {
- _updateGradient(*child, gradients);
+ _updateGradient(loader, *child, gradients);
}
} else {
if (node->style->fill.paint.url) {
- if (node->style->fill.paint.gradient) {
- node->style->fill.paint.gradient->clear();
- free(node->style->fill.paint.gradient);
+ auto newGrad = _gradientDup(loader, gradients, node->style->fill.paint.url);
+ if (newGrad) {
+ if (node->style->fill.paint.gradient) {
+ node->style->fill.paint.gradient->clear();
+ free(node->style->fill.paint.gradient);
+ }
+ node->style->fill.paint.gradient = newGrad;
}
- node->style->fill.paint.gradient = _gradientDup(gradients, node->style->fill.paint.url);
}
if (node->style->stroke.paint.url) {
- if (node->style->stroke.paint.gradient) {
- node->style->stroke.paint.gradient->clear();
- free(node->style->stroke.paint.gradient);
+ auto newGrad = _gradientDup(loader, gradients, node->style->stroke.paint.url);
+ if (newGrad) {
+ if (node->style->stroke.paint.gradient) {
+ node->style->stroke.paint.gradient->clear();
+ free(node->style->stroke.paint.gradient);
+ }
+ node->style->stroke.paint.gradient = newGrad;
}
- node->style->stroke.paint.gradient = _gradientDup(gradients, node->style->stroke.paint.url);
}
}
}
@@ -3181,7 +3477,8 @@ SvgLoader::~SvgLoader()
void SvgLoader::run(unsigned tid)
{
//According to the SVG standard the value of the width/height of the viewbox set to 0 disables rendering
- if (renderingDisabled) {
+ if ((viewFlag & SvgViewFlag::Viewbox) && (fabsf(vw) <= FLT_EPSILON || fabsf(vh) <= FLT_EPSILON)) {
+ TVGLOG("SVG", "The <viewBox> width and/or height set to 0 - rendering disabled.");
root = Scene::gen();
return;
}
@@ -3199,12 +3496,12 @@ void SvgLoader::run(unsigned tid)
_updateComposite(loaderData.doc, loaderData.doc);
if (defs) _updateComposite(loaderData.doc, defs);
- if (loaderData.gradients.count > 0) _updateGradient(loaderData.doc, &loaderData.gradients);
- if (defs) _updateGradient(loaderData.doc, &defs->node.defs.gradients);
-
_updateStyle(loaderData.doc, nullptr);
+
+ if (loaderData.gradients.count > 0) _updateGradient(&loaderData, loaderData.doc, &loaderData.gradients);
+ if (defs) _updateGradient(&loaderData, loaderData.doc, &defs->node.defs.gradients);
}
- root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, align, meetOrSlice, svgPath);
+ root = svgSceneBuild(loaderData, {vx, vy, vw, vh}, w, h, align, meetOrSlice, svgPath, viewFlag);
}
@@ -3217,34 +3514,78 @@ bool SvgLoader::header()
if (!loaderData.svgParse) return false;
loaderData.svgParse->flags = SvgStopStyleFlags::StopDefault;
+ viewFlag = SvgViewFlag::None;
simpleXmlParse(content, size, true, _svgLoaderParserForValidCheck, &(loaderData));
if (loaderData.doc && loaderData.doc->type == SvgNodeType::Doc) {
- //Return the brief resource info such as viewbox:
- vx = loaderData.doc->node.doc.vx;
- vy = loaderData.doc->node.doc.vy;
- w = vw = loaderData.doc->node.doc.vw;
- h = vh = loaderData.doc->node.doc.vh;
-
- //Override size
- if (loaderData.doc->node.doc.w > 0) {
+ viewFlag = loaderData.doc->node.doc.viewFlag;
+ align = loaderData.doc->node.doc.align;
+ meetOrSlice = loaderData.doc->node.doc.meetOrSlice;
+
+ if (viewFlag & SvgViewFlag::Viewbox) {
+ vx = loaderData.doc->node.doc.vx;
+ vy = loaderData.doc->node.doc.vy;
+ vw = loaderData.doc->node.doc.vw;
+ vh = loaderData.doc->node.doc.vh;
+
+ if (viewFlag & SvgViewFlag::Width) w = loaderData.doc->node.doc.w;
+ else {
+ w = loaderData.doc->node.doc.vw;
+ if (viewFlag & SvgViewFlag::WidthInPercent) {
+ w *= loaderData.doc->node.doc.w;
+ viewFlag = (viewFlag ^ SvgViewFlag::WidthInPercent);
+ }
+ viewFlag = (viewFlag | SvgViewFlag::Width);
+ }
+ if (viewFlag & SvgViewFlag::Height) h = loaderData.doc->node.doc.h;
+ else {
+ h = loaderData.doc->node.doc.vh;
+ if (viewFlag & SvgViewFlag::HeightInPercent) {
+ h *= loaderData.doc->node.doc.h;
+ viewFlag = (viewFlag ^ SvgViewFlag::HeightInPercent);
+ }
+ viewFlag = (viewFlag | SvgViewFlag::Height);
+ }
+ //In case no viewbox and width/height data is provided the completion of loading
+ //has to be forced, in order to establish this data based on the whole picture.
+ } else {
+ //Before loading, set default viewbox & size if they are empty
+ vx = vy = 0.0f;
+ if (viewFlag & SvgViewFlag::Width) {
+ vw = w = loaderData.doc->node.doc.w;
+ } else {
+ vw = 1.0f;
+ if (viewFlag & SvgViewFlag::WidthInPercent) {
+ w = loaderData.doc->node.doc.w;
+ } else w = 1.0f;
+ }
+
+ if (viewFlag & SvgViewFlag::Height) {
+ vh = h = loaderData.doc->node.doc.h;
+ } else {
+ vh = 1.0f;
+ if (viewFlag & SvgViewFlag::HeightInPercent) {
+ h = loaderData.doc->node.doc.h;
+ } else h = 1.0f;
+ }
+
+ run(0);
+
+ //Override viewbox & size again after svg loading.
+ vx = loaderData.doc->node.doc.vx;
+ vy = loaderData.doc->node.doc.vy;
+ vw = loaderData.doc->node.doc.vw;
+ vh = loaderData.doc->node.doc.vh;
w = loaderData.doc->node.doc.w;
- if (vw < FLT_EPSILON) vw = w;
- }
- if (loaderData.doc->node.doc.h > 0) {
h = loaderData.doc->node.doc.h;
- if (vh < FLT_EPSILON) vh = h;
}
- align = loaderData.doc->node.doc.align;
- meetOrSlice = loaderData.doc->node.doc.meetOrSlice;
- } else {
- TVGLOG("SVG", "No SVG File. There is no <svg/>");
- return false;
+ return true;
}
- return true;
+ TVGLOG("SVG", "No SVG File. There is no <svg/>");
+ return false;
}
@@ -3304,6 +3645,9 @@ bool SvgLoader::read()
{
if (!content || size == 0) return false;
+ //the loading has been already completed in header()
+ if (root) return true;
+
TaskScheduler::request(this);
return true;
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h
index c6fdde55af..5c74184ec8 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_SVG_LOADER_H_
#define _TVG_SVG_LOADER_H_
@@ -50,9 +51,9 @@ public:
unique_ptr<Paint> paint() override;
private:
+ SvgViewFlag viewFlag = SvgViewFlag::None;
AspectRatioAlign align = AspectRatioAlign::XMidYMid;
AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet;
- bool renderingDisabled = false;
bool header();
void clear();
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
index 3588cabf0b..dec9fadebe 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_SVG_LOADER_COMMON_H_
#define _TVG_SVG_LOADER_COMMON_H_
@@ -79,6 +80,16 @@ enum class SvgFillFlags
ClipPath = 0x16
};
+constexpr bool operator &(SvgFillFlags a, SvgFillFlags b)
+{
+ return int(a) & int(b);
+}
+
+constexpr SvgFillFlags operator |(SvgFillFlags a, SvgFillFlags b)
+{
+ return SvgFillFlags(int(a) | int(b));
+}
+
enum class SvgStrokeFlags
{
Paint = 0x1,
@@ -91,6 +102,17 @@ enum class SvgStrokeFlags
Dash = 0x80,
};
+constexpr bool operator &(SvgStrokeFlags a, SvgStrokeFlags b)
+{
+ return int(a) & int(b);
+}
+
+constexpr SvgStrokeFlags operator |(SvgStrokeFlags a, SvgStrokeFlags b)
+{
+ return SvgStrokeFlags(int(a) | int(b));
+}
+
+
enum class SvgGradientType
{
Linear,
@@ -114,9 +136,20 @@ enum class SvgStyleFlags
ClipPath = 0x1000,
Mask = 0x2000,
MaskType = 0x4000,
- Display = 0x8000
+ Display = 0x8000,
+ PaintOrder = 0x10000
};
+constexpr bool operator &(SvgStyleFlags a, SvgStyleFlags b)
+{
+ return int(a) & int(b);
+}
+
+constexpr SvgStyleFlags operator |(SvgStyleFlags a, SvgStyleFlags b)
+{
+ return SvgStyleFlags(int(a) | int(b));
+}
+
enum class SvgStopStyleFlags
{
StopDefault = 0x0,
@@ -124,6 +157,42 @@ enum class SvgStopStyleFlags
StopColor = 0x02
};
+constexpr bool operator &(SvgStopStyleFlags a, SvgStopStyleFlags b)
+{
+ return int(a) & int(b);
+}
+
+constexpr SvgStopStyleFlags operator |(SvgStopStyleFlags a, SvgStopStyleFlags b)
+{
+ return SvgStopStyleFlags(int(a) | int(b));
+}
+
+enum class SvgGradientFlags
+{
+ None = 0x0,
+ GradientUnits = 0x1,
+ SpreadMethod = 0x2,
+ X1 = 0x4,
+ X2 = 0x8,
+ Y1 = 0x10,
+ Y2 = 0x20,
+ Cx = 0x40,
+ Cy = 0x80,
+ R = 0x100,
+ Fx = 0x200,
+ Fy = 0x400
+};
+
+constexpr bool operator &(SvgGradientFlags a, SvgGradientFlags b)
+{
+ return int(a) & int(b);
+}
+
+constexpr SvgGradientFlags operator |(SvgGradientFlags a, SvgGradientFlags b)
+{
+ return SvgGradientFlags(int(a) | int(b));
+}
+
enum class SvgFillRule
{
Winding = 0,
@@ -145,6 +214,31 @@ enum class SvgParserLengthType
Other
};
+enum class SvgViewFlag
+{
+ None = 0x0,
+ Width = 0x01, //viewPort width
+ Height = 0x02, //viewPort height
+ Viewbox = 0x04, //viewBox x,y,w,h - used only if all 4 are correctly set
+ WidthInPercent = 0x08,
+ HeightInPercent = 0x10
+};
+
+constexpr bool operator &(SvgViewFlag a, SvgViewFlag b)
+{
+ return static_cast<int>(a) & static_cast<int>(b);
+}
+
+constexpr SvgViewFlag operator |(SvgViewFlag a, SvgViewFlag b)
+{
+ return SvgViewFlag(int(a) | int(b));
+}
+
+constexpr SvgViewFlag operator ^(SvgViewFlag a, SvgViewFlag b)
+{
+ return SvgViewFlag(int(a) ^ int(b));
+}
+
enum class AspectRatioAlign
{
None,
@@ -167,12 +261,13 @@ enum class AspectRatioMeetOrSlice
struct SvgDocNode
{
- float w;
- float h;
+ float w; //unit: point or in percentage see: SvgViewFlag
+ float h; //unit: point or in percentage see: SvgViewFlag
float vx;
float vy;
float vw;
float vh;
+ SvgViewFlag viewFlag;
SvgNode* defs;
SvgNode* style;
AspectRatioAlign align;
@@ -339,6 +434,7 @@ struct SvgStyleGradient
SvgLinearGradient* linear;
Matrix* transform;
Array<Fill::ColorStop> stops;
+ SvgGradientFlags flags;
bool userSpace;
void clear()
@@ -384,6 +480,7 @@ struct SvgStyleProperty
SvgColor color;
bool curColorSet;
char* cssClass;
+ bool paintOrder; //true if default (fill, stroke), false otherwise
SvgStyleFlags flags;
};
@@ -456,6 +553,11 @@ struct SvgLoaderData
bool style = false;
};
+struct Box
+{
+ float x, y, w, h;
+};
+
/*
* https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strtof-strtod-l-wcstod-wcstod-l?view=vs-2017
*
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp
index a09a2797d0..e044931b51 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -52,7 +52,6 @@
#include <cstring>
#include <math.h>
-#include <clocale>
#include <ctype.h>
#include "tvgSvgLoaderCommon.h"
#include "tvgSvgPath.h"
@@ -545,11 +544,6 @@ bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point
char cmd = 0;
bool isQuadratic = false;
char* path = (char*)svgPath;
- char* curLocale;
-
- curLocale = setlocale(LC_NUMERIC, NULL);
- if (curLocale) curLocale = strdup(curLocale);
- setlocale(LC_NUMERIC, "POSIX");
while ((path[0] != '\0')) {
path = _nextCommand(path, &cmd, numberArray, &numberCount);
@@ -557,8 +551,5 @@ bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point
if (!_processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &startPoint, &isQuadratic)) break;
}
- setlocale(LC_NUMERIC, curLocale);
- if (curLocale) free(curLocale);
-
return true;
}
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h
index 8f5f9035dc..4199088dc1 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp
index 254ee2d008..c5e5df893e 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -61,12 +61,6 @@
/* Internal Class Implementation */
/************************************************************************/
-struct Box
-{
- float x, y, w, h;
-};
-
-
static bool _appendShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath);
static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite = nullptr);
@@ -255,7 +249,6 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox
node->style->clipPath.applying = true;
auto comp = Shape::gen();
- if (node->transform) comp->transform(*node->transform);
auto child = compNode->child.data;
auto valid = false; //Composite only when valid shapes are existed
@@ -264,6 +257,12 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox
if (_appendChildShape(*child, comp.get(), vBox, svgPath)) valid = true;
}
+ if (node->transform) {
+ auto m = comp->transform();
+ m = mathMultiply(node->transform, &m);
+ comp->transform(m);
+ }
+
if (valid) paint->composite(move(comp), CompositeMethod::ClipPath);
node->style->clipPath.applying = false;
@@ -331,6 +330,8 @@ static void _applyProperty(SvgNode* node, Shape* vg, const Box& vBox, const stri
//Apply the fill rule
vg->fill((tvg::FillRule)style->fill.fillRule);
+ //Rendering order
+ vg->order(!style->paintOrder);
//Apply node opacity
if (style->opacity < 255) vg->opacity(style->opacity);
@@ -444,9 +445,11 @@ enum class imageMimeTypeEncoding
base64 = 0x1,
utf8 = 0x2
};
+
constexpr imageMimeTypeEncoding operator|(imageMimeTypeEncoding a, imageMimeTypeEncoding b) {
return static_cast<imageMimeTypeEncoding>(static_cast<int>(a) | static_cast<int>(b));
}
+
constexpr bool operator&(imageMimeTypeEncoding a, imageMimeTypeEncoding b) {
return (static_cast<int>(a) & static_cast<int>(b));
}
@@ -755,24 +758,45 @@ static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox,
}
+static void _updateInvalidViewSize(const Scene* scene, Box& vBox, float& w, float& h, SvgViewFlag viewFlag)
+{
+ bool validWidth = (viewFlag & SvgViewFlag::Width);
+ bool validHeight = (viewFlag & SvgViewFlag::Height);
+
+ float x, y;
+ scene->bounds(&x, &y, &vBox.w, &vBox.h, false);
+ if (!validWidth && !validHeight) {
+ vBox.x = x;
+ vBox.y = y;
+ } else {
+ if (validWidth) vBox.w = w;
+ if (validHeight) vBox.h = h;
+ }
+
+ //the size would have 1x1 or percentage values.
+ if (!validWidth) w *= vBox.w;
+ if (!validHeight) h *= vBox.h;
+}
+
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
-unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath)
+unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag)
{
//TODO: aspect ratio is valid only if viewBox was set
- if (!node || (node->type != SvgNodeType::Doc)) return nullptr;
+ if (!loaderData.doc || (loaderData.doc->type != SvgNodeType::Doc)) return nullptr;
- Box vBox = {vx, vy, vw, vh};
- auto docNode = _sceneBuildHelper(node, vBox, svgPath, false, 0);
+ auto docNode = _sceneBuildHelper(loaderData.doc, vBox, svgPath, false, 0);
- if (!mathEqual(w, vw) || !mathEqual(h, vh)) {
+ if (!(viewFlag & SvgViewFlag::Viewbox)) _updateInvalidViewSize(docNode.get(), vBox, w, h, viewFlag);
+
+ if (!mathEqual(w, vBox.w) || !mathEqual(h, vBox.h)) {
Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, vBox);
docNode->transform(m);
- } else if (!mathZero(vx) || !mathZero(vy)) {
- docNode->translate(-vx, -vy);
+ } else if (!mathZero(vBox.x) || !mathZero(vBox.y)) {
+ docNode->translate(-vBox.x, -vBox.y);
}
auto viewBoxClip = Shape::gen();
@@ -786,5 +810,12 @@ unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, flo
auto root = Scene::gen();
root->push(move(compositeLayer));
+ loaderData.doc->node.doc.vx = vBox.x;
+ loaderData.doc->node.doc.vy = vBox.y;
+ loaderData.doc->node.doc.vw = vBox.w;
+ loaderData.doc->node.doc.vh = vBox.h;
+ loaderData.doc->node.doc.w = w;
+ loaderData.doc->node.doc.h = h;
+
return root;
}
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h
index 311f3c80e6..f6a60f850d 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,6 +25,6 @@
#include "tvgCommon.h"
-unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath);
+unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag);
#endif //_TVG_SVG_SCENE_BUILDER_H_
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp
index 7fb108bc21..12d20c9731 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -94,8 +94,8 @@ float svgUtilStrtof(const char *nPtr, char **endPtr)
if ((tolower(*(iter + 1)) == 'n') && (tolower(*(iter + 2)) == 'f')) iter += 3;
else goto error;
- if (tolower(*(iter + 3)) == 'i') {
- if ((tolower(*(iter + 4)) == 'n') && (tolower(*(iter + 5)) == 'i') && (tolower(*(iter + 6)) == 't') && (tolower(*(iter + 7)) == 'y')) iter += 5;
+ if (tolower(*(iter)) == 'i') {
+ if ((tolower(*(iter + 1)) == 'n') && (tolower(*(iter + 2)) == 'i') && (tolower(*(iter + 3)) == 't') && (tolower(*(iter + 4)) == 'y')) iter += 5;
else goto error;
}
if (endPtr) *endPtr = (char *)(iter);
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h
index b5e6e1bdb2..6f94367aeb 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp
index 0e2c3fa141..77467e071b 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h
index e2761ca8da..7333bb09fb 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp b/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp
index 01a39b6e17..2b89d6bb59 100644
--- a/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp
+++ b/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include <memory.h>
#ifdef _WIN32
@@ -357,27 +358,45 @@ static bool _parsePicture(TvgBinBlock block, Paint* paint)
{
auto picture = static_cast<Picture*>(paint);
- //Case1: Image Picture
- if (block.type == TVG_TAG_PICTURE_RAW_IMAGE) {
- if (block.length < 2 * SIZE(uint32_t)) return false;
+ switch (block.type) {
+ case TVG_TAG_PICTURE_RAW_IMAGE: {
+ if (block.length < 2 * SIZE(uint32_t)) return false;
- auto ptr = block.data;
- uint32_t w, h;
+ auto ptr = block.data;
+ uint32_t w, h;
- READ_UI32(&w, ptr);
- ptr += SIZE(uint32_t);
- READ_UI32(&h, ptr);
- ptr += SIZE(uint32_t);
+ READ_UI32(&w, ptr);
+ ptr += SIZE(uint32_t);
+ READ_UI32(&h, ptr);
+ ptr += SIZE(uint32_t);
- auto size = w * h * SIZE(uint32_t);
- if (block.length != 2 * SIZE(uint32_t) + size) return false;
+ auto size = w * h * SIZE(uint32_t);
+ if (block.length != 2 * SIZE(uint32_t) + size) return false;
- picture->load((uint32_t*) ptr, w, h, true);
- return true;
- }
+ picture->load((uint32_t*) ptr, w, h, true);
- //Case2: Base Paint Properties
- if (_parsePaintProperty(block, picture)) return true;
+ return true;
+ }
+ case TVG_TAG_PICTURE_MESH: {
+ if (block.length < 1 * SIZE(uint32_t)) return false;
+
+ auto ptr = block.data;
+ uint32_t meshCnt;
+ READ_UI32(&meshCnt, ptr);
+ ptr += SIZE(uint32_t);
+
+ auto size = meshCnt * SIZE(Polygon);
+ if (block.length != SIZE(uint32_t) + size) return false;
+
+ picture->mesh((Polygon*) ptr, meshCnt);
+
+ return true;
+ }
+ //Base Paint Properties
+ default: {
+ if (_parsePaintProperty(block, picture)) return true;
+ }
+ }
//Vector Picture won't be requested since Saver replaces it with the Scene
return false;
@@ -414,7 +433,7 @@ static Paint* _parsePaint(TvgBinBlock baseBlock)
auto ptr = baseBlock.data;
- //2. Read Subsquent properties of the current paint.
+ //2. Read Subsequent properties of the current paint.
while (ptr < baseBlock.end) {
auto block = _readBlock(ptr);
if (block.end > baseBlock.end) return paint;
diff --git a/thirdparty/thorvg/src/loaders/tvg/tvgTvgCommon.h b/thirdparty/thorvg/src/loaders/tvg/tvgTvgCommon.h
index a0762d0fcc..29fa1025b0 100644
--- a/thirdparty/thorvg/src/loaders/tvg/tvgTvgCommon.h
+++ b/thirdparty/thorvg/src/loaders/tvg/tvgTvgCommon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.cpp b/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.cpp
index 95d629d1f6..82c578e6d4 100644
--- a/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include <memory.h>
#include <fstream>
#include "tvgLoader.h"
diff --git a/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.h b/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.h
index 3ae841aa85..b98dff83b0 100644
--- a/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.h
+++ b/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp b/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp
index 57a21dcce1..1098570140 100644
--- a/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp
+++ b/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgMath.h"
#include "tvgSaveModule.h"
#include "tvgTvgSaver.h"
@@ -169,7 +170,7 @@ bool TvgSaver::saveEncoding(const std::string& path)
memcpy(uncompressed, &compressedSizeBits, TVG_HEADER_COMPRESSED_SIZE_BITS);
//Good optimization, flush to file.
- auto fp = _fopen(path.c_str(), "w+");
+ auto fp = _fopen(path.c_str(), "wb+");
if (!fp) goto fail;
//write header
@@ -192,7 +193,7 @@ fail:
bool TvgSaver::flushTo(const std::string& path)
{
- auto fp = _fopen(path.c_str(), "w+");
+ auto fp = _fopen(path.c_str(), "wb+");
if (!fp) return false;
if (fwrite(buffer.data, SIZE(uint8_t), buffer.count, fp) == 0) {
@@ -355,7 +356,7 @@ TvgBinCounter TvgSaver::serializeChild(const Paint* parent, const Paint* child,
TvgBinCounter TvgSaver::serializeScene(const Scene* scene, const Matrix* pTransform, const Matrix* cTransform)
{
- auto it = this->iterator(scene);
+ auto it = IteratorAccessor::iterator(scene);
if (it->count() == 0) {
delete(it);
return 0;
@@ -567,7 +568,7 @@ TvgBinCounter TvgSaver::serializeShape(const Shape* shape, const Matrix* pTransf
/* Picture has either a vector scene or a bitmap. */
TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* pTransform, const Matrix* cTransform)
{
- auto it = this->iterator(picture);
+ auto it = IteratorAccessor::iterator(picture);
//Case - Vector Scene:
if (it->count() == 1) {
@@ -609,6 +610,20 @@ TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* p
cnt += writeData(pixels, imgSize);
cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter);
+ //mesh: currently only available in bitmap image.
+ const Polygon* triangles = nullptr;
+ auto triangleCnt = picture->mesh(&triangles);
+ if (triangles && triangleCnt > 0) {
+ TvgBinCounter triangleCntSize = SIZE(triangleCnt);
+ TvgBinCounter trianglesSize = triangleCnt * SIZE(triangles[0]);
+
+ writeTag(TVG_TAG_PICTURE_MESH);
+ writeCount(triangleCntSize + trianglesSize);
+ cnt += writeData(&triangleCnt, triangleCntSize);
+ cnt += writeData(triangles, trianglesSize);
+ cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter);
+ }
+
//Bitmap picture needs the transform info.
cnt += writeTransform(cTransform, TVG_TAG_PAINT_TRANSFORM);
diff --git a/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.h b/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.h
index 4acb35e76a..0824475923 100644
--- a/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.h
+++ b/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#ifndef _TVG_TVGSAVER_H_
#define _TVG_TVGSAVER_H_
diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh
index 34bb3b8e59..4eb7bf47ed 100755
--- a/thirdparty/thorvg/update-thorvg.sh
+++ b/thirdparty/thorvg/update-thorvg.sh
@@ -1,9 +1,9 @@
-VERSION=0.8.4
+VERSION=0.9.0
rm -rf AUTHORS inc LICENSE src *.zip
curl -L -O https://github.com/thorvg/thorvg/archive/v$VERSION.zip
bsdtar --strip-components=1 -xvf *.zip
rm *.zip
-rm -rf .github docs pc res test tools tvgcompat .git* *.md *.txt wasm_build.sh
+rm -rf .github docs pc res test tools tvgcompat .git* *.md *.txt wasm_build.sh CODEOWNERS
find . -type f -name 'meson.build' -delete
rm -rf src/bin src/bindings src/examples src/wasm
rm -rf src/lib/gl_engine src/loaders/external_jpg src/loaders/png