Skip to content

Commit

Permalink
Support compress svg file option
Browse files Browse the repository at this point in the history
(Internal update) SVGSprite no longer loads the same svg file multiple times
  • Loading branch information
heppocogne committed Jan 11, 2023
1 parent 2b1dc11 commit af83d11
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 35 deletions.
4 changes: 2 additions & 2 deletions addons/svg_sprite/plugin.cfg
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[plugin]

name="SVGSprite"
description=""
description="Rasterize svg dynamically"
author="heppocogne"
version="1.3.1"
version="1.3.2"
script="plugin.gd"
46 changes: 43 additions & 3 deletions addons/svg_sprite/plugin.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ tool
extends EditorPlugin

const _rawsvg_root:="res://_rawsvg"
const compress_setting:="svgsprite/compress"
var res_file_sys:EditorFileSystem
var file_sys:FileSystemDock
var _compress_setting_cache:bool


func _enter_tree():
Expand All @@ -13,13 +15,22 @@ func _enter_tree():
file_sys=get_editor_interface().get_file_system_dock()
file_sys.connect("file_removed",self,"_on_file_removed")
file_sys.connect("files_moved",self,"_on_files_moved")
ProjectSettings.connect("project_settings_changed",self,"_on_project_settings_changed")

var dir:=Directory.new()
if !dir.dir_exists(_rawsvg_root):
dir.make_dir(_rawsvg_root)
pick_svg_files("res://")

add_custom_type("SVGSprite","Node2D",preload("res://addons/svg_sprite/svgsprite_library.gdns"),preload("res://addons/svg_sprite/icon_svgsprite.svg"))
add_custom_type("SVGSprite",
"Node2D",
preload("res://addons/svg_sprite/svgsprite_library.gdns"),
preload("res://addons/svg_sprite/icon_svgsprite.svg"))

if !ProjectSettings.has_setting(compress_setting):
ProjectSettings.set_setting(compress_setting,false)

_compress_setting_cache=ProjectSettings.get_setting(compress_setting)


func _exit_tree():
Expand Down Expand Up @@ -56,11 +67,25 @@ func get_rawsvg_path(path:String)->String:
return _rawsvg_root.plus_file(path.get_file()+"-"+path.get_basename().sha256_text()+".rawsvg")


func get_rawsvgz_path(path:String)->String:
return _rawsvg_root.plus_file(path.get_file()+"-"+path.get_basename().sha256_text()+".rawsvgz")


func _on_resources_reimported(paths:PoolStringArray):
for path in paths:
if path.ends_with(".svg"):
var d:=Directory.new()
d.copy(path,get_rawsvg_path(path))
if ProjectSettings.get_setting(compress_setting):
var f:=File.new()
var svg:String
if f.open(path,File.READ)==OK:
svg=f.get_as_text()
f.close()
if f.open_compressed(get_rawsvgz_path(path),File.WRITE,File.COMPRESSION_DEFLATE)==OK:
f.store_string(svg)
f.close()
else:
var d:=Directory.new()
d.copy(path,get_rawsvg_path(path))


func _on_file_removed(path:String):
Expand All @@ -73,3 +98,18 @@ func _on_files_moved(old_path:String,new_path:String):
if old_path.ends_with(".svg"):
var d:=Directory.new()
d.rename(get_rawsvg_path(old_path),get_rawsvg_path(new_path))


func _on_project_settings_changed():
if _compress_setting_cache!=ProjectSettings.get_setting(compress_setting):
var dir:=Directory.new()
dir.change_dir(_rawsvg_root)
dir.list_dir_begin(true,true)
var item_name:=dir.get_next()
while item_name!="":
dir.remove(item_name)
item_name=dir.get_next()
dir.list_dir_end()

pick_svg_files("res://")
_compress_setting_cache=ProjectSettings.get_setting(compress_setting)
3 changes: 3 additions & 0 deletions cpp/src/gdlibrary.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#include "svgsprite.h"
#include "rawsvg_loader.h"

extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o)
{
godot::Godot::gdnative_init(o);
godot::RawSvgLoader::on_library_init();
}

extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o)
{
godot::RawSvgLoader::on_library_terminate();
godot::Godot::gdnative_terminate(o);
}

Expand Down
57 changes: 57 additions & 0 deletions cpp/src/rawsvg_loader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "rawsvg_loader.h"
#include <File.hpp>

using namespace godot;

RawSvgLoader *RawSvgLoader::singleton = nullptr;

void RawSvgLoader::on_library_init()
{
if (singleton != nullptr)
delete singleton;
singleton = new RawSvgLoader();
}

void RawSvgLoader::on_library_terminate()
{
delete singleton;
singleton = nullptr;
}

RawSvgLoader *RawSvgLoader::get_singleton()
{
return singleton;
}

RawSvgLoader::~RawSvgLoader()
{
for (auto &pair : docs_cache)
docs_cache[pair.first] = nullptr;
}

