summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelipe Augusto Marques <felaugmar@gmail.com>2023-06-14 20:27:56 -0300
committerFelipe Augusto Marques <felaugmar@gmail.com>2023-06-23 00:43:43 -0300
commit26eb3db234ec6e16a954f34f6aa7e68e7a926848 (patch)
tree1a6839163663aa195858edef5900c3be8a28475d
parentf9fc77bbe474e33967dfde69a2efa442f465fae2 (diff)
downloadredot-engine-26eb3db234ec6e16a954f34f6aa7e68e7a926848.tar.gz
Added Image's `load_svg_from_(buffer|string)`
No core dependency to the svg module.
-rw-r--r--core/io/image.cpp26
-rw-r--r--core/io/image.h5
-rw-r--r--doc/classes/Image.xml19
-rw-r--r--editor/editor_themes.cpp3
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp18
-rw-r--r--modules/svg/image_loader_svg.cpp22
-rw-r--r--modules/svg/image_loader_svg.h12
-rw-r--r--platform/android/export/export_plugin.cpp5
-rw-r--r--platform/ios/export/export_plugin.cpp3
-rw-r--r--platform/linuxbsd/export/export_plugin.cpp5
-rw-r--r--platform/macos/export/export_plugin.cpp5
-rw-r--r--platform/uwp/export/export_plugin.cpp3
-rw-r--r--platform/web/export/export_plugin.cpp5
-rw-r--r--platform/windows/export/export_plugin.cpp5
-rw-r--r--scene/resources/default_theme/default_theme.cpp4
15 files changed, 96 insertions, 44 deletions
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 9bb987b670..1711e4c265 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -3004,6 +3004,7 @@ ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr;
+ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr;
void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr;
@@ -3476,6 +3477,9 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer);
ClassDB::bind_method(D_METHOD("load_bmp_from_buffer", "buffer"), &Image::load_bmp_from_buffer);
+ ClassDB::bind_method(D_METHOD("load_svg_from_buffer", "buffer", "scale"), &Image::load_svg_from_buffer, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("load_svg_from_string", "svg_str", "scale"), &Image::load_svg_from_string, DEFVAL(1.0));
+
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data");
BIND_CONSTANT(MAX_WIDTH);
@@ -3825,6 +3829,28 @@ Error Image::load_bmp_from_buffer(const Vector<uint8_t> &p_array) {
return _load_from_buffer(p_array, _bmp_mem_loader_func);
}
+Error Image::load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale) {
+ ERR_FAIL_NULL_V_MSG(
+ _svg_scalable_mem_loader_func,
+ ERR_UNAVAILABLE,
+ "The SVG module isn't enabled. Recompile the Godot editor or export template binary with the `module_svg_enabled=yes` SCons option.");
+
+ int buffer_size = p_array.size();
+
+ ERR_FAIL_COND_V(buffer_size == 0, ERR_INVALID_PARAMETER);
+
+ Ref<Image> image = _svg_scalable_mem_loader_func(p_array.ptr(), buffer_size, scale);
+ ERR_FAIL_COND_V(!image.is_valid(), ERR_PARSE_ERROR);
+
+ copy_internals_from(image);
+
+ return OK;
+}
+
+Error Image::load_svg_from_string(const String &p_svg_str, float scale) {
+ return load_svg_from_buffer(p_svg_str.to_utf8_buffer(), scale);
+}
+
void Image::convert_rg_to_ra_rgba8() {
ERR_FAIL_COND(format != FORMAT_RGBA8);
ERR_FAIL_COND(!data.size());
diff --git a/core/io/image.h b/core/io/image.h
index 8e353a8bb7..f877b00ee6 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -48,6 +48,7 @@ typedef Vector<uint8_t> (*SavePNGBufferFunc)(const Ref<Image> &p_img);
typedef Error (*SaveJPGFunc)(const String &p_path, const Ref<Image> &p_img, float p_quality);
typedef Vector<uint8_t> (*SaveJPGBufferFunc)(const Ref<Image> &p_img, float p_quality);
typedef Ref<Image> (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size);
+typedef Ref<Image> (*ScalableImageMemLoadFunc)(const uint8_t *p_data, int p_size, float p_scale);
typedef Error (*SaveWebPFunc)(const String &p_path, const Ref<Image> &p_img, const bool p_lossy, const float p_quality);
typedef Vector<uint8_t> (*SaveWebPBufferFunc)(const Ref<Image> &p_img, const bool p_lossy, const float p_quality);
@@ -148,6 +149,7 @@ public:
static ImageMemLoadFunc _webp_mem_loader_func;
static ImageMemLoadFunc _tga_mem_loader_func;
static ImageMemLoadFunc _bmp_mem_loader_func;
+ static ScalableImageMemLoadFunc _svg_scalable_mem_loader_func;
static void (*_image_compress_bc_func)(Image *, UsedChannels p_channels);
static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels);
@@ -401,6 +403,9 @@ public:
Error load_tga_from_buffer(const Vector<uint8_t> &p_array);
Error load_bmp_from_buffer(const Vector<uint8_t> &p_array);
+ Error load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale = 1.0);
+ Error load_svg_from_string(const String &p_svg_str, float scale = 1.0);
+
void convert_rg_to_ra_rgba8();
void convert_ra_rgba8_to_rg();
void convert_rgba8_to_bgra8();
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 130f848a73..6aebd025cf 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -333,6 +333,25 @@
Loads an image from the binary contents of a PNG file.
</description>
</method>
+ <method name="load_svg_from_buffer">
+ <return type="int" enum="Error" />
+ <param index="0" name="buffer" type="PackedByteArray" />
+ <param index="1" name="scale" type="float" default="1.0" />
+ <description>
+ Loads an image from the UTF-8 binary contents of an [b]uncompressed[/b] SVG file ([b].svg[/b]).
+ [b]Note:[/b] Beware when using compressed SVG files (like [b].svgz[/b]), they need to be [code]decompressed[/code] before loading.
+ [b]Note:[/b] This method is only available in engine builds with the SVG module enabled. By default, the SVG module is enabled, but it can be disabled at build-time using the [code]module_svg_enabled=no[/code] SCons option.
+ </description>
+ </method>
+ <method name="load_svg_from_string">
+ <return type="int" enum="Error" />
+ <param index="0" name="svg_str" type="String" />
+ <param index="1" name="scale" type="float" default="1.0" />
+ <description>
+ Loads an image from the string contents of a SVG file ([b].svg[/b]).
+ [b]Note:[/b] This method is only available in engine builds with the SVG module enabled. By default, the SVG module is enabled, but it can be disabled at build-time using the [code]module_svg_enabled=no[/code] SCons option.
+ </description>
+ </method>
<method name="load_tga_from_buffer">
<return type="int" enum="Error" />
<param index="0" name="buffer" type="PackedByteArray" />
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 2ff53dd9f1..f5d800cca8 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -244,8 +244,7 @@ static Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float
// Generating upsampled icons is slower, and the benefit is hardly visible
// with integer editor scales.
const bool upsample = !Math::is_equal_approx(Math::round(p_scale), p_scale);
- ImageLoaderSVG img_loader;
- Error err = img_loader.create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_colors);
+ Error err = ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_colors);
ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in editor theme.");
if (p_saturation != 1.0) {
img->adjust_bcs(1.0, 1.0, p_saturation);
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index eeb0fd5f66..b2e40fa6c0 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -43,11 +43,6 @@
#include "editor/project_settings_editor.h"
#include "scene/gui/menu_button.h"
-#include "modules/modules_enabled.gen.h" // For svg.
-#ifdef MODULE_SVG_ENABLED
-#include "modules/svg/image_loader_svg.h"
-#endif
-
static inline void setup_http_request(HTTPRequest *request) {
request->set_use_threads(EDITOR_DEF("asset_library/use_threads", true));
@@ -775,18 +770,9 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB
image->copy_internals_from(Image::_webp_mem_loader_func(r, len));
} else if ((memcmp(&r[0], &bmp_signature[0], 2) == 0) && Image::_bmp_mem_loader_func) {
image->copy_internals_from(Image::_bmp_mem_loader_func(r, len));
+ } else if (Image::_svg_scalable_mem_loader_func) {
+ image->copy_internals_from(Image::_svg_scalable_mem_loader_func(r, len, 1.0));
}
-#ifdef MODULE_SVG_ENABLED
- else {
- ImageLoaderSVG svg_loader;
- Ref<Image> img = Ref<Image>(memnew(Image));
- Error err = svg_loader.create_image_from_utf8_buffer(img, image_data, 1.0, false);
-
- if (err == OK) {
- image->copy_internals_from(img);
- }
- }
-#endif
}
if (!image->is_empty()) {
diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp
index ad7feeda49..7639155914 100644
--- a/modules/svg/image_loader_svg.cpp
+++ b/modules/svg/image_loader_svg.cpp
@@ -67,12 +67,22 @@ void ImageLoaderSVG::_replace_color_property(const HashMap<Color, Color> &p_colo
}
}
-Error ImageLoaderSVG::create_image_from_utf8_buffer(Ref<Image> p_image, const PackedByteArray &p_buffer, float p_scale, bool p_upsample) {
+Ref<Image> ImageLoaderSVG::load_mem_svg(const uint8_t *p_svg, int p_size, float p_scale) {
+ Ref<Image> img;
+ img.instantiate();
+
+ Error err = create_image_from_utf8_buffer(img, p_svg, p_size, p_scale, false);
+ ERR_FAIL_COND_V(err, Ref<Image>());
+
+ return img;
+}
+
+Error ImageLoaderSVG::create_image_from_utf8_buffer(Ref<Image> p_image, const uint8_t *p_buffer, int p_buffer_size, float p_scale, bool p_upsample) {
ERR_FAIL_COND_V_MSG(Math::is_zero_approx(p_scale), ERR_INVALID_PARAMETER, "ImageLoaderSVG: Can't load SVG with a scale of 0.");
std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
- tvg::Result result = picture->load((const char *)p_buffer.ptr(), p_buffer.size(), "svg", true);
+ tvg::Result result = picture->load((const char *)p_buffer, p_buffer_size, "svg", true);
if (result != tvg::Result::Success) {
return ERR_INVALID_DATA;
}
@@ -142,6 +152,10 @@ Error ImageLoaderSVG::create_image_from_utf8_buffer(Ref<Image> p_image, const Pa
return OK;
}
+Error ImageLoaderSVG::create_image_from_utf8_buffer(Ref<Image> p_image, const PackedByteArray &p_buffer, float p_scale, bool p_upsample) {
+ return create_image_from_utf8_buffer(p_image, p_buffer.ptr(), p_buffer.size(), p_scale, p_upsample);
+}
+
Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, const HashMap<Color, Color> &p_color_map) {
if (p_color_map.size()) {
_replace_color_property(p_color_map, "stop-color=\"", p_string);
@@ -179,3 +193,7 @@ Error ImageLoaderSVG::load_image(Ref<Image> p_image, Ref<FileAccess> p_fileacces
}
return OK;
}
+
+ImageLoaderSVG::ImageLoaderSVG() {
+ Image::_svg_scalable_mem_loader_func = load_mem_svg;
+}
diff --git a/modules/svg/image_loader_svg.h b/modules/svg/image_loader_svg.h
index e0d2849a62..90e9458c37 100644
--- a/modules/svg/image_loader_svg.h
+++ b/modules/svg/image_loader_svg.h
@@ -36,16 +36,22 @@
class ImageLoaderSVG : public ImageFormatLoader {
static HashMap<Color, Color> forced_color_map;
- void _replace_color_property(const HashMap<Color, Color> &p_color_map, const String &p_prefix, String &r_string);
+ static void _replace_color_property(const HashMap<Color, Color> &p_color_map, const String &p_prefix, String &r_string);
+
+ static Ref<Image> load_mem_svg(const uint8_t *p_svg, int p_size, float p_scale);
public:
static void set_forced_color_map(const HashMap<Color, Color> &p_color_map);
- Error create_image_from_utf8_buffer(Ref<Image> p_image, const PackedByteArray &p_buffer, float p_scale, bool p_upsample);
- Error create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, const HashMap<Color, Color> &p_color_map);
+ static Error create_image_from_utf8_buffer(Ref<Image> p_image, const uint8_t *p_buffer, int p_buffer_size, float p_scale, bool p_upsample);
+ static Error create_image_from_utf8_buffer(Ref<Image> p_image, const PackedByteArray &p_buffer, float p_scale, bool p_upsample);
+
+ static Error create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, const HashMap<Color, Color> &p_color_map);
virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, BitField<ImageFormatLoader::LoaderFlags> p_flags, float p_scale) override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
+
+ ImageLoaderSVG();
};
#endif // IMAGE_LOADER_SVG_H
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 5d31c4911c..5a50aa9081 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -3291,11 +3291,10 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
Ref<Image> img = memnew(Image);
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
- ImageLoaderSVG img_loader;
- img_loader.create_image_from_string(img, _android_logo_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _android_logo_svg, EDSCALE, upsample, false);
logo = ImageTexture::create_from_image(img);
- img_loader.create_image_from_string(img, _android_run_icon_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _android_run_icon_svg, EDSCALE, upsample, false);
run_icon = ImageTexture::create_from_image(img);
#endif
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index 1b9b02d0e0..4860ef0ad7 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -1970,8 +1970,7 @@ EditorExportPlatformIOS::EditorExportPlatformIOS() {
Ref<Image> img = memnew(Image);
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
- ImageLoaderSVG img_loader;
- img_loader.create_image_from_string(img, _ios_logo_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _ios_logo_svg, EDSCALE, upsample, false);
logo = ImageTexture::create_from_image(img);
#endif
diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp
index f74bdf3516..40151b1a02 100644
--- a/platform/linuxbsd/export/export_plugin.cpp
+++ b/platform/linuxbsd/export/export_plugin.cpp
@@ -521,11 +521,10 @@ EditorExportPlatformLinuxBSD::EditorExportPlatformLinuxBSD() {
Ref<Image> img = memnew(Image);
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
- ImageLoaderSVG img_loader;
- img_loader.create_image_from_string(img, _linuxbsd_logo_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _linuxbsd_logo_svg, EDSCALE, upsample, false);
set_logo(ImageTexture::create_from_image(img));
- img_loader.create_image_from_string(img, _linuxbsd_run_icon_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _linuxbsd_run_icon_svg, EDSCALE, upsample, false);
run_icon = ImageTexture::create_from_image(img);
#endif
diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp
index 2d185db812..0dc6d0dcee 100644
--- a/platform/macos/export/export_plugin.cpp
+++ b/platform/macos/export/export_plugin.cpp
@@ -2442,11 +2442,10 @@ EditorExportPlatformMacOS::EditorExportPlatformMacOS() {
Ref<Image> img = memnew(Image);
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
- ImageLoaderSVG img_loader;
- img_loader.create_image_from_string(img, _macos_logo_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _macos_logo_svg, EDSCALE, upsample, false);
logo = ImageTexture::create_from_image(img);
- img_loader.create_image_from_string(img, _macos_run_icon_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _macos_run_icon_svg, EDSCALE, upsample, false);
run_icon = ImageTexture::create_from_image(img);
#endif
diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp
index 0332fbf718..6b3e650118 100644
--- a/platform/uwp/export/export_plugin.cpp
+++ b/platform/uwp/export/export_plugin.cpp
@@ -515,8 +515,7 @@ EditorExportPlatformUWP::EditorExportPlatformUWP() {
Ref<Image> img = memnew(Image);
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
- ImageLoaderSVG img_loader;
- img_loader.create_image_from_string(img, _uwp_logo_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _uwp_logo_svg, EDSCALE, upsample, false);
logo = ImageTexture::create_from_image(img);
#endif
diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp
index 0bc3b92f09..d5834d08d6 100644
--- a/platform/web/export/export_plugin.cpp
+++ b/platform/web/export/export_plugin.cpp
@@ -666,11 +666,10 @@ EditorExportPlatformWeb::EditorExportPlatformWeb() {
Ref<Image> img = memnew(Image);
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
- ImageLoaderSVG img_loader;
- img_loader.create_image_from_string(img, _web_logo_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _web_logo_svg, EDSCALE, upsample, false);
logo = ImageTexture::create_from_image(img);
- img_loader.create_image_from_string(img, _web_run_icon_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _web_run_icon_svg, EDSCALE, upsample, false);
run_icon = ImageTexture::create_from_image(img);
#endif
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index b521a649be..0ef07c3275 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -1011,11 +1011,10 @@ EditorExportPlatformWindows::EditorExportPlatformWindows() {
Ref<Image> img = memnew(Image);
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
- ImageLoaderSVG img_loader;
- img_loader.create_image_from_string(img, _windows_logo_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _windows_logo_svg, EDSCALE, upsample, false);
set_logo(ImageTexture::create_from_image(img));
- img_loader.create_image_from_string(img, _windows_run_icon_svg, EDSCALE, upsample, false);
+ ImageLoaderSVG::create_image_from_string(img, _windows_run_icon_svg, EDSCALE, upsample, false);
run_icon = ImageTexture::create_from_image(img);
#endif
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 1bfcf8d3ac..9cec99cb22 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -83,8 +83,8 @@ static Ref<ImageTexture> generate_icon(int p_index) {
// Generating upsampled icons is slower, and the benefit is hardly visible
// with integer scales.
const bool upsample = !Math::is_equal_approx(Math::round(scale), scale);
- ImageLoaderSVG img_loader;
- Error err = img_loader.create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, HashMap<Color, Color>());
+
+ Error err = ImageLoaderSVG::create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, HashMap<Color, Color>());
ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in default theme.");
#else
// If the SVG module is disabled, we can't really display the UI well, but at least we won't crash.