summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp96
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.h1
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp3
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp1
-rw-r--r--modules/gdscript/gdscript_parser.cpp8
-rw-r--r--modules/gdscript/icons/GDScriptInternal.svg1
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp13
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h1
-rw-r--r--modules/mono/csharp_script.cpp12
-rw-r--r--modules/mono/csharp_script.h1
-rw-r--r--modules/mono/godotsharp_dirs.cpp7
-rw-r--r--modules/pvr/SCsub38
-rw-r--r--modules/pvr/config.py6
-rw-r--r--modules/pvr/image_compress_pvrtc.cpp88
-rw-r--r--modules/pvr/image_compress_pvrtc.h36
-rw-r--r--modules/pvr/register_types.cpp48
-rw-r--r--modules/pvr/register_types.h37
-rw-r--r--modules/pvr/texture_loader_pvr.cpp608
-rw-r--r--modules/pvr/texture_loader_pvr.h48
-rw-r--r--modules/svg/SCsub56
-rw-r--r--modules/svg/image_loader_svg.cpp190
-rw-r--r--modules/svg/image_loader_svg.h34
-rw-r--r--modules/svg/register_types.cpp10
-rw-r--r--modules/text_server_adv/text_server_adv.cpp36
-rw-r--r--modules/text_server_adv/text_server_adv.h3
-rw-r--r--modules/text_server_fb/text_server_fb.cpp29
-rw-r--r--modules/text_server_fb/text_server_fb.h3
-rw-r--r--modules/visual_script/editor/visual_script_editor.cpp9
-rw-r--r--modules/visual_script/icons/VisualScriptInternal.svg1
29 files changed, 347 insertions, 1077 deletions
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index 6425123e63..5cc295bbab 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -60,7 +60,9 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
bool in_keyword = false;
bool in_word = false;
bool in_function_name = false;
+ bool in_lambda = false;
bool in_variable_declaration = false;
+ bool in_signal_declaration = false;
bool in_function_args = false;
bool in_member_variable = false;
bool in_node_path = false;
@@ -105,12 +107,15 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
/* color regions */
if (is_a_symbol || in_region != -1) {
int from = j;
- for (; from < line_length; from++) {
- if (str[from] == '\\') {
- from++;
- continue;
+
+ if (in_region == -1) {
+ for (; from < line_length; from++) {
+ if (str[from] == '\\') {
+ from++;
+ continue;
+ }
+ break;
}
- break;
}
if (from != line_length) {
@@ -142,6 +147,12 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
/* check if it's the whole line */
if (end_key_length == 0 || color_regions[c].line_only || from + end_key_length > line_length) {
+ if (from + end_key_length > line_length) {
+ // If it's key length and there is a '\', dont skip to highlight esc chars.
+ if (str.find("\\", from) >= 0) {
+ break;
+ }
+ }
prev_color = color_regions[in_region].color;
highlighter_info["color"] = color_regions[c].color;
color_map[j] = highlighter_info;
@@ -161,13 +172,25 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
/* if we are in one find the end key */
if (in_region != -1) {
+ Color region_color = color_regions[in_region].color;
+ if (in_node_path && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) {
+ region_color = node_path_color;
+ }
+
+ prev_color = region_color;
+ highlighter_info["color"] = region_color;
+ color_map[j] = highlighter_info;
+
/* search the line */
int region_end_index = -1;
int end_key_length = color_regions[in_region].end_key.length();
const char32_t *end_key = color_regions[in_region].end_key.get_data();
for (; from < line_length; from++) {
if (line_length - from < end_key_length) {
- break;
+ // Don't break if '\' to highlight esc chars.
+ if (str.find("\\", from) < 0) {
+ break;
+ }
}
if (!is_symbol(str[from])) {
@@ -175,7 +198,16 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
}
if (str[from] == '\\') {
+ Dictionary escape_char_highlighter_info;
+ escape_char_highlighter_info["color"] = symbol_color;
+ color_map[from] = escape_char_highlighter_info;
+
from++;
+
+ Dictionary region_continue_highlighter_info;
+ prev_color = region_color;
+ region_continue_highlighter_info["color"] = region_color;
+ color_map[from + 1] = region_continue_highlighter_info;
continue;
}
@@ -192,10 +224,6 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
}
}
- prev_color = color_regions[in_region].color;
- highlighter_info["color"] = color_regions[in_region].color;
- color_map[j] = highlighter_info;
-
previous_type = REGION;
previous_text = "";
previous_column = j;
@@ -289,20 +317,36 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
}
if (!in_function_name && in_word && !in_keyword) {
- int k = j;
- while (k < str.length() && !is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
- k++;
- }
+ if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::SIGNAL)) {
+ in_signal_declaration = true;
+ } else {
+ int k = j;
+ while (k < str.length() && !is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
+ k++;
+ }
- // check for space between name and bracket
- while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) {
- k++;
- }
+ // check for space between name and bracket
+ while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) {
+ k++;
+ }
- if (str[k] == '(') {
- in_function_name = true;
- } else if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::VAR)) {
- in_variable_declaration = true;
+ if (str[k] == '(') {
+ in_function_name = true;
+ } else if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::VAR)) {
+ in_variable_declaration = true;
+ }
+
+ // Check for lambda.
+ if (in_function_name && previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::FUNC)) {
+ k = j - 1;
+ while (k > 0 && (str[k] == '\t' || str[k] == ' ')) {
+ k--;
+ }
+
+ if (str[k] == ':') {
+ in_lambda = true;
+ }
+ }
}
}
@@ -348,7 +392,9 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
}
in_variable_declaration = false;
+ in_signal_declaration = false;
in_function_name = false;
+ in_lambda = false;
in_member_variable = false;
}
@@ -376,10 +422,14 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
} else if (in_member_variable) {
next_type = MEMBER;
color = member_color;
+ } else if (in_signal_declaration) {
+ next_type = SIGNAL;
+
+ color = member_color;
} else if (in_function_name) {
next_type = FUNCTION;
- if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::FUNC)) {
+ if (!in_lambda && previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::FUNC)) {
color = function_definition_color;
} else {
color = function_color;
diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h
index ac4995bee7..1ae0d72896 100644
--- a/modules/gdscript/editor/gdscript_highlighter.h
+++ b/modules/gdscript/editor/gdscript_highlighter.h
@@ -58,6 +58,7 @@ private:
SYMBOL,
NUMBER,
FUNCTION,
+ SIGNAL,
KEYWORD,
MEMBER,
IDENTIFIER,
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 3a79190149..0d295c3a51 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -2641,7 +2641,8 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
GDScriptParser::DataType result;
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
result.kind = GDScriptParser::DataType::ENUM_VALUE;
- result.builtin_type = base.builtin_type;
+ result.is_constant = true;
+ result.builtin_type = Variant::INT;
result.native_type = base.native_type;
result.enum_type = name;
p_identifier->set_datatype(result);
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index 8623122edc..82aa14795e 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -688,6 +688,7 @@ void GDScriptByteCodeGenerator::write_ternary_false_expr(const Address &p_expr)
void GDScriptByteCodeGenerator::write_end_ternary() {
patch_jump(ternary_jump_skip_pos.back()->get());
ternary_jump_skip_pos.pop_back();
+ ternary_result.pop_back();
}
void GDScriptByteCodeGenerator::write_set(const Address &p_target, const Address &p_index, const Address &p_source) {
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 432d31f78f..5e210074ed 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -3497,7 +3497,7 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
variable->export_info.hint_string = hint_string;
- // This is called after tne analyzer is done finding the type, so this should be set here.
+ // This is called after the analyzer is done finding the type, so this should be set here.
DataType export_type = variable->get_datatype();
if (p_annotation->name == "@export") {
@@ -4236,7 +4236,11 @@ void GDScriptParser::TreePrinter::print_get_node(GetNodeNode *p_get_node) {
}
void GDScriptParser::TreePrinter::print_identifier(IdentifierNode *p_identifier) {
- push_text(p_identifier->name);
+ if (p_identifier != nullptr) {
+ push_text(p_identifier->name);
+ } else {
+ push_text("<invalid identifier>");
+ }
}
void GDScriptParser::TreePrinter::print_if(IfNode *p_if, bool p_is_elif) {
diff --git a/modules/gdscript/icons/GDScriptInternal.svg b/modules/gdscript/icons/GDScriptInternal.svg
new file mode 100644
index 0000000000..fcabaafbd0
--- /dev/null
+++ b/modules/gdscript/icons/GDScriptInternal.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1-.56445 2.2578c-.2364329.0758517-.4668872.16921-.68945.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941c-.1119126.2211335-.2072287.4502818-.28516.68555l-2.2539.5625v2l2.2578.56445c.075942.2357685.1692993.465568.2793.6875l-1.1934 1.9902 1.4141 1.4141 1.9941-1.1953c.2211335.111913.4502818.207229.68555.28516l.5625 2.2539h2l.56445-2.2578c.2357685-.07594.465568-.169299.6875-.2793l1.9902 1.1934 1.4141-1.4141-1.1953-1.9941c.111913-.221133.207229-.4502818.28516-.68555l2.2539-.5625v-2l-2.2578-.56445c-.075942-.2357685-.169299-.4655679-.2793-.6875l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953c-.221133-.1119126-.4502818-.2072287-.68555-.28516l-.5625-2.2539zm1 5c1.1045695 0 2 .8954305 2 2s-.8954305 2-2 2-2-.8954305-2-2 .8954305-2 2-2z" fill="none" stroke="#e0e0e0"/></svg>
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index 7abc8f7d7a..5ef48f8645 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -1028,6 +1028,13 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) {
}
}
+void GridMapEditor::_update_theme() {
+ options->set_icon(get_theme_icon(SNAME("GridMap"), SNAME("EditorIcons")));
+ search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
+ mode_thumbnail->set_icon(get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons")));
+ mode_list->set_icon(get_theme_icon(SNAME("FileList"), SNAME("EditorIcons")));
+}
+
void GridMapEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -1048,6 +1055,7 @@ void GridMapEditor::_notification(int p_what) {
_update_selection_transform();
_update_paste_indicator();
+ _update_theme();
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -1088,8 +1096,7 @@ void GridMapEditor::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
- options->set_icon(get_theme_icon(SNAME("GridMap"), SNAME("EditorIcons")));
- search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
+ _update_theme();
} break;
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
@@ -1250,7 +1257,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
mode_thumbnail->set_flat(true);
mode_thumbnail->set_toggle_mode(true);
mode_thumbnail->set_pressed(true);
- mode_thumbnail->set_icon(p_editor->get_gui_base()->get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons")));
hb->add_child(mode_thumbnail);
mode_thumbnail->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_THUMBNAIL));
@@ -1258,7 +1264,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
mode_list->set_flat(true);
mode_list->set_toggle_mode(true);
mode_list->set_pressed(false);
- mode_list->set_icon(p_editor->get_gui_base()->get_theme_icon(SNAME("FileList"), SNAME("EditorIcons")));
hb->add_child(mode_list);
mode_list->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_LIST));
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index 7e9510e227..37298a1d80 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -201,6 +201,7 @@ class GridMapEditor : public VBoxContainer {
void _update_cursor_transform();
void _update_cursor_instance();
void _update_clip();
+ void _update_theme();
void _text_changed(const String &p_text);
void _sbox_input(const Ref<InputEvent> &p_ie);
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 3d02f638ec..9d416dcfce 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -2995,6 +2995,7 @@ void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMon
CRASH_COND(p_script->native == nullptr);
p_script->valid = true;
+ p_script->reload_invalidated = false;
update_script_class_info(p_script);
@@ -3351,13 +3352,13 @@ MethodInfo CSharpScript::get_method_info(const StringName &p_method) const {
}
Error CSharpScript::reload(bool p_keep_state) {
- bool has_instances;
- {
- MutexLock lock(CSharpLanguage::get_singleton()->script_instances_mutex);
- has_instances = instances.size();
+ if (!reload_invalidated) {
+ return OK;
}
- ERR_FAIL_COND_V(!p_keep_state && has_instances, ERR_ALREADY_IN_USE);
+ // In the case of C#, reload doesn't really do any script reloading.
+ // That's done separately via domain reloading.
+ reload_invalidated = false;
GD_MONO_SCOPE_THREAD_ATTACH;
@@ -3544,6 +3545,7 @@ void CSharpScript::_update_name() {
void CSharpScript::_clear() {
tool = false;
valid = false;
+ reload_invalidated = true;
base = nullptr;
native = nullptr;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 221bba3af9..2be588cac4 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -101,6 +101,7 @@ private:
bool tool = false;
bool valid = false;
+ bool reload_invalidated = false;
bool builtin;
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index 02739f0480..c0cd18e29d 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -68,7 +68,14 @@ String _get_mono_user_dir() {
} else {
String settings_path;
+ // Self-contained mode if a `._sc_` or `_sc_` file is present in executable dir.
String exe_dir = OS::get_singleton()->get_executable_path().get_base_dir();
+
+ // On macOS, look outside .app bundle, since .app bundle is read-only.
+ if (OS::get_singleton()->has_feature("macos") && exe_dir.ends_with("MacOS") && exe_dir.plus_file("..").simplify_path().ends_with("Contents")) {
+ exe_dir = exe_dir.plus_file("../../..").simplify_path();
+ }
+
DirAccessRef d = DirAccess::create_for_path(exe_dir);
if (d->file_exists("._sc_") || d->file_exists("_sc_")) {
diff --git a/modules/pvr/SCsub b/modules/pvr/SCsub
deleted file mode 100644
index 36052cffed..0000000000
--- a/modules/pvr/SCsub
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-Import("env_modules")
-
-env_pvr = env_modules.Clone()
-
-# Thirdparty source files
-
-thirdparty_obj = []
-
-# Not unbundled so far since not widespread as shared library
-thirdparty_dir = "#thirdparty/pvrtccompressor/"
-thirdparty_sources = [
- "BitScale.cpp",
- "MortonTable.cpp",
- "PvrTcDecoder.cpp",
- "PvrTcEncoder.cpp",
- "PvrTcPacket.cpp",
-]
-thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
-
-env_pvr.Prepend(CPPPATH=[thirdparty_dir])
-
-env_thirdparty = env_pvr.Clone()
-env_thirdparty.disable_warnings()
-env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
-env.modules_sources += thirdparty_obj
-
-# Godot source files
-
-module_obj = []
-
-env_pvr.add_source_files(module_obj, "*.cpp")
-env.modules_sources += module_obj
-
-# Needed to force rebuilding the module files when the thirdparty library is updated.
-env.Depends(module_obj, thirdparty_obj)
diff --git a/modules/pvr/config.py b/modules/pvr/config.py
deleted file mode 100644
index d22f9454ed..0000000000
--- a/modules/pvr/config.py
+++ /dev/null
@@ -1,6 +0,0 @@
-def can_build(env, platform):
- return True
-
-
-def configure(env):
- pass
diff --git a/modules/pvr/image_compress_pvrtc.cpp b/modules/pvr/image_compress_pvrtc.cpp
deleted file mode 100644
index b996d910d5..0000000000
--- a/modules/pvr/image_compress_pvrtc.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*************************************************************************/
-/* image_compress_pvrtc.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "image_compress_pvrtc.h"
-
-#include "core/io/image.h"
-#include "core/object/ref_counted.h"
-
-#include <PvrTcEncoder.h>
-#include <RgbaBitmap.h>
-
-static void _compress_pvrtc1_4bpp(Image *p_img) {
- Ref<Image> img = p_img->duplicate();
-
- bool make_mipmaps = false;
- if (!img->is_size_po2() || img->get_width() != img->get_height()) {
- make_mipmaps = img->has_mipmaps();
- img->resize_to_po2(true);
- // Resizing can fail for some formats
- if (!img->is_size_po2() || img->get_width() != img->get_height()) {
- ERR_FAIL_MSG("Failed to resize the image for compression.");
- }
- }
- img->convert(Image::FORMAT_RGBA8);
- if (!img->has_mipmaps() && make_mipmaps) {
- img->generate_mipmaps();
- }
-
- bool use_alpha = img->detect_alpha();
-
- Ref<Image> new_img;
- new_img.instantiate();
- new_img->create(img->get_width(), img->get_height(), img->has_mipmaps(), use_alpha ? Image::FORMAT_PVRTC1_4A : Image::FORMAT_PVRTC1_4);
-
- Vector<uint8_t> data = new_img->get_data();
- {
- uint8_t *wr = data.ptrw();
- const uint8_t *r = img->get_data().ptr();
-
- for (int i = 0; i <= new_img->get_mipmap_count(); i++) {
- int ofs, size, w, h;
- img->get_mipmap_offset_size_and_dimensions(i, ofs, size, w, h);
- Javelin::RgbaBitmap bm(w, h);
- void *dst = (void *)bm.GetData();
- memcpy(dst, &r[ofs], size);
- Javelin::ColorRgba<unsigned char> *dp = bm.GetData();
- for (int j = 0; j < size / 4; j++) {
- // Red and blue colors are swapped.
- SWAP(dp[j].r, dp[j].b);
- }
- new_img->get_mipmap_offset_size_and_dimensions(i, ofs, size, w, h);
- Javelin::PvrTcEncoder::EncodeRgba4Bpp(&wr[ofs], bm);
- }
- }
-
- p_img->create(new_img->get_width(), new_img->get_height(), new_img->has_mipmaps(), new_img->get_format(), data);
-}
-
-void _register_pvrtc_compress_func() {
- Image::_image_compress_pvrtc1_4bpp_func = _compress_pvrtc1_4bpp;
-}
diff --git a/modules/pvr/image_compress_pvrtc.h b/modules/pvr/image_compress_pvrtc.h
deleted file mode 100644
index 80edb81363..0000000000
--- a/modules/pvr/image_compress_pvrtc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*************************************************************************/
-/* image_compress_pvrtc.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef IMAGE_COMPRESS_PVRTC_H
-#define IMAGE_COMPRESS_PVRTC_H
-
-void _register_pvrtc_compress_func();
-
-#endif // IMAGE_COMPRESS_PVRTC_H
diff --git a/modules/pvr/register_types.cpp b/modules/pvr/register_types.cpp
deleted file mode 100644
index dcc7f505a1..0000000000
--- a/modules/pvr/register_types.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*************************************************************************/
-/* register_types.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "register_types.h"
-
-#include "image_compress_pvrtc.h"
-#include "texture_loader_pvr.h"
-
-static Ref<ResourceFormatPVR> resource_loader_pvr;
-
-void register_pvr_types() {
- resource_loader_pvr.instantiate();
- ResourceLoader::add_resource_format_loader(resource_loader_pvr);
-
- _register_pvrtc_compress_func();
-}
-
-void unregister_pvr_types() {
- ResourceLoader::remove_resource_format_loader(resource_loader_pvr);
- resource_loader_pvr.unref();
-}
diff --git a/modules/pvr/register_types.h b/modules/pvr/register_types.h
deleted file mode 100644
index faefb98678..0000000000
--- a/modules/pvr/register_types.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*************************************************************************/
-/* register_types.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef PVR_REGISTER_TYPES_H
-#define PVR_REGISTER_TYPES_H
-
-void register_pvr_types();
-void unregister_pvr_types();
-
-#endif // PVR_REGISTER_TYPES_H
diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp
deleted file mode 100644
index ff66a101ab..0000000000
--- a/modules/pvr/texture_loader_pvr.cpp
+++ /dev/null
@@ -1,608 +0,0 @@
-/*************************************************************************/
-/* texture_loader_pvr.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "texture_loader_pvr.h"
-
-#include "core/io/file_access.h"
-
-static void _pvrtc_decompress(Image *p_img);
-
-enum PVRFLags {
- PVR_HAS_MIPMAPS = 0x00000100,
- PVR_TWIDDLED = 0x00000200,
- PVR_NORMAL_MAP = 0x00000400,
- PVR_BORDER = 0x00000800,
- PVR_CUBE_MAP = 0x00001000,
- PVR_FALSE_MIPMAPS = 0x00002000,
- PVR_VOLUME_TEXTURES = 0x00004000,
- PVR_HAS_ALPHA = 0x00008000,
- PVR_VFLIP = 0x00010000
-};
-
-RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
- if (r_error) {
- *r_error = ERR_CANT_OPEN;
- }
-
- Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
- if (!f) {
- return RES();
- }
-
- FileAccessRef faref(f);
-
- ERR_FAIL_COND_V(err, RES());
-
- if (r_error) {
- *r_error = ERR_FILE_CORRUPT;
- }
-
- uint32_t hsize = f->get_32();
-
- ERR_FAIL_COND_V(hsize != 52, RES());
- uint32_t height = f->get_32();
- uint32_t width = f->get_32();
- uint32_t mipmaps = f->get_32();
- uint32_t flags = f->get_32();
- uint32_t surfsize = f->get_32();
- f->seek(f->get_position() + 20); // bpp, rmask, gmask, bmask, amask
- uint8_t pvrid[5] = { 0, 0, 0, 0, 0 };
- f->get_buffer(pvrid, 4);
- ERR_FAIL_COND_V(String((char *)pvrid) != "PVR!", RES());
- f->get_32(); // surfcount
-
- /*
- print_line("height: "+itos(height));
- print_line("width: "+itos(width));
- print_line("mipmaps: "+itos(mipmaps));
- print_line("flags: "+itos(flags));
- print_line("surfsize: "+itos(surfsize));
- print_line("bpp: "+itos(bpp));
- print_line("rmask: "+itos(rmask));
- print_line("gmask: "+itos(gmask));
- print_line("bmask: "+itos(bmask));
- print_line("amask: "+itos(amask));
- print_line("surfcount: "+itos(surfcount));
- */
-
- Vector<uint8_t> data;
- data.resize(surfsize);
-
- ERR_FAIL_COND_V(data.size() == 0, RES());
-
- uint8_t *w = data.ptrw();
- f->get_buffer(&w[0], surfsize);
- err = f->get_error();
- ERR_FAIL_COND_V(err != OK, RES());
-
- Image::Format format = Image::FORMAT_MAX;
-
- switch (flags & 0xFF) {
- case 0x18:
- case 0xC:
- format = (flags & PVR_HAS_ALPHA) ? Image::FORMAT_PVRTC1_2A : Image::FORMAT_PVRTC1_2;
- break;
- case 0x19:
- case 0xD:
- format = (flags & PVR_HAS_ALPHA) ? Image::FORMAT_PVRTC1_4A : Image::FORMAT_PVRTC1_4;
- break;
- case 0x16:
- format = Image::FORMAT_L8;
- break;
- case 0x17:
- format = Image::FORMAT_LA8;
- break;
- case 0x20:
- case 0x80:
- case 0x81:
- format = Image::FORMAT_DXT1;
- break;
- case 0x21:
- case 0x22:
- case 0x82:
- case 0x83:
- format = Image::FORMAT_DXT3;
- break;
- case 0x23:
- case 0x24:
- case 0x84:
- case 0x85:
- format = Image::FORMAT_DXT5;
- break;
- case 0x4:
- case 0x15:
- format = Image::FORMAT_RGB8;
- break;
- case 0x5:
- case 0x12:
- format = Image::FORMAT_RGBA8;
- break;
- case 0x36:
- format = Image::FORMAT_ETC;
- break;
- default:
- ERR_FAIL_V_MSG(RES(), "Unsupported format in PVR texture: " + itos(flags & 0xFF) + ".");
- }
-
- Ref<Image> image = memnew(Image(width, height, mipmaps, format, data));
- ERR_FAIL_COND_V(image->is_empty(), RES());
-
- Ref<ImageTexture> texture = memnew(ImageTexture);
- texture->create_from_image(image);
-
- if (r_error) {
- *r_error = OK;
- }
-
- return texture;
-}
-
-void ResourceFormatPVR::get_recognized_extensions(List<String> *p_extensions) const {
- p_extensions->push_back("pvr");
-}
-
-bool ResourceFormatPVR::handles_type(const String &p_type) const {
- return ClassDB::is_parent_class(p_type, "Texture2D");
-}
-
-String ResourceFormatPVR::get_resource_type(const String &p_path) const {
- if (p_path.get_extension().to_lower() == "pvr") {
- return "Texture2D";
- }
- return "";
-}
-
-ResourceFormatPVR::ResourceFormatPVR() {
- Image::_image_decompress_pvrtc = _pvrtc_decompress;
-}
-
-/////////////////////////////////////////////////////////
-
-//PVRTC decompressor, Based on PVRTC decompressor by IMGTEC.
-
-/////////////////////////////////////////////////////////
-
-#define PT_INDEX 2
-#define BLK_Y_SIZE 4
-#define BLK_X_MAX 8
-#define BLK_X_2BPP 8
-#define BLK_X_4BPP 4
-
-#define WRAP_COORD(Val, Size) ((Val) & ((Size)-1))
-
-/*
- Define an expression to either wrap or clamp large or small vals to the
- legal coordinate range
-*/
-#define LIMIT_COORD(Val, Size, p_tiled) \
- ((p_tiled) ? WRAP_COORD((Val), (Size)) : CLAMP((Val), 0, (Size)-1))
-
-struct PVRTCBlock {
- //blocks are 64 bits
- uint32_t data[2] = {};
-};
-
-_FORCE_INLINE_ bool is_po2(uint32_t p_input) {
- if (p_input == 0) {
- return false;
- }
- uint32_t minus1 = p_input - 1;
- return ((p_input | minus1) == (p_input ^ minus1)) ? true : false;
-}
-
-static void unpack_5554(const PVRTCBlock *p_block, int p_ab_colors[2][4]) {
- uint32_t raw_bits[2];
- raw_bits[0] = p_block->data[1] & (0xFFFE);
- raw_bits[1] = p_block->data[1] >> 16;
-
- for (int i = 0; i < 2; i++) {
- if (raw_bits[i] & (1 << 15)) {
- p_ab_colors[i][0] = (raw_bits[i] >> 10) & 0x1F;
- p_ab_colors[i][1] = (raw_bits[i] >> 5) & 0x1F;
- p_ab_colors[i][2] = raw_bits[i] & 0x1F;
- if (i == 0) {
- p_ab_colors[0][2] |= p_ab_colors[0][2] >> 4;
- }
- p_ab_colors[i][3] = 0xF;
- } else {
- p_ab_colors[i][0] = (raw_bits[i] >> (8 - 1)) & 0x1E;
- p_ab_colors[i][1] = (raw_bits[i] >> (4 - 1)) & 0x1E;
-
- p_ab_colors[i][0] |= p_ab_colors[i][0] >> 4;
- p_ab_colors[i][1] |= p_ab_colors[i][1] >> 4;
-
- p_ab_colors[i][2] = (raw_bits[i] & 0xF) << 1;
-
- if (i == 0) {
- p_ab_colors[0][2] |= p_ab_colors[0][2] >> 3;
- } else {
- p_ab_colors[0][2] |= p_ab_colors[0][2] >> 4;
- }
-
- p_ab_colors[i][3] = (raw_bits[i] >> 11) & 0xE;
- }
- }
-}
-
-static void unpack_modulations(const PVRTCBlock *p_block, const int p_2bit, int p_modulation[8][16], int p_modulation_modes[8][16], int p_x, int p_y) {
- int block_mod_mode = p_block->data[1] & 1;
- uint32_t modulation_bits = p_block->data[0];
-
- if (p_2bit && block_mod_mode) {
- for (int y = 0; y < BLK_Y_SIZE; y++) {
- for (int x = 0; x < BLK_X_2BPP; x++) {
- p_modulation_modes[y + p_y][x + p_x] = block_mod_mode;
-
- if (((x ^ y) & 1) == 0) {
- p_modulation[y + p_y][x + p_x] = modulation_bits & 3;
- modulation_bits >>= 2;
- }
- }
- }
-
- } else if (p_2bit) {
- for (int y = 0; y < BLK_Y_SIZE; y++) {
- for (int x = 0; x < BLK_X_2BPP; x++) {
- p_modulation_modes[y + p_y][x + p_x] = block_mod_mode;
-
- if (modulation_bits & 1) {
- p_modulation[y + p_y][x + p_x] = 0x3;
- } else {
- p_modulation[y + p_y][x + p_x] = 0x0;
- }
-
- modulation_bits >>= 1;
- }
- }
- } else {
- for (int y = 0; y < BLK_Y_SIZE; y++) {
- for (int x = 0; x < BLK_X_4BPP; x++) {
- p_modulation_modes[y + p_y][x + p_x] = block_mod_mode;
- p_modulation[y + p_y][x + p_x] = modulation_bits & 3;
- modulation_bits >>= 2;
- }
- }
- }
-
- ERR_FAIL_COND(modulation_bits != 0);
-}
-
-static void interpolate_colors(const int p_colorp[4], const int p_colorq[4], const int p_colorr[4], const int p_colors[4], bool p_2bit, const int x, const int y, int r_result[4]) {
- int u, v, uscale;
- int k;
-
- int tmp1, tmp2;
-
- int P[4], Q[4], R[4], S[4];
-
- for (k = 0; k < 4; k++) {
- P[k] = p_colorp[k];
- Q[k] = p_colorq[k];
- R[k] = p_colorr[k];
- S[k] = p_colors[k];
- }
-
- v = (y & 0x3) | ((~y & 0x2) << 1);
-
- if (p_2bit) {
- u = (x & 0x7) | ((~x & 0x4) << 1);
- } else {
- u = (x & 0x3) | ((~x & 0x2) << 1);
- }
-
- v = v - BLK_Y_SIZE / 2;
-
- if (p_2bit) {
- u = u - BLK_X_2BPP / 2;
- uscale = 8;
- } else {
- u = u - BLK_X_4BPP / 2;
- uscale = 4;
- }
-
- for (k = 0; k < 4; k++) {
- tmp1 = P[k] * uscale + u * (Q[k] - P[k]);
- tmp2 = R[k] * uscale + u * (S[k] - R[k]);
-
- tmp1 = tmp1 * 4 + v * (tmp2 - tmp1);
-
- r_result[k] = tmp1;
- }
-
- if (p_2bit) {
- for (k = 0; k < 3; k++) {
- r_result[k] >>= 2;
- }
-
- r_result[3] >>= 1;
- } else {
- for (k = 0; k < 3; k++) {
- r_result[k] >>= 1;
- }
- }
-
- for (k = 0; k < 4; k++) {
- ERR_FAIL_COND(r_result[k] >= 256);
- }
-
- for (k = 0; k < 3; k++) {
- r_result[k] += r_result[k] >> 5;
- }
-
- r_result[3] += r_result[3] >> 4;
-
- for (k = 0; k < 4; k++) {
- ERR_FAIL_COND(r_result[k] >= 256);
- }
-}
-
-static void get_modulation_value(int x, int y, const int p_2bit, const int p_modulation[8][16], const int p_modulation_modes[8][16], int *r_mod, int *p_dopt) {
- static const int rep_vals0[4] = { 0, 3, 5, 8 };
- static const int rep_vals1[4] = { 0, 4, 4, 8 };
-
- int mod_val;
-
- y = (y & 0x3) | ((~y & 0x2) << 1);
-
- if (p_2bit) {
- x = (x & 0x7) | ((~x & 0x4) << 1);
- } else {
- x = (x & 0x3) | ((~x & 0x2) << 1);
- }
-
- *p_dopt = 0;
-
- if (p_modulation_modes[y][x] == 0) {
- mod_val = rep_vals0[p_modulation[y][x]];
- } else if (p_2bit) {
- if (((x ^ y) & 1) == 0) {
- mod_val = rep_vals0[p_modulation[y][x]];
- } else if (p_modulation_modes[y][x] == 1) {
- mod_val = (rep_vals0[p_modulation[y - 1][x]] +
- rep_vals0[p_modulation[y + 1][x]] +
- rep_vals0[p_modulation[y][x - 1]] +
- rep_vals0[p_modulation[y][x + 1]] + 2) /
- 4;
- } else if (p_modulation_modes[y][x] == 2) {
- mod_val = (rep_vals0[p_modulation[y][x - 1]] +
- rep_vals0[p_modulation[y][x + 1]] + 1) /
- 2;
- } else {
- mod_val = (rep_vals0[p_modulation[y - 1][x]] +
- rep_vals0[p_modulation[y + 1][x]] + 1) /
- 2;
- }
- } else {
- mod_val = rep_vals1[p_modulation[y][x]];
-
- *p_dopt = p_modulation[y][x] == PT_INDEX;
- }
-
- *r_mod = mod_val;
-}
-
-static int disable_twiddling = 0;
-
-static uint32_t twiddle_uv(uint32_t p_height, uint32_t p_width, uint32_t p_y, uint32_t p_x) {
- uint32_t twiddled;
-
- uint32_t min_dimension;
- uint32_t max_value;
-
- uint32_t scr_bit_pos;
- uint32_t dst_bit_pos;
-
- int shift_count;
-
- ERR_FAIL_COND_V(p_y >= p_height, 0);
- ERR_FAIL_COND_V(p_x >= p_width, 0);
-
- ERR_FAIL_COND_V(!is_po2(p_height), 0);
- ERR_FAIL_COND_V(!is_po2(p_width), 0);
-
- if (p_height < p_width) {
- min_dimension = p_height;
- max_value = p_x;
- } else {
- min_dimension = p_width;
- max_value = p_y;
- }
-
- if (disable_twiddling) {
- return (p_y * p_width + p_x);
- }
-
- scr_bit_pos = 1;
- dst_bit_pos = 1;
- twiddled = 0;
- shift_count = 0;
-
- while (scr_bit_pos < min_dimension) {
- if (p_y & scr_bit_pos) {
- twiddled |= dst_bit_pos;
- }
-
- if (p_x & scr_bit_pos) {
- twiddled |= (dst_bit_pos << 1);
- }
-
- scr_bit_pos <<= 1;
- dst_bit_pos <<= 2;
- shift_count += 1;
- }
-
- max_value >>= shift_count;
-
- twiddled |= (max_value << (2 * shift_count));
-
- return twiddled;
-}
-
-static void decompress_pvrtc(PVRTCBlock *p_comp_img, const int p_2bit, const int p_width, const int p_height, const int p_tiled, unsigned char *p_dst) {
- int x, y;
- int i, j;
-
- int block_x, blk_y;
- int block_xp1, blk_yp1;
- int x_block_size;
- int block_width, block_height;
-
- int p_x, p_y;
-
- int p_modulation[8][16] = { { 0 } };
- int p_modulation_modes[8][16] = { { 0 } };
-
- int Mod, DoPT;
-
- unsigned int u_pos;
-
- // local neighbourhood of blocks
- PVRTCBlock *p_blocks[2][2];
-
- PVRTCBlock *prev[2][2] = { { nullptr, nullptr }, { nullptr, nullptr } };
-
- struct
- {
- int Reps[2][4];
- } colors5554[2][2];
-
- int ASig[4], BSig[4];
-
- int r_result[4];
-
- if (p_2bit) {
- x_block_size = BLK_X_2BPP;
- } else {
- x_block_size = BLK_X_4BPP;
- }
-
- block_width = MAX(2, p_width / x_block_size);
- block_height = MAX(2, p_height / BLK_Y_SIZE);
-
- for (y = 0; y < p_height; y++) {
- for (x = 0; x < p_width; x++) {
- block_x = (x - x_block_size / 2);
- blk_y = (y - BLK_Y_SIZE / 2);
-
- block_x = LIMIT_COORD(block_x, p_width, p_tiled);
- blk_y = LIMIT_COORD(blk_y, p_height, p_tiled);
-
- block_x /= x_block_size;
- blk_y /= BLK_Y_SIZE;
-
- block_xp1 = LIMIT_COORD(block_x + 1, block_width, p_tiled);
- blk_yp1 = LIMIT_COORD(blk_y + 1, block_height, p_tiled);
-
- p_blocks[0][0] = p_comp_img + twiddle_uv(block_height, block_width, blk_y, block_x);
- p_blocks[0][1] = p_comp_img + twiddle_uv(block_height, block_width, blk_y, block_xp1);
- p_blocks[1][0] = p_comp_img + twiddle_uv(block_height, block_width, blk_yp1, block_x);
- p_blocks[1][1] = p_comp_img + twiddle_uv(block_height, block_width, blk_yp1, block_xp1);
-
- if (memcmp(prev, p_blocks, 4 * sizeof(void *)) != 0) {
- p_y = 0;
- for (i = 0; i < 2; i++) {
- p_x = 0;
- for (j = 0; j < 2; j++) {
- unpack_5554(p_blocks[i][j], colors5554[i][j].Reps);
-
- unpack_modulations(
- p_blocks[i][j],
- p_2bit,
- p_modulation,
- p_modulation_modes,
- p_x, p_y);
-
- p_x += x_block_size;
- }
-
- p_y += BLK_Y_SIZE;
- }
-
- memcpy(prev, p_blocks, 4 * sizeof(void *));
- }
-
- interpolate_colors(
- colors5554[0][0].Reps[0],
- colors5554[0][1].Reps[0],
- colors5554[1][0].Reps[0],
- colors5554[1][1].Reps[0],
- p_2bit, x, y,
- ASig);
-
- interpolate_colors(
- colors5554[0][0].Reps[1],
- colors5554[0][1].Reps[1],
- colors5554[1][0].Reps[1],
- colors5554[1][1].Reps[1],
- p_2bit, x, y,
- BSig);
-
- get_modulation_value(x, y, p_2bit, (const int(*)[16])p_modulation, (const int(*)[16])p_modulation_modes,
- &Mod, &DoPT);
-
- for (i = 0; i < 4; i++) {
- r_result[i] = ASig[i] * 8 + Mod * (BSig[i] - ASig[i]);
- r_result[i] >>= 3;
- }
-
- if (DoPT) {
- r_result[3] = 0;
- }
-
- u_pos = (x + y * p_width) << 2;
- p_dst[u_pos + 0] = (uint8_t)r_result[0];
- p_dst[u_pos + 1] = (uint8_t)r_result[1];
- p_dst[u_pos + 2] = (uint8_t)r_result[2];
- p_dst[u_pos + 3] = (uint8_t)r_result[3];
- }
- }
-}
-
-static void _pvrtc_decompress(Image *p_img) {
- ERR_FAIL_COND(p_img->get_format() != Image::FORMAT_PVRTC1_2 && p_img->get_format() != Image::FORMAT_PVRTC1_2A && p_img->get_format() != Image::FORMAT_PVRTC1_4 && p_img->get_format() != Image::FORMAT_PVRTC1_4A);
-
- bool _2bit = (p_img->get_format() == Image::FORMAT_PVRTC1_2 || p_img->get_format() == Image::FORMAT_PVRTC1_2A);
-
- Vector<uint8_t> data = p_img->get_data();
- const uint8_t *r = data.ptr();
-
- Vector<uint8_t> newdata;
- newdata.resize(p_img->get_width() * p_img->get_height() * 4);
- uint8_t *w = newdata.ptrw();
-
- decompress_pvrtc((PVRTCBlock *)r, _2bit, p_img->get_width(), p_img->get_height(), 0, (unsigned char *)w);
-
- bool make_mipmaps = p_img->has_mipmaps();
- p_img->create(p_img->get_width(), p_img->get_height(), false, Image::FORMAT_RGBA8, newdata);
- if (make_mipmaps) {
- p_img->generate_mipmaps();
- }
-}
diff --git a/modules/pvr/texture_loader_pvr.h b/modules/pvr/texture_loader_pvr.h
deleted file mode 100644
index 06e8e91ba2..0000000000
--- a/modules/pvr/texture_loader_pvr.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*************************************************************************/
-/* texture_loader_pvr.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef TEXTURE_LOADER_PVR_H
-#define TEXTURE_LOADER_PVR_H
-
-#include "core/io/resource_loader.h"
-#include "scene/resources/texture.h"
-
-class ResourceFormatPVR : public ResourceFormatLoader {
-public:
- virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual bool handles_type(const String &p_type) const;
- virtual String get_resource_type(const String &p_path) const;
-
- ResourceFormatPVR();
- virtual ~ResourceFormatPVR() {}
-};
-
-#endif // TEXTURE_LOADER_PVR_H
diff --git a/modules/svg/SCsub b/modules/svg/SCsub
index c7228a8d0b..bb03147731 100644
--- a/modules/svg/SCsub
+++ b/modules/svg/SCsub
@@ -9,16 +9,66 @@ env_svg = env_modules.Clone()
thirdparty_obj = []
-thirdparty_dir = "#thirdparty/nanosvg/"
+thirdparty_dir = "#thirdparty/thorvg/"
thirdparty_sources = [
- "nanosvg.cc",
+ "src/lib/tvgBezier.cpp",
+ "src/lib/tvgCanvas.cpp",
+ "src/lib/tvgFill.cpp",
+ "src/lib/tvgGlCanvas.cpp",
+ "src/lib/tvgInitializer.cpp",
+ "src/lib/tvgLinearGradient.cpp",
+ "src/lib/tvgLoader.cpp",
+ "src/lib/tvgLzw.cpp",
+ "src/lib/tvgPaint.cpp",
+ "src/lib/tvgPicture.cpp",
+ "src/lib/tvgRadialGradient.cpp",
+ "src/lib/tvgRender.cpp",
+ "src/lib/tvgSaver.cpp",
+ "src/lib/tvgScene.cpp",
+ "src/lib/tvgShape.cpp",
+ "src/lib/tvgSwCanvas.cpp",
+ "src/lib/tvgTaskScheduler.cpp",
+ "src/loaders/raw/tvgRawLoader.cpp",
+ "src/loaders/svg/tvgXmlParser.cpp",
+ "src/loaders/svg/tvgSvgUtil.cpp",
+ "src/loaders/svg/tvgSvgSceneBuilder.cpp",
+ "src/loaders/svg/tvgSvgPath.cpp",
+ "src/loaders/svg/tvgSvgLoader.cpp",
+ "src/loaders/tvg/tvgTvgBinInterpreter.cpp",
+ "src/loaders/tvg/tvgTvgLoader.cpp",
+ "src/loaders/jpg/tvgJpgLoader.cpp",
+ "src/loaders/jpg/tvgJpgd.cpp",
+ "src/loaders/external_png/tvgPngLoader.cpp",
+ "src/lib/sw_engine/tvgSwFill.cpp",
+ "src/lib/sw_engine/tvgSwImage.cpp",
+ "src/lib/sw_engine/tvgSwMath.cpp",
+ "src/lib/sw_engine/tvgSwMemPool.cpp",
+ "src/lib/sw_engine/tvgSwRaster.cpp",
+ "src/lib/sw_engine/tvgSwRenderer.cpp",
+ "src/lib/sw_engine/tvgSwRle.cpp",
+ "src/lib/sw_engine/tvgSwShape.cpp",
+ "src/lib/sw_engine/tvgSwStroke.cpp",
+ "src/savers/tvg/tvgTvgSaver.cpp",
]
+
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
-env_svg.Prepend(CPPPATH=[thirdparty_dir])
+env_svg.Prepend(CPPPATH=[thirdparty_dir + "inc"])
env_thirdparty = env_svg.Clone()
env_thirdparty.disable_warnings()
+env_thirdparty.Prepend(
+ CPPPATH=[
+ thirdparty_dir + "src/lib",
+ thirdparty_dir + "src/lib/sw_engine",
+ thirdparty_dir + "src/loaders/raw",
+ thirdparty_dir + "src/loaders/svg",
+ thirdparty_dir + "src/loaders/jpg",
+ thirdparty_dir + "src/loaders/png",
+ thirdparty_dir + "src/loaders/tvg",
+ thirdparty_dir + "src/savers/tvg",
+ ]
+)
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
env.modules_sources += thirdparty_obj
diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp
index bf43d7a4ad..96b83bf25a 100644
--- a/modules/svg/image_loader_svg.cpp
+++ b/modules/svg/image_loader_svg.cpp
@@ -30,132 +30,118 @@
#include "image_loader_svg.h"
-#include <nanosvg.h>
-#include <nanosvgrast.h>
-
-void SVGRasterizer::rasterize(NSVGimage *p_image, float p_tx, float p_ty, float p_scale, unsigned char *p_dst, int p_w, int p_h, int p_stride) {
- nsvgRasterize(rasterizer, p_image, p_tx, p_ty, p_scale, p_dst, p_w, p_h, p_stride);
-}
-
-SVGRasterizer::SVGRasterizer() {
- rasterizer = nsvgCreateRasterizer();
-}
-
-SVGRasterizer::~SVGRasterizer() {
- nsvgDeleteRasterizer(rasterizer);
-}
-
-SVGRasterizer ImageLoaderSVG::rasterizer;
-
-inline void change_nsvg_paint_color(NSVGpaint *p_paint, const uint32_t p_old, const uint32_t p_new) {
- if (p_paint->type == NSVG_PAINT_COLOR) {
- if (p_paint->color << 8 == p_old << 8) {
- p_paint->color = (p_paint->color & 0xFF000000) | (p_new & 0x00FFFFFF);
- }
- }
-
- if (p_paint->type == NSVG_PAINT_LINEAR_GRADIENT || p_paint->type == NSVG_PAINT_RADIAL_GRADIENT) {
- for (int stop_index = 0; stop_index < p_paint->gradient->nstops; stop_index++) {
- if (p_paint->gradient->stops[stop_index].color << 8 == p_old << 8) {
- p_paint->gradient->stops[stop_index].color = p_new;
+#include "core/os/memory.h"
+#include "core/variant/variant.h"
+
+#include <thorvg.h>
+
+void ImageLoaderSVG::_replace_color_property(const String &p_prefix, String &r_string) {
+ // Replace colors in the SVG based on what is configured in `replace_colors`.
+ // Used to change the colors of editor icons based on the used theme.
+ // The strings being replaced are typically of the form:
+ // fill="#5abbef"
+ // But can also be 3-letter codes, include alpha, be "none" or a named color
+ // string ("blue"). So we convert to Godot Color to compare with `replace_colors`.
+
+ const int prefix_len = p_prefix.length();
+ int pos = r_string.find(p_prefix);
+ while (pos != -1) {
+ pos += prefix_len; // Skip prefix.
+ int end_pos = r_string.find("\"", pos);
+ ERR_FAIL_COND_MSG(end_pos == -1, vformat("Malformed SVG string after property \"%s\".", p_prefix));
+ const String color_code = r_string.substr(pos, end_pos - pos);
+ if (color_code != "none" && !color_code.begins_with("url(")) {
+ const Color color = Color(color_code); // Handles both HTML codes and named colors.
+ if (replace_colors.has(color)) {
+ r_string = r_string.left(pos) + "#" + replace_colors[color].operator Color().to_html(false) + r_string.substr(end_pos);
}
}
+ // Search for other occurrences.
+ pos = r_string.find(p_prefix, pos);
}
}
-void ImageLoaderSVG::_convert_colors(NSVGimage *p_svg_image) {
- for (NSVGshape *shape = p_svg_image->shapes; shape != nullptr; shape = shape->next) {
- for (int i = 0; i < replace_colors.old_colors.size(); i++) {
- change_nsvg_paint_color(&(shape->stroke), replace_colors.old_colors[i], replace_colors.new_colors[i]);
- change_nsvg_paint_color(&(shape->fill), replace_colors.old_colors[i], replace_colors.new_colors[i]);
- }
- }
-}
+void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, bool p_convert_color) {
+ ERR_FAIL_COND(Math::is_zero_approx(p_scale));
-void ImageLoaderSVG::set_convert_colors(Dictionary *p_replace_color) {
- if (p_replace_color) {
- Dictionary replace_color = *p_replace_color;
- for (int i = 0; i < replace_color.keys().size(); i++) {
- Variant o_c = replace_color.keys()[i];
- Variant n_c = replace_color[replace_color.keys()[i]];
- if (o_c.get_type() == Variant::COLOR && n_c.get_type() == Variant::COLOR) {
- Color old_color = o_c;
- Color new_color = n_c;
- replace_colors.old_colors.push_back(old_color.to_abgr32());
- replace_colors.new_colors.push_back(new_color.to_abgr32());
- }
- }
- } else {
- replace_colors.old_colors.clear();
- replace_colors.new_colors.clear();
+ if (p_convert_color) {
+ _replace_color_property("stop-color=\"", p_string);
+ _replace_color_property("fill=\"", p_string);
+ _replace_color_property("stroke=\"", p_string);
}
-}
-Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const Vector<uint8_t> *p_data, float p_scale, bool upsample, bool convert_colors) {
- NSVGimage *svg_image;
- const uint8_t *src_r = p_data->ptr();
- svg_image = nsvgParse((char *)src_r, "px", 96);
- if (svg_image == nullptr) {
- ERR_PRINT("SVG Corrupted");
- return ERR_FILE_CORRUPT;
- }
+ std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
+ PackedByteArray bytes = p_string.to_utf8_buffer();
- if (convert_colors) {
- _convert_colors(svg_image);
+ tvg::Result result = picture->load((const char *)bytes.ptr(), bytes.size(), "svg", true);
+ if (result != tvg::Result::Success) {
+ return;
}
+ float fw, fh;
+ picture->viewbox(nullptr, nullptr, &fw, &fh);
- const float upscale = upsample ? 2.0 : 1.0;
-
- const int w = (int)(svg_image->width * p_scale * upscale);
- ERR_FAIL_COND_V_MSG(w > Image::MAX_WIDTH, ERR_PARAMETER_RANGE_ERROR, vformat("Can't create image from SVG with scale %s, the resulting image size exceeds max width.", rtos(p_scale)));
-
- const int h = (int)(svg_image->height * p_scale * upscale);
- ERR_FAIL_COND_V_MSG(h > Image::MAX_HEIGHT, ERR_PARAMETER_RANGE_ERROR, vformat("Can't create image from SVG with scale %s, the resulting image size exceeds max height.", rtos(p_scale)));
-
- Vector<uint8_t> dst_image;
- dst_image.resize(w * h * 4);
+ uint32_t width = MIN(fw * p_scale, 16 * 1024);
+ uint32_t height = MIN(fh * p_scale, 16 * 1024);
+ picture->size(width, height);
- uint8_t *dw = dst_image.ptrw();
+ std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen();
+ // Note: memalloc here, be sure to memfree before any return.
+ uint32_t *buffer = (uint32_t *)memalloc(sizeof(uint32_t) * width * height);
- rasterizer.rasterize(svg_image, 0, 0, p_scale * upscale, (unsigned char *)dw, w, h, w * 4);
-
- p_image->create(w, h, false, Image::FORMAT_RGBA8, dst_image);
- if (upsample) {
- p_image->shrink_x2();
+ tvg::Result res = sw_canvas->target(buffer, width, width, height, tvg::SwCanvas::ARGB8888_STRAIGHT);
+ if (res != tvg::Result::Success) {
+ memfree(buffer);
+ ERR_FAIL_MSG("ImageLoaderSVG can't create image.");
}
- nsvgDelete(svg_image);
+ res = sw_canvas->push(move(picture));
+ if (res != tvg::Result::Success) {
+ memfree(buffer);
+ ERR_FAIL_MSG("ImageLoaderSVG can't create image.");
+ }
- return OK;
-}
+ res = sw_canvas->draw();
+ if (res != tvg::Result::Success) {
+ memfree(buffer);
+ ERR_FAIL_MSG("ImageLoaderSVG can't create image.");
+ }
-Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, const char *p_svg_str, float p_scale, bool upsample, bool convert_colors) {
- size_t str_len = strlen(p_svg_str);
- Vector<uint8_t> src_data;
- src_data.resize(str_len + 1);
- uint8_t *src_w = src_data.ptrw();
- memcpy(src_w, p_svg_str, str_len + 1);
+ res = sw_canvas->sync();
+ if (res != tvg::Result::Success) {
+ memfree(buffer);
+ ERR_FAIL_MSG("ImageLoaderSVG can't create image.");
+ }
- return _create_image(p_image, &src_data, p_scale, upsample, convert_colors);
-}
+ Vector<uint8_t> image;
+ image.resize(width * height * sizeof(uint32_t));
+
+ for (uint32_t y = 0; y < height; y++) {
+ for (uint32_t x = 0; x < width; x++) {
+ uint32_t n = buffer[y * width + x];
+ const size_t offset = sizeof(uint32_t) * width * y + sizeof(uint32_t) * x;
+ image.write[offset + 0] = (n >> 16) & 0xff;
+ image.write[offset + 1] = (n >> 8) & 0xff;
+ image.write[offset + 2] = n & 0xff;
+ image.write[offset + 3] = (n >> 24) & 0xff;
+ }
+ }
-Error ImageLoaderSVG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
- uint64_t size = f->get_length();
- Vector<uint8_t> src_image;
- src_image.resize(size + 1);
- uint8_t *src_w = src_image.ptrw();
- f->get_buffer(src_w, size);
- src_w[size] = '\0';
+ res = sw_canvas->clear(true);
+ memfree(buffer);
- return _create_image(p_image, &src_image, p_scale, 1.0);
+ p_image->create(width, height, false, Image::FORMAT_RGBA8, image);
}
void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("svg");
- p_extensions->push_back("svgz");
}
-ImageLoaderSVG::ImageLoaderSVG() {
+Error ImageLoaderSVG::load_image(Ref<Image> p_image, FileAccess *p_fileaccess, bool p_force_linear, float p_scale) {
+ String svg = p_fileaccess->get_as_utf8_string();
+ create_image_from_string(p_image, svg, p_scale, false, false);
+ ERR_FAIL_COND_V(p_image->is_empty(), FAILED);
+ if (p_force_linear) {
+ p_image->srgb_to_linear();
+ }
+ return OK;
}
-
-ImageLoaderSVG::ReplaceColors ImageLoaderSVG::replace_colors;
diff --git a/modules/svg/image_loader_svg.h b/modules/svg/image_loader_svg.h
index 03307c319e..d0bd71d92d 100644
--- a/modules/svg/image_loader_svg.h
+++ b/modules/svg/image_loader_svg.h
@@ -32,38 +32,18 @@
#define IMAGE_LOADER_SVG_H
#include "core/io/image_loader.h"
-#include "core/string/ustring.h"
-
-// Forward declare and include thirdparty headers in .cpp.
-struct NSVGrasterizer;
-struct NSVGimage;
-
-class SVGRasterizer {
- NSVGrasterizer *rasterizer;
-
-public:
- void rasterize(NSVGimage *p_image, float p_tx, float p_ty, float p_scale, unsigned char *p_dst, int p_w, int p_h, int p_stride);
-
- SVGRasterizer();
- ~SVGRasterizer();
-};
class ImageLoaderSVG : public ImageFormatLoader {
- static struct ReplaceColors {
- List<uint32_t> old_colors;
- List<uint32_t> new_colors;
- } replace_colors;
- static SVGRasterizer rasterizer;
- static void _convert_colors(NSVGimage *p_svg_image);
- static Error _create_image(Ref<Image> p_image, const Vector<uint8_t> *p_data, float p_scale, bool upsample, bool convert_colors = false);
+ Dictionary replace_colors;
+ void _replace_color_property(const String &p_prefix, String &r_string);
public:
- static void set_convert_colors(Dictionary *p_replace_color = nullptr);
- static Error create_image_from_string(Ref<Image> p_image, const char *p_svg_str, float p_scale, bool upsample, bool convert_colors = false);
+ // Called by the editor to handle theme icon colors.
+ void set_replace_colors(Dictionary p_replace_colors) { replace_colors = p_replace_colors; }
+ void create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, bool p_convert_color);
- virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- ImageLoaderSVG();
+ virtual Error load_image(Ref<Image> p_image, FileAccess *p_fileaccess, bool p_force_linear, float p_scale) override;
+ virtual void get_recognized_extensions(List<String> *p_extensions) const override;
};
#endif // IMAGE_LOADER_SVG_H
diff --git a/modules/svg/register_types.cpp b/modules/svg/register_types.cpp
index 1560af95c3..a4341c6f1e 100644
--- a/modules/svg/register_types.cpp
+++ b/modules/svg/register_types.cpp
@@ -32,13 +32,23 @@
#include "image_loader_svg.h"
+#include <thorvg.h>
+
static ImageLoaderSVG *image_loader_svg = nullptr;
void register_svg_types() {
+ tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw;
+ if (tvg::Initializer::init(tvgEngine, 0) != tvg::Result::Success) {
+ return;
+ }
image_loader_svg = memnew(ImageLoaderSVG);
ImageLoader::add_image_format_loader(image_loader_svg);
}
void unregister_svg_types() {
+ if (!image_loader_svg) {
+ return;
+ }
memdelete(image_loader_svg);
+ tvg::Initializer::term(tvg::CanvasEngine::Sw);
}
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 6002dc80da..e0ee809331 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -322,7 +322,7 @@ _FORCE_INLINE_ bool is_underscore(char32_t p_char) {
/*************************************************************************/
String TextServerAdvanced::interface_name = "ICU / HarfBuzz / Graphite";
-uint32_t TextServerAdvanced::interface_features = FEATURE_BIDI_LAYOUT | FEATURE_VERTICAL_LAYOUT | FEATURE_SHAPING | FEATURE_KASHIDA_JUSTIFICATION | FEATURE_BREAK_ITERATORS | FEATURE_USE_SUPPORT_DATA | FEATURE_FONT_VARIABLE;
+uint32_t TextServerAdvanced::interface_features = FEATURE_BIDI_LAYOUT | FEATURE_VERTICAL_LAYOUT | FEATURE_SHAPING | FEATURE_KASHIDA_JUSTIFICATION | FEATURE_BREAK_ITERATORS | FEATURE_USE_SUPPORT_DATA | FEATURE_FONT_VARIABLE | FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION;
bool TextServerAdvanced::has_feature(Feature p_feature) const {
return (interface_features & p_feature) == p_feature;
@@ -5229,6 +5229,40 @@ String TextServerAdvanced::strip_diacritics(const String &p_string) const {
return result;
}
+String TextServerAdvanced::string_to_upper(const String &p_string, const String &p_language) const {
+ // Convert to UTF-16.
+ Char16String utf16 = p_string.utf16();
+
+ Char16String upper;
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t len = u_strToUpper(nullptr, 0, utf16.ptr(), -1, p_language.ascii().get_data(), &err);
+ ERR_FAIL_COND_V_MSG(err != U_BUFFER_OVERFLOW_ERROR, p_string, u_errorName(err));
+ upper.resize(len);
+ err = U_ZERO_ERROR;
+ u_strToUpper(upper.ptrw(), len, utf16.ptr(), -1, p_language.ascii().get_data(), &err);
+ ERR_FAIL_COND_V_MSG(U_FAILURE(err), p_string, u_errorName(err));
+
+ // Convert back to UTF-32.
+ return String::utf16(upper.ptr(), len);
+}
+
+String TextServerAdvanced::string_to_lower(const String &p_string, const String &p_language) const {
+ // Convert to UTF-16.
+ Char16String utf16 = p_string.utf16();
+
+ Char16String lower;
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t len = u_strToLower(nullptr, 0, utf16.ptr(), -1, p_language.ascii().get_data(), &err);
+ ERR_FAIL_COND_V_MSG(err != U_BUFFER_OVERFLOW_ERROR, p_string, u_errorName(err));
+ lower.resize(len);
+ err = U_ZERO_ERROR;
+ u_strToLower(lower.ptrw(), len, utf16.ptr(), -1, p_language.ascii().get_data(), &err);
+ ERR_FAIL_COND_V_MSG(U_FAILURE(err), p_string, u_errorName(err));
+
+ // Convert back to UTF-32.
+ return String::utf16(lower.ptr(), len);
+}
+
TextServerAdvanced::TextServerAdvanced() {
_insert_num_systems_lang();
_insert_feature_sets();
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index d088219d91..f2ae24cae6 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -527,6 +527,9 @@ public:
virtual String strip_diacritics(const String &p_string) const override;
+ virtual String string_to_upper(const String &p_string, const String &p_language = "") const override;
+ virtual String string_to_lower(const String &p_string, const String &p_language = "") const override;
+
TextServerAdvanced();
~TextServerAdvanced();
};
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index c7a7c4aa70..ffbd2da22d 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -32,6 +32,7 @@
#include "core/error/error_macros.h"
#include "core/string/print_string.h"
+#include "core/string/ucaps.h"
#include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
@@ -3356,6 +3357,34 @@ float TextServerFallback::shaped_text_get_underline_thickness(RID p_shaped) cons
return sd->uthk;
}
+String TextServerFallback::string_to_upper(const String &p_string, const String &p_language) const {
+ String upper = p_string;
+
+ for (int i = 0; i < upper.size(); i++) {
+ const char32_t s = upper[i];
+ const char32_t t = _find_upper(s);
+ if (s != t) { // avoid copy on write
+ upper[i] = t;
+ }
+ }
+
+ return upper;
+}
+
+String TextServerFallback::string_to_lower(const String &p_string, const String &p_language) const {
+ String lower = p_string;
+
+ for (int i = 0; i < lower.size(); i++) {
+ const char32_t s = lower[i];
+ const char32_t t = _find_lower(s);
+ if (s != t) { // avoid copy on write
+ lower[i] = t;
+ }
+ }
+
+ return lower;
+}
+
TextServerFallback::TextServerFallback() {
_insert_feature_sets();
};
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index e8619e0825..b356b90d2c 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -430,6 +430,9 @@ public:
virtual float shaped_text_get_underline_position(RID p_shaped) const override;
virtual float shaped_text_get_underline_thickness(RID p_shaped) const override;
+ virtual String string_to_upper(const String &p_string, const String &p_language = "") const override;
+ virtual String string_to_lower(const String &p_string, const String &p_language = "") const override;
+
TextServerFallback();
~TextServerFallback();
};
diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp
index 0436f90c4c..ec1a8a6b42 100644
--- a/modules/visual_script/editor/visual_script_editor.cpp
+++ b/modules/visual_script/editor/visual_script_editor.cpp
@@ -2655,6 +2655,15 @@ String VisualScriptEditor::get_name() {
}
Ref<Texture2D> VisualScriptEditor::get_theme_icon() {
+ String icon_name = "VisualScript";
+ if (script->is_built_in()) {
+ icon_name += "Internal";
+ }
+
+ if (Control::has_theme_icon(icon_name, "EditorIcons")) {
+ return Control::get_theme_icon(icon_name, SNAME("EditorIcons"));
+ }
+
return Control::get_theme_icon(SNAME("VisualScript"), SNAME("EditorIcons"));
}
diff --git a/modules/visual_script/icons/VisualScriptInternal.svg b/modules/visual_script/icons/VisualScriptInternal.svg
new file mode 100644
index 0000000000..ea83047a29
--- /dev/null
+++ b/modules/visual_script/icons/VisualScriptInternal.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="3" cy="3.000024" fill="#6e6e6e" r="0"/><path d="m11 10a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324-1 2 2 0 0 0 0-2 2 2 0 0 0 -1.7324-1h2v-2z" fill="#e0e0e0"/><path d="m3 10v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4z" fill="#e0e0e0"/><path d="m7 1-.56445 2.2578a5 5 0 0 0 -.68945.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -.28516.68555l-2.2539.5625v2h5.2715a2 2 0 0 1 -.27148-1 2 2 0 0 1 2-2 2 2 0 0 1 2 2 2 2 0 0 1 -.26953 1h5.2695v-2l-2.2578-.56445a5 5 0 0 0 -.2793-.6875l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -.68555-.28516l-.5625-2.2539h-2z" fill="none" stroke="#e0e0e0"/></svg>