std::unique_ptr<lunasvg::Document> &RawSvgLoader::load(const String &path)
{
if (docs_cache.count(path) == 0)
{
Ref<File> ref_f = File::_new();
Error err;
if (path.ends_with(".rawsvg"))
err = ref_f->open(path, File::READ);
else if (path.ends_with(".rawsvgz"))
err = ref_f->open_compressed(path, File::READ, File::COMPRESSION_DEFLATE);

if (err == godot::Error::OK)
{
char *buf = ref_f->get_as_text().alloc_c_string();
docs_cache[path] = lunasvg::Document::loadFromData(const_cast<const char *>(buf));
godot::api->godot_free(buf);
if (!docs_cache[path])
{
Godot::print_error("invalid svg file:" + path, __func__, __FILE__, __LINE__);
docs_cache[path] = nullptr;
}
}
}

return docs_cache[path];
}
28 changes: 28 additions & 0 deletions cpp/src/rawsvg_loader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef RAWSVG_LOADER_H
#define RAWSVG_LOADER_H

#include <Godot.hpp>

#include <map>
#include <memory>
#include <lunasvg.h>

namespace godot
{
class RawSvgLoader
{
static RawSvgLoader *singleton;
RawSvgLoader() {}
std::map<String, std::unique_ptr<lunasvg::Document>> docs_cache;

public:
static void on_library_init();
static void on_library_terminate();
static RawSvgLoader *get_singleton();
~RawSvgLoader();

std::unique_ptr<lunasvg::Document> &load(const String &path);
};
};

#endif
44 changes: 15 additions & 29 deletions cpp/src/svgsprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <Image.hpp>
#include <Vector2.hpp>
#include <Transform2D.hpp>
// #include <ProjectSettings.hpp>
#include <ProjectSettings.hpp>
#include <GodotGlobal.hpp>
#ifndef EDITOR_FEATURE_DISABLED
#include <Engine.hpp>
Expand All @@ -13,6 +13,7 @@

#include <algorithm>
#include <cstring>
#include "rawsvg_loader.h"

using namespace godot;

Expand Down Expand Up @@ -46,11 +47,10 @@ void SVGSprite::_register_methods()
}

SVGSprite::SVGSprite() : _cache_dirty(true),
#ifndef EDITOR_FEATURE_DISABLED
_svg_doc(nullptr),
_ref_texture(ImageTexture::_new()),
#ifndef EDITOR_FEATURE_DISABLED
_ref_prerasterized(nullptr)
#else
_ref_texture(ImageTexture::_new())
#endif
{
}
Expand Down Expand Up @@ -181,36 +181,17 @@ void SVGSprite::_notification(int what)
void SVGSprite::set_svg_file(String p_svg_file)
{
svg_file = p_svg_file;

if (svg_file == "")
{
#ifndef EDITOR_FEATURE_DISABLED
if (svg_file == "")
_ref_prerasterized = nullptr;
#endif
_svg_doc = nullptr;
}
else
{
#ifndef EDITOR_FEATURE_DISABLED
_ref_prerasterized = ResourceLoader::get_singleton()->load(svg_file);
#endif
Ref<File> ref_f = File::_new();
const String rawsvg_file = get_rawsvg_path(svg_file);
if (ref_f->open(rawsvg_file, File::READ) == godot::Error::OK)
{
char *buf = ref_f->get_as_text().alloc_c_string();
_svg_doc = lunasvg::Document::loadFromData(const_cast<const char *>(buf));
godot::api->godot_free(buf);
if (!_svg_doc)
Godot::print_error("invalid svg file:" + rawsvg_file, __func__, __FILE__, __LINE__);
}
else
{
_svg_doc = nullptr;
Godot::print_error(String("cannot open file (error code=") + Variant((int)ref_f->get_error()) + String("):") + rawsvg_file, __func__, __FILE__, __LINE__);
}
}
if ((bool)ProjectSettings::get_singleton()->get_setting("svgsprite/compress") == false)
_svg_doc = RawSvgLoader::get_singleton()->load(get_rawsvg_path(p_svg_file)).get();
else
_svg_doc = RawSvgLoader::get_singleton()->load(get_rawsvgz_path(p_svg_file)).get();
_cache_dirty = true;
#endif
update();
}

Expand Down Expand Up @@ -257,3 +238,8 @@ String SVGSprite::get_rawsvg_path(String path)
{
return String(_rawsvg_root).plus_file(path.get_file() + "-" + path.get_basename().sha256_text() + ".rawsvg");
}

String SVGSprite::get_rawsvgz_path(String path)
{
return String(_rawsvg_root).plus_file(path.get_file() + "-" + path.get_basename().sha256_text() + ".rawsvgz");
}
3 changes: 2 additions & 1 deletion cpp/src/svgsprite.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace godot
{
GODOT_CLASS(SVGSprite, Node2D)

std::unique_ptr<lunasvg::Document> _svg_doc;
lunasvg::Document *_svg_doc;
// rotation and scaling
Transform2D _transform;
PoolByteArray _bitmap_byte_array;
Expand All @@ -36,6 +36,7 @@ namespace godot

static void _register_methods();
static String get_rawsvg_path(String path);
static String get_rawsvgz_path(String path);

SVGSprite();
~SVGSprite();
Expand Down
4 changes: 4 additions & 0 deletions project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ common/enable_pause_aware_picking=true
[rendering]

environment/default_environment="res://default_env.tres"

[svgsprite]

compress=true

0 comments on commit af83d11

Please sign in to comment.