diff options
1344 files changed, 38531 insertions, 14387 deletions
diff --git a/.github/workflows/javascript_builds.yml b/.github/workflows/javascript_builds.yml index 395dfdd7f5..00c79e8ba0 100644 --- a/.github/workflows/javascript_builds.yml +++ b/.github/workflows/javascript_builds.yml @@ -6,7 +6,7 @@ env: # Only used for the cache key. Increment version to force clean build. GODOT_BASE_BRANCH: master SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no - EM_VERSION: 2.0.27 + EM_VERSION: 3.1.10 EM_CACHE_FOLDER: "emsdk-cache" concurrency: diff --git a/core/config/engine.cpp b/core/config/engine.cpp index ff8a8d283f..782d369ae6 100644 --- a/core/config/engine.cpp +++ b/core/config/engine.cpp @@ -208,9 +208,9 @@ void Engine::add_singleton(const Singleton &p_singleton) { } Object *Engine::get_singleton_object(const StringName &p_name) const { - const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name); + HashMap<StringName, Object *>::ConstIterator E = singleton_ptrs.find(p_name); ERR_FAIL_COND_V_MSG(!E, nullptr, "Failed to retrieve non-existent singleton '" + String(p_name) + "'."); - return E->get(); + return E->value; } bool Engine::is_singleton_user_created(const StringName &p_name) const { diff --git a/core/config/engine.h b/core/config/engine.h index eac96852b3..82e3ee5487 100644 --- a/core/config/engine.h +++ b/core/config/engine.h @@ -69,7 +69,7 @@ private: bool _in_physics = false; List<Singleton> singletons; - Map<StringName, Object *> singleton_ptrs; + HashMap<StringName, Object *> singleton_ptrs; bool editor_hint = false; bool project_manager_hint = false; diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 79fa6a0895..4638d70e59 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -331,7 +331,7 @@ struct _VCSort { void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const { _THREAD_SAFE_METHOD_ - Set<_VCSort> vclist; + RBSet<_VCSort> vclist; for (const KeyValue<StringName, VariantContainer> &E : props) { const VariantContainer *v = &E.value; @@ -360,7 +360,7 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const { vclist.insert(vc); } - for (Set<_VCSort>::Element *E = vclist.front(); E; E = E->next()) { + for (RBSet<_VCSort>::Element *E = vclist.front(); E; E = E->next()) { String prop_info_name = E->get().name; int dot = prop_info_name.find("."); if (dot != -1 && !custom_prop_info.has(prop_info_name)) { @@ -764,7 +764,7 @@ Error ProjectSettings::save() { return error; } -Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) { +Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) { Error err; Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err); ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.binary at " + p_file + "."); @@ -800,19 +800,20 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str file->store_32(count); //store how many properties are saved } - for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) { - for (String &key : E->get()) { - if (!E->key().is_empty()) { - key = E->key() + "/" + key; + for (const KeyValue<String, List<String>> &E : props) { + for (const String &key : E.value) { + String k = key; + if (!E.key.is_empty()) { + k = E.key + "/" + k; } Variant value; - if (p_custom.has(key)) { - value = p_custom[key]; + if (p_custom.has(k)) { + value = p_custom[k]; } else { - value = get(key); + value = get(k); } - file->store_pascal_string(key); + file->store_pascal_string(k); int len; err = encode_variant(value, nullptr, len, true); @@ -831,7 +832,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str return OK; } -Error ProjectSettings::_save_settings_text(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) { +Error ProjectSettings::_save_settings_text(const String &p_file, const RBMap<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) { Error err; Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err); @@ -852,18 +853,18 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin } file->store_string("\n"); - for (const Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) { - if (E != props.front()) { + for (const KeyValue<String, List<String>> &E : props) { + if (E.key != props.begin()->key) { file->store_string("\n"); } - if (!E->key().is_empty()) { - file->store_string("[" + E->key() + "]\n\n"); + if (!E.key.is_empty()) { + file->store_string("[" + E.key + "]\n\n"); } - for (const String &F : E->get()) { + for (const String &F : E.value) { String key = F; - if (!E->key().is_empty()) { - key = E->key() + "/" + key; + if (!E.key.is_empty()) { + key = E.key + "/" + key; } Variant value; if (p_custom.has(key)) { @@ -917,7 +918,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust project_features = _trim_to_supported_features(project_features); set_setting("application/config/features", project_features); - Set<_VCSort> vclist; + RBSet<_VCSort> vclist; if (p_merge_with_current) { for (const KeyValue<StringName, VariantContainer> &G : props) { @@ -946,19 +947,19 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust for (const KeyValue<String, Variant> &E : p_custom) { // Lookup global prop to store in the same order - Map<StringName, VariantContainer>::Element *global_prop = props.find(E.key); + RBMap<StringName, VariantContainer>::Iterator global_prop = props.find(E.key); _VCSort vc; vc.name = E.key; - vc.order = global_prop ? global_prop->get().order : 0xFFFFFFF; + vc.order = global_prop ? global_prop->value.order : 0xFFFFFFF; vc.type = E.value.get_type(); vc.flags = PROPERTY_USAGE_STORAGE; vclist.insert(vc); } - Map<String, List<String>> props; + RBMap<String, List<String>> props; - for (Set<_VCSort>::Element *E = vclist.front(); E; E = E->next()) { + for (RBSet<_VCSort>::Element *E = vclist.front(); E; E = E->next()) { String category = E->get().name; String name = E->get().name; @@ -1051,7 +1052,7 @@ void ProjectSettings::set_custom_property_info(const String &p_prop, const Prope custom_prop_info[p_prop].name = p_prop; } -const Map<StringName, PropertyInfo> &ProjectSettings::get_custom_property_info() const { +const HashMap<StringName, PropertyInfo> &ProjectSettings::get_custom_property_info() const { return custom_prop_info; } @@ -1091,7 +1092,7 @@ bool ProjectSettings::has_custom_feature(const String &p_feature) const { return custom_features.has(p_feature); } -OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> ProjectSettings::get_autoload_list() const { +const HashMap<StringName, ProjectSettings::AutoloadInfo> &ProjectSettings::get_autoload_list() const { return autoloads; } @@ -1135,13 +1136,13 @@ void ProjectSettings::_bind_methods() { void ProjectSettings::_add_builtin_input_map() { if (InputMap::get_singleton()) { - OrderedHashMap<String, List<Ref<InputEvent>>> builtins = InputMap::get_singleton()->get_builtins(); + HashMap<String, List<Ref<InputEvent>>> builtins = InputMap::get_singleton()->get_builtins(); - for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) { + for (KeyValue<String, List<Ref<InputEvent>>> &E : builtins) { Array events; // Convert list of input events into array - for (List<Ref<InputEvent>>::Element *I = E.get().front(); I; I = I->next()) { + for (List<Ref<InputEvent>>::Element *I = E.value.front(); I; I = I->next()) { events.push_back(I->get()); } @@ -1149,7 +1150,7 @@ void ProjectSettings::_add_builtin_input_map() { action["deadzone"] = Variant(0.5f); action["events"] = events; - String action_name = "input/" + E.key(); + String action_name = "input/" + E.key; GLOBAL_DEF(action_name, action); input_presets.push_back(action_name); } @@ -1175,6 +1176,22 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("application/config/use_custom_user_dir", false); GLOBAL_DEF("application/config/custom_user_dir_name", ""); GLOBAL_DEF("application/config/project_settings_override", ""); + + GLOBAL_DEF_BASIC("display/window/size/viewport_width", 1024); + custom_prop_info["display/window/size/viewport_width"] = PropertyInfo(Variant::INT, "display/window/size/viewport_width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"); // 8K resolution + + GLOBAL_DEF_BASIC("display/window/size/viewport_height", 600); + custom_prop_info["display/window/size/viewport_height"] = PropertyInfo(Variant::INT, "display/window/size/viewport_height", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"); // 8K resolution + + GLOBAL_DEF_BASIC("display/window/size/resizable", true); + GLOBAL_DEF_BASIC("display/window/size/borderless", false); + GLOBAL_DEF_BASIC("display/window/size/fullscreen", false); + GLOBAL_DEF("display/window/size/always_on_top", false); + GLOBAL_DEF("display/window/size/window_width_override", 0); + custom_prop_info["display/window/size/window_width_override"] = PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"); // 8K resolution + GLOBAL_DEF("display/window/size/window_height_override", 0); + custom_prop_info["display/window/size/window_height_override"] = PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"); // 8K resolution + GLOBAL_DEF_BASIC("audio/buses/default_bus_layout", "res://default_bus_layout.tres"); custom_prop_info["audio/buses/default_bus_layout"] = PropertyInfo(Variant::STRING, "audio/buses/default_bus_layout", PROPERTY_HINT_FILE, "*.tres"); diff --git a/core/config/project_settings.h b/core/config/project_settings.h index 614a11f726..bacc8adc54 100644 --- a/core/config/project_settings.h +++ b/core/config/project_settings.h @@ -33,15 +33,15 @@ #include "core/object/class_db.h" #include "core/os/thread_safe.h" -#include "core/templates/ordered_hash_map.h" -#include "core/templates/set.h" +#include "core/templates/hash_map.h" +#include "core/templates/rb_set.h" class ProjectSettings : public Object { GDCLASS(ProjectSettings, Object); _THREAD_SAFE_CLASS_ public: - typedef Map<String, Variant> CustomMap; + typedef HashMap<String, Variant> CustomMap; static const String PROJECT_DATA_DIR_NAME_SUFFIX; enum { @@ -84,17 +84,17 @@ protected: int last_builtin_order = 0; uint64_t last_save_time = 0; - Map<StringName, VariantContainer> props; + RBMap<StringName, VariantContainer> props; // NOTE: Key order is used e.g. in the save_custom method. String resource_path; - Map<StringName, PropertyInfo> custom_prop_info; + HashMap<StringName, PropertyInfo> custom_prop_info; bool disable_feature_overrides = false; bool using_datapack = false; List<String> input_presets; - Set<String> custom_features; - Map<StringName, StringName> feature_overrides; + RBSet<String> custom_features; + HashMap<StringName, StringName> feature_overrides; - OrderedHashMap<StringName, AutoloadInfo> autoloads; + HashMap<StringName, AutoloadInfo> autoloads; String project_data_dir_name; @@ -108,8 +108,8 @@ protected: Error _load_settings_binary(const String &p_path); Error _load_settings_text_or_binary(const String &p_text_path, const String &p_bin_path); - Error _save_settings_text(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String()); - Error _save_settings_binary(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String()); + Error _save_settings_text(const String &p_file, const RBMap<String, List<String>> &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String()); + Error _save_settings_binary(const String &p_file, const RBMap<String, List<String>> &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String()); Error _save_custom_bnd(const String &p_file); @@ -168,7 +168,7 @@ public: Error save_custom(const String &p_path = "", const CustomMap &p_custom = CustomMap(), const Vector<String> &p_custom_features = Vector<String>(), bool p_merge_with_current = true); Error save(); void set_custom_property_info(const String &p_prop, const PropertyInfo &p_info); - const Map<StringName, PropertyInfo> &get_custom_property_info() const; + const HashMap<StringName, PropertyInfo> &get_custom_property_info() const; uint64_t get_last_saved_time() { return last_save_time; } Vector<String> get_optimizer_presets() const; @@ -181,7 +181,7 @@ public: bool has_custom_feature(const String &p_feature) const; - OrderedHashMap<StringName, AutoloadInfo> get_autoload_list() const; + const HashMap<StringName, AutoloadInfo> &get_autoload_list() const; void add_autoload(const AutoloadInfo &p_autoload); void remove_autoload(const StringName &p_autoload); bool has_autoload(const StringName &p_autoload) const; diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 7c3cbfe48d..194c7fdefd 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -439,7 +439,7 @@ void OS::print_resources_by_type(const Vector<String> &p_types) { print_line(vformat("Resources currently in use for the following types: %s", p_types)); - Map<String, int> type_count; + RBMap<String, int> type_count; List<Ref<Resource>> resources; ResourceCache::get_cached_resources(&resources); diff --git a/core/core_bind.h b/core/core_bind.h index 76313dc1a8..e4d15d5c9d 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -680,8 +680,8 @@ public: class EngineDebugger : public Object { GDCLASS(EngineDebugger, Object); - Map<StringName, Callable> captures; - Map<StringName, Ref<EngineProfiler>> profilers; + HashMap<StringName, Callable> captures; + HashMap<StringName, Ref<EngineProfiler>> profilers; protected: static void _bind_methods(); diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 2a514b68d8..a53929a3af 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -703,6 +703,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_NEGATE", Variant::OP_NEGATE); BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_POSITIVE", Variant::OP_POSITIVE); BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_MODULE", Variant::OP_MODULE); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_POWER", Variant::OP_POWER); //bitwise BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_SHIFT_LEFT", Variant::OP_SHIFT_LEFT); BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_SHIFT_RIGHT", Variant::OP_SHIFT_RIGHT); diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index 54760d8d65..263c75760b 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -39,9 +39,9 @@ EngineDebugger *EngineDebugger::singleton = nullptr; ScriptDebugger *EngineDebugger::script_debugger = nullptr; -Map<StringName, EngineDebugger::Profiler> EngineDebugger::profilers; -Map<StringName, EngineDebugger::Capture> EngineDebugger::captures; -Map<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols; +HashMap<StringName, EngineDebugger::Profiler> EngineDebugger::profilers; +HashMap<StringName, EngineDebugger::Capture> EngineDebugger::captures; +HashMap<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols; void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) { ERR_FAIL_COND_MSG(profilers.has(p_name), "Profiler already registered: " + p_name); diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h index fdfa41c9cc..a8a791f9b0 100644 --- a/core/debugger/engine_debugger.h +++ b/core/debugger/engine_debugger.h @@ -33,7 +33,7 @@ #include "core/string/string_name.h" #include "core/string/ustring.h" -#include "core/templates/map.h" +#include "core/templates/hash_map.h" #include "core/templates/vector.h" #include "core/variant/array.h" #include "core/variant/variant.h" @@ -96,9 +96,9 @@ protected: static EngineDebugger *singleton; static ScriptDebugger *script_debugger; - static Map<StringName, Profiler> profilers; - static Map<StringName, Capture> captures; - static Map<String, CreatePeerFunc> protocols; + static HashMap<StringName, Profiler> profilers; + static HashMap<StringName, Capture> captures; + static HashMap<String, CreatePeerFunc> protocols; public: _FORCE_INLINE_ static EngineDebugger *get_singleton() { return singleton; } diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp index 4ed4c97c64..f378ba94c3 100644 --- a/core/debugger/local_debugger.cpp +++ b/core/debugger/local_debugger.cpp @@ -241,14 +241,14 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } else if (line.begins_with("br") || line.begins_with("break")) { if (line.get_slice_count(" ") <= 1) { - const Map<int, Set<StringName>> &breakpoints = script_debugger->get_breakpoints(); + const HashMap<int, RBSet<StringName>> &breakpoints = script_debugger->get_breakpoints(); if (breakpoints.size() == 0) { print_line("No Breakpoints."); continue; } print_line("Breakpoint(s): " + itos(breakpoints.size())); - for (const KeyValue<int, Set<StringName>> &E : breakpoints) { + for (const KeyValue<int, RBSet<StringName>> &E : breakpoints) { print_line("\t" + String(E.value.front()->get()) + ":" + itos(E.key)); } diff --git a/core/debugger/local_debugger.h b/core/debugger/local_debugger.h index ecd805a6cb..c687214c65 100644 --- a/core/debugger/local_debugger.h +++ b/core/debugger/local_debugger.h @@ -42,7 +42,7 @@ private: ScriptsProfiler *scripts_profiler = nullptr; String target_function; - Map<String, String> options; + HashMap<String, String> options; Pair<String, int> to_breakpoint(const String &p_line); void print_variables(const List<String> &names, const List<Variant> &values, const String &variable_prefix); diff --git a/core/debugger/script_debugger.cpp b/core/debugger/script_debugger.cpp index 4dd93249ef..1efa7f7690 100644 --- a/core/debugger/script_debugger.cpp +++ b/core/debugger/script_debugger.cpp @@ -50,7 +50,7 @@ int ScriptDebugger::get_depth() const { void ScriptDebugger::insert_breakpoint(int p_line, const StringName &p_source) { if (!breakpoints.has(p_line)) { - breakpoints[p_line] = Set<StringName>(); + breakpoints[p_line] = RBSet<StringName>(); } breakpoints[p_line].insert(p_source); } diff --git a/core/debugger/script_debugger.h b/core/debugger/script_debugger.h index feb6702b54..a5a72d7c54 100644 --- a/core/debugger/script_debugger.h +++ b/core/debugger/script_debugger.h @@ -33,8 +33,8 @@ #include "core/object/script_language.h" #include "core/string/string_name.h" -#include "core/templates/map.h" -#include "core/templates/set.h" +#include "core/templates/rb_map.h" +#include "core/templates/rb_set.h" #include "core/templates/vector.h" class ScriptDebugger { @@ -44,7 +44,7 @@ class ScriptDebugger { int depth = -1; bool skip_breakpoints = false; - Map<int, Set<StringName>> breakpoints; + HashMap<int, RBSet<StringName>> breakpoints; ScriptLanguage *break_lang = nullptr; Vector<StackInfo> error_stack_info; @@ -66,7 +66,7 @@ public: bool is_breakpoint(int p_line, const StringName &p_source) const; bool is_breakpoint_line(int p_line) const; void clear_breakpoints(); - const Map<int, Set<StringName>> &get_breakpoints() const { return breakpoints; } + const HashMap<int, RBSet<StringName>> &get_breakpoints() const { return breakpoints; } void debug(ScriptLanguage *p_lang, bool p_can_continue = true, bool p_is_error_breakpoint = false); ScriptLanguage *get_break_language() const; diff --git a/core/doc_data.h b/core/doc_data.h index 194a39a729..af20b717d7 100644 --- a/core/doc_data.h +++ b/core/doc_data.h @@ -32,7 +32,7 @@ #define DOC_DATA_H #include "core/io/xml_parser.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/variant/variant.h" struct ScriptMemberInfo { @@ -161,7 +161,7 @@ public: Vector<MethodDoc> operators; Vector<MethodDoc> signals; Vector<ConstantDoc> constants; - Map<String, String> enums; + HashMap<String, String> enums; Vector<PropertyDoc> properties; Vector<ThemeItemDoc> theme_properties; bool is_script_doc = false; diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index f64c30dca5..9e8addf8aa 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -267,10 +267,10 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { { Variant::BASIS, "z", vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(double), vec3_elems * 2 * sizeof(double) }, { Variant::TRANSFORM3D, "basis", 0, 0, 0, 0 }, { Variant::TRANSFORM3D, "origin", (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) }, - { Variant::COLOR, "x", 0, 0, 0, 0 }, - { Variant::COLOR, "y", sizeof(float), sizeof(float), sizeof(float), sizeof(float) }, - { Variant::COLOR, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float) }, - { Variant::COLOR, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float) }, + { Variant::COLOR, "r", 0, 0, 0, 0 }, + { Variant::COLOR, "g", sizeof(float), sizeof(float), sizeof(float), sizeof(float) }, + { Variant::COLOR, "b", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float) }, + { Variant::COLOR, "a", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float) }, { Variant::NIL, nullptr, 0, 0, 0, 0 }, }; @@ -334,7 +334,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { { // Global enums and constants. Array constants; - Map<String, List<Pair<String, int>>> enum_list; + HashMap<String, List<Pair<String, int>>> enum_list; for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) { int value = CoreConstants::get_global_constant_value(i); diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h index 4d2682b253..98976b29f6 100644 --- a/core/extension/gdnative_interface.h +++ b/core/extension/gdnative_interface.h @@ -114,6 +114,7 @@ typedef enum { GDNATIVE_VARIANT_OP_NEGATE, GDNATIVE_VARIANT_OP_POSITIVE, GDNATIVE_VARIANT_OP_MODULE, + GDNATIVE_VARIANT_OP_POWER, /* bitwise */ GDNATIVE_VARIANT_OP_SHIFT_LEFT, GDNATIVE_VARIANT_OP_SHIFT_RIGHT, @@ -246,8 +247,6 @@ typedef struct { typedef void *GDNativeExtensionClassLibraryPtr; -typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count); - /* Method */ typedef enum { diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp index db1cbd53b4..5738b42049 100644 --- a/core/extension/native_extension.cpp +++ b/core/extension/native_extension.cpp @@ -426,7 +426,7 @@ Ref<Resource> NativeExtensionResourceLoader::load(const String &p_path, const St return Ref<Resource>(); } - if (!library_path.is_resource_file()) { + if (!library_path.is_resource_file() && !library_path.is_absolute_path()) { library_path = p_path.get_base_dir().plus_file(library_path); } diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h index af5a474e79..8f106f753d 100644 --- a/core/extension/native_extension.h +++ b/core/extension/native_extension.h @@ -45,7 +45,7 @@ class NativeExtension : public Resource { ObjectNativeExtension native_extension; }; - Map<StringName, Extension> extension_classes; + HashMap<StringName, Extension> extension_classes; static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); diff --git a/core/extension/native_extension_manager.cpp b/core/extension/native_extension_manager.cpp index 5436f7d51e..186fcc44f6 100644 --- a/core/extension/native_extension_manager.cpp +++ b/core/extension/native_extension_manager.cpp @@ -90,9 +90,9 @@ Vector<String> NativeExtensionManager::get_loaded_extensions() const { return ret; } Ref<NativeExtension> NativeExtensionManager::get_extension(const String &p_path) { - Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.find(p_path); + HashMap<String, Ref<NativeExtension>>::Iterator E = native_extension_map.find(p_path); ERR_FAIL_COND_V(!E, Ref<NativeExtension>()); - return E->get(); + return E->value; } void NativeExtensionManager::initialize_extensions(NativeExtension::InitializationLevel p_level) { diff --git a/core/extension/native_extension_manager.h b/core/extension/native_extension_manager.h index b8339e4817..5594f6c0de 100644 --- a/core/extension/native_extension_manager.h +++ b/core/extension/native_extension_manager.h @@ -37,7 +37,7 @@ class NativeExtensionManager : public Object { GDCLASS(NativeExtensionManager, Object); int32_t level = -1; - Map<String, Ref<NativeExtension>> native_extension_map; + HashMap<String, Ref<NativeExtension>> native_extension_map; static void _bind_methods(); diff --git a/core/input/input.cpp b/core/input/input.cpp index 40cea2cd80..4befdfac58 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -227,8 +227,8 @@ Input::VelocityTrack::VelocityTrack() { bool Input::is_anything_pressed() const { _THREAD_SAFE_METHOD_ - for (Map<StringName, Input::Action>::Element *E = action_state.front(); E; E = E->next()) { - if (E->get().pressed) { + for (const KeyValue<StringName, Input::Action> &E : action_state) { + if (E.value.pressed) { return true; } } @@ -272,65 +272,65 @@ bool Input::is_action_pressed(const StringName &p_action, bool p_exact) const { bool Input::is_action_just_pressed(const StringName &p_action, bool p_exact) const { ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action)); - const Map<StringName, Action>::Element *E = action_state.find(p_action); + HashMap<StringName, Action>::ConstIterator E = action_state.find(p_action); if (!E) { return false; } - if (p_exact && E->get().exact == false) { + if (p_exact && E->value.exact == false) { return false; } if (Engine::get_singleton()->is_in_physics_frame()) { - return E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames(); + return E->value.pressed && E->value.physics_frame == Engine::get_singleton()->get_physics_frames(); } else { - return E->get().pressed && E->get().process_frame == Engine::get_singleton()->get_process_frames(); + return E->value.pressed && E->value.process_frame == Engine::get_singleton()->get_process_frames(); } } bool Input::is_action_just_released(const StringName &p_action, bool p_exact) const { ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action)); - const Map<StringName, Action>::Element *E = action_state.find(p_action); + HashMap<StringName, Action>::ConstIterator E = action_state.find(p_action); if (!E) { return false; } - if (p_exact && E->get().exact == false) { + if (p_exact && E->value.exact == false) { return false; } if (Engine::get_singleton()->is_in_physics_frame()) { - return !E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames(); + return !E->value.pressed && E->value.physics_frame == Engine::get_singleton()->get_physics_frames(); } else { - return !E->get().pressed && E->get().process_frame == Engine::get_singleton()->get_process_frames(); + return !E->value.pressed && E->value.process_frame == Engine::get_singleton()->get_process_frames(); } } float Input::get_action_strength(const StringName &p_action, bool p_exact) const { ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), 0.0, InputMap::get_singleton()->suggest_actions(p_action)); - const Map<StringName, Action>::Element *E = action_state.find(p_action); + HashMap<StringName, Action>::ConstIterator E = action_state.find(p_action); if (!E) { return 0.0f; } - if (p_exact && E->get().exact == false) { + if (p_exact && E->value.exact == false) { return 0.0f; } - return E->get().strength; + return E->value.strength; } float Input::get_action_raw_strength(const StringName &p_action, bool p_exact) const { - const Map<StringName, Action>::Element *E = action_state.find(p_action); + HashMap<StringName, Action>::ConstIterator E = action_state.find(p_action); if (!E) { return 0.0f; } - if (p_exact && E->get().exact == false) { + if (p_exact && E->value.exact == false) { return 0.0f; } - return E->get().raw_strength; + return E->value.raw_strength; } float Input::get_axis(const StringName &p_negative_action, const StringName &p_positive_action) const { @@ -636,21 +636,21 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em } } - for (OrderedHashMap<StringName, InputMap::Action>::ConstElement E = InputMap::get_singleton()->get_action_map().front(); E; E = E.next()) { - if (InputMap::get_singleton()->event_is_action(p_event, E.key())) { + for (const KeyValue<StringName, InputMap::Action> &E : InputMap::get_singleton()->get_action_map()) { + if (InputMap::get_singleton()->event_is_action(p_event, E.key)) { // If not echo and action pressed state has changed - if (!p_event->is_echo() && is_action_pressed(E.key(), false) != p_event->is_action_pressed(E.key())) { + if (!p_event->is_echo() && is_action_pressed(E.key, false) != p_event->is_action_pressed(E.key)) { Action action; action.physics_frame = Engine::get_singleton()->get_physics_frames(); action.process_frame = Engine::get_singleton()->get_process_frames(); - action.pressed = p_event->is_action_pressed(E.key()); + action.pressed = p_event->is_action_pressed(E.key); action.strength = 0.0f; action.raw_strength = 0.0f; - action.exact = InputMap::get_singleton()->event_is_action(p_event, E.key(), true); - action_state[E.key()] = action; + action.exact = InputMap::get_singleton()->event_is_action(p_event, E.key, true); + action_state[E.key] = action; } - action_state[E.key()].strength = p_event->get_action_strength(E.key()); - action_state[E.key()].raw_strength = p_event->get_action_raw_strength(E.key()); + action_state[E.key].strength = p_event->get_action_strength(E.key); + action_state[E.key].raw_strength = p_event->get_action_raw_strength(E.key); } } @@ -1403,12 +1403,12 @@ String Input::get_joy_guid(int p_device) const { Array Input::get_connected_joypads() { Array ret; - Map<int, Joypad>::Element *elem = joy_names.front(); + HashMap<int, Joypad>::Iterator elem = joy_names.begin(); while (elem) { - if (elem->get().connected) { - ret.push_back(elem->key()); + if (elem->value.connected) { + ret.push_back(elem->key); } - elem = elem->next(); + ++elem; } return ret; } diff --git a/core/input/input.h b/core/input/input.h index 5a7cb84ece..7bb7889a43 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -82,11 +82,11 @@ public: private: MouseButton mouse_button_mask = MouseButton::NONE; - Set<Key> physical_keys_pressed; - Set<Key> keys_pressed; - Set<JoyButton> joy_buttons_pressed; - Map<JoyAxis, float> _joy_axis; - //Map<StringName,int> custom_action_press; + RBSet<Key> physical_keys_pressed; + RBSet<Key> keys_pressed; + RBSet<JoyButton> joy_buttons_pressed; + RBMap<JoyAxis, float> _joy_axis; + //RBMap<StringName,int> custom_action_press; Vector3 gravity; Vector3 accelerometer; Vector3 magnetometer; @@ -103,7 +103,7 @@ private: float raw_strength; }; - Map<StringName, Action> action_state; + HashMap<StringName, Action> action_state; bool emulate_touch_from_mouse = false; bool emulate_mouse_from_touch = false; @@ -137,8 +137,8 @@ private: }; VelocityTrack mouse_velocity_track; - Map<int, VelocityTrack> touch_velocity_track; - Map<int, Joypad> joy_names; + HashMap<int, VelocityTrack> touch_velocity_track; + HashMap<int, Joypad> joy_names; int fallback_mapping = -1; CursorShape default_shape = CURSOR_ARROW; @@ -231,7 +231,7 @@ protected: uint64_t timestamp; }; - Map<int, VibrationInfo> joy_vibration; + HashMap<int, VibrationInfo> joy_vibration; static void _bind_methods(); diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index ab94c00999..942c5248df 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -119,8 +119,8 @@ List<StringName> InputMap::get_actions() const { return actions; } - for (OrderedHashMap<StringName, Action>::Element E = input_map.front(); E; E = E.next()) { - actions.push_back(E.key()); + for (const KeyValue<StringName, Action> &E : input_map) { + actions.push_back(E.key); } return actions; @@ -203,12 +203,12 @@ Array InputMap::_action_get_events(const StringName &p_action) { } const List<Ref<InputEvent>> *InputMap::action_get_events(const StringName &p_action) { - const OrderedHashMap<StringName, Action>::Element E = input_map.find(p_action); + HashMap<StringName, Action>::Iterator E = input_map.find(p_action); if (!E) { return nullptr; } - return &E.get().inputs; + return &E->value.inputs; } bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match) const { @@ -216,7 +216,7 @@ bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName } bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength) const { - OrderedHashMap<StringName, Action>::Element E = input_map.find(p_action); + HashMap<StringName, Action>::Iterator E = input_map.find(p_action); ERR_FAIL_COND_V_MSG(!E, false, suggest_actions(p_action)); Ref<InputEventAction> input_event_action = p_event; @@ -235,11 +235,11 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str return input_event_action->get_action() == p_action; } - List<Ref<InputEvent>>::Element *event = _find_event(E.get(), p_event, p_exact_match, r_pressed, r_strength, r_raw_strength); + List<Ref<InputEvent>>::Element *event = _find_event(E->value, p_event, p_exact_match, r_pressed, r_strength, r_raw_strength); return event != nullptr; } -const OrderedHashMap<StringName, InputMap::Action> &InputMap::get_action_map() const { +const HashMap<StringName, InputMap::Action> &InputMap::get_action_map() const { return input_map; } @@ -360,7 +360,7 @@ String InputMap::get_builtin_display_name(const String &p_name) const { return p_name; } -const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() { +const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() { // Return cache if it has already been built. if (default_builtin_cache.size()) { return default_builtin_cache; @@ -686,19 +686,19 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() { return default_builtin_cache; } -const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_feature_overrides_applied() { +const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_feature_overrides_applied() { if (default_builtin_with_overrides_cache.size() > 0) { return default_builtin_with_overrides_cache; } - OrderedHashMap<String, List<Ref<InputEvent>>> builtins = get_builtins(); + const HashMap<String, List<Ref<InputEvent>>> &builtins = get_builtins(); // Get a list of all built in inputs which are valid overrides for the OS // Key = builtin name (e.g. ui_accept) // Value = override/feature names (e.g. macos, if it was defined as "ui_accept.macos" and the platform supports that feature) - Map<String, Vector<String>> builtins_with_overrides; - for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) { - String fullname = E.key(); + HashMap<String, Vector<String>> builtins_with_overrides; + for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) { + String fullname = E.key; Vector<String> split = fullname.split("."); String name = split[0]; @@ -709,8 +709,8 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with } } - for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) { - String fullname = E.key(); + for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) { + String fullname = E.key; Vector<String> split = fullname.split("."); String name = split[0]; @@ -726,22 +726,22 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with continue; } - default_builtin_with_overrides_cache.insert(name, E.value()); + default_builtin_with_overrides_cache.insert(name, E.value); } return default_builtin_with_overrides_cache; } void InputMap::load_default() { - OrderedHashMap<String, List<Ref<InputEvent>>> builtins = get_builtins_with_feature_overrides_applied(); + HashMap<String, List<Ref<InputEvent>>> builtins = get_builtins_with_feature_overrides_applied(); - for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) { - String name = E.key(); + for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) { + String name = E.key; add_action(name); - List<Ref<InputEvent>> inputs = E.get(); - for (List<Ref<InputEvent>>::Element *I = inputs.front(); I; I = I->next()) { + const List<Ref<InputEvent>> &inputs = E.value; + for (const List<Ref<InputEvent>>::Element *I = inputs.front(); I; I = I->next()) { Ref<InputEventKey> iek = I->get(); // For the editor, only add keyboard actions. diff --git a/core/input/input_map.h b/core/input/input_map.h index 79b4d1038f..2400a4a3f7 100644 --- a/core/input/input_map.h +++ b/core/input/input_map.h @@ -34,7 +34,7 @@ #include "core/input/input_event.h" #include "core/object/class_db.h" #include "core/object/object.h" -#include "core/templates/ordered_hash_map.h" +#include "core/templates/hash_map.h" class InputMap : public Object { GDCLASS(InputMap, Object); @@ -54,9 +54,9 @@ public: private: static InputMap *singleton; - mutable OrderedHashMap<StringName, Action> input_map; - OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_cache; - OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_with_overrides_cache; + mutable HashMap<StringName, Action> input_map; + HashMap<String, List<Ref<InputEvent>>> default_builtin_cache; + HashMap<String, List<Ref<InputEvent>>> default_builtin_with_overrides_cache; List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const; @@ -85,7 +85,7 @@ public: bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false) const; bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const; - const OrderedHashMap<StringName, Action> &get_action_map() const; + const HashMap<StringName, Action> &get_action_map() const; void load_from_project_settings(); void load_default(); @@ -93,8 +93,8 @@ public: String get_builtin_display_name(const String &p_name) const; // Use an Ordered Map so insertion order is preserved. We want the elements to be 'grouped' somewhat. - const OrderedHashMap<String, List<Ref<InputEvent>>> &get_builtins(); - const OrderedHashMap<String, List<Ref<InputEvent>>> &get_builtins_with_feature_overrides_applied(); + const HashMap<String, List<Ref<InputEvent>>> &get_builtins(); + const HashMap<String, List<Ref<InputEvent>>> &get_builtins_with_feature_overrides_applied(); InputMap(); ~InputMap(); diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index bc24cac955..dd0191f43f 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -73,7 +73,7 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V } else { if (!values.has(p_section)) { - values[p_section] = OrderedHashMap<String, Variant>(); + values[p_section] = HashMap<String, Variant>(); } values[p_section][p_key] = p_value; @@ -102,16 +102,16 @@ bool ConfigFile::has_section_key(const String &p_section, const String &p_key) c } void ConfigFile::get_sections(List<String> *r_sections) const { - for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::ConstElement E = values.front(); E; E = E.next()) { - r_sections->push_back(E.key()); + for (const KeyValue<String, HashMap<String, Variant>> &E : values) { + r_sections->push_back(E.key); } } void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const { ERR_FAIL_COND_MSG(!values.has(p_section), vformat("Cannot get keys from nonexistent section \"%s\".", p_section)); - for (OrderedHashMap<String, Variant>::ConstElement E = values[p_section].front(); E; E = E.next()) { - r_keys->push_back(E.key()); + for (const KeyValue<String, Variant> &E : values[p_section]) { + r_keys->push_back(E.key); } } @@ -174,18 +174,21 @@ Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass } Error ConfigFile::_internal_save(Ref<FileAccess> file) { - for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::Element E = values.front(); E; E = E.next()) { - if (E != values.front()) { + bool first = true; + for (const KeyValue<String, HashMap<String, Variant>> &E : values) { + if (first) { + first = false; + } else { file->store_string("\n"); } - if (!E.key().is_empty()) { - file->store_string("[" + E.key() + "]\n\n"); + if (!E.key.is_empty()) { + file->store_string("[" + E.key + "]\n\n"); } - for (OrderedHashMap<String, Variant>::Element F = E.get().front(); F; F = F.next()) { + for (const KeyValue<String, Variant> &F : E.value) { String vstr; - VariantWriter::write_to_string(F.get(), vstr); - file->store_string(F.key().property_name_encode() + "=" + vstr + "\n"); + VariantWriter::write_to_string(F.value, vstr); + file->store_string(F.key.property_name_encode() + "=" + vstr + "\n"); } } diff --git a/core/io/config_file.h b/core/io/config_file.h index 7a52b0e16a..3b07ec52f5 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -33,13 +33,13 @@ #include "core/io/file_access.h" #include "core/object/ref_counted.h" -#include "core/templates/ordered_hash_map.h" +#include "core/templates/hash_map.h" #include "core/variant/variant_parser.h" class ConfigFile : public RefCounted { GDCLASS(ConfigFile, RefCounted); - OrderedHashMap<String, OrderedHashMap<String, Variant>> values; + HashMap<String, HashMap<String, Variant>> values; PackedStringArray _get_sections() const; PackedStringArray _get_section_keys(const String &p_section) const; diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index 943dc72307..499d001234 100644 --- a/core/io/file_access_memory.cpp +++ b/core/io/file_access_memory.cpp @@ -32,13 +32,13 @@ #include "core/config/project_settings.h" #include "core/io/dir_access.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" -static Map<String, Vector<uint8_t>> *files = nullptr; +static HashMap<String, Vector<uint8_t>> *files = nullptr; void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) { if (!files) { - files = memnew((Map<String, Vector<uint8_t>>)); + files = memnew((HashMap<String, Vector<uint8_t>>)); } String name; @@ -84,11 +84,11 @@ Error FileAccessMemory::_open(const String &p_path, int p_mode_flags) { String name = fix_path(p_path); //name = DirAccess::normalize_path(name); - Map<String, Vector<uint8_t>>::Element *E = files->find(name); + HashMap<String, Vector<uint8_t>>::Iterator E = files->find(name); ERR_FAIL_COND_V_MSG(!E, ERR_FILE_NOT_FOUND, "Can't find file '" + p_path + "'."); - data = E->get().ptrw(); - length = E->get().size(); + data = E->value.ptrw(); + length = E->value.size(); pos = 0; return OK; diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h index 214d391c95..c7431752c0 100644 --- a/core/io/file_access_network.h +++ b/core/io/file_access_network.h @@ -52,7 +52,7 @@ class FileAccessNetworkClient { bool quit = false; Mutex mutex; Mutex blockrequest_mutex; - Map<int, FileAccessNetwork *> accesses; + HashMap<int, FileAccessNetwork *> accesses; Ref<StreamPeerTCP> client; int32_t last_id = 0; int32_t lockcount = 0; diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index ba120de68b..89efdc4938 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -406,7 +406,7 @@ Error DirAccessPack::list_dir_begin() { list_dirs.push_back(E.key); } - for (Set<String>::Element *E = current->files.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = current->files.front(); E; E = E->next()) { list_files.push_back(E->get()); } diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 17e87c835a..404ad38c96 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -35,8 +35,8 @@ #include "core/io/file_access.h" #include "core/string/print_string.h" #include "core/templates/list.h" -#include "core/templates/map.h" -#include "core/templates/set.h" +#include "core/templates/rb_map.h" +#include "core/templates/rb_set.h" // Godot's packed file magic header ("GDPC" in ASCII). #define PACK_HEADER_MAGIC 0x43504447 @@ -72,23 +72,20 @@ private: struct PackedDir { PackedDir *parent = nullptr; String name; - Map<String, PackedDir *> subdirs; - Set<String> files; + HashMap<String, PackedDir *> subdirs; + RBSet<String> files; }; struct PathMD5 { uint64_t a = 0; uint64_t b = 0; - bool operator<(const PathMD5 &p_md5) const { - if (p_md5.a == a) { - return b < p_md5.b; - } else { - return a < p_md5.a; - } - } - bool operator==(const PathMD5 &p_md5) const { - return a == p_md5.a && b == p_md5.b; + bool operator==(const PathMD5 &p_val) const { + return (a == p_val.a) && (b == p_val.b); + } + static uint32_t hash(const PathMD5 &p_val) { + uint32_t h = hash_djb2_one_32(p_val.a); + return hash_djb2_one_32(p_val.b, h); } PathMD5() {} @@ -99,7 +96,7 @@ private: } }; - Map<PathMD5, PackedFile> files; + HashMap<PathMD5, PackedFile, PathMD5> files; Vector<PackSource *> sources; @@ -186,15 +183,15 @@ public: Ref<FileAccess> PackedData::try_open_path(const String &p_path) { PathMD5 pmd5(p_path.md5_buffer()); - Map<PathMD5, PackedFile>::Element *E = files.find(pmd5); + HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5); if (!E) { return nullptr; //not found } - if (E->get().offset == 0) { + if (E->value.offset == 0) { return nullptr; //was erased } - return E->get().src->get_file(p_path, &E->get()); + return E->value.src->get_file(p_path, &E->value); } bool PackedData::has_path(const String &p_path) { diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h index ae58d99a66..6ea603546a 100644 --- a/core/io/file_access_zip.h +++ b/core/io/file_access_zip.h @@ -34,7 +34,7 @@ #ifdef MINIZIP_ENABLED #include "core/io/file_access_pack.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "thirdparty/minizip/unzip.h" @@ -55,7 +55,7 @@ private: }; Vector<Package> packages; - Map<String, File> files; + HashMap<String, File> files; static ZipArchive *instance; diff --git a/core/io/image.cpp b/core/io/image.cpp index 661a9f7177..dfba45c4e9 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -436,7 +436,7 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p const uint8_t *rofs = &p_src[((y * p_width) + x) * (read_bytes + (read_alpha ? 1 : 0))]; uint8_t *wofs = &p_dst[((y * p_width) + x) * (write_bytes + (write_alpha ? 1 : 0))]; - uint8_t rgba[4]; + uint8_t rgba[4] = { 0, 0, 0, 255 }; if (read_gray) { rgba[0] = rofs[0]; @@ -454,7 +454,7 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p if (write_gray) { //TODO: not correct grayscale, should use fixed point version of actual weights - wofs[0] = uint8_t((uint16_t(rofs[0]) + uint16_t(rofs[1]) + uint16_t(rofs[2])) / 3); + wofs[0] = uint8_t((uint16_t(rgba[0]) + uint16_t(rgba[1]) + uint16_t(rgba[2])) / 3); } else { for (uint32_t i = 0; i < write_bytes; i++) { wofs[i] = rgba[i]; @@ -1944,12 +1944,15 @@ Vector<uint8_t> Image::get_data() const { } void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { - ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0."); - ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0."); - ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + "."); - ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + "."); - ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); - ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "Image format out of range, please see Image's Format enum."); + ERR_FAIL_COND_MSG(p_width <= 0, "The Image width specified (" + itos(p_width) + " pixels) must be greater than 0 pixels."); + ERR_FAIL_COND_MSG(p_height <= 0, "The Image height specified (" + itos(p_height) + " pixels) must be greater than 0 pixels."); + ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, + "The Image width specified (" + itos(p_width) + " pixels) cannot be greater than " + itos(MAX_WIDTH) + "pixels."); + ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, + "The Image height specified (" + itos(p_height) + " pixels) cannot be greater than " + itos(MAX_HEIGHT) + "pixels."); + ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, + "Too many pixels for Image. Maximum is " + itos(MAX_WIDTH) + "x" + itos(MAX_HEIGHT) + " = " + itos(MAX_PIXELS) + "pixels."); + ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "The Image format specified (" + itos(p_format) + ") is out of range. See Image's Format enum."); int mm = 0; int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); @@ -1967,17 +1970,34 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma } void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { - ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0."); - ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0."); - ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + "."); - ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + "."); - ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); - ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "Image format out of range, please see Image's Format enum."); + ERR_FAIL_COND_MSG(p_width <= 0, "The Image width specified (" + itos(p_width) + " pixels) must be greater than 0 pixels."); + ERR_FAIL_COND_MSG(p_height <= 0, "The Image height specified (" + itos(p_height) + " pixels) must be greater than 0 pixels."); + ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, + "The Image width specified (" + itos(p_width) + " pixels) cannot be greater than " + itos(MAX_WIDTH) + " pixels."); + ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, + "The Image height specified (" + itos(p_height) + " pixels) cannot be greater than " + itos(MAX_HEIGHT) + " pixels."); + ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, + "Too many pixels for Image. Maximum is " + itos(MAX_WIDTH) + "x" + itos(MAX_HEIGHT) + " = " + itos(MAX_PIXELS) + "pixels ."); + ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "The Image format specified (" + itos(p_format) + ") is out of range. See Image's Format enum."); int mm; int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); - ERR_FAIL_COND_MSG(p_data.size() != size, "Expected data size of " + itos(size) + " bytes in Image::create(), got instead " + itos(p_data.size()) + " bytes."); + if (unlikely(p_data.size() != size)) { + String description_mipmaps; + if (p_use_mipmaps) { + const int num_mipmaps = get_image_required_mipmaps(p_width, p_height, p_format); + if (num_mipmaps != 1) { + description_mipmaps = vformat("with %d mipmaps", num_mipmaps); + } else { + description_mipmaps = "with 1 mipmap"; + } + } else { + description_mipmaps = "without mipmaps"; + } + const String description = vformat("%dx%dx%d (%s)", p_width, p_height, get_format_pixel_size(p_format), description_mipmaps); + ERR_FAIL_MSG(vformat("Expected Image data size of %s = %d bytes, got %d bytes instead.", description, size, p_data.size())); + } height = p_height; width = p_width; diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 5156a5cb99..25e3bef5fc 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -267,7 +267,7 @@ Array IP::_get_local_addresses() const { Array IP::_get_local_interfaces() const { Array results; - Map<String, Interface_Info> interfaces; + HashMap<String, Interface_Info> interfaces; get_local_interfaces(&interfaces); for (KeyValue<String, Interface_Info> &E : interfaces) { Interface_Info &c = E.value; @@ -289,7 +289,7 @@ Array IP::_get_local_interfaces() const { } void IP::get_local_addresses(List<IPAddress> *r_addresses) const { - Map<String, Interface_Info> interfaces; + HashMap<String, Interface_Info> interfaces; get_local_interfaces(&interfaces); for (const KeyValue<String, Interface_Info> &E : interfaces) { for (const IPAddress &F : E.value.ip_addresses) { diff --git a/core/io/ip.h b/core/io/ip.h index 06ff8a4d70..4d83515e2b 100644 --- a/core/io/ip.h +++ b/core/io/ip.h @@ -92,7 +92,7 @@ public: virtual void _resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type = TYPE_ANY) const = 0; Array get_resolve_item_addresses(ResolverID p_id) const; - virtual void get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const = 0; + virtual void get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const = 0; void erase_resolve_item(ResolverID p_id); void clear_cache(const String &p_hostname = ""); diff --git a/core/io/json.cpp b/core/io/json.cpp index 4b745dff44..b3a9762e75 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -55,7 +55,7 @@ String JSON::_make_indent(const String &p_indent, int p_size) { return indent_text; } -String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, Set<const void *> &p_markers, bool p_full_precision) { +String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, RBSet<const void *> &p_markers, bool p_full_precision) { String colon = ":"; String end_statement = ""; @@ -529,7 +529,7 @@ Error JSON::_parse_string(const String &p_json, Variant &r_ret, String &r_err_st } String JSON::stringify(const Variant &p_var, const String &p_indent, bool p_sort_keys, bool p_full_precision) { - Set<const void *> markers; + RBSet<const void *> markers; return _stringify(p_var, p_indent, 0, p_sort_keys, markers, p_full_precision); } diff --git a/core/io/json.h b/core/io/json.h index ed251938ec..f883d3963a 100644 --- a/core/io/json.h +++ b/core/io/json.h @@ -70,7 +70,7 @@ class JSON : public RefCounted { static const char *tk_name[]; static String _make_indent(const String &p_indent, int p_size); - static String _stringify(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, Set<const void *> &p_markers, bool p_full_precision = false); + static String _stringify(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, RBSet<const void *> &p_markers, bool p_full_precision = false); static Error _get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str); static Error _parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str); static Error _parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str); diff --git a/core/io/logger.cpp b/core/io/logger.cpp index c19fc2820b..925bfdbd02 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -128,7 +128,7 @@ void RotatedFileLogger::clear_old_backups() { da->list_dir_begin(); String f = da->get_next(); - Set<String> backups; + RBSet<String> backups; while (!f.is_empty()) { if (!da->current_is_dir() && f.begins_with(basename) && f.get_extension() == extension && f != base_path.get_file()) { backups.insert(f); @@ -141,7 +141,7 @@ void RotatedFileLogger::clear_old_backups() { // since backups are appended with timestamp and Set iterates them in sorted order, // first backups are the oldest int to_delete = backups.size() - max_backups; - for (Set<String>::Element *E = backups.front(); E && to_delete > 0; E = E->next(), --to_delete) { + for (RBSet<String>::Element *E = backups.front(); E && to_delete > 0; E = E->next(), --to_delete) { da->remove(E->get()); } } diff --git a/core/io/missing_resource.cpp b/core/io/missing_resource.cpp index 7aae6c6f0a..29814cdeb3 100644 --- a/core/io/missing_resource.cpp +++ b/core/io/missing_resource.cpp @@ -53,8 +53,8 @@ bool MissingResource::_get(const StringName &p_name, Variant &r_ret) const { } void MissingResource::_get_property_list(List<PropertyInfo> *p_list) const { - for (OrderedHashMap<StringName, Variant>::ConstElement E = properties.front(); E; E = E.next()) { - p_list->push_back(PropertyInfo(E.value().get_type(), E.key())); + for (const KeyValue<StringName, Variant> &E : properties) { + p_list->push_back(PropertyInfo(E.value.get_type(), E.key)); } } diff --git a/core/io/missing_resource.h b/core/io/missing_resource.h index e87efe1a98..6536a4119b 100644 --- a/core/io/missing_resource.h +++ b/core/io/missing_resource.h @@ -38,7 +38,7 @@ class MissingResource : public Resource { GDCLASS(MissingResource, Resource) - OrderedHashMap<StringName, Variant> properties; + HashMap<StringName, Variant> properties; String original_class; bool recording_properties = false; diff --git a/core/io/packed_data_container.cpp b/core/io/packed_data_container.cpp index 027fdd51aa..a456318148 100644 --- a/core/io/packed_data_container.cpp +++ b/core/io/packed_data_container.cpp @@ -210,7 +210,7 @@ Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, b } } -uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpdata, Map<String, uint32_t> &string_cache) { +uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpdata, HashMap<String, uint32_t> &string_cache) { switch (p_data.get_type()) { case Variant::STRING: { String s = p_data; @@ -321,7 +321,7 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd Error PackedDataContainer::pack(const Variant &p_data) { Vector<uint8_t> tmpdata; - Map<String, uint32_t> string_cache; + HashMap<String, uint32_t> string_cache; _pack(p_data, tmpdata, string_cache); datalen = tmpdata.size(); data.resize(tmpdata.size()); diff --git a/core/io/packed_data_container.h b/core/io/packed_data_container.h index f042b364ee..73c215aed8 100644 --- a/core/io/packed_data_container.h +++ b/core/io/packed_data_container.h @@ -50,7 +50,7 @@ class PackedDataContainer : public Resource { Vector<uint8_t> data; int datalen = 0; - uint32_t _pack(const Variant &p_data, Vector<uint8_t> &tmpdata, Map<String, uint32_t> &string_cache); + uint32_t _pack(const Variant &p_data, Vector<uint8_t> &tmpdata, HashMap<String, uint32_t> &string_cache); Variant _iter_init_ofs(const Array &p_iter, uint32_t p_offset); Variant _iter_next_ofs(const Array &p_iter, uint32_t p_offset); diff --git a/core/io/resource.cpp b/core/io/resource.cpp index e6535c67a4..4a94c17132 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -193,7 +193,7 @@ void Resource::reload_from_file() { copy_from(s); } -Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache) { +Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache) { List<PropertyInfo> plist; get_property_list(&plist); @@ -228,7 +228,7 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res return r; } -void Resource::configure_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache) { +void Resource::configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache) { List<PropertyInfo> plist; get_property_list(&plist); @@ -317,7 +317,7 @@ void Resource::unregister_owner(Object *p_owner) { } void Resource::notify_change_to_owners() { - for (Set<ObjectID>::Element *E = owners.front(); E; E = E->next()) { + for (RBSet<ObjectID>::Element *E = owners.front(); E; E = E->next()) { Object *obj = ObjectDB::get_instance(E->get()); ERR_CONTINUE_MSG(!obj, "Object was deleted, while still owning a resource."); //wtf //TODO store string @@ -478,10 +478,8 @@ void ResourceCache::clear() { if (resources.size()) { ERR_PRINT("Resources still in use at exit (run with --verbose for details)."); if (OS::get_singleton()->is_stdout_verbose()) { - const String *K = nullptr; - while ((K = resources.next(K))) { - Resource *r = resources[*K]; - print_line(vformat("Resource still in use: %s (%s)", *K, r->get_class())); + for (const KeyValue<String, Resource *> &E : resources) { + print_line(vformat("Resource still in use: %s (%s)", E.key, E.value->get_class())); } } } @@ -516,10 +514,8 @@ Resource *ResourceCache::get(const String &p_path) { void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) { lock.read_lock(); - const String *K = nullptr; - while ((K = resources.next(K))) { - Resource *r = resources[*K]; - p_resources->push_back(Ref<Resource>(r)); + for (KeyValue<String, Resource *> &E : resources) { + p_resources->push_back(Ref<Resource>(E.value)); } lock.read_unlock(); } @@ -536,7 +532,7 @@ void ResourceCache::dump(const char *p_file, bool p_short) { #ifdef DEBUG_ENABLED lock.read_lock(); - Map<String, int> type_count; + HashMap<String, int> type_count; Ref<FileAccess> f; if (p_file) { @@ -544,9 +540,8 @@ void ResourceCache::dump(const char *p_file, bool p_short) { ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file at path '" + String::utf8(p_file) + "'."); } - const String *K = nullptr; - while ((K = resources.next(K))) { - Resource *r = resources[*K]; + for (KeyValue<String, Resource *> &E : resources) { + Resource *r = E.value; if (!type_count.has(r->get_class())) { type_count[r->get_class()] = 0; diff --git a/core/io/resource.h b/core/io/resource.h index 43ae104da5..53c828f9cd 100644 --- a/core/io/resource.h +++ b/core/io/resource.h @@ -54,7 +54,7 @@ public: virtual String get_base_extension() const { return "res"; } private: - Set<ObjectID> owners; + RBSet<ObjectID> owners; friend class ResBase; friend class ResourceCache; @@ -111,8 +111,8 @@ public: String get_scene_unique_id() const; virtual Ref<Resource> duplicate(bool p_subresources = false) const; - Ref<Resource> duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache); - void configure_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache); + Ref<Resource> duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache); + void configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache); void set_local_to_scene(bool p_enable); bool is_local_to_scene() const; diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index fbb4293961..cf87869a32 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -635,8 +635,6 @@ Error ResourceLoaderBinary::load() { return error; } - int stage = 0; - for (int i = 0; i < external_resources.size(); i++) { String path = external_resources[i].path; @@ -674,8 +672,6 @@ Error ResourceLoaderBinary::load() { } } } - - stage++; } for (int i = 0; i < internal_resources.size(); i++) { @@ -700,7 +696,6 @@ Error ResourceLoaderBinary::load() { Ref<Resource> cached = ResourceCache::get(path); if (cached.is_valid()) { //already loaded, don't do anything - stage++; error = OK; internal_index_cache[path] = cached; continue; @@ -817,7 +812,6 @@ Error ResourceLoaderBinary::load() { #ifdef TOOLS_ENABLED res->set_edited(false); #endif - stage++; if (progress) { *progress = (i + 1) / float(internal_resources.size()); @@ -1136,7 +1130,7 @@ void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<Str loader.get_dependencies(f, p_dependencies, p_add_types); } -Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { +Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_path + "'."); @@ -1390,7 +1384,7 @@ void ResourceFormatSaverBinaryInstance::_pad_buffer(Ref<FileAccess> f, int p_byt } } -void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const Variant &p_property, Map<Ref<Resource>, int> &resource_map, Map<Ref<Resource>, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) { +void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const Variant &p_property, HashMap<Ref<Resource>, int> &resource_map, HashMap<Ref<Resource>, int> &external_resources, HashMap<StringName, int> &string_map, const PropertyInfo &p_hint) { switch (p_property.get_type()) { case Variant::NIL: { f->store_32(VARIANT_NIL); @@ -2028,7 +2022,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re // save internal resource table f->store_32(saved_resources.size()); //amount of internal resources Vector<uint64_t> ofs_pos; - Set<String> used_unique_ids; + RBSet<String> used_unique_ids; for (Ref<Resource> &r : saved_resources) { if (r->is_built_in()) { @@ -2042,7 +2036,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re } } - Map<Ref<Resource>, int> resource_map; + HashMap<Ref<Resource>, int> resource_map; int res_index = 0; for (Ref<Resource> &r : saved_resources) { if (r->is_built_in()) { diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 92d4e4eeaa..db29909dd5 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -75,12 +75,12 @@ class ResourceLoaderBinary { }; Vector<IntResource> internal_resources; - Map<String, Ref<Resource>> internal_index_cache; + HashMap<String, Ref<Resource>> internal_index_cache; String get_unicode_string(); void _advance_padding(uint32_t p_len); - Map<String, String> remaps; + HashMap<String, String> remaps; Error error = OK; ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE; @@ -89,7 +89,7 @@ class ResourceLoaderBinary { Error parse_variant(Variant &r_v); - Map<String, Ref<Resource>> dependency_cache; + HashMap<String, Ref<Resource>> dependency_cache; public: void set_local_path(const String &p_local_path); @@ -97,7 +97,7 @@ public: Error load(); void set_translation_remapped(bool p_remapped); - void set_remaps(const Map<String, String> &p_remaps) { remaps = p_remaps; } + void set_remaps(const HashMap<String, String> &p_remaps) { remaps = p_remaps; } void open(Ref<FileAccess> p_f, bool p_no_resources = false, bool p_keep_uuid_paths = false); String recognize(Ref<FileAccess> p_f); void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types); @@ -114,7 +114,7 @@ public: virtual String get_resource_type(const String &p_path) const; virtual ResourceUID::ID get_resource_uid(const String &p_path) const; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); - virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map); + virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map); }; class ResourceFormatSaverBinaryInstance { @@ -127,7 +127,7 @@ class ResourceFormatSaverBinaryInstance { bool big_endian; bool takeover_paths; String magic; - Set<Ref<Resource>> resource_set; + RBSet<Ref<Resource>> resource_set; struct NonPersistentKey { //for resource properties generated on the fly Ref<Resource> base; @@ -135,11 +135,11 @@ class ResourceFormatSaverBinaryInstance { bool operator<(const NonPersistentKey &p_key) const { return base == p_key.base ? property < p_key.property : base < p_key.base; } }; - Map<NonPersistentKey, Ref<Resource>> non_persistent_map; - Map<StringName, int> string_map; + RBMap<NonPersistentKey, Ref<Resource>> non_persistent_map; + HashMap<StringName, int> string_map; Vector<StringName> strings; - Map<Ref<Resource>, int> external_resources; + HashMap<Ref<Resource>, int> external_resources; List<Ref<Resource>> saved_resources; struct Property { @@ -168,7 +168,7 @@ public: RESERVED_FIELDS = 11 }; Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0); - static void write_variant(Ref<FileAccess> f, const Variant &p_property, Map<Ref<Resource>, int> &resource_map, Map<Ref<Resource>, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo()); + static void write_variant(Ref<FileAccess> f, const Variant &p_property, HashMap<Ref<Resource>, int> &resource_map, HashMap<Ref<Resource>, int> &external_resources, HashMap<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo()); }; class ResourceFormatSaverBinary : public ResourceFormatSaver { diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index 984cf06d2b..5deee9721b 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -139,7 +139,7 @@ Ref<Resource> ResourceFormatImporter::load(const String &p_path, const String &p } void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extensions) const { - Set<String> found; + RBSet<String> found; for (int i = 0; i < importers.size(); i++) { List<String> local_exts; @@ -159,7 +159,7 @@ void ResourceFormatImporter::get_recognized_extensions_for_type(const String &p_ return; } - Set<String> found; + RBSet<String> found; for (int i = 0; i < importers.size(); i++) { String res_type = importers[i]->get_resource_type(); diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index b3d777847b..0c7909df06 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -134,15 +134,15 @@ public: virtual String get_preset_name(int p_idx) const { return String(); } virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const = 0; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const = 0; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const = 0; virtual String get_option_group_file() const { return String(); } - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) = 0; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) = 0; virtual bool can_import_threaded() const { return true; } virtual void import_threaded_begin() {} virtual void import_threaded_end() {} - virtual Error import_group_file(const String &p_group_file, const Map<String, Map<StringName, Variant>> &p_source_file_options, const Map<String, String> &p_base_paths) { return ERR_UNAVAILABLE; } + virtual Error import_group_file(const String &p_group_file, const HashMap<String, HashMap<StringName, Variant>> &p_source_file_options, const HashMap<String, String> &p_base_paths) { return ERR_UNAVAILABLE; } virtual bool are_import_settings_valid(const String &p_path) const { return true; } virtual String get_import_settings_string() const { return String(); } }; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index d125dd4e91..9e6330f34b 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -154,7 +154,7 @@ void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> * } } -Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { +Error ResourceFormatLoader::rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) { Dictionary deps_dict; for (KeyValue<String, String> E : p_map) { deps_dict[E.key] = E.value; @@ -391,7 +391,7 @@ float ResourceLoader::_dependency_get_progress(const String &p_path) { int dep_count = load_task.sub_tasks.size(); if (dep_count > 0) { float dep_progress = 0; - for (Set<String>::Element *E = load_task.sub_tasks.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = load_task.sub_tasks.front(); E; E = E->next()) { dep_progress += _dependency_get_progress(E->get()); } dep_progress /= float(dep_count); @@ -733,7 +733,7 @@ void ResourceLoader::get_dependencies(const String &p_path, List<String> *p_depe } } -Error ResourceLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { +Error ResourceLoader::rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) { String local_path = _path_remap(_validate_local_path(p_path)); for (int i = 0; i < loader_count; i++) { diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index ea18ac23fd..e189ad1dff 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -70,7 +70,7 @@ public: virtual String get_resource_type(const String &p_path) const; virtual ResourceUID::ID get_resource_uid(const String &p_path) const; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); - virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map); + virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map); virtual bool is_import_valid(const String &p_path) const { return true; } virtual bool is_imported(const String &p_path) const { return false; } virtual int get_import_order(const String &p_path) const { return 0; } @@ -145,7 +145,7 @@ private: bool start_next = true; int requests = 0; int poll_requests = 0; - Set<String> sub_tasks; + RBSet<String> sub_tasks; }; static void _thread_load_function(void *p_userdata); @@ -173,7 +173,7 @@ public: static String get_resource_type(const String &p_path); static ResourceUID::ID get_resource_uid(const String &p_path); static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); - static Error rename_dependencies(const String &p_path, const Map<String, String> &p_map); + static Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map); static bool is_import_valid(const String &p_path); static String get_import_group_file(const String &p_path); static bool is_imported(const String &p_path); diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp index 515b7c710e..fc324a26da 100644 --- a/core/io/resource_uid.cpp +++ b/core/io/resource_uid.cpp @@ -149,12 +149,12 @@ Error ResourceUID::save_to_cache() { cache_entries = 0; - for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) { - f->store_64(E.key()); - uint32_t s = E.get().cs.length(); + for (KeyValue<ID, Cache> &E : unique_ids) { + f->store_64(E.key); + uint32_t s = E.value.cs.length(); f->store_32(s); - f->store_buffer((const uint8_t *)E.get().cs.ptr(), s); - E.get().saved_to_cache = true; + f->store_buffer((const uint8_t *)E.value.cs.ptr(), s); + E.value.saved_to_cache = true; cache_entries++; } @@ -202,8 +202,8 @@ Error ResourceUID::update_cache() { MutexLock l(mutex); Ref<FileAccess> f; - for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) { - if (!E.get().saved_to_cache) { + for (KeyValue<ID, Cache> &E : unique_ids) { + if (!E.value.saved_to_cache) { if (f.is_null()) { f = FileAccess::open(get_cache_file(), FileAccess::READ_WRITE); //append if (f.is_null()) { @@ -211,11 +211,11 @@ Error ResourceUID::update_cache() { } f->seek_end(); } - f->store_64(E.key()); - uint32_t s = E.get().cs.length(); + f->store_64(E.key); + uint32_t s = E.value.cs.length(); f->store_32(s); - f->store_buffer((const uint8_t *)E.get().cs.ptr(), s); - E.get().saved_to_cache = true; + f->store_buffer((const uint8_t *)E.value.cs.ptr(), s); + E.value.saved_to_cache = true; cache_entries++; } } diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h index 0b7ffdf6d0..da42553cf5 100644 --- a/core/io/resource_uid.h +++ b/core/io/resource_uid.h @@ -33,7 +33,7 @@ #include "core/object/ref_counted.h" #include "core/string/string_name.h" -#include "core/templates/ordered_hash_map.h" +#include "core/templates/hash_map.h" class ResourceUID : public Object { GDCLASS(ResourceUID, Object) @@ -53,7 +53,7 @@ private: bool saved_to_cache = false; }; - OrderedHashMap<ID, Cache> unique_ids; //unique IDs and utf8 paths (less memory used) + HashMap<ID, Cache> unique_ids; //unique IDs and utf8 paths (less memory used) static ResourceUID *singleton; uint32_t cache_entries = 0; diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp index 2cc844b628..e573e8de19 100644 --- a/core/io/zip_io.cpp +++ b/core/io/zip_io.cpp @@ -31,18 +31,19 @@ #include "zip_io.h" void *zipio_open(voidpf opaque, const char *p_fname, int mode) { - ZipIOData *zd = (ZipIOData *)opaque; + Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque); + ERR_FAIL_COND_V(fa == nullptr, nullptr); String fname; fname.parse_utf8(p_fname); if (mode & ZLIB_FILEFUNC_MODE_WRITE) { - zd->f = FileAccess::open(fname, FileAccess::WRITE); + (*fa) = FileAccess::open(fname, FileAccess::WRITE); } else { - zd->f = FileAccess::open(fname, FileAccess::READ); + (*fa) = FileAccess::open(fname, FileAccess::READ); } - if (zd->f.is_null()) { + if (fa->is_null()) { return nullptr; } @@ -50,49 +51,66 @@ void *zipio_open(voidpf opaque, const char *p_fname, int mode) { } uLong zipio_read(voidpf opaque, voidpf stream, void *buf, uLong size) { - ZipIOData *zd = (ZipIOData *)opaque; - return zd->f->get_buffer((uint8_t *)buf, size); + Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque); + ERR_FAIL_COND_V(fa == nullptr, 0); + ERR_FAIL_COND_V(fa->is_null(), 0); + + return (*fa)->get_buffer((uint8_t *)buf, size); } uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size) { - ZipIOData *zd = (ZipIOData *)opaque; - zd->f->store_buffer((uint8_t *)buf, size); + Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque); + ERR_FAIL_COND_V(fa == nullptr, 0); + ERR_FAIL_COND_V(fa->is_null(), 0); + + (*fa)->store_buffer((uint8_t *)buf, size); return size; } long zipio_tell(voidpf opaque, voidpf stream) { - ZipIOData *zd = (ZipIOData *)opaque; - return zd->f->get_position(); + Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque); + ERR_FAIL_COND_V(fa == nullptr, 0); + ERR_FAIL_COND_V(fa->is_null(), 0); + + return (*fa)->get_position(); } long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) { - ZipIOData *zd = (ZipIOData *)opaque; + Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque); + ERR_FAIL_COND_V(fa == nullptr, 0); + ERR_FAIL_COND_V(fa->is_null(), 0); uint64_t pos = offset; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR: - pos = zd->f->get_position() + offset; + pos = (*fa)->get_position() + offset; break; case ZLIB_FILEFUNC_SEEK_END: - pos = zd->f->get_length() + offset; + pos = (*fa)->get_length() + offset; break; default: break; } - zd->f->seek(pos); + (*fa)->seek(pos); return 0; } int zipio_close(voidpf opaque, voidpf stream) { - ZipIOData *zd = (ZipIOData *)opaque; - memdelete(zd); + Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque); + ERR_FAIL_COND_V(fa == nullptr, 0); + ERR_FAIL_COND_V(fa->is_null(), 0); + + fa->unref(); return 0; } int zipio_testerror(voidpf opaque, voidpf stream) { - ZipIOData *zd = (ZipIOData *)opaque; - return (zd->f.is_valid() && zd->f->get_error() != OK) ? 1 : 0; + Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque); + ERR_FAIL_COND_V(fa == nullptr, 1); + ERR_FAIL_COND_V(fa->is_null(), 0); + + return (fa->is_valid() && (*fa)->get_error() != OK) ? 1 : 0; } voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) { @@ -105,9 +123,9 @@ void zipio_free(voidpf opaque, voidpf address) { memfree(address); } -zlib_filefunc_def zipio_create_io() { +zlib_filefunc_def zipio_create_io(Ref<FileAccess> *p_data) { zlib_filefunc_def io; - io.opaque = (void *)memnew(ZipIOData); + io.opaque = (void *)p_data; io.zopen_file = zipio_open; io.zread_file = zipio_read; io.zwrite_file = zipio_write; diff --git a/core/io/zip_io.h b/core/io/zip_io.h index 3bcd1f830d..f137bd2bbf 100644 --- a/core/io/zip_io.h +++ b/core/io/zip_io.h @@ -39,10 +39,6 @@ #include "thirdparty/minizip/unzip.h" #include "thirdparty/minizip/zip.h" -struct ZipIOData { - Ref<FileAccess> f; -}; - void *zipio_open(voidpf opaque, const char *p_fname, int mode); uLong zipio_read(voidpf opaque, voidpf stream, void *buf, uLong size); uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size); @@ -57,6 +53,6 @@ int zipio_testerror(voidpf opaque, voidpf stream); voidpf zipio_alloc(voidpf opaque, uInt items, uInt size); void zipio_free(voidpf opaque, voidpf address); -zlib_filefunc_def zipio_create_io(); +zlib_filefunc_def zipio_create_io(Ref<FileAccess> *p_data); #endif // ZIP_IO_H diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 284b4294ea..a3ee259030 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -151,7 +151,7 @@ void AStar3D::connect_points(int p_id, int p_with_id, bool bidirectional) { s.direction = Segment::BIDIRECTIONAL; } - Set<Segment>::Element *element = segments.find(s); + RBSet<Segment>::Element *element = segments.find(s); if (element != nullptr) { s.direction |= element->get().direction; if (s.direction == Segment::BIDIRECTIONAL) { @@ -177,7 +177,7 @@ void AStar3D::disconnect_points(int p_id, int p_with_id, bool bidirectional) { Segment s(p_id, p_with_id); int remove_direction = bidirectional ? (int)Segment::BIDIRECTIONAL : s.direction; - Set<Segment>::Element *element = segments.find(s); + RBSet<Segment>::Element *element = segments.find(s); if (element != nullptr) { // s is the new segment // Erase the directions to be removed @@ -235,7 +235,7 @@ Vector<int> AStar3D::get_point_connections(int p_id) { bool AStar3D::are_points_connected(int p_id, int p_with_id, bool bidirectional) const { Segment s(p_id, p_with_id); - const Set<Segment>::Element *element = segments.find(s); + const RBSet<Segment>::Element *element = segments.find(s); return element != nullptr && (bidirectional || (element->get().direction & s.direction) == s.direction); @@ -293,7 +293,7 @@ Vector3 AStar3D::get_closest_position_in_segment(const Vector3 &p_point) const { real_t closest_dist = 1e20; Vector3 closest_point; - for (const Set<Segment>::Element *E = segments.front(); E; E = E->next()) { + for (const RBSet<Segment>::Element *E = segments.front(); E; E = E->next()) { Point *from_point = nullptr, *to_point = nullptr; points.lookup(E->get().u, from_point); points.lookup(E->get().v, to_point); diff --git a/core/math/a_star.h b/core/math/a_star.h index bb7112fb09..086be839b5 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -112,7 +112,7 @@ class AStar3D : public RefCounted { uint64_t pass = 1; OAHashMap<int, Point *> points; - Set<Segment> segments; + RBSet<Segment> segments; bool _solve(Point *begin_point, Point *end_point); diff --git a/core/math/color.cpp b/core/math/color.cpp index e32f9147d9..74552a2894 100644 --- a/core/math/color.cpp +++ b/core/math/color.cpp @@ -33,7 +33,7 @@ #include "color_names.inc" #include "core/math/math_funcs.h" #include "core/string/print_string.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" uint32_t Color::to_argb32() const { uint32_t c = (uint8_t)Math::round(a * 255); diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h index 7ad5f76645..f8a10ec87e 100644 --- a/core/math/delaunay_3d.h +++ b/core/math/delaunay_3d.h @@ -323,7 +323,6 @@ public: E = N; } - uint32_t good_triangles = 0; for (uint32_t j = 0; j < triangles.size(); j++) { if (triangles[j].bad) { continue; @@ -360,11 +359,8 @@ public: } } } - - good_triangles++; } - //print_line("at point " + itos(i) + "/" + itos(point_count) + " simplices added " + itos(good_triangles) + "/" + itos(simplex_list.size()) + " - triangles: " + itos(triangles.size())); triangles.clear(); triangles_inserted.clear(); } diff --git a/core/math/disjoint_set.h b/core/math/disjoint_set.h index 8657dc068e..d07c08e45e 100644 --- a/core/math/disjoint_set.h +++ b/core/math/disjoint_set.h @@ -31,11 +31,11 @@ #ifndef DISJOINT_SET_H #define DISJOINT_SET_H -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/templates/vector.h" /* This DisjointSet class uses Find with path compression and Union by rank */ -template <typename T, class C = Comparator<T>, class AL = DefaultAllocator> +template <typename T, class H = HashMapHasherDefault, class C = HashMapComparatorDefault<T>, class AL = DefaultAllocator> class DisjointSet { struct Element { T object; @@ -43,7 +43,7 @@ class DisjointSet { int rank = 0; }; - typedef Map<T, Element *, C, AL> MapT; + typedef HashMap<T, Element *, H, C> MapT; MapT elements; @@ -65,15 +65,15 @@ public: /* FUNCTIONS */ -template <typename T, class C, class AL> -DisjointSet<T, C, AL>::~DisjointSet() { - for (typename MapT::Element *itr = elements.front(); itr != nullptr; itr = itr->next()) { - memdelete_allocator<Element, AL>(itr->value()); +template <typename T, class H, class C, class AL> +DisjointSet<T, H, C, AL>::~DisjointSet() { + for (KeyValue<T, Element *> &E : elements) { + memdelete_allocator<Element, AL>(E.value); } } -template <typename T, class C, class AL> -typename DisjointSet<T, C, AL>::Element *DisjointSet<T, C, AL>::get_parent(Element *element) { +template <typename T, class H, class C, class AL> +typename DisjointSet<T, H, C, AL>::Element *DisjointSet<T, H, C, AL>::get_parent(Element *element) { if (element->parent != element) { element->parent = get_parent(element->parent); } @@ -81,11 +81,11 @@ typename DisjointSet<T, C, AL>::Element *DisjointSet<T, C, AL>::get_parent(Eleme return element->parent; } -template <typename T, class C, class AL> -typename DisjointSet<T, C, AL>::Element *DisjointSet<T, C, AL>::insert_or_get(T object) { - typename MapT::Element *itr = elements.find(object); +template <typename T, class H, class C, class AL> +typename DisjointSet<T, H, C, AL>::Element *DisjointSet<T, H, C, AL>::insert_or_get(T object) { + typename MapT::Iterator itr = elements.find(object); if (itr != nullptr) { - return itr->value(); + return itr->value; } Element *new_element = memnew_allocator(Element, AL); @@ -96,8 +96,8 @@ typename DisjointSet<T, C, AL>::Element *DisjointSet<T, C, AL>::insert_or_get(T return new_element; } -template <typename T, class C, class AL> -void DisjointSet<T, C, AL>::create_union(T a, T b) { +template <typename T, class H, class C, class AL> +void DisjointSet<T, H, C, AL>::create_union(T a, T b) { Element *x = insert_or_get(a); Element *y = insert_or_get(b); @@ -121,28 +121,28 @@ void DisjointSet<T, C, AL>::create_union(T a, T b) { } } -template <typename T, class C, class AL> -void DisjointSet<T, C, AL>::get_representatives(Vector<T> &out_representatives) { - for (typename MapT::Element *itr = elements.front(); itr != nullptr; itr = itr->next()) { - Element *element = itr->value(); +template <typename T, class H, class C, class AL> +void DisjointSet<T, H, C, AL>::get_representatives(Vector<T> &out_representatives) { + for (KeyValue<T, Element *> &E : elements) { + Element *element = E.value; if (element->parent == element) { out_representatives.push_back(element->object); } } } -template <typename T, class C, class AL> -void DisjointSet<T, C, AL>::get_members(Vector<T> &out_members, T representative) { - typename MapT::Element *rep_itr = elements.find(representative); +template <typename T, class H, class C, class AL> +void DisjointSet<T, H, C, AL>::get_members(Vector<T> &out_members, T representative) { + typename MapT::Iterator rep_itr = elements.find(representative); ERR_FAIL_COND(rep_itr == nullptr); - Element *rep_element = rep_itr->value(); + Element *rep_element = rep_itr->value; ERR_FAIL_COND(rep_element->parent != rep_element); - for (typename MapT::Element *itr = elements.front(); itr != nullptr; itr = itr->next()) { - Element *parent = get_parent(itr->value()); + for (KeyValue<T, Element *> &E : elements) { + Element *parent = get_parent(E.value); if (parent == rep_element) { - out_members.push_back(itr->key()); + out_members.push_back(E.key); } } } diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 9dd1257474..97dc175d94 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -155,7 +155,12 @@ Error Expression::_get_token(Token &r_token) { return OK; } case '*': { - r_token.type = TK_OP_MUL; + if (expression[str_ofs] == '*') { + r_token.type = TK_OP_POW; + str_ofs++; + } else { + r_token.type = TK_OP_MUL; + } return OK; } case '%': { @@ -542,6 +547,7 @@ const char *Expression::token_name[TK_MAX] = { "OP MUL", "OP DIV", "OP MOD", + "OP POW", "OP SHIFT LEFT", "OP SHIFT RIGHT", "OP BIT AND", @@ -1013,6 +1019,9 @@ Expression::ENode *Expression::_parse_expression() { case TK_OP_MOD: op = Variant::OP_MODULE; break; + case TK_OP_POW: + op = Variant::OP_POWER; + break; case TK_OP_SHIFT_LEFT: op = Variant::OP_SHIFT_LEFT; break; @@ -1066,35 +1075,38 @@ Expression::ENode *Expression::_parse_expression() { bool unary = false; switch (expression[i].op) { - case Variant::OP_BIT_NEGATE: + case Variant::OP_POWER: priority = 0; + break; + case Variant::OP_BIT_NEGATE: + priority = 1; unary = true; break; case Variant::OP_NEGATE: - priority = 1; + priority = 2; unary = true; break; case Variant::OP_MULTIPLY: case Variant::OP_DIVIDE: case Variant::OP_MODULE: - priority = 2; + priority = 3; break; case Variant::OP_ADD: case Variant::OP_SUBTRACT: - priority = 3; + priority = 4; break; case Variant::OP_SHIFT_LEFT: case Variant::OP_SHIFT_RIGHT: - priority = 4; + priority = 5; break; case Variant::OP_BIT_AND: - priority = 5; + priority = 6; break; case Variant::OP_BIT_XOR: - priority = 6; + priority = 7; break; case Variant::OP_BIT_OR: - priority = 7; + priority = 8; break; case Variant::OP_LESS: case Variant::OP_LESS_EQUAL: @@ -1102,20 +1114,20 @@ Expression::ENode *Expression::_parse_expression() { case Variant::OP_GREATER_EQUAL: case Variant::OP_EQUAL: case Variant::OP_NOT_EQUAL: - priority = 8; + priority = 9; break; case Variant::OP_IN: - priority = 10; + priority = 11; break; case Variant::OP_NOT: - priority = 11; + priority = 12; unary = true; break; case Variant::OP_AND: - priority = 12; + priority = 13; break; case Variant::OP_OR: - priority = 13; + priority = 14; break; default: { _set_error("Parser bug, invalid operator in expression: " + itos(expression[i].op)); diff --git a/core/math/expression.h b/core/math/expression.h index d43cc4091a..6ea3c1611f 100644 --- a/core/math/expression.h +++ b/core/math/expression.h @@ -85,6 +85,7 @@ private: TK_OP_MUL, TK_OP_DIV, TK_OP_MOD, + TK_OP_POW, TK_OP_SHIFT_LEFT, TK_OP_SHIFT_RIGHT, TK_OP_BIT_AND, diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp index f76de079e4..ec96753c79 100644 --- a/core/math/geometry_3d.cpp +++ b/core/math/geometry_3d.cpp @@ -36,7 +36,7 @@ #include "thirdparty/misc/polypartition.h" void Geometry3D::MeshData::optimize_vertices() { - Map<int, int> vtx_remap; + HashMap<int, int> vtx_remap; for (int i = 0; i < faces.size(); i++) { for (int j = 0; j < faces[i].indices.size(); j++) { diff --git a/core/math/octree.h b/core/math/octree.h index 65ab9e2292..8dd103f109 100644 --- a/core/math/octree.h +++ b/core/math/octree.h @@ -36,7 +36,7 @@ #include "core/math/vector3.h" #include "core/string/print_string.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/variant/variant.h" typedef uint32_t OctreeElementID; @@ -151,8 +151,8 @@ private: typename List<PairData *, AL>::Element *eA, *eB; }; - typedef Map<OctreeElementID, Element, Comparator<OctreeElementID>, AL> ElementMap; - typedef Map<PairKey, PairData, Comparator<PairKey>, AL> PairMap; + typedef HashMap<OctreeElementID, Element, Comparator<OctreeElementID>, AL> ElementMap; + typedef HashMap<PairKey, PairData, Comparator<PairKey>, AL> PairMap; ElementMap element_map; PairMap pair_map; diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 8e87d44b7f..43744deeb0 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -30,7 +30,7 @@ #include "quick_hull.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" uint32_t QuickHull::debug_stop_after = 0xFFFFFFFF; @@ -52,7 +52,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ Vector<bool> valid_points; valid_points.resize(p_points.size()); - Set<Vector3> valid_cache; + RBSet<Vector3> valid_cache; for (int i = 0; i < p_points.size(); i++) { Vector3 sp = p_points[i].snapped(Vector3(0.0001, 0.0001, 0.0001)); @@ -237,7 +237,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ //find lit faces and lit edges List<List<Face>::Element *> lit_faces; //lit face is a death sentence - Map<Edge, FaceConnect> lit_edges; //create this on the flight, should not be that bad for performance and simplifies code a lot + HashMap<Edge, FaceConnect, Edge> lit_edges; //create this on the flight, should not be that bad for performance and simplifies code a lot for (List<Face>::Element *E = faces.front(); E; E = E->next()) { if (E->get().plane.distance_to(v) > 0) { @@ -248,15 +248,15 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ uint32_t b = E->get().vertices[(i + 1) % 3]; Edge e(a, b); - Map<Edge, FaceConnect>::Element *F = lit_edges.find(e); + HashMap<Edge, FaceConnect, Edge>::Iterator F = lit_edges.find(e); if (!F) { F = lit_edges.insert(e, FaceConnect()); } if (e.vertices[0] == a) { //left - F->get().left = E; + F->value.left = E; } else { - F->get().right = E; + F->value.right = E; } } } @@ -333,7 +333,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ /* CREATE MESHDATA */ //make a map of edges again - Map<Edge, RetFaceConnect> ret_edges; + HashMap<Edge, RetFaceConnect, Edge> ret_edges; List<Geometry3D::MeshData::Face> ret_faces; for (const Face &E : faces) { @@ -351,15 +351,15 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ uint32_t b = E.vertices[(i + 1) % 3]; Edge e(a, b); - Map<Edge, RetFaceConnect>::Element *G = ret_edges.find(e); + HashMap<Edge, RetFaceConnect, Edge>::Iterator G = ret_edges.find(e); if (!G) { G = ret_edges.insert(e, RetFaceConnect()); } if (e.vertices[0] == a) { //left - G->get().left = F; + G->value.left = F; } else { - G->get().right = F; + G->value.right = F; } } } @@ -374,17 +374,16 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ int b = E->get().indices[(i + 1) % f.indices.size()]; Edge e(a, b); - Map<Edge, RetFaceConnect>::Element *F = ret_edges.find(e); + HashMap<Edge, RetFaceConnect, Edge>::Iterator F = ret_edges.find(e); ERR_CONTINUE(!F); - List<Geometry3D::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left; + List<Geometry3D::MeshData::Face>::Element *O = F->value.left == E ? F->value.right : F->value.left; ERR_CONTINUE(O == E); ERR_CONTINUE(O == nullptr); if (O->get().plane.is_equal_approx(f.plane)) { //merge and delete edge and contiguous face, while repointing edges (uuugh!) int ois = O->get().indices.size(); - int merged = 0; for (int j = 0; j < ois; j++) { //search a @@ -399,17 +398,16 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ if (idx != a) { f.indices.insert(i + 1, idx); i++; - merged++; } Edge e2(idx, idxn); - Map<Edge, RetFaceConnect>::Element *F2 = ret_edges.find(e2); + HashMap<Edge, RetFaceConnect, Edge>::Iterator F2 = ret_edges.find(e2); ERR_CONTINUE(!F2); //change faceconnect, point to this face instead - if (F2->get().left == O) { - F2->get().left = E; - } else if (F2->get().right == O) { - F2->get().right = E; + if (F2->value.left == O) { + F2->value.left = E; + } else if (F2->value.right == O) { + F2->value.right = E; } } @@ -428,7 +426,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ } } - ret_edges.erase(F); //remove the edge + ret_edges.remove(F); //remove the edge ret_faces.erase(O); //remove the face } } diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h index b8d813c979..1c354880b4 100644 --- a/core/math/quick_hull.h +++ b/core/math/quick_hull.h @@ -34,7 +34,7 @@ #include "core/math/aabb.h" #include "core/math/geometry_3d.h" #include "core/templates/list.h" -#include "core/templates/set.h" +#include "core/templates/rb_set.h" class QuickHull { public: @@ -44,9 +44,16 @@ public: uint64_t id = 0; }; + static uint32_t hash(const Edge &p_edge) { + return hash_one_uint64(p_edge.id); + } + bool operator<(const Edge &p_edge) const { return id < p_edge.id; } + bool operator==(const Edge &p_edge) const { + return id == p_edge.id; + } Edge(int p_vtx_a = 0, int p_vtx_b = 0) { if (p_vtx_a > p_vtx_b) { diff --git a/core/math/static_raycaster.h b/core/math/static_raycaster.h index 33254399c7..adc81906d7 100644 --- a/core/math/static_raycaster.h +++ b/core/math/static_raycaster.h @@ -102,7 +102,7 @@ public: virtual void add_mesh(const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices, unsigned int p_id) = 0; virtual void commit() = 0; - virtual void set_mesh_filter(const Set<int> &p_mesh_ids) = 0; + virtual void set_mesh_filter(const RBSet<int> &p_mesh_ids) = 0; virtual void clear_mesh_filter() = 0; static Ref<StaticRaycaster> create(); diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index e146c4a4e3..54461bf70f 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -122,7 +122,7 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces) { const Vector3 *r = p_faces.ptr(); Triangle *w = triangles.ptrw(); - Map<Vector3, int> db; + HashMap<Vector3, int> db; for (int i = 0; i < fc; i++) { Triangle &f = w[i]; @@ -131,9 +131,9 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces) { for (int j = 0; j < 3; j++) { int vidx = -1; Vector3 vs = v[j].snapped(Vector3(0.0001, 0.0001, 0.0001)); - Map<Vector3, int>::Element *E = db.find(vs); + HashMap<Vector3, int>::Iterator E = db.find(vs); if (E) { - vidx = E->get(); + vidx = E->value; } else { vidx = db.size(); db[vs] = vidx; diff --git a/core/multiplayer/multiplayer_api.cpp b/core/multiplayer/multiplayer_api.cpp index 3533acd103..e18c3dd2e4 100644 --- a/core/multiplayer/multiplayer_api.cpp +++ b/core/multiplayer/multiplayer_api.cpp @@ -494,7 +494,7 @@ Vector<int> MultiplayerAPI::get_peer_ids() const { ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), Vector<int>(), "No multiplayer peer is assigned. Assume no peers are connected."); Vector<int> ret; - for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = connected_peers.front(); E; E = E->next()) { ret.push_back(E->get()); } diff --git a/core/multiplayer/multiplayer_api.h b/core/multiplayer/multiplayer_api.h index 9fe67615e3..b93f2acbd3 100644 --- a/core/multiplayer/multiplayer_api.h +++ b/core/multiplayer/multiplayer_api.h @@ -113,7 +113,7 @@ public: private: Ref<MultiplayerPeer> multiplayer_peer; - Set<int> connected_peers; + RBSet<int> connected_peers; int remote_sender_id = 0; int remote_sender_override = 0; @@ -172,7 +172,7 @@ public: bool has_multiplayer_peer() const { return multiplayer_peer.is_valid(); } Vector<int> get_peer_ids() const; - const Set<int> get_connected_peers() const { return connected_peers; } + const RBSet<int> get_connected_peers() const { return connected_peers; } int get_remote_sender_id() const { return remote_sender_override ? remote_sender_override : remote_sender_id; } void set_remote_sender_override(int p_id) { remote_sender_override = p_id; } int get_unique_id() const; diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index 593f27b7cf..d19cbf2642 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -90,10 +90,8 @@ bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inh void ClassDB::get_class_list(List<StringName> *p_classes) { OBJTYPE_RLOCK; - const StringName *k = nullptr; - - while ((k = classes.next(k))) { - p_classes->push_back(*k); + for (const KeyValue<StringName, ClassInfo> &E : classes) { + p_classes->push_back(E.key); } p_classes->sort(); @@ -102,11 +100,9 @@ void ClassDB::get_class_list(List<StringName> *p_classes) { void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) { OBJTYPE_RLOCK; - const StringName *k = nullptr; - - while ((k = classes.next(k))) { - if (*k != p_class && _is_parent_class(*k, p_class)) { - p_classes->push_back(*k); + for (const KeyValue<StringName, ClassInfo> &E : classes) { + if (E.key != p_class && _is_parent_class(E.key, p_class)) { + p_classes->push_back(E.key); } } } @@ -114,11 +110,9 @@ void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringNa void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) { OBJTYPE_RLOCK; - const StringName *k = nullptr; - - while ((k = classes.next(k))) { - if (*k != p_class && _get_parent_class(*k) == p_class) { - p_classes->push_back(*k); + for (const KeyValue<StringName, ClassInfo> &E : classes) { + if (E.key != p_class && _get_parent_class(E.key) == p_class) { + p_classes->push_back(E.key); } } } @@ -172,17 +166,12 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG)); - List<StringName> names; - - const StringName *k = nullptr; + List<StringName> class_list; + ClassDB::get_class_list(&class_list); + // Must be alphabetically sorted for hash to compute. + class_list.sort_custom<StringName::AlphCompare>(); - while ((k = classes.next(k))) { - names.push_back(*k); - } - //must be alphabetically sorted for hash to compute - names.sort_custom<StringName::AlphCompare>(); - - for (const StringName &E : names) { + for (const StringName &E : class_list) { ClassInfo *t = classes.getptr(E); ERR_FAIL_COND_V_MSG(!t, 0, "Cannot get class '" + String(E) + "'."); if (t->api != p_api || !t->exposed) { @@ -195,10 +184,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->method_map.next(k))) { - String name = k->operator String(); + for (const KeyValue<StringName, MethodBind *> &F : t->method_map) { + String name = F.key.operator String(); ERR_CONTINUE(name.is_empty()); @@ -206,7 +193,7 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { continue; // Ignore non-virtual methods that start with an underscore } - snames.push_back(*k); + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -241,10 +228,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->constant_map.next(k))) { - snames.push_back(*k); + for (const KeyValue<StringName, int> &F : t->constant_map) { + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -259,10 +244,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->signal_map.next(k))) { - snames.push_back(*k); + for (const KeyValue<StringName, MethodInfo> &F : t->signal_map) { + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -280,10 +263,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->property_setget.next(k))) { - snames.push_back(*k); + for (const KeyValue<StringName, PropertySetGet> &F : t->property_setget) { + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -474,10 +455,8 @@ void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_met #else - const StringName *K = nullptr; - - while ((K = type->method_map.next(K))) { - MethodBind *m = type->method_map[*K]; + for (KeyValue<StringName, MethodBind *> &E : type->method_map) { + MethodBind *m = E.value; MethodInfo minfo = info_from_bind(m); p_methods->push_back(minfo); } @@ -603,10 +582,9 @@ void ClassDB::get_integer_constant_list(const StringName &p_class, List<String> p_constants->push_back(E); } #else - const StringName *K = nullptr; - while ((K = type->constant_map.next(K))) { - p_constants->push_back(*K); + for (const KeyValue<StringName, int> &E : type->constant_map) { + p_constants->push_back(E.key); } #endif @@ -667,12 +645,11 @@ StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const S ClassInfo *type = classes.getptr(p_class); while (type) { - const StringName *k = nullptr; - while ((k = type->enum_map.next(k))) { - List<StringName> &constants_list = type->enum_map.get(*k); + for (KeyValue<StringName, List<StringName>> &E : type->enum_map) { + List<StringName> &constants_list = E.value; const List<StringName>::Element *found = constants_list.find(p_name); if (found) { - return *k; + return E.key; } } @@ -692,9 +669,8 @@ void ClassDB::get_enum_list(const StringName &p_class, List<StringName> *p_enums ClassInfo *type = classes.getptr(p_class); while (type) { - const StringName *k = nullptr; - while ((k = type->enum_map.next(k))) { - p_enums->push_back(*k); + for (KeyValue<StringName, List<StringName>> &E : type->enum_map) { + p_enums->push_back(E.key); } if (p_no_inheritance) { @@ -800,9 +776,8 @@ void ClassDB::get_signal_list(const StringName &p_class, List<MethodInfo> *p_sig ClassInfo *check = type; while (check) { - const StringName *S = nullptr; - while ((S = check->signal_map.next(S))) { - p_signals->push_back(check->signal_map[*S]); + for (KeyValue<StringName, MethodInfo> &E : check->signal_map) { + p_signals->push_back(E.value); } if (p_no_inheritance) { @@ -1397,10 +1372,8 @@ void ClassDB::add_resource_base_extension(const StringName &p_extension, const S } void ClassDB::get_resource_base_extensions(List<String> *p_extensions) { - const StringName *K = nullptr; - - while ((K = resource_base_extensions.next(K))) { - p_extensions->push_back(*K); + for (const KeyValue<StringName, StringName> &E : resource_base_extensions) { + p_extensions->push_back(E.key); } } @@ -1409,18 +1382,15 @@ bool ClassDB::is_resource_extension(const StringName &p_extension) { } void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p_extensions) { - const StringName *K = nullptr; - - while ((K = resource_base_extensions.next(K))) { - StringName cmp = resource_base_extensions[*K]; - if (is_parent_class(p_class, cmp) || is_parent_class(cmp, p_class)) { - p_extensions->push_back(*K); + for (const KeyValue<StringName, StringName> &E : resource_base_extensions) { + if (is_parent_class(p_class, E.value) || is_parent_class(E.value, p_class)) { + p_extensions->push_back(E.key); } } } HashMap<StringName, HashMap<StringName, Variant>> ClassDB::default_values; -Set<StringName> ClassDB::default_values_cached; +RBSet<StringName> ClassDB::default_values_cached; Variant ClassDB::class_get_default_property_value(const StringName &p_class, const StringName &p_property, bool *r_valid) { if (!default_values_cached.has(p_class)) { @@ -1522,7 +1492,7 @@ void ClassDB::unregister_extension_class(const StringName &p_class) { classes.erase(p_class); } -Map<StringName, ClassDB::NativeStruct> ClassDB::native_structs; +HashMap<StringName, ClassDB::NativeStruct> ClassDB::native_structs; void ClassDB::register_native_struct(const StringName &p_name, const String &p_code, uint64_t p_current_size) { NativeStruct ns; ns.ccode = p_code; @@ -1556,14 +1526,11 @@ void ClassDB::cleanup_defaults() { void ClassDB::cleanup() { //OBJTYPE_LOCK; hah not here - const StringName *k = nullptr; - - while ((k = classes.next(k))) { - ClassInfo &ti = classes[*k]; + for (KeyValue<StringName, ClassInfo> &E : classes) { + ClassInfo &ti = E.value; - const StringName *m = nullptr; - while ((m = ti.method_map.next(m))) { - memdelete(ti.method_map[*m]); + for (KeyValue<StringName, MethodBind *> &F : ti.method_map) { + memdelete(F.value); } } classes.clear(); diff --git a/core/object/class_db.h b/core/object/class_db.h index d4e1fc4e76..67b71ab058 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -110,10 +110,10 @@ public: #ifdef DEBUG_METHODS_ENABLED List<StringName> constant_order; List<StringName> method_order; - Set<StringName> methods_in_properties; + RBSet<StringName> methods_in_properties; List<MethodInfo> virtual_methods; - Map<StringName, MethodInfo> virtual_methods_map; - Map<StringName, Vector<Error>> method_error_values; + HashMap<StringName, MethodInfo> virtual_methods_map; + HashMap<StringName, Vector<Error>> method_error_values; #endif HashMap<StringName, PropertySetGet> property_setget; @@ -149,14 +149,14 @@ public: static void _add_class2(const StringName &p_class, const StringName &p_inherits); static HashMap<StringName, HashMap<StringName, Variant>> default_values; - static Set<StringName> default_values_cached; + static RBSet<StringName> default_values_cached; // Native structs, used by binder struct NativeStruct { String ccode; // C code to create the native struct, fields separated by ; Arrays accepted (even containing other structs), also function pointers. All types must be Godot types. uint64_t struct_size; // local size of struct, for comparison }; - static Map<StringName, NativeStruct> native_structs; + static HashMap<StringName, NativeStruct> native_structs; private: // Non-locking variants of get_parent_class and is_parent_class. diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp index 79c36ac81f..fa1945cf79 100644 --- a/core/object/message_queue.cpp +++ b/core/object/message_queue.cpp @@ -142,9 +142,9 @@ Error MessageQueue::push_callablep(const Callable &p_callable, const Variant **p } void MessageQueue::statistics() { - Map<StringName, int> set_count; - Map<int, int> notify_count; - Map<Callable, int> call_count; + HashMap<StringName, int> set_count; + HashMap<int, int> notify_count; + HashMap<Callable, int> call_count; int null_count = 0; uint32_t read_pos = 0; diff --git a/core/object/object.cpp b/core/object/object.cpp index 2b62041533..0912ea55f0 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -417,9 +417,9 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid return; } else { - OrderedHashMap<StringName, Variant>::Element *E = metadata_properties.getptr(p_name); - if (E) { - E->get() = p_value; + Variant **V = metadata_properties.getptr(p_name); + if (V) { + **V = p_value; if (r_valid) { *r_valid = true; } @@ -508,10 +508,10 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { return ret; } - const OrderedHashMap<StringName, Variant>::Element *E = metadata_properties.getptr(p_name); + const Variant *const *V = metadata_properties.getptr(p_name); - if (E) { - ret = E->get(); + if (V) { + ret = **V; if (r_valid) { *r_valid = true; } @@ -666,9 +666,9 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons script_instance->get_property_list(p_list); } - for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) { - PropertyInfo pi = PropertyInfo(K.value().get_type(), "metadata/" + K.key().operator String()); - if (K.value().get_type() == Variant::OBJECT) { + for (const KeyValue<StringName, Variant> &K : metadata) { + PropertyInfo pi = PropertyInfo(K.value.get_type(), "metadata/" + K.key.operator String()); + if (K.value.get_type() == Variant::OBJECT) { pi.hint = PROPERTY_HINT_RESOURCE_TYPE; pi.hint_string = "Resource"; } @@ -944,13 +944,13 @@ void Object::set_meta(const StringName &p_name, const Variant &p_value) { return; } - OrderedHashMap<StringName, Variant>::Element E = metadata.find(p_name); + HashMap<StringName, Variant>::Iterator E = metadata.find(p_name); if (E) { - E.value() = p_value; + E->value = p_value; } else { ERR_FAIL_COND(!p_name.operator String().is_valid_identifier()); - E = metadata.insert(p_name, p_value); - metadata_properties["metadata/" + p_name.operator String()] = E; + Variant *V = &metadata.insert(p_name, p_value)->value; + metadata_properties["metadata/" + p_name.operator String()] = V; notify_property_list_changed(); } } @@ -993,16 +993,16 @@ Array Object::_get_method_list_bind() const { Vector<StringName> Object::_get_meta_list_bind() const { Vector<StringName> _metaret; - for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) { - _metaret.push_back(K.key()); + for (const KeyValue<StringName, Variant> &K : metadata) { + _metaret.push_back(K.key); } return _metaret; } void Object::get_meta_list(List<StringName> *p_list) const { - for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) { - p_list->push_back(K.key()); + for (const KeyValue<StringName, Variant> &K : metadata) { + p_list->push_back(K.key); } } @@ -1250,21 +1250,18 @@ void Object::get_signal_list(List<MethodInfo> *p_signals) const { ClassDB::get_signal_list(get_class_name(), p_signals); //find maybe usersignals? - const StringName *S = nullptr; - while ((S = signal_map.next(S))) { - if (!signal_map[*S].user.name.is_empty()) { + for (const KeyValue<StringName, SignalData> &E : signal_map) { + if (!E.value.user.name.is_empty()) { //user signal - p_signals->push_back(signal_map[*S].user); + p_signals->push_back(E.value.user); } } } void Object::get_all_signal_connections(List<Connection> *p_connections) const { - const StringName *S = nullptr; - - while ((S = signal_map.next(S))) { - const SignalData *s = &signal_map[*S]; + for (const KeyValue<StringName, SignalData> &E : signal_map) { + const SignalData *s = &E.value; for (int i = 0; i < s->slot_map.size(); i++) { p_connections->push_back(s->slot_map.getv(i).conn); @@ -1285,10 +1282,9 @@ void Object::get_signal_connection_list(const StringName &p_signal, List<Connect int Object::get_persistent_signal_connection_count() const { int count = 0; - const StringName *S = nullptr; - while ((S = signal_map.next(S))) { - const SignalData *s = &signal_map[*S]; + for (const KeyValue<StringName, SignalData> &E : signal_map) { + const SignalData *s = &E.value; for (int i = 0; i < s->slot_map.size(); i++) { if (s->slot_map.getv(i).conn.flags & CONNECT_PERSIST) { @@ -1386,8 +1382,6 @@ bool Object::is_connected(const StringName &p_signal, const Callable &p_callable Callable target = p_callable; return s->slot_map.has(*target.get_base_comparator()); - //const Map<Signal::Target,Signal::Slot>::Element *E = s->slot_map.find(target); - //return (E!=nullptr ); } void Object::disconnect(const StringName &p_signal, const Callable &p_callable) { @@ -1866,15 +1860,15 @@ Object::~Object() { _extension_instance = nullptr; } - const StringName *S = nullptr; - if (_emitting) { //@todo this may need to actually reach the debugger prioritarily somehow because it may crash before ERR_PRINT("Object " + to_string() + " was freed or unreferenced while a signal is being emitted from it. Try connecting to the signal using 'CONNECT_DEFERRED' flag, or use queue_free() to free the object (if this object is a Node) to avoid this error and potential crashes."); } - while ((S = signal_map.next(nullptr))) { - SignalData *s = &signal_map[*S]; + while (signal_map.size()) { + // Avoid regular iteration so erasing is safe. + KeyValue<StringName, SignalData> &E = *signal_map.begin(); + SignalData *s = &E.value; //brute force disconnect for performance int slot_count = s->slot_map.size(); @@ -1884,7 +1878,7 @@ Object::~Object() { slot_list[i].value.conn.callable.get_object()->connections.erase(slot_list[i].value.cE); } - signal_map.erase(*S); + signal_map.erase(E.key); } //signals from nodes that connect to this node diff --git a/core/object/object.h b/core/object/object.h index c3e3c68b59..ca7b9965f1 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -38,10 +38,9 @@ #include "core/os/spin_lock.h" #include "core/templates/hash_map.h" #include "core/templates/list.h" -#include "core/templates/map.h" -#include "core/templates/ordered_hash_map.h" +#include "core/templates/rb_map.h" +#include "core/templates/rb_set.h" #include "core/templates/safe_refcount.h" -#include "core/templates/set.h" #include "core/templates/vmap.h" #include "core/variant/callable_bind.h" #include "core/variant/variant.h" @@ -511,12 +510,12 @@ private: #ifdef TOOLS_ENABLED bool _edited = false; uint32_t _edited_version = 0; - Set<String> editor_section_folding; + RBSet<String> editor_section_folding; #endif ScriptInstance *script_instance = nullptr; Variant script; // Reference does not exist yet, store it in a Variant. - OrderedHashMap<StringName, Variant> metadata; - HashMap<StringName, OrderedHashMap<StringName, Variant>::Element> metadata_properties; + HashMap<StringName, Variant> metadata; + HashMap<StringName, Variant *> metadata_properties; mutable StringName _class_name; mutable const StringName *_class_ptr = nullptr; @@ -816,7 +815,7 @@ public: #ifdef TOOLS_ENABLED void editor_set_section_unfold(const String &p_section, bool p_unfolded); bool editor_is_section_unfolded(const String &p_section); - const Set<String> &editor_get_section_folding() const { return editor_section_folding; } + const RBSet<String> &editor_get_section_folding() const { return editor_section_folding; } void editor_clear_section_folding() { editor_section_folding.clear(); } #endif diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index a5d25bf533..1546d52fd2 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -93,7 +93,7 @@ Array Script::_get_script_signal_list() { Dictionary Script::_get_script_constant_map() { Dictionary ret; - Map<StringName, Variant> map; + HashMap<StringName, Variant> map; get_constants(&map); for (const KeyValue<StringName, Variant> &E : map) { ret[E.key] = E.value; @@ -253,10 +253,9 @@ StringName ScriptServer::get_global_class_native_base(const String &p_class) { } void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) { - const StringName *K = nullptr; List<StringName> classes; - while ((K = global_classes.next(K))) { - classes.push_back(*K); + for (const KeyValue<StringName, GlobalScriptClass> &E : global_classes) { + classes.push_back(E.key); } classes.sort_custom<StringName::AlphCompare>(); for (const StringName &E : classes) { @@ -475,8 +474,8 @@ bool PlaceHolderScriptInstance::has_method(const StringName &p_method) const { return false; } -void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, const Map<StringName, Variant> &p_values) { - Set<StringName> new_values; +void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, const HashMap<StringName, Variant> &p_values) { + RBSet<StringName> new_values; for (const PropertyInfo &E : p_properties) { StringName n = E.name; new_values.insert(n); @@ -491,16 +490,16 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c properties = p_properties; List<StringName> to_remove; - for (Map<StringName, Variant>::Element *E = values.front(); E; E = E->next()) { - if (!new_values.has(E->key())) { - to_remove.push_back(E->key()); + for (KeyValue<StringName, Variant> &E : values) { + if (!new_values.has(E.key)) { + to_remove.push_back(E.key); } Variant defval; - if (script->get_property_default_value(E->key(), defval)) { + if (script->get_property_default_value(E.key, defval)) { //remove because it's the same as the default value - if (defval == E->get()) { - to_remove.push_back(E->key()); + if (defval == E.value) { + to_remove.push_back(E.key); } } } @@ -521,10 +520,10 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid) { if (script->is_placeholder_fallback_enabled()) { - Map<StringName, Variant>::Element *E = values.find(p_name); + HashMap<StringName, Variant>::Iterator E = values.find(p_name); if (E) { - E->value() = p_value; + E->value = p_value; } else { values.insert(p_name, p_value); } @@ -548,13 +547,13 @@ void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name, Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_name, bool *r_valid) { if (script->is_placeholder_fallback_enabled()) { - const Map<StringName, Variant>::Element *E = values.find(p_name); + HashMap<StringName, Variant>::ConstIterator E = values.find(p_name); if (E) { if (r_valid) { *r_valid = true; } - return E->value(); + return E->value; } E = constants.find(p_name); @@ -562,7 +561,7 @@ Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_nam if (r_valid) { *r_valid = true; } - return E->value(); + return E->value; } } diff --git a/core/object/script_language.h b/core/object/script_language.h index f58ef45743..b1481a372e 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -34,8 +34,8 @@ #include "core/doc_data.h" #include "core/io/resource.h" #include "core/multiplayer/multiplayer.h" -#include "core/templates/map.h" #include "core/templates/pair.h" +#include "core/templates/rb_map.h" class ScriptLanguage; @@ -154,8 +154,8 @@ public: virtual int get_member_line(const StringName &p_member) const { return -1; } - virtual void get_constants(Map<StringName, Variant> *p_constants) {} - virtual void get_members(Set<StringName> *p_constants) {} + virtual void get_constants(HashMap<StringName, Variant> *p_constants) {} + virtual void get_members(RBSet<StringName> *p_constants) {} virtual bool is_placeholder_fallback_enabled() const { return false; } @@ -283,7 +283,7 @@ public: virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const { return Ref<Script>(); } virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) { return Vector<ScriptTemplate>(); } virtual bool is_using_templates() { return false; } - virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptError> *r_errors = nullptr, List<Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const = 0; + virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptError> *r_errors = nullptr, List<Warning> *r_warnings = nullptr, RBSet<int> *r_safe_lines = nullptr) const = 0; virtual String validate_path(const String &p_path) const { return ""; } virtual Script *create_script() const = 0; virtual bool has_named_classes() const = 0; @@ -346,6 +346,7 @@ public: LOOKUP_RESULT_CLASS_CONSTANT, LOOKUP_RESULT_CLASS_PROPERTY, LOOKUP_RESULT_CLASS_METHOD, + LOOKUP_RESULT_CLASS_SIGNAL, LOOKUP_RESULT_CLASS_ENUM, LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE, LOOKUP_RESULT_MAX @@ -432,8 +433,8 @@ extern uint8_t script_encryption_key[32]; class PlaceHolderScriptInstance : public ScriptInstance { Object *owner = nullptr; List<PropertyInfo> properties; - Map<StringName, Variant> values; - Map<StringName, Variant> constants; + HashMap<StringName, Variant> values; + HashMap<StringName, Variant> constants; ScriptLanguage *language = nullptr; Ref<Script> script; @@ -458,7 +459,7 @@ public: Object *get_owner() override { return owner; } - void update(const List<PropertyInfo> &p_properties, const Map<StringName, Variant> &p_values); //likely changed in editor + void update(const List<PropertyInfo> &p_properties, const HashMap<StringName, Variant> &p_values); //likely changed in editor virtual bool is_placeholder() const override { return true; } diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp index 21d7685674..5af79bbea3 100644 --- a/core/object/script_language_extension.cpp +++ b/core/object/script_language_extension.cpp @@ -157,6 +157,7 @@ void ScriptLanguageExtension::_bind_methods() { BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_CONSTANT); BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_PROPERTY); BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_METHOD); + BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_SIGNAL); BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_ENUM); BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE); BIND_ENUM_CONSTANT(LOOKUP_RESULT_MAX); diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index 40f18ab30d..5ffa6c5a70 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -153,7 +153,7 @@ public: GDVIRTUAL0RC(Dictionary, _get_constants) - virtual void get_constants(Map<StringName, Variant> *p_constants) override { + virtual void get_constants(HashMap<StringName, Variant> *p_constants) override { Dictionary constants; GDVIRTUAL_REQUIRED_CALL(_get_constants, constants); List<Variant> keys; @@ -163,7 +163,7 @@ public: } } GDVIRTUAL0RC(TypedArray<StringName>, _get_members) - virtual void get_members(Set<StringName> *p_members) override { + virtual void get_members(RBSet<StringName> *p_members) override { TypedArray<StringName> members; GDVIRTUAL_REQUIRED_CALL(_get_members, members); for (int i = 0; i < members.size(); i++) { @@ -282,7 +282,7 @@ public: EXBIND0R(bool, is_using_templates) GDVIRTUAL6RC(Dictionary, _validate, const String &, const String &, bool, bool, bool, bool) - virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptError> *r_errors = nullptr, List<Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const override { + virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptError> *r_errors = nullptr, List<Warning> *r_warnings = nullptr, RBSet<int> *r_safe_lines = nullptr) const override { Dictionary ret; GDVIRTUAL_REQUIRED_CALL(_validate, p_script, p_path, r_functions != nullptr, r_errors != nullptr, r_warnings != nullptr, r_safe_lines != nullptr, ret); if (!ret.has("valid")) { diff --git a/core/os/memory.h b/core/os/memory.h index baa96ef3e9..42ba9634e2 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -197,4 +197,12 @@ struct _GlobalNilClass { static _GlobalNil _nil; }; +template <class T> +class DefaultTypedAllocator { +public: + template <class... Args> + _FORCE_INLINE_ T *new_allocation(const Args &&...p_args) { return memnew(T(p_args...)); } + _FORCE_INLINE_ void delete_allocation(T *p_allocation) { memdelete(p_allocation); } +}; + #endif // MEMORY_H diff --git a/core/os/os.h b/core/os/os.h index 5eac77d634..157b8ab992 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -82,11 +82,6 @@ public: RENDER_SEPARATE_THREAD }; - enum RenderMainThreadMode { - RENDER_MAIN_THREAD_ONLY, - RENDER_ANY_THREAD, - }; - protected: friend class Main; // Needed by tests to setup command-line args. @@ -94,7 +89,6 @@ protected: HasServerFeatureCallback has_server_feature_callback = nullptr; RenderThreadMode _render_thread_mode = RENDER_THREAD_SAFE; - RenderMainThreadMode _render_main_thread_mode = RENDER_ANY_THREAD; // Functions used by Main to initialize/deinitialize the OS. void add_logger(Logger *p_logger); @@ -258,8 +252,6 @@ public: virtual uint64_t get_free_static_memory() const; RenderThreadMode get_render_thread_mode() const { return _render_thread_mode; } - RenderMainThreadMode get_render_main_thread_mode() const { return _render_main_thread_mode; } - void set_render_main_thread_mode(RenderMainThreadMode p_thread_mode) { _render_main_thread_mode = p_thread_mode; } virtual String get_locale() const; String get_locale_language() const; diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp index 93429744fc..07302cc8c3 100644 --- a/core/string/optimized_translation.cpp +++ b/core/string/optimized_translation.cpp @@ -53,7 +53,7 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) { int size = Math::larger_prime(keys.size()); Vector<Vector<Pair<int, CharString>>> buckets; - Vector<Map<uint32_t, int>> table; + Vector<HashMap<uint32_t, int>> table; Vector<uint32_t> hfunc_table; Vector<CompressedString> compressed; @@ -108,7 +108,7 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) { for (int i = 0; i < size; i++) { const Vector<Pair<int, CharString>> &b = buckets[i]; - Map<uint32_t, int> &t = table.write[i]; + HashMap<uint32_t, int> &t = table.write[i]; if (b.size() == 0) { continue; @@ -147,7 +147,7 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) { int btindex = 0; for (int i = 0; i < size; i++) { - const Map<uint32_t, int> &t = table[i]; + const HashMap<uint32_t, int> &t = table[i]; if (t.size() == 0) { htw[i] = 0xFFFFFFFF; //nothing continue; diff --git a/core/string/translation.cpp b/core/string/translation.cpp index d6d361b5f1..c64f815563 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -95,12 +95,12 @@ StringName Translation::get_message(const StringName &p_src_text, const StringNa WARN_PRINT("Translation class doesn't handle context. Using context in get_message() on a Translation instance is probably a mistake. \nUse a derived Translation class that handles context, such as TranslationPO class"); } - const Map<StringName, StringName>::Element *E = translation_map.find(p_src_text); + HashMap<StringName, StringName>::ConstIterator E = translation_map.find(p_src_text); if (!E) { return StringName(); } - return E->get(); + return E->value; } StringName Translation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const { @@ -215,12 +215,12 @@ static _character_accent_pair _character_to_accented[] = { Vector<TranslationServer::LocaleScriptInfo> TranslationServer::locale_script_info; -Map<String, String> TranslationServer::language_map; -Map<String, String> TranslationServer::script_map; -Map<String, String> TranslationServer::locale_rename_map; -Map<String, String> TranslationServer::country_name_map; -Map<String, String> TranslationServer::variant_map; -Map<String, String> TranslationServer::country_rename_map; +HashMap<String, String> TranslationServer::language_map; +HashMap<String, String> TranslationServer::script_map; +HashMap<String, String> TranslationServer::locale_rename_map; +HashMap<String, String> TranslationServer::country_name_map; +HashMap<String, String> TranslationServer::variant_map; +HashMap<String, String> TranslationServer::country_rename_map; void TranslationServer::init_locale_info() { // Init locale info. @@ -452,8 +452,8 @@ String TranslationServer::get_locale_name(const String &p_locale) const { Vector<String> TranslationServer::get_all_languages() const { Vector<String> languages; - for (const Map<String, String>::Element *E = language_map.front(); E; E = E->next()) { - languages.push_back(E->key()); + for (const KeyValue<String, String> &E : language_map) { + languages.push_back(E.key); } return languages; @@ -466,8 +466,8 @@ String TranslationServer::get_language_name(const String &p_language) const { Vector<String> TranslationServer::get_all_scripts() const { Vector<String> scripts; - for (const Map<String, String>::Element *E = script_map.front(); E; E = E->next()) { - scripts.push_back(E->key()); + for (const KeyValue<String, String> &E : script_map) { + scripts.push_back(E.key); } return scripts; @@ -480,8 +480,8 @@ String TranslationServer::get_script_name(const String &p_script) const { Vector<String> TranslationServer::get_all_countries() const { Vector<String> countries; - for (const Map<String, String>::Element *E = country_name_map.front(); E; E = E->next()) { - countries.push_back(E->key()); + for (const KeyValue<String, String> &E : country_name_map) { + countries.push_back(E.key); } return countries; @@ -507,7 +507,7 @@ String TranslationServer::get_locale() const { Array TranslationServer::get_loaded_locales() const { Array locales; - for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { + for (const RBSet<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { const Ref<Translation> &t = E->get(); ERR_FAIL_COND_V(t.is_null(), Array()); String l = t->get_locale(); @@ -530,7 +530,7 @@ Ref<Translation> TranslationServer::get_translation_object(const String &p_local Ref<Translation> res; int best_score = 0; - for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { + for (const RBSet<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { const Ref<Translation> &t = E->get(); ERR_FAIL_COND_V(t.is_null(), nullptr); String l = t->get_locale(); @@ -599,7 +599,7 @@ StringName TranslationServer::_get_message_from_translations(const StringName &p StringName res; int best_score = 0; - for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { + for (const RBSet<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { const Ref<Translation> &t = E->get(); ERR_FAIL_COND_V(t.is_null(), p_message); String l = t->get_locale(); diff --git a/core/string/translation.h b/core/string/translation.h index ded6ed5925..f58f6f91a2 100644 --- a/core/string/translation.h +++ b/core/string/translation.h @@ -41,7 +41,7 @@ class Translation : public Resource { RES_BASE_EXTENSION("translation"); String locale = "en"; - Map<StringName, StringName> translation_map; + HashMap<StringName, StringName> translation_map; virtual Vector<String> _get_message_list() const; virtual Dictionary _get_messages() const; @@ -74,7 +74,7 @@ class TranslationServer : public Object { String locale = "en"; String fallback; - Set<Ref<Translation>> translations; + RBSet<Ref<Translation>> translations; Ref<Translation> tool_translation; Ref<Translation> doc_translation; @@ -111,16 +111,16 @@ class TranslationServer : public Object { String name; String script; String default_country; - Set<String> supported_countries; + RBSet<String> supported_countries; }; static Vector<LocaleScriptInfo> locale_script_info; - static Map<String, String> language_map; - static Map<String, String> script_map; - static Map<String, String> locale_rename_map; - static Map<String, String> country_name_map; - static Map<String, String> country_rename_map; - static Map<String, String> variant_map; + static HashMap<String, String> language_map; + static HashMap<String, String> script_map; + static HashMap<String, String> locale_rename_map; + static HashMap<String, String> country_name_map; + static HashMap<String, String> country_rename_map; + static HashMap<String, String> variant_map; void init_locale_info(); diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp index 3f94e064ec..fa656b634d 100644 --- a/core/string/translation_po.cpp +++ b/core/string/translation_po.cpp @@ -70,21 +70,14 @@ Dictionary TranslationPO::_get_messages() const { Dictionary d; - List<StringName> context_l; - translation_map.get_key_list(&context_l); - for (const StringName &ctx : context_l) { - const HashMap<StringName, Vector<StringName>> &id_str_map = translation_map[ctx]; - + for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) { Dictionary d2; - List<StringName> id_l; - id_str_map.get_key_list(&id_l); - // Save list of id and strs associated with a context in a temporary dictionary. - for (List<StringName>::Element *E2 = id_l.front(); E2; E2 = E2->next()) { - StringName id = E2->get(); - d2[id] = id_str_map[id]; + + for (const KeyValue<StringName, Vector<StringName>> &E2 : E.value) { + d2[E2.key] = E2.value; } - d[ctx] = d2; + d[E.key] = d2; } return d; @@ -274,31 +267,24 @@ void TranslationPO::get_message_list(List<StringName> *r_messages) const { // OptimizedTranslation uses this function to get the list of msgid. // Return all the keys of translation_map under "" context. - List<StringName> context_l; - translation_map.get_key_list(&context_l); - - for (const StringName &E : context_l) { - if (String(E) != "") { + for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) { + if (E.key != StringName()) { continue; } - List<StringName> msgid_l; - translation_map[E].get_key_list(&msgid_l); - - for (List<StringName>::Element *E2 = msgid_l.front(); E2; E2 = E2->next()) { - r_messages->push_back(E2->get()); + for (const KeyValue<StringName, Vector<StringName>> &E2 : E.value) { + r_messages->push_back(E2.key); } } } int TranslationPO::get_message_count() const { - List<StringName> context_l; - translation_map.get_key_list(&context_l); - int count = 0; - for (const StringName &E : context_l) { - count += translation_map[E].size(); + + for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) { + count += E.value.size(); } + return count; } diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 5d998d22d4..f6ad0fe3b0 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -3655,6 +3655,31 @@ bool String::is_absolute_path() const { } } +static _FORCE_INLINE_ bool _is_valid_identifier_bit(int p_index, char32_t p_char) { + if (p_index == 0 && is_digit(p_char)) { + return false; // No start with number plz. + } + return is_ascii_identifier_char(p_char); +} + +String String::validate_identifier() const { + if (is_empty()) { + return "_"; // Empty string is not a valid identifier; + } + + String result = *this; + int len = result.length(); + char32_t *buffer = result.ptrw(); + + for (int i = 0; i < len; i++) { + if (!_is_valid_identifier_bit(i, buffer[i])) { + buffer[i] = '_'; + } + } + + return result; +} + bool String::is_valid_identifier() const { int len = length(); @@ -3665,15 +3690,7 @@ bool String::is_valid_identifier() const { const char32_t *str = &operator[](0); for (int i = 0; i < len; i++) { - if (i == 0) { - if (is_digit(str[0])) { - return false; // no start with number plz - } - } - - bool valid_char = is_ascii_identifier_char(str[i]); - - if (!valid_char) { + if (!_is_valid_identifier_bit(i, str[i])) { return false; } } @@ -4779,6 +4796,17 @@ Vector<uint8_t> String::to_utf32_buffer() const { } #ifdef TOOLS_ENABLED +/** + * "Tools TRanslate". Performs string replacement for internationalization + * within the editor. A translation context can optionally be specified to + * disambiguate between identical source strings in translations. When + * placeholders are desired, use `vformat(TTR("Example: %s"), some_string)`. + * If a string mentions a quantity (and may therefore need a dynamic plural form), + * use `TTRN()` instead of `TTR()`. + * + * NOTE: Only use `TTR()` in editor-only code (typically within the `editor/` folder). + * For translations that can be supplied by exported projects, use `RTR()` instead. + */ String TTR(const String &p_text, const String &p_context) { if (TranslationServer::get_singleton()) { return TranslationServer::get_singleton()->tool_translate(p_text, p_context); @@ -4787,6 +4815,18 @@ String TTR(const String &p_text, const String &p_context) { return p_text; } +/** + * "Tools TRanslate for N items". Performs string replacement for + * internationalization within the editor. A translation context can optionally + * be specified to disambiguate between identical source strings in + * translations. Use `TTR()` if the string doesn't need dynamic plural form. + * When placeholders are desired, use + * `vformat(TTRN("%d item", "%d items", some_integer), some_integer)`. + * The placeholder must be present in both strings to avoid run-time warnings in `vformat()`. + * + * NOTE: Only use `TTRN()` in editor-only code (typically within the `editor/` folder). + * For translations that can be supplied by exported projects, use `RTRN()` instead. + */ String TTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) { if (TranslationServer::get_singleton()) { return TranslationServer::get_singleton()->tool_translate_plural(p_text, p_text_plural, p_n, p_context); @@ -4799,9 +4839,10 @@ String TTRN(const String &p_text, const String &p_text_plural, int p_n, const St return p_text_plural; } -/* DTR and DTRN are used for the documentation, handling descriptions extracted - * from the XML. - * They also replace `$DOCS_URL` with the actual URL to the documentation's branch, +/** + * "Docs TRanslate". Used for the editor class reference documentation, + * handling descriptions extracted from the XML. + * It also replaces `$DOCS_URL` with the actual URL to the documentation's branch, * to allow dehardcoding it in the XML and doing proper substitutions everywhere. */ String DTR(const String &p_text, const String &p_context) { @@ -4815,6 +4856,12 @@ String DTR(const String &p_text, const String &p_context) { return text.replace("$DOCS_URL", VERSION_DOCS_URL); } +/** + * "Docs TRanslate for N items". Used for the editor class reference documentation + * (with support for plurals), handling descriptions extracted from the XML. + * It also replaces `$DOCS_URL` with the actual URL to the documentation's branch, + * to allow dehardcoding it in the XML and doing proper substitutions everywhere. + */ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) { const String text = p_text.dedent().strip_edges(); const String text_plural = p_text_plural.dedent().strip_edges(); @@ -4831,6 +4878,19 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St } #endif +/** + * "Run-time TRanslate". Performs string replacement for internationalization + * within a running project. The translation string must be supplied by the + * project, as Godot does not provide built-in translations for `RTR()` strings + * to keep binary size low. A translation context can optionally be specified to + * disambiguate between identical source strings in translations. When + * placeholders are desired, use `vformat(RTR("Example: %s"), some_string)`. + * If a string mentions a quantity (and may therefore need a dynamic plural form), + * use `RTRN()` instead of `RTR()`. + * + * NOTE: Do not use `RTR()` in editor-only code (typically within the `editor/` + * folder). For editor translations, use `TTR()` instead. + */ String RTR(const String &p_text, const String &p_context) { if (TranslationServer::get_singleton()) { String rtr = TranslationServer::get_singleton()->tool_translate(p_text, p_context); @@ -4844,6 +4904,20 @@ String RTR(const String &p_text, const String &p_context) { return p_text; } +/** + * "Run-time TRanslate for N items". Performs string replacement for + * internationalization within a running project. The translation string must be + * supplied by the project, as Godot does not provide built-in translations for + * `RTRN()` strings to keep binary size low. A translation context can + * optionally be specified to disambiguate between identical source strings in + * translations. Use `RTR()` if the string doesn't need dynamic plural form. + * When placeholders are desired, use + * `vformat(RTRN("%d item", "%d items", some_integer), some_integer)`. + * The placeholder must be present in both strings to avoid run-time warnings in `vformat()`. + * + * NOTE: Do not use `RTRN()` in editor-only code (typically within the `editor/` + * folder). For editor translations, use `TTRN()` instead. + */ String RTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) { if (TranslationServer::get_singleton()) { String rtr = TranslationServer::get_singleton()->tool_translate_plural(p_text, p_text_plural, p_n, p_context); diff --git a/core/string/ustring.h b/core/string/ustring.h index 48f2e45105..0d10d4cf10 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -427,6 +427,7 @@ public: // node functions static const String invalid_node_name_characters; String validate_node_name() const; + String validate_identifier() const; bool is_valid_identifier() const; bool is_valid_int() const; diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h index f1ac32928f..e760fc2176 100644 --- a/core/templates/cowdata.h +++ b/core/templates/cowdata.h @@ -183,6 +183,8 @@ public: } int find(const T &p_val, int p_from = 0) const; + int rfind(const T &p_val, int p_from = -1) const; + int count(const T &p_val) const; _FORCE_INLINE_ CowData() {} _FORCE_INLINE_ ~CowData(); @@ -350,6 +352,36 @@ int CowData<T>::find(const T &p_val, int p_from) const { } template <class T> +int CowData<T>::rfind(const T &p_val, int p_from) const { + const int s = size(); + + if (p_from < 0) { + p_from = s + p_from; + } + if (p_from < 0 || p_from >= s) { + p_from = s - 1; + } + + for (int i = p_from; i >= 0; i--) { + if (get(i) == p_val) { + return i; + } + } + return -1; +} + +template <class T> +int CowData<T>::count(const T &p_val) const { + int amount = 0; + for (int i = 0; i < size(); i++) { + if (get(i) == p_val) { + amount++; + } + } + return amount; +} + +template <class T> void CowData<T>::_ref(const CowData *p_from) { _ref(*p_from); } diff --git a/core/templates/hash_map.h b/core/templates/hash_map.h index fa5677cc70..e5f73171a2 100644 --- a/core/templates/hash_map.h +++ b/core/templates/hash_map.h @@ -31,524 +31,557 @@ #ifndef HASH_MAP_H #define HASH_MAP_H -#include "core/error/error_macros.h" #include "core/math/math_funcs.h" #include "core/os/memory.h" -#include "core/string/ustring.h" #include "core/templates/hashfuncs.h" -#include "core/templates/list.h" +#include "core/templates/paged_allocator.h" +#include "core/templates/pair.h" /** - * @class HashMap + * A HashMap implementation that uses open addressing with Robin Hood hashing. + * Robin Hood hashing swaps out entries that have a smaller probing distance + * than the to-be-inserted entry, that evens out the average probing distance + * and enables faster lookups. Backward shift deletion is employed to further + * improve the performance and to avoid infinite loops in rare cases. * - * Implementation of a standard Hashing HashMap, for quick lookups of Data associated with a Key. - * The implementation provides hashers for the default types, if you need a special kind of hasher, provide - * your own. - * @param TKey Key, search is based on it, needs to be hasheable. It is unique in this container. - * @param TData Data, data associated with the key - * @param Hasher Hasher object, needs to provide a valid static hash function for TKey - * @param Comparator comparator object, needs to be able to safely compare two TKey values. - * It needs to ensure that x == x for any items inserted in the map. Bear in mind that nan != nan when implementing an equality check. - * @param MIN_HASH_TABLE_POWER Miminum size of the hash table, as a power of two. You rarely need to change this parameter. - * @param RELATIONSHIP Relationship at which the hash table is resized. if amount of elements is RELATIONSHIP - * times bigger than the hash table, table is resized to solve this condition. if RELATIONSHIP is zero, table is always MIN_HASH_TABLE_POWER. + * Keys and values are stored in a double linked list by insertion order. This + * has a slight performance overhead on lookup, which can be mostly compensated + * using a paged allocator if required. * + * The assignment operator copy the pairs from one map to the other. */ -template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>, uint8_t MIN_HASH_TABLE_POWER = 3, uint8_t RELATIONSHIP = 8> +template <class TKey, class TValue> +struct HashMapElement { + HashMapElement *next = nullptr; + HashMapElement *prev = nullptr; + KeyValue<TKey, TValue> data; + HashMapElement() {} + HashMapElement(const TKey &p_key, const TValue &p_value) : + data(p_key, p_value) {} +}; + +template <class TKey, class TValue, + class Hasher = HashMapHasherDefault, + class Comparator = HashMapComparatorDefault<TKey>, + class Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>> class HashMap { public: - struct Pair { - TKey key; - TData data; + const uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime. + const float MAX_OCCUPANCY = 0.75; + const uint32_t EMPTY_HASH = 0; - Pair(const TKey &p_key) : - key(p_key), - data() {} - Pair(const TKey &p_key, const TData &p_data) : - key(p_key), - data(p_data) { - } - }; +private: + Allocator element_alloc; + HashMapElement<TKey, TValue> **elements = nullptr; + uint32_t *hashes = nullptr; + HashMapElement<TKey, TValue> *head_element = nullptr; + HashMapElement<TKey, TValue> *tail_element = nullptr; - struct Element { - private: - friend class HashMap; + uint32_t capacity_index = 0; + uint32_t num_elements = 0; - uint32_t hash = 0; - Element *next = nullptr; - Element() {} - Pair pair; + _FORCE_INLINE_ uint32_t _hash(const TKey &p_key) const { + uint32_t hash = Hasher::hash(p_key); - public: - const TKey &key() const { - return pair.key; + if (unlikely(hash == EMPTY_HASH)) { + hash = EMPTY_HASH + 1; } - TData &value() { - return pair.data; - } + return hash; + } - const TData &value() const { - return pair.value(); + _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash, uint32_t p_capacity) const { + uint32_t original_pos = p_hash % p_capacity; + return (p_pos - original_pos + p_capacity) % p_capacity; + } + + bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const { + if (elements == nullptr) { + return false; // Failed lookups, no elements } - Element(const TKey &p_key) : - pair(p_key) {} - Element(const Element &p_other) : - hash(p_other.hash), - pair(p_other.pair.key, p_other.pair.data) {} - }; + uint32_t capacity = hash_table_size_primes[capacity_index]; + uint32_t hash = _hash(p_key); + uint32_t pos = hash % capacity; + uint32_t distance = 0; -private: - Element **hash_table = nullptr; - uint8_t hash_table_power = 0; - uint32_t elements = 0; + while (true) { + if (hashes[pos] == EMPTY_HASH) { + return false; + } - void make_hash_table() { - ERR_FAIL_COND(hash_table); + if (distance > _get_probe_length(pos, hashes[pos], capacity)) { + return false; + } - hash_table = memnew_arr(Element *, (1 << MIN_HASH_TABLE_POWER)); + if (hashes[pos] == hash && Comparator::compare(elements[pos]->data.key, p_key)) { + r_pos = pos; + return true; + } - hash_table_power = MIN_HASH_TABLE_POWER; - elements = 0; - for (int i = 0; i < (1 << MIN_HASH_TABLE_POWER); i++) { - hash_table[i] = nullptr; + pos = (pos + 1) % capacity; + distance++; } } - void erase_hash_table() { - ERR_FAIL_COND_MSG(elements, "Cannot erase hash table if there are still elements inside."); - - memdelete_arr(hash_table); - hash_table = nullptr; - hash_table_power = 0; - elements = 0; - } + void _insert_with_hash(uint32_t p_hash, HashMapElement<TKey, TValue> *p_value) { + uint32_t capacity = hash_table_size_primes[capacity_index]; + uint32_t hash = p_hash; + HashMapElement<TKey, TValue> *value = p_value; + uint32_t distance = 0; + uint32_t pos = hash % capacity; - void check_hash_table() { - int new_hash_table_power = -1; + while (true) { + if (hashes[pos] == EMPTY_HASH) { + elements[pos] = value; + hashes[pos] = hash; - if ((int)elements > ((1 << hash_table_power) * RELATIONSHIP)) { - /* rehash up */ - new_hash_table_power = hash_table_power + 1; + num_elements++; - while ((int)elements > ((1 << new_hash_table_power) * RELATIONSHIP)) { - new_hash_table_power++; + return; } - } else if ((hash_table_power > (int)MIN_HASH_TABLE_POWER) && ((int)elements < ((1 << (hash_table_power - 1)) * RELATIONSHIP))) { - /* rehash down */ - new_hash_table_power = hash_table_power - 1; - - while ((int)elements < ((1 << (new_hash_table_power - 1)) * RELATIONSHIP)) { - new_hash_table_power--; + // Not an empty slot, let's check the probing length of the existing one. + uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity); + if (existing_probe_len < distance) { + SWAP(hash, hashes[pos]); + SWAP(value, elements[pos]); + distance = existing_probe_len; } - if (new_hash_table_power < (int)MIN_HASH_TABLE_POWER) { - new_hash_table_power = MIN_HASH_TABLE_POWER; - } + pos = (pos + 1) % capacity; + distance++; } + } - if (new_hash_table_power == -1) { - return; - } + void _resize_and_rehash(uint32_t p_new_capacity_index) { + uint32_t old_capacity = hash_table_size_primes[capacity_index]; - Element **new_hash_table = memnew_arr(Element *, ((uint64_t)1 << new_hash_table_power)); - ERR_FAIL_COND_MSG(!new_hash_table, "Out of memory."); + // Capacity can't be 0. + capacity_index = MAX((uint32_t)MIN_CAPACITY_INDEX, p_new_capacity_index); - for (int i = 0; i < (1 << new_hash_table_power); i++) { - new_hash_table[i] = nullptr; - } + uint32_t capacity = hash_table_size_primes[capacity_index]; - if (hash_table) { - for (int i = 0; i < (1 << hash_table_power); i++) { - while (hash_table[i]) { - Element *se = hash_table[i]; - hash_table[i] = se->next; - int new_pos = se->hash & ((1 << new_hash_table_power) - 1); - se->next = new_hash_table[new_pos]; - new_hash_table[new_pos] = se; - } - } + HashMapElement<TKey, TValue> **old_elements = elements; + uint32_t *old_hashes = hashes; - memdelete_arr(hash_table); - } - hash_table = new_hash_table; - hash_table_power = new_hash_table_power; - } + num_elements = 0; + hashes = reinterpret_cast<uint32_t *>(Memory::alloc_static(sizeof(uint32_t) * capacity)); + elements = reinterpret_cast<HashMapElement<TKey, TValue> **>(Memory::alloc_static(sizeof(HashMapElement<TKey, TValue> *) * capacity)); - /* I want to have only one function.. */ - _FORCE_INLINE_ const Element *get_element(const TKey &p_key) const { - uint32_t hash = Hasher::hash(p_key); - uint32_t index = hash & ((1 << hash_table_power) - 1); + for (uint32_t i = 0; i < capacity; i++) { + hashes[i] = 0; + elements[i] = nullptr; + } - Element *e = hash_table[index]; + if (old_capacity == 0) { + // Nothing to do. + return; + } - while (e) { - /* checking hash first avoids comparing key, which may take longer */ - if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) { - /* the pair exists in this hashtable, so just update data */ - return e; + for (uint32_t i = 0; i < old_capacity; i++) { + if (old_hashes[i] == EMPTY_HASH) { + continue; } - e = e->next; + _insert_with_hash(old_hashes[i], old_elements[i]); } - return nullptr; + Memory::free_static(old_elements); + Memory::free_static(old_hashes); } - Element *create_element(const TKey &p_key) { - /* if element doesn't exist, create it */ - Element *e = memnew(Element(p_key)); - ERR_FAIL_COND_V_MSG(!e, nullptr, "Out of memory."); - uint32_t hash = Hasher::hash(p_key); - uint32_t index = hash & ((1 << hash_table_power) - 1); - e->next = hash_table[index]; - e->hash = hash; - - hash_table[index] = e; - elements++; + _FORCE_INLINE_ HashMapElement<TKey, TValue> *_insert(const TKey &p_key, const TValue &p_value, bool p_front_insert = false) { + uint32_t capacity = hash_table_size_primes[capacity_index]; + if (unlikely(elements == nullptr)) { + // Allocate on demand to save memory. - return e; - } + hashes = reinterpret_cast<uint32_t *>(Memory::alloc_static(sizeof(uint32_t) * capacity)); + elements = reinterpret_cast<HashMapElement<TKey, TValue> **>(Memory::alloc_static(sizeof(HashMapElement<TKey, TValue> *) * capacity)); - void copy_from(const HashMap &p_t) { - if (&p_t == this) { - return; /* much less bother with that */ - } - - clear(); - - if (!p_t.hash_table || p_t.hash_table_power == 0) { - return; /* not copying from empty table */ + for (uint32_t i = 0; i < capacity; i++) { + hashes[i] = EMPTY_HASH; + elements[i] = nullptr; + } } - hash_table = memnew_arr(Element *, (uint64_t)1 << p_t.hash_table_power); - hash_table_power = p_t.hash_table_power; - elements = p_t.elements; + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); - for (int i = 0; i < (1 << p_t.hash_table_power); i++) { - hash_table[i] = nullptr; - - const Element *e = p_t.hash_table[i]; - - while (e) { - Element *le = memnew(Element(*e)); /* local element */ + if (exists) { + elements[pos]->data.value = p_value; + return elements[pos]; + } else { + if (num_elements + 1 > MAX_OCCUPANCY * capacity) { + ERR_FAIL_COND_V_MSG(capacity_index + 1 == HASH_TABLE_SIZE_MAX, nullptr, "Hash table maximum capacity reached, aborting insertion."); + _resize_and_rehash(capacity_index + 1); + } - /* add to list and reassign pointers */ - le->next = hash_table[i]; - hash_table[i] = le; + HashMapElement<TKey, TValue> *elem = element_alloc.new_allocation(HashMapElement<TKey, TValue>(p_key, p_value)); - e = e->next; + if (tail_element == nullptr) { + head_element = elem; + tail_element = elem; + } else if (p_front_insert) { + head_element->prev = elem; + elem->next = head_element; + head_element = elem; + } else { + tail_element->next = elem; + elem->prev = tail_element; + tail_element = elem; } + + uint32_t hash = _hash(p_key); + _insert_with_hash(hash, elem); + return elem; } } public: - Element *set(const TKey &p_key, const TData &p_data) { - return set(Pair(p_key, p_data)); - } + _FORCE_INLINE_ uint32_t get_capacity() const { return hash_table_size_primes[capacity_index]; } + _FORCE_INLINE_ uint32_t size() const { return num_elements; } - Element *set(const Pair &p_pair) { - Element *e = nullptr; - if (!hash_table) { - make_hash_table(); // if no table, make one - } else { - e = const_cast<Element *>(get_element(p_pair.key)); - } + /* Standard Godot Container API */ - /* if we made it up to here, the pair doesn't exist, create and assign */ + bool is_empty() const { + return num_elements == 0; + } - if (!e) { - e = create_element(p_pair.key); - if (!e) { - return nullptr; - } - check_hash_table(); // perform mantenience routine + void clear() { + if (elements == nullptr) { + return; } + uint32_t capacity = hash_table_size_primes[capacity_index]; + for (uint32_t i = 0; i < capacity; i++) { + if (hashes[i] == EMPTY_HASH) { + continue; + } - e->pair.data = p_pair.data; - return e; - } + hashes[i] = EMPTY_HASH; + element_alloc.delete_allocation(elements[i]); + elements[i] = nullptr; + } - bool has(const TKey &p_key) const { - return getptr(p_key) != nullptr; + tail_element = nullptr; + head_element = nullptr; + num_elements = 0; } - /** - * Get a key from data, return a const reference. - * WARNING: this doesn't check errors, use either getptr and check nullptr, or check - * first with has(key) - */ - - const TData &get(const TKey &p_key) const { - const TData *res = getptr(p_key); - CRASH_COND_MSG(!res, "Map key not found."); - return *res; + TValue &get(const TKey &p_key) { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); + CRASH_COND_MSG(!exists, "HashMap key not found."); + return elements[pos]->data.value; } - TData &get(const TKey &p_key) { - TData *res = getptr(p_key); - CRASH_COND_MSG(!res, "Map key not found."); - return *res; + const TValue &get(const TKey &p_key) const { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); + CRASH_COND_MSG(!exists, "HashMap key not found."); + return elements[pos]->data.value; } - /** - * Same as get, except it can return nullptr when item was not found. - * This is mainly used for speed purposes. - */ + const TValue *getptr(const TKey &p_key) const { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); - _FORCE_INLINE_ TData *getptr(const TKey &p_key) { - if (unlikely(!hash_table)) { - return nullptr; + if (exists) { + return &elements[pos]->data.value; } + return nullptr; + } - Element *e = const_cast<Element *>(get_element(p_key)); + TValue *getptr(const TKey &p_key) { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); - if (e) { - return &e->pair.data; + if (exists) { + return &elements[pos]->data.value; } - return nullptr; } - _FORCE_INLINE_ const TData *getptr(const TKey &p_key) const { - if (unlikely(!hash_table)) { - return nullptr; - } + _FORCE_INLINE_ bool has(const TKey &p_key) const { + uint32_t _pos = 0; + return _lookup_pos(p_key, _pos); + } - const Element *e = const_cast<Element *>(get_element(p_key)); + bool erase(const TKey &p_key) { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); - if (e) { - return &e->pair.data; + if (!exists) { + return false; } - return nullptr; - } + uint32_t capacity = hash_table_size_primes[capacity_index]; + uint32_t next_pos = (pos + 1) % capacity; + while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity) != 0) { + SWAP(hashes[next_pos], hashes[pos]); + SWAP(elements[next_pos], elements[pos]); + pos = next_pos; + next_pos = (pos + 1) % capacity; + } - /** - * Same as get, except it can return nullptr when item was not found. - * This version is custom, will take a hash and a custom key (that should support operator==() - */ + hashes[pos] = EMPTY_HASH; - template <class C> - _FORCE_INLINE_ TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) { - if (unlikely(!hash_table)) { - return nullptr; + if (head_element == elements[pos]) { + head_element = elements[pos]->next; } - uint32_t hash = p_custom_hash; - uint32_t index = hash & ((1 << hash_table_power) - 1); - - Element *e = hash_table[index]; + if (tail_element == elements[pos]) { + tail_element = elements[pos]->prev; + } - while (e) { - /* checking hash first avoids comparing key, which may take longer */ - if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) { - /* the pair exists in this hashtable, so just update data */ - return &e->pair.data; - } + if (elements[pos]->prev) { + elements[pos]->prev->next = elements[pos]->next; + } - e = e->next; + if (elements[pos]->next) { + elements[pos]->next->prev = elements[pos]->prev; } - return nullptr; + element_alloc.delete_allocation(elements[pos]); + elements[pos] = nullptr; + + num_elements--; + return true; } - template <class C> - _FORCE_INLINE_ const TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) const { - if (unlikely(!hash_table)) { - return nullptr; + // Reserves space for a number of elements, useful to avoid many resizes and rehashes. + // If adding a known (possibly large) number of elements at once, must be larger than old capacity. + void reserve(uint32_t p_new_capacity) { + uint32_t new_index = capacity_index; + + while (hash_table_size_primes[new_index] < p_new_capacity) { + ERR_FAIL_COND_MSG(new_index + 1 == (uint32_t)HASH_TABLE_SIZE_MAX, nullptr); + new_index++; } - uint32_t hash = p_custom_hash; - uint32_t index = hash & ((1 << hash_table_power) - 1); + if (new_index == capacity_index) { + return; + } - const Element *e = hash_table[index]; + if (elements == nullptr) { + capacity_index = new_index; + return; // Unallocated yet. + } + _resize_and_rehash(new_index); + } - while (e) { - /* checking hash first avoids comparing key, which may take longer */ - if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) { - /* the pair exists in this hashtable, so just update data */ - return &e->pair.data; - } + /** Iterator API **/ - e = e->next; + struct ConstIterator { + _FORCE_INLINE_ const KeyValue<TKey, TValue> &operator*() const { + return E->data; + } + _FORCE_INLINE_ const KeyValue<TKey, TValue> *operator->() const { return &E->data; } + _FORCE_INLINE_ ConstIterator &operator++() { + if (E) { + E = E->next; + } + return *this; + } + _FORCE_INLINE_ ConstIterator &operator--() { + if (E) { + E = E->prev; + } + return *this; } - return nullptr; - } + _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; } + _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; } - /** - * Erase an item, return true if erasing was successful - */ + _FORCE_INLINE_ explicit operator bool() const { + return E != nullptr; + } - bool erase(const TKey &p_key) { - if (unlikely(!hash_table)) { - return false; + _FORCE_INLINE_ ConstIterator(const HashMapElement<TKey, TValue> *p_E) { E = p_E; } + _FORCE_INLINE_ ConstIterator() {} + _FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; } + _FORCE_INLINE_ void operator=(const ConstIterator &p_it) { + E = p_it.E; } - uint32_t hash = Hasher::hash(p_key); - uint32_t index = hash & ((1 << hash_table_power) - 1); - - Element *e = hash_table[index]; - Element *p = nullptr; - while (e) { - /* checking hash first avoids comparing key, which may take longer */ - if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) { - if (p) { - p->next = e->next; - } else { - //begin of list - hash_table[index] = e->next; - } - - memdelete(e); - elements--; - - if (elements == 0) { - erase_hash_table(); - } else { - check_hash_table(); - } - return true; + private: + const HashMapElement<TKey, TValue> *E = nullptr; + }; + + struct Iterator { + _FORCE_INLINE_ KeyValue<TKey, TValue> &operator*() const { + return E->data; + } + _FORCE_INLINE_ KeyValue<TKey, TValue> *operator->() const { return &E->data; } + _FORCE_INLINE_ Iterator &operator++() { + if (E) { + E = E->next; + } + return *this; + } + _FORCE_INLINE_ Iterator &operator--() { + if (E) { + E = E->prev; } + return *this; + } - p = e; - e = e->next; + _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; } + _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; } + + _FORCE_INLINE_ explicit operator bool() const { + return E != nullptr; } - return false; - } + _FORCE_INLINE_ Iterator(HashMapElement<TKey, TValue> *p_E) { E = p_E; } + _FORCE_INLINE_ Iterator() {} + _FORCE_INLINE_ Iterator(const Iterator &p_it) { E = p_it.E; } + _FORCE_INLINE_ void operator=(const Iterator &p_it) { + E = p_it.E; + } + + operator ConstIterator() const { + return ConstIterator(E); + } - inline const TData &operator[](const TKey &p_key) const { //constref + private: + HashMapElement<TKey, TValue> *E = nullptr; + }; - return get(p_key); + _FORCE_INLINE_ Iterator begin() { + return Iterator(head_element); + } + _FORCE_INLINE_ Iterator end() { + return Iterator(nullptr); + } + _FORCE_INLINE_ Iterator last() { + return Iterator(tail_element); } - inline TData &operator[](const TKey &p_key) { //assignment - Element *e = nullptr; - if (!hash_table) { - make_hash_table(); // if no table, make one - } else { - e = const_cast<Element *>(get_element(p_key)); + _FORCE_INLINE_ Iterator find(const TKey &p_key) { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); + if (!exists) { + return end(); } + return Iterator(elements[pos]); + } - /* if we made it up to here, the pair doesn't exist, create */ - if (!e) { - e = create_element(p_key); - CRASH_COND(!e); - check_hash_table(); // perform mantenience routine + _FORCE_INLINE_ void remove(const Iterator &p_iter) { + if (p_iter) { + erase(p_iter->key); } + } - return e->pair.data; + _FORCE_INLINE_ ConstIterator begin() const { + return ConstIterator(head_element); + } + _FORCE_INLINE_ ConstIterator end() const { + return ConstIterator(nullptr); + } + _FORCE_INLINE_ ConstIterator last() const { + return ConstIterator(tail_element); } - /** - * Get the next key to p_key, and the first key if p_key is null. - * Returns a pointer to the next key if found, nullptr otherwise. - * Adding/Removing elements while iterating will, of course, have unexpected results, don't do it. - * - * Example: - * - * const TKey *k=nullptr; - * - * while( (k=table.next(k)) ) { - * - * print( *k ); - * } - * - */ - const TKey *next(const TKey *p_key) const { - if (unlikely(!hash_table)) { - return nullptr; + _FORCE_INLINE_ ConstIterator find(const TKey &p_key) const { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); + if (!exists) { + return end(); } + return ConstIterator(elements[pos]); + } - if (!p_key) { /* get the first key */ - - for (int i = 0; i < (1 << hash_table_power); i++) { - if (hash_table[i]) { - return &hash_table[i]->pair.key; - } - } - - } else { /* get the next key */ + /* Indexing */ - const Element *e = get_element(*p_key); - ERR_FAIL_COND_V_MSG(!e, nullptr, "Invalid key supplied."); - if (e->next) { - /* if there is a "next" in the list, return that */ - return &e->next->pair.key; - } else { - /* go to next elements */ - uint32_t index = e->hash & ((1 << hash_table_power) - 1); - index++; - for (int i = index; i < (1 << hash_table_power); i++) { - if (hash_table[i]) { - return &hash_table[i]->pair.key; - } - } - } + const TValue &operator[](const TKey &p_key) const { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); + CRASH_COND(!exists); + return elements[pos]->data.value; + } - /* nothing found, was at end */ + TValue &operator[](const TKey &p_key) { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); + if (!exists) { + return _insert(p_key, TValue())->data.value; + } else { + return elements[pos]->data.value; } - - return nullptr; /* nothing found */ } - inline unsigned int size() const { - return elements; - } + /* Insert */ - inline bool is_empty() const { - return elements == 0; + Iterator insert(const TKey &p_key, const TValue &p_value, bool p_front_insert = false) { + return Iterator(_insert(p_key, p_value, p_front_insert)); } - void clear() { - /* clean up */ - if (hash_table) { - for (int i = 0; i < (1 << hash_table_power); i++) { - while (hash_table[i]) { - Element *e = hash_table[i]; - hash_table[i] = e->next; - memdelete(e); - } - } + /* Constructors */ - memdelete_arr(hash_table); + HashMap(const HashMap &p_other) { + reserve(hash_table_size_primes[p_other.capacity_index]); + + if (p_other.num_elements == 0) { + return; } - hash_table = nullptr; - hash_table_power = 0; - elements = 0; + for (const KeyValue<TKey, TValue> &E : p_other) { + insert(E.key, E.value); + } } - void operator=(const HashMap &p_table) { - copy_from(p_table); - } + void operator=(const HashMap &p_other) { + if (this == &p_other) { + return; // Ignore self assignment. + } + if (num_elements != 0) { + clear(); + } - void get_key_list(List<TKey> *r_keys) const { - if (unlikely(!hash_table)) { - return; + reserve(hash_table_size_primes[p_other.capacity_index]); + + if (p_other.elements == nullptr) { + return; // Nothing to copy. } - for (int i = 0; i < (1 << hash_table_power); i++) { - Element *e = hash_table[i]; - while (e) { - r_keys->push_back(e->pair.key); - e = e->next; - } + + for (const KeyValue<TKey, TValue> &E : p_other) { + insert(E.key, E.value); } } - HashMap() {} + HashMap(uint32_t p_initial_capacity) { + // Capacity can't be 0. + capacity_index = 0; + reserve(p_initial_capacity); + } + HashMap() { + capacity_index = MIN_CAPACITY_INDEX; + } - HashMap(const HashMap &p_table) { - copy_from(p_table); + uint32_t debug_get_hash(uint32_t p_index) { + if (num_elements == 0) { + return 0; + } + ERR_FAIL_INDEX_V(p_index, get_capacity(), 0); + return hashes[p_index]; + } + Iterator debug_get_element(uint32_t p_index) { + if (num_elements == 0) { + return Iterator(); + } + ERR_FAIL_INDEX_V(p_index, get_capacity(), Iterator()); + return Iterator(elements[p_index]); } ~HashMap() { clear(); + + if (elements != nullptr) { + Memory::free_static(elements); + Memory::free_static(hashes); + } } }; diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h index 2a129f97d5..1330d55270 100644 --- a/core/templates/hashfuncs.h +++ b/core/templates/hashfuncs.h @@ -31,14 +31,22 @@ #ifndef HASHFUNCS_H #define HASHFUNCS_H +#include "core/math/aabb.h" #include "core/math/math_defs.h" #include "core/math/math_funcs.h" +#include "core/math/rect2.h" +#include "core/math/rect2i.h" +#include "core/math/vector2.h" +#include "core/math/vector2i.h" +#include "core/math/vector3.h" +#include "core/math/vector3i.h" #include "core/object/object_id.h" #include "core/string/node_path.h" #include "core/string/string_name.h" #include "core/string/ustring.h" #include "core/templates/rid.h" #include "core/typedefs.h" + /** * Hashing functions */ @@ -155,6 +163,9 @@ static inline uint64_t make_uint64_t(T p_in) { return _u._u64; } +template <class T> +class Ref; + struct HashMapHasherDefault { static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } @@ -178,6 +189,55 @@ struct HashMapHasherDefault { static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); } static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); } + template <class T> + static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); } + + template <class T> + static _FORCE_INLINE_ uint32_t hash(const Ref<T> &p_ref) { return hash_one_uint64((uint64_t)p_ref.operator->()); } + + static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) { + uint32_t h = hash_djb2_one_32(p_vec.x); + return hash_djb2_one_32(p_vec.y, h); + } + static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) { + uint32_t h = hash_djb2_one_32(p_vec.x); + h = hash_djb2_one_32(p_vec.y, h); + return hash_djb2_one_32(p_vec.z, h); + } + + static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) { + uint32_t h = hash_djb2_one_float(p_vec.x); + return hash_djb2_one_float(p_vec.y, h); + } + static _FORCE_INLINE_ uint32_t hash(const Vector3 &p_vec) { + uint32_t h = hash_djb2_one_float(p_vec.x); + h = hash_djb2_one_float(p_vec.y, h); + return hash_djb2_one_float(p_vec.z, h); + } + + static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) { + uint32_t h = hash_djb2_one_32(p_rect.position.x); + h = hash_djb2_one_32(p_rect.position.y, h); + h = hash_djb2_one_32(p_rect.size.x, h); + return hash_djb2_one_32(p_rect.size.y, h); + } + + static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) { + uint32_t h = hash_djb2_one_float(p_rect.position.x); + h = hash_djb2_one_float(p_rect.position.y, h); + h = hash_djb2_one_float(p_rect.size.x, h); + return hash_djb2_one_float(p_rect.size.y, h); + } + + static _FORCE_INLINE_ uint32_t hash(const AABB &p_aabb) { + uint32_t h = hash_djb2_one_float(p_aabb.position.x); + h = hash_djb2_one_float(p_aabb.position.y, h); + h = hash_djb2_one_float(p_aabb.position.z, h); + h = hash_djb2_one_float(p_aabb.size.x, h); + h = hash_djb2_one_float(p_aabb.size.y, h); + return hash_djb2_one_float(p_aabb.size.z, h); + } + //static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); } }; @@ -186,14 +246,68 @@ struct HashMapComparatorDefault { static bool compare(const T &p_lhs, const T &p_rhs) { return p_lhs == p_rhs; } +}; - bool compare(const float &p_lhs, const float &p_rhs) { +template <> +struct HashMapComparatorDefault<float> { + static bool compare(const float &p_lhs, const float &p_rhs) { return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); } +}; - bool compare(const double &p_lhs, const double &p_rhs) { +template <> +struct HashMapComparatorDefault<double> { + static bool compare(const double &p_lhs, const double &p_rhs) { return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); } }; +template <> +struct HashMapComparatorDefault<Vector2> { + static bool compare(const Vector2 &p_lhs, const Vector2 &p_rhs) { + return ((p_lhs.x == p_rhs.x) || (Math::is_nan(p_lhs.x) && Math::is_nan(p_rhs.x))) && ((p_lhs.y == p_rhs.y) || (Math::is_nan(p_lhs.y) && Math::is_nan(p_rhs.y))); + } +}; + +template <> +struct HashMapComparatorDefault<Vector3> { + static bool compare(const Vector3 &p_lhs, const Vector3 &p_rhs) { + return ((p_lhs.x == p_rhs.x) || (Math::is_nan(p_lhs.x) && Math::is_nan(p_rhs.x))) && ((p_lhs.y == p_rhs.y) || (Math::is_nan(p_lhs.y) && Math::is_nan(p_rhs.y))) && ((p_lhs.z == p_rhs.z) || (Math::is_nan(p_lhs.z) && Math::is_nan(p_rhs.z))); + } +}; + +constexpr uint32_t HASH_TABLE_SIZE_MAX = 29; + +const uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = { + 5, + 13, + 23, + 47, + 97, + 193, + 389, + 769, + 1543, + 3079, + 6151, + 12289, + 24593, + 49157, + 98317, + 196613, + 393241, + 786433, + 1572869, + 3145739, + 6291469, + 12582917, + 25165843, + 50331653, + 100663319, + 201326611, + 402653189, + 805306457, + 1610612741, +}; + #endif // HASHFUNCS_H diff --git a/core/templates/ordered_hash_map.h b/core/templates/ordered_hash_map.h deleted file mode 100644 index 3d1f3a08ec..0000000000 --- a/core/templates/ordered_hash_map.h +++ /dev/null @@ -1,301 +0,0 @@ -/*************************************************************************/ -/* ordered_hash_map.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 ORDERED_HASH_MAP_H -#define ORDERED_HASH_MAP_H - -#include "core/templates/hash_map.h" -#include "core/templates/list.h" -#include "core/templates/pair.h" - -/** - * A hash map which allows to iterate elements in insertion order. - * Insertion, lookup, deletion have O(1) complexity. - * The API aims to be consistent with Map rather than HashMap, because the - * former is more frequently used and is more coherent with the rest of the - * codebase. - * Deletion during iteration is safe and will preserve the order. - */ -template <class K, class V, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<K>, uint8_t MIN_HASH_TABLE_POWER = 3, uint8_t RELATIONSHIP = 8> -class OrderedHashMap { - typedef List<Pair<const K *, V>> InternalList; - typedef HashMap<K, typename InternalList::Element *, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP> InternalMap; - - InternalList list; - InternalMap map; - -public: - class Element { - friend class OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>; - - typename InternalList::Element *list_element = nullptr; - typename InternalList::Element *prev_element = nullptr; - typename InternalList::Element *next_element = nullptr; - - Element(typename InternalList::Element *p_element) { - list_element = p_element; - - if (list_element) { - next_element = list_element->next(); - prev_element = list_element->prev(); - } - } - - public: - _FORCE_INLINE_ Element() {} - - Element next() const { - return Element(next_element); - } - - Element prev() const { - return Element(prev_element); - } - - Element(const Element &other) : - list_element(other.list_element), - prev_element(other.prev_element), - next_element(other.next_element) { - } - - void operator=(const Element &other) { - list_element = other.list_element; - next_element = other.next_element; - prev_element = other.prev_element; - } - - _FORCE_INLINE_ bool operator==(const Element &p_other) const { - return this->list_element == p_other.list_element; - } - _FORCE_INLINE_ bool operator!=(const Element &p_other) const { - return this->list_element != p_other.list_element; - } - - operator bool() const { - return (list_element != nullptr); - } - - const K &key() const { - CRASH_COND(!list_element); - return *(list_element->get().first); - } - - V &value() { - CRASH_COND(!list_element); - return list_element->get().second; - } - - const V &value() const { - CRASH_COND(!list_element); - return list_element->get().second; - } - - V &get() { - CRASH_COND(!list_element); - return list_element->get().second; - } - - const V &get() const { - CRASH_COND(!list_element); - return list_element->get().second; - } - }; - - class ConstElement { - friend class OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>; - - const typename InternalList::Element *list_element = nullptr; - - ConstElement(const typename InternalList::Element *p_element) : - list_element(p_element) { - } - - public: - _FORCE_INLINE_ ConstElement() {} - - ConstElement(const ConstElement &other) : - list_element(other.list_element) { - } - - void operator=(const ConstElement &other) { - list_element = other.list_element; - } - - ConstElement next() const { - return ConstElement(list_element ? list_element->next() : nullptr); - } - - ConstElement prev() const { - return ConstElement(list_element ? list_element->prev() : nullptr); - } - - _FORCE_INLINE_ bool operator==(const ConstElement &p_other) const { - return this->list_element == p_other.list_element; - } - _FORCE_INLINE_ bool operator!=(const ConstElement &p_other) const { - return this->list_element != p_other.list_element; - } - - operator bool() const { - return (list_element != nullptr); - } - - const K &key() const { - CRASH_COND(!list_element); - return *(list_element->get().first); - } - - const V &value() const { - CRASH_COND(!list_element); - return list_element->get().second; - } - - const V &get() const { - CRASH_COND(!list_element); - return list_element->get().second; - } - }; - - ConstElement find(const K &p_key) const { - typename InternalList::Element *const *list_element = map.getptr(p_key); - if (list_element) { - return ConstElement(*list_element); - } - return ConstElement(nullptr); - } - - Element find(const K &p_key) { - typename InternalList::Element **list_element = map.getptr(p_key); - if (list_element) { - return Element(*list_element); - } - return Element(nullptr); - } - - Element insert(const K &p_key, const V &p_value) { - typename InternalList::Element **list_element = map.getptr(p_key); - if (list_element) { - (*list_element)->get().second = p_value; - return Element(*list_element); - } - // Incorrectly set the first value of the pair with a value that will - // be invalid as soon as we leave this function... - typename InternalList::Element *new_element = list.push_back(Pair<const K *, V>(&p_key, p_value)); - // ...this is needed here in case the hashmap recursively reference itself... - typename InternalMap::Element *e = map.set(p_key, new_element); - // ...now we can set the right value ! - new_element->get().first = &e->key(); - - return Element(new_element); - } - - void erase(Element &p_element) { - map.erase(p_element.key()); - list.erase(p_element.list_element); - p_element.list_element = nullptr; - } - - bool erase(const K &p_key) { - typename InternalList::Element **list_element = map.getptr(p_key); - if (list_element) { - list.erase(*list_element); - map.erase(p_key); - return true; - } - return false; - } - - inline bool has(const K &p_key) const { - return map.has(p_key); - } - - const V &operator[](const K &p_key) const { - ConstElement e = find(p_key); - CRASH_COND(!e); - return e.value(); - } - - V &operator[](const K &p_key) { - Element e = find(p_key); - if (!e) { - // consistent with Map behaviour - e = insert(p_key, V()); - } - return e.value(); - } - - inline Element front() { - return Element(list.front()); - } - - inline Element back() { - return Element(list.back()); - } - - inline ConstElement front() const { - return ConstElement(list.front()); - } - - inline ConstElement back() const { - return ConstElement(list.back()); - } - - inline bool is_empty() const { return list.is_empty(); } - inline int size() const { return list.size(); } - - const void *id() const { - return list.id(); - } - - void clear() { - map.clear(); - list.clear(); - } - -private: - void _copy_from(const OrderedHashMap &p_map) { - for (ConstElement E = p_map.front(); E; E = E.next()) { - insert(E.key(), E.value()); - } - } - -public: - void operator=(const OrderedHashMap &p_map) { - _copy_from(p_map); - } - - OrderedHashMap(const OrderedHashMap &p_map) { - _copy_from(p_map); - } - - _FORCE_INLINE_ OrderedHashMap() {} -}; - -#endif // ORDERED_HASH_MAP_H diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h index b9067e2edd..cf5911a847 100644 --- a/core/templates/paged_allocator.h +++ b/core/templates/paged_allocator.h @@ -50,6 +50,10 @@ class PagedAllocator { SpinLock spin_lock; public: + enum { + DEFAULT_PAGE_SIZE = 4096 + }; + template <class... Args> T *alloc(const Args &&...p_args) { if (thread_safe) { @@ -121,7 +125,9 @@ public: page_shift = get_shift_from_power_of_2(page_size); } - PagedAllocator(uint32_t p_page_size = 4096) { // power of 2 recommended because of alignment with OS page sizes. Even if element is bigger, its still a multiple and get rounded amount of pages + // Power of 2 recommended because of alignment with OS page sizes. + // Even if element is bigger, it's still a multiple and gets rounded to amount of pages. + PagedAllocator(uint32_t p_page_size = DEFAULT_PAGE_SIZE) { configure(p_page_size); } diff --git a/core/templates/pair.h b/core/templates/pair.h index eb86e21b03..6d33213fe3 100644 --- a/core/templates/pair.h +++ b/core/templates/pair.h @@ -31,8 +31,8 @@ #ifndef PAIR_H #define PAIR_H +#include "core/templates/hashfuncs.h" #include "core/typedefs.h" - template <class F, class S> struct Pair { F first; @@ -69,6 +69,15 @@ struct PairSort { } }; +template <class F, class S> +struct PairHash { + static uint32_t hash(const Pair<F, S> &P) { + uint64_t h1 = HashMapHasherDefault::hash(P.first); + uint64_t h2 = HashMapHasherDefault::hash(P.second); + return hash_one_uint64((h1 << 32) | h2); + } +}; + template <class K, class V> struct KeyValue { const K key; diff --git a/core/templates/map.h b/core/templates/rb_map.h index c54da1dc03..c732ccd485 100644 --- a/core/templates/map.h +++ b/core/templates/rb_map.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* map.h */ +/* rb_map.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef MAP_H -#define MAP_H +#ifndef RB_MAP_H +#define RB_MAP_H #include "core/error/error_macros.h" #include "core/os/memory.h" @@ -39,7 +39,7 @@ // https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html template <class K, class V, class C = Comparator<K>, class A = DefaultAllocator> -class Map { +class RBMap { enum Color { RED, BLACK @@ -49,7 +49,7 @@ class Map { public: class Element { private: - friend class Map<K, V, C, A>; + friend class RBMap<K, V, C, A>; int color = RED; Element *right = nullptr; Element *left = nullptr; @@ -111,7 +111,9 @@ public: _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; } _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; } - + explicit operator bool() const { + return E != nullptr; + } Iterator(Element *p_E) { E = p_E; } Iterator() {} Iterator(const Iterator &p_it) { E = p_it.E; } @@ -136,7 +138,9 @@ public: _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; } _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; } - + explicit operator bool() const { + return E != nullptr; + } ConstIterator(const Element *p_E) { E = p_E; } ConstIterator() {} ConstIterator(const ConstIterator &p_it) { E = p_it.E; } @@ -572,7 +576,7 @@ private: memdelete_allocator<Element, A>(p_element); } - void _copy_from(const Map &p_map) { + void _copy_from(const RBMap &p_map) { clear(); // not the fastest way, but safeset to write. for (Element *I = p_map.front(); I; I = I->next()) { @@ -710,8 +714,12 @@ public: return e; } - inline bool is_empty() const { return _data.size_cache == 0; } - inline int size() const { return _data.size_cache; } + inline bool is_empty() const { + return _data.size_cache == 0; + } + inline int size() const { + return _data.size_cache; + } int calculate_depth() const { // used for debug mostly @@ -735,17 +743,17 @@ public: _data._free_root(); } - void operator=(const Map &p_map) { + void operator=(const RBMap &p_map) { _copy_from(p_map); } - Map(const Map &p_map) { + RBMap(const RBMap &p_map) { _copy_from(p_map); } - _FORCE_INLINE_ Map() {} + _FORCE_INLINE_ RBMap() {} - ~Map() { + ~RBMap() { clear(); } }; diff --git a/core/templates/set.h b/core/templates/rb_set.h index a8a0a77712..2de816769c 100644 --- a/core/templates/set.h +++ b/core/templates/rb_set.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* set.h */ +/* rb_set.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SET_H -#define SET_H +#ifndef RB_SET_H +#define RB_SET_H #include "core/os/memory.h" #include "core/typedefs.h" @@ -38,7 +38,7 @@ // https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html template <class T, class C = Comparator<T>, class A = DefaultAllocator> -class Set { +class RBSet { enum Color { RED, BLACK @@ -48,7 +48,7 @@ class Set { public: class Element { private: - friend class Set<T, C, A>; + friend class RBSet<T, C, A>; int color = RED; Element *right = nullptr; Element *left = nullptr; @@ -554,7 +554,7 @@ private: memdelete_allocator<Element, A>(p_element); } - void _copy_from(const Set &p_set) { + void _copy_from(const RBSet &p_set) { clear(); // not the fastest way, but safeset to write. for (Element *I = p_set.front(); I; I = I->next()) { @@ -661,8 +661,12 @@ public: return e; } - inline bool is_empty() const { return _data.size_cache == 0; } - inline int size() const { return _data.size_cache; } + inline bool is_empty() const { + return _data.size_cache == 0; + } + inline int size() const { + return _data.size_cache; + } int calculate_depth() const { // used for debug mostly @@ -686,17 +690,17 @@ public: _data._free_root(); } - void operator=(const Set &p_set) { + void operator=(const RBSet &p_set) { _copy_from(p_set); } - Set(const Set &p_set) { + RBSet(const RBSet &p_set) { _copy_from(p_set); } - _FORCE_INLINE_ Set() {} + _FORCE_INLINE_ RBSet() {} - ~Set() { + ~RBSet() { clear(); } }; diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h index 95632cdec2..d26977380e 100644 --- a/core/templates/rid_owner.h +++ b/core/templates/rid_owner.h @@ -36,9 +36,9 @@ #include "core/string/print_string.h" #include "core/templates/list.h" #include "core/templates/oa_hash_map.h" +#include "core/templates/rb_set.h" #include "core/templates/rid.h" #include "core/templates/safe_refcount.h" -#include "core/templates/set.h" #include <stdio.h> #include <typeinfo> diff --git a/core/templates/vector.h b/core/templates/vector.h index d87e76139b..2ac7c7630a 100644 --- a/core/templates/vector.h +++ b/core/templates/vector.h @@ -92,6 +92,8 @@ public: _FORCE_INLINE_ const T &operator[](int p_index) const { return _cowdata.get(p_index); } Error insert(int p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); } int find(const T &p_val, int p_from = 0) const { return _cowdata.find(p_val, p_from); } + int rfind(const T &p_val, int p_from = -1) const { return _cowdata.rfind(p_val, p_from); } + int count(const T &p_val) const { return _cowdata.count(p_val); } void append_array(Vector<T> p_other); diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp index 0f2f8fc8ed..bda8c93a79 100644 --- a/core/variant/dictionary.cpp +++ b/core/variant/dictionary.cpp @@ -30,7 +30,7 @@ #include "dictionary.h" -#include "core/templates/ordered_hash_map.h" +#include "core/templates/hash_map.h" #include "core/templates/safe_refcount.h" #include "core/variant/variant.h" // required in this order by VariantInternal, do not remove this comment. @@ -41,7 +41,8 @@ struct DictionaryPrivate { SafeRefCount refcount; - OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map; + Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values. + HashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map; }; void Dictionary::get_key_list(List<Variant> *p_keys) const { @@ -49,16 +50,16 @@ void Dictionary::get_key_list(List<Variant> *p_keys) const { return; } - for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { - p_keys->push_back(E.key()); + for (const KeyValue<Variant, Variant> &E : _p->variant_map) { + p_keys->push_back(E.key); } } Variant Dictionary::get_key_at_index(int p_index) const { int index = 0; - for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { + for (const KeyValue<Variant, Variant> &E : _p->variant_map) { if (index == p_index) { - return E.key(); + return E.key; } index++; } @@ -68,9 +69,9 @@ Variant Dictionary::get_key_at_index(int p_index) const { Variant Dictionary::get_value_at_index(int p_index) const { int index = 0; - for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { + for (const KeyValue<Variant, Variant> &E : _p->variant_map) { if (index == p_index) { - return E.value(); + return E.value; } index++; } @@ -79,11 +80,22 @@ Variant Dictionary::get_value_at_index(int p_index) const { } Variant &Dictionary::operator[](const Variant &p_key) { - if (p_key.get_type() == Variant::STRING_NAME) { - const StringName *sn = VariantInternal::get_string_name(&p_key); - return _p->variant_map[sn->operator String()]; + if (unlikely(_p->read_only)) { + if (p_key.get_type() == Variant::STRING_NAME) { + const StringName *sn = VariantInternal::get_string_name(&p_key); + *_p->read_only = _p->variant_map[sn->operator String()]; + } else { + *_p->read_only = _p->variant_map[p_key]; + } + + return *_p->read_only; } else { - return _p->variant_map[p_key]; + if (p_key.get_type() == Variant::STRING_NAME) { + const StringName *sn = VariantInternal::get_string_name(&p_key); + return _p->variant_map[sn->operator String()]; + } else { + return _p->variant_map[p_key]; + } } } @@ -97,50 +109,55 @@ const Variant &Dictionary::operator[](const Variant &p_key) const { } const Variant *Dictionary::getptr(const Variant &p_key) const { - OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E; + HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E; if (p_key.get_type() == Variant::STRING_NAME) { const StringName *sn = VariantInternal::get_string_name(&p_key); - E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String()); + E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String()); } else { - E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); + E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); } if (!E) { return nullptr; } - return &E.get(); + return &E->value; } Variant *Dictionary::getptr(const Variant &p_key) { - OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E; + HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E; if (p_key.get_type() == Variant::STRING_NAME) { const StringName *sn = VariantInternal::get_string_name(&p_key); - E = ((OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String()); + E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String()); } else { - E = ((OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); + E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); } if (!E) { return nullptr; } - return &E.get(); + if (unlikely(_p->read_only != nullptr)) { + *_p->read_only = E->value; + return _p->read_only; + } else { + return &E->value; + } } Variant Dictionary::get_valid(const Variant &p_key) const { - OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E; + HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E; if (p_key.get_type() == Variant::STRING_NAME) { const StringName *sn = VariantInternal::get_string_name(&p_key); - E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String()); + E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String()); } else { - E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); + E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); } if (!E) { return Variant(); } - return E.get(); + return E->value; } Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const { @@ -179,6 +196,7 @@ bool Dictionary::has_all(const Array &p_keys) const { } bool Dictionary::erase(const Variant &p_key) { + ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state."); if (p_key.get_type() == Variant::STRING_NAME) { const StringName *sn = VariantInternal::get_string_name(&p_key); return _p->variant_map.erase(sn->operator String()); @@ -210,9 +228,9 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c return true; } recursion_count++; - for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement this_E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->front(); this_E; this_E = this_E.next()) { - OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement other_E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key()); - if (!other_E || !this_E.value().hash_compare(other_E.value(), recursion_count)) { + for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) { + HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator other_E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key); + if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count)) { return false; } } @@ -220,6 +238,16 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c } void Dictionary::_ref(const Dictionary &p_from) const { + if (unlikely(p_from._p->read_only != nullptr)) { + // If p_from is a read-only dictionary, just copy the contents to avoid further modification. + if (_p) { + _unref(); + } + _p = memnew(DictionaryPrivate); + _p->refcount.init(); + _p->variant_map = p_from._p->variant_map; + return; + } //make a copy first (thread safe) if (!p_from._p->refcount.ref()) { return; // couldn't copy @@ -237,12 +265,16 @@ void Dictionary::_ref(const Dictionary &p_from) const { } void Dictionary::clear() { + ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state."); _p->variant_map.clear(); } void Dictionary::_unref() const { ERR_FAIL_COND(!_p); if (_p->refcount.unref()) { + if (_p->read_only) { + memdelete(_p->read_only); + } memdelete(_p); } _p = nullptr; @@ -261,9 +293,9 @@ uint32_t Dictionary::recursive_hash(int recursion_count) const { uint32_t h = hash_djb2_one_32(Variant::DICTIONARY); recursion_count++; - for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { - h = hash_djb2_one_32(E.key().recursive_hash(recursion_count), h); - h = hash_djb2_one_32(E.value().recursive_hash(recursion_count), h); + for (const KeyValue<Variant, Variant> &E : _p->variant_map) { + h = hash_djb2_one_32(E.key.recursive_hash(recursion_count), h); + h = hash_djb2_one_32(E.value.recursive_hash(recursion_count), h); } return h; @@ -278,8 +310,8 @@ Array Dictionary::keys() const { varr.resize(size()); int i = 0; - for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { - varr[i] = E.key(); + for (const KeyValue<Variant, Variant> &E : _p->variant_map) { + varr[i] = E.key; i++; } @@ -295,8 +327,8 @@ Array Dictionary::values() const { varr.resize(size()); int i = 0; - for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { - varr[i] = E.get(); + for (const KeyValue<Variant, Variant> &E : _p->variant_map) { + varr[i] = E.value; i++; } @@ -306,16 +338,23 @@ Array Dictionary::values() const { const Variant *Dictionary::next(const Variant *p_key) const { if (p_key == nullptr) { // caller wants to get the first element - if (_p->variant_map.front()) { - return &_p->variant_map.front().key(); + if (_p->variant_map.begin()) { + return &_p->variant_map.begin()->key; } return nullptr; } - OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(*p_key); + HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E = _p->variant_map.find(*p_key); + + if (!E) { + return nullptr; + } + + ++E; - if (E && E.next()) { - return &E.next().key(); + if (E) { + return &E->key; } + return nullptr; } @@ -323,6 +362,21 @@ Dictionary Dictionary::duplicate(bool p_deep) const { return recursive_duplicate(p_deep, 0); } +void Dictionary::set_read_only(bool p_enable) { + if (p_enable == bool(_p->read_only != nullptr)) { + return; + } + if (p_enable) { + _p->read_only = memnew(Variant); + } else { + memdelete(_p->read_only); + _p->read_only = nullptr; + } +} +bool Dictionary::is_read_only() const { + return _p->read_only != nullptr; +} + Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) const { Dictionary n; @@ -333,12 +387,12 @@ Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) con if (p_deep) { recursion_count++; - for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { - n[E.key().recursive_duplicate(true, recursion_count)] = E.value().recursive_duplicate(true, recursion_count); + for (const KeyValue<Variant, Variant> &E : _p->variant_map) { + n[E.key.recursive_duplicate(true, recursion_count)] = E.value.recursive_duplicate(true, recursion_count); } } else { - for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { - n[E.key()] = E.value(); + for (const KeyValue<Variant, Variant> &E : _p->variant_map) { + n[E.key] = E.value; } } @@ -346,6 +400,9 @@ Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) con } void Dictionary::operator=(const Dictionary &p_dictionary) { + if (this == &p_dictionary) { + return; + } _ref(p_dictionary); } diff --git a/core/variant/dictionary.h b/core/variant/dictionary.h index 16cf0c2bf8..1224a4ff6f 100644 --- a/core/variant/dictionary.h +++ b/core/variant/dictionary.h @@ -84,6 +84,9 @@ public: Dictionary duplicate(bool p_deep = false) const; Dictionary recursive_duplicate(bool p_deep, int recursion_count) const; + void set_read_only(bool p_enable); + bool is_read_only() const; + const void *id() const; Dictionary(const Dictionary &p_from); diff --git a/core/variant/variant.h b/core/variant/variant.h index 475bf7158d..726ba120b5 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -473,6 +473,7 @@ public: OP_NEGATE, OP_POSITIVE, OP_MODULE, + OP_POWER, //bitwise OP_SHIFT_LEFT, OP_SHIFT_RIGHT, diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index f4b2af5a94..a3568a8d6a 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -919,11 +919,11 @@ struct _VariantCall { } struct ConstantData { - Map<StringName, int> value; + HashMap<StringName, int> value; #ifdef DEBUG_ENABLED List<StringName> value_ordered; #endif - Map<StringName, Variant> variant_value; + HashMap<StringName, Variant> variant_value; #ifdef DEBUG_ENABLED List<StringName> variant_value_ordered; #endif @@ -1281,14 +1281,14 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0); _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; - Map<StringName, int>::Element *E = cd.value.find(p_value); + HashMap<StringName, int>::Iterator E = cd.value.find(p_value); if (!E) { - Map<StringName, Variant>::Element *F = cd.variant_value.find(p_value); + HashMap<StringName, Variant>::Iterator F = cd.variant_value.find(p_value); if (F) { if (r_valid) { *r_valid = true; } - return F->get(); + return F->value; } else { return -1; } @@ -1297,7 +1297,7 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va *r_valid = true; } - return E->get(); + return E->value; } #ifdef DEBUG_METHODS_ENABLED @@ -1873,6 +1873,9 @@ static void _register_variant_builtin_methods() { bind_method(PackedByteArray, sort, sarray(), varray()); bind_method(PackedByteArray, bsearch, sarray("value", "before"), varray(true)); bind_method(PackedByteArray, duplicate, sarray(), varray()); + bind_method(PackedByteArray, find, sarray("value", "from"), varray(0)); + bind_method(PackedByteArray, rfind, sarray("value", "from"), varray(-1)); + bind_method(PackedByteArray, count, sarray("value"), varray()); bind_function(PackedByteArray, get_string_from_ascii, _VariantCall::func_PackedByteArray_get_string_from_ascii, sarray(), varray()); bind_function(PackedByteArray, get_string_from_utf8, _VariantCall::func_PackedByteArray_get_string_from_utf8, sarray(), varray()); @@ -1935,6 +1938,9 @@ static void _register_variant_builtin_methods() { bind_method(PackedInt32Array, sort, sarray(), varray()); bind_method(PackedInt32Array, bsearch, sarray("value", "before"), varray(true)); bind_method(PackedInt32Array, duplicate, sarray(), varray()); + bind_method(PackedInt32Array, find, sarray("value", "from"), varray(0)); + bind_method(PackedInt32Array, rfind, sarray("value", "from"), varray(-1)); + bind_method(PackedInt32Array, count, sarray("value"), varray()); /* Int64 Array */ @@ -1955,6 +1961,9 @@ static void _register_variant_builtin_methods() { bind_method(PackedInt64Array, sort, sarray(), varray()); bind_method(PackedInt64Array, bsearch, sarray("value", "before"), varray(true)); bind_method(PackedInt64Array, duplicate, sarray(), varray()); + bind_method(PackedInt64Array, find, sarray("value", "from"), varray(0)); + bind_method(PackedInt64Array, rfind, sarray("value", "from"), varray(-1)); + bind_method(PackedInt64Array, count, sarray("value"), varray()); /* Float32 Array */ @@ -1975,6 +1984,9 @@ static void _register_variant_builtin_methods() { bind_method(PackedFloat32Array, sort, sarray(), varray()); bind_method(PackedFloat32Array, bsearch, sarray("value", "before"), varray(true)); bind_method(PackedFloat32Array, duplicate, sarray(), varray()); + bind_method(PackedFloat32Array, find, sarray("value", "from"), varray(0)); + bind_method(PackedFloat32Array, rfind, sarray("value", "from"), varray(-1)); + bind_method(PackedFloat32Array, count, sarray("value"), varray()); /* Float64 Array */ @@ -1995,6 +2007,9 @@ static void _register_variant_builtin_methods() { bind_method(PackedFloat64Array, sort, sarray(), varray()); bind_method(PackedFloat64Array, bsearch, sarray("value", "before"), varray(true)); bind_method(PackedFloat64Array, duplicate, sarray(), varray()); + bind_method(PackedFloat64Array, find, sarray("value", "from"), varray(0)); + bind_method(PackedFloat64Array, rfind, sarray("value", "from"), varray(-1)); + bind_method(PackedFloat64Array, count, sarray("value"), varray()); /* String Array */ @@ -2015,6 +2030,9 @@ static void _register_variant_builtin_methods() { bind_method(PackedStringArray, sort, sarray(), varray()); bind_method(PackedStringArray, bsearch, sarray("value", "before"), varray(true)); bind_method(PackedStringArray, duplicate, sarray(), varray()); + bind_method(PackedStringArray, find, sarray("value", "from"), varray(0)); + bind_method(PackedStringArray, rfind, sarray("value", "from"), varray(-1)); + bind_method(PackedStringArray, count, sarray("value"), varray()); /* Vector2 Array */ @@ -2035,6 +2053,9 @@ static void _register_variant_builtin_methods() { bind_method(PackedVector2Array, sort, sarray(), varray()); bind_method(PackedVector2Array, bsearch, sarray("value", "before"), varray(true)); bind_method(PackedVector2Array, duplicate, sarray(), varray()); + bind_method(PackedVector2Array, find, sarray("value", "from"), varray(0)); + bind_method(PackedVector2Array, rfind, sarray("value", "from"), varray(-1)); + bind_method(PackedVector2Array, count, sarray("value"), varray()); /* Vector3 Array */ @@ -2055,6 +2076,9 @@ static void _register_variant_builtin_methods() { bind_method(PackedVector3Array, sort, sarray(), varray()); bind_method(PackedVector3Array, bsearch, sarray("value", "before"), varray(true)); bind_method(PackedVector3Array, duplicate, sarray(), varray()); + bind_method(PackedVector3Array, find, sarray("value", "from"), varray(0)); + bind_method(PackedVector3Array, rfind, sarray("value", "from"), varray(-1)); + bind_method(PackedVector3Array, count, sarray("value"), varray()); /* Color Array */ @@ -2075,6 +2099,9 @@ static void _register_variant_builtin_methods() { bind_method(PackedColorArray, sort, sarray(), varray()); bind_method(PackedColorArray, bsearch, sarray("value", "before"), varray(true)); bind_method(PackedColorArray, duplicate, sarray(), varray()); + bind_method(PackedColorArray, find, sarray("value", "from"), varray(0)); + bind_method(PackedColorArray, rfind, sarray("value", "from"), varray(-1)); + bind_method(PackedColorArray, count, sarray("value"), varray()); /* Register constants */ diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h index ce2e9af04f..638c0136f3 100644 --- a/core/variant/variant_construct.h +++ b/core/variant/variant_construct.h @@ -344,7 +344,7 @@ public: return; } - VariantTypeChanger<Array>::change(&r_ret); + r_ret = Array(); Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret); const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]); @@ -356,7 +356,7 @@ public: } static inline void validated_construct(Variant *r_ret, const Variant **p_args) { - VariantTypeChanger<Array>::change(r_ret); + *r_ret = Array(); Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(r_ret); const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]); diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index 35e0319aa3..adace2b534 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -361,6 +361,11 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorStringModT<PackedVector3Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_VECTOR3_ARRAY); register_op<OperatorEvaluatorStringModT<PackedColorArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_COLOR_ARRAY); + register_op<OperatorEvaluatorPow<int64_t, int64_t, int64_t>>(Variant::OP_POWER, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorPow<double, int64_t, double>>(Variant::OP_POWER, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorPow<double, double, double>>(Variant::OP_POWER, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorPow<double, double, int64_t>>(Variant::OP_POWER, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorNeg<int64_t, int64_t>>(Variant::OP_NEGATE, Variant::INT, Variant::NIL); register_op<OperatorEvaluatorNeg<double, double>>(Variant::OP_NEGATE, Variant::FLOAT, Variant::NIL); register_op<OperatorEvaluatorNeg<Vector2, Vector2>>(Variant::OP_NEGATE, Variant::VECTOR2, Variant::NIL); @@ -929,6 +934,7 @@ static const char *_op_names[Variant::OP_MAX] = { "unary-", "unary+", "%", + "**", "<<", ">>", "&", diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h index f72a92d31a..3e9bae1078 100644 --- a/core/variant/variant_op.h +++ b/core/variant/variant_op.h @@ -92,6 +92,24 @@ public: }; template <class R, class A, class B> +class OperatorEvaluatorPow { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = R(Math::pow((double)a, (double)b)); + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr<R>::get_ptr(r_ret) = R(Math::pow((double)*VariantGetInternalPtr<A>::get_ptr(left), (double)*VariantGetInternalPtr<B>::get_ptr(right))); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(R(Math::pow((double)PtrToArg<A>::convert(left), (double)PtrToArg<B>::convert(right))), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> class OperatorEvaluatorXForm { public: static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h index 70ca8d8cb5..56b484c8bc 100644 --- a/core/variant/variant_parser.h +++ b/core/variant/variant_parser.h @@ -113,7 +113,7 @@ public: struct Tag { String name; - Map<String, Variant> fields; + HashMap<String, Variant> fields; }; private: diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index 6023e4d129..6514922d01 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -766,11 +766,20 @@ struct VariantIndexedSetGet_String { PtrToArg<Variant>::encode(*ptr, member); \ } \ static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \ + if (VariantGetInternalPtr<m_base_type>::get_ptr(base)->is_read_only()) { \ + *valid = false; \ + *oob = true; \ + return; \ + } \ (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \ *oob = false; \ *valid = true; \ } \ static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \ + if (VariantGetInternalPtr<m_base_type>::get_ptr(base)->is_read_only()) { \ + *oob = true; \ + return; \ + } \ (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \ *oob = false; \ } \ @@ -946,6 +955,10 @@ struct VariantKeyedSetGetDictionary { PtrToArg<Variant>::encode(*ptr, value); } static void set(Variant *base, const Variant *key, const Variant *value, bool *r_valid) { + if (VariantGetInternalPtr<Dictionary>::get_ptr(base)->is_read_only()) { + *r_valid = false; + return; + } (*VariantGetInternalPtr<Dictionary>::get_ptr(base))[*key] = *value; *r_valid = true; } diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index a40b851efc..5f81c80887 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -2799,40 +2799,43 @@ <constant name="OP_MODULE" value="12" enum="Variant.Operator"> Remainder/modulo operator ([code]%[/code]). </constant> - <constant name="OP_SHIFT_LEFT" value="13" enum="Variant.Operator"> + <constant name="OP_POWER" value="13" enum="Variant.Operator"> + Power operator ([code]**[/code]). + </constant> + <constant name="OP_SHIFT_LEFT" value="14" enum="Variant.Operator"> Left shift operator ([code]<<[/code]). </constant> - <constant name="OP_SHIFT_RIGHT" value="14" enum="Variant.Operator"> + <constant name="OP_SHIFT_RIGHT" value="15" enum="Variant.Operator"> Right shift operator ([code]>>[/code]). </constant> - <constant name="OP_BIT_AND" value="15" enum="Variant.Operator"> + <constant name="OP_BIT_AND" value="16" enum="Variant.Operator"> Bitwise AND operator ([code]&[/code]). </constant> - <constant name="OP_BIT_OR" value="16" enum="Variant.Operator"> + <constant name="OP_BIT_OR" value="17" enum="Variant.Operator"> Bitwise OR operator ([code]|[/code]). </constant> - <constant name="OP_BIT_XOR" value="17" enum="Variant.Operator"> + <constant name="OP_BIT_XOR" value="18" enum="Variant.Operator"> Bitwise XOR operator ([code]^[/code]). </constant> - <constant name="OP_BIT_NEGATE" value="18" enum="Variant.Operator"> + <constant name="OP_BIT_NEGATE" value="19" enum="Variant.Operator"> Bitwise NOT operator ([code]~[/code]). </constant> - <constant name="OP_AND" value="19" enum="Variant.Operator"> + <constant name="OP_AND" value="20" enum="Variant.Operator"> Logical AND operator ([code]and[/code] or [code]&&[/code]). </constant> - <constant name="OP_OR" value="20" enum="Variant.Operator"> + <constant name="OP_OR" value="21" enum="Variant.Operator"> Logical OR operator ([code]or[/code] or [code]||[/code]). </constant> - <constant name="OP_XOR" value="21" enum="Variant.Operator"> + <constant name="OP_XOR" value="22" enum="Variant.Operator"> Logical XOR operator (not implemented in GDScript). </constant> - <constant name="OP_NOT" value="22" enum="Variant.Operator"> + <constant name="OP_NOT" value="23" enum="Variant.Operator"> Logical NOT operator ([code]not[/code] or [code]![/code]). </constant> - <constant name="OP_IN" value="23" enum="Variant.Operator"> + <constant name="OP_IN" value="24" enum="Variant.Operator"> Logical IN operator ([code]in[/code]). </constant> - <constant name="OP_MAX" value="24" enum="Variant.Operator"> + <constant name="OP_MAX" value="25" enum="Variant.Operator"> Represents the size of the [enum Variant.Operator] enum. </constant> </constants> diff --git a/doc/classes/AnimatedSprite2D.xml b/doc/classes/AnimatedSprite2D.xml index e89134d1ac..638d142791 100644 --- a/doc/classes/AnimatedSprite2D.xml +++ b/doc/classes/AnimatedSprite2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AnimatedSprite2D" inherits="Node2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Sprite node that can use multiple textures for animation. + Sprite node that contains multiple textures as frames to play for animation. </brief_description> <description> - Animations are created using a [SpriteFrames] resource, which can be configured in the editor via the SpriteFrames panel. + [AnimatedSprite2D] is similar to the [Sprite2D] node, except it carries multiple textures as animation frames. Animations are created using a [SpriteFrames] resource, which allows you to import image files (or a folder containing said files) to provide the animation frames for the sprite. The [SpriteFrames] resource can be configured in the editor via the SpriteFrames bottom panel. [b]Note:[/b] You can associate a set of normal or specular maps by creating additional [SpriteFrames] resources with a [code]_normal[/code] or [code]_specular[/code] suffix. For example, having 3 [SpriteFrames] resources [code]run[/code], [code]run_normal[/code], and [code]run_specular[/code] will make it so the [code]run[/code] animation uses normal and specular maps. </description> <tutorials> @@ -29,7 +29,7 @@ </methods> <members> <member name="animation" type="StringName" setter="set_animation" getter="get_animation" default="&"default""> - The current animation from the [code]frames[/code] resource. If this value changes, the [code]frame[/code] counter is reset. + The current animation from the [member frames] resource. If this value changes, the [code]frame[/code] counter is reset. </member> <member name="centered" type="bool" setter="set_centered" getter="is_centered" default="true"> If [code]true[/code], texture will be centered. @@ -44,7 +44,7 @@ The displayed animation frame's index. </member> <member name="frames" type="SpriteFrames" setter="set_sprite_frames" getter="get_sprite_frames"> - The [SpriteFrames] resource containing the animation(s). + The [SpriteFrames] resource containing the animation(s). Allows you the option to load, edit, clear, make unique and save the states of the [SpriteFrames] resource. </member> <member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2(0, 0)"> The texture's drawing offset. diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml index 625cf3c47c..653607610d 100644 --- a/doc/classes/AnimationPlayer.xml +++ b/doc/classes/AnimationPlayer.xml @@ -179,6 +179,7 @@ <argument index="1" name="update" type="bool" default="false" /> <description> Seeks the animation to the [code]seconds[/code] point in time (in seconds). If [code]update[/code] is [code]true[/code], the animation updates too, otherwise it updates at process time. Events between the current frame and [code]seconds[/code] are skipped. + [b]Note:[/b] Seeking to the end of the animation doesn't emit [signal animation_finished]. If you want to skip animation and emit the signal, use [method advance]. </description> </method> <method name="set_blend_time"> diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml index 5008cd826e..56e5ce1522 100644 --- a/doc/classes/Camera3D.xml +++ b/doc/classes/Camera3D.xml @@ -88,14 +88,14 @@ <return type="Vector3" /> <argument index="0" name="screen_point" type="Vector2" /> <description> - Returns a normal vector in world space, that is the result of projecting a point on the [Viewport] rectangle by the camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking. + Returns a normal vector in world space, that is the result of projecting a point on the [Viewport] rectangle by the inverse camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking. </description> </method> <method name="project_ray_origin" qualifiers="const"> <return type="Vector3" /> <argument index="0" name="screen_point" type="Vector2" /> <description> - Returns a 3D position in world space, that is the result of projecting a point on the [Viewport] rectangle by the camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking. + Returns a 3D position in world space, that is the result of projecting a point on the [Viewport] rectangle by the inverse camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking. </description> </method> <method name="set_cull_mask_value"> diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml index a9d8a85226..f290fc9801 100644 --- a/doc/classes/CollisionPolygon2D.xml +++ b/doc/classes/CollisionPolygon2D.xml @@ -18,6 +18,7 @@ </member> <member name="one_way_collision" type="bool" setter="set_one_way_collision" getter="is_one_way_collision_enabled" default="false"> If [code]true[/code], only edges that face up, relative to [CollisionPolygon2D]'s rotation, will collide with other objects. + [b]Note:[/b] This property has no effect if this [CollisionPolygon2D] is a child of an [Area2D] node. </member> <member name="one_way_collision_margin" type="float" setter="set_one_way_collision_margin" getter="get_one_way_collision_margin" default="1.0"> The margin used for one-way collision (in pixels). Higher values will make the shape thicker, and work better for colliders that enter the polygon at a high velocity. diff --git a/doc/classes/CollisionShape2D.xml b/doc/classes/CollisionShape2D.xml index f3a4cbc2d6..246e0e8663 100644 --- a/doc/classes/CollisionShape2D.xml +++ b/doc/classes/CollisionShape2D.xml @@ -18,6 +18,7 @@ </member> <member name="one_way_collision" type="bool" setter="set_one_way_collision" getter="is_one_way_collision_enabled" default="false"> Sets whether this collision shape should only detect collision on one side (top or bottom). + [b]Note:[/b] This property has no effect if this [CollisionShape2D] is a child of an [Area2D] node. </member> <member name="one_way_collision_margin" type="float" setter="set_one_way_collision_margin" getter="get_one_way_collision_margin" default="1.0"> The margin used for one-way collision (in pixels). Higher values will make the shape thicker, and work better for colliders that enter the shape at a high velocity. diff --git a/doc/classes/DirectionalLight3D.xml b/doc/classes/DirectionalLight3D.xml index 754518239c..9c943b8c8b 100644 --- a/doc/classes/DirectionalLight3D.xml +++ b/doc/classes/DirectionalLight3D.xml @@ -34,7 +34,6 @@ <member name="directional_shadow_split_3" type="float" setter="set_param" getter="get_param" default="0.5"> The distance from shadow split 2 to split 3. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]. </member> - <member name="shadow_bias" type="float" setter="set_param" getter="get_param" overrides="Light3D" default="0.1" /> <member name="sky_mode" type="int" setter="set_sky_mode" getter="get_sky_mode" enum="DirectionalLight3D.SkyMode" default="0"> Set whether this [DirectionalLight3D] is visible in the sky, in the scene, or both in the sky and in the scene. See [enum SkyMode] for options. </member> diff --git a/doc/classes/EditorFileSystem.xml b/doc/classes/EditorFileSystem.xml index 300cb4bfd6..60ac499d25 100644 --- a/doc/classes/EditorFileSystem.xml +++ b/doc/classes/EditorFileSystem.xml @@ -42,6 +42,15 @@ Returns [code]true[/code] of the filesystem is being scanned. </description> </method> + <method name="reimport_files"> + <return type="void" /> + <argument index="0" name="files" type="PackedStringArray" /> + <description> + Reimports a set of files. Call this if these files or their [code].import[/code] files were directly edited by script or an external program. + If the file type changed or the file was newly created, use [method update_file] or [method scan]. + [b]Note:[/b] This function blocks until the import is finished. However, the main loop iteration, including timers and [method Node._process], will occur during the import process due to progress bar updates. Avoid calls to [method reimport_files] or [method scan] while an import is in progress. + </description> + </method> <method name="scan"> <return type="void" /> <description> @@ -58,7 +67,8 @@ <return type="void" /> <argument index="0" name="path" type="String" /> <description> - Update a file information. Call this if an external program (not Godot) modified the file. + Add a file in an existing directory, or schedule file information to be updated on editor restart. Can be used to update text files saved by an external program. + This will not import the file. To reimport, call [method reimport_files] or [method scan] methods. </description> </method> <method name="update_script_classes"> diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml index 96dea1edce..2ada211dab 100644 --- a/doc/classes/EditorSpinSlider.xml +++ b/doc/classes/EditorSpinSlider.xml @@ -11,6 +11,9 @@ <members> <member name="flat" type="bool" setter="set_flat" getter="is_flat" default="false"> </member> + <member name="hide_slider" type="bool" setter="set_hide_slider" getter="is_hiding_slider" default="false"> + If [code]true[/code], the slider is hidden. + </member> <member name="label" type="String" setter="set_label" getter="get_label" default=""""> </member> <member name="read_only" type="bool" setter="set_read_only" getter="is_read_only" default="false"> diff --git a/doc/classes/GPUParticlesAttractor3D.xml b/doc/classes/GPUParticlesAttractor3D.xml index 5577b47c89..e69255cc31 100644 --- a/doc/classes/GPUParticlesAttractor3D.xml +++ b/doc/classes/GPUParticlesAttractor3D.xml @@ -1,19 +1,31 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GPUParticlesAttractor3D" inherits="VisualInstance3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Abstract class for 3D particle attractors affecting [GPUParticles3D] nodes. </brief_description> <description> + Particle attractors can be used to attract particles towards the attractor's origin, or to push them away from the attractor's origin. + Particle attractors work in real-time and can be moved, rotated and scaled during gameplay. Unlike collision shapes, non-uniform scaling of attractors is also supported. + Attractors can be temporarily disabled by hiding them, or by setting their [member strength] to [code]0.0[/code]. + [b]Note:[/b] Particle attractors only affect [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> </tutorials> <members> <member name="attenuation" type="float" setter="set_attenuation" getter="get_attenuation" default="1.0"> + The particle attractor's attenuation. Higher values result in more gradual pushing of particles as they come closer to the attractor's origin. Zero or negative values will cause particles to be pushed very fast as soon as the touch the attractor's edges. </member> <member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="4294967295"> + The particle rendering layers ([member VisualInstance3D.layers]) that will be affected by the attractor. By default, all particles are affected by an attractor. + After configuring particle nodes accordingly, specific layers can be unchecked to prevent certain particles from being affected by attractors. For example, this can be used if you're using an attractor as part of a spell effect but don't want the attractor to affect unrelated weather particles at the same position. + Particle attraction can also be disabled on a per-process material basis by setting [member ParticlesMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. </member> <member name="directionality" type="float" setter="set_directionality" getter="get_directionality" default="0.0"> + Adjusts how directional the attractor is. At [code]0.0[/code], the attractor is not directional at all: it will attract particles towards its center. At [code]1.0[/code], the attractor is fully directional: particles will always be pushed towards local -Z (or +Z if [member strength] is negative). + [b]Note:[/b] If [member directionality] is greater than [code]0.0[/code], the direction in which particles are pushed can be changed by rotating the [GPUParticlesAttractor3D] node. </member> <member name="strength" type="float" setter="set_strength" getter="get_strength" default="1.0"> + If [member strength] is negative, particles will be pushed in the reverse direction. Particles will be pushed [i]away[/i] from the attractor's origin if [member directionality] is [code]0.0[/code], or towards local +Z if [member directionality] is greater than [code]0.0[/code]. </member> </members> </class> diff --git a/doc/classes/GPUParticlesAttractorBox3D.xml b/doc/classes/GPUParticlesAttractorBox3D.xml index 3fa8276579..6595428cc2 100644 --- a/doc/classes/GPUParticlesAttractorBox3D.xml +++ b/doc/classes/GPUParticlesAttractorBox3D.xml @@ -1,13 +1,17 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GPUParticlesAttractorBox3D" inherits="GPUParticlesAttractor3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Box-shaped 3D particle attractor affecting [GPUParticles3D] nodes. </brief_description> <description> + Box-shaped 3D particle attractor affecting [GPUParticles3D] nodes. + [b]Note:[/b] Particle attractors only affect [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> </tutorials> <members> <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> + The attractor box's extents in 3D units. </member> </members> </class> diff --git a/doc/classes/GPUParticlesAttractorSphere3D.xml b/doc/classes/GPUParticlesAttractorSphere3D.xml index 2b68637b38..4077937ef3 100644 --- a/doc/classes/GPUParticlesAttractorSphere3D.xml +++ b/doc/classes/GPUParticlesAttractorSphere3D.xml @@ -1,13 +1,18 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GPUParticlesAttractorSphere3D" inherits="GPUParticlesAttractor3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Ellipse-shaped 3D particle attractor affecting [GPUParticles3D] nodes. </brief_description> <description> + Ellipse-shaped 3D particle attractor affecting [GPUParticles3D] nodes. + [b]Note:[/b] Particle attractors only affect [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> </tutorials> <members> <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0"> + The attractor sphere's radius in 3D units. + [b]Note:[/b] Stretched ellipses can be obtained by using non-uniform scaling on the [GPUParticlesAttractorSphere3D] node. </member> </members> </class> diff --git a/doc/classes/GPUParticlesAttractorVectorField3D.xml b/doc/classes/GPUParticlesAttractorVectorField3D.xml index cbf817f407..aeadfaf4ab 100644 --- a/doc/classes/GPUParticlesAttractorVectorField3D.xml +++ b/doc/classes/GPUParticlesAttractorVectorField3D.xml @@ -1,15 +1,22 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GPUParticlesAttractorVectorField3D" inherits="GPUParticlesAttractor3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Box-shaped 3D particle attractor with strength varying within the box, affecting [GPUParticles3D] nodes. </brief_description> <description> + Box-shaped 3D particle attractor with strength varying within the box, affecting [GPUParticles3D] nodes. + Unlike [GPUParticlesAttractorBox3D], [GPUParticlesAttractorVectorField3D] uses a [member texture] to affect attraction strength within the box. This can be used to create complex attraction scenarios where particles travel in different directions depending on their location. This can be useful for weather effects such as sandstorms. + [b]Note:[/b] Particle attractors only affect [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> </tutorials> <members> <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> + The extents of the vector field box in 3D units. </member> <member name="texture" type="Texture3D" setter="set_texture" getter="get_texture"> + The 3D texture to be used. Values are linearly interpolated between the texture's pixels. + [b]Note:[/b] To get better performance, the 3D texture's resolution should reflect the [member extents] of the attractor. Since particle attraction is usually low-frequency data, the texture can be kept at a low resolution such as 64×64×64. </member> </members> </class> diff --git a/doc/classes/GPUParticlesCollision3D.xml b/doc/classes/GPUParticlesCollision3D.xml index 45bc9b402b..435f9781f0 100644 --- a/doc/classes/GPUParticlesCollision3D.xml +++ b/doc/classes/GPUParticlesCollision3D.xml @@ -1,13 +1,23 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GPUParticlesCollision3D" inherits="VisualInstance3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Abstract class for 3D particle collision shapes affecting [GPUParticles3D] nodes. </brief_description> <description> + Particle collision shapes can be used to make particles stop or bounce against them. + Particle collision shapes in real-time and can be moved, rotated and scaled during gameplay. Unlike attractors, non-uniform scaling of collision shapes is [i]not[/i] supported. + Particle collision shapes can be temporarily disabled by hiding them. + [b]Note:[/b] [member ParticlesMaterial.collision_enabled] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. + [b]Note:[/b] Particles pushed by a collider that is being moved will not be interpolated, which can result in visible stuttering. This can be alleviated by setting [member GPUParticles3D.fixed_fps] to [code]0[/code] or a value that matches or exceeds the target framerate. </description> <tutorials> </tutorials> <members> <member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="4294967295"> + The particle rendering layers ([member VisualInstance3D.layers]) that will be affected by the collision shape. By default, all particles that have [member ParticlesMaterial.collision_enabled] set to [code]true[/code] will be affected by a collision shape. + After configuring particle nodes accordingly, specific layers can be unchecked to prevent certain particles from being affected by attractors. For example, this can be used if you're using an attractor as part of a spell effect but don't want the attractor to affect unrelated weather particles at the same position. + Particle attraction can also be disabled on a per-process material basis by setting [member ParticlesMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. </member> </members> </class> diff --git a/doc/classes/GPUParticlesCollisionBox3D.xml b/doc/classes/GPUParticlesCollisionBox3D.xml index 091b4ca730..60d66ca682 100644 --- a/doc/classes/GPUParticlesCollisionBox3D.xml +++ b/doc/classes/GPUParticlesCollisionBox3D.xml @@ -1,13 +1,18 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GPUParticlesCollisionBox3D" inherits="GPUParticlesCollision3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Box-shaped 3D particle collision shape affecting [GPUParticles3D] nodes. </brief_description> <description> + Box-shaped 3D particle collision shape affecting [GPUParticles3D] nodes. + [b]Note:[/b] [member ParticlesMaterial.collision_enabled] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> </tutorials> <members> <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> + The collision box's extents in 3D units. </member> </members> </class> diff --git a/doc/classes/GPUParticlesCollisionHeightField3D.xml b/doc/classes/GPUParticlesCollisionHeightField3D.xml index e7e14375d9..3fcad43efb 100644 --- a/doc/classes/GPUParticlesCollisionHeightField3D.xml +++ b/doc/classes/GPUParticlesCollisionHeightField3D.xml @@ -1,41 +1,59 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GPUParticlesCollisionHeightField3D" inherits="GPUParticlesCollision3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Real-time heightmap-shaped 3D particle attractor affecting [GPUParticles3D] nodes. </brief_description> <description> + Real-time heightmap-shaped 3D particle attractor affecting [GPUParticles3D] nodes. + Heightmap shapes allow for efficiently representing collisions for convex and concave objects with a single "floor" (such as terrain). This is less flexible than [GPUParticlesCollisionSDF3D], but it doesn't require a baking step. + [GPUParticlesCollisionHeightField3D] can also be regenerated in real-time when it is moved, when the camera moves, or even continuously. This makes [GPUParticlesCollisionHeightField3D] a good choice for weather effects such as rain and snow and games with highly dynamic geometry. However, since heightmaps cannot represent overhangs, [GPUParticlesCollisionHeightField3D] is not suited for indoor particle collision. + [b]Note:[/b] [member ParticlesMaterial.collision_enabled] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> </tutorials> <members> <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> + The collision heightmap's extents in 3D units. To improve heightmap quality, [member extents] should be set as small as possible while covering the parts of the scene you need. </member> - <member name="follow_camera_enabled" type="bool" setter="set_follow_camera_mode" getter="is_follow_camera_mode_enabled" default="false"> - </member> - <member name="follow_camera_push_ratio" type="float" setter="set_follow_camera_push_ratio" getter="get_follow_camera_push_ratio" default="0.1"> + <member name="follow_camera_enabled" type="bool" setter="set_follow_camera_enabled" getter="is_follow_camera_enabled" default="false"> + If [code]true[/code], the [GPUParticlesCollisionHeightField3D] will follow the current camera in global space. The [GPUParticlesCollisionHeightField3D] does not need to be a child of the [Camera3D] node for this to work. + Following the camera has a performance cost, as it will force the heightmap to update whenever the camera moves. Consider lowering [member resolution] to improve performance if [member follow_camera_enabled] is [code]true[/code]. </member> <member name="resolution" type="int" setter="set_resolution" getter="get_resolution" enum="GPUParticlesCollisionHeightField3D.Resolution" default="2"> + Higher resolutions can represent small details more accurately in large scenes, at the cost of lower performance. If [member update_mode] is [constant UPDATE_MODE_ALWAYS], consider using the lowest resolution possible. </member> <member name="update_mode" type="int" setter="set_update_mode" getter="get_update_mode" enum="GPUParticlesCollisionHeightField3D.UpdateMode" default="0"> + The update policy to use for the generated heightmap. </member> </members> <constants> <constant name="RESOLUTION_256" value="0" enum="Resolution"> + Generate a 256×256 heightmap. Intended for small-scale scenes, or larger scenes with no distant particles. </constant> <constant name="RESOLUTION_512" value="1" enum="Resolution"> + Generate a 512×512 heightmap. Intended for medium-scale scenes, or larger scenes with no distant particles. </constant> <constant name="RESOLUTION_1024" value="2" enum="Resolution"> + Generate a 1024×1024 heightmap. Intended for large scenes with distant particles. </constant> <constant name="RESOLUTION_2048" value="3" enum="Resolution"> + Generate a 2048×2048 heightmap. Intended for very large scenes with distant particles. </constant> <constant name="RESOLUTION_4096" value="4" enum="Resolution"> + Generate a 4096×4096 heightmap. Intended for huge scenes with distant particles. </constant> <constant name="RESOLUTION_8192" value="5" enum="Resolution"> + Generate a 8192×8192 heightmap. Intended for gigantic scenes with distant particles. </constant> <constant name="RESOLUTION_MAX" value="6" enum="Resolution"> + Represents the size of the [enum Resolution] enum. </constant> <constant name="UPDATE_MODE_WHEN_MOVED" value="0" enum="UpdateMode"> + Only update the heightmap when the [GPUParticlesCollisionHeightField3D] node is moved, or when the camera moves if [member follow_camera_enabled] is [code]true[/code]. An update can be forced by slightly moving the [GPUParticlesCollisionHeightField3D] in any direction. </constant> <constant name="UPDATE_MODE_ALWAYS" value="1" enum="UpdateMode"> + Update the heightmap every frame. This has a significant performance cost. This update should only be used when geometry that particles can collide with changes significantly during gameplay. </constant> </constants> </class> diff --git a/doc/classes/GPUParticlesCollisionSDF3D.xml b/doc/classes/GPUParticlesCollisionSDF3D.xml index 6f59a18eb5..c9af07288e 100644 --- a/doc/classes/GPUParticlesCollisionSDF3D.xml +++ b/doc/classes/GPUParticlesCollisionSDF3D.xml @@ -1,35 +1,53 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GPUParticlesCollisionSDF3D" inherits="GPUParticlesCollision3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Baked signed distance field 3D particle attractor affecting [GPUParticles3D] nodes. </brief_description> <description> + Baked signed distance field 3D particle attractor affecting [GPUParticles3D] nodes. + Signed distance fields (SDF) allow for efficiently representing approximate collision shapes for convex and concave objects of any shape. This is more flexible than [GPUParticlesCollisionHeightField3D], but it requires a baking step. + [b]Baking:[/b] The signed distance field texture can be baked by selecting the [GPUParticlesCollisionSDF3D] node in the editor, then clicking [b]Bake SDF[/b] at the top of the 3D viewport. Any [i]visible[/i] [MeshInstance3D]s touching the [member extents] will be taken into account for baking, regardless of their [member GeometryInstance3D.gi_mode]. + [b]Note:[/b] Baking a [GPUParticlesCollisionSDF3D]'s [member texture] is only possible within the editor, as there is no bake method exposed for use in exported projects. However, it's still possible to load pre-baked [Texture3D]s into its [member texture] property in an exported project. + [b]Note:[/b] [member ParticlesMaterial.collision_enabled] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> </tutorials> <members> <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> + The collision SDF's extents in 3D units. To improve SDF quality, the [member extents] should be set as small as possible while covering the parts of the scene you need. </member> <member name="resolution" type="int" setter="set_resolution" getter="get_resolution" enum="GPUParticlesCollisionSDF3D.Resolution" default="2"> + The bake resolution to use for the signed distance field [member texture]. The texture must be baked again for changes to the [member resolution] property to be effective. Higher resolutions have a greater performance cost and take more time to bake. Higher resolutions also result in larger baked textures, leading to increased VRAM and storage space requirements. To improve performance and reduce bake times, use the lowest resolution possible for the object you're representing the collision of. </member> <member name="texture" type="Texture3D" setter="set_texture" getter="get_texture"> + The 3D texture representing the signed distance field. </member> <member name="thickness" type="float" setter="set_thickness" getter="get_thickness" default="1.0"> + The collision shape's thickness. Unlike other particle colliders, [GPUParticlesCollisionSDF3D] is actually hollow on the inside. [member thickness] can be increased to prevent particles from tunneling through the collision shape at high speeds, or when the [GPUParticlesCollisionSDF3D] is moved. </member> </members> <constants> <constant name="RESOLUTION_16" value="0" enum="Resolution"> + Bake a 16×16×16 signed distance field. This is the fastest option, but also the least precise. </constant> <constant name="RESOLUTION_32" value="1" enum="Resolution"> + Bake a 32×32×32 signed distance field. </constant> <constant name="RESOLUTION_64" value="2" enum="Resolution"> + Bake a 64×64×64 signed distance field. </constant> <constant name="RESOLUTION_128" value="3" enum="Resolution"> + Bake a 128×128×128 signed distance field. </constant> <constant name="RESOLUTION_256" value="4" enum="Resolution"> + Bake a 256×256×256 signed distance field. </constant> <constant name="RESOLUTION_512" value="5" enum="Resolution"> + Bake a 512×512×512 signed distance field. This is the slowest option, but also the most precise. </constant> <constant name="RESOLUTION_MAX" value="6" enum="Resolution"> + Represents the size of the [enum Resolution] enum. </constant> </constants> </class> diff --git a/doc/classes/GPUParticlesCollisionSphere3D.xml b/doc/classes/GPUParticlesCollisionSphere3D.xml index b78e114d09..6651a732da 100644 --- a/doc/classes/GPUParticlesCollisionSphere3D.xml +++ b/doc/classes/GPUParticlesCollisionSphere3D.xml @@ -1,13 +1,18 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GPUParticlesCollisionSphere3D" inherits="GPUParticlesCollision3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Sphere-shaped 3D particle collision shape affecting [GPUParticles3D] nodes. </brief_description> <description> + Sphere-shaped 3D particle collision shape affecting [GPUParticles3D] nodes. + [b]Note:[/b] [member ParticlesMaterial.collision_enabled] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> </tutorials> <members> <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0"> + The collision sphere's radius in 3D units. </member> </members> </class> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index e699a40ea0..02352ca808 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -296,8 +296,9 @@ </description> </signal> <signal name="delete_nodes_request"> + <argument index="0" name="nodes" type="StringName[]" /> <description> - Emitted when a GraphNode is attempted to be removed from the GraphEdit. + Emitted when a GraphNode is attempted to be removed from the GraphEdit. Provides a list of node names to be removed (all selected nodes, excluding nodes without closing button). </description> </signal> <signal name="disconnection_request"> diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index 173da63a15..5f0dca0402 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -119,6 +119,13 @@ Returns the right (output) type of the slot [code]idx[/code]. </description> </method> + <method name="is_slot_draw_stylebox" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="idx" type="int" /> + <description> + Returns true if the background [StyleBox] of the slot [code]idx[/code] is drawn. + </description> + </method> <method name="is_slot_enabled_left" qualifiers="const"> <return type="bool" /> <argument index="0" name="idx" type="int" /> @@ -152,6 +159,7 @@ <argument index="6" name="color_right" type="Color" /> <argument index="7" name="custom_left" type="Texture2D" default="null" /> <argument index="8" name="custom_right" type="Texture2D" default="null" /> + <argument index="9" name="enable" type="bool" default="true" /> <description> Sets properties of the slot with ID [code]idx[/code]. If [code]enable_left[/code]/[code]right[/code], a port will appear and the slot will be able to be connected from this side. @@ -178,6 +186,14 @@ Sets the [Color] of the right (output) side of the slot [code]idx[/code] to [code]color_right[/code]. </description> </method> + <method name="set_slot_draw_stylebox"> + <return type="void" /> + <argument index="0" name="idx" type="int" /> + <argument index="1" name="draw_stylebox" type="bool" /> + <description> + Toggles the background [StyleBox] of the slot [code]idx[/code]. + </description> + </method> <method name="set_slot_enabled_left"> <return type="void" /> <argument index="0" name="idx" type="int" /> @@ -301,6 +317,8 @@ <theme_item name="title_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Color of the title text. </theme_item> + <theme_item name="close_h_offset" data_type="constant" type="int" default="22"> + </theme_item> <theme_item name="close_offset" data_type="constant" type="int" default="22"> The vertical offset of the close button. </theme_item> @@ -343,5 +361,8 @@ <theme_item name="selected_frame" data_type="style" type="StyleBox"> The background used when the [GraphNode] is selected. </theme_item> + <theme_item name="slot" data_type="style" type="StyleBox"> + The [StyleBox] used for each slot of the [GraphNode]. + </theme_item> </theme_items> </class> diff --git a/doc/classes/Label3D.xml b/doc/classes/Label3D.xml index 1bd52ab2dc..c4d02e6101 100644 --- a/doc/classes/Label3D.xml +++ b/doc/classes/Label3D.xml @@ -78,7 +78,7 @@ Font size of the [Label3D]'s text. </member> <member name="horizontal_alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="1"> - Controls the text's horizontal alignment. Supports left, center, right. Set it to one of the [enum HorizontalAlignment] constants. + Controls the text's horizontal alignment. Supports left, center, right, and fill, or justify. Set it to one of the [enum HorizontalAlignment] constants. </member> <member name="language" type="String" setter="set_language" getter="get_language" default=""""> Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index b7822f1bb0..4d8fd63257 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -80,7 +80,7 @@ <member name="light_specular" type="float" setter="set_param" getter="get_param" default="0.5"> The intensity of the specular blob in objects affected by the light. At [code]0[/code], the light becomes a pure diffuse light. When not baking emission, this can be used to avoid unrealistic reflections when placing lights above an emissive surface. </member> - <member name="shadow_bias" type="float" setter="set_param" getter="get_param" default="0.2"> + <member name="shadow_bias" type="float" setter="set_param" getter="get_param" default="0.1"> Used to adjust shadow appearance. Too small a value results in self-shadowing ("shadow acne"), while too large a value causes shadows to separate from casters ("peter-panning"). Adjust as needed. </member> <member name="shadow_blur" type="float" setter="set_param" getter="get_param" default="1.0"> diff --git a/doc/classes/NavigationMeshGenerator.xml b/doc/classes/NavigationMeshGenerator.xml index 1cffb1a627..36588ce2f5 100644 --- a/doc/classes/NavigationMeshGenerator.xml +++ b/doc/classes/NavigationMeshGenerator.xml @@ -1,8 +1,13 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="NavigationMeshGenerator" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Helper class for creating and clearing navigation meshes. </brief_description> <description> + This class is responsible for creating and clearing 3D navigation meshes used as [NavigationMesh] resources inside [NavigationRegion3D]. The [NavigationMeshGenerator] has very limited to no use for 2D as the navigation mesh baking process expects 3D node types and 3D source geometry to parse. + The entire navigation mesh baking is best done in a separate thread as the voxelization, collision tests and mesh optimization steps involved are very performance and time hungry operations. + Navigation mesh baking happens in multiple steps and the result depends on 3D source geometry and properties of the [NavigationMesh] resource. In the first step, starting from a root node and depending on [NavigationMesh] properties all valid 3D source geometry nodes are collected from the [SceneTree]. Second, all collected nodes are parsed for their relevant 3D geometry data and a combined 3D mesh is build. Due to the many different types of parsable objects, from normal [MeshInstance3D]s to [CSGShape3D]s or various [CollisionObject3D]s, some operations to collect geometry data can trigger [RenderingServer] and [PhysicsServer3D] synchronizations. Server synchronization can have a negative effect on baking time or framerate as it often involves [Mutex] locking for thread security. Many parsable objects and the continuous synchronization with other threaded Servers can increase the baking time significantly. On the other hand only a few but very large and complex objects will take some time to prepare for the Servers which can noticeably stall the next frame render. As a general rule the total amount of parsable objects and their individual size and complexity should be balanced to avoid framerate issues or very long baking times. The combined mesh is then passed to the Recast Navigation Object to test the source geometry for walkable terrain suitable to [NavigationMesh] agent properties by creating a voxel world around the meshes bounding area. + The finalized navigation mesh is then returned and stored inside the [NavigationMesh] for use as a resource inside [NavigationRegion3D] nodes. </description> <tutorials> </tutorials> @@ -12,12 +17,14 @@ <argument index="0" name="nav_mesh" type="NavigationMesh" /> <argument index="1" name="root_node" type="Node" /> <description> + Bakes navigation data to the provided [code]nav_mesh[/code] by parsing child nodes under the provided [code]root_node[/code] or a specific group of nodes for potential source geometry. The parse behavior can be controlled with the [member NavigationMesh.geometry/parsed_geometry_type] and [member NavigationMesh.geometry/source_geometry_mode] properties on the [NavigationMesh] resource. </description> </method> <method name="clear"> <return type="void" /> <argument index="0" name="nav_mesh" type="NavigationMesh" /> <description> + Removes all polygons and vertices from the provided [code]nav_mesh[/code] resource. </description> </method> </methods> diff --git a/doc/classes/NavigationObstacle2D.xml b/doc/classes/NavigationObstacle2D.xml index 2540c56258..f3690ce8a7 100644 --- a/doc/classes/NavigationObstacle2D.xml +++ b/doc/classes/NavigationObstacle2D.xml @@ -8,6 +8,14 @@ </description> <tutorials> </tutorials> + <methods> + <method name="get_rid" qualifiers="const"> + <return type="RID" /> + <description> + Returns the [RID] of this obstacle on the [NavigationServer2D]. + </description> + </method> + </methods> <members> <member name="estimate_radius" type="bool" setter="set_estimate_radius" getter="is_radius_estimated" default="true"> Enables radius estimation algorithm which uses parent's collision shapes to determine the obstacle radius. diff --git a/doc/classes/NavigationObstacle3D.xml b/doc/classes/NavigationObstacle3D.xml index f9489db5f1..e6ea70b91a 100644 --- a/doc/classes/NavigationObstacle3D.xml +++ b/doc/classes/NavigationObstacle3D.xml @@ -8,6 +8,14 @@ </description> <tutorials> </tutorials> + <methods> + <method name="get_rid" qualifiers="const"> + <return type="RID" /> + <description> + Returns the [RID] of this obstacle on the [NavigationServer3D]. + </description> + </method> + </methods> <members> <member name="estimate_radius" type="bool" setter="set_estimate_radius" getter="is_radius_estimated" default="true"> Enables radius estimation algorithm which uses parent's collision shapes to determine the obstacle radius. diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml index 60f1020286..42f0e0c5d9 100644 --- a/doc/classes/NavigationRegion3D.xml +++ b/doc/classes/NavigationRegion3D.xml @@ -14,7 +14,7 @@ <return type="void" /> <argument index="0" name="on_thread" type="bool" default="true" /> <description> - Bakes the [NavigationMesh]. If [code]on_thread[/code] is set to [code]true[/code] (default), the baking is done on a separate thread. Baking on separate thread is useful because navigation baking is not a cheap operation. When it is completed, it automatically sets the new [NavigationMesh]. Please note that baking on separate thread may be very slow if geometry is parsed from meshes as async access to each mesh involves heavy synchronization. + Bakes the [NavigationMesh]. If [code]on_thread[/code] is set to [code]true[/code] (default), the baking is done on a separate thread. Baking on separate thread is useful because navigation baking is not a cheap operation. When it is completed, it automatically sets the new [NavigationMesh]. Please note that baking on separate thread may be very slow if geometry is parsed from meshes as async access to each mesh involves heavy synchronization. Also, please note that baking on a separate thread is automatically disabled on operating systems that cannot use threads (such as HTML5 with threads disabled). </description> </method> <method name="get_region_rid" qualifiers="const"> diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index e007dfd9b5..928834101f 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -21,6 +21,13 @@ Creates the agent. </description> </method> + <method name="agent_get_map" qualifiers="const"> + <return type="RID" /> + <argument index="0" name="agent" type="RID" /> + <description> + Returns the navigation map [RID] the requested [code]agent[/code] is currently assigned to. + </description> + </method> <method name="agent_is_map_changed" qualifiers="const"> <return type="bool" /> <argument index="0" name="agent" type="RID" /> @@ -123,6 +130,13 @@ Create a new map. </description> </method> + <method name="map_get_agents" qualifiers="const"> + <return type="Array" /> + <argument index="0" name="map" type="RID" /> + <description> + Returns all navigation agents [RID]s that are currently assigned to the requested navigation [code]map[/code]. + </description> + </method> <method name="map_get_cell_size" qualifiers="const"> <return type="float" /> <argument index="0" name="map" type="RID" /> @@ -164,6 +178,13 @@ Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path. </description> </method> + <method name="map_get_regions" qualifiers="const"> + <return type="Array" /> + <argument index="0" name="map" type="RID" /> + <description> + Returns all navigation regions [RID]s that are currently assigned to the requested navigation [code]map[/code]. + </description> + </method> <method name="map_is_active" qualifiers="const"> <return type="bool" /> <argument index="0" name="nap" type="RID" /> @@ -231,6 +252,13 @@ Returns the region's layers. </description> </method> + <method name="region_get_map" qualifiers="const"> + <return type="RID" /> + <argument index="0" name="region" type="RID" /> + <description> + Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to. + </description> + </method> <method name="region_set_layers" qualifiers="const"> <return type="void" /> <argument index="0" name="region" type="RID" /> diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index c987bc9042..8c83fe5485 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -21,6 +21,13 @@ Creates the agent. </description> </method> + <method name="agent_get_map" qualifiers="const"> + <return type="RID" /> + <argument index="0" name="agent" type="RID" /> + <description> + Returns the navigation map [RID] the requested [code]agent[/code] is currently assigned to. + </description> + </method> <method name="agent_is_map_changed" qualifiers="const"> <return type="bool" /> <argument index="0" name="agent" type="RID" /> @@ -123,6 +130,13 @@ Create a new map. </description> </method> + <method name="map_get_agents" qualifiers="const"> + <return type="Array" /> + <argument index="0" name="map" type="RID" /> + <description> + Returns all navigation agents [RID]s that are currently assigned to the requested navigation [code]map[/code]. + </description> + </method> <method name="map_get_cell_size" qualifiers="const"> <return type="float" /> <argument index="0" name="map" type="RID" /> @@ -182,6 +196,13 @@ Returns the navigation path to reach the destination from the origin. [code]layers[/code] is a bitmask of all region layers that are allowed to be in the path. </description> </method> + <method name="map_get_regions" qualifiers="const"> + <return type="Array" /> + <argument index="0" name="map" type="RID" /> + <description> + Returns all navigation regions [RID]s that are currently assigned to the requested navigation [code]map[/code]. + </description> + </method> <method name="map_get_up" qualifiers="const"> <return type="Vector3" /> <argument index="0" name="map" type="RID" /> @@ -281,6 +302,13 @@ Returns the region's layers. </description> </method> + <method name="region_get_map" qualifiers="const"> + <return type="RID" /> + <argument index="0" name="region" type="RID" /> + <description> + Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to. + </description> + </method> <method name="region_set_layers" qualifiers="const"> <return type="void" /> <argument index="0" name="region" type="RID" /> diff --git a/doc/classes/OmniLight3D.xml b/doc/classes/OmniLight3D.xml index f83d31a9b5..ce63dbdbc1 100644 --- a/doc/classes/OmniLight3D.xml +++ b/doc/classes/OmniLight3D.xml @@ -19,6 +19,7 @@ <member name="omni_shadow_mode" type="int" setter="set_shadow_mode" getter="get_shadow_mode" enum="OmniLight3D.ShadowMode" default="1"> See [enum ShadowMode]. </member> + <member name="shadow_bias" type="float" setter="set_param" getter="get_param" overrides="Light3D" default="0.2" /> </members> <constants> <constant name="SHADOW_DUAL_PARABOLOID" value="0" enum="ShadowMode"> diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml index 61dc1eef00..5d0861bcf3 100644 --- a/doc/classes/PackedByteArray.xml +++ b/doc/classes/PackedByteArray.xml @@ -61,6 +61,13 @@ Returns a new [PackedByteArray] with the data compressed. Set the compression mode using one of [enum File.CompressionMode]'s constants. </description> </method> + <method name="count" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="int" /> + <description> + Returns the number of times an element is in the array. + </description> + </method> <method name="decode_double" qualifiers="const"> <return type="float" /> <argument index="0" name="byte_offset" type="int" /> @@ -257,6 +264,14 @@ Assigns the given value to all elements in the array. This can typically be used together with [method resize] to create an array with a given size and initialized elements. </description> </method> + <method name="find" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="int" /> + <argument index="1" name="from" type="int" default="0" /> + <description> + Searches the array for a value and returns its index or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + </description> + </method> <method name="get_string_from_ascii" qualifiers="const"> <return type="String" /> <description> @@ -352,6 +367,14 @@ Reverses the order of the elements in the array. </description> </method> + <method name="rfind" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="int" /> + <argument index="1" name="from" type="int" default="-1" /> + <description> + Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array. + </description> + </method> <method name="set"> <return type="void" /> <argument index="0" name="index" type="int" /> diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml index f880771c77..12a553af49 100644 --- a/doc/classes/PackedColorArray.xml +++ b/doc/classes/PackedColorArray.xml @@ -54,6 +54,13 @@ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior. </description> </method> + <method name="count" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="Color" /> + <description> + Returns the number of times an element is in the array. + </description> + </method> <method name="duplicate"> <return type="PackedColorArray" /> <description> @@ -67,6 +74,14 @@ Assigns the given value to all elements in the array. This can typically be used together with [method resize] to create an array with a given size and initialized elements. </description> </method> + <method name="find" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="Color" /> + <argument index="1" name="from" type="int" default="0" /> + <description> + Searches the array for a value and returns its index or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + </description> + </method> <method name="has" qualifiers="const"> <return type="bool" /> <argument index="0" name="value" type="Color" /> @@ -115,6 +130,14 @@ Reverses the order of the elements in the array. </description> </method> + <method name="rfind" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="Color" /> + <argument index="1" name="from" type="int" default="-1" /> + <description> + Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array. + </description> + </method> <method name="set"> <return type="void" /> <argument index="0" name="index" type="int" /> diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml index e2b877ad5f..0a114e6c06 100644 --- a/doc/classes/PackedFloat32Array.xml +++ b/doc/classes/PackedFloat32Array.xml @@ -55,6 +55,13 @@ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior. </description> </method> + <method name="count" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="float" /> + <description> + Returns the number of times an element is in the array. + </description> + </method> <method name="duplicate"> <return type="PackedFloat32Array" /> <description> @@ -68,6 +75,14 @@ Assigns the given value to all elements in the array. This can typically be used together with [method resize] to create an array with a given size and initialized elements. </description> </method> + <method name="find" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="float" /> + <argument index="1" name="from" type="int" default="0" /> + <description> + Searches the array for a value and returns its index or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + </description> + </method> <method name="has" qualifiers="const"> <return type="bool" /> <argument index="0" name="value" type="float" /> @@ -116,6 +131,14 @@ Reverses the order of the elements in the array. </description> </method> + <method name="rfind" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="float" /> + <argument index="1" name="from" type="int" default="-1" /> + <description> + Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array. + </description> + </method> <method name="set"> <return type="void" /> <argument index="0" name="index" type="int" /> diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml index be7a52b7f4..0327559f5b 100644 --- a/doc/classes/PackedFloat64Array.xml +++ b/doc/classes/PackedFloat64Array.xml @@ -55,6 +55,13 @@ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior. </description> </method> + <method name="count" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="float" /> + <description> + Returns the number of times an element is in the array. + </description> + </method> <method name="duplicate"> <return type="PackedFloat64Array" /> <description> @@ -68,6 +75,14 @@ Assigns the given value to all elements in the array. This can typically be used together with [method resize] to create an array with a given size and initialized elements. </description> </method> + <method name="find" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="float" /> + <argument index="1" name="from" type="int" default="0" /> + <description> + Searches the array for a value and returns its index or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + </description> + </method> <method name="has" qualifiers="const"> <return type="bool" /> <argument index="0" name="value" type="float" /> @@ -116,6 +131,14 @@ Reverses the order of the elements in the array. </description> </method> + <method name="rfind" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="float" /> + <argument index="1" name="from" type="int" default="-1" /> + <description> + Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array. + </description> + </method> <method name="set"> <return type="void" /> <argument index="0" name="index" type="int" /> diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml index 108273d859..f8b606d266 100644 --- a/doc/classes/PackedInt32Array.xml +++ b/doc/classes/PackedInt32Array.xml @@ -55,6 +55,13 @@ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior. </description> </method> + <method name="count" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="int" /> + <description> + Returns the number of times an element is in the array. + </description> + </method> <method name="duplicate"> <return type="PackedInt32Array" /> <description> @@ -68,6 +75,14 @@ Assigns the given value to all elements in the array. This can typically be used together with [method resize] to create an array with a given size and initialized elements. </description> </method> + <method name="find" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="int" /> + <argument index="1" name="from" type="int" default="0" /> + <description> + Searches the array for a value and returns its index or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + </description> + </method> <method name="has" qualifiers="const"> <return type="bool" /> <argument index="0" name="value" type="int" /> @@ -116,6 +131,14 @@ Reverses the order of the elements in the array. </description> </method> + <method name="rfind" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="int" /> + <argument index="1" name="from" type="int" default="-1" /> + <description> + Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array. + </description> + </method> <method name="set"> <return type="void" /> <argument index="0" name="index" type="int" /> diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml index c34f2fc75e..ea3e304d35 100644 --- a/doc/classes/PackedInt64Array.xml +++ b/doc/classes/PackedInt64Array.xml @@ -55,6 +55,13 @@ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior. </description> </method> + <method name="count" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="int" /> + <description> + Returns the number of times an element is in the array. + </description> + </method> <method name="duplicate"> <return type="PackedInt64Array" /> <description> @@ -68,6 +75,14 @@ Assigns the given value to all elements in the array. This can typically be used together with [method resize] to create an array with a given size and initialized elements. </description> </method> + <method name="find" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="int" /> + <argument index="1" name="from" type="int" default="0" /> + <description> + Searches the array for a value and returns its index or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + </description> + </method> <method name="has" qualifiers="const"> <return type="bool" /> <argument index="0" name="value" type="int" /> @@ -116,6 +131,14 @@ Reverses the order of the elements in the array. </description> </method> + <method name="rfind" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="int" /> + <argument index="1" name="from" type="int" default="-1" /> + <description> + Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array. + </description> + </method> <method name="set"> <return type="void" /> <argument index="0" name="index" type="int" /> diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml index 536f5f02eb..a4653344f0 100644 --- a/doc/classes/PackedStringArray.xml +++ b/doc/classes/PackedStringArray.xml @@ -5,6 +5,12 @@ </brief_description> <description> An array specifically designed to hold [String]s. Packs data tightly, so it saves memory for large array sizes. + If you want to join the strings in the array, use [method String.join]. + [codeblock] + var string_array = PackedStringArray(["hello", "world"]) + var string = " ".join(string_array) + print(string) # "hello world" + [/codeblock] </description> <tutorials> <link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link> @@ -55,6 +61,13 @@ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior. </description> </method> + <method name="count" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="String" /> + <description> + Returns the number of times an element is in the array. + </description> + </method> <method name="duplicate"> <return type="PackedStringArray" /> <description> @@ -68,6 +81,14 @@ Assigns the given value to all elements in the array. This can typically be used together with [method resize] to create an array with a given size and initialized elements. </description> </method> + <method name="find" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="String" /> + <argument index="1" name="from" type="int" default="0" /> + <description> + Searches the array for a value and returns its index or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + </description> + </method> <method name="has" qualifiers="const"> <return type="bool" /> <argument index="0" name="value" type="String" /> @@ -116,6 +137,14 @@ Reverses the order of the elements in the array. </description> </method> + <method name="rfind" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="String" /> + <argument index="1" name="from" type="int" default="-1" /> + <description> + Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array. + </description> + </method> <method name="set"> <return type="void" /> <argument index="0" name="index" type="int" /> diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml index 29423d1cde..8f3e5d173d 100644 --- a/doc/classes/PackedVector2Array.xml +++ b/doc/classes/PackedVector2Array.xml @@ -55,6 +55,13 @@ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior. </description> </method> + <method name="count" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="Vector2" /> + <description> + Returns the number of times an element is in the array. + </description> + </method> <method name="duplicate"> <return type="PackedVector2Array" /> <description> @@ -68,6 +75,14 @@ Assigns the given value to all elements in the array. This can typically be used together with [method resize] to create an array with a given size and initialized elements. </description> </method> + <method name="find" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="Vector2" /> + <argument index="1" name="from" type="int" default="0" /> + <description> + Searches the array for a value and returns its index or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + </description> + </method> <method name="has" qualifiers="const"> <return type="bool" /> <argument index="0" name="value" type="Vector2" /> @@ -116,6 +131,14 @@ Reverses the order of the elements in the array. </description> </method> + <method name="rfind" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="Vector2" /> + <argument index="1" name="from" type="int" default="-1" /> + <description> + Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array. + </description> + </method> <method name="set"> <return type="void" /> <argument index="0" name="index" type="int" /> diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml index 6d460cecab..1207293c32 100644 --- a/doc/classes/PackedVector3Array.xml +++ b/doc/classes/PackedVector3Array.xml @@ -54,6 +54,13 @@ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior. </description> </method> + <method name="count" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="Vector3" /> + <description> + Returns the number of times an element is in the array. + </description> + </method> <method name="duplicate"> <return type="PackedVector3Array" /> <description> @@ -67,6 +74,14 @@ Assigns the given value to all elements in the array. This can typically be used together with [method resize] to create an array with a given size and initialized elements. </description> </method> + <method name="find" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="Vector3" /> + <argument index="1" name="from" type="int" default="0" /> + <description> + Searches the array for a value and returns its index or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + </description> + </method> <method name="has" qualifiers="const"> <return type="bool" /> <argument index="0" name="value" type="Vector3" /> @@ -115,6 +130,14 @@ Reverses the order of the elements in the array. </description> </method> + <method name="rfind" qualifiers="const"> + <return type="int" /> + <argument index="0" name="value" type="Vector3" /> + <argument index="1" name="from" type="int" default="-1" /> + <description> + Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array. + </description> + </method> <method name="set"> <return type="void" /> <argument index="0" name="index" type="int" /> diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml index bcaf38fd06..01da9cb9a2 100644 --- a/doc/classes/Performance.xml +++ b/doc/classes/Performance.xml @@ -6,8 +6,8 @@ <description> This class provides access to a number of different monitors related to performance, such as memory usage, draw calls, and FPS. These are the same as the values displayed in the [b]Monitor[/b] tab in the editor's [b]Debugger[/b] panel. By using the [method get_monitor] method of this class, you can access this data from your code. You can add custom monitors using the [method add_custom_monitor] method. Custom monitors are available in [b]Monitor[/b] tab in the editor's [b]Debugger[/b] panel together with built-in monitors. - [b]Note:[/b] A few of these monitors are only available in debug mode and will always return 0 when used in a release build. - [b]Note:[/b] Many of these monitors are not updated in real-time, so there may be a short delay between changes. + [b]Note:[/b] Some of the built-in monitors are only available in debug mode and will always return [code]0[/code] when used in a project exported in release mode. + [b]Note:[/b] Some of the built-in monitors are not updated in real-time for performance reasons, so there may be a delay of up to 1 second between changes. [b]Note:[/b] Custom monitors do not support negative values. Negative values are clamped to 0. </description> <tutorials> @@ -19,7 +19,7 @@ <argument index="1" name="callable" type="Callable" /> <argument index="2" name="arguments" type="Array" default="[]" /> <description> - Adds a custom monitor with name same as id. You can specify the category of monitor using '/' in id. If there are more than one '/' then default category is used. Default category is "Custom". + Adds a custom monitor with the name [code]id[/code]. You can specify the category of the monitor using slash delimiters in [code]id[/code] (for example: [code]"Game/NumberOfNPCs"[/code]). If there is more than one slash delimiter, then the default category is used. The default category is [code]"Custom"[/code]. Prints an error if given [code]id[/code] is already present. [codeblocks] [gdscript] func _ready(): @@ -29,11 +29,11 @@ Performance.add_custom_monitor("MyCategory/MyMonitor", monitor_value) # Adds monitor with name "MyName" to category "Custom". - # Note: "MyCategory/MyMonitor" and "MyMonitor" have same name but different ids so the code is valid. + # Note: "MyCategory/MyMonitor" and "MyMonitor" have same name but different IDs, so the code is valid. Performance.add_custom_monitor("MyMonitor", monitor_value) # Adds monitor with name "MyName" to category "Custom". - # Note: "MyMonitor" and "Custom/MyMonitor" have same name and same category but different ids so the code is valid. + # Note: "MyMonitor" and "Custom/MyMonitor" have same name and same category but different IDs, so the code is valid. Performance.add_custom_monitor("Custom/MyMonitor", monitor_value) # Adds monitor with name "MyCategoryOne/MyCategoryTwo/MyMonitor" to category "Custom". @@ -67,30 +67,28 @@ } [/csharp] [/codeblocks] - The debugger calls the callable to get the value of custom monitor. The callable must return a number. + The debugger calls the callable to get the value of custom monitor. The callable must return a zero or positive integer or floating-point number. Callables are called with arguments supplied in argument array. - [b]Note:[/b] It prints an error if given id is already present. </description> </method> <method name="get_custom_monitor"> <return type="Variant" /> <argument index="0" name="id" type="StringName" /> <description> - Returns the value of custom monitor with given id. The callable is called to get the value of custom monitor. - [b]Note:[/b] It prints an error if the given id is absent. + Returns the value of custom monitor with given [code]id[/code]. The callable is called to get the value of custom monitor. See also [method has_custom_monitor]. Prints an error if the given [code]id[/code] is absent. </description> </method> <method name="get_custom_monitor_names"> <return type="Array" /> <description> - Returns the names of active custom monitors in an array. + Returns the names of active custom monitors in an [Array]. </description> </method> <method name="get_monitor" qualifiers="const"> <return type="float" /> <argument index="0" name="monitor" type="int" enum="Performance.Monitor" /> <description> - Returns the value of one of the available monitors. You should provide one of the [enum Monitor] constants as the argument, like this: + Returns the value of one of the available built-in monitors. You should provide one of the [enum Monitor] constants as the argument, like this: [codeblocks] [gdscript] print(Performance.get_monitor(Performance.TIME_FPS)) # Prints the FPS to the console. @@ -99,95 +97,99 @@ GD.Print(Performance.GetMonitor(Performance.Monitor.TimeFps)); // Prints the FPS to the console. [/csharp] [/codeblocks] + See [method get_custom_monitor] to query custom performance monitors' values. </description> </method> <method name="get_monitor_modification_time"> <return type="int" /> <description> - Returns the last tick in which custom monitor was added/removed. + Returns the last tick in which custom monitor was added/removed (in microseconds since the engine started). This is set to [method Time.get_ticks_usec] when the monitor is updated. </description> </method> <method name="has_custom_monitor"> <return type="bool" /> <argument index="0" name="id" type="StringName" /> <description> - Returns true if custom monitor with the given id is present otherwise returns false. + Returns [code]true[/code] if custom monitor with the given [code]id[/code] is present, [code]false[/code] otherwise. </description> </method> <method name="remove_custom_monitor"> <return type="void" /> <argument index="0" name="id" type="StringName" /> <description> - Removes the custom monitor with given id. - [b]Note:[/b] It prints an error if the given id is already absent. + Removes the custom monitor with given [code]id[/code]. Prints an error if the given [code]id[/code] is already absent. </description> </method> </methods> <constants> <constant name="TIME_FPS" value="0" enum="Monitor"> - Number of frames per second. + The number of frames rendered in the last second. This metric is only updated once per second, even if queried more often. [i]Higher is better.[/i] </constant> <constant name="TIME_PROCESS" value="1" enum="Monitor"> - Time it took to complete one frame, in seconds. + Time it took to complete one frame, in seconds. [i]Lower is better.[/i] </constant> <constant name="TIME_PHYSICS_PROCESS" value="2" enum="Monitor"> - Time it took to complete one physics frame, in seconds. + Time it took to complete one physics frame, in seconds. [i]Lower is better.[/i] </constant> <constant name="MEMORY_STATIC" value="3" enum="Monitor"> - Static memory currently used, in bytes. Not available in release builds. + Static memory currently used, in bytes. Not available in release builds. [i]Lower is better.[/i] </constant> <constant name="MEMORY_STATIC_MAX" value="4" enum="Monitor"> - Available static memory. Not available in release builds. + Available static memory. Not available in release builds. [i]Lower is better.[/i] </constant> <constant name="MEMORY_MESSAGE_BUFFER_MAX" value="5" enum="Monitor"> - Largest amount of memory the message queue buffer has used, in bytes. The message queue is used for deferred functions calls and notifications. + Largest amount of memory the message queue buffer has used, in bytes. The message queue is used for deferred functions calls and notifications. [i]Lower is better.[/i] </constant> <constant name="OBJECT_COUNT" value="6" enum="Monitor"> - Number of objects currently instantiated (including nodes). + Number of objects currently instantiated (including nodes). [i]Lower is better.[/i] </constant> <constant name="OBJECT_RESOURCE_COUNT" value="7" enum="Monitor"> - Number of resources currently used. + Number of resources currently used. [i]Lower is better.[/i] </constant> <constant name="OBJECT_NODE_COUNT" value="8" enum="Monitor"> - Number of nodes currently instantiated in the scene tree. This also includes the root node. + Number of nodes currently instantiated in the scene tree. This also includes the root node. [i]Lower is better.[/i] </constant> <constant name="OBJECT_ORPHAN_NODE_COUNT" value="9" enum="Monitor"> - Number of orphan nodes, i.e. nodes which are not parented to a node of the scene tree. + Number of orphan nodes, i.e. nodes which are not parented to a node of the scene tree. [i]Lower is better.[/i] </constant> <constant name="RENDER_TOTAL_OBJECTS_IN_FRAME" value="10" enum="Monitor"> + The total number of objects in the last rendered frame. This metric doesn't include culled objects (either via hiding nodes, frustum culling or occlusion culling). [i]Lower is better.[/i] </constant> <constant name="RENDER_TOTAL_PRIMITIVES_IN_FRAME" value="11" enum="Monitor"> + The total number of vertices or indices rendered in the last rendered frame. This metric doesn't include primitives from culled objects (either via hiding nodes, frustum culling or occlusion culling). Due to the depth prepass and shadow passes, the number of primitives is always higher than the actual number of vertices in the scene (typically double or triple the original vertex count). [i]Lower is better.[/i] </constant> <constant name="RENDER_TOTAL_DRAW_CALLS_IN_FRAME" value="12" enum="Monitor"> + The total number of draw calls performed in the last rendered frame. This metric doesn't include culled objects (either via hiding nodes, frustum culling or occlusion culling), since they do not result in draw calls. [i]Lower is better.[/i] </constant> <constant name="RENDER_VIDEO_MEM_USED" value="13" enum="Monitor"> - The amount of video memory used, i.e. texture and vertex memory combined. + The amount of video memory used (texture and vertex memory combined, in bytes). Since this metric also includes miscellaneous allocations, this value is always greater than the sum of [constant RENDER_TEXTURE_MEM_USED] and [constant RENDER_BUFFER_MEM_USED]. [i]Lower is better.[/i] </constant> <constant name="RENDER_TEXTURE_MEM_USED" value="14" enum="Monitor"> - The amount of texture memory used. + The amount of texture memory used (in bytes). [i]Lower is better.[/i] </constant> <constant name="RENDER_BUFFER_MEM_USED" value="15" enum="Monitor"> + The amount of render buffer memory used (in bytes). [i]Lower is better.[/i] </constant> <constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="16" enum="Monitor"> - Number of active [RigidDynamicBody2D] nodes in the game. + Number of active [RigidDynamicBody2D] nodes in the game. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_2D_COLLISION_PAIRS" value="17" enum="Monitor"> - Number of collision pairs in the 2D physics engine. + Number of collision pairs in the 2D physics engine. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_2D_ISLAND_COUNT" value="18" enum="Monitor"> - Number of islands in the 2D physics engine. + Number of islands in the 2D physics engine. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="19" enum="Monitor"> - Number of active [RigidDynamicBody3D] and [VehicleBody3D] nodes in the game. + Number of active [RigidDynamicBody3D] and [VehicleBody3D] nodes in the game. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_3D_COLLISION_PAIRS" value="20" enum="Monitor"> - Number of collision pairs in the 3D physics engine. + Number of collision pairs in the 3D physics engine. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_3D_ISLAND_COUNT" value="21" enum="Monitor"> - Number of islands in the 3D physics engine. + Number of islands in the 3D physics engine. [i]Lower is better.[/i] </constant> <constant name="AUDIO_OUTPUT_LATENCY" value="22" enum="Monitor"> - Output latency of the [AudioServer]. + Output latency of the [AudioServer]. [i]Lower is better.[/i] </constant> <constant name="MONITOR_MAX" value="23" enum="Monitor"> Represents the size of the [enum Monitor] enum. diff --git a/doc/classes/ProgressBar.xml b/doc/classes/ProgressBar.xml index 1e9ab7c375..8a781c51fb 100644 --- a/doc/classes/ProgressBar.xml +++ b/doc/classes/ProgressBar.xml @@ -9,10 +9,27 @@ <tutorials> </tutorials> <members> + <member name="fill_mode" type="int" setter="set_fill_mode" getter="get_fill_mode" default="0"> + The fill direction. See [enum FillMode] for possible values. + </member> <member name="percent_visible" type="bool" setter="set_percent_visible" getter="is_percent_visible" default="true"> If [code]true[/code], the fill percentage is displayed on the bar. </member> </members> + <constants> + <constant name="FILL_BEGIN_TO_END" value="0" enum="FillMode"> + The progress bar fills from begin to end horizontally, according to the language direction. If [method Control.is_layout_rtl] returns [code]false[/code], it fills from left to right, and if it returns [code]true[/code], it fills from right to left. + </constant> + <constant name="FILL_END_TO_BEGIN" value="1" enum="FillMode"> + The progress bar fills from end to begin horizontally, according to the language direction. If [method Control.is_layout_rtl] returns [code]false[/code], it fills from right to left, and if it returns [code]true[/code], it fills from left to right. + </constant> + <constant name="FILL_TOP_TO_BOTTOM" value="2" enum="FillMode"> + The progress fills from top to bottom. + </constant> + <constant name="FILL_BOTTOM_TO_TOP" value="3" enum="FillMode"> + The progress fills from bottom to top. + </constant> + </constants> <theme_items> <theme_item name="font_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> The color of the text. diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 7c6d6d1c10..7f3c0ea6d9 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1557,18 +1557,6 @@ [b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_ticks_per_second] instead. [b]Note:[/b] Only 8 physics ticks may be simulated per rendered frame at most. If more than 8 physics ticks have to be simulated per rendered frame to keep up with rendering, the game will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended not to increase [member physics/common/physics_ticks_per_second] above 240. Otherwise, the game will slow down when the rendering framerate goes below 30 FPS. </member> - <member name="rendering/2d/opengl/batching_send_null" type="int" setter="" getter="" default="0"> - </member> - <member name="rendering/2d/opengl/batching_stream" type="int" setter="" getter="" default="0"> - </member> - <member name="rendering/2d/opengl/legacy_orphan_buffers" type="int" setter="" getter="" default="0"> - </member> - <member name="rendering/2d/opengl/legacy_stream" type="int" setter="" getter="" default="0"> - </member> - <member name="rendering/2d/options/ninepatch_mode" type="int" setter="" getter="" default="1"> - </member> - <member name="rendering/2d/options/use_software_skinning" type="bool" setter="" getter="" default="true"> - </member> <member name="rendering/2d/sdf/oversize" type="int" setter="" getter="" default="1"> </member> <member name="rendering/2d/sdf/scale" type="int" setter="" getter="" default="1"> @@ -1594,32 +1582,6 @@ </member> <member name="rendering/anti_aliasing/screen_space_roughness_limiter/limit" type="float" setter="" getter="" default="0.18"> </member> - <member name="rendering/batching/debug/diagnose_frame" type="bool" setter="" getter="" default="false"> - </member> - <member name="rendering/batching/debug/flash_batching" type="bool" setter="" getter="" default="false"> - </member> - <member name="rendering/batching/lights/max_join_items" type="int" setter="" getter="" default="32"> - </member> - <member name="rendering/batching/lights/scissor_area_threshold" type="float" setter="" getter="" default="1.0"> - </member> - <member name="rendering/batching/options/single_rect_fallback" type="bool" setter="" getter="" default="false"> - </member> - <member name="rendering/batching/options/use_batching" type="bool" setter="" getter="" default="false"> - </member> - <member name="rendering/batching/options/use_batching_in_editor" type="bool" setter="" getter="" default="false"> - </member> - <member name="rendering/batching/parameters/batch_buffer_size" type="int" setter="" getter="" default="16384"> - </member> - <member name="rendering/batching/parameters/colored_vertex_format_threshold" type="float" setter="" getter="" default="0.25"> - </member> - <member name="rendering/batching/parameters/item_reordering_lookahead" type="int" setter="" getter="" default="4"> - </member> - <member name="rendering/batching/parameters/max_join_item_commands" type="int" setter="" getter="" default="16"> - </member> - <member name="rendering/batching/precision/uv_contract" type="bool" setter="" getter="" default="false"> - </member> - <member name="rendering/batching/precision/uv_contract_amount" type="int" setter="" getter="" default="100"> - </member> <member name="rendering/camera/depth_of_field/depth_of_field_bokeh_quality" type="int" setter="" getter="" default="1"> Sets the quality of the depth of field effect. Higher quality takes more samples, which is slower but looks smoother. </member> @@ -1629,13 +1591,16 @@ <member name="rendering/camera/depth_of_field/depth_of_field_use_jitter" type="bool" setter="" getter="" default="false"> If [code]true[/code], jitters DOF samples to make effect slightly blurrier and hide lines created from low sample rates. This can result in a slightly grainy appearance when used with a low number of samples. </member> + <member name="rendering/driver/depth_prepass/disable_for_vendors" type="String" setter="" getter="" default=""PowerVR,Mali,Adreno,Apple""> + Disables [member rendering/driver/depth_prepass/enable] conditionally for certain venders. By default, disables the depth prepass for mobile devices as mobile devices do not benefit from the depth prepass due to their unique architecture. + </member> <member name="rendering/driver/depth_prepass/enable" type="bool" setter="" getter="" default="true"> If [code]true[/code], performs a previous depth pass before rendering 3D materials. This increases performance significantly in scenes with high overdraw, when complex materials and lighting are used. However, in scenes with few occluded surfaces, the depth prepass may reduce performance. If your game is viewed from a fixed angle that makes it easy to avoid overdraw (such as top-down or side-scrolling perspective), consider disabling the depth prepass to improve performance. This setting can be changed at run-time to optimize performance depending on the scene currently being viewed. - [b]Note:[/b] Only supported when using the Vulkan Clustered backend (not Vulkan Mobile or OpenGL). When using Vulkan Mobile or OpenGL, there is no depth prepass performed. + [b]Note:[/b] Only supported when using the Vulkan Clustered backend or the OpenGL backend. When using Vulkan Mobile there is no depth prepass performed. </member> <member name="rendering/driver/driver_name" type="String" setter="" getter="" default=""vulkan""> The video driver to use. - [b]Note:[/b] OpenGL support is currently incomplete. Only basic 2D rendering is supported, and single-window mode is required for correct operation. + [b]Note:[/b] OpenGL support is currently incomplete. Only basic rendering is supported. [b]Note:[/b] The backend in use can be overridden at runtime via the [code]--rendering-driver[/code] command line argument. [b]FIXME:[/b] No longer valid after DisplayServer split: In such cases, this property is not updated, so use [code]OS.get_current_video_driver[/code] to query it at run-time. @@ -1715,10 +1680,6 @@ <member name="rendering/environment/volumetric_fog/volume_size" type="int" setter="" getter="" default="64"> Base size used to determine size of froxel buffer in the camera X-axis and Y-axis. The final size is scaled by the aspect ratio of the screen, so actual values may differ from what is set. Set a larger size for more detailed fog, set a smaller size for better performance. </member> - <member name="rendering/gles2/compatibility/disable_half_float" type="bool" setter="" getter="" default="false"> - </member> - <member name="rendering/gles2/compatibility/enable_high_float.Android" type="bool" setter="" getter="" default="false"> - </member> <member name="rendering/global_illumination/gi/use_half_resolution" type="bool" setter="" getter="" default="false"> If [code]true[/code], renders [VoxelGI] and SDFGI ([member Environment.sdfgi_enabled]) buffers at halved resolution (e.g. 960×540 when the viewport size is 1920×1080). This improves performance significantly when VoxelGI or SDFGI is enabled, at the cost of artifacts that may be visible on polygon edges. The loss in quality becomes less noticeable as the viewport resolution increases. [LightmapGI] rendering is not affected by this setting. [b]Note:[/b] This property is only read when the project starts. To set half-resolution GI at run-time, call [method RenderingServer.gi_set_use_half_resolution] instead. @@ -1761,6 +1722,15 @@ </member> <member name="rendering/limits/global_shader_variables/buffer_size" type="int" setter="" getter="" default="65536"> </member> + <member name="rendering/limits/opengl/max_lights_per_object" type="int" setter="" getter="" default="8"> + Max number of omnilights and spotlights renderable per object. At the default value of 8, this means that each surface can be affected by up to 8 omnilights and 8 spotlights. This is further limited by hardware support and [member rendering/limits/opengl/max_renderable_lights]. Setting this low will slightly reduce memory usage, may decrease shader compile times, and may result in faster rendering on low-end, mobile, or web devices. + </member> + <member name="rendering/limits/opengl/max_renderable_elements" type="int" setter="" getter="" default="65536"> + Max amount of elements renderable in a frame. If more elements than this are visible per frame, they will not be drawn. Keep in mind elements refer to mesh surfaces and not meshes themselves. Setting this low will slightly reduce memory usage and may decrease shader compile times, particularly on web. For most uses, the default value is suitable, but consider lowering as much as possible on web export. + </member> + <member name="rendering/limits/opengl/max_renderable_lights" type="int" setter="" getter="" default="32"> + Max number of positional lights renderable in a frame. If more lights than this number are used, they will be ignored. Setting this low will slightly reduce memory usage and may decrease shader compile times, particularly on web. For most uses, the default value is suitable, but consider lowering as much as possible on web export. + </member> <member name="rendering/limits/spatial_indexer/threaded_cull_minimum_instances" type="int" setter="" getter="" default="1000"> </member> <member name="rendering/limits/spatial_indexer/update_iterations_per_frame" type="int" setter="" getter="" default="10"> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 970f5125cd..3cd2ab0903 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -18,9 +18,9 @@ <argument index="0" name="group" type="StringName" /> <argument index="1" name="method" type="StringName" /> <description> - Calls [code]method[/code] on each member of the given group. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. This method is equivalent of calling [method call_group_flags] with [constant GROUP_CALL_DEFAULT] flag. + Calls [code]method[/code] on each member of the given group. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. [b]Note:[/b] Due to design limitations, [method call_group] will fail silently if one of the arguments is [code]null[/code]. - [b]Note:[/b] [method call_group] will always call methods with an one-frame delay, in a way similar to [method Object.call_deferred]. To call methods immediately, use [method call_group_flags] with the [constant GROUP_CALL_REALTIME] flag. + [b]Note:[/b] [method call_group] will call methods immediately on all members at once, which can cause stuttering if an expensive method is called on lots of members. To wait for one frame after [method call_group] was called, use [method call_group_flags] with the [constant GROUP_CALL_DEFERRED] flag. </description> </method> <method name="call_group_flags" qualifiers="vararg"> @@ -30,11 +30,12 @@ <argument index="2" name="method" type="StringName" /> <description> Calls [code]method[/code] on each member of the given group, respecting the given [enum GroupCallFlags]. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. - [b]Note:[/b] Due to design limitations, [method call_group_flags] will fail silently if one of the arguments is [code]null[/code]. [codeblock] - # Call the method immediately and in reverse order. - get_tree().call_group_flags(SceneTree.GROUP_CALL_REALTIME | SceneTree.GROUP_CALL_REVERSE, "bases", "destroy") + # Call the method in a deferred manner and in reverse order. + get_tree().call_group_flags(SceneTree.GROUP_CALL_DEFERRED | SceneTree.GROUP_CALL_REVERSE) [/codeblock] + [b]Note:[/b] Due to design limitations, [method call_group_flags] will fail silently if one of the arguments is [code]null[/code]. + [b]Note:[/b] Group call flags are used to control the method calling behavior. By default, methods will be called immediately in a way similar to [method call_group]. However, if the [constant GROUP_CALL_DEFERRED] flag is present in the [code]flags[/code] argument, methods will be called with a one-frame delay in a way similar to [method Object.set_deferred]. </description> </method> <method name="change_scene"> @@ -139,6 +140,7 @@ <argument index="1" name="notification" type="int" /> <description> Sends the given notification to all members of the [code]group[/code]. + [b]Note:[/b] [method notify_group] will immediately notify all members at once, which can cause stuttering if an expensive method is called as a result of sending the notification lots of members. To wait for one frame, use [method notify_group_flags] with the [constant GROUP_CALL_DEFERRED] flag. </description> </method> <method name="notify_group_flags"> @@ -148,6 +150,7 @@ <argument index="2" name="notification" type="int" /> <description> Sends the given notification to all members of the [code]group[/code], respecting the given [enum GroupCallFlags]. + [b]Note:[/b] Group call flags are used to control the notification sending behavior. By default, notifications will be sent immediately in a way similar to [method notify_group]. However, if the [constant GROUP_CALL_DEFERRED] flag is present in the [code]flags[/code] argument, notifications will be sent with a one-frame delay in a way similar to using [code]Object.call_deferred("notification", ...)[/code]. </description> </method> <method name="queue_delete"> @@ -189,6 +192,7 @@ <argument index="2" name="value" type="Variant" /> <description> Sets the given [code]property[/code] to [code]value[/code] on all members of the given group. + [b]Note:[/b] [method set_group] will set the property immediately on all members at once, which can cause stuttering if a property with an expensive setter is set on lots of members. To wait for one frame, use [method set_group_flags] with the [constant GROUP_CALL_DEFERRED] flag. </description> </method> <method name="set_group_flags"> @@ -199,6 +203,7 @@ <argument index="3" name="value" type="Variant" /> <description> Sets the given [code]property[/code] to [code]value[/code] on all members of the given group, respecting the given [enum GroupCallFlags]. + [b]Note:[/b] Group call flags are used to control the property setting behavior. By default, properties will be set immediately in a way similar to [method set_group]. However, if the [constant GROUP_CALL_DEFERRED] flag is present in the [code]flags[/code] argument, properties will be set with a one-frame delay in a way similar to [method Object.call_deferred]. </description> </method> <method name="set_multiplayer"> @@ -297,8 +302,8 @@ <constant name="GROUP_CALL_REVERSE" value="1" enum="GroupCallFlags"> Call a group in reverse scene order. </constant> - <constant name="GROUP_CALL_REALTIME" value="2" enum="GroupCallFlags"> - Call a group immediately (calls are normally made on idle). + <constant name="GROUP_CALL_DEFERRED" value="2" enum="GroupCallFlags"> + Call a group with a one-frame delay (idle frame, not physics). </constant> <constant name="GROUP_CALL_UNIQUE" value="4" enum="GroupCallFlags"> Call a group only once even if the call is executed many times. diff --git a/doc/classes/ScriptLanguageExtension.xml b/doc/classes/ScriptLanguageExtension.xml index d66bb6a7c7..0f757cf806 100644 --- a/doc/classes/ScriptLanguageExtension.xml +++ b/doc/classes/ScriptLanguageExtension.xml @@ -372,11 +372,13 @@ </constant> <constant name="LOOKUP_RESULT_CLASS_METHOD" value="4" enum="LookupResultType"> </constant> - <constant name="LOOKUP_RESULT_CLASS_ENUM" value="5" enum="LookupResultType"> + <constant name="LOOKUP_RESULT_CLASS_SIGNAL" value="5" enum="LookupResultType"> </constant> - <constant name="LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE" value="6" enum="LookupResultType"> + <constant name="LOOKUP_RESULT_CLASS_ENUM" value="6" enum="LookupResultType"> </constant> - <constant name="LOOKUP_RESULT_MAX" value="7" enum="LookupResultType"> + <constant name="LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE" value="7" enum="LookupResultType"> + </constant> + <constant name="LOOKUP_RESULT_MAX" value="8" enum="LookupResultType"> </constant> <constant name="LOCATION_LOCAL" value="0" enum="CodeCompletionLocation"> The option is local to the location of the code completion query - e.g. a local variable. diff --git a/doc/classes/Shape2D.xml b/doc/classes/Shape2D.xml index 03ff3cc188..94fb2d7dc7 100644 --- a/doc/classes/Shape2D.xml +++ b/doc/classes/Shape2D.xml @@ -26,7 +26,9 @@ <argument index="1" name="with_shape" type="Shape2D" /> <argument index="2" name="shape_xform" type="Transform2D" /> <description> - Returns a list of the points where this shape touches another. If there are no collisions the list is empty. + Returns a list of contact point pairs where this shape touches another. + If there are no collisions, the returned list is empty. Otherwise, the returned list contains contact points arranged in pairs, with entries alternating between points on the boundary of this shape and points on the boundary of [code]with_shape[/code]. + A collision pair A, B can be used to calculate the collision normal with [code](B - A).normalized()[/code], and the collision depth with [code](B - A).length()[/code]. This information is typically used to separate shapes, particularly in collision solvers. This method needs the transformation matrix for this shape ([code]local_xform[/code]), the shape to check collisions with ([code]with_shape[/code]), and the transformation matrix of that shape ([code]shape_xform[/code]). </description> </method> @@ -50,7 +52,9 @@ <argument index="3" name="shape_xform" type="Transform2D" /> <argument index="4" name="shape_motion" type="Vector2" /> <description> - Returns a list of the points where this shape would touch another, if a given movement was applied. If there are no collisions the list is empty. + Returns a list of contact point pairs where this shape would touch another, if a given movement was applied. + If there would be no collisions, the returned list is empty. Otherwise, the returned list contains contact points arranged in pairs, with entries alternating between points on the boundary of this shape and points on the boundary of [code]with_shape[/code]. + A collision pair A, B can be used to calculate the collision normal with [code](B - A).normalized()[/code], and the collision depth with [code](B - A).length()[/code]. This information is typically used to separate shapes, particularly in collision solvers. This method needs the transformation matrix for this shape ([code]local_xform[/code]), the movement to test on this shape ([code]local_motion[/code]), the shape to check collisions with ([code]with_shape[/code]), the transformation matrix of that shape ([code]shape_xform[/code]), and the movement to test onto the other object ([code]shape_motion[/code]). </description> </method> diff --git a/doc/classes/TextMesh.xml b/doc/classes/TextMesh.xml new file mode 100644 index 0000000000..5a1501d2ca --- /dev/null +++ b/doc/classes/TextMesh.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="TextMesh" inherits="PrimitiveMesh" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Generate an [PrimitiveMesh] from the text. + </brief_description> + <description> + Generate an [PrimitiveMesh] from the text. + TextMesh can be generated only when using dynamic fonts with vector glyph contours. Bitmap fonts (including bitmap data in the TrueType/OpenType containers, like color emoji fonts) are not supported. + The UV layout is arranged in 4 horizontal strips, top to bottom: 40% of the height for the front face, 40% for the back face, 10% for the outer edges and 10% for the inner edges. + </description> + <tutorials> + </tutorials> + <methods> + <method name="clear_opentype_features"> + <return type="void" /> + <description> + Removes all OpenType features. + </description> + </method> + <method name="get_opentype_feature" qualifiers="const"> + <return type="int" /> + <argument index="0" name="tag" type="String" /> + <description> + Returns OpenType feature [code]tag[/code]. + </description> + </method> + <method name="set_opentype_feature"> + <return type="void" /> + <argument index="0" name="tag" type="String" /> + <argument index="1" name="value" type="int" /> + <description> + Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url]. + </description> + </method> + </methods> + <members> + <member name="curve_step" type="float" setter="set_curve_step" getter="get_curve_step" default="0.5"> + Step (in pixels) used to approximate Bézier curves. + </member> + <member name="depth" type="float" setter="set_depth" getter="get_depth" default="0.05"> + Depths of the mesh, if set to [code]0.0[/code] only front surface, is generated, and UV layout is changed to use full texture for the front face only. + </member> + <member name="font" type="Font" setter="set_font" getter="get_font"> + [Font] used for the [TextMesh]'s text. + </member> + <member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16"> + Font size of the [TextMesh]'s text. + </member> + <member name="horizontal_alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="1"> + Controls the text's horizontal alignment. Supports left, center, right, and fill, or justify. Set it to one of the [enum HorizontalAlignment] constants. + </member> + <member name="language" type="String" setter="set_language" getter="get_language" default=""""> + Language code used for text shaping algorithms, if left empty current locale is used instead. + </member> + <member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01"> + The size of one pixel's width on the text to scale it in 3D. + </member> + <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> + Set BiDi algorithm override for the structured text. + </member> + <member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]"> + Set additional options for BiDi override. + </member> + <member name="text" type="String" setter="set_text" getter="get_text" default=""""> + The text to generate mesh from. + </member> + <member name="text_direction" type="int" setter="set_text_direction" getter="get_text_direction" enum="TextServer.Direction" default="0"> + Base text writing direction. + </member> + <member name="uppercase" type="bool" setter="set_uppercase" getter="is_uppercase" default="false"> + If [code]true[/code], all the text displays as UPPERCASE. + </member> + <member name="width" type="float" setter="set_width" getter="get_width" default="500.0"> + Text width (in pixels), used for fill alignment. + </member> + </members> +</class> diff --git a/doc/classes/VisualInstance3D.xml b/doc/classes/VisualInstance3D.xml index 78a681d92a..2468042850 100644 --- a/doc/classes/VisualInstance3D.xml +++ b/doc/classes/VisualInstance3D.xml @@ -66,6 +66,7 @@ <member name="layers" type="int" setter="set_layer_mask" getter="get_layer_mask"> The render layer(s) this [VisualInstance3D] is drawn on. This object will only be visible for [Camera3D]s whose cull mask includes the render object this [VisualInstance3D] is set to. + For [Light3D]s, this can be used to control which [VisualInstance3D]s are affected by a specific light. For [GPUParticles3D], this can be used to control which particles are effected by a specific attractor. For [Decal]s, this can be used to control which [VisualInstance3D]s are affected by a specific decal. </member> </members> </class> diff --git a/doc/classes/VisualShaderNodeColorFunc.xml b/doc/classes/VisualShaderNodeColorFunc.xml index 4a73b1662e..6116e0df68 100644 --- a/doc/classes/VisualShaderNodeColorFunc.xml +++ b/doc/classes/VisualShaderNodeColorFunc.xml @@ -24,7 +24,13 @@ return vec3(max3, max3, max3); [/codeblock] </constant> - <constant name="FUNC_SEPIA" value="1" enum="Function"> + <constant name="FUNC_HSV2RGB" value="1" enum="Function"> + Converts HSV vector to RGB equivalent. + </constant> + <constant name="FUNC_RGB2HSV" value="2" enum="Function"> + Converts RGB vector to HSV equivalent. + </constant> + <constant name="FUNC_SEPIA" value="3" enum="Function"> Applies sepia tone effect using the following formula: [codeblock] vec3 c = input; @@ -34,7 +40,7 @@ return vec3(r, g, b); [/codeblock] </constant> - <constant name="FUNC_MAX" value="2" enum="Function"> + <constant name="FUNC_MAX" value="4" enum="Function"> Represents the size of the [enum Function] enum. </constant> </constants> diff --git a/doc/classes/VisualShaderNodeVectorFunc.xml b/doc/classes/VisualShaderNodeVectorFunc.xml index dc6628a9af..bc4e12c0b3 100644 --- a/doc/classes/VisualShaderNodeVectorFunc.xml +++ b/doc/classes/VisualShaderNodeVectorFunc.xml @@ -26,100 +26,94 @@ <constant name="FUNC_RECIPROCAL" value="3" enum="Function"> Returns [code]1/vector[/code]. </constant> - <constant name="FUNC_RGB2HSV" value="4" enum="Function"> - Converts RGB vector to HSV equivalent. - </constant> - <constant name="FUNC_HSV2RGB" value="5" enum="Function"> - Converts HSV vector to RGB equivalent. - </constant> - <constant name="FUNC_ABS" value="6" enum="Function"> + <constant name="FUNC_ABS" value="4" enum="Function"> Returns the absolute value of the parameter. </constant> - <constant name="FUNC_ACOS" value="7" enum="Function"> + <constant name="FUNC_ACOS" value="5" enum="Function"> Returns the arc-cosine of the parameter. </constant> - <constant name="FUNC_ACOSH" value="8" enum="Function"> + <constant name="FUNC_ACOSH" value="6" enum="Function"> Returns the inverse hyperbolic cosine of the parameter. </constant> - <constant name="FUNC_ASIN" value="9" enum="Function"> + <constant name="FUNC_ASIN" value="7" enum="Function"> Returns the arc-sine of the parameter. </constant> - <constant name="FUNC_ASINH" value="10" enum="Function"> + <constant name="FUNC_ASINH" value="8" enum="Function"> Returns the inverse hyperbolic sine of the parameter. </constant> - <constant name="FUNC_ATAN" value="11" enum="Function"> + <constant name="FUNC_ATAN" value="9" enum="Function"> Returns the arc-tangent of the parameter. </constant> - <constant name="FUNC_ATANH" value="12" enum="Function"> + <constant name="FUNC_ATANH" value="10" enum="Function"> Returns the inverse hyperbolic tangent of the parameter. </constant> - <constant name="FUNC_CEIL" value="13" enum="Function"> + <constant name="FUNC_CEIL" value="11" enum="Function"> Finds the nearest integer that is greater than or equal to the parameter. </constant> - <constant name="FUNC_COS" value="14" enum="Function"> + <constant name="FUNC_COS" value="12" enum="Function"> Returns the cosine of the parameter. </constant> - <constant name="FUNC_COSH" value="15" enum="Function"> + <constant name="FUNC_COSH" value="13" enum="Function"> Returns the hyperbolic cosine of the parameter. </constant> - <constant name="FUNC_DEGREES" value="16" enum="Function"> + <constant name="FUNC_DEGREES" value="14" enum="Function"> Converts a quantity in radians to degrees. </constant> - <constant name="FUNC_EXP" value="17" enum="Function"> + <constant name="FUNC_EXP" value="15" enum="Function"> Base-e Exponential. </constant> - <constant name="FUNC_EXP2" value="18" enum="Function"> + <constant name="FUNC_EXP2" value="16" enum="Function"> Base-2 Exponential. </constant> - <constant name="FUNC_FLOOR" value="19" enum="Function"> + <constant name="FUNC_FLOOR" value="17" enum="Function"> Finds the nearest integer less than or equal to the parameter. </constant> - <constant name="FUNC_FRAC" value="20" enum="Function"> + <constant name="FUNC_FRAC" value="18" enum="Function"> Computes the fractional part of the argument. </constant> - <constant name="FUNC_INVERSE_SQRT" value="21" enum="Function"> + <constant name="FUNC_INVERSE_SQRT" value="19" enum="Function"> Returns the inverse of the square root of the parameter. </constant> - <constant name="FUNC_LOG" value="22" enum="Function"> + <constant name="FUNC_LOG" value="20" enum="Function"> Natural logarithm. </constant> - <constant name="FUNC_LOG2" value="23" enum="Function"> + <constant name="FUNC_LOG2" value="21" enum="Function"> Base-2 logarithm. </constant> - <constant name="FUNC_RADIANS" value="24" enum="Function"> + <constant name="FUNC_RADIANS" value="22" enum="Function"> Converts a quantity in degrees to radians. </constant> - <constant name="FUNC_ROUND" value="25" enum="Function"> + <constant name="FUNC_ROUND" value="23" enum="Function"> Finds the nearest integer to the parameter. </constant> - <constant name="FUNC_ROUNDEVEN" value="26" enum="Function"> + <constant name="FUNC_ROUNDEVEN" value="24" enum="Function"> Finds the nearest even integer to the parameter. </constant> - <constant name="FUNC_SIGN" value="27" enum="Function"> + <constant name="FUNC_SIGN" value="25" enum="Function"> Extracts the sign of the parameter, i.e. returns [code]-1[/code] if the parameter is negative, [code]1[/code] if it's positive and [code]0[/code] otherwise. </constant> - <constant name="FUNC_SIN" value="28" enum="Function"> + <constant name="FUNC_SIN" value="26" enum="Function"> Returns the sine of the parameter. </constant> - <constant name="FUNC_SINH" value="29" enum="Function"> + <constant name="FUNC_SINH" value="27" enum="Function"> Returns the hyperbolic sine of the parameter. </constant> - <constant name="FUNC_SQRT" value="30" enum="Function"> + <constant name="FUNC_SQRT" value="28" enum="Function"> Returns the square root of the parameter. </constant> - <constant name="FUNC_TAN" value="31" enum="Function"> + <constant name="FUNC_TAN" value="29" enum="Function"> Returns the tangent of the parameter. </constant> - <constant name="FUNC_TANH" value="32" enum="Function"> + <constant name="FUNC_TANH" value="30" enum="Function"> Returns the hyperbolic tangent of the parameter. </constant> - <constant name="FUNC_TRUNC" value="33" enum="Function"> + <constant name="FUNC_TRUNC" value="31" enum="Function"> Returns a value equal to the nearest integer to the parameter whose absolute value is not larger than the absolute value of the parameter. </constant> - <constant name="FUNC_ONEMINUS" value="34" enum="Function"> + <constant name="FUNC_ONEMINUS" value="32" enum="Function"> Returns [code]1.0 - vector[/code]. </constant> - <constant name="FUNC_MAX" value="35" enum="Function"> + <constant name="FUNC_MAX" value="33" enum="Function"> Represents the size of the [enum Function] enum. </constant> </constants> diff --git a/doc/classes/float.xml b/doc/classes/float.xml index 50961f9c7f..f36b1fddeb 100644 --- a/doc/classes/float.xml +++ b/doc/classes/float.xml @@ -124,6 +124,18 @@ Multiplies a [float] and an [int]. The result is a [float]. </description> </operator> + <operator name="operator **"> + <return type="float" /> + <argument index="0" name="right" type="float" /> + <description> + </description> + </operator> + <operator name="operator **"> + <return type="float" /> + <argument index="0" name="right" type="int" /> + <description> + </description> + </operator> <operator name="operator +"> <return type="float" /> <argument index="0" name="right" type="float" /> diff --git a/doc/classes/int.xml b/doc/classes/int.xml index 609291b69c..2eceba40fa 100644 --- a/doc/classes/int.xml +++ b/doc/classes/int.xml @@ -171,6 +171,18 @@ Multiplies two [int]s. </description> </operator> + <operator name="operator **"> + <return type="float" /> + <argument index="0" name="right" type="float" /> + <description> + </description> + </operator> + <operator name="operator **"> + <return type="int" /> + <argument index="0" name="right" type="int" /> + <description> + </description> + </operator> <operator name="operator +"> <return type="String" /> <argument index="0" name="right" type="String" /> diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index eba4cee33a..2e227ce578 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -677,7 +677,8 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S for value in e.values.values(): f.write("- **{}** = **{}**".format(value.name, value.value)) if value.text is not None and value.text.strip() != "": - f.write(" --- " + rstize_text(value.text.strip(), state)) + # If value.text contains a bullet point list, each entry needs additional indentation + f.write(" --- " + indent_bullets(rstize_text(value.text.strip(), state))) f.write("\n\n") @@ -904,7 +905,7 @@ def rstize_text(text, state): # type: (str, State) -> str pre_text = text[:pos] indent_level = 0 - while text[pos + 1] == "\t": + while pos + 1 < len(text) and text[pos + 1] == "\t": pos += 1 indent_level += 1 post_text = text[pos + 1 :] @@ -1409,6 +1410,8 @@ def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str clear_name = "div" elif clear_name == "%": clear_name = "mod" + elif clear_name == "**": + clear_name = "pow" elif clear_name == "unary+": clear_name = "unplus" @@ -1438,5 +1441,24 @@ def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str return clear_name +def indent_bullets(text): # type: (str) -> str + # Take the text and check each line for a bullet point represented by "-". + # Where found, indent the given line by a further "\t". + # Used to properly indent bullet points contained in the description for enum values. + # Ignore the first line - text will be prepended to it so bullet points wouldn't work anyway. + bullet_points = "-" + + lines = text.splitlines(keepends=True) + for line_index, line in enumerate(lines[1:], start=1): + pos = 0 + while pos < len(line) and line[pos] == "\t": + pos += 1 + + if pos < len(line) and line[pos] in bullet_points: + lines[line_index] = line[:pos] + "\t" + line[pos:] + + return "".join(lines) + + if __name__ == "__main__": main() diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h index b19f133d89..f86037f092 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.h +++ b/drivers/coreaudio/audio_driver_coreaudio.h @@ -35,9 +35,9 @@ #include "servers/audio_server.h" -#include <AudioUnit/AudioUnit.h> +#import <AudioUnit/AudioUnit.h> #ifdef OSX_ENABLED -#include <CoreAudio/AudioHardware.h> +#import <CoreAudio/AudioHardware.h> #endif class AudioDriverCoreAudio : public AudioDriver { diff --git a/drivers/coremidi/midi_driver_coremidi.cpp b/drivers/coremidi/midi_driver_coremidi.cpp index ecd10f900b..dc69ab9472 100644 --- a/drivers/coremidi/midi_driver_coremidi.cpp +++ b/drivers/coremidi/midi_driver_coremidi.cpp @@ -34,8 +34,8 @@ #include "core/string/print_string.h" -#include <CoreAudio/HostTime.h> -#include <CoreServices/CoreServices.h> +#import <CoreAudio/HostTime.h> +#import <CoreServices/CoreServices.h> void MIDIDriverCoreMidi::read(const MIDIPacketList *packet_list, void *read_proc_ref_con, void *src_conn_ref_con) { MIDIPacket *packet = const_cast<MIDIPacket *>(packet_list->packet); diff --git a/drivers/coremidi/midi_driver_coremidi.h b/drivers/coremidi/midi_driver_coremidi.h index be0a9f610e..0085141c6d 100644 --- a/drivers/coremidi/midi_driver_coremidi.h +++ b/drivers/coremidi/midi_driver_coremidi.h @@ -36,7 +36,7 @@ #include "core/os/midi_driver.h" #include "core/templates/vector.h" -#include <CoreMIDI/CoreMIDI.h> +#import <CoreMIDI/CoreMIDI.h> #include <stdio.h> class MIDIDriverCoreMidi : public MIDIDriver { diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 1197f4aac1..df54686574 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -179,12 +179,12 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ //print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale)); state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5); - glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_BUFFER_OBJECT, state.canvas_state_buffer); + glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_state_buffer); glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW); GLuint global_buffer = material_storage->global_variables_get_uniform_buffer(); - glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_BUFFER_OBJECT, global_buffer); + glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_LOCATION, global_buffer); glBindBuffer(GL_UNIFORM_BUFFER, 0); } @@ -522,7 +522,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item } } - glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_BUFFER_OBJECT, state.canvas_instance_data_buffers[state.current_buffer]); + glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer]); #ifdef JAVASCRIPT_ENABLED //WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData), &state.instance_data_array[0], GL_DYNAMIC_DRAW); @@ -728,7 +728,7 @@ void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) { } } - glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_BUFFER_OBJECT, state.canvas_instance_data_buffers[state.current_buffer]); + glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer]); #ifdef JAVASCRIPT_ENABLED //WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData) * r_index, state.instance_data_array, GL_DYNAMIC_DRAW); diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index b77b295de9..aedde7c265 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -97,13 +97,12 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender { }; public: - //TODO move to Material storage enum { - BASE_UNIFORM_BUFFER_OBJECT = 0, - GLOBAL_UNIFORM_BUFFER_OBJECT = 1, - LIGHT_UNIFORM_BUFFER_OBJECT = 2, - INSTANCE_UNIFORM_BUFFER_OBJECT = 3, - MATERIAL_UNIFORM_BUFFER_OBJECT = 4, + BASE_UNIFORM_LOCATION = 0, + GLOBAL_UNIFORM_LOCATION = 1, + LIGHT_UNIFORM_LOCATION = 2, + INSTANCE_UNIFORM_LOCATION = 3, + MATERIAL_UNIFORM_LOCATION = 4, }; struct StateBuffer { diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index e09355e433..69f69099c7 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -210,6 +210,9 @@ RasterizerGLES3::RasterizerGLES3() { #ifdef GLAD_ENABLED if (!gladLoadGL()) { ERR_PRINT("Error initializing GLAD"); + // FIXME this is an early return from a constructor. Any other code using this instance will crash or the finalizer will crash, because none of + // the members of this instance are initialized, so this just makes debugging harder. It should either crash here intentionally, + // or we need to actually test for this situation before constructing this. return; } #endif @@ -268,10 +271,6 @@ RasterizerGLES3::RasterizerGLES3() { storage = memnew(RasterizerStorageGLES3); canvas = memnew(RasterizerCanvasGLES3(storage)); scene = memnew(RasterizerSceneGLES3(storage)); - - texture_storage->set_main_thread_id(Thread::get_caller_id()); - // make sure the OS knows to only access the renderer from the main thread - OS::get_singleton()->set_render_main_thread_mode(OS::RENDER_MAIN_THREAD_ONLY); } RasterizerGLES3::~RasterizerGLES3() { @@ -289,6 +288,9 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display // TODO: do we need a keep 3d linear option? + // Make sure we are drawing to the right context. + DisplayServer::get_singleton()->gl_window_make_current(p_screen); + if (rt->external.fbo != 0) { glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo); } else { @@ -296,6 +298,7 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display } glReadBuffer(GL_COLOR_ATTACHMENT0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); + // Flip content upside down to correct for coordinates. glBlitFramebuffer(0, 0, rt->size.x, rt->size.y, 0, p_screen_rect.size.y, p_screen_rect.size.x, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); } diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index 33bb97d105..ad3d3d7325 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -92,9 +92,9 @@ public: static void make_current() { _create_func = _create_current; + low_end = true; } - virtual bool is_low_end() const { return true; } uint64_t get_frame_number() const { return frame; } double get_frame_delta_time() const { return delta; } diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index e0373ab8e8..7937090862 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -30,10 +30,26 @@ #include "rasterizer_scene_gles3.h" #include "core/config/project_settings.h" +#include "core/templates/sort_array.h" #include "servers/rendering/rendering_server_default.h" +#include "storage/config.h" #ifdef GLES3_ENABLED +void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) { +#ifdef GLES_OVER_GL + + for (int i = 0; i < levels; i++) { + glTexImage2D(target, i, internalformat, width, height, 0, format, type, nullptr); + width = MAX(1, (width / 2)); + height = MAX(1, (height / 2)); + } + +#else + glTexStorage2D(target, levels, internalformat, width, height); +#endif +} + uint64_t RasterizerSceneGLES3::auto_exposure_counter = 2; RasterizerSceneGLES3 *RasterizerSceneGLES3::singleton = nullptr; @@ -42,66 +58,192 @@ RasterizerSceneGLES3 *RasterizerSceneGLES3::get_singleton() { return singleton; } -RasterizerSceneGLES3::GeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID p_base) { - return nullptr; +RendererSceneRender::GeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID p_base) { + RS::InstanceType type = storage->get_base_type(p_base); + ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); + + GeometryInstanceGLES3 *ginstance = geometry_instance_alloc.alloc(); + ginstance->data = memnew(GeometryInstanceGLES3::Data); + + ginstance->data->base = p_base; + ginstance->data->base_type = type; + + _geometry_instance_mark_dirty(ginstance); + + return ginstance; } void RasterizerSceneGLES3::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->skeleton = p_skeleton; + + _geometry_instance_mark_dirty(ginstance); + ginstance->data->dirty_dependencies = true; } void RasterizerSceneGLES3::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->material_override = p_override; + + _geometry_instance_mark_dirty(ginstance); + ginstance->data->dirty_dependencies = true; } void RasterizerSceneGLES3::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->material_overlay = p_overlay; + + _geometry_instance_mark_dirty(ginstance); + ginstance->data->dirty_dependencies = true; } -void RasterizerSceneGLES3::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) { +void RasterizerSceneGLES3::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->surface_materials = p_materials; + + _geometry_instance_mark_dirty(ginstance); + ginstance->data->dirty_dependencies = true; } void RasterizerSceneGLES3::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ERR_FAIL_COND(!ginstance); + ginstance->mesh_instance = p_mesh_instance; + + _geometry_instance_mark_dirty(ginstance); } -void RasterizerSceneGLES3::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) { +void RasterizerSceneGLES3::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->transform = p_transform; + ginstance->mirror = p_transform.basis.determinant() < 0; + ginstance->data->aabb = p_aabb; + ginstance->transformed_aabb = p_transformed_aabb; + + Vector3 model_scale_vec = p_transform.basis.get_scale_abs(); + // handle non uniform scale here + + float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z)); + float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z)); + ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9; + + ginstance->lod_model_scale = max_scale; } void RasterizerSceneGLES3::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->layer_mask = p_layer_mask; } void RasterizerSceneGLES3::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->lod_bias = p_lod_bias; } void RasterizerSceneGLES3::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->force_alpha = CLAMP(1.0 - p_transparency, 0, 1); } void RasterizerSceneGLES3::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->fade_near = p_enable_near; + ginstance->fade_near_begin = p_near_begin; + ginstance->fade_near_end = p_near_end; + ginstance->fade_far = p_enable_far; + ginstance->fade_far_begin = p_far_begin; + ginstance->fade_far_end = p_far_end; } void RasterizerSceneGLES3::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->parent_fade_alpha = p_alpha; } void RasterizerSceneGLES3::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->use_baked_light = p_enable; + + _geometry_instance_mark_dirty(ginstance); } void RasterizerSceneGLES3::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->use_dynamic_gi = p_enable; + _geometry_instance_mark_dirty(ginstance); } void RasterizerSceneGLES3::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); } void RasterizerSceneGLES3::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); } void RasterizerSceneGLES3::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->shader_parameters_offset = p_offset; + _geometry_instance_mark_dirty(ginstance); } void RasterizerSceneGLES3::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->cast_double_sided_shadows = p_enable; + _geometry_instance_mark_dirty(ginstance); } uint32_t RasterizerSceneGLES3::geometry_instance_get_pair_mask() { - return 0; + return (1 << RS::INSTANCE_LIGHT); } void RasterizerSceneGLES3::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + + GLES3::Config *config = GLES3::Config::get_singleton(); + + ginstance->omni_light_count = 0; + ginstance->spot_light_count = 0; + ginstance->omni_lights.clear(); + ginstance->spot_lights.clear(); + + for (uint32_t i = 0; i < p_light_instance_count; i++) { + RS::LightType type = light_instance_get_type(p_light_instances[i]); + switch (type) { + case RS::LIGHT_OMNI: { + if (ginstance->omni_light_count < (uint32_t)config->max_lights_per_object) { + ginstance->omni_lights.push_back(p_light_instances[i]); + ginstance->omni_light_count++; + } + } break; + case RS::LIGHT_SPOT: { + if (ginstance->spot_light_count < (uint32_t)config->max_lights_per_object) { + ginstance->spot_lights.push_back(p_light_instances[i]); + ginstance->spot_light_count++; + } + } break; + default: + break; + } + } } void RasterizerSceneGLES3::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { @@ -114,9 +256,312 @@ void RasterizerSceneGLES3::geometry_instance_pair_voxel_gi_instances(GeometryIns } void RasterizerSceneGLES3::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); } void RasterizerSceneGLES3::geometry_instance_free(GeometryInstance *p_geometry_instance) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + GeometryInstanceSurface *surf = ginstance->surface_caches; + while (surf) { + GeometryInstanceSurface *next = surf->next; + geometry_instance_surface_alloc.free(surf); + surf = next; + } + memdelete(ginstance->data); + geometry_instance_alloc.free(ginstance); +} + +void RasterizerSceneGLES3::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + if (ginstance->dirty_list_element.in_list()) { + return; + } + + //clear surface caches + GeometryInstanceSurface *surf = ginstance->surface_caches; + + while (surf) { + GeometryInstanceSurface *next = surf->next; + geometry_instance_surface_alloc.free(surf); + surf = next; + } + + ginstance->surface_caches = nullptr; + + geometry_instance_dirty_list.add(&ginstance->dirty_list_element); +} + +void RasterizerSceneGLES3::_update_dirty_geometry_instances() { + while (geometry_instance_dirty_list.first()) { + _geometry_instance_update(geometry_instance_dirty_list.first()->self()); + } +} + +void RasterizerSceneGLES3::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) { + switch (p_notification) { + case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: + case RendererStorage::DEPENDENCY_CHANGED_MESH: + case RendererStorage::DEPENDENCY_CHANGED_PARTICLES: + case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH: + case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: { + static_cast<RasterizerSceneGLES3 *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + } break; + case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_tracker->userdata); + if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { + ginstance->instance_count = GLES3::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base); + } + } break; + default: { + //rest of notifications of no interest + } break; + } +} + +void RasterizerSceneGLES3::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) { + static_cast<RasterizerSceneGLES3 *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); +} + +void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { + GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton(); + + bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; + bool has_base_alpha = ((p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha); + bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; + bool has_alpha = has_base_alpha || has_blend_alpha; + + uint32_t flags = 0; + + if (p_material->shader_data->uses_screen_texture) { + flags |= GeometryInstanceSurface::FLAG_USES_SCREEN_TEXTURE; + } + + if (p_material->shader_data->uses_depth_texture) { + flags |= GeometryInstanceSurface::FLAG_USES_DEPTH_TEXTURE; + } + + if (p_material->shader_data->uses_normal_texture) { + flags |= GeometryInstanceSurface::FLAG_USES_NORMAL_TEXTURE; + } + + if (ginstance->data->cast_double_sided_shadows) { + flags |= GeometryInstanceSurface::FLAG_USES_DOUBLE_SIDED_SHADOWS; + } + + if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED) { + //material is only meant for alpha pass + flags |= GeometryInstanceSurface::FLAG_PASS_ALPHA; + if (p_material->shader_data->uses_depth_pre_pass && !(p_material->shader_data->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED)) { + flags |= GeometryInstanceSurface::FLAG_PASS_DEPTH; + flags |= GeometryInstanceSurface::FLAG_PASS_SHADOW; + } + } else { + flags |= GeometryInstanceSurface::FLAG_PASS_OPAQUE; + flags |= GeometryInstanceSurface::FLAG_PASS_DEPTH; + flags |= GeometryInstanceSurface::FLAG_PASS_SHADOW; + } + + GLES3::SceneMaterialData *material_shadow = nullptr; + void *surface_shadow = nullptr; + if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) { + flags |= GeometryInstanceSurface::FLAG_USES_SHARED_SHADOW_MATERIAL; + material_shadow = static_cast<GLES3::SceneMaterialData *>(GLES3::MaterialStorage::get_singleton()->material_get_data(scene_globals.default_material, RS::SHADER_SPATIAL)); + + RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh); + + if (shadow_mesh.is_valid()) { + surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface); + } + + } else { + material_shadow = p_material; + } + + GeometryInstanceSurface *sdcache = geometry_instance_surface_alloc.alloc(); + + sdcache->flags = flags; + + sdcache->shader = p_material->shader_data; + sdcache->material = p_material; + sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface); + sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface); + sdcache->surface_index = p_surface; + + if (ginstance->data->dirty_dependencies) { + storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker); + } + + //shadow + sdcache->shader_shadow = material_shadow->shader_data; + sdcache->material_shadow = material_shadow; + + sdcache->surface_shadow = surface_shadow ? surface_shadow : sdcache->surface; + + sdcache->owner = ginstance; + + sdcache->next = ginstance->surface_caches; + ginstance->surface_caches = sdcache; + + //sortkey + + sdcache->sort.sort_key1 = 0; + sdcache->sort.sort_key2 = 0; + + sdcache->sort.surface_index = p_surface; + sdcache->sort.material_id_low = p_material_id & 0x0000FFFF; + sdcache->sort.material_id_hi = p_material_id >> 16; + sdcache->sort.shader_id = p_shader_id; + sdcache->sort.geometry_id = p_mesh.get_local_index(); + sdcache->sort.priority = p_material->priority; +} + +void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material_chain(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material_data, RID p_mat_src, RID p_mesh) { + GLES3::SceneMaterialData *material_data = p_material_data; + GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); + + _geometry_instance_add_surface_with_material(ginstance, p_surface, material_data, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh); + + while (material_data->next_pass.is_valid()) { + RID next_pass = material_data->next_pass; + material_data = static_cast<GLES3::SceneMaterialData *>(material_storage->material_get_data(next_pass, RS::SHADER_SPATIAL)); + if (!material_data || !material_data->shader_data->valid) { + break; + } + if (ginstance->data->dirty_dependencies) { + material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); + } + _geometry_instance_add_surface_with_material(ginstance, p_surface, material_data, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh); + } +} + +void RasterizerSceneGLES3::_geometry_instance_add_surface(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { + GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); + RID m_src; + + m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material; + + GLES3::SceneMaterialData *material_data = nullptr; + + if (m_src.is_valid()) { + material_data = static_cast<GLES3::SceneMaterialData *>(material_storage->material_get_data(m_src, RS::SHADER_SPATIAL)); + if (!material_data || !material_data->shader_data->valid) { + material_data = nullptr; + } + } + + if (material_data) { + if (ginstance->data->dirty_dependencies) { + material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + } + } else { + material_data = static_cast<GLES3::SceneMaterialData *>(material_storage->material_get_data(scene_globals.default_material, RS::SHADER_SPATIAL)); + m_src = scene_globals.default_material; + } + + ERR_FAIL_COND(!material_data); + + _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material_data, m_src, p_mesh); + + if (ginstance->data->material_overlay.is_valid()) { + m_src = ginstance->data->material_overlay; + + material_data = static_cast<GLES3::SceneMaterialData *>(material_storage->material_get_data(m_src, RS::SHADER_SPATIAL)); + if (material_data && material_data->shader_data->valid) { + if (ginstance->data->dirty_dependencies) { + material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + } + + _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material_data, m_src, p_mesh); + } + } +} + +void RasterizerSceneGLES3::_geometry_instance_update(GeometryInstance *p_geometry_instance) { + GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton(); + GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); + + if (ginstance->data->dirty_dependencies) { + ginstance->data->dependency_tracker.update_begin(); + } + + //add geometry for drawing + switch (ginstance->data->base_type) { + case RS::INSTANCE_MESH: { + const RID *materials = nullptr; + uint32_t surface_count; + RID mesh = ginstance->data->base; + + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); + if (materials) { + //if no materials, no surfaces. + const RID *inst_materials = ginstance->data->surface_materials.ptr(); + uint32_t surf_mat_count = ginstance->data->surface_materials.size(); + + for (uint32_t j = 0; j < surface_count; j++) { + RID material = (j < surf_mat_count && inst_materials[j].is_valid()) ? inst_materials[j] : materials[j]; + _geometry_instance_add_surface(ginstance, j, material, mesh); + } + } + + ginstance->instance_count = 1; + + } break; + + case RS::INSTANCE_MULTIMESH: { + RID mesh = mesh_storage->multimesh_get_mesh(ginstance->data->base); + if (mesh.is_valid()) { + const RID *materials = nullptr; + uint32_t surface_count; + + materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count); + if (materials) { + for (uint32_t j = 0; j < surface_count; j++) { + _geometry_instance_add_surface(ginstance, j, materials[j], mesh); + } + } + + ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base); + } + + } break; + case RS::INSTANCE_PARTICLES: { + } break; + + default: { + } + } + + bool store_transform = true; + ginstance->base_flags = 0; + + if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; + if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; + } + if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; + } + if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; + } + + //ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_globals.default_shader_rd, TRANSFORMS_UNIFORM_SET); + + } else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) { + } else if (ginstance->data->base_type == RS::INSTANCE_MESH) { + } + + ginstance->store_transform_cache = store_transform; + + if (ginstance->data->dirty_dependencies) { + ginstance->data->dependency_tracker.update_end(); + ginstance->data->dirty_dependencies = false; + } + + ginstance->dirty_list_element.remove_from_list(); } /* SHADOW ATLAS API */ @@ -147,12 +592,12 @@ void RasterizerSceneGLES3::set_directional_shadow_count(int p_count) { /* SKY API */ -void RasterizerSceneGLES3::Sky::free() { - if (radiance != 0) { - glDeleteTextures(1, &radiance); - radiance = 0; - glDeleteFramebuffers(1, &radiance_framebuffer); - radiance_framebuffer = 0; +void RasterizerSceneGLES3::_free_sky_data(Sky *p_sky) { + if (p_sky->radiance != 0) { + glDeleteTextures(1, &p_sky->radiance); + p_sky->radiance = 0; + glDeleteFramebuffers(1, &p_sky->radiance_framebuffer); + p_sky->radiance_framebuffer = 0; } } @@ -175,7 +620,8 @@ void RasterizerSceneGLES3::sky_set_radiance_size(RID p_sky, int p_radiance_size) sky->radiance_size = p_radiance_size; - sky->free(); + _free_sky_data(sky); + _invalidate_sky(sky); } void RasterizerSceneGLES3::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { @@ -187,10 +633,7 @@ void RasterizerSceneGLES3::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { } sky->mode = p_mode; - - if (sky->mode == RS::SKY_MODE_REALTIME) { - WARN_PRINT_ONCE("The OpenGL renderer does not support the Real Time Sky Update Mode yet. Please use High Quality Mode instead"); - } + _invalidate_sky(sky); } void RasterizerSceneGLES3::sky_set_material(RID p_sky, RID p_material) { @@ -202,6 +645,7 @@ void RasterizerSceneGLES3::sky_set_material(RID p_sky, RID p_material) { } sky->material = p_material; + _invalidate_sky(sky); } void RasterizerSceneGLES3::_invalidate_sky(Sky *p_sky) { @@ -217,13 +661,57 @@ void RasterizerSceneGLES3::_update_dirty_skys() { while (sky) { if (sky->radiance == 0) { - //int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1; + sky->mipmap_count = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8) + 1; - //uint32_t w = sky->radiance_size, h = sky->radiance_size; - //int layers = sky_globals.roughness_layers; + // Left uninitialized, will attach a texture at render time glGenFramebuffers(1, &sky->radiance_framebuffer); + GLenum internal_format = GL_RGB10_A2; + glGenTextures(1, &sky->radiance); + glBindTexture(GL_TEXTURE_CUBE_MAP, sky->radiance); + +#ifdef GLES_OVER_GL + GLenum format = GL_RGBA; + GLenum type = GL_UNSIGNED_INT_2_10_10_10_REV; + //TODO, on low-end compare this to allocating each face of each mip individually + // see: https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexStorage2D.xhtml + for (int i = 0; i < 6; i++) { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internal_format, sky->radiance_size, sky->radiance_size, 0, format, type, nullptr); + } + + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); +#else + glTexStorage2D(GL_TEXTURE_CUBE_MAP, sky->mipmap_count, internal_format, sky->radiance_size, sky->radiance_size); +#endif + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count); + + glGenTextures(1, &sky->raw_radiance); + glBindTexture(GL_TEXTURE_CUBE_MAP, sky->raw_radiance); + +#ifdef GLES_OVER_GL + //TODO, on low-end compare this to allocating each face of each mip individually + // see: https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexStorage2D.xhtml + for (int i = 0; i < 6; i++) { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internal_format, sky->radiance_size, sky->radiance_size, 0, format, type, nullptr); + } + + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); +#else + glTexStorage2D(GL_TEXTURE_CUBE_MAP, sky->mipmap_count, internal_format, sky->radiance_size, sky->radiance_size); +#endif + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); } sky->reflection_dirty = true; @@ -238,39 +726,384 @@ void RasterizerSceneGLES3::_update_dirty_skys() { dirty_sky_list = nullptr; } -void RasterizerSceneGLES3::_draw_sky(Sky *p_sky, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_custom_fov, float p_energy, const Basis &p_sky_orientation) { - ERR_FAIL_COND(!p_sky); +void RasterizerSceneGLES3::_setup_sky(Environment *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) { + GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton(); + GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); + ERR_FAIL_COND(!p_env); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); + GLES3::SkyMaterialData *material = nullptr; + Sky *sky = sky_owner.get_or_null(p_env->sky); + + RID sky_material; + + GLES3::SkyShaderData *shader_data = nullptr; + + if (sky) { + sky_material = sky->material; - //state.sky_shader.version_bind_shader(sky_globals.default_shader, SkyShaderGLES3::MODE_BACKGROUND); - //glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.canvas_instance_data_buffers[state.current_buffer]); // Canvas data updated here - //glBindBufferBase(GL_UNIFORM_BUFFER, 1, state.canvas_instance_data_buffers[state.current_buffer]); // Global data - //glBindBufferBase(GL_UNIFORM_BUFFER, 2, state.canvas_instance_data_buffers[state.current_buffer]); // Directional light data - //glBindBufferBase(GL_UNIFORM_BUFFER, 3, state.canvas_instance_data_buffers[state.current_buffer]); // Material uniforms + if (sky_material.is_valid()) { + material = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY)); + if (!material || !material->shader_data->valid) { + material = nullptr; + } + } + + if (!material) { + sky_material = sky_globals.default_material; + material = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY)); + } + + ERR_FAIL_COND(!material); + + shader_data = material->shader_data; + + ERR_FAIL_COND(!shader_data); + + if (shader_data->uses_time && time - sky->prev_time > 0.00001) { + sky->prev_time = time; + sky->reflection_dirty = true; + RenderingServerDefault::redraw_request(); + } + + if (material != sky->prev_material) { + sky->prev_material = material; + sky->reflection_dirty = true; + } + + if (material->uniform_set_updated) { + material->uniform_set_updated = false; + sky->reflection_dirty = true; + } + + if (!p_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) { + sky->prev_position = p_transform.origin; + sky->reflection_dirty = true; + } + + if (shader_data->uses_light) { + sky_globals.directional_light_count = 0; + for (int i = 0; i < (int)p_lights.size(); i++) { + LightInstance *li = light_instance_owner.get_or_null(p_lights[i]); + if (!li) { + continue; + } + RID base = li->light; + + ERR_CONTINUE(base.is_null()); + + RS::LightType type = light_storage->light_get_type(base); + if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) { + DirectionalLightData &sky_light_data = sky_globals.directional_lights[sky_globals.directional_light_count]; + Transform3D light_transform = li->transform; + Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); + + sky_light_data.direction[0] = world_direction.x; + sky_light_data.direction[1] = world_direction.y; + sky_light_data.direction[2] = world_direction.z; + + float sign = light_storage->light_is_negative(base) ? -1 : 1; + sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); + + Color linear_col = light_storage->light_get_color(base); + sky_light_data.color[0] = linear_col.r; + sky_light_data.color[1] = linear_col.g; + sky_light_data.color[2] = linear_col.b; + + sky_light_data.enabled = true; + + float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); + if (angular_diameter > 0.0) { + angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + } else { + angular_diameter = 0.0; + } + sky_light_data.size = angular_diameter; + sky_globals.directional_light_count++; + if (sky_globals.directional_light_count >= sky_globals.max_directional_lights) { + break; + } + } + } + // Check whether the directional_light_buffer changes + bool light_data_dirty = false; + + // Light buffer is dirty if we have fewer or more lights + // If we have fewer lights, make sure that old lights are disabled + if (sky_globals.directional_light_count != sky_globals.last_frame_directional_light_count) { + light_data_dirty = true; + for (uint32_t i = sky_globals.directional_light_count; i < sky_globals.max_directional_lights; i++) { + sky_globals.directional_lights[i].enabled = false; + } + } + + if (!light_data_dirty) { + for (uint32_t i = 0; i < sky_globals.directional_light_count; i++) { + if (sky_globals.directional_lights[i].direction[0] != sky_globals.last_frame_directional_lights[i].direction[0] || + sky_globals.directional_lights[i].direction[1] != sky_globals.last_frame_directional_lights[i].direction[1] || + sky_globals.directional_lights[i].direction[2] != sky_globals.last_frame_directional_lights[i].direction[2] || + sky_globals.directional_lights[i].energy != sky_globals.last_frame_directional_lights[i].energy || + sky_globals.directional_lights[i].color[0] != sky_globals.last_frame_directional_lights[i].color[0] || + sky_globals.directional_lights[i].color[1] != sky_globals.last_frame_directional_lights[i].color[1] || + sky_globals.directional_lights[i].color[2] != sky_globals.last_frame_directional_lights[i].color[2] || + sky_globals.directional_lights[i].enabled != sky_globals.last_frame_directional_lights[i].enabled || + sky_globals.directional_lights[i].size != sky_globals.last_frame_directional_lights[i].size) { + light_data_dirty = true; + break; + } + } + } + + if (light_data_dirty) { + glBindBufferBase(GL_UNIFORM_BUFFER, SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION, sky_globals.directional_light_buffer); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(DirectionalLightData) * sky_globals.directional_light_count, sky_globals.directional_lights); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + DirectionalLightData *temp = sky_globals.last_frame_directional_lights; + sky_globals.last_frame_directional_lights = sky_globals.directional_lights; + sky_globals.directional_lights = temp; + sky_globals.last_frame_directional_light_count = sky_globals.directional_light_count; + sky->reflection_dirty = true; + } + } + + if (!sky->radiance) { + _update_dirty_skys(); + } + } +} + +void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform) { + GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); + ERR_FAIL_COND(!p_env); + + Sky *sky = sky_owner.get_or_null(p_env->sky); + ERR_FAIL_COND(!sky); + + GLES3::SkyMaterialData *material_data = nullptr; + RID sky_material; + + RS::EnvironmentBG background = p_env->background; + + if (sky) { + ERR_FAIL_COND(!sky); + sky_material = sky->material; + + if (sky_material.is_valid()) { + material_data = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY)); + if (!material_data || !material_data->shader_data->valid) { + material_data = nullptr; + } + } + + if (!material_data) { + sky_material = sky_globals.default_material; + material_data = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY)); + } + } else if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { + sky_material = sky_globals.fog_material; + material_data = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY)); + } + + ERR_FAIL_COND(!material_data); + material_data->bind_uniforms(); + + GLES3::SkyShaderData *shader_data = material_data->shader_data; + + ERR_FAIL_COND(!shader_data); // Camera CameraMatrix camera; - if (p_custom_fov) { + if (p_env->sky_custom_fov) { float near_plane = p_projection.get_z_near(); float far_plane = p_projection.get_z_far(); float aspect = p_projection.get_aspect(); - camera.set_perspective(p_custom_fov, aspect, near_plane, far_plane); - + camera.set_perspective(p_env->sky_custom_fov, aspect, near_plane, far_plane); } else { camera = p_projection; } + Basis sky_transform = p_env->sky_orientation; + sky_transform.invert(); + sky_transform = p_transform.basis * sky_transform; + + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, sky_transform, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.matrix[2][0], camera.matrix[0][0], camera.matrix[2][1], camera.matrix[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); + glBindVertexArray(sky_globals.screen_triangle_array); glDrawArrays(GL_TRIANGLES, 0, 3); } +void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform) { + GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); + ERR_FAIL_COND(!p_env); + + Sky *sky = sky_owner.get_or_null(p_env->sky); + ERR_FAIL_COND(!sky); + + GLES3::SkyMaterialData *material_data = nullptr; + RID sky_material; + + RS::EnvironmentBG background = p_env->background; + + if (sky) { + ERR_FAIL_COND(!sky); + sky_material = sky->material; + + if (sky_material.is_valid()) { + material_data = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY)); + if (!material_data || !material_data->shader_data->valid) { + material_data = nullptr; + } + } + + if (!material_data) { + sky_material = sky_globals.default_material; + material_data = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY)); + } + } else if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { + sky_material = sky_globals.fog_material; + material_data = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY)); + } + + ERR_FAIL_COND(!material_data); + material_data->bind_uniforms(); + + GLES3::SkyShaderData *shader_data = material_data->shader_data; + + ERR_FAIL_COND(!shader_data); + + bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY; + RS::SkyMode sky_mode = sky->mode; + + if (sky_mode == RS::SKY_MODE_AUTOMATIC) { + if (shader_data->uses_time || shader_data->uses_position) { + update_single_frame = true; + sky_mode = RS::SKY_MODE_REALTIME; + } else if (shader_data->uses_light || shader_data->ubo_size > 0) { + update_single_frame = false; + sky_mode = RS::SKY_MODE_INCREMENTAL; + } else { + update_single_frame = true; + sky_mode = RS::SKY_MODE_QUALITY; + } + } + + if (sky->processing_layer == 0 && sky_mode == RS::SKY_MODE_INCREMENTAL) { + // On the first frame after creating sky, rebuild in single frame + update_single_frame = true; + sky_mode = RS::SKY_MODE_QUALITY; + } + + int max_processing_layer = sky->mipmap_count; + + // Update radiance cubemap + if (sky->reflection_dirty && (sky->processing_layer >= max_processing_layer || update_single_frame)) { + static const Vector3 view_normals[6] = { + Vector3(+1, 0, 0), + Vector3(-1, 0, 0), + Vector3(0, +1, 0), + Vector3(0, -1, 0), + Vector3(0, 0, +1), + Vector3(0, 0, -1) + }; + static const Vector3 view_up[6] = { + Vector3(0, -1, 0), + Vector3(0, -1, 0), + Vector3(0, 0, +1), + Vector3(0, 0, -1), + Vector3(0, -1, 0), + Vector3(0, -1, 0) + }; + + CameraMatrix cm; + cm.set_perspective(90, 1, 0.01, 10.0); + CameraMatrix correction; + correction.set_depth_correction(true); + cm = correction * cm; + + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_CUBEMAP); + + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP); + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP); + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.matrix[2][0], cm.matrix[0][0], cm.matrix[2][1], cm.matrix[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP); + + // Bind a vertex array or else OpenGL complains. We won't actually use it + glBindVertexArray(sky_globals.screen_triangle_array); + + glViewport(0, 0, sky->radiance_size, sky->radiance_size); + glBindFramebuffer(GL_FRAMEBUFFER, sky->radiance_framebuffer); + + for (int i = 0; i < 6; i++) { + Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, local_view, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, sky->raw_radiance, 0); + glDrawArrays(GL_TRIANGLES, 0, 3); + } + + if (update_single_frame) { + for (int i = 0; i < max_processing_layer; i++) { + _filter_sky_radiance(sky, i); + } + } else { + _filter_sky_radiance(sky, 0); //Just copy over the first mipmap + } + sky->processing_layer = 1; + + sky->reflection_dirty = false; + } else { + if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) { + _filter_sky_radiance(sky, sky->processing_layer); + sky->processing_layer++; + } + } +} + +void RasterizerSceneGLES3::_filter_sky_radiance(Sky *p_sky, int p_base_layer) { + GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, p_sky->raw_radiance); + glBindFramebuffer(GL_FRAMEBUFFER, p_sky->radiance_framebuffer); + + CubemapFilterShaderGLES3::ShaderVariant mode = CubemapFilterShaderGLES3::MODE_DEFAULT; + + if (p_base_layer == 0) { + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + mode = CubemapFilterShaderGLES3::MODE_COPY; + + //Copy over base layer + } + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, sky_globals.radical_inverse_vdc_cache_tex); + + int size = p_sky->radiance_size >> p_base_layer; + glViewport(0, 0, size, size); + glBindVertexArray(sky_globals.screen_triangle_array); + + material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, mode); + material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::SAMPLE_COUNT, sky_globals.ggx_samples, scene_globals.cubemap_filter_shader_version, mode); + material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, float(p_base_layer) / (p_sky->mipmap_count - 1.0), scene_globals.cubemap_filter_shader_version, mode); + material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::FACE_SIZE, float(size), scene_globals.cubemap_filter_shader_version, mode); + + for (int i = 0; i < 6; i++) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, p_sky->radiance, p_base_layer); +#ifdef DEBUG_ENABLED + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); +#endif + material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::FACE_ID, i, scene_globals.cubemap_filter_shader_version, mode); + + glDrawArrays(GL_TRIANGLES, 0, 3); + } + glBindVertexArray(0); + glViewport(0, 0, p_sky->screen_size.x, p_sky->screen_size.y); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + Ref<Image> RasterizerSceneGLES3::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) { return Ref<Image>(); } @@ -498,13 +1331,29 @@ void RasterizerSceneGLES3::directional_shadow_quality_set(RS::ShadowQuality p_qu } RID RasterizerSceneGLES3::light_instance_create(RID p_light) { - return RID(); + RID li = light_instance_owner.make_rid(LightInstance()); + + LightInstance *light_instance = light_instance_owner.get_or_null(li); + + light_instance->self = li; + light_instance->light = p_light; + light_instance->light_type = RSG::light_storage->light_get_type(p_light); + + return li; } void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) { + LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); + ERR_FAIL_COND(!light_instance); + + light_instance->transform = p_transform; } void RasterizerSceneGLES3::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) { + LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); + ERR_FAIL_COND(!light_instance); + + light_instance->aabb = p_aabb; } void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { @@ -599,20 +1448,497 @@ void RasterizerSceneGLES3::voxel_gi_update(RID p_probe, bool p_update_light_inst void RasterizerSceneGLES3::voxel_gi_set_quality(RS::VoxelGIQuality) { } +void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append) { + GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton(); + + if (p_render_list == RENDER_LIST_OPAQUE) { + scene_state.used_screen_texture = false; + scene_state.used_normal_texture = false; + scene_state.used_depth_texture = false; + } + + Plane near_plane; + if (p_render_data->cam_orthogonal) { + near_plane = Plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin); + near_plane.d += p_render_data->cam_projection.get_z_near(); + } + float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near(); + + RenderList *rl = &render_list[p_render_list]; + + // Parse any updates on our geometry, updates surface caches and such + _update_dirty_geometry_instances(); + + if (!p_append) { + rl->clear(); + if (p_render_list == RENDER_LIST_OPAQUE) { + render_list[RENDER_LIST_ALPHA].clear(); //opaque fills alpha too + } + } + + //fill list + + for (int i = 0; i < (int)p_render_data->instances->size(); i++) { + GeometryInstanceGLES3 *inst = static_cast<GeometryInstanceGLES3 *>((*p_render_data->instances)[i]); + + if (p_render_data->cam_orthogonal) { + Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); + inst->depth = near_plane.distance_to(support_min); + } else { + Vector3 aabb_center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5); + inst->depth = p_render_data->cam_transform.origin.distance_to(aabb_center); + } + uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15); + + uint32_t flags = inst->base_flags; //fill flags if appropriate + + if (inst->non_uniform_scale) { + flags |= INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE; + } + + // Sets the index values for lookup in the shader + // This has to be done after _setup_lights was called this frame + // TODO, check shadow status of lights here, if using shadows, skip here and add below + if (p_pass_mode == PASS_MODE_COLOR) { + if (inst->omni_light_count) { + inst->omni_light_gl_cache.resize(inst->omni_light_count); + for (uint32_t j = 0; j < inst->omni_light_count; j++) { + inst->omni_light_gl_cache[j] = light_instance_get_gl_id(inst->omni_lights[j]); + } + } + if (inst->spot_light_count) { + inst->spot_light_gl_cache.resize(inst->spot_light_count); + for (uint32_t j = 0; j < inst->spot_light_count; j++) { + inst->spot_light_gl_cache[j] = light_instance_get_gl_id(inst->spot_lights[j]); + } + } + } + + inst->flags_cache = flags; + + GeometryInstanceSurface *surf = inst->surface_caches; + + while (surf) { + // LOD + + if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { + //lod + Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal); + Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal); + + float distance_min = p_render_data->lod_camera_plane.distance_to(lod_support_min); + float distance_max = p_render_data->lod_camera_plane.distance_to(lod_support_max); + + float distance = 0.0; + + if (distance_min * distance_max < 0.0) { + //crossing plane + distance = 0.0; + } else if (distance_min >= 0.0) { + distance = distance_min; + } else if (distance_max <= 0.0) { + distance = -distance_max; + } + + if (p_render_data->cam_orthogonal) { + distance = 1.0; + } + + uint32_t indices; + surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); + /* + if (p_render_data->render_info) { + indices = _indices_to_primitives(surf->primitive, indices); + if (p_render_list == RENDER_LIST_OPAQUE) { //opaque + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += indices; + } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += indices; + } + } + */ + } else { + surf->lod_index = 0; + /* + if (p_render_data->render_info) { + uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); + to_draw = _indices_to_primitives(surf->primitive, to_draw); + to_draw *= inst->instance_count; + if (p_render_list == RENDER_LIST_OPAQUE) { //opaque + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); + } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); + } + } + */ + } + + // ADD Element + if (p_pass_mode == PASS_MODE_COLOR) { +#ifdef DEBUG_ENABLED + bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW); +#else + bool force_alpha = false; +#endif + if (!force_alpha && (surf->flags & GeometryInstanceSurface::FLAG_PASS_OPAQUE)) { + rl->add_element(surf); + } + if (force_alpha || (surf->flags & GeometryInstanceSurface::FLAG_PASS_ALPHA)) { + render_list[RENDER_LIST_ALPHA].add_element(surf); + } + + if (surf->flags & GeometryInstanceSurface::FLAG_USES_SCREEN_TEXTURE) { + scene_state.used_screen_texture = true; + } + if (surf->flags & GeometryInstanceSurface::FLAG_USES_NORMAL_TEXTURE) { + scene_state.used_normal_texture = true; + } + if (surf->flags & GeometryInstanceSurface::FLAG_USES_DEPTH_TEXTURE) { + scene_state.used_depth_texture = true; + } + + /* + Add elements here if there are shadows + */ + + } else if (p_pass_mode == PASS_MODE_SHADOW) { + if (surf->flags & GeometryInstanceSurface::FLAG_PASS_SHADOW) { + rl->add_element(surf); + } + } else { + if (surf->flags & (GeometryInstanceSurface::FLAG_PASS_DEPTH | GeometryInstanceSurface::FLAG_PASS_OPAQUE)) { + rl->add_element(surf); + } + } + + surf->sort.depth_layer = depth_layer; + + surf = surf->next; + } + } +} + +// Needs to be called after _setup_lights so that directional_light_count is accurate. +void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows) { + CameraMatrix correction; + correction.set_depth_correction(p_flip_y); + CameraMatrix projection = correction * p_render_data->cam_projection; + //store camera into ubo + RasterizerStorageGLES3::store_camera(projection, scene_state.ubo.projection_matrix); + RasterizerStorageGLES3::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); + RasterizerStorageGLES3::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); + RasterizerStorageGLES3::store_transform(p_render_data->inv_cam_transform, scene_state.ubo.view_matrix); + + scene_state.ubo.directional_light_count = p_render_data->directional_light_count; + + scene_state.ubo.z_far = p_render_data->z_far; + scene_state.ubo.z_near = p_render_data->z_near; + + scene_state.ubo.viewport_size[0] = p_screen_size.x; + scene_state.ubo.viewport_size[1] = p_screen_size.y; + + Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size); + scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x; + scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y; + + //time global variables + scene_state.ubo.time = time; + + if (is_environment(p_render_data->environment)) { + Environment *env = environment_owner.get_or_null(p_render_data->environment); + RS::EnvironmentBG env_bg = env->background; + RS::EnvironmentAmbientSource ambient_src = env->ambient_source; + + float bg_energy = env->bg_energy; + scene_state.ubo.ambient_light_color_energy[3] = bg_energy; + + scene_state.ubo.ambient_color_sky_mix = env->ambient_sky_contribution; + + //ambient + if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) { + Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : env->bg_color; + color = color.srgb_to_linear(); + + scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; + scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy; + scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy; + scene_state.ubo.use_ambient_light = true; + scene_state.ubo.use_ambient_cubemap = false; + } else { + float energy = env->ambient_light_energy; + Color color = env->ambient_light; + color = color.srgb_to_linear(); + scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; + scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; + scene_state.ubo.ambient_light_color_energy[2] = color.b * energy; + + Basis sky_transform = env->sky_orientation; + sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis; + RasterizerStorageGLES3::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); + scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY; + scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR; + } + + //specular + RS::EnvironmentReflectionSource ref_src = env->reflection_source; + if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) { + scene_state.ubo.use_reflection_cubemap = true; + } else { + scene_state.ubo.use_reflection_cubemap = false; + } + + scene_state.ubo.fog_enabled = env->fog_enabled; + scene_state.ubo.fog_density = env->fog_density; + scene_state.ubo.fog_height = env->fog_height; + scene_state.ubo.fog_height_density = env->fog_height_density; + scene_state.ubo.fog_aerial_perspective = env->fog_aerial_perspective; + + Color fog_color = env->fog_light_color.srgb_to_linear(); + float fog_energy = env->fog_light_energy; + + scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; + scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy; + scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy; + + scene_state.ubo.fog_sun_scatter = env->fog_sun_scatter; + + } else { + } + + if (scene_state.ubo_buffer == 0) { + glGenBuffers(1, &scene_state.ubo_buffer); + } + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_DATA_UNIFORM_LOCATION, scene_state.ubo_buffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::UBO), &scene_state.ubo, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); +} + +// Puts lights into Uniform Buffers. Needs to be called before _fill_list as this caches the index of each light in the Uniform Buffer +void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_omni_light_count, uint32_t &r_spot_light_count) { + GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton(); + GLES3::Config *config = GLES3::Config::get_singleton(); + + const Transform3D inverse_transform = p_render_data->inv_cam_transform; + + const PagedArray<RID> &lights = *p_render_data->lights; + + r_directional_light_count = 0; + r_omni_light_count = 0; + r_spot_light_count = 0; + + int num_lights = lights.size(); + + for (int i = 0; i < num_lights; i++) { + LightInstance *li = light_instance_owner.get_or_null(lights[i]); + if (!li) { + continue; + } + RID base = li->light; + + ERR_CONTINUE(base.is_null()); + + RS::LightType type = light_storage->light_get_type(base); + switch (type) { + case RS::LIGHT_DIRECTIONAL: { + if (r_directional_light_count >= RendererSceneRender::MAX_DIRECTIONAL_LIGHTS || light_storage->light_directional_get_sky_mode(base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { + continue; + } + + DirectionalLightData &light_data = scene_state.directional_lights[r_directional_light_count]; + + Transform3D light_transform = li->transform; + + Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized(); + + light_data.direction[0] = direction.x; + light_data.direction[1] = direction.y; + light_data.direction[2] = direction.z; + + float sign = light_storage->light_is_negative(base) ? -1 : 1; + + light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI; + + Color linear_col = light_storage->light_get_color(base).srgb_to_linear(); + light_data.color[0] = linear_col.r; + light_data.color[1] = linear_col.g; + light_data.color[2] = linear_col.b; + + float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); + light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset + + light_data.specular = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR); + + r_directional_light_count++; + } break; + case RS::LIGHT_OMNI: { + if (r_omni_light_count >= (uint32_t)config->max_renderable_lights) { + continue; + } + + const real_t distance = p_render_data->cam_transform.origin.distance_to(li->transform.origin); + + if (light_storage->light_is_distance_fade_enabled(li->light)) { + const float fade_begin = light_storage->light_get_distance_fade_begin(li->light); + const float fade_length = light_storage->light_get_distance_fade_length(li->light); + + if (distance > fade_begin) { + if (distance > fade_begin + fade_length) { + // Out of range, don't draw this light to improve performance. + continue; + } + } + } + + li->gl_id = r_omni_light_count; + + scene_state.omni_light_sort[r_omni_light_count].instance = li; + scene_state.omni_light_sort[r_omni_light_count].depth = distance; + r_omni_light_count++; + } break; + case RS::LIGHT_SPOT: { + if (r_spot_light_count >= (uint32_t)config->max_renderable_lights) { + continue; + } + + const real_t distance = p_render_data->cam_transform.origin.distance_to(li->transform.origin); + + if (light_storage->light_is_distance_fade_enabled(li->light)) { + const float fade_begin = light_storage->light_get_distance_fade_begin(li->light); + const float fade_length = light_storage->light_get_distance_fade_length(li->light); + + if (distance > fade_begin) { + if (distance > fade_begin + fade_length) { + // Out of range, don't draw this light to improve performance. + continue; + } + } + } + + li->gl_id = r_spot_light_count; + + scene_state.spot_light_sort[r_spot_light_count].instance = li; + scene_state.spot_light_sort[r_spot_light_count].depth = distance; + r_spot_light_count++; + } break; + } + } + + if (r_omni_light_count) { + SortArray<InstanceSort<LightInstance>> sorter; + sorter.sort(scene_state.omni_light_sort, r_omni_light_count); + } + + if (r_spot_light_count) { + SortArray<InstanceSort<LightInstance>> sorter; + sorter.sort(scene_state.spot_light_sort, r_spot_light_count); + } + + for (uint32_t i = 0; i < (r_omni_light_count + r_spot_light_count); i++) { + uint32_t index = (i < r_omni_light_count) ? i : i - (r_omni_light_count); + LightData &light_data = (i < r_omni_light_count) ? scene_state.omni_lights[index] : scene_state.spot_lights[index]; + //RS::LightType type = (i < omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT; + LightInstance *li = (i < r_omni_light_count) ? scene_state.omni_light_sort[index].instance : scene_state.spot_light_sort[index].instance; + RID base = li->light; + + Transform3D light_transform = li->transform; + Vector3 pos = inverse_transform.xform(light_transform.origin); + + light_data.position[0] = pos.x; + light_data.position[1] = pos.y; + light_data.position[2] = pos.z; + + float radius = MAX(0.001, light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE)); + light_data.inv_radius = 1.0 / radius; + + Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized(); + + light_data.direction[0] = direction.x; + light_data.direction[1] = direction.y; + light_data.direction[2] = direction.z; + + float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); + + light_data.size = size; + + float sign = light_storage->light_is_negative(base) ? -1 : 1; + Color linear_col = light_storage->light_get_color(base).srgb_to_linear(); + + // Reuse fade begin, fade length and distance for shadow LOD determination later. + float fade_begin = 0.0; + float fade_length = 0.0; + real_t distance = 0.0; + + float fade = 1.0; + if (light_storage->light_is_distance_fade_enabled(li->light)) { + fade_begin = light_storage->light_get_distance_fade_begin(li->light); + fade_length = light_storage->light_get_distance_fade_length(li->light); + distance = p_render_data->cam_transform.origin.distance_to(li->transform.origin); + + if (distance > fade_begin) { + // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. + fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length); + } + } + + float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade; + + light_data.color[0] = linear_col.r * energy; + light_data.color[1] = linear_col.g * energy; + light_data.color[2] = linear_col.b * energy; + + light_data.attenuation = light_storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION); + + light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION); + + float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE); + light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle)); + + light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0; + + light_data.shadow_enabled = false; + } + + // TODO, to avoid stalls, should rotate between 3 buffers based on frame index. + // TODO, consider mapping the buffer as in 2D + if (r_omni_light_count) { + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_OMNILIGHT_UNIFORM_LOCATION, scene_state.omni_light_buffer); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightData) * r_omni_light_count, scene_state.omni_lights); + } + + if (r_spot_light_count) { + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_SPOTLIGHT_UNIFORM_LOCATION, scene_state.spot_light_buffer); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightData) * r_spot_light_count, scene_state.spot_lights); + } + + if (r_directional_light_count) { + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_DIRECTIONAL_LIGHT_UNIFORM_LOCATION, scene_state.directional_light_buffer); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(DirectionalLightData) * r_directional_light_count, scene_state.directional_lights); + } + glBindBuffer(GL_UNIFORM_BUFFER, 0); +} + void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); + GLES3::Config *config = GLES3::Config::get_singleton(); RENDER_TIMESTAMP("Setup 3D Scene"); - // assign render data + + RenderBuffers *rb = nullptr; + if (p_render_buffers.is_valid()) { + rb = render_buffers_owner.get_or_null(p_render_buffers); + ERR_FAIL_COND(!rb); + } + + // Assign render data // Use the format from rendererRD RenderDataGLES3 render_data; { render_data.render_buffers = p_render_buffers; - + render_data.transparent_bg = rb->is_transparent; // Our first camera is used by default render_data.cam_transform = p_camera_data->main_transform; + render_data.inv_cam_transform = render_data.cam_transform.affine_inverse(); render_data.cam_projection = p_camera_data->main_projection; render_data.view_projection[0] = p_camera_data->main_projection; - render_data.cam_ortogonal = p_camera_data->is_orthogonal; + render_data.cam_orthogonal = p_camera_data->is_orthogonal; render_data.view_count = p_camera_data->view_count; for (uint32_t v = 0; v < p_camera_data->view_count; v++) { @@ -625,14 +1951,8 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * render_data.instances = &p_instances; render_data.lights = &p_lights; render_data.reflection_probes = &p_reflection_probes; - //render_data.voxel_gi_instances = &p_voxel_gi_instances; - //render_data.decals = &p_decals; - //render_data.lightmaps = &p_lightmaps; - //render_data.fog_volumes = &p_fog_volumes; render_data.environment = p_environment; render_data.camera_effects = p_camera_effects; - render_data.shadow_atlas = p_shadow_atlas; - render_data.reflection_atlas = p_reflection_atlas; render_data.reflection_probe = p_reflection_probe; render_data.reflection_probe_pass = p_reflection_probe_pass; @@ -655,14 +1975,14 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * render_data.reflection_probes = ∅ } - RenderBuffers *rb = nullptr; - //RasterizerStorageGLES3::RenderTarget *rt = nullptr; - if (p_render_buffers.is_valid()) { - rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); - //rt = texture_storage->render_target_owner.get_or_null(rb->render_target); - //ERR_FAIL_COND(!rt); - } + bool reverse_cull = false; + + /////////// + // Fill Light lists here + ////////// + + GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_variables_get_uniform_buffer(); + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer); Color clear_color; if (p_render_buffers.is_valid()) { @@ -675,39 +1995,61 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * bool fb_cleared = false; - glDepthFunc(GL_LEQUAL); + Size2i screen_size; + screen_size.x = rb->width; + screen_size.y = rb->height; - /* Depth Prepass */ + bool use_wireframe = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME; - glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer); + SceneState::TonemapUBO tonemap_ubo; + if (env) { + tonemap_ubo.exposure = env->exposure; + tonemap_ubo.white = env->white; + tonemap_ubo.tonemapper = int32_t(env->tone_mapper); + } - if (!fb_cleared) { - glClearDepth(1.0f); - glClear(GL_DEPTH_BUFFER_BIT); + if (scene_state.tonemap_buffer == 0) { + // Only create if using 3D + glGenBuffers(1, &scene_state.tonemap_buffer); } + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_TONEMAP_UNIFORM_LOCATION, scene_state.tonemap_buffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::TonemapUBO), &tonemap_ubo, GL_STREAM_DRAW); + + _setup_lights(&render_data, false, render_data.directional_light_count, render_data.omni_light_count, render_data.spot_light_count); + _setup_environment(&render_data, render_data.reflection_probe.is_valid(), screen_size, !render_data.reflection_probe.is_valid(), clear_color, false); + + _fill_render_list(RENDER_LIST_OPAQUE, &render_data, PASS_MODE_COLOR); + render_list[RENDER_LIST_OPAQUE].sort_by_key(); + render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority(); bool draw_sky = false; + bool draw_sky_fog_only = false; bool keep_color = false; if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { - clear_color = Color(0, 0, 0, 1); - } - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black - } else if (is_environment(p_environment)) { - RS::EnvironmentBG bg_mode = environment_get_background(p_environment); - float bg_energy = env->bg_energy; //environment_get_bg_energy(p_environment); + } else if (env) { + RS::EnvironmentBG bg_mode = env->background; + float bg_energy = env->bg_energy; switch (bg_mode) { case RS::ENV_BG_CLEAR_COLOR: { clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; + if (env->fog_enabled) { + draw_sky_fog_only = true; + GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color)); + } } break; case RS::ENV_BG_COLOR: { - clear_color = env->bg_color; //environment_get_bg_color(p_environment); + clear_color = env->bg_color; clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; + if (env->fog_enabled) { + draw_sky_fog_only = true; + GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color)); + } } break; case RS::ENV_BG_SKY: { draw_sky = true; @@ -723,27 +2065,401 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * default: { } } + // setup sky if used for ambient, reflections, or background + if (draw_sky || draw_sky_fog_only || env->reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || env->ambient_source == RS::ENV_AMBIENT_SOURCE_SKY) { + RENDER_TIMESTAMP("Setup Sky"); + CameraMatrix projection = render_data.cam_projection; + if (render_data.reflection_probe.is_valid()) { + CameraMatrix correction; + correction.set_depth_correction(true); + projection = correction * render_data.cam_projection; + } + + _setup_sky(env, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size); + + if (env->sky.is_valid()) { + if (env->reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || env->ambient_source == RS::ENV_AMBIENT_SOURCE_SKY || (env->reflection_source == RS::ENV_REFLECTION_SOURCE_BG && env->background == RS::ENV_BG_SKY)) { + _update_sky_radiance(env, projection, render_data.cam_transform); + } + } else { + // do not try to draw sky if invalid + draw_sky = false; + } + } + } + + glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer); + glViewport(0, 0, rb->width, rb->height); + + // Do depth prepass if it's explicitly enabled + bool use_depth_prepass = config->use_depth_prepass; + + // Don't do depth prepass we are rendering overdraw + use_depth_prepass = use_depth_prepass && get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_OVERDRAW; + + if (use_depth_prepass) { + RENDER_TIMESTAMP("Depth Prepass"); + //pre z pass + + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glDisable(GL_SCISSOR_TEST); + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); + scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK; + + glColorMask(0, 0, 0, 0); + glClearDepth(1.0f); + glClear(GL_DEPTH_BUFFER_BIT); + + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, 0, use_wireframe); + _render_list_template<PASS_MODE_DEPTH>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_OPAQUE].elements.size()); + + glColorMask(1, 1, 1, 1); + + fb_cleared = true; + scene_state.used_depth_prepass = true; + } else { + scene_state.used_depth_prepass = false; + } + + glBlendEquation(GL_FUNC_ADD); + + if (render_data.transparent_bg) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + } else { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); + glDisable(GL_BLEND); + } + scene_state.current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX; + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glDepthMask(GL_TRUE); + scene_state.current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_ENABLED; + scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE; + + if (!fb_cleared) { + glClearDepth(1.0f); + glClear(GL_DEPTH_BUFFER_BIT); } if (!keep_color) { glClearBufferfv(GL_COLOR, 0, clear_color.components); } + RENDER_TIMESTAMP("Render Opaque Pass"); + uint32_t spec_constant_base_flags = 0; + + { + // Specialization Constants that apply for entire rendering pass. + if (render_data.directional_light_count == 0) { + spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS; + } + + if (!env || (env && !env->fog_enabled)) { + spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG; + } + } + // Render Opaque Objects. + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, spec_constant_base_flags, use_wireframe); + + _render_list_template<PASS_MODE_COLOR>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_OPAQUE].elements.size()); if (draw_sky) { - //_draw_sky(sky, render_data.cam_projection, render_data.cam_transform, env->sky_custom_fov, env->bg_energy, env->sky_orientation); + RENDER_TIMESTAMP("Render Sky"); + if (scene_state.current_depth_test != GLES3::SceneShaderData::DEPTH_TEST_ENABLED) { + glEnable(GL_DEPTH_TEST); + scene_state.current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_ENABLED; + } + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_BLEND); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + scene_state.current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_ENABLED; + scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_DISABLED; + scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK; + + _draw_sky(env, render_data.cam_projection, render_data.cam_transform); } - if (p_render_buffers.is_valid()) { - /* - RENDER_TIMESTAMP("Tonemap"); - _render_buffers_post_process_and_tonemap(&render_data); - */ + RENDER_TIMESTAMP("Render 3D Transparent Pass"); + glEnable(GL_BLEND); + + //Render transparent pass + RenderListParameters render_list_params_alpha(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, spec_constant_base_flags, use_wireframe); + + _render_list_template<PASS_MODE_COLOR_TRANSPARENT>(&render_list_params_alpha, &render_data, 0, render_list[RENDER_LIST_ALPHA].elements.size(), true); + if (p_render_buffers.is_valid()) { _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex); } + glDisable(GL_BLEND); texture_storage->render_target_disable_clear_request(rb->render_target); } +template <PassMode p_pass_mode> +void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, const RenderDataGLES3 *p_render_data, uint32_t p_from_element, uint32_t p_to_element, bool p_alpha_pass) { + GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton(); + GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); + GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); + GLES3::Config *config = GLES3::Config::get_singleton(); + + GLuint prev_vertex_array_gl = 0; + GLuint prev_index_array_gl = 0; + + GLES3::SceneMaterialData *prev_material_data = nullptr; + GLES3::SceneShaderData *prev_shader = nullptr; + GeometryInstanceGLES3 *prev_inst = nullptr; + + SceneShaderGLES3::ShaderVariant shader_variant = SceneShaderGLES3::MODE_COLOR; // Assigned to silence wrong -Wmaybe-initialized. + + switch (p_pass_mode) { + case PASS_MODE_COLOR: + case PASS_MODE_COLOR_TRANSPARENT: { + } break; + case PASS_MODE_COLOR_ADDITIVE: { + shader_variant = SceneShaderGLES3::MODE_ADDITIVE; + } break; + case PASS_MODE_SHADOW: + case PASS_MODE_DEPTH: { + shader_variant = SceneShaderGLES3::MODE_DEPTH; + } break; + } + + if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) { + Environment *env = environment_owner.get_or_null(p_render_data->environment); + glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 2); + GLuint texture_to_bind = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_CUBEMAP_BLACK))->tex_id; + if (env) { + Sky *sky = sky_owner.get_or_null(env->sky); + if (sky && sky->radiance != 0) { + texture_to_bind = sky->radiance; + // base_spec_constant |= USE_RADIANCE_MAP; + } + glBindTexture(GL_TEXTURE_CUBE_MAP, texture_to_bind); + } + } + + for (uint32_t i = p_from_element; i < p_to_element; i++) { + const GeometryInstanceSurface *surf = p_params->elements[i]; + GeometryInstanceGLES3 *inst = surf->owner; + + if (p_pass_mode == PASS_MODE_COLOR && !(surf->flags & GeometryInstanceSurface::FLAG_PASS_OPAQUE)) { + continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass + } + + if (inst->instance_count == 0) { + continue; + } + + //uint32_t base_spec_constants = p_params->spec_constant_base_flags; + + GLES3::SceneShaderData *shader; + GLES3::SceneMaterialData *material_data; + void *mesh_surface; + + if (p_pass_mode == PASS_MODE_SHADOW) { + shader = surf->shader_shadow; + material_data = surf->material_shadow; + mesh_surface = surf->surface_shadow; + } else { + shader = surf->shader; + material_data = surf->material; + mesh_surface = surf->surface; + } + + if (!mesh_surface) { + continue; + } + + if (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) { + if (scene_state.current_depth_test != shader->depth_test) { + if (shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED) { + glDisable(GL_DEPTH_TEST); + } else { + glEnable(GL_DEPTH_TEST); + } + scene_state.current_depth_test = shader->depth_test; + } + } + + if (scene_state.current_depth_draw != shader->depth_draw) { + switch (shader->depth_draw) { + case GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE: { + glDepthMask(p_pass_mode == PASS_MODE_COLOR); + } break; + case GLES3::SceneShaderData::DEPTH_DRAW_ALWAYS: { + glDepthMask(GL_TRUE); + } break; + case GLES3::SceneShaderData::DEPTH_DRAW_DISABLED: { + glDepthMask(GL_FALSE); + } break; + } + + scene_state.current_depth_draw = shader->depth_draw; + } + + if (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_ADDITIVE) { + GLES3::SceneShaderData::BlendMode desired_blend_mode; + if (p_pass_mode == PASS_MODE_COLOR_ADDITIVE) { + desired_blend_mode = GLES3::SceneShaderData::BLEND_MODE_ADD; + } else { + desired_blend_mode = shader->blend_mode; + } + + if (desired_blend_mode != scene_state.current_blend_mode) { + switch (desired_blend_mode) { + case GLES3::SceneShaderData::BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + if (p_render_data->transparent_bg) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); + } + + } break; + case GLES3::SceneShaderData::BLEND_MODE_ADD: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(p_pass_mode == PASS_MODE_COLOR_TRANSPARENT ? GL_SRC_ALPHA : GL_ONE, GL_ONE); + + } break; + case GLES3::SceneShaderData::BLEND_MODE_SUB: { + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + } break; + case GLES3::SceneShaderData::BLEND_MODE_MUL: { + glBlendEquation(GL_FUNC_ADD); + if (p_render_data->transparent_bg) { + glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO); + } else { + glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE); + } + + } break; + case GLES3::SceneShaderData::BLEND_MODE_ALPHA_TO_COVERAGE: { + // Do nothing for now. + } break; + } + scene_state.current_blend_mode = desired_blend_mode; + } + } + + //find cull variant + GLES3::SceneShaderData::Cull cull_mode = shader->cull_mode; + + if ((surf->flags & GeometryInstanceSurface::FLAG_USES_DOUBLE_SIDED_SHADOWS)) { + cull_mode = GLES3::SceneShaderData::CULL_DISABLED; + } else { + bool mirror = inst->mirror; + if (p_params->reverse_cull) { + mirror = !mirror; + } + if (cull_mode == GLES3::SceneShaderData::CULL_FRONT && mirror) { + cull_mode = GLES3::SceneShaderData::CULL_BACK; + } else if (cull_mode == GLES3::SceneShaderData::CULL_BACK && mirror) { + cull_mode = GLES3::SceneShaderData::CULL_FRONT; + } + } + + if (scene_state.cull_mode != cull_mode) { + if (cull_mode == GLES3::SceneShaderData::CULL_DISABLED) { + glDisable(GL_CULL_FACE); + } else { + if (scene_state.cull_mode == GLES3::SceneShaderData::CULL_DISABLED) { + // Last time was disabled, so enable and set proper face. + glEnable(GL_CULL_FACE); + } + glCullFace(cull_mode == GLES3::SceneShaderData::CULL_FRONT ? GL_FRONT : GL_BACK); + } + scene_state.cull_mode = cull_mode; + } + + RS::PrimitiveType primitive = surf->primitive; + static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP }; + GLenum primitive_gl = prim[int(primitive)]; + + GLuint vertex_array_gl = 0; + GLuint index_array_gl = 0; + + //skeleton and blend shape + if (surf->owner->mesh_instance.is_valid()) { + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, shader->vertex_input_mask, vertex_array_gl); + } else { + mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, shader->vertex_input_mask, vertex_array_gl); + } + + index_array_gl = mesh_storage->mesh_surface_get_index_buffer(mesh_surface, surf->lod_index); + + if (prev_vertex_array_gl != vertex_array_gl) { + glBindVertexArray(vertex_array_gl); + prev_vertex_array_gl = vertex_array_gl; + } + + bool use_index_buffer = false; + if (prev_index_array_gl != index_array_gl) { + if (index_array_gl != 0) { + // Bind index each time so we can use LODs + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_gl); + use_index_buffer = true; + } + prev_index_array_gl = index_array_gl; + } + + Transform3D world_transform; + if (inst->store_transform_cache) { + world_transform = inst->transform; + } + + if (prev_material_data != material_data) { + material_data->bind_uniforms(); + prev_material_data = material_data; + } + + if (prev_shader != shader) { + material_storage->shaders.scene_shader.version_bind_shader(shader->version, shader_variant); + float opaque_prepass_threshold = 0.0; + if (p_pass_mode == PASS_MODE_DEPTH) { + opaque_prepass_threshold = 0.99; + } else if (p_pass_mode == PASS_MODE_SHADOW) { + opaque_prepass_threshold = 0.1; + } + + material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, shader_variant); + + prev_shader = shader; + } + + if (prev_inst != inst) { + // Rebind the light indices. + material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, inst->omni_light_count, shader->version, shader_variant); + material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_count, shader->version, shader_variant); + + if (inst->omni_light_count) { + glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES, shader->version, shader_variant), inst->omni_light_count, inst->omni_light_gl_cache.ptr()); + } + + if (inst->spot_light_count) { + glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES, shader->version, shader_variant), inst->spot_light_count, inst->spot_light_gl_cache.ptr()); + } + + prev_inst = inst; + } + + material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, shader_variant); + + if (use_index_buffer) { + glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), mesh_storage->mesh_surface_get_index_type(mesh_surface), 0); + } else { + glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface)); + } + } +} + void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { } @@ -879,6 +2595,8 @@ void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_ GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target); + rb->is_transparent = rt->flags[RendererTextureStorage::RENDER_TARGET_TRANSPARENT]; + // framebuffer glGenFramebuffers(1, &rb->framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer); @@ -975,7 +2693,7 @@ bool RasterizerSceneGLES3::free(RID p_rid) { } else if (sky_owner.owns(p_rid)) { Sky *sky = sky_owner.get_or_null(p_rid); ERR_FAIL_COND_V(!sky, false); - sky->free(); + _free_sky_data(sky); sky_owner.free(p_rid); } else if (render_buffers_owner.owns(p_rid)) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_rid); @@ -983,6 +2701,10 @@ bool RasterizerSceneGLES3::free(RID p_rid) { _free_render_buffer_data(rb); render_buffers_owner.free(p_rid); + } else if (light_instance_owner.owns(p_rid)) { + LightInstance *light_instance = light_instance_owner.get_or_null(p_rid); + ERR_FAIL_COND_V(!light_instance, false); + light_instance_owner.free(p_rid); } else { return false; } @@ -1004,9 +2726,85 @@ void RasterizerSceneGLES3::light_projectors_set_filter(RS::LightProjectorFilter RasterizerSceneGLES3::RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage) { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); + GLES3::Config *config = GLES3::Config::get_singleton(); + storage = p_storage; { + // Setup Lights + + config->max_renderable_lights = MIN(config->max_renderable_lights, config->max_uniform_buffer_size / (int)sizeof(RasterizerSceneGLES3::LightData)); + config->max_lights_per_object = MIN(config->max_lights_per_object, config->max_renderable_lights); + + uint32_t light_buffer_size = config->max_renderable_lights * sizeof(LightData); + scene_state.omni_lights = memnew_arr(LightData, config->max_renderable_lights); + scene_state.omni_light_sort = memnew_arr(InstanceSort<LightInstance>, config->max_renderable_lights); + glGenBuffers(1, &scene_state.omni_light_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, scene_state.omni_light_buffer); + glBufferData(GL_UNIFORM_BUFFER, light_buffer_size, nullptr, GL_STREAM_DRAW); + + scene_state.spot_lights = memnew_arr(LightData, config->max_renderable_lights); + scene_state.spot_light_sort = memnew_arr(InstanceSort<LightInstance>, config->max_renderable_lights); + glGenBuffers(1, &scene_state.spot_light_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, scene_state.spot_light_buffer); + glBufferData(GL_UNIFORM_BUFFER, light_buffer_size, nullptr, GL_STREAM_DRAW); + + uint32_t directional_light_buffer_size = MAX_DIRECTIONAL_LIGHTS * sizeof(DirectionalLightData); + scene_state.directional_lights = memnew_arr(DirectionalLightData, MAX_DIRECTIONAL_LIGHTS); + glGenBuffers(1, &scene_state.directional_light_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, scene_state.directional_light_buffer); + glBufferData(GL_UNIFORM_BUFFER, directional_light_buffer_size, nullptr, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + { + sky_globals.max_directional_lights = 4; + uint32_t directional_light_buffer_size = sky_globals.max_directional_lights * sizeof(DirectionalLightData); + sky_globals.directional_lights = memnew_arr(DirectionalLightData, sky_globals.max_directional_lights); + sky_globals.last_frame_directional_lights = memnew_arr(DirectionalLightData, sky_globals.max_directional_lights); + sky_globals.last_frame_directional_light_count = sky_globals.max_directional_lights + 1; + glGenBuffers(1, &sky_globals.directional_light_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, sky_globals.directional_light_buffer); + glBufferData(GL_UNIFORM_BUFFER, directional_light_buffer_size, nullptr, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + { + String global_defines; + global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now + global_defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(config->max_renderable_lights) + "\n"; + global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n"; + global_defines += "\n#define MAX_FORWARD_LIGHTS " + itos(config->max_lights_per_object) + "\n"; + material_storage->shaders.scene_shader.initialize(global_defines); + scene_globals.shader_default_version = material_storage->shaders.scene_shader.version_create(); + material_storage->shaders.scene_shader.version_bind_shader(scene_globals.shader_default_version, SceneShaderGLES3::MODE_COLOR); + } + + { + //default material and shader + scene_globals.default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(scene_globals.default_shader); + material_storage->shader_set_code(scene_globals.default_shader, R"( +// Default 3D material shader (clustered). + +shader_type spatial; + +void vertex() { + ROUGHNESS = 0.8; +} + +void fragment() { + ALBEDO = vec3(0.6); + ROUGHNESS = 0.8; + METALLIC = 0.2; +} +)"); + scene_globals.default_material = material_storage->material_allocate(); + material_storage->material_initialize(scene_globals.default_material); + material_storage->material_set_shader(scene_globals.default_material, scene_globals.default_shader); + } + + { // Initialize Sky stuff sky_globals.roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers"); sky_globals.ggx_samples = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples"); @@ -1014,9 +2812,13 @@ RasterizerSceneGLES3::RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage) { String global_defines; global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_globals.max_directional_lights) + "\n"; - state.sky_shader.initialize(global_defines); - sky_globals.shader_default_version = state.sky_shader.version_create(); - state.sky_shader.version_bind_shader(sky_globals.shader_default_version, SkyShaderGLES3::MODE_BACKGROUND); + material_storage->shaders.sky_shader.initialize(global_defines); + sky_globals.shader_default_version = material_storage->shaders.sky_shader.version_create(); + material_storage->shaders.sky_shader.version_bind_shader(sky_globals.shader_default_version, SkyShaderGLES3::MODE_BACKGROUND); + + material_storage->shaders.cubemap_filter_shader.initialize(); + scene_globals.cubemap_filter_shader_version = material_storage->shaders.cubemap_filter_shader.version_create(); + material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, CubemapFilterShaderGLES3::MODE_DEFAULT); } { @@ -1038,12 +2840,115 @@ void sky() { material_storage->material_set_shader(sky_globals.default_material, sky_globals.default_shader); } + { + sky_globals.fog_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(sky_globals.fog_shader); + + material_storage->shader_set_code(sky_globals.fog_shader, R"( +// Default clear color sky shader. + +shader_type sky; + +uniform vec4 clear_color; + +void sky() { + COLOR = clear_color.rgb; +} +)"); + sky_globals.fog_material = material_storage->material_allocate(); + material_storage->material_initialize(sky_globals.fog_material); + + material_storage->material_set_shader(sky_globals.fog_material, sky_globals.fog_shader); + } + + { + glGenBuffers(1, &sky_globals.screen_triangle); + glBindBuffer(GL_ARRAY_BUFFER, sky_globals.screen_triangle); + + const float qv[6] = { + -1.0f, + -1.0f, + 3.0f, + -1.0f, + -1.0f, + 3.0f, + }; + + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, qv, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + + glGenVertexArrays(1, &sky_globals.screen_triangle_array); + glBindVertexArray(sky_globals.screen_triangle_array); + glBindBuffer(GL_ARRAY_BUFFER, sky_globals.screen_triangle); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, nullptr); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + } + + // Radical inverse vdc cache texture used for cubemap filtering. + { + glGenTextures(1, &sky_globals.radical_inverse_vdc_cache_tex); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, sky_globals.radical_inverse_vdc_cache_tex); + + uint8_t radical_inverse[512]; + + for (uint32_t i = 0; i < 512; i++) { + uint32_t bits = i; + + bits = (bits << 16) | (bits >> 16); + bits = ((bits & 0x55555555) << 1) | ((bits & 0xAAAAAAAA) >> 1); + bits = ((bits & 0x33333333) << 2) | ((bits & 0xCCCCCCCC) >> 2); + bits = ((bits & 0x0F0F0F0F) << 4) | ((bits & 0xF0F0F0F0) >> 4); + bits = ((bits & 0x00FF00FF) << 8) | ((bits & 0xFF00FF00) >> 8); + + float value = float(bits) * 2.3283064365386963e-10; + radical_inverse[i] = uint8_t(CLAMP(value * 255.0, 0, 255)); + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 512, 1, 0, GL_RED, GL_UNSIGNED_BYTE, radical_inverse); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //need this for proper sampling + + glBindTexture(GL_TEXTURE_2D, 0); + } +#ifdef GLES_OVER_GL + glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); +#endif } RasterizerSceneGLES3::~RasterizerSceneGLES3() { - state.sky_shader.version_free(sky_globals.shader_default_version); + glDeleteBuffers(1, &scene_state.directional_light_buffer); + glDeleteBuffers(1, &scene_state.omni_light_buffer); + glDeleteBuffers(1, &scene_state.spot_light_buffer); + memdelete_arr(scene_state.directional_lights); + memdelete_arr(scene_state.omni_lights); + memdelete_arr(scene_state.spot_lights); + memdelete_arr(scene_state.omni_light_sort); + memdelete_arr(scene_state.spot_light_sort); + + // Scene Shader + GLES3::MaterialStorage::get_singleton()->shaders.scene_shader.version_free(scene_globals.shader_default_version); + GLES3::MaterialStorage::get_singleton()->shaders.cubemap_filter_shader.version_free(scene_globals.cubemap_filter_shader_version); + storage->free(scene_globals.default_material); + storage->free(scene_globals.default_shader); + + // Sky Shader + GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_free(sky_globals.shader_default_version); storage->free(sky_globals.default_material); storage->free(sky_globals.default_shader); + storage->free(sky_globals.fog_material); + storage->free(sky_globals.fog_shader); + glDeleteBuffers(1, &sky_globals.screen_triangle); + glDeleteVertexArrays(1, &sky_globals.screen_triangle_array); + glDeleteTextures(1, &sky_globals.radical_inverse_vdc_cache_tex); + glDeleteBuffers(1, &sky_globals.directional_light_buffer); + memdelete_arr(sky_globals.directional_lights); + memdelete_arr(sky_globals.last_frame_directional_lights); } #endif // GLES3_ENABLED diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index ed529beb25..d9a848c0f6 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -34,6 +34,7 @@ #ifdef GLES3_ENABLED #include "core/math/camera_matrix.h" +#include "core/templates/paged_allocator.h" #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" #include "rasterizer_storage_gles3.h" @@ -42,15 +43,60 @@ #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering_server.h" #include "shader_gles3.h" +#include "shaders/cubemap_filter.glsl.gen.h" #include "shaders/sky.glsl.gen.h" -// Copied from renderer_scene_render_rd +enum RenderListType { + RENDER_LIST_OPAQUE, //used for opaque objects + RENDER_LIST_ALPHA, //used for transparent objects + RENDER_LIST_SECONDARY, //used for shadows and other objects + RENDER_LIST_MAX +}; + +enum PassMode { + PASS_MODE_COLOR, + PASS_MODE_COLOR_TRANSPARENT, + PASS_MODE_COLOR_ADDITIVE, + PASS_MODE_SHADOW, + PASS_MODE_DEPTH, +}; + +// These should share as much as possible with SkyUniform Location +enum SceneUniformLocation { + SCENE_TONEMAP_UNIFORM_LOCATION, + SCENE_GLOBALS_UNIFORM_LOCATION, + SCENE_DATA_UNIFORM_LOCATION, + SCENE_MATERIAL_UNIFORM_LOCATION, + SCENE_EMPTY, // Unused, put here to avoid conflicts with SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION. + SCENE_OMNILIGHT_UNIFORM_LOCATION, + SCENE_SPOTLIGHT_UNIFORM_LOCATION, + SCENE_DIRECTIONAL_LIGHT_UNIFORM_LOCATION, +}; + +enum SkyUniformLocation { + SKY_TONEMAP_UNIFORM_LOCATION, + SKY_GLOBALS_UNIFORM_LOCATION, + SKY_EMPTY, // Unused, put here to avoid conflicts with SCENE_DATA_UNIFORM_LOCATION. + SKY_MATERIAL_UNIFORM_LOCATION, + SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION, +}; + +enum { + SPEC_CONSTANT_DISABLE_LIGHTMAP = 0, + SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS = 1, + SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 2, + SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 3, + SPEC_CONSTANT_DISABLE_FOG = 4, +}; + struct RenderDataGLES3 { RID render_buffers = RID(); + bool transparent_bg = false; Transform3D cam_transform = Transform3D(); + Transform3D inv_cam_transform = Transform3D(); CameraMatrix cam_projection = CameraMatrix(); - bool cam_ortogonal = false; + bool cam_orthogonal = false; // For stereo rendering uint32_t view_count = 1; @@ -62,14 +108,8 @@ struct RenderDataGLES3 { const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr; const PagedArray<RID> *lights = nullptr; const PagedArray<RID> *reflection_probes = nullptr; - //const PagedArray<RID> *voxel_gi_instances = nullptr; - //const PagedArray<RID> *decals = nullptr; - //const PagedArray<RID> *lightmaps = nullptr; - //const PagedArray<RID> *fog_volumes = nullptr; RID environment = RID(); RID camera_effects = RID(); - RID shadow_atlas = RID(); - RID reflection_atlas = RID(); RID reflection_probe = RID(); int reflection_probe_pass = 0; @@ -78,6 +118,8 @@ struct RenderDataGLES3 { float screen_mesh_lod_threshold = 0.0; uint32_t directional_light_count = 0; + uint32_t spot_light_count = 0; + uint32_t omni_light_count = 0; RendererScene::RenderInfo *render_info = nullptr; }; @@ -91,16 +133,388 @@ private: RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; uint64_t scene_pass = 0; - /* Sky */ - struct SkyGlobals { - RID shader_current_version; + template <class T> + struct InstanceSort { + float depth; + T *instance = nullptr; + bool operator<(const InstanceSort &p_sort) const { + return depth < p_sort.depth; + } + }; + + struct SceneGlobals { RID shader_default_version; RID default_material; RID default_shader; - uint32_t max_directional_lights = 4; - uint32_t roughness_layers = 8; - uint32_t ggx_samples = 128; - } sky_globals; + RID cubemap_filter_shader_version; + } scene_globals; + + /* LIGHT INSTANCE */ + + struct LightData { + float position[3]; + float inv_radius; + + float direction[3]; // Only used by SpotLight + float size; + + float color[3]; + float attenuation; + + float inv_spot_attenuation; + float cos_spot_angle; + float specular_amount; + uint32_t shadow_enabled; + }; + static_assert(sizeof(LightData) % 16 == 0, "LightData size must be a multiple of 16 bytes"); + + struct DirectionalLightData { + float direction[3]; + float energy; + + float color[3]; + float size; + + uint32_t enabled; // For use by SkyShaders + float pad[2]; + float specular; + }; + static_assert(sizeof(DirectionalLightData) % 16 == 0, "DirectionalLightData size must be a multiple of 16 bytes"); + + struct LightInstance { + RS::LightType light_type = RS::LIGHT_DIRECTIONAL; + + AABB aabb; + RID self; + RID light; + Transform3D transform; + + Vector3 light_vector; + Vector3 spot_vector; + float linear_att = 0.0; + + uint64_t shadow_pass = 0; + uint64_t last_scene_pass = 0; + uint64_t last_scene_shadow_pass = 0; + uint64_t last_pass = 0; + uint32_t cull_mask = 0; + uint32_t light_directional_index = 0; + + Rect2 directional_rect; + + uint32_t gl_id = -1; + + LightInstance() {} + }; + + mutable RID_Owner<LightInstance> light_instance_owner; + + struct GeometryInstanceGLES3; + + // Cached data for drawing surfaces + struct GeometryInstanceSurface { + enum { + FLAG_PASS_DEPTH = 1, + FLAG_PASS_OPAQUE = 2, + FLAG_PASS_ALPHA = 4, + FLAG_PASS_SHADOW = 8, + FLAG_USES_SHARED_SHADOW_MATERIAL = 128, + FLAG_USES_SCREEN_TEXTURE = 2048, + FLAG_USES_DEPTH_TEXTURE = 4096, + FLAG_USES_NORMAL_TEXTURE = 8192, + FLAG_USES_DOUBLE_SIDED_SHADOWS = 16384, + }; + + union { + struct { + uint64_t lod_index : 8; + uint64_t surface_index : 8; + uint64_t geometry_id : 32; + uint64_t material_id_low : 16; + + uint64_t material_id_hi : 16; + uint64_t shader_id : 32; + uint64_t uses_softshadow : 1; + uint64_t uses_projector : 1; + uint64_t uses_forward_gi : 1; + uint64_t uses_lightmap : 1; + uint64_t depth_layer : 4; + uint64_t priority : 8; + }; + struct { + uint64_t sort_key1; + uint64_t sort_key2; + }; + } sort; + + RS::PrimitiveType primitive = RS::PRIMITIVE_MAX; + uint32_t flags = 0; + uint32_t surface_index = 0; + uint32_t lod_index = 0; + + void *surface = nullptr; + GLES3::SceneShaderData *shader = nullptr; + GLES3::SceneMaterialData *material = nullptr; + + void *surface_shadow = nullptr; + GLES3::SceneShaderData *shader_shadow = nullptr; + GLES3::SceneMaterialData *material_shadow = nullptr; + + GeometryInstanceSurface *next = nullptr; + GeometryInstanceGLES3 *owner = nullptr; + }; + + struct GeometryInstanceGLES3 : public GeometryInstance { + //used during rendering + bool mirror = false; + bool non_uniform_scale = false; + float lod_bias = 0.0; + float lod_model_scale = 1.0; + AABB transformed_aabb; //needed for LOD + float depth = 0; + uint32_t flags_cache = 0; + bool store_transform_cache = true; + int32_t shader_parameters_offset = -1; + + uint32_t layer_mask = 1; + uint32_t instance_count = 0; + + RID mesh_instance; + bool can_sdfgi = false; + bool using_projectors = false; + bool using_softshadows = false; + bool fade_near = false; + float fade_near_begin = 0; + float fade_near_end = 0; + bool fade_far = false; + float fade_far_begin = 0; + float fade_far_end = 0; + float force_alpha = 1.0; + float parent_fade_alpha = 1.0; + + uint32_t omni_light_count = 0; + LocalVector<RID> omni_lights; + uint32_t spot_light_count = 0; + LocalVector<RID> spot_lights; + LocalVector<uint32_t> omni_light_gl_cache; + LocalVector<uint32_t> spot_light_gl_cache; + + //used during setup + uint32_t base_flags = 0; + Transform3D transform; + GeometryInstanceSurface *surface_caches = nullptr; + SelfList<GeometryInstanceGLES3> dirty_list_element; + + struct Data { + //data used less often goes into regular heap + RID base; + RS::InstanceType base_type; + + RID skeleton; + Vector<RID> surface_materials; + RID material_override; + RID material_overlay; + AABB aabb; + + bool use_dynamic_gi = false; + bool use_baked_light = false; + bool cast_double_sided_shadows = false; + bool mirror = false; + bool dirty_dependencies = false; + + RendererStorage::DependencyTracker dependency_tracker; + }; + + Data *data = nullptr; + + GeometryInstanceGLES3() : + dirty_list_element(this) {} + }; + + enum { + INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5, + INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6, + INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8, + INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9, + INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10, + INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11, + INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, + INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, + INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, + INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15, + }; + + static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker); + static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker); + + SelfList<GeometryInstanceGLES3>::List geometry_instance_dirty_list; + + // Use PagedAllocator instead of RID to maximize performance + PagedAllocator<GeometryInstanceGLES3> geometry_instance_alloc; + PagedAllocator<GeometryInstanceSurface> geometry_instance_surface_alloc; + + void _geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); + void _geometry_instance_add_surface_with_material_chain(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, RID p_mat_src, RID p_mesh); + void _geometry_instance_add_surface(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); + void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); + void _geometry_instance_update(GeometryInstance *p_geometry_instance); + void _update_dirty_geometry_instances(); + + struct SceneState { + struct UBO { + float projection_matrix[16]; + float inv_projection_matrix[16]; + float inv_view_matrix[16]; + float view_matrix[16]; + + float viewport_size[2]; + float screen_pixel_size[2]; + + float ambient_light_color_energy[4]; + + float ambient_color_sky_mix; + uint32_t material_uv2_mode; + float pad2; + uint32_t use_ambient_light = 0; + + uint32_t use_ambient_cubemap = 0; + uint32_t use_reflection_cubemap = 0; + float fog_aerial_perspective; + float time; + + float radiance_inverse_xform[12]; + + uint32_t directional_light_count; + float z_far; + float z_near; + float pad1; + + uint32_t fog_enabled; + float fog_density; + float fog_height; + float fog_height_density; + + float fog_light_color[3]; + float fog_sun_scatter; + }; + static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes"); + + struct TonemapUBO { + float exposure = 1.0; + float white = 1.0; + int32_t tonemapper = 0; + int32_t pad = 0; + }; + static_assert(sizeof(TonemapUBO) % 16 == 0, "Tonemap UBO size must be a multiple of 16 bytes"); + + UBO ubo; + GLuint ubo_buffer = 0; + GLuint tonemap_buffer = 0; + + bool used_depth_prepass = false; + + GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX; + GLES3::SceneShaderData::DepthDraw current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE; + GLES3::SceneShaderData::DepthTest current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_DISABLED; + GLES3::SceneShaderData::Cull cull_mode = GLES3::SceneShaderData::CULL_BACK; + + bool texscreen_copied = false; + bool used_screen_texture = false; + bool used_normal_texture = false; + bool used_depth_texture = false; + + LightData *omni_lights = nullptr; + LightData *spot_lights = nullptr; + + InstanceSort<LightInstance> *omni_light_sort; + InstanceSort<LightInstance> *spot_light_sort; + GLuint omni_light_buffer = 0; + GLuint spot_light_buffer = 0; + uint32_t omni_light_count = 0; + uint32_t spot_light_count = 0; + + DirectionalLightData *directional_lights = nullptr; + GLuint directional_light_buffer = 0; + } scene_state; + + struct RenderListParameters { + GeometryInstanceSurface **elements = nullptr; + int element_count = 0; + bool reverse_cull = false; + uint32_t spec_constant_base_flags = 0; + bool force_wireframe = false; + + RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint32_t p_spec_constant_base_flags, bool p_force_wireframe = false) { + elements = p_elements; + element_count = p_element_count; + reverse_cull = p_reverse_cull; + spec_constant_base_flags = p_spec_constant_base_flags; + force_wireframe = p_force_wireframe; + } + }; + + struct RenderList { + LocalVector<GeometryInstanceSurface *> elements; + + void clear() { + elements.clear(); + } + + //should eventually be replaced by radix + + struct SortByKey { + _FORCE_INLINE_ bool operator()(const GeometryInstanceSurface *A, const GeometryInstanceSurface *B) const { + return (A->sort.sort_key2 == B->sort.sort_key2) ? (A->sort.sort_key1 < B->sort.sort_key1) : (A->sort.sort_key2 < B->sort.sort_key2); + } + }; + + void sort_by_key() { + SortArray<GeometryInstanceSurface *, SortByKey> sorter; + sorter.sort(elements.ptr(), elements.size()); + } + + void sort_by_key_range(uint32_t p_from, uint32_t p_size) { + SortArray<GeometryInstanceSurface *, SortByKey> sorter; + sorter.sort(elements.ptr() + p_from, p_size); + } + + struct SortByDepth { + _FORCE_INLINE_ bool operator()(const GeometryInstanceSurface *A, const GeometryInstanceSurface *B) const { + return (A->owner->depth < B->owner->depth); + } + }; + + void sort_by_depth() { //used for shadows + + SortArray<GeometryInstanceSurface *, SortByDepth> sorter; + sorter.sort(elements.ptr(), elements.size()); + } + + struct SortByReverseDepthAndPriority { + _FORCE_INLINE_ bool operator()(const GeometryInstanceSurface *A, const GeometryInstanceSurface *B) const { + return (A->sort.priority == B->sort.priority) ? (A->owner->depth > B->owner->depth) : (A->sort.priority < B->sort.priority); + } + }; + + void sort_by_reverse_depth_and_priority() { //used for alpha + + SortArray<GeometryInstanceSurface *, SortByReverseDepthAndPriority> sorter; + sorter.sort(elements.ptr(), elements.size()); + } + + _FORCE_INLINE_ void add_element(GeometryInstanceSurface *p_element) { + elements.push_back(p_element); + } + }; + + RenderList render_list[RENDER_LIST_MAX]; + + void _setup_lights(const RenderDataGLES3 *p_render_data, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_omni_light_count, uint32_t &r_spot_light_count); + void _setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows); + void _fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append = false); + + template <PassMode p_pass_mode> + _FORCE_INLINE_ void _render_list_template(RenderListParameters *p_params, const RenderDataGLES3 *p_render_data, uint32_t p_from_element, uint32_t p_to_element, bool p_alpha_pass = false); protected: double time; @@ -117,6 +531,8 @@ protected: //bool use_debanding = false; //uint32_t view_count = 1; + bool is_transparent = false; + RID render_target; GLuint internal_texture = 0; // Used for rendering when post effects are enabled GLuint depth_texture = 0; // Main depth texture @@ -293,6 +709,33 @@ protected: /* Sky */ + struct SkyGlobals { + float fog_aerial_perspective = 0.0; + Color fog_light_color; + float fog_sun_scatter = 0.0; + bool fog_enabled = false; + float fog_density = 0.0; + float z_far = 0.0; + uint32_t directional_light_count = 0; + + DirectionalLightData *directional_lights = nullptr; + DirectionalLightData *last_frame_directional_lights = nullptr; + uint32_t last_frame_directional_light_count = 0; + GLuint directional_light_buffer = 0; + + RID shader_default_version; + RID default_material; + RID default_shader; + RID fog_material; + RID fog_shader; + GLuint screen_triangle = 0; + GLuint screen_triangle_array = 0; + GLuint radical_inverse_vdc_cache_tex = 0; + uint32_t max_directional_lights = 4; + uint32_t roughness_layers = 8; + uint32_t ggx_samples = 128; + } sky_globals; + struct Sky { // Screen Buffers GLuint half_res_pass = 0; @@ -304,11 +747,13 @@ protected: // Radiance Cubemap GLuint radiance = 0; GLuint radiance_framebuffer = 0; + GLuint raw_radiance = 0; RID material; - RID uniform_buffer; + GLuint uniform_buffer; int radiance_size = 256; + int mipmap_count = 1; RS::SkyMode mode = RS::SKY_MODE_AUTOMATIC; @@ -319,33 +764,26 @@ protected: Sky *dirty_list = nullptr; //State to track when radiance cubemap needs updating - //SkyMaterialData *prev_material; + GLES3::SkyMaterialData *prev_material; Vector3 prev_position = Vector3(0.0, 0.0, 0.0); float prev_time = 0.0f; - - void free(); - bool set_radiance_size(int p_radiance_size); - bool set_mode(RS::SkyMode p_mode); - bool set_material(RID p_material); - Ref<Image> bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size); }; Sky *dirty_sky_list = nullptr; mutable RID_Owner<Sky, true> sky_owner; + void _setup_sky(Environment *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size); void _invalidate_sky(Sky *p_sky); void _update_dirty_skys(); - void _draw_sky(Sky *p_sky, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_custom_fov, float p_energy, const Basis &p_sky_orientation); + void _update_sky_radiance(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform); + void _filter_sky_radiance(Sky *p_sky, int p_base_layer); + void _draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform); + void _free_sky_data(Sky *p_sky); public: RasterizerStorageGLES3 *storage; RasterizerCanvasGLES3 *canvas; - // References to shaders are needed in public space so they can be accessed in RasterizerStorageGLES3 - struct State { - SkyShaderGLES3 sky_shader; - } state; - GeometryInstance *geometry_instance_create(RID p_base) override; void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; @@ -388,9 +826,15 @@ public: /* SDFGI UPDATE */ void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} - int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; } - AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); } - uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; } + int sdfgi_get_pending_region_count(RID p_render_buffers) const override { + return 0; + } + AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { + return AABB(); + } + uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { + return 0; + } /* SKY API */ @@ -463,6 +907,15 @@ public: void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; void light_instance_mark_visible(RID p_light_instance) override; + _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->light_type; + } + _FORCE_INLINE_ uint32_t light_instance_get_gl_id(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->gl_id; + } + RID fog_volume_instance_create(RID p_fog_volume) override; void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override; void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index cca445bf00..8046a18f05 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -39,6 +39,19 @@ #include "servers/rendering/shader_language.h" void RasterizerStorageGLES3::base_update_dependency(RID p_base, DependencyTracker *p_instance) { + if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_base)) { + GLES3::Mesh *mesh = GLES3::MeshStorage::get_singleton()->get_mesh(p_base); + p_instance->update_dependency(&mesh->dependency); + } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_base)) { + GLES3::MultiMesh *multimesh = GLES3::MeshStorage::get_singleton()->get_multimesh(p_base); + p_instance->update_dependency(&multimesh->dependency); + if (multimesh->mesh.is_valid()) { + base_update_dependency(multimesh->mesh, p_instance); + } + } else if (GLES3::LightStorage::get_singleton()->owns_light(p_base)) { + GLES3::Light *l = GLES3::LightStorage::get_singleton()->get_light(p_base); + p_instance->update_dependency(&l->dependency); + } } /* VOXEL GI API */ @@ -342,25 +355,14 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, */ RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { - return RS::INSTANCE_NONE; - - /* - if (mesh_owner.owns(p_rid)) { + if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) { return RS::INSTANCE_MESH; - } else if (light_owner.owns(p_rid)) { - return RS::INSTANCE_LIGHT; - } else if (multimesh_owner.owns(p_rid)) { + } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { return RS::INSTANCE_MULTIMESH; - } else if (immediate_owner.owns(p_rid)) { - return RS::INSTANCE_IMMEDIATE; - } else if (reflection_probe_owner.owns(p_rid)) { - return RS::INSTANCE_REFLECTION_PROBE; - } else if (lightmap_capture_data_owner.owns(p_rid)) { - return RS::INSTANCE_LIGHTMAP_CAPTURE; - } else { - return RS::INSTANCE_NONE; + } else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) { + return RS::INSTANCE_LIGHT; } -*/ + return RS::INSTANCE_NONE; } bool RasterizerStorageGLES3::free(RID p_rid) { @@ -379,89 +381,23 @@ bool RasterizerStorageGLES3::free(RID p_rid) { } else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) { GLES3::MaterialStorage::get_singleton()->material_free(p_rid); return true; - } else { - return false; - } - /* - } else if (skeleton_owner.owns(p_rid)) { - Skeleton *s = skeleton_owner.get_or_null(p_rid); - - if (s->update_list.in_list()) { - skeleton_update_list.remove(&s->update_list); - } - - for (Set<InstanceBaseDependency *>::Element *E = s->instances.front(); E; E = E->next()) { - E->get()->skeleton = RID(); - } - - skeleton_allocate(p_rid, 0, false); - - if (s->tex_id) { - glDeleteTextures(1, &s->tex_id); - } - - skeleton_owner.free(p_rid); - memdelete(s); - - return true; - } else if (mesh_owner.owns(p_rid)) { - Mesh *mesh = mesh_owner.get_or_null(p_rid); - - mesh->instance_remove_deps(); - mesh_clear(p_rid); - - while (mesh->multimeshes.first()) { - MultiMesh *multimesh = mesh->multimeshes.first()->self(); - multimesh->mesh = RID(); - multimesh->dirty_aabb = true; - - mesh->multimeshes.remove(mesh->multimeshes.first()); - - if (!multimesh->update_list.in_list()) { - multimesh_update_list.add(&multimesh->update_list); - } - } - - mesh_owner.free(p_rid); - memdelete(mesh); - + } else if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) { + GLES3::MeshStorage::get_singleton()->mesh_free(p_rid); return true; - } else if (multimesh_owner.owns(p_rid)) { - MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid); - multimesh->instance_remove_deps(); - - if (multimesh->mesh.is_valid()) { - Mesh *mesh = mesh_owner.get_or_null(multimesh->mesh); - if (mesh) { - mesh->multimeshes.remove(&multimesh->mesh_list); - } - } - - multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_3D, RS::MULTIMESH_COLOR_NONE); - - _update_dirty_multimeshes(); - - multimesh_owner.free(p_rid); - memdelete(multimesh); - + } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { + GLES3::MeshStorage::get_singleton()->multimesh_free(p_rid); return true; - } else if (immediate_owner.owns(p_rid)) { - Immediate *im = immediate_owner.get_or_null(p_rid); - im->instance_remove_deps(); - - immediate_owner.free(p_rid); - memdelete(im); - + } else if (GLES3::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) { + GLES3::MeshStorage::get_singleton()->mesh_instance_free(p_rid); return true; - } else if (light_owner.owns(p_rid)) { - Light *light = light_owner.get_or_null(p_rid); - light->instance_remove_deps(); - - light_owner.free(p_rid); - memdelete(light); - + } else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) { + GLES3::LightStorage::get_singleton()->light_free(p_rid); return true; - } else if (reflection_probe_owner.owns(p_rid)) { + } else { + return false; + } + /* + else if (reflection_probe_owner.owns(p_rid)) { // delete the texture ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid); reflection_probe->instance_remove_deps(); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 6401771abb..fa74fbd5f6 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -41,6 +41,7 @@ #include "servers/rendering/shader_compiler.h" #include "servers/rendering/shader_language.h" #include "storage/config.h" +#include "storage/light_storage.h" #include "storage/material_storage.h" #include "storage/mesh_storage.h" #include "storage/texture_storage.h" @@ -55,6 +56,48 @@ public: GLES3::Config *config = nullptr; + static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) { + p_array[0] = p_mtx.basis.rows[0][0]; + p_array[1] = p_mtx.basis.rows[1][0]; + p_array[2] = p_mtx.basis.rows[2][0]; + p_array[3] = 0; + p_array[4] = p_mtx.basis.rows[0][1]; + p_array[5] = p_mtx.basis.rows[1][1]; + p_array[6] = p_mtx.basis.rows[2][1]; + p_array[7] = 0; + p_array[8] = p_mtx.basis.rows[0][2]; + p_array[9] = p_mtx.basis.rows[1][2]; + p_array[10] = p_mtx.basis.rows[2][2]; + p_array[11] = 0; + p_array[12] = p_mtx.origin.x; + p_array[13] = p_mtx.origin.y; + p_array[14] = p_mtx.origin.z; + p_array[15] = 1; + } + + static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) { + p_array[0] = p_mtx.rows[0][0]; + p_array[1] = p_mtx.rows[1][0]; + p_array[2] = p_mtx.rows[2][0]; + p_array[3] = 0; + p_array[4] = p_mtx.rows[0][1]; + p_array[5] = p_mtx.rows[1][1]; + p_array[6] = p_mtx.rows[2][1]; + p_array[7] = 0; + p_array[8] = p_mtx.rows[0][2]; + p_array[9] = p_mtx.rows[1][2]; + p_array[10] = p_mtx.rows[2][2]; + p_array[11] = 0; + } + + static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + p_array[i * 4 + j] = p_mtx.matrix[i][j]; + } + } + } + struct Resources { GLuint mipmap_blur_fbo; GLuint mipmap_blur_color; @@ -302,7 +345,7 @@ inline void RasterizerStorageGLES3::buffer_orphan_and_upload(unsigned int p_buff } inline String RasterizerStorageGLES3::get_framebuffer_error(GLenum p_status) { -#ifdef DEBUG_ENABLED +#if defined(DEBUG_ENABLED) && defined(GLES_OVER_GL) if (p_status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) { return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; } else if (p_status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) { diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index e356fa8c1f..33d5494837 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -171,6 +171,15 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant } builder.append("\n"); //make sure defines begin at newline + // Default to highp precision unless specified otherwise. + builder.append("precision highp float;\n"); + builder.append("precision highp int;\n"); +#ifndef GLES_OVER_GL + builder.append("precision highp sampler2D;\n"); + builder.append("precision highp samplerCube;\n"); + builder.append("precision highp sampler2DArray;\n"); +#endif + for (uint32_t i = 0; i < p_template.chunks.size(); i++) { const StageTemplate::Chunk &chunk = p_template.chunks[i]; switch (chunk.type) { @@ -576,7 +585,7 @@ void ShaderGLES3::_initialize_version(Version *p_version) { } } -void ShaderGLES3::version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines, const Vector<StringName> &p_texture_uniforms, bool p_initialize) { +void ShaderGLES3::version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines, const Vector<StringName> &p_texture_uniforms, bool p_initialize) { Version *version = version_owner.get_or_null(p_version); ERR_FAIL_COND(!version); diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 15281064af..228bed6f9b 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -35,7 +35,7 @@ #include "core/string/string_builder.h" #include "core/templates/hash_map.h" #include "core/templates/local_vector.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/templates/rid_owner.h" #include "core/variant/variant.h" #include "servers/rendering_server.h" @@ -73,16 +73,17 @@ private: //versions CharString general_defines; - // A version is a high-level construct which is a combination of built-in and user-defined shader code - // Variants use #idefs to toggle behaviour on and off to change behaviour of the shader + // A version is a high-level construct which is a combination of built-in and user-defined shader code, Each user-created Shader makes one version + // Variants use #ifdefs to toggle behaviour on and off to change behaviour of the shader + // All variants are compiled each time a new version is created // Specializations use #ifdefs to toggle behaviour on and off for performance, on supporting hardware, they will compile a version with everything enabled, and then compile more copies to improve performance - // Use specializations to enable and disabled advanced features, use variants to toggle behaviour when different data may be used (e.g. using a samplerArray vs a sampler) + // Use specializations to enable and disabled advanced features, use variants to toggle behaviour when different data may be used (e.g. using a samplerArray vs a sampler, or doing a depth prepass vs a color pass) struct Version { Vector<StringName> texture_uniforms; CharString uniforms; CharString vertex_globals; CharString fragment_globals; - Map<StringName, CharString> code_sections; + HashMap<StringName, CharString> code_sections; Vector<CharString> custom_defines; struct Specialization { @@ -91,7 +92,7 @@ private: GLuint frag_id; LocalVector<GLint> uniform_location; LocalVector<GLint> texture_uniform_locations; - Map<StringName, GLint> custom_uniform_locations; + HashMap<StringName, GLint> custom_uniform_locations; bool build_queued = false; bool ok = false; Specialization() { @@ -217,7 +218,11 @@ protected: ERR_FAIL_INDEX_V(p_which, uniform_count, -1); Version *version = version_owner.get_or_null(p_version); ERR_FAIL_COND_V(!version, -1); - return version->variants[p_variant].lookup_ptr(p_specialization)->uniform_location[p_which]; + ERR_FAIL_INDEX_V(p_variant, int(version->variants.size()), -1); + Version::Specialization *spec = version->variants[p_variant].lookup_ptr(p_specialization); + ERR_FAIL_COND_V(!spec, -1); + ERR_FAIL_INDEX_V(p_which, int(spec->uniform_location.size()), -1); + return spec->uniform_location[p_which]; } virtual void _init() = 0; @@ -225,7 +230,7 @@ protected: public: RID version_create(); - void version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines, const Vector<StringName> &p_texture_uniforms, bool p_initialize = false); + void version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines, const Vector<StringName> &p_texture_uniforms, bool p_initialize = false); bool version_is_valid(RID p_version); diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index 79247f38d4..d8dd573f57 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -2,10 +2,18 @@ Import("env") -env.Depends("#drivers/gles3/shaders/copy.glsl.gen.h", "#core/math/basis.h") -env.Depends("#drivers/gles3/shaders/copy.glsl.gen.h", "#core/math/transform_2d.h") - if "GLES3_GLSL" in env["BUILDERS"]: + # find all include files + gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + + # find all shader code(all glsl files excluding our include files) + glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] + + # make sure we recompile shaders if include files change + env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files) + env.GLES3_GLSL("canvas.glsl") env.GLES3_GLSL("copy.glsl") + env.GLES3_GLSL("scene.glsl") env.GLES3_GLSL("sky.glsl") + env.GLES3_GLSL("cubemap_filter.glsl") diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 41d308b776..381a0e8a73 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -21,6 +21,15 @@ layout(location = 10) in uvec4 bone_attrib; layout(location = 11) in vec4 weight_attrib; #endif + +// This needs to be outside clang-format so the ubo comment is in the right place +#ifdef MATERIAL_UNIFORMS_USED +layout(std140) uniform MaterialUniforms{ //ubo:4 + +#MATERIAL_UNIFORMS + +}; +#endif /* clang-format on */ #include "canvas_uniforms_inc.glsl" #include "stdlib_inc.glsl" @@ -38,15 +47,6 @@ out vec2 pixel_size_interp; #endif -#ifdef MATERIAL_UNIFORMS_USED -layout(std140) uniform MaterialUniforms{ -//ubo:4 - -#MATERIAL_UNIFORMS - -}; -#endif - #GLOBALS void main() { @@ -518,8 +518,8 @@ void main() { float px_size = max(0.5 * dot((vec2(px_range) / msdf_size), dest_size), 1.0); float d = msdf_median(msdf_sample.r, msdf_sample.g, msdf_sample.b, msdf_sample.a) - 0.5; - if (outline_thickness > 0) { - float cr = clamp(outline_thickness, 0.0, px_range / 2) / px_range; + if (outline_thickness > 0.0) { + float cr = clamp(outline_thickness, 0.0, px_range / 2.0) / px_range; float a = clamp((d + cr) * px_size, 0.0, 1.0); color.a = a * color.a; } else { @@ -710,8 +710,8 @@ void main() { vec2 pos_rot = pos_norm * mat2(vec2(0.7071067811865476, -0.7071067811865476), vec2(0.7071067811865476, 0.7071067811865476)); //is there a faster way to 45 degrees rot? float tex_ofs; float distance; - if (pos_rot.y > 0) { - if (pos_rot.x > 0) { + if (pos_rot.y > 0.0) { + if (pos_rot.x > 0.0) { tex_ofs = pos_box.y * 0.125 + 0.125; distance = shadow_pos.x; } else { @@ -719,7 +719,7 @@ void main() { distance = shadow_pos.y; } } else { - if (pos_rot.x < 0) { + if (pos_rot.x < 0.0) { tex_ofs = pos_box.y * -0.125 + (0.5 + 0.125); distance = -shadow_pos.x; } else { diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index 2081abfef6..81e66c956c 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -1,136 +1,102 @@ /* clang-format off */ -[vertex] +#[modes] -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -precision highp float; -precision highp int; -#endif +mode_default = +mode_copy = #define MODE_DIRECT_WRITE + +#[specializations] -layout(location = 0) in highp vec2 vertex; +#[vertex] + +layout(location = 0) in highp vec2 vertex_attrib; /* clang-format on */ -layout(location = 4) in highp vec2 uv; out highp vec2 uv_interp; void main() { - uv_interp = uv; - gl_Position = vec4(vertex, 0, 1); + uv_interp = vertex_attrib; + gl_Position = vec4(uv_interp, 0.0, 1.0); } /* clang-format off */ -[fragment] +#[fragment] -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif +#define M_PI 3.14159265359 -#ifdef USE_SOURCE_PANORAMA -uniform sampler2D source_panorama; //texunit:0 -#else uniform samplerCube source_cube; //texunit:0 -#endif + /* clang-format on */ uniform int face_id; uniform float roughness; -in highp vec2 uv_interp; - -uniform sampler2D radical_inverse_vdc_cache; // texunit:1 - -#define M_PI 3.14159265359 - -#ifdef LOW_QUALITY - -#define SAMPLE_COUNT 64 - -#else - -#define SAMPLE_COUNT 512 +uniform float face_size; +uniform int sample_count; +//Todo, profile on low end hardware to see if fixed loop is faster +#ifdef USE_FIXED_SAMPLES +#define FIXED_SAMPLE_COUNT 32 #endif -#ifdef USE_SOURCE_PANORAMA +in highp vec2 uv_interp; -vec4 texturePanorama(sampler2D pano, vec3 normal) { - vec2 st = vec2( - atan(normal.x, normal.z), - acos(normal.y)); +uniform sampler2D radical_inverse_vdc_cache; // texunit:1 - if (st.x < 0.0) - st.x += M_PI * 2.0; +layout(location = 0) out vec4 frag_color; - st /= vec2(M_PI * 2.0, M_PI); +#define M_PI 3.14159265359 - return textureLod(pano, st, 0.0); +// Don't include tonemap_inc.glsl because all we want is these functions, we don't want the uniforms +vec3 linear_to_srgb(vec3 color) { + return max(vec3(1.055) * pow(color, vec3(0.416666667)) - vec3(0.055), vec3(0.0)); } -#endif +vec3 srgb_to_linear(vec3 color) { + return color * (color * (color * 0.305306011 + 0.682171111) + 0.012522878); +} vec3 texelCoordToVec(vec2 uv, int faceID) { mat3 faceUvVectors[6]; // -x - faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z - faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face + faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z + faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face // +x - faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z - faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face + faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z + faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face // -y - faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z - faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face + faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z + faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face // +y - faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z - faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face + faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z + faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face // -z - faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x - faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face + faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x + faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face // +z - faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face + faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. - vec3 result; - for (int i = 0; i < 6; i++) { - if (i == faceID) { - result = (faceUvVectors[i][0] * uv.x) + (faceUvVectors[i][1] * uv.y) + faceUvVectors[i][2]; - break; - } - } + vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2]; return normalize(result); } -vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { - float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] - +vec3 ImportanceSampleGGX(vec2 xi, float roughness4) { // Compute distribution direction - float Phi = 2.0 * M_PI * Xi.x; - float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y)); + float Phi = 2.0 * M_PI * xi.x; + float CosTheta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y)); float SinTheta = sqrt(1.0 - CosTheta * CosTheta); // Convert to spherical direction @@ -139,12 +105,26 @@ vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { H.y = SinTheta * sin(Phi); H.z = CosTheta; - vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 TangentX = normalize(cross(UpVector, N)); - vec3 TangentY = cross(N, TangentX); + return H; +} + +float DistributionGGX(float NdotH, float roughness4) { + float NdotH2 = NdotH * NdotH; + float denom = (NdotH2 * (roughness4 - 1.0) + 1.0); + denom = M_PI * denom * denom; + + return roughness4 / denom; +} + +// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float GGX(float NdotV, float a) { + float k = a / 2.0; + return NdotV / (NdotV * (1.0 - k) + k); +} - // Tangent to world space - return TangentX * H.x + TangentY * H.y + N * H.z; +// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float G_Smith(float a, float nDotV, float nDotL) { + return GGX(nDotL, a * a) * GGX(nDotV, a * a); } float radical_inverse_VdC(int i) { @@ -155,60 +135,54 @@ vec2 Hammersley(int i, int N) { return vec2(float(i) / float(N), radical_inverse_VdC(i)); } -uniform bool z_flip; - -layout(location = 0) out vec4 frag_color; - void main() { vec3 color = vec3(0.0); - - vec2 uv = (uv_interp * 2.0) - 1.0; + vec2 uv = uv_interp; vec3 N = texelCoordToVec(uv, face_id); -#ifdef USE_DIRECT_WRITE - -#ifdef USE_SOURCE_PANORAMA - - frag_color = vec4(texturePanorama(source_panorama, N).rgb, 1.0); -#else - - frag_color = vec4(textureCube(source_cube, N).rgb, 1.0); -#endif //USE_SOURCE_PANORAMA - +#ifdef MODE_DIRECT_WRITE + frag_color = vec4(textureCubeLod(source_cube, N, 0.0).rgb, 1.0); #else vec4 sum = vec4(0.0); + float solid_angle_texel = 4.0 * M_PI / (6.0 * face_size * face_size); + float roughness2 = roughness * roughness; + float roughness4 = roughness2 * roughness2; + vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + mat3 T; + T[0] = normalize(cross(UpVector, N)); + T[1] = cross(N, T[0]); + T[2] = N; - for (int sample_num = 0; sample_num < SAMPLE_COUNT; sample_num++) { - vec2 xi = Hammersley(sample_num, SAMPLE_COUNT); + for (int sample_num = 0; sample_num < sample_count; sample_num++) { + vec2 xi = Hammersley(sample_num, sample_count); - vec3 H = ImportanceSampleGGX(xi, roughness, N); - vec3 V = N; - vec3 L = (2.0 * dot(V, H) * H - V); + vec3 H = T * ImportanceSampleGGX(xi, roughness4); + float NdotH = dot(N, H); + vec3 L = (2.0 * NdotH * H - N); float NdotL = clamp(dot(N, L), 0.0, 1.0); if (NdotL > 0.0) { + float D = DistributionGGX(NdotH, roughness4); + float pdf = D * NdotH / (4.0 * NdotH) + 0.0001; -#ifdef USE_SOURCE_PANORAMA - vec3 val = texturePanorama(source_panorama, L).rgb; -#else - vec3 val = textureCubeLod(source_cube, L, 0.0).rgb; -#endif - //mix using Linear, to approximate high end back-end - val = mix(pow((val + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), val * (1.0 / 12.92), vec3(lessThan(val, vec3(0.04045)))); + float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001); - sum.rgb += val * NdotL; + float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(solid_angle_sample / solid_angle_texel); + + vec3 val = textureCubeLod(source_cube, L, mipLevel).rgb; + // Mix using linear + val = srgb_to_linear(val); + sum.rgb += val * NdotL; sum.a += NdotL; } } sum /= sum.a; - vec3 a = vec3(0.055); - sum.rgb = mix((vec3(1.0) + a) * pow(sum.rgb, vec3(1.0 / 2.4)) - a, 12.92 * sum.rgb, vec3(lessThan(sum.rgb, vec3(0.0031308)))); - + sum.rgb = linear_to_srgb(sum.rgb); frag_color = vec4(sum.rgb, 1.0); #endif } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index ebb00e81d0..198d1d9ec7 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1,980 +1,512 @@ /* clang-format off */ -[vertex] +#[modes] -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -precision highp float; -precision highp int; -#endif - -#define SHADER_IS_SRGB true //TODO remove - -#define M_PI 3.14159265359 - -// -// attributes -// - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ -layout(location = 1) in vec3 normal_attrib; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -layout(location = 2) in vec4 tangent_attrib; -#endif +mode_color = #define BASE_PASS +mode_additive = #define USE_ADDITIVE_LIGHTING +mode_depth = #define MODE_RENDER_DEPTH -#if defined(ENABLE_COLOR_INTERP) -layout(location = 3) in vec4 color_attrib; -#endif +#[specializations] -#if defined(ENABLE_UV_INTERP) -layout(location = 4) in vec2 uv_attrib; -#endif +DISABLE_LIGHTMAP = false +DISABLE_LIGHT_DIRECTIONAL = false +DISABLE_LIGHT_OMNI = false +DISABLE_LIGHT_SPOT = false +DISABLE_FOG = false +USE_RADIANCE_MAP = true -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) -layout(location = 5) in vec2 uv2_attrib; -#endif - -#ifdef USE_SKELETON - -#ifdef USE_SKELETON_SOFTWARE -layout(location = 13) in highp vec4 bone_transform_row_0; -layout(location = 14) in highp vec4 bone_transform_row_1; -layout(location = 15) in highp vec4 bone_transform_row_2; +#[vertex] -#else +#define M_PI 3.14159265359 -layout(location = 6) in vec4 bone_ids; -layout(location = 7) in highp vec4 bone_weights; +#define SHADER_IS_SRGB true -uniform highp sampler2D bone_transforms; // texunit:-1 -uniform ivec2 skeleton_texture_size; +#include "stdlib_inc.glsl" +#if !defined(MODE_RENDER_DEPTH) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) ||defined(LIGHT_CLEARCOAT_USED) +#ifndef NORMAL_USED +#define NORMAL_USED #endif - #endif -#ifdef USE_INSTANCING +/* +from RenderingServer: +ARRAY_VERTEX = 0, // RG32F or RGB32F (depending on 2D bit) +ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored. +ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal. +ARRAY_COLOR = 3, // RGBA8 +ARRAY_TEX_UV = 4, // RG32F +ARRAY_TEX_UV2 = 5, // RG32F +ARRAY_CUSTOM0 = 6, // Depends on ArrayCustomFormat. +ARRAY_CUSTOM1 = 7, +ARRAY_CUSTOM2 = 8, +ARRAY_CUSTOM3 = 9, +ARRAY_BONES = 10, // RGBA16UI (x2 if 8 weights) +ARRAY_WEIGHTS = 11, // RGBA16UNORM (x2 if 8 weights) +ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF. +ARRAY_MAX = 13 +*/ -layout(location = 8) in highp vec4 instance_xform_row_0; -layout(location = 9) in highp vec4 instance_xform_row_1; -layout(location = 10) in highp vec4 instance_xform_row_2; +/* INPUT ATTRIBS */ -layout(location = 11) in highp vec4 instance_color; -layout(location = 12) in highp vec4 instance_custom_data; +layout(location = 0) in highp vec3 vertex_attrib; +/* clang-format on */ +#ifdef NORMAL_USED +layout(location = 1) in vec3 normal_attrib; #endif -// -// uniforms -// - -uniform highp mat4 inv_view_matrix; -uniform highp mat4 view_matrix; -uniform highp mat4 projection_matrix; -uniform highp mat4 projection_inverse_matrix; - -uniform highp mat4 world_transform; - -uniform highp float time; - -uniform highp vec2 viewport_size; - -#ifdef RENDER_DEPTH -uniform float light_bias; -uniform float light_normal_bias; +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) +layout(location = 2) in vec4 tangent_attrib; #endif -// -// varyings -// - -#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS) -out highp vec4 position_interp; +#if defined(COLOR_USED) +layout(location = 3) in vec4 color_attrib; #endif -out highp vec3 vertex_interp; -out vec3 normal_interp; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -out vec3 tangent_interp; -out vec3 binormal_interp; +#ifdef UV_USED +layout(location = 4) in vec2 uv_attrib; #endif -#if defined(ENABLE_COLOR_INTERP) -out vec4 color_interp; +#if defined(UV2_USED) || defined(USE_LIGHTMAP) +layout(location = 5) in vec2 uv2_attrib; #endif -#if defined(ENABLE_UV_INTERP) -out vec2 uv_interp; +#if defined(CUSTOM0_USED) +layout(location = 6) in vec4 custom0_attrib; #endif -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) -out vec2 uv2_interp; +#if defined(CUSTOM1_USED) +layout(location = 7) in vec4 custom1_attrib; #endif -/* clang-format off */ - -VERTEX_SHADER_GLOBALS - -/* clang-format on */ - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - -out highp float dp_clip; -uniform highp float shadow_dual_paraboloid_render_zfar; -uniform highp float shadow_dual_paraboloid_render_side; - +#if defined(CUSTOM2_USED) +layout(location = 8) in vec4 custom2_attrib; #endif -#if defined(USE_SHADOW) && defined(USE_LIGHTING) - -uniform highp mat4 light_shadow_matrix; -out highp vec4 shadow_coord; - -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) -uniform highp mat4 light_shadow_matrix2; -out highp vec4 shadow_coord2; +#if defined(CUSTOM3_USED) +layout(location = 9) in vec4 custom3_attrib; #endif -#if defined(LIGHT_USE_PSSM4) - -uniform highp mat4 light_shadow_matrix3; -uniform highp mat4 light_shadow_matrix4; -out highp vec4 shadow_coord3; -out highp vec4 shadow_coord4; - +#if defined(BONES_USED) +layout(location = 10) in uvec4 bone_attrib; #endif +#if defined(WEIGHTS_USED) +layout(location = 11) in vec4 weight_attrib; #endif -#if defined(USE_VERTEX_LIGHTING) && defined(USE_LIGHTING) +layout(std140) uniform GlobalVariableData { //ubo:1 + vec4 global_variables[MAX_GLOBAL_VARIABLES]; +}; -out highp vec3 diffuse_interp; -out highp vec3 specular_interp; +layout(std140) uniform SceneData { // ubo:2 + highp mat4 projection_matrix; + highp mat4 inv_projection_matrix; + highp mat4 inv_view_matrix; + highp mat4 view_matrix; -// general for all lights -uniform highp vec4 light_color; -uniform highp vec4 shadow_color; -uniform highp float light_specular; + vec2 viewport_size; + vec2 screen_pixel_size; -// directional -uniform highp vec3 light_direction; + mediump vec4 ambient_light_color_energy; -// omni -uniform highp vec3 light_position; + mediump float ambient_color_sky_mix; + bool material_uv2_mode; + float pad2; + bool use_ambient_light; + bool use_ambient_cubemap; + bool use_reflection_cubemap; -uniform highp float light_range; -uniform highp float light_attenuation; + float fog_aerial_perspective; + float time; -// spot -uniform highp float light_spot_attenuation; -uniform highp float light_spot_range; -uniform highp float light_spot_angle; + mat3 radiance_inverse_xform; -void light_compute( - vec3 N, - vec3 L, - vec3 V, - vec3 light_color, - vec3 attenuation, - float roughness) { -//this makes lights behave closer to linear, but then addition of lights looks bad -//better left disabled + uint directional_light_count; + float z_far; + float z_near; + float pad; -//#define SRGB_APPROX(m_var) m_var = pow(m_var,0.4545454545); -/* -#define SRGB_APPROX(m_var) {\ - float S1 = sqrt(m_var);\ - float S2 = sqrt(S1);\ - float S3 = sqrt(S2);\ - m_var = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * m_var;\ - } -*/ -#define SRGB_APPROX(m_var) + bool fog_enabled; + float fog_density; + float fog_height; + float fog_height_density; - float NdotL = dot(N, L); - float cNdotL = max(NdotL, 0.0); // clamped NdotL - float NdotV = dot(N, V); - float cNdotV = max(NdotV, 0.0); - -#if defined(DIFFUSE_OREN_NAYAR) - vec3 diffuse_brdf_NL; -#else - float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance -#endif - -#if defined(DIFFUSE_LAMBERT_WRAP) - // energy conserving lambert wrap shader - diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); - -#elif defined(DIFFUSE_OREN_NAYAR) - - { - // see http://mimosa-pudica.net/improved-oren-nayar.html - float LdotV = dot(L, V); - - float s = LdotV - NdotL * NdotV; - float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); + vec3 fog_light_color; + float fog_sun_scatter; +} +scene_data; - float sigma2 = roughness * roughness; // TODO: this needs checking - vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); - float B = 0.45 * sigma2 / (sigma2 + 0.09); +uniform highp mat4 world_transform; - diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); - } -#else - // lambert by default for everything else - diffuse_brdf_NL = cNdotL * (1.0 / M_PI); +#ifdef USE_LIGHTMAP +uniform highp vec4 lightmap_uv_rect; #endif - SRGB_APPROX(diffuse_brdf_NL) - - diffuse_interp += light_color * diffuse_brdf_NL * attenuation; +/* Varyings */ - if (roughness > 0.0) { - // D - float specular_brdf_NL = 0.0; - -#if !defined(SPECULAR_DISABLED) - //normalized blinn always unless disabled - vec3 H = normalize(V + L); - float cNdotH = max(dot(N, H), 0.0); - float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess) * cNdotL; - blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - specular_brdf_NL = blinn; +out highp vec3 vertex_interp; +#ifdef NORMAL_USED +out vec3 normal_interp; #endif - SRGB_APPROX(specular_brdf_NL) - specular_interp += specular_brdf_NL * light_color * attenuation * (1.0 / M_PI); - } -} - +#if defined(COLOR_USED) +out vec4 color_interp; #endif -#ifdef USE_VERTEX_LIGHTING - -#ifdef USE_REFLECTION_PROBE1 - -uniform highp mat4 refprobe1_local_matrix; -out mediump vec4 refprobe1_reflection_normal_blend; -uniform highp vec3 refprobe1_box_extents; - -#ifndef USE_LIGHTMAP -out mediump vec3 refprobe1_ambient_normal; +#if defined(UV_USED) +out vec2 uv_interp; #endif -#endif //reflection probe1 - -#ifdef USE_REFLECTION_PROBE2 - -uniform highp mat4 refprobe2_local_matrix; -out mediump vec4 refprobe2_reflection_normal_blend; -uniform highp vec3 refprobe2_box_extents; +#if defined(UV2_USED) +out vec2 uv2_interp; +#else +#ifdef USE_LIGHTMAP +out vec2 uv2_interp; +#endif +#endif -#ifndef USE_LIGHTMAP -out mediump vec3 refprobe2_ambient_normal; +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) +out vec3 tangent_interp; +out vec3 binormal_interp; #endif -#endif //reflection probe2 +#if defined(MATERIAL_UNIFORMS_USED) -#endif //vertex lighting for refprobes +/* clang-format off */ +layout(std140) uniform MaterialUniforms { // ubo:3 -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) +#MATERIAL_UNIFORMS -out vec4 fog_interp; +}; +/* clang-format on */ -uniform mediump vec4 fog_color_base; -#ifdef LIGHT_MODE_DIRECTIONAL -uniform mediump vec4 fog_sun_color_amount; #endif -uniform bool fog_transmit_enabled; -uniform mediump float fog_transmit_curve; - -#ifdef FOG_DEPTH_ENABLED -uniform highp float fog_depth_begin; -uniform mediump float fog_depth_curve; -uniform mediump float fog_max_distance; -#endif +/* clang-format off */ -#ifdef FOG_HEIGHT_ENABLED -uniform highp float fog_height_min; -uniform highp float fog_height_max; -uniform mediump float fog_height_curve; -#endif +#GLOBALS -#endif //fog +/* clang-format on */ +invariant gl_Position; void main() { - highp vec4 vertex = vertex_attrib; - - mat4 model_matrix = world_transform; + highp vec3 vertex = vertex_attrib; -#ifdef USE_INSTANCING - { - highp mat4 m = mat4( - instance_xform_row_0, - instance_xform_row_1, - instance_xform_row_2, - vec4(0.0, 0.0, 0.0, 1.0)); - model_matrix = model_matrix * transpose(m); - } + highp mat4 model_matrix = world_transform; +#ifdef NORMAL_USED + vec3 normal = normal_attrib * 2.0 - 1.0; #endif + highp mat3 model_normal_matrix = mat3(model_matrix); - vec3 normal = normal_attrib; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - vec3 tangent = tangent_attrib.xyz; - float binormalf = tangent_attrib.a; +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) + vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0; + float binormalf = tangent_attrib.a * 2.0 - 1.0; vec3 binormal = normalize(cross(normal, tangent) * binormalf); #endif -#if defined(ENABLE_COLOR_INTERP) +#if defined(COLOR_USED) color_interp = color_attrib; -#ifdef USE_INSTANCING - color_interp *= instance_color; -#endif #endif -#if defined(ENABLE_UV_INTERP) +#if defined(UV_USED) uv_interp = uv_attrib; #endif -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) +#ifdef USE_LIGHTMAP + uv2_interp = lightmap_uv_rect.zw * uv2_attrib + lightmap_uv_rect.xy; +#else +#if defined(UV2_USED) uv2_interp = uv2_attrib; #endif +#endif #if defined(OVERRIDE_POSITION) highp vec4 position; #endif + highp mat4 projection_matrix = scene_data.projection_matrix; + highp mat4 inv_projection_matrix = scene_data.inv_projection_matrix; -#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - vertex = model_matrix * vertex; - normal = normalize((model_matrix * vec4(normal, 0.0)).xyz); -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - - tangent = normalize((model_matrix * vec4(tangent, 0.0)).xyz); - binormal = normalize((model_matrix * vec4(binormal, 0.0)).xyz); -#endif -#endif - -#ifdef USE_SKELETON - - highp mat4 bone_transform = mat4(0.0); - -#ifdef USE_SKELETON_SOFTWARE - // passing the transform as attributes - - bone_transform[0] = vec4(bone_transform_row_0.x, bone_transform_row_1.x, bone_transform_row_2.x, 0.0); - bone_transform[1] = vec4(bone_transform_row_0.y, bone_transform_row_1.y, bone_transform_row_2.y, 0.0); - bone_transform[2] = vec4(bone_transform_row_0.z, bone_transform_row_1.z, bone_transform_row_2.z, 0.0); - bone_transform[3] = vec4(bone_transform_row_0.w, bone_transform_row_1.w, bone_transform_row_2.w, 1.0); - -#else - // look up transform from the "pose texture" - { - for (int i = 0; i < 4; i++) { - ivec2 tex_ofs = ivec2(int(bone_ids[i]) * 3, 0); + vec4 instance_custom = vec4(0.0); - highp mat4 b = mat4( - texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(0, 0)), - texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(1, 0)), - texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(2, 0)), - vec4(0.0, 0.0, 0.0, 1.0)); + // Using world coordinates +#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - bone_transform += transpose(b) * bone_weights[i]; - } - } + vertex = (model_matrix * vec4(vertex, 1.0)).xyz; +#ifdef NORMAL_USED + normal = model_normal_matrix * normal; #endif - model_matrix = model_matrix * bone_transform; +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -#endif - -#ifdef USE_INSTANCING - vec4 instance_custom = instance_custom_data; -#else - vec4 instance_custom = vec4(0.0); + tangent = model_normal_matrix * tangent; + binormal = model_normal_matrix * binormal; #endif +#endif - mat4 local_projection_matrix = projection_matrix; - - mat4 modelview = view_matrix * model_matrix; float roughness = 1.0; -#define projection_matrix local_projection_matrix -#define world_transform model_matrix + highp mat4 modelview = scene_data.view_matrix * model_matrix; + highp mat3 modelview_normal = mat3(scene_data.view_matrix) * model_normal_matrix; float point_size = 1.0; { - /* clang-format off */ - -VERTEX_SHADER_CODE - - /* clang-format on */ +#CODE : VERTEX } gl_PointSize = point_size; - vec4 outvec = vertex; - // use local coordinates + // Using local coordinates (default) #if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) - vertex = modelview * vertex; - normal = normalize((modelview * vec4(normal, 0.0)).xyz); -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - tangent = normalize((modelview * vec4(tangent, 0.0)).xyz); - binormal = normalize((modelview * vec4(binormal, 0.0)).xyz); -#endif -#endif - -#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - vertex = view_matrix * vertex; - normal = normalize((view_matrix * vec4(normal, 0.0)).xyz); -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - tangent = normalize((view_matrix * vec4(tangent, 0.0)).xyz); - binormal = normalize((view_matrix * vec4(binormal, 0.0)).xyz); -#endif + vertex = (modelview * vec4(vertex, 1.0)).xyz; +#ifdef NORMAL_USED + normal = modelview_normal * normal; #endif - vertex_interp = vertex.xyz; - normal_interp = normal; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - tangent_interp = tangent; - binormal_interp = binormal; #endif -#ifdef RENDER_DEPTH - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - - vertex_interp.z *= shadow_dual_paraboloid_render_side; - normal_interp.z *= shadow_dual_paraboloid_render_side; - - dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias - - //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges - - highp vec3 vtx = vertex_interp + normalize(vertex_interp) * light_bias; - highp float distance = length(vtx); - vtx = normalize(vtx); - vtx.xy /= 1.0 - vtx.z; - vtx.z = (distance / shadow_dual_paraboloid_render_zfar); - vtx.z = vtx.z * 2.0 - 1.0; - - vertex_interp = vtx; - -#else - float z_ofs = light_bias; - z_ofs += (1.0 - abs(normal_interp.z)) * light_normal_bias; - - vertex_interp.z -= z_ofs; -#endif //dual parabolloid - -#endif //depth - -//vertex lighting -#if defined(USE_VERTEX_LIGHTING) && defined(USE_LIGHTING) - //vertex shaded version of lighting (more limited) - vec3 L; - vec3 light_att; - -#ifdef LIGHT_MODE_OMNI - vec3 light_vec = light_position - vertex_interp; - float light_length = length(light_vec); - - float normalized_distance = light_length / light_range; - - if (normalized_distance < 1.0) { - float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation); - - vec3 attenuation = vec3(omni_attenuation); - light_att = vec3(omni_attenuation); - } else { - light_att = vec3(0.0); - } - - L = normalize(light_vec); +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) + binormal = modelview_normal * binormal; + tangent = modelview_normal * tangent; #endif -#ifdef LIGHT_MODE_SPOT - - vec3 light_rel_vec = light_position - vertex_interp; - float light_length = length(light_rel_vec); - float normalized_distance = light_length / light_range; - - if (normalized_distance < 1.0) { - float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation); - vec3 spot_dir = light_direction; - - float spot_cutoff = light_spot_angle; - - float angle = dot(-normalize(light_rel_vec), spot_dir); - - if (angle > spot_cutoff) { - float scos = max(angle, spot_cutoff); - float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff)); - - spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation); - - light_att = vec3(spot_attenuation); - } else { - light_att = vec3(0.0); - } - } else { - light_att = vec3(0.0); - } - - L = normalize(light_rel_vec); - -#endif - -#ifdef LIGHT_MODE_DIRECTIONAL - vec3 light_vec = -light_direction; - light_att = vec3(1.0); //no base attenuation - L = normalize(light_vec); -#endif - - diffuse_interp = vec3(0.0); - specular_interp = vec3(0.0); - light_compute(normal_interp, L, -normalize(vertex_interp), light_color.rgb, light_att, roughness); + // Using world coordinates +#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) + vertex = (scene_data.view_matrix * vec4(vertex, 1.0)).xyz; +#ifdef NORMAL_USED + normal = (scene_data.view_matrix * vec4(normal, 0.0)).xyz; #endif -//shadows (for both vertex and fragment) -#if defined(USE_SHADOW) && defined(USE_LIGHTING) - - vec4 vi4 = vec4(vertex_interp, 1.0); - shadow_coord = light_shadow_matrix * vi4; - -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) - shadow_coord2 = light_shadow_matrix2 * vi4; +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) + binormal = (scene_data.view_matrix * vec4(binormal, 0.0)).xyz; + tangent = (scene_data.view_matrix * vec4(tangent, 0.0)).xyz; #endif - -#if defined(LIGHT_USE_PSSM4) - shadow_coord3 = light_shadow_matrix3 * vi4; - shadow_coord4 = light_shadow_matrix4 * vi4; - #endif -#endif //use shadow and use lighting - -#ifdef USE_VERTEX_LIGHTING - -#ifdef USE_REFLECTION_PROBE1 - { - vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp)); - vec3 local_pos = (refprobe1_local_matrix * vec4(vertex_interp, 1.0)).xyz; - vec3 inner_pos = abs(local_pos / refprobe1_box_extents); - float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); - - { - vec3 local_ref_vec = (refprobe1_local_matrix * vec4(ref_normal, 0.0)).xyz; - refprobe1_reflection_normal_blend.xyz = local_ref_vec; - refprobe1_reflection_normal_blend.a = blend; - } -#ifndef USE_LIGHTMAP - - refprobe1_ambient_normal = (refprobe1_local_matrix * vec4(normal_interp, 0.0)).xyz; -#endif - } - -#endif //USE_REFLECTION_PROBE1 - -#ifdef USE_REFLECTION_PROBE2 - { - vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp)); - vec3 local_pos = (refprobe2_local_matrix * vec4(vertex_interp, 1.0)).xyz; - vec3 inner_pos = abs(local_pos / refprobe2_box_extents); - float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); - - { - vec3 local_ref_vec = (refprobe2_local_matrix * vec4(ref_normal, 0.0)).xyz; - refprobe2_reflection_normal_blend.xyz = local_ref_vec; - refprobe2_reflection_normal_blend.a = blend; - } -#ifndef USE_LIGHTMAP - - refprobe2_ambient_normal = (refprobe2_local_matrix * vec4(normal_interp, 0.0)).xyz; -#endif - } - -#endif //USE_REFLECTION_PROBE2 - -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - - float fog_amount = 0.0; - -#ifdef LIGHT_MODE_DIRECTIONAL - - vec3 fog_color = mix(fog_color_base.rgb, fog_sun_color_amount.rgb, fog_sun_color_amount.a * pow(max(dot(normalize(vertex_interp), light_direction), 0.0), 8.0)); -#else - vec3 fog_color = fog_color_base.rgb; -#endif - -#ifdef FOG_DEPTH_ENABLED - - { - float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); - - fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a; - } + vertex_interp = vertex; +#ifdef NORMAL_USED + normal_interp = normal; #endif -#ifdef FOG_HEIGHT_ENABLED - { - float y = (inv_view_matrix * vec4(vertex_interp, 1.0)).y; - fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); - } +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) + tangent_interp = tangent; + binormal_interp = binormal; #endif - fog_interp = vec4(fog_color, fog_amount); - -#endif //fog - -#endif //use vertex lighting #if defined(OVERRIDE_POSITION) gl_Position = position; #else gl_Position = projection_matrix * vec4(vertex_interp, 1.0); #endif - -#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS) - position_interp = gl_Position; -#endif } /* clang-format off */ -[fragment] - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif - -#define M_PI 3.14159265359 -#define SHADER_IS_SRGB true - -// -// uniforms -// - -uniform highp mat4 inv_view_matrix; -/* clang-format on */ -uniform highp mat4 view_matrix; -uniform highp mat4 projection_matrix; -uniform highp mat4 projection_inverse_matrix; - -uniform highp mat4 world_transform; +#[fragment] -uniform highp float time; -uniform highp vec2 viewport_size; - -#if defined(SCREEN_UV_USED) -uniform vec2 screen_pixel_size; +// Default to SPECULAR_SCHLICK_GGX. +#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_TOON) +#define SPECULAR_SCHLICK_GGX #endif -#if defined(SCREEN_TEXTURE_USED) -uniform highp sampler2D screen_texture; //texunit:-4 +#if !defined(MODE_RENDER_DEPTH) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) ||defined(LIGHT_CLEARCOAT_USED) +#ifndef NORMAL_USED +#define NORMAL_USED #endif -#if defined(DEPTH_TEXTURE_USED) -uniform highp sampler2D depth_texture; //texunit:-4 #endif -#ifdef USE_REFLECTION_PROBE1 +#include "tonemap_inc.glsl" +#include "stdlib_inc.glsl" -#ifdef USE_VERTEX_LIGHTING +/* texture unit usage, N is max_texture_unity-N -in mediump vec4 refprobe1_reflection_normal_blend; -#ifndef USE_LIGHTMAP -in mediump vec3 refprobe1_ambient_normal; -#endif - -#else +1-color correction // In tonemap_inc.glsl +2-radiance +3-directional_shadow +4-positional_shadow +5-screen +6-depth -uniform bool refprobe1_use_box_project; -uniform highp vec3 refprobe1_box_extents; -uniform vec3 refprobe1_box_offset; -uniform highp mat4 refprobe1_local_matrix; - -#endif //use vertex lighting - -uniform bool refprobe1_exterior; - -uniform highp samplerCube reflection_probe1; //texunit:-5 +*/ -uniform float refprobe1_intensity; -uniform vec4 refprobe1_ambient; +#define M_PI 3.14159265359 +/* clang-format on */ -#endif //USE_REFLECTION_PROBE1 +#define SHADER_IS_SRGB true -#ifdef USE_REFLECTION_PROBE2 +/* Varyings */ -#ifdef USE_VERTEX_LIGHTING +#if defined(COLOR_USED) +in vec4 color_interp; +#endif -in mediump vec4 refprobe2_reflection_normal_blend; -#ifndef USE_LIGHTMAP -in mediump vec3 refprobe2_ambient_normal; +#if defined(UV_USED) +in vec2 uv_interp; #endif +#if defined(UV2_USED) +in vec2 uv2_interp; #else - -uniform bool refprobe2_use_box_project; -uniform highp vec3 refprobe2_box_extents; -uniform vec3 refprobe2_box_offset; -uniform highp mat4 refprobe2_local_matrix; - -#endif //use vertex lighting - -uniform bool refprobe2_exterior; - -uniform highp samplerCube reflection_probe2; //texunit:-6 - -uniform float refprobe2_intensity; -uniform vec4 refprobe2_ambient; - -#endif //USE_REFLECTION_PROBE2 - -#define RADIANCE_MAX_LOD 6.0 - -#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) - -void reflection_process(samplerCube reflection_map, -#ifdef USE_VERTEX_LIGHTING - vec3 ref_normal, -#ifndef USE_LIGHTMAP - vec3 amb_normal, +#ifdef USE_LIGHTMAP +in vec2 uv2_interp; #endif - float ref_blend, - -#else //no vertex lighting - vec3 normal, vec3 vertex, - mat4 local_matrix, - bool use_box_project, vec3 box_extents, vec3 box_offset, -#endif //vertex lighting - bool exterior, float intensity, vec4 ref_ambient, float roughness, vec3 ambient, vec3 skybox, inout highp vec4 reflection_accum, inout highp vec4 ambient_accum) { - vec4 reflection; - -#ifdef USE_VERTEX_LIGHTING - - reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb; - - float blend = ref_blend; //crappier blend formula for vertex - blend *= blend; - blend = max(0.0, 1.0 - blend); - -#else //fragment lighting - - vec3 local_pos = (local_matrix * vec4(vertex, 1.0)).xyz; - - if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box - return; - } - - vec3 inner_pos = abs(local_pos / box_extents); - float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); - blend = mix(length(inner_pos), blend, blend); - blend *= blend; - blend = max(0.0, 1.0 - blend); - - //reflect and make local - vec3 ref_normal = normalize(reflect(vertex, normal)); - ref_normal = (local_matrix * vec4(ref_normal, 0.0)).xyz; - - if (use_box_project) { //box project - - vec3 nrdir = normalize(ref_normal); - vec3 rbmax = (box_extents - local_pos) / nrdir; - vec3 rbmin = (-box_extents - local_pos) / nrdir; - - vec3 rbminmax = mix(rbmin, rbmax, vec3(greaterThan(nrdir, vec3(0.0, 0.0, 0.0)))); - - float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z); - vec3 posonbox = local_pos + nrdir * fa; - ref_normal = posonbox - box_offset.xyz; - } - - reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb; #endif - if (exterior) { - reflection.rgb = mix(skybox, reflection.rgb, blend); - } - reflection.rgb *= intensity; - reflection.a = blend; - reflection.rgb *= blend; - - reflection_accum += reflection; - -#ifndef USE_LIGHTMAP - - vec4 ambient_out; -#ifndef USE_VERTEX_LIGHTING +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) +in vec3 tangent_interp; +in vec3 binormal_interp; +#endif - vec3 amb_normal = (local_matrix * vec4(normal, 0.0)).xyz; +#ifdef NORMAL_USED +in vec3 normal_interp; #endif - ambient_out.rgb = textureCubeLod(reflection_map, amb_normal, RADIANCE_MAX_LOD).rgb; - ambient_out.rgb = mix(ref_ambient.rgb, ambient_out.rgb, ref_ambient.a); - if (exterior) { - ambient_out.rgb = mix(ambient, ambient_out.rgb, blend); - } +in highp vec3 vertex_interp; - ambient_out.a = blend; - ambient_out.rgb *= blend; - ambient_accum += ambient_out; +#ifdef USE_RADIANCE_MAP -#endif -} +#define RADIANCE_MAX_LOD 5.0 -#endif //use refprobe 1 or 2 +uniform samplerCube radiance_map; // texunit:-2 -#ifdef USE_LIGHTMAP -uniform mediump sampler2D lightmap; //texunit:-4 -uniform mediump float lightmap_energy; #endif -#ifdef USE_LIGHTMAP_CAPTURE -uniform mediump vec4[12] lightmap_captures; -uniform bool lightmap_capture_sky; +layout(std140) uniform GlobalVariableData { //ubo:1 + vec4 global_variables[MAX_GLOBAL_VARIABLES]; +}; -#endif + /* Material Uniforms */ -#ifdef USE_RADIANCE_MAP +#if defined(MATERIAL_UNIFORMS_USED) -uniform samplerCube radiance_map; // texunit:-2 +/* clang-format off */ +layout(std140) uniform MaterialUniforms { // ubo:3 -uniform mat4 radiance_inverse_xform; +#MATERIAL_UNIFORMS -#endif +}; +/* clang-format on */ -uniform vec4 bg_color; -uniform float bg_energy; +#endif -uniform float ambient_sky_contribution; -uniform vec4 ambient_color; -uniform float ambient_energy; +layout(std140) uniform SceneData { // ubo:2 + highp mat4 projection_matrix; + highp mat4 inv_projection_matrix; + highp mat4 inv_view_matrix; + highp mat4 view_matrix; -#ifdef USE_LIGHTING + vec2 viewport_size; + vec2 screen_pixel_size; -uniform highp vec4 shadow_color; + mediump vec4 ambient_light_color_energy; -#ifdef USE_VERTEX_LIGHTING + mediump float ambient_color_sky_mix; + bool material_uv2_mode; + float pad2; + bool use_ambient_light; + bool use_ambient_cubemap; + bool use_reflection_cubemap; -//get from vertex -in highp vec3 diffuse_interp; -in highp vec3 specular_interp; + float fog_aerial_perspective; + float time; -uniform highp vec3 light_direction; //may be used by fog, so leave here + mat3 radiance_inverse_xform; -#else -//done in fragment -// general for all lights -uniform highp vec4 light_color; + uint directional_light_count; + float z_far; + float z_near; + float pad; -uniform highp float light_specular; + bool fog_enabled; + float fog_density; + float fog_height; + float fog_height_density; -// directional -uniform highp vec3 light_direction; -// omni -uniform highp vec3 light_position; - -uniform highp float light_attenuation; + vec3 fog_light_color; + float fog_sun_scatter; +} +scene_data; -// spot -uniform highp float light_spot_attenuation; -uniform highp float light_spot_range; -uniform highp float light_spot_angle; -#endif +/* clang-format off */ -//this is needed outside above if because dual paraboloid wants it -uniform highp float light_range; +#GLOBALS -#ifdef USE_SHADOW +/* clang-format on */ -uniform highp vec2 shadow_pixel_size; +//directional light data -#if defined(LIGHT_MODE_OMNI) || defined(LIGHT_MODE_SPOT) -uniform highp sampler2D light_shadow_atlas; //texunit:-3 -#endif +#ifndef DISABLE_LIGHT_DIRECTIONAL -#ifdef LIGHT_MODE_DIRECTIONAL -uniform highp sampler2D light_directional_shadow; // texunit:-3 -uniform highp vec4 light_split_offsets; -#endif +struct DirectionalLightData { + mediump vec3 direction; + mediump float energy; + mediump vec3 color; + mediump float size; + mediump vec3 pad; + mediump float specular; +}; -in highp vec4 shadow_coord; +layout(std140) uniform DirectionalLights { // ubo:7 + DirectionalLightData directional_lights[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; +}; -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) -in highp vec4 shadow_coord2; #endif -#if defined(LIGHT_USE_PSSM4) - -in highp vec4 shadow_coord3; -in highp vec4 shadow_coord4; - -#endif +// omni and spot +#if !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT) +struct LightData { //this structure needs to be as packed as possible + highp vec3 position; + highp float inv_radius; -uniform vec4 light_clamp; + mediump vec3 direction; + highp float size; -#endif // light shadow + mediump vec3 color; + mediump float attenuation; -// directional shadow + mediump float cone_attenuation; + mediump float cone_angle; + mediump float specular_amount; + bool shadow_enabled; +}; +#ifndef DISABLE_LIGHT_OMNI +layout(std140) uniform OmniLightData { // ubo:5 + LightData omni_lights[MAX_LIGHT_DATA_STRUCTS]; +}; +uniform uint omni_light_indices[MAX_FORWARD_LIGHTS]; +uniform int omni_light_count; #endif -// -// varyings -// +#ifndef DISABLE_LIGHT_SPOT -#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS) -in highp vec4 position_interp; -#endif - -in highp vec3 vertex_interp; -in vec3 normal_interp; +layout(std140) uniform SpotLightData { // ubo:6 -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -in vec3 tangent_interp; -in vec3 binormal_interp; + LightData spot_lights[MAX_LIGHT_DATA_STRUCTS]; +}; +uniform uint spot_light_indices[MAX_FORWARD_LIGHTS]; +uniform int spot_light_count; #endif -#if defined(ENABLE_COLOR_INTERP) -in vec4 color_interp; +#ifdef USE_ADDITIVE_LIGHTING +uniform highp samplerCubeShadow positional_shadow; // texunit:-4 #endif -#if defined(ENABLE_UV_INTERP) -in vec2 uv_interp; -#endif +#endif // !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT) -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) -in vec2 uv2_interp; -#endif +uniform highp sampler2D screen_texture; // texunit:-5 +uniform highp sampler2D depth_buffer; // texunit:-6 -in vec3 view_interp; +uniform highp mat4 world_transform; +uniform mediump float opaque_prepass_threshold; layout(location = 0) out vec4 frag_color; @@ -985,95 +517,31 @@ vec3 F0(float metallic, float specular, vec3 albedo) { return mix(vec3(dielectric), albedo, vec3(metallic)); } -/* clang-format off */ - -FRAGMENT_SHADER_GLOBALS - -/* clang-format on */ - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - -in highp float dp_clip; - -#endif - -#ifdef USE_LIGHTING - -// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V. -// We're dividing this factor off because the overall term we'll end up looks like -// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012): -// -// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V) -// -// We're basically regouping this as -// -// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)] -// -// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V. -// -// The contents of the D and G (G1) functions (GGX) are taken from -// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014). -// Eqns 71-72 and 85-86 (see also Eqns 43 and 80). - -/* -float G_GGX_2cos(float cos_theta_m, float alpha) { - // Schlick's approximation - // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994) - // Eq. (19), although see Heitz (2014) the about the problems with his derivation. - // It nevertheless approximates GGX well with k = alpha/2. - float k = 0.5 * alpha; - return 0.5 / (cos_theta_m * (1.0 - k) + k); - - // float cos2 = cos_theta_m * cos_theta_m; - // float sin2 = (1.0 - cos2); - // return 1.0 / (cos_theta_m + sqrt(cos2 + alpha * alpha * sin2)); -} -*/ - -// This approximates G_GGX_2cos(cos_theta_l, alpha) * G_GGX_2cos(cos_theta_v, alpha) -// See Filament docs, Specular G section. -float V_GGX(float cos_theta_l, float cos_theta_v, float alpha) { - return 0.5 / mix(2.0 * cos_theta_l * cos_theta_v, cos_theta_l + cos_theta_v, alpha); -} - +#if !defined(DISABLE_LIGHT_DIRECTIONAL) || !defined(DISABLE_LIGHT_OMNI) || !defined(DISABLE_LIGHT_SPOT) float D_GGX(float cos_theta_m, float alpha) { - float alpha2 = alpha * alpha; - float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m; - return alpha2 / (M_PI * d * d); -} - -/* -float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { - float cos2 = cos_theta_m * cos_theta_m; - float sin2 = (1.0 - cos2); - float s_x = alpha_x * cos_phi; - float s_y = alpha_y * sin_phi; - return 1.0 / max(cos_theta_m + sqrt(cos2 + (s_x * s_x + s_y * s_y) * sin2), 0.001); + float a = cos_theta_m * alpha; + float k = alpha / (1.0 - cos_theta_m * cos_theta_m + a * a); + return k * k * (1.0 / M_PI); } -*/ -// This approximates G_GGX_anisotropic_2cos(cos_theta_l, ...) * G_GGX_anisotropic_2cos(cos_theta_v, ...) -// See Filament docs, Anisotropic specular BRDF section. -float V_GGX_anisotropic(float alpha_x, float alpha_y, float TdotV, float TdotL, float BdotV, float BdotL, float NdotV, float NdotL) { - float Lambda_V = NdotL * length(vec3(alpha_x * TdotV, alpha_y * BdotV, NdotV)); - float Lambda_L = NdotV * length(vec3(alpha_x * TdotL, alpha_y * BdotL, NdotL)); - return 0.5 / (Lambda_V + Lambda_L); +// From Earl Hammon, Jr. "PBR Diffuse Lighting for GGX+Smith Microsurfaces" https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX +float V_GGX(float NdotL, float NdotV, float alpha) { + return 0.5 / mix(2.0 * NdotL * NdotV, NdotL + NdotV, alpha); } -float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi, float NdotH) { +float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { float alpha2 = alpha_x * alpha_y; - highp vec3 v = vec3(alpha_y * cos_phi, alpha_x * sin_phi, alpha2 * NdotH); + highp vec3 v = vec3(alpha_y * cos_phi, alpha_x * sin_phi, alpha2 * cos_theta_m); highp float v2 = dot(v, v); float w2 = alpha2 / v2; float D = alpha2 * w2 * w2 * (1.0 / M_PI); return D; +} - /* float cos2 = cos_theta_m * cos_theta_m; - float sin2 = (1.0 - cos2); - float r_x = cos_phi / alpha_x; - float r_y = sin_phi / alpha_y; - float d = cos2 + sin2 * (r_x * r_x + r_y * r_y); - return 1.0 / max(M_PI * alpha_x * alpha_y * d * d, 0.001); */ +float V_GGX_anisotropic(float alpha_x, float alpha_y, float TdotV, float TdotL, float BdotV, float BdotL, float NdotV, float NdotL) { + float Lambda_V = NdotL * length(vec3(alpha_x * TdotV, alpha_y * BdotV, NdotV)); + float Lambda_L = NdotV * length(vec3(alpha_x * TdotL, alpha_y * BdotL, NdotL)); + return 0.5 / (Lambda_V + Lambda_L); } float SchlickFresnel(float u) { @@ -1082,109 +550,59 @@ float SchlickFresnel(float u) { return m2 * m2 * m; // pow(m,5) } -float GTR1(float NdotH, float a) { - if (a >= 1.0) - return 1.0 / M_PI; - float a2 = a * a; - float t = 1.0 + (a2 - 1.0) * NdotH * NdotH; - return (a2 - 1.0) / (M_PI * log(a2) * t); -} - -void light_compute( - vec3 N, - vec3 L, - vec3 V, - vec3 B, - vec3 T, - vec3 light_color, - vec3 attenuation, - vec3 diffuse_color, - vec3 transmission, - float specular_blob_intensity, - float roughness, - float metallic, - float specular, - float rim, - float rim_tint, - float clearcoat, - float clearcoat_roughness, - float anisotropy, - inout vec3 diffuse_light, - inout vec3 specular_light, - inout float alpha) { -//this makes lights behave closer to linear, but then addition of lights looks bad -//better left disabled - -//#define SRGB_APPROX(m_var) m_var = pow(m_var,0.4545454545); -/* -#define SRGB_APPROX(m_var) {\ - float S1 = sqrt(m_var);\ - float S2 = sqrt(S1);\ - float S3 = sqrt(S2);\ - m_var = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * m_var;\ - } -*/ -#define SRGB_APPROX(m_var) +void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, float roughness, float metallic, float specular_amount, vec3 albedo, inout float alpha, +#ifdef LIGHT_BACKLIGHT_USED + vec3 backlight, +#endif +#ifdef LIGHT_RIM_USED + float rim, float rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + float clearcoat, float clearcoat_roughness, vec3 vertex_normal, +#endif +#ifdef LIGHT_ANISOTROPY_USED + vec3 B, vec3 T, float anisotropy, +#endif + inout vec3 diffuse_light, inout vec3 specular_light) { #if defined(USE_LIGHT_SHADER_CODE) // light is written by the light shader vec3 normal = N; - vec3 albedo = diffuse_color; vec3 light = L; vec3 view = V; /* clang-format off */ -LIGHT_SHADER_CODE + +#CODE : LIGHT /* clang-format on */ #else - float NdotL = dot(N, L); + float NdotL = min(A + dot(N, L), 1.0); float cNdotL = max(NdotL, 0.0); // clamped NdotL float NdotV = dot(N, V); - float cNdotV = max(abs(NdotV), 1e-6); + float cNdotV = max(NdotV, 1e-4); -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) vec3 H = normalize(V + L); #endif -#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) - float cNdotH = max(dot(N, H), 0.0); +#if defined(SPECULAR_SCHLICK_GGX) + float cNdotH = clamp(A + dot(N, H), 0.0, 1.0); #endif -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) - float cLdotH = max(dot(L, H), 0.0); +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) + float cLdotH = clamp(A + dot(L, H), 0.0, 1.0); #endif if (metallic < 1.0) { -#if defined(DIFFUSE_OREN_NAYAR) - vec3 diffuse_brdf_NL; -#else float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance -#endif #if defined(DIFFUSE_LAMBERT_WRAP) // energy conserving lambert wrap shader diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); - -#elif defined(DIFFUSE_OREN_NAYAR) - - { - // see http://mimosa-pudica.net/improved-oren-nayar.html - float LdotV = dot(L, V); - - float s = LdotV - NdotL * NdotV; - float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); - - float sigma2 = roughness * roughness; // TODO: this needs checking - vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); - float B = 0.45 * sigma2 / (sigma2 + 0.09); - - diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); - } - #elif defined(DIFFUSE_TOON) diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); @@ -1196,230 +614,250 @@ LIGHT_SHADER_CODE float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV); float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL); diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; - /* - float energyBias = mix(roughness, 0.0, 0.5); - float energyFactor = mix(roughness, 1.0, 1.0 / 1.51); - float fd90 = energyBias + 2.0 * VoH * VoH * roughness; - float f0 = 1.0; - float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0); - float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0); - - diffuse_brdf_NL = lightScatter * viewScatter * energyFactor; - */ } #else // lambert diffuse_brdf_NL = cNdotL * (1.0 / M_PI); #endif - SRGB_APPROX(diffuse_brdf_NL) - - diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation; + diffuse_light += light_color * diffuse_brdf_NL * attenuation; -#if defined(TRANSMISSION_USED) - diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation; +#if defined(LIGHT_BACKLIGHT_USED) + diffuse_light += light_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation; #endif -#if defined(LIGHT_USE_RIM) +#if defined(LIGHT_RIM_USED) float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); - diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color; + diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color; #endif } - if (roughness > 0.0) { - -#if defined(SPECULAR_SCHLICK_GGX) - vec3 specular_brdf_NL = vec3(0.0); -#else - float specular_brdf_NL = 0.0; -#endif + if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely -#if defined(SPECULAR_BLINN) - - //normalized blinn - float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess) * cNdotL; - blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - specular_brdf_NL = blinn; - -#elif defined(SPECULAR_PHONG) - - vec3 R = normalize(-reflect(L, N)); - float cRdotV = max(0.0, dot(R, V)); - float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float phong = pow(cRdotV, shininess); - phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - specular_brdf_NL = (phong) / max(4.0 * cNdotV * cNdotL, 0.75); + // D -#elif defined(SPECULAR_TOON) +#if defined(SPECULAR_TOON) vec3 R = normalize(-reflect(L, N)); float RdotV = dot(R, V); float mid = 1.0 - roughness; mid *= mid; - specular_brdf_NL = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid; + float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid; + diffuse_light += light_color * intensity * attenuation * specular_amount; // write to diffuse_light, as in toon shading you generally want no reflection #elif defined(SPECULAR_DISABLED) // none.. + #elif defined(SPECULAR_SCHLICK_GGX) // shlick+ggx as default - -#if defined(LIGHT_USE_ANISOTROPY) float alpha_ggx = roughness * roughness; +#if defined(LIGHT_ANISOTROPY_USED) + float aspect = sqrt(1.0 - anisotropy * 0.9); float ax = alpha_ggx / aspect; float ay = alpha_ggx * aspect; float XdotH = dot(T, H); float YdotH = dot(B, H); - float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH, cNdotH); - //float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); + float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH); float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL); - -#else - float alpha_ggx = roughness * roughness; +#else // LIGHT_ANISOTROPY_USED float D = D_GGX(cNdotH, alpha_ggx); - //float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx); float G = V_GGX(cNdotL, cNdotV, alpha_ggx); -#endif - // F - vec3 f0 = F0(metallic, specular, diffuse_color); +#endif // LIGHT_ANISOTROPY_USED + // F float cLdotH5 = SchlickFresnel(cLdotH); vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); - specular_brdf_NL = cNdotL * D * F * G; + vec3 specular_brdf_NL = cNdotL * D * F * G; + specular_light += specular_brdf_NL * light_color * attenuation * specular_amount; #endif - SRGB_APPROX(specular_brdf_NL) - specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; - -#if defined(LIGHT_USE_CLEARCOAT) +#if defined(LIGHT_CLEARCOAT_USED) + // Clearcoat ignores normal_map, use vertex normal instead + float ccNdotL = max(min(A + dot(vertex_normal, L), 1.0), 0.0); + float ccNdotH = clamp(A + dot(vertex_normal, H), 0.0, 1.0); + float ccNdotV = max(dot(vertex_normal, V), 1e-4); #if !defined(SPECULAR_SCHLICK_GGX) float cLdotH5 = SchlickFresnel(cLdotH); #endif - float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_roughness)); + float Dr = D_GGX(ccNdotH, mix(0.001, 0.1, clearcoat_roughness)); + float Gr = 0.25 / (cLdotH * cLdotH); float Fr = mix(.04, 1.0, cLdotH5); - //float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); - float Gr = V_GGX(cNdotL, cNdotV, 0.25); + float clearcoat_specular_brdf_NL = clearcoat * Gr * Fr * Dr * cNdotL; - float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; - - specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; -#endif + specular_light += clearcoat_specular_brdf_NL * light_color * attenuation * specular_amount; + // TODO: Clearcoat adds light to the scene right now (it is non-energy conserving), both diffuse and specular need to be scaled by (1.0 - FR) + // but to do so we need to rearrange this entire function +#endif // LIGHT_CLEARCOAT_USED } #ifdef USE_SHADOW_TO_OPACITY - alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0)); + alpha = min(alpha, clamp(1.0 - attenuation, 0.0, 1.0)); #endif -#endif //defined(USE_LIGHT_SHADER_CODE) +#endif //defined(LIGHT_CODE_USED) } -#endif -// shadows - -#ifdef USE_SHADOW - -#ifdef USE_RGBA_SHADOWS - -#define SHADOW_DEPTH(m_val) dot(m_val, vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0)) - -#else - -#define SHADOW_DEPTH(m_val) (m_val).r +float get_omni_attenuation(float distance, float inv_range, float decay) { + float nd = distance * inv_range; + nd *= nd; + nd *= nd; // nd^4 + nd = max(1.0 - nd, 0.0); + nd *= nd; // nd^2 + return nd * pow(max(distance, 0.0001), -decay); +} +void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha, +#ifdef LIGHT_BACKLIGHT_USED + vec3 backlight, #endif - -#define SAMPLE_SHADOW_TEXEL(p_shadow, p_pos, p_depth) step(p_depth, SHADOW_DEPTH(texture(p_shadow, p_pos))) -#define SAMPLE_SHADOW_TEXEL_PROJ(p_shadow, p_pos) step(p_pos.z, SHADOW_DEPTH(textureProj(p_shadow, p_pos))) - -float sample_shadow(highp sampler2D shadow, highp vec4 spos) { -#ifdef SHADOW_MODE_PCF_13 - - spos.xyz /= spos.w; - vec2 pos = spos.xy; - float depth = spos.z; - - float avg = SAMPLE_SHADOW_TEXEL(shadow, pos, depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth); - return avg * (1.0 / 13.0); +#ifdef LIGHT_RIM_USED + float rim, float rim_tint, #endif +#ifdef LIGHT_CLEARCOAT_USED + float clearcoat, float clearcoat_roughness, vec3 vertex_normal, +#endif +#ifdef LIGHT_ANISOTROPY_USED + vec3 binormal, vec3 tangent, float anisotropy, +#endif + inout vec3 diffuse_light, inout vec3 specular_light) { + vec3 light_rel_vec = omni_lights[idx].position - vertex; + float light_length = length(light_rel_vec); + float omni_attenuation = get_omni_attenuation(light_length, omni_lights[idx].inv_radius, omni_lights[idx].attenuation); + vec3 color = omni_lights[idx].color; + float size_A = 0.0; -#ifdef SHADOW_MODE_PCF_5 - - spos.xyz /= spos.w; - vec2 pos = spos.xy; - float depth = spos.z; + if (omni_lights[idx].size > 0.0) { + float t = omni_lights[idx].size / max(0.001, light_length); + size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); + } - float avg = SAMPLE_SHADOW_TEXEL(shadow, pos, depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y), depth); - return avg * (1.0 / 5.0); + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, omni_attenuation, f0, roughness, metallic, omni_lights[idx].specular_amount, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, +#endif +#ifdef LIGHT_RIM_USED + rim * omni_attenuation, rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, vertex_normal, +#endif +#ifdef LIGHT_ANISOTROPY_USED + binormal, tangent, anisotropy, +#endif + diffuse_light, + specular_light); +} +void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha, +#ifdef LIGHT_BACKLIGHT_USED + vec3 backlight, +#endif +#ifdef LIGHT_RIM_USED + float rim, float rim_tint, #endif +#ifdef LIGHT_CLEARCOAT_USED + float clearcoat, float clearcoat_roughness, vec3 vertex_normal, +#endif +#ifdef LIGHT_ANISOTROPY_USED + vec3 binormal, vec3 tangent, float anisotropy, +#endif + inout vec3 diffuse_light, + inout vec3 specular_light) { -#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13) + vec3 light_rel_vec = spot_lights[idx].position - vertex; + float light_length = length(light_rel_vec); + float spot_attenuation = get_omni_attenuation(light_length, spot_lights[idx].inv_radius, spot_lights[idx].attenuation); + vec3 spot_dir = spot_lights[idx].direction; + float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights[idx].cone_angle); + float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights[idx].cone_angle)); + spot_attenuation *= 1.0 - pow(spot_rim, spot_lights[idx].cone_attenuation); + vec3 color = spot_lights[idx].color; + + float size_A = 0.0; + + if (spot_lights[idx].size > 0.0) { + float t = spot_lights[idx].size / max(0.001, light_length); + size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); + } - return SAMPLE_SHADOW_TEXEL_PROJ(shadow, spos); + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, spot_attenuation, f0, roughness, metallic, spot_lights[idx].specular_amount, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, +#endif +#ifdef LIGHT_RIM_USED + rim * spot_attenuation, rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, vertex_normal, +#endif +#ifdef LIGHT_ANISOTROPY_USED + binormal, tangent, anisotropy, #endif + diffuse_light, specular_light); } +#endif // !defined(DISABLE_LIGHT_DIRECTIONAL) || !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT) -#endif +#ifndef MODE_RENDER_DEPTH +vec4 fog_process(vec3 vertex) { + vec3 fog_color = scene_data.fog_light_color; -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) +#ifdef USE_RADIANCE_MAP +/* + if (scene_data.fog_aerial_perspective > 0.0) { + vec3 sky_fog_color = vec3(0.0); + vec3 cube_view = scene_data.radiance_inverse_xform * vertex; + // mip_level always reads from the second mipmap and higher so the fog is always slightly blurred + float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)); -#if defined(USE_VERTEX_LIGHTING) + sky_fog_color = textureCubeLod(radiance_map, cube_view, mip_level * RADIANCE_MAX_LOD).rgb; -in vec4 fog_interp; + fog_color = mix(fog_color, sky_fog_color, scene_data.fog_aerial_perspective); + } + */ +#endif + +#ifndef DISABLE_LIGHT_DIRECTIONAL + if (scene_data.fog_sun_scatter > 0.001) { + vec4 sun_scatter = vec4(0.0); + float sun_total = 0.0; + vec3 view = normalize(vertex); + for (uint i = uint(0); i < scene_data.directional_light_count; i++) { + vec3 light_color = directional_lights[i].color * directional_lights[i].energy; + float light_amount = pow(max(dot(view, directional_lights[i].direction), 0.0), 8.0); + fog_color += light_color * light_amount * scene_data.fog_sun_scatter; + } + } +#endif // !DISABLE_LIGHT_DIRECTIONAL -#else -uniform mediump vec4 fog_color_base; -#ifdef LIGHT_MODE_DIRECTIONAL -uniform mediump vec4 fog_sun_color_amount; -#endif + float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density)); -uniform bool fog_transmit_enabled; -uniform mediump float fog_transmit_curve; + if (abs(scene_data.fog_height_density) >= 0.0001) { + float y = (scene_data.inv_view_matrix * vec4(vertex, 1.0)).y; -#ifdef FOG_DEPTH_ENABLED -uniform highp float fog_depth_begin; -uniform mediump float fog_depth_curve; -uniform mediump float fog_max_distance; -#endif + float y_dist = y - scene_data.fog_height; -#ifdef FOG_HEIGHT_ENABLED -uniform highp float fog_height_min; -uniform highp float fog_height_max; -uniform mediump float fog_height_curve; -#endif + float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density)); -#endif //vertex lit -#endif //fog + fog_amount = max(vfog_amount, fog_amount); + } -void main() { -#ifdef RENDER_DEPTH_DUAL_PARABOLOID + return vec4(fog_color, fog_amount); +} - if (dp_clip > 0.0) - discard; -#endif - highp vec3 vertex = vertex_interp; +#endif // !MODE_RENDER_DEPTH + +void main() { + //lay out everything, whatever is unused is optimized away anyway + vec3 vertex = vertex_interp; vec3 view = -normalize(vertex_interp); vec3 albedo = vec3(1.0); - vec3 transmission = vec3(0.0); + vec3 backlight = vec3(0.0); + vec4 transmittance_color = vec4(0.0, 0.0, 0.0, 1.0); + float transmittance_depth = 0.0; + float transmittance_boost = 0.0; float metallic = 0.0; float specular = 0.5; vec3 emission = vec3(0.0); @@ -1430,617 +868,304 @@ void main() { float clearcoat_roughness = 0.0; float anisotropy = 0.0; vec2 anisotropy_flow = vec2(1.0, 0.0); - float sss_strength = 0.0; //unused - // gl_FragDepth is not available in GLES2, so writing to DEPTH is not converted to gl_FragDepth by Godot compiler resulting in a - // compile error because DEPTH is not a variable. - float m_DEPTH = 0.0; - - float alpha = 1.0; - float side = 1.0; - - float specular_blob_intensity = 1.0; -#if defined(SPECULAR_TOON) - specular_blob_intensity *= specular * 2.0; + vec4 fog = vec4(0.0); +#if defined(CUSTOM_RADIANCE_USED) + vec4 custom_radiance = vec4(0.0); +#endif +#if defined(CUSTOM_IRRADIANCE_USED) + vec4 custom_irradiance = vec4(0.0); #endif -#if defined(ENABLE_AO) float ao = 1.0; float ao_light_affect = 0.0; -#endif -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - vec3 binormal = normalize(binormal_interp) * side; - vec3 tangent = normalize(tangent_interp) * side; + float alpha = 1.0; + +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) + vec3 binormal = normalize(binormal_interp); + vec3 tangent = normalize(tangent_interp); #else vec3 binormal = vec3(0.0); vec3 tangent = vec3(0.0); #endif - vec3 normal = normalize(normal_interp) * side; -#if defined(ENABLE_NORMALMAP) - vec3 normalmap = vec3(0.5); +#ifdef NORMAL_USED + vec3 normal = normalize(normal_interp); + +#if defined(DO_SIDE_CHECK) + if (!gl_FrontFacing) { + normal = -normal; + } #endif - float normaldepth = 1.0; -#if defined(ALPHA_SCISSOR_USED) - float alpha_scissor = 0.5; +#endif //NORMAL_USED + +#ifdef UV_USED + vec2 uv = uv_interp; #endif -#if defined(SCREEN_UV_USED) - vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; +#if defined(UV2_USED) || defined(USE_LIGHTMAP) + vec2 uv2 = uv2_interp; #endif - { - /* clang-format off */ +#if defined(COLOR_USED) + vec4 color = color_interp; +#endif -FRAGMENT_SHADER_CODE +#if defined(NORMAL_MAP_USED) - /* clang-format on */ - } + vec3 normal_map = vec3(0.5); +#endif -#if defined(ENABLE_NORMALMAP) - normalmap.xy = normalmap.xy * 2.0 - 1.0; - normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); + float normal_map_depth = 1.0; - normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side; - //normal = normalmap; -#endif + vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size; - normal = normalize(normal); + float sss_strength = 0.0; - vec3 N = normal; +#ifdef ALPHA_SCISSOR_USED + float alpha_scissor_threshold = 1.0; +#endif // ALPHA_SCISSOR_USED - vec3 specular_light = vec3(0.0, 0.0, 0.0); - vec3 diffuse_light = vec3(0.0, 0.0, 0.0); - vec3 ambient_light = vec3(0.0, 0.0, 0.0); +#ifdef ALPHA_HASH_USED + float alpha_hash_scale = 1.0; +#endif // ALPHA_HASH_USED - vec3 eye_position = view; +#ifdef ALPHA_ANTIALIASING_EDGE_USED + float alpha_antialiasing_edge = 0.0; + vec2 alpha_texture_coordinate = vec2(0.0, 0.0); +#endif // ALPHA_ANTIALIASING_EDGE_USED + { +#CODE : FRAGMENT + } -#if !defined(USE_SHADOW_TO_OPACITY) +#ifndef USE_SHADOW_TO_OPACITY #if defined(ALPHA_SCISSOR_USED) - if (alpha < alpha_scissor) { + if (alpha < alpha_scissor_threshold) { discard; } #endif // ALPHA_SCISSOR_USED -#ifdef USE_DEPTH_PREPASS - if (alpha < 0.1) { +#ifdef USE_OPAQUE_PREPASS +#if !defined(ALPHA_SCISSOR_USED) + + if (alpha < opaque_prepass_threshold) { discard; } -#endif // USE_DEPTH_PREPASS -#endif // !USE_SHADOW_TO_OPACITY +#endif // not ALPHA_SCISSOR_USED +#endif // USE_OPAQUE_PREPASS -#ifdef BASE_PASS - - // IBL precalculations - float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0); - vec3 f0 = F0(metallic, specular, albedo); - vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0); +#endif // !USE_SHADOW_TO_OPACITY -#ifdef AMBIENT_LIGHT_DISABLED - ambient_light = vec3(0.0, 0.0, 0.0); -#else +#ifdef NORMAL_MAP_USED -#ifdef USE_RADIANCE_MAP + normal_map.xy = normal_map.xy * 2.0 - 1.0; + normal_map.z = sqrt(max(0.0, 1.0 - dot(normal_map.xy, normal_map.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. - vec3 ref_vec = reflect(-eye_position, N); - ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz); + normal = normalize(mix(normal, tangent * normal_map.x + binormal * normal_map.y + normal * normal_map.z, normal_map_depth)); - ref_vec.z *= -1.0; +#endif - specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy; -#ifndef USE_LIGHTMAP - { - vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz); - vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, 4.0).xyz * bg_energy; - env_ambient *= 1.0 - F; +#ifdef LIGHT_ANISOTROPY_USED - ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution); + if (anisotropy > 0.01) { + //rotation matrix + mat3 rot = mat3(tangent, binormal, normal); + //make local to space + tangent = normalize(rot * vec3(anisotropy_flow.x, anisotropy_flow.y, 0.0)); + binormal = normalize(rot * vec3(-anisotropy_flow.y, anisotropy_flow.x, 0.0)); } + #endif -#else +#ifndef MODE_RENDER_DEPTH - ambient_light = ambient_color.rgb; - specular_light = bg_color.rgb * bg_energy; +#ifndef CUSTOM_FOG_USED +#ifndef DISABLE_FOG + // fog must be processed as early as possible and then packed. + // to maximize VGPR usage -#endif -#endif // AMBIENT_LIGHT_DISABLED - ambient_light *= ambient_energy; + if (scene_data.fog_enabled) { + fog = fog_process(vertex); + } +#endif // !DISABLE_FOG +#endif //!CUSTOM_FOG_USED -#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) + uint fog_rg = packHalf2x16(fog.rg); + uint fog_ba = packHalf2x16(fog.ba); - vec4 ambient_accum = vec4(0.0); - vec4 reflection_accum = vec4(0.0); +#endif //!MODE_RENDER_DEPTH -#ifdef USE_REFLECTION_PROBE1 +#ifndef MODE_RENDER_DEPTH - reflection_process(reflection_probe1, -#ifdef USE_VERTEX_LIGHTING - refprobe1_reflection_normal_blend.rgb, -#ifndef USE_LIGHTMAP - refprobe1_ambient_normal, -#endif - refprobe1_reflection_normal_blend.a, -#else - normal_interp, vertex_interp, refprobe1_local_matrix, - refprobe1_use_box_project, refprobe1_box_extents, refprobe1_box_offset, -#endif - refprobe1_exterior, refprobe1_intensity, refprobe1_ambient, roughness, - ambient_light, specular_light, reflection_accum, ambient_accum); + // Convert colors to linear + albedo = srgb_to_linear(albedo); + emission = srgb_to_linear(emission); + // TODO Backlight and transmittance when used +#ifndef MODE_UNSHADED + vec3 f0 = F0(metallic, specular, albedo); + vec3 specular_light = vec3(0.0, 0.0, 0.0); + vec3 diffuse_light = vec3(0.0, 0.0, 0.0); + vec3 ambient_light = vec3(0.0, 0.0, 0.0); -#endif // USE_REFLECTION_PROBE1 +#ifdef BASE_PASS + /////////////////////// LIGHTING ////////////////////////////// -#ifdef USE_REFLECTION_PROBE2 + // IBL precalculations + float ndotv = clamp(dot(normal, view), 0.0, 1.0); + vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0); - reflection_process(reflection_probe2, -#ifdef USE_VERTEX_LIGHTING - refprobe2_reflection_normal_blend.rgb, -#ifndef USE_LIGHTMAP - refprobe2_ambient_normal, -#endif - refprobe2_reflection_normal_blend.a, +#ifdef USE_RADIANCE_MAP + if (scene_data.use_reflection_cubemap) { +#ifdef LIGHT_ANISOTROPY_USED + // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy + vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; + vec3 anisotropic_tangent = cross(anisotropic_direction, view); + vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); + vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); + vec3 ref_vec = reflect(-view, bent_normal); #else - normal_interp, vertex_interp, refprobe2_local_matrix, - refprobe2_use_box_project, refprobe2_box_extents, refprobe2_box_offset, + vec3 ref_vec = reflect(-view, normal); +#endif + float horizon = min(1.0 + dot(ref_vec, normal), 1.0); + ref_vec = scene_data.radiance_inverse_xform * ref_vec; + specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).rgb; + specular_light = srgb_to_linear(specular_light); + specular_light *= horizon * horizon; + specular_light *= scene_data.ambient_light_color_energy.a; + } #endif - refprobe2_exterior, refprobe2_intensity, refprobe2_ambient, roughness, - ambient_light, specular_light, reflection_accum, ambient_accum); -#endif // USE_REFLECTION_PROBE2 + // Calculate Reflection probes + // Calculate Lightmaps - if (reflection_accum.a > 0.0) { - specular_light = reflection_accum.rgb / reflection_accum.a; - } +#if defined(CUSTOM_RADIANCE_USED) + specular_light = mix(specular_light, custom_radiance.rgb, custom_radiance.a); +#endif // CUSTOM_RADIANCE_USED #ifndef USE_LIGHTMAP - if (ambient_accum.a > 0.0) { - ambient_light = ambient_accum.rgb / ambient_accum.a; - } + //lightmap overrides everything + if (scene_data.use_ambient_light) { + ambient_light = scene_data.ambient_light_color_energy.rgb; +#ifdef USE_RADIANCE_MAP + if (scene_data.use_ambient_cubemap) { + vec3 ambient_dir = scene_data.radiance_inverse_xform * normal; + vec3 cubemap_ambient = textureCubeLod(radiance_map, ambient_dir, RADIANCE_MAX_LOD).rgb; + cubemap_ambient = srgb_to_linear(cubemap_ambient); + ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix); + } #endif + } +#endif // USE_LIGHTMAP + +#if defined(CUSTOM_IRRADIANCE_USED) + ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a); +#endif // CUSTOM_IRRADIANCE_USED + ambient_light *= albedo.rgb; -#endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) + ambient_light *= ao; + + // convert ao to direct light ao + ao = mix(1.0, ao, ao_light_affect); - // environment BRDF approximation { #if defined(DIFFUSE_TOON) //simplify for toon, as specular_light *= specular * metallic * albedo * 2.0; #else - // scales the specular reflections, needs to be computed before lighting happens, - // but after environment and reflection probes are added - //TODO: this curve is not really designed for gammaspace, should be adjusted + // scales the specular reflections, needs to be be computed before lighting happens, + // but after environment, GI, and reflection probes are added + // Environment brdf approximation (Lazarov 2013) + // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); vec4 r = roughness * c0 + c1; + float ndotv = clamp(dot(normal, view), 0.0, 1.0); + float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * F + env.y; - -#endif - } - -#ifdef USE_LIGHTMAP - //ambient light will come entirely from lightmap is lightmap is used - ambient_light = texture(lightmap, uv2_interp).rgb * lightmap_energy; + specular_light *= env.x * f0 + env.y; #endif - -#ifdef USE_LIGHTMAP_CAPTURE - { - vec3 cone_dirs[12]; - cone_dirs[0] = vec3(0.0, 0.0, 1.0); - cone_dirs[1] = vec3(0.866025, 0.0, 0.5); - cone_dirs[2] = vec3(0.267617, 0.823639, 0.5); - cone_dirs[3] = vec3(-0.700629, 0.509037, 0.5); - cone_dirs[4] = vec3(-0.700629, -0.509037, 0.5); - cone_dirs[5] = vec3(0.267617, -0.823639, 0.5); - cone_dirs[6] = vec3(0.0, 0.0, -1.0); - cone_dirs[7] = vec3(0.866025, 0.0, -0.5); - cone_dirs[8] = vec3(0.267617, 0.823639, -0.5); - cone_dirs[9] = vec3(-0.700629, 0.509037, -0.5); - cone_dirs[10] = vec3(-0.700629, -0.509037, -0.5); - cone_dirs[11] = vec3(0.267617, -0.823639, -0.5); - - vec3 local_normal = normalize(inv_view_matrix * vec4(normal, 0.0)).xyz; - vec4 captured = vec4(0.0); - float sum = 0.0; - for (int i = 0; i < 12; i++) { - float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect - captured += lightmap_captures[i] * amount; - sum += amount; - } - - captured /= sum; - - if (lightmap_capture_sky) { - ambient_light = mix(ambient_light, captured.rgb, captured.a); - } else { - ambient_light = captured.rgb; - } } -#endif - -#endif //BASE PASS - -// -// Lighting -// -#ifdef USE_LIGHTING -#ifndef USE_VERTEX_LIGHTING - vec3 L; -#endif - vec3 light_att = vec3(1.0); - -#ifdef LIGHT_MODE_OMNI - -#ifndef USE_VERTEX_LIGHTING - vec3 light_vec = light_position - vertex; - float light_length = length(light_vec); - - float normalized_distance = light_length / light_range; - if (normalized_distance < 1.0) { - float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation); - - light_att = vec3(omni_attenuation); - } else { - light_att = vec3(0.0); - } - L = normalize(light_vec); - -#endif - -#if !defined(SHADOWS_DISABLED) - -#ifdef USE_SHADOW - { - highp vec4 splane = shadow_coord; - float shadow_len = length(splane.xyz); - - splane.xyz = normalize(splane.xyz); - - vec4 clamp_rect = light_clamp; - - if (splane.z >= 0.0) { - splane.z += 1.0; - - clamp_rect.y += clamp_rect.w; - } else { - splane.z = 1.0 - splane.z; - } - - splane.xy /= splane.z; - splane.xy = splane.xy * 0.5 + 0.5; - splane.z = shadow_len / light_range; - - splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; - splane.w = 1.0; - - float shadow = sample_shadow(light_shadow_atlas, splane); - - light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); - } -#endif - -#endif //SHADOWS_DISABLED - -#endif //type omni - -#ifdef LIGHT_MODE_DIRECTIONAL - -#ifndef USE_VERTEX_LIGHTING - vec3 light_vec = -light_direction; - L = normalize(light_vec); -#endif - float depth_z = -vertex.z; - -#if !defined(SHADOWS_DISABLED) - -#ifdef USE_SHADOW - -#ifdef USE_VERTEX_LIGHTING - //compute shadows in a mobile friendly way - -#ifdef LIGHT_USE_PSSM4 - //take advantage of prefetch - float shadow1 = sample_shadow(light_directional_shadow, shadow_coord); - float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2); - float shadow3 = sample_shadow(light_directional_shadow, shadow_coord3); - float shadow4 = sample_shadow(light_directional_shadow, shadow_coord4); - - if (depth_z < light_split_offsets.w) { - float pssm_fade = 0.0; - float shadow_att = 1.0; -#ifdef LIGHT_USE_PSSM_BLEND - float shadow_att2 = 1.0; - float pssm_blend = 0.0; - bool use_blend = true; -#endif - if (depth_z < light_split_offsets.y) { - if (depth_z < light_split_offsets.x) { - shadow_att = shadow1; - -#ifdef LIGHT_USE_PSSM_BLEND - shadow_att2 = shadow2; - - pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); -#endif - } else { - shadow_att = shadow2; - -#ifdef LIGHT_USE_PSSM_BLEND - shadow_att2 = shadow3; +#endif // BASE_PASS - pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); +#ifndef DISABLE_LIGHT_DIRECTIONAL + //diffuse_light = normal; // + for (uint i = uint(0); i < scene_data.directional_light_count; i++) { + light_compute(normal, normalize(directional_lights[i].direction), normalize(view), directional_lights[i].size, directional_lights[i].color * directional_lights[i].energy, 1.0, f0, roughness, metallic, 1.0, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, #endif - } - } else { - if (depth_z < light_split_offsets.z) { - shadow_att = shadow3; - -#if defined(LIGHT_USE_PSSM_BLEND) - shadow_att2 = shadow4; - pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z); +#ifdef LIGHT_RIM_USED + rim, rim_tint, #endif - - } else { - shadow_att = shadow4; - pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z); - -#if defined(LIGHT_USE_PSSM_BLEND) - use_blend = false; +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif - } - } -#if defined(LIGHT_USE_PSSM_BLEND) - if (use_blend) { - shadow_att = mix(shadow_att, shadow_att2, pssm_blend); - } +#ifdef LIGHT_ANISOTROPY_USED + binormal, + tangent, anisotropy, #endif - light_att *= mix(shadow_color.rgb, vec3(1.0), shadow_att); + diffuse_light, + specular_light); } +#endif //!DISABLE_LIGHT_DIRECTIONAL -#endif //LIGHT_USE_PSSM4 - -#ifdef LIGHT_USE_PSSM2 - - //take advantage of prefetch - float shadow1 = sample_shadow(light_directional_shadow, shadow_coord); - float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2); - - if (depth_z < light_split_offsets.y) { - float shadow_att = 1.0; - float pssm_fade = 0.0; - -#ifdef LIGHT_USE_PSSM_BLEND - float shadow_att2 = 1.0; - float pssm_blend = 0.0; - bool use_blend = true; -#endif - if (depth_z < light_split_offsets.x) { - float pssm_fade = 0.0; - shadow_att = shadow1; - -#ifdef LIGHT_USE_PSSM_BLEND - shadow_att2 = shadow2; - pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); -#endif - } else { - shadow_att = shadow2; - pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); -#ifdef LIGHT_USE_PSSM_BLEND - use_blend = false; -#endif +#ifndef DISABLE_LIGHT_OMNI + for (int i = 0; i < MAX_FORWARD_LIGHTS; i++) { + if (i >= omni_light_count) { + break; } -#ifdef LIGHT_USE_PSSM_BLEND - if (use_blend) { - shadow_att = mix(shadow_att, shadow_att2, pssm_blend); - } -#endif - light_att *= mix(shadow_color.rgb, vec3(1.0), shadow_att); - } - -#endif //LIGHT_USE_PSSM2 - -#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) - - light_att *= mix(shadow_color.rgb, vec3(1.0), sample_shadow(light_directional_shadow, shadow_coord)); -#endif //orthogonal - -#else //fragment version of pssm - - { -#ifdef LIGHT_USE_PSSM4 - if (depth_z < light_split_offsets.w) { -#elif defined(LIGHT_USE_PSSM2) - if (depth_z < light_split_offsets.y) { -#else - if (depth_z < light_split_offsets.x) { -#endif //pssm2 - - highp vec4 pssm_coord; - float pssm_fade = 0.0; - -#ifdef LIGHT_USE_PSSM_BLEND - float pssm_blend; - highp vec4 pssm_coord2; - bool use_blend = true; + light_process_omni(omni_light_indices[i], vertex, view, normal, f0, roughness, metallic, 0.0, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, #endif - -#ifdef LIGHT_USE_PSSM4 - - if (depth_z < light_split_offsets.y) { - if (depth_z < light_split_offsets.x) { - pssm_coord = shadow_coord; - -#ifdef LIGHT_USE_PSSM_BLEND - pssm_coord2 = shadow_coord2; - - pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); +#ifdef LIGHT_RIM_USED + rim, + rim_tint, #endif - } else { - pssm_coord = shadow_coord2; - -#ifdef LIGHT_USE_PSSM_BLEND - pssm_coord2 = shadow_coord3; - - pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif - } - } else { - if (depth_z < light_split_offsets.z) { - pssm_coord = shadow_coord3; - -#if defined(LIGHT_USE_PSSM_BLEND) - pssm_coord2 = shadow_coord4; - pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z); +#ifdef LIGHT_ANISOTROPY_USED + binormal, tangent, anisotropy, #endif + diffuse_light, specular_light); + } +#endif // !DISABLE_LIGHT_OMNI - } else { - pssm_coord = shadow_coord4; - pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z); - -#if defined(LIGHT_USE_PSSM_BLEND) - use_blend = false; -#endif - } - } - -#endif // LIGHT_USE_PSSM4 - -#ifdef LIGHT_USE_PSSM2 - if (depth_z < light_split_offsets.x) { - pssm_coord = shadow_coord; - -#ifdef LIGHT_USE_PSSM_BLEND - pssm_coord2 = shadow_coord2; - pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); +#ifndef DISABLE_LIGHT_SPOT + for (int i = 0; i < MAX_FORWARD_LIGHTS; i++) { + if (i >= spot_light_count) { + break; + } + light_process_spot(spot_light_indices[i], vertex, view, normal, f0, roughness, metallic, 0.0, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, #endif - } else { - pssm_coord = shadow_coord2; - pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); -#ifdef LIGHT_USE_PSSM_BLEND - use_blend = false; +#ifdef LIGHT_RIM_USED + rim, + rim_tint, #endif - } - -#endif // LIGHT_USE_PSSM2 - -#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) - { - pssm_coord = shadow_coord; - } +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif - - float shadow = sample_shadow(light_directional_shadow, pssm_coord); - -#ifdef LIGHT_USE_PSSM_BLEND - if (use_blend) { - shadow = mix(shadow, sample_shadow(light_directional_shadow, pssm_coord2), pssm_blend); - } +#ifdef LIGHT_ANISOTROPY_USED + tangent, + binormal, anisotropy, #endif - - light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); - } + diffuse_light, specular_light); } -#endif //use vertex lighting - -#endif //use shadow - -#endif // SHADOWS_DISABLED -#endif - -#ifdef LIGHT_MODE_SPOT - - light_att = vec3(1.0); - -#ifndef USE_VERTEX_LIGHTING - - vec3 light_rel_vec = light_position - vertex; - float light_length = length(light_rel_vec); - float normalized_distance = light_length / light_range; - - if (normalized_distance < 1.0) { - float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation); - vec3 spot_dir = light_direction; - - float spot_cutoff = light_spot_angle; - float angle = dot(-normalize(light_rel_vec), spot_dir); - - if (angle > spot_cutoff) { - float scos = max(angle, spot_cutoff); - float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff)); - spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation); - - light_att = vec3(spot_attenuation); - } else { - light_att = vec3(0.0); - } - } else { - light_att = vec3(0.0); - } - - L = normalize(light_rel_vec); - -#endif - -#if !defined(SHADOWS_DISABLED) - -#ifdef USE_SHADOW - { - highp vec4 splane = shadow_coord; - - float shadow = sample_shadow(light_shadow_atlas, splane); - light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); - } -#endif - -#endif // SHADOWS_DISABLED - -#endif // LIGHT_MODE_SPOT - -#ifdef USE_VERTEX_LIGHTING - //vertex lighting - - specular_light += specular_interp * specular_blob_intensity * light_att; - diffuse_light += diffuse_interp * albedo * light_att; - -#else - //fragment lighting - light_compute( - normal, - L, - eye_position, - binormal, - tangent, - light_color.xyz, - light_att, - albedo, - transmission, - specular_blob_intensity * light_specular, - roughness, - metallic, - specular, - rim, - rim_tint, - clearcoat, - clearcoat_roughness, - anisotropy, - diffuse_light, - specular_light, - alpha); - -#endif //vertex lighting - -#endif //USE_LIGHTING - //compute and merge - -#ifdef USE_SHADOW_TO_OPACITY +#endif // !DISABLE_LIGHT_SPOT +#endif // !MODE_UNSHADED +#endif // !MODE_RENDER_DEPTH +#if defined(USE_SHADOW_TO_OPACITY) alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0)); #if defined(ALPHA_SCISSOR_USED) @@ -2049,105 +1174,60 @@ FRAGMENT_SHADER_CODE } #endif // ALPHA_SCISSOR_USED -#ifdef USE_DEPTH_PREPASS - if (alpha < 0.1) { +#ifdef USE_OPAQUE_PREPASS +#if !defined(ALPHA_SCISSOR_USED) + + if (alpha < opaque_prepass_threshold) { discard; } -#endif // USE_DEPTH_PREPASS -#endif // !USE_SHADOW_TO_OPACITY +#endif // not ALPHA_SCISSOR_USED +#endif // USE_OPAQUE_PREPASS -#ifndef RENDER_DEPTH +#endif // USE_SHADOW_TO_OPACITY -#ifdef SHADELESS +#ifdef MODE_RENDER_DEPTH +//nothing happens, so a tree-ssa optimizer will result in no fragment shader :) +#else // !MODE_RENDER_DEPTH +#ifdef MODE_UNSHADED frag_color = vec4(albedo, alpha); #else - ambient_light *= albedo; - -#if defined(ENABLE_AO) - ambient_light *= ao; - ao_light_affect = mix(1.0, ao, ao_light_affect); - specular_light *= ao_light_affect; - diffuse_light *= ao_light_affect; -#endif + diffuse_light *= albedo; diffuse_light *= 1.0 - metallic; ambient_light *= 1.0 - metallic; - frag_color = vec4(ambient_light + diffuse_light + specular_light, alpha); - - //add emission if in base pass + frag_color = vec4(diffuse_light + specular_light, alpha); #ifdef BASE_PASS - frag_color.rgb += emission; + frag_color.rgb += emission + ambient_light; #endif - // frag_color = vec4(normal, 1.0); - -//apply fog -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -#if defined(USE_VERTEX_LIGHTING) +#endif //MODE_UNSHADED + fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba)); -#if defined(BASE_PASS) - frag_color.rgb = mix(frag_color.rgb, fog_interp.rgb, fog_interp.a); +#ifndef DISABLE_FOG + if (scene_data.fog_enabled) { +#ifdef BASE_PASS + frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); #else - frag_color.rgb *= (1.0 - fog_interp.a); + frag_color.rgb *= (1.0 - fog.a); #endif // BASE_PASS - -#else //pixel based fog - float fog_amount = 0.0; - -#ifdef LIGHT_MODE_DIRECTIONAL - - vec3 fog_color = mix(fog_color_base.rgb, fog_sun_color_amount.rgb, fog_sun_color_amount.a * pow(max(dot(eye_position, light_direction), 0.0), 8.0)); -#else - vec3 fog_color = fog_color_base.rgb; + } #endif -#ifdef FOG_DEPTH_ENABLED - - { - float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); + // Tonemap before writing as we are writing to an sRGB framebuffer + frag_color.rgb *= exposure; + frag_color.rgb = apply_tonemapping(frag_color.rgb, white); + frag_color.rgb = linear_to_srgb(frag_color.rgb); - fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a; - - if (fog_transmit_enabled) { - vec3 total_light = frag_color.rgb; - float transmit = pow(fog_z, fog_transmit_curve); - fog_color = mix(max(total_light, fog_color), fog_color, transmit); - } - } +#ifdef USE_BCS + frag_color.rgb = apply_bcs(frag_color.rgb, bcs); #endif -#ifdef FOG_HEIGHT_ENABLED - { - float y = (inv_view_matrix * vec4(vertex, 1.0)).y; - fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); - } +#ifdef USE_COLOR_CORRECTION + frag_color.rgb = apply_color_correction(frag_color.rgb, color_correction); #endif -#if defined(BASE_PASS) - frag_color.rgb = mix(frag_color.rgb, fog_color, fog_amount); -#else - frag_color.rgb *= (1.0 - fog_amount); -#endif // BASE_PASS - -#endif //use vertex lit - -#endif // defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -#endif //unshaded - -#else // not RENDER_DEPTH -//depth render -#ifdef USE_RGBA_SHADOWS - - highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias - highp vec4 comp = fract(depth * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0)); - comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0); - frag_color = comp; - -#endif -#endif +#endif //!MODE_RENDER_DEPTH } diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 0faa3eb70c..50ab38bc31 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -12,22 +12,13 @@ mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PA #[vertex] -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -precision highp float; -precision highp int; -#endif +layout(location = 0) in vec2 vertex_attrib; out vec2 uv_interp; /* clang-format on */ void main() { - // One big triangle to cover the whole screen - vec2 base_arr[3] = vec2[](vec2(-1.0, -2.0), vec2(-1.0, 2.0), vec2(2.0, 2.0)); - uv_interp = base_arr[gl_VertexID]; + uv_interp = vertex_attrib; gl_Position = vec4(uv_interp, 1.0, 1.0); } @@ -36,19 +27,7 @@ void main() { #define M_PI 3.14159265359 -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif +#include "tonemap_inc.glsl" in vec2 uv_interp; @@ -63,16 +42,6 @@ uniform sampler2D half_res; //texunit:-2 uniform sampler2D quarter_res; //texunit:-3 #endif -layout(std140) uniform CanvasData { //ubo:0 - mat3 orientation; - vec4 projection; - vec4 position_multiplier; - float time; - float luminance_multiplier; - float pad1; - float pad2; -}; - layout(std140) uniform GlobalVariableData { //ubo:1 vec4 global_variables[MAX_GLOBAL_VARIABLES]; }; @@ -83,20 +52,21 @@ struct DirectionalLightData { bool enabled; }; -layout(std140) uniform DirectionalLights { //ubo:2 +layout(std140) uniform DirectionalLights { //ubo:4 DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; } directional_lights; +/* clang-format off */ + #ifdef MATERIAL_UNIFORMS_USED -layout(std140) uniform MaterialUniforms{ -//ubo:3 +layout(std140) uniform MaterialUniforms{ //ubo:3 #MATERIAL_UNIFORMS -} material; +}; #endif - +/* clang-format on */ #GLOBALS #ifdef USE_CUBEMAP_PASS @@ -117,6 +87,20 @@ layout(std140) uniform MaterialUniforms{ #define AT_QUARTER_RES_PASS false #endif +// mat4 is a waste of space, but we don't have an easy way to set a mat3 uniform for now +uniform mat4 orientation; +uniform vec4 projection; +uniform vec3 position; +uniform float time; + +uniform float fog_aerial_perspective; +uniform vec3 fog_light_color; +uniform float fog_sun_scatter; +uniform bool fog_enabled; +uniform float fog_density; +uniform float z_far; +uniform uint directional_light_count; + layout(location = 0) out vec4 frag_color; void main() { @@ -125,12 +109,11 @@ void main() { cube_normal.x = (uv_interp.x + projection.x) / projection.y; cube_normal.y = (-uv_interp.y - projection.z) / projection.w; cube_normal = mat3(orientation) * cube_normal; - cube_normal.z = -cube_normal.z; cube_normal = normalize(cube_normal); - vec2 uv = uv_interp * 0.5 + 0.5; + vec2 uv = gl_FragCoord.xy; // uv_interp * 0.5 + 0.5; - vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y)); + vec2 panorama_coords = vec2(atan(cube_normal.x, -cube_normal.z), acos(cube_normal.y)); if (panorama_coords.x < 0.0) { panorama_coords.x += M_PI * 2.0; @@ -145,20 +128,18 @@ void main() { vec4 custom_fog = vec4(0.0); #ifdef USE_CUBEMAP_PASS - vec3 inverted_cube_normal = cube_normal; - inverted_cube_normal.z *= -1.0; #ifdef USES_HALF_RES_COLOR - half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * luminance_multiplier; + half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal); #endif #ifdef USES_QUARTER_RES_COLOR - quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * luminance_multiplier; + quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal); #endif #else #ifdef USES_HALF_RES_COLOR - half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * luminance_multiplier; + half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); #endif #ifdef USES_QUARTER_RES_COLOR - quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * luminance_multiplier; + quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); #endif #endif @@ -168,12 +149,20 @@ void main() { } - frag_color.rgb = color * position_multiplier.w / luminance_multiplier; - frag_color.a = alpha; + // Convert to Linear for tonemapping so color matches scene shader better + color = srgb_to_linear(color); + color *= exposure; + color = apply_tonemapping(color, white); + color = linear_to_srgb(color); - // Blending is disabled for Sky, so alpha doesn't blend - // alpha is used for subsurface scattering so make sure it doesn't get applied to Sky - if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) { - frag_color.a = 0.0; - } +#ifdef USE_BCS + color = apply_bcs(color, bcs); +#endif + +#ifdef USE_COLOR_CORRECTION + color = apply_color_correction(color, color_correction); +#endif + + frag_color.rgb = color; + frag_color.a = alpha; } diff --git a/drivers/gles3/shaders/stdlib_inc.glsl b/drivers/gles3/shaders/stdlib_inc.glsl index 2eddf9d479..d5051760d7 100644 --- a/drivers/gles3/shaders/stdlib_inc.glsl +++ b/drivers/gles3/shaders/stdlib_inc.glsl @@ -1,5 +1,6 @@ -//TODO: only needed by GLES_OVER_GL +#ifdef USE_GLES_OVER_GL +// Floating point pack/unpack functions are part of the GLSL ES 300 specification used by web and mobile. uint float2half(uint f) { return ((f >> uint(16)) & uint(0x8000)) | ((((f & uint(0x7f800000)) - uint(0x38000000)) >> uint(13)) & uint(0x7c00)) | @@ -37,14 +38,15 @@ vec2 unpackSnorm2x16(uint p) { vec2 v = vec2(float(p & uint(0xffff)), float(p >> uint(16))); return clamp((v - 32767.0) * vec2(0.00003051851), vec2(-1.0), vec2(1.0)); } +#endif uint packUnorm4x8(vec4 v) { uvec4 uv = uvec4(round(clamp(v, vec4(0.0), vec4(1.0)) * 255.0)); - return uv.x | uv.y << uint(8) | uv.z << uint(16) | uv.w << uint(24); + return uv.x | (uv.y << uint(8)) | (uv.z << uint(16)) | (uv.w << uint(24)); } vec4 unpackUnorm4x8(uint p) { - return vec4(float(p & uint(0xffff)), float((p >> uint(8)) & uint(0xffff)), float((p >> uint(16)) & uint(0xffff)), float(p >> uint(24))) * 0.00392156862; // 1.0 / 255.0 + return vec4(float(p & uint(0xff)), float((p >> uint(8)) & uint(0xff)), float((p >> uint(16)) & uint(0xff)), float(p >> uint(24))) * 0.00392156862; // 1.0 / 255.0 } uint packSnorm4x8(vec4 v) { @@ -53,6 +55,6 @@ uint packSnorm4x8(vec4 v) { } vec4 unpackSnorm4x8(uint p) { - vec4 v = vec4(float(p & uint(0xffff)), float((p >> uint(8)) & uint(0xffff)), float((p >> uint(16)) & uint(0xffff)), float(p >> uint(24))); + vec4 v = vec4(float(p & uint(0xff)), float((p >> uint(8)) & uint(0xff)), float((p >> uint(16)) & uint(0xff)), float(p >> uint(24))); return clamp((v - vec4(127.0)) * vec4(0.00787401574), vec4(-1.0), vec4(1.0)); } diff --git a/drivers/gles3/shaders/tonemap_inc.glsl b/drivers/gles3/shaders/tonemap_inc.glsl new file mode 100644 index 0000000000..f8f12760ec --- /dev/null +++ b/drivers/gles3/shaders/tonemap_inc.glsl @@ -0,0 +1,127 @@ +#ifdef USE_BCS +uniform vec3 bcs; +#endif + +#ifdef USE_COLOR_CORRECTION +#ifdef USE_1D_LUT +uniform sampler2D source_color_correction; //texunit:-1 +#else +uniform sampler3D source_color_correction; //texunit:-1 +#endif +#endif + +layout(std140) uniform TonemapData { //ubo:0 + float exposure; + float white; + int tonemapper; + int pad; +}; + +vec3 apply_bcs(vec3 color, vec3 bcs) { + color = mix(vec3(0.0), color, bcs.x); + color = mix(vec3(0.5), color, bcs.y); + color = mix(vec3(dot(vec3(1.0), color) * 0.33333), color, bcs.z); + + return color; +} +#ifdef USE_COLOR_CORRECTION +#ifdef USE_1D_LUT +vec3 apply_color_correction(vec3 color) { + color.r = texture(source_color_correction, vec2(color.r, 0.0f)).r; + color.g = texture(source_color_correction, vec2(color.g, 0.0f)).g; + color.b = texture(source_color_correction, vec2(color.b, 0.0f)).b; + return color; +} +#else +vec3 apply_color_correction(vec3 color) { + return textureLod(source_color_correction, color, 0.0).rgb; +} +#endif +#endif + +vec3 tonemap_filmic(vec3 color, float p_white) { + // exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers + // also useful to scale the input to the range that the tonemapper is designed for (some require very high input values) + // has no effect on the curve's general shape or visual properties + const float exposure_bias = 2.0f; + const float A = 0.22f * exposure_bias * exposure_bias; // bias baked into constants for performance + const float B = 0.30f * exposure_bias; + const float C = 0.10f; + const float D = 0.20f; + const float E = 0.01f; + const float F = 0.30f; + + vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F; + float p_white_tonemapped = ((p_white * (A * p_white + C * B) + D * E) / (p_white * (A * p_white + B) + D * F)) - E / F; + + return color_tonemapped / p_white_tonemapped; +} + +// Adapted from https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl +// (MIT License). +vec3 tonemap_aces(vec3 color, float p_white) { + const float exposure_bias = 1.8f; + const float A = 0.0245786f; + const float B = 0.000090537f; + const float C = 0.983729f; + const float D = 0.432951f; + const float E = 0.238081f; + + // Exposure bias baked into transform to save shader instructions. Equivalent to `color *= exposure_bias` + const mat3 rgb_to_rrt = mat3( + vec3(0.59719f * exposure_bias, 0.35458f * exposure_bias, 0.04823f * exposure_bias), + vec3(0.07600f * exposure_bias, 0.90834f * exposure_bias, 0.01566f * exposure_bias), + vec3(0.02840f * exposure_bias, 0.13383f * exposure_bias, 0.83777f * exposure_bias)); + + const mat3 odt_to_rgb = mat3( + vec3(1.60475f, -0.53108f, -0.07367f), + vec3(-0.10208f, 1.10813f, -0.00605f), + vec3(-0.00327f, -0.07276f, 1.07602f)); + + color *= rgb_to_rrt; + vec3 color_tonemapped = (color * (color + A) - B) / (color * (C * color + D) + E); + color_tonemapped *= odt_to_rgb; + + p_white *= exposure_bias; + float p_white_tonemapped = (p_white * (p_white + A) - B) / (p_white * (C * p_white + D) + E); + + return color_tonemapped / p_white_tonemapped; +} + +vec3 tonemap_reinhard(vec3 color, float p_white) { + return (p_white * color + color) / (color * p_white + p_white); +} + +// This expects 0-1 range input. +vec3 linear_to_srgb(vec3 color) { + //color = clamp(color, vec3(0.0), vec3(1.0)); + //const vec3 a = vec3(0.055f); + //return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f))); + // Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html + return max(vec3(1.055) * pow(color, vec3(0.416666667)) - vec3(0.055), vec3(0.0)); +} + +// This expects 0-1 range input, outside that range it behaves poorly. +vec3 srgb_to_linear(vec3 color) { + // Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html + return color * (color * (color * 0.305306011 + 0.682171111) + 0.012522878); +} + +#define TONEMAPPER_LINEAR 0 +#define TONEMAPPER_REINHARD 1 +#define TONEMAPPER_FILMIC 2 +#define TONEMAPPER_ACES 3 + +vec3 apply_tonemapping(vec3 color, float p_white) { // inputs are LINEAR, always outputs clamped [0;1] color + // Ensure color values passed to tonemappers are positive. + // They can be negative in the case of negative lights, which leads to undesired behavior. + if (tonemapper == TONEMAPPER_LINEAR) { + return color; + } else if (tonemapper == TONEMAPPER_REINHARD) { + return tonemap_reinhard(max(vec3(0.0f), color), p_white); + } else if (tonemapper == TONEMAPPER_FILMIC) { + return tonemap_filmic(max(vec3(0.0f), color), p_white); + } else { // TONEMAPPER_ACES + return tonemap_aces(max(vec3(0.0f), color), p_white); + } +} diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp index 369e523cc4..49a2a79cb2 100644 --- a/drivers/gles3/storage/config.cpp +++ b/drivers/gles3/storage/config.cpp @@ -44,7 +44,7 @@ Config::Config() { singleton = this; { - int max_extensions = 0; + GLint max_extensions = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &max_extensions); for (int i = 0; i < max_extensions; i++) { const GLubyte *s = glGetStringi(GL_EXTENSIONS, i); @@ -120,16 +120,6 @@ Config::Config() { support_write_depth = extensions.has("GL_EXT_frag_depth"); #endif - support_half_float_vertices = true; -//every platform should support this except web, iOS has issues with their support, so add option to disable -#ifdef JAVASCRIPT_ENABLED - support_half_float_vertices = false; -#endif - bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float"); - if (disable_half_float) { - support_half_float_vertices = false; - } - //picky requirements for these support_shadow_cubemaps = support_write_depth && support_depth_cubemaps; // the use skeleton software path should be used if either float texture is not supported, @@ -149,6 +139,27 @@ Config::Config() { force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); use_nearest_mip_filter = GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter"); + + use_depth_prepass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")); + if (use_depth_prepass) { + String vendors = GLOBAL_GET("rendering/driver/depth_prepass/disable_for_vendors"); + Vector<String> vendor_match = vendors.split(","); + String renderer = (const char *)glGetString(GL_RENDERER); + for (int i = 0; i < vendor_match.size(); i++) { + String v = vendor_match[i].strip_edges(); + if (v == String()) { + continue; + } + + if (renderer.findn(v) != -1) { + use_depth_prepass = false; + } + } + } + + max_renderable_elements = GLOBAL_GET("rendering/limits/opengl/max_renderable_elements"); + max_renderable_lights = GLOBAL_GET("rendering/limits/opengl/max_renderable_lights"); + max_lights_per_object = GLOBAL_GET("rendering/limits/opengl/max_lights_per_object"); } Config::~Config() { diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h index 0646881b72..975508b555 100644 --- a/drivers/gles3/storage/config.h +++ b/drivers/gles3/storage/config.h @@ -34,7 +34,7 @@ #ifdef GLES3_ENABLED #include "core/string/ustring.h" -#include "core/templates/set.h" +#include "core/templates/rb_set.h" // This must come first to avoid windows.h mess #include "platform_config.h" @@ -58,11 +58,14 @@ public: int max_texture_image_units = 0; int max_texture_size = 0; int max_uniform_buffer_size = 0; + int max_renderable_elements = 0; + int max_renderable_lights = 0; + int max_lights_per_object = 0; // TODO implement wireframe in OpenGL // bool generate_wireframes; - Set<String> extensions; + RBSet<String> extensions; bool float_texture_supported = false; bool s3tc_supported = false; @@ -82,7 +85,6 @@ public: bool support_32_bits_indices = false; bool support_write_depth = false; - bool support_half_float_vertices = false; bool support_npot_repeat_mipmap = false; bool support_depth_cubemaps = false; bool support_shadow_cubemaps = false; @@ -97,6 +99,8 @@ public: // so the user can switch orphaning off for them. bool should_orphan = true; + bool use_depth_prepass = true; + static Config *get_singleton() { return singleton; }; Config(); diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp index 7395611d71..954aa11c0d 100644 --- a/drivers/gles3/storage/light_storage.cpp +++ b/drivers/gles3/storage/light_storage.cpp @@ -32,6 +32,7 @@ #include "light_storage.h" #include "config.h" +#include "texture_storage.h" using namespace GLES3; @@ -51,122 +52,284 @@ LightStorage::~LightStorage() { /* Light API */ +void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) { + Light light; + light.type = p_type; + + light.param[RS::LIGHT_PARAM_ENERGY] = 1.0; + light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0; + light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5; + light.param[RS::LIGHT_PARAM_RANGE] = 1.0; + light.param[RS::LIGHT_PARAM_SIZE] = 0.0; + light.param[RS::LIGHT_PARAM_ATTENUATION] = 1.0; + light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45; + light.param[RS::LIGHT_PARAM_SPOT_ATTENUATION] = 1.0; + light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0; + light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1; + light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3; + light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6; + light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8; + light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0; + light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02; + light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0; + light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0; + light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1; + light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05; + + light_owner.initialize_rid(p_light, light); +} + RID LightStorage::directional_light_allocate() { - return RID(); + return light_owner.allocate_rid(); } void LightStorage::directional_light_initialize(RID p_rid) { + _light_initialize(p_rid, RS::LIGHT_DIRECTIONAL); } RID LightStorage::omni_light_allocate() { - return RID(); + return light_owner.allocate_rid(); } void LightStorage::omni_light_initialize(RID p_rid) { + _light_initialize(p_rid, RS::LIGHT_OMNI); } RID LightStorage::spot_light_allocate() { - return RID(); + return light_owner.allocate_rid(); } void LightStorage::spot_light_initialize(RID p_rid) { + _light_initialize(p_rid, RS::LIGHT_SPOT); } void LightStorage::light_free(RID p_rid) { + light_set_projector(p_rid, RID()); //clear projector + + // delete the texture + Light *light = light_owner.get_or_null(p_rid); + light->dependency.deleted_notify(p_rid); + light_owner.free(p_rid); } void LightStorage::light_set_color(RID p_light, const Color &p_color) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + + light->color = p_color; } void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_value) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX); + + if (light->param[p_param] == p_value) { + return; + } + + switch (p_param) { + case RS::LIGHT_PARAM_RANGE: + case RS::LIGHT_PARAM_SPOT_ANGLE: + case RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE: + case RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET: + case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET: + case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET: + case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS: + case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE: + case RS::LIGHT_PARAM_SHADOW_BIAS: { + light->version++; + light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + } break; + case RS::LIGHT_PARAM_SIZE: { + if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) { + //changing from no size to size and the opposite + light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); + } + } break; + default: { + } + } + + light->param[p_param] = p_value; } void LightStorage::light_set_shadow(RID p_light, bool p_enabled) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + light->shadow = p_enabled; + + light->version++; + light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_set_projector(RID p_light, RID p_texture) { + GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + + if (light->projector == p_texture) { + return; + } + + if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) { + texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI); + } + + light->projector = p_texture; + + if (light->type != RS::LIGHT_DIRECTIONAL) { + if (light->projector.is_valid()) { + texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI); + } + light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); + } } void LightStorage::light_set_negative(RID p_light, bool p_enable) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + + light->negative = p_enable; } void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + + light->cull_mask = p_mask; + + light->version++; + light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + + light->distance_fade = p_enabled; + light->distance_fade_begin = p_begin; + light->distance_fade_shadow = p_shadow; + light->distance_fade_length = p_length; } void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + + light->reverse_cull = p_enabled; + + light->version++; + light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) { -} + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + + light->bake_mode = p_bake_mode; -void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) { + light->version++; + light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) { -} + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); -void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) { -} + light->omni_shadow_mode = p_mode; -void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) { + light->version++; + light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); } -bool LightStorage::light_directional_get_blend_splits(RID p_light) const { - return false; -} +RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE); -void LightStorage::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) { + return light->omni_shadow_mode; } -RS::LightDirectionalSkyMode LightStorage::light_directional_get_sky_mode(RID p_light) const { - return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; -} +void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); -RS::LightDirectionalShadowMode LightStorage::light_directional_get_shadow_mode(RID p_light) { - return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; + light->directional_shadow_mode = p_mode; + light->version++; + light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); } -RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) { - return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; -} +void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); -bool LightStorage::light_has_shadow(RID p_light) const { - return false; + light->directional_blend_splits = p_enable; + light->version++; + light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); } -bool LightStorage::light_has_projector(RID p_light) const { - return false; -} +bool LightStorage::light_directional_get_blend_splits(RID p_light) const { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, false); -RS::LightType LightStorage::light_get_type(RID p_light) const { - return RS::LIGHT_OMNI; + return light->directional_blend_splits; } -AABB LightStorage::light_get_aabb(RID p_light) const { - return AABB(); +void LightStorage::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + + light->directional_sky_mode = p_mode; } -float LightStorage::light_get_param(RID p_light, RS::LightParam p_param) { - return 0.0; +RS::LightDirectionalSkyMode LightStorage::light_directional_get_sky_mode(RID p_light) const { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY); + + return light->directional_sky_mode; } -Color LightStorage::light_get_color(RID p_light) { - return Color(); +RS::LightDirectionalShadowMode LightStorage::light_directional_get_shadow_mode(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); + + return light->directional_shadow_mode; } RS::LightBakeMode LightStorage::light_get_bake_mode(RID p_light) { - return RS::LIGHT_BAKE_DISABLED; -} + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED); -uint32_t LightStorage::light_get_max_sdfgi_cascade(RID p_light) { - return 0; + return light->bake_mode; } uint64_t LightStorage::light_get_version(RID p_light) const { - return 0; + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, 0); + + return light->version; +} + +AABB LightStorage::light_get_aabb(RID p_light) const { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, AABB()); + + switch (light->type) { + case RS::LIGHT_SPOT: { + float len = light->param[RS::LIGHT_PARAM_RANGE]; + float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; + return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); + }; + case RS::LIGHT_OMNI: { + float r = light->param[RS::LIGHT_PARAM_RANGE]; + return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2); + }; + case RS::LIGHT_DIRECTIONAL: { + return AABB(); + }; + } + + ERR_FAIL_V(AABB()); } /* PROBE API */ diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h index 6f24e467bc..5acaf45aa3 100644 --- a/drivers/gles3/storage/light_storage.h +++ b/drivers/gles3/storage/light_storage.h @@ -40,12 +40,100 @@ #include "servers/rendering/renderer_storage.h" #include "servers/rendering/storage/light_storage.h" +#include "platform_config.h" +#ifndef OPENGL_INCLUDE_H +#include <GLES3/gl3.h> +#else +#include OPENGL_INCLUDE_H +#endif + namespace GLES3 { +/* LIGHT */ + +struct Light { + RS::LightType type; + float param[RS::LIGHT_PARAM_MAX]; + Color color = Color(1, 1, 1, 1); + RID projector; + bool shadow = false; + bool negative = false; + bool reverse_cull = false; + RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC; + uint32_t max_sdfgi_cascade = 2; + uint32_t cull_mask = 0xFFFFFFFF; + bool distance_fade = false; + real_t distance_fade_begin = 40.0; + real_t distance_fade_shadow = 50.0; + real_t distance_fade_length = 10.0; + RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; + RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; + bool directional_blend_splits = false; + RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; + uint64_t version = 0; + + RendererStorage::Dependency dependency; +}; + +/* REFLECTION PROBE */ + +struct ReflectionProbe { + RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE; + int resolution = 256; + float intensity = 1.0; + RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT; + Color ambient_color; + float ambient_color_energy = 1.0; + float max_distance = 0; + Vector3 extents = Vector3(1, 1, 1); + Vector3 origin_offset; + bool interior = false; + bool box_projection = false; + bool enable_shadows = false; + uint32_t cull_mask = (1 << 20) - 1; + float mesh_lod_threshold = 0.01; + + RendererStorage::Dependency dependency; +}; + +/* LIGHTMAP */ + +struct Lightmap { + RID light_texture; + bool uses_spherical_harmonics = false; + bool interior = false; + AABB bounds = AABB(Vector3(), Vector3(1, 1, 1)); + int32_t array_index = -1; //unassigned + PackedVector3Array points; + PackedColorArray point_sh; + PackedInt32Array tetrahedra; + PackedInt32Array bsp_tree; + + struct BSP { + static const int32_t EMPTY_LEAF = INT32_MIN; + float plane[4]; + int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; + }; + + RendererStorage::Dependency dependency; +}; + class LightStorage : public RendererLightStorage { private: static LightStorage *singleton; + /* LIGHT */ + mutable RID_Owner<Light, true> light_owner; + + /* REFLECTION PROBE */ + mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner; + + /* LIGHTMAP */ + + Vector<RID> lightmap_textures; + + mutable RID_Owner<Lightmap, true> lightmap_owner; + public: static LightStorage *get_singleton(); @@ -54,6 +142,11 @@ public: /* Light API */ + Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); }; + bool owns_light(RID p_rid) { return light_owner.owns(p_rid); }; + + void _light_initialize(RID p_rid, RS::LightType p_type); + virtual RID directional_light_allocate() override; virtual void directional_light_initialize(RID p_rid) override; virtual RID omni_light_allocate() override; @@ -72,7 +165,7 @@ public: virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override; virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override; - virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override; + virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {} virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override; @@ -84,16 +177,99 @@ public: virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override; virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override; + virtual RS::LightType light_get_type(RID p_light) const override { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); - virtual bool light_has_shadow(RID p_light) const override; - virtual bool light_has_projector(RID p_light) const override; - - virtual RS::LightType light_get_type(RID p_light) const override; + return light->type; + } virtual AABB light_get_aabb(RID p_light) const override; - virtual float light_get_param(RID p_light, RS::LightParam p_param) override; - virtual Color light_get_color(RID p_light) override; + + virtual float light_get_param(RID p_light, RS::LightParam p_param) override { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, 0); + + return light->param[p_param]; + } + + _FORCE_INLINE_ RID light_get_projector(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, RID()); + + return light->projector; + } + + virtual Color light_get_color(RID p_light) override { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, Color()); + + return light->color; + } + + _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, 0); + + return light->cull_mask; + } + + _FORCE_INLINE_ bool light_is_distance_fade_enabled(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + return light->distance_fade; + } + + _FORCE_INLINE_ float light_get_distance_fade_begin(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + return light->distance_fade_begin; + } + + _FORCE_INLINE_ float light_get_distance_fade_shadow(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + return light->distance_fade_shadow; + } + + _FORCE_INLINE_ float light_get_distance_fade_length(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + return light->distance_fade_length; + } + + virtual bool light_has_shadow(RID p_light) const override { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); + + return light->shadow; + } + + virtual bool light_has_projector(RID p_light) const override { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); + + return light_owner.owns(light->projector); + } + + _FORCE_INLINE_ bool light_is_negative(RID p_light) const { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); + + return light->negative; + } + + _FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, 0.0); + + return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS]; + } + + _FORCE_INLINE_ float light_get_shadow_volumetric_fog_fade(RID p_light) const { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, 0.0); + + return light->param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE]; + } + virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override; - virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override; + virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; } virtual uint64_t light_get_version(RID p_light) const override; /* PROBE API */ diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index d14d26346c..e93c503396 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -43,7 +43,7 @@ using namespace GLES3; /////////////////////////////////////////////////////////////////////////// // UBI helper functions -_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) { +_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data) { switch (type) { case ShaderLanguage::TYPE_BOOL: { uint32_t *gui = (uint32_t *)data; @@ -399,9 +399,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { if (i < s) { Color color = a[i]; - if (p_linear_color) { - color = color.srgb_to_linear(); - } gui[j] = color.r; gui[j + 1] = color.g; gui[j + 2] = color.b; @@ -433,10 +430,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy if (value.get_type() == Variant::COLOR) { Color v = value; - if (p_linear_color) { - v = v.srgb_to_linear(); - } - gui[0] = v.r; gui[1] = v.g; gui[2] = v.b; @@ -459,9 +452,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy for (int i = 0, j = 0; i < p_array_size; i++, j += 4) { if (i < s) { Color color = a[i]; - if (p_linear_color) { - color = color.srgb_to_linear(); - } gui[j] = color.r; gui[j + 1] = color.g; gui[j + 2] = color.b; @@ -496,10 +486,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy if (value.get_type() == Variant::COLOR) { Color v = value; - if (p_linear_color) { - v = v.srgb_to_linear(); - } - gui[0] = v.r; gui[1] = v.g; gui[2] = v.b; @@ -900,7 +886,43 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, /////////////////////////////////////////////////////////////////////////// // MaterialData -void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { +// Look up table to translate ShaderLanguage::DataType to GL_TEXTURE_* +static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = { + GL_TEXTURE_2D, // TYPE_VOID, + GL_TEXTURE_2D, // TYPE_BOOL, + GL_TEXTURE_2D, // TYPE_BVEC2, + GL_TEXTURE_2D, // TYPE_BVEC3, + GL_TEXTURE_2D, // TYPE_BVEC4, + GL_TEXTURE_2D, // TYPE_INT, + GL_TEXTURE_2D, // TYPE_IVEC2, + GL_TEXTURE_2D, // TYPE_IVEC3, + GL_TEXTURE_2D, // TYPE_IVEC4, + GL_TEXTURE_2D, // TYPE_UINT, + GL_TEXTURE_2D, // TYPE_UVEC2, + GL_TEXTURE_2D, // TYPE_UVEC3, + GL_TEXTURE_2D, // TYPE_UVEC4, + GL_TEXTURE_2D, // TYPE_FLOAT, + GL_TEXTURE_2D, // TYPE_VEC2, + GL_TEXTURE_2D, // TYPE_VEC3, + GL_TEXTURE_2D, // TYPE_VEC4, + GL_TEXTURE_2D, // TYPE_MAT2, + GL_TEXTURE_2D, // TYPE_MAT3, + GL_TEXTURE_2D, // TYPE_MAT4, + GL_TEXTURE_2D, // TYPE_SAMPLER2D, + GL_TEXTURE_2D, // TYPE_ISAMPLER2D, + GL_TEXTURE_2D, // TYPE_USAMPLER2D, + GL_TEXTURE_2D_ARRAY, // TYPE_SAMPLER2DARRAY, + GL_TEXTURE_2D_ARRAY, // TYPE_ISAMPLER2DARRAY, + GL_TEXTURE_2D_ARRAY, // TYPE_USAMPLER2DARRAY, + GL_TEXTURE_3D, // TYPE_SAMPLER3D, + GL_TEXTURE_3D, // TYPE_ISAMPLER3D, + GL_TEXTURE_3D, // TYPE_USAMPLER3D, + GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE, + GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY, + GL_TEXTURE_2D, // TYPE_STRUCT +}; + +void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { MaterialStorage *material_storage = MaterialStorage::get_singleton(); bool uses_global_buffer = false; @@ -947,11 +969,11 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S ERR_CONTINUE(offset + size > p_buffer_size); #endif uint8_t *data = &p_buffer[offset]; - const Map<StringName, Variant>::Element *V = p_parameters.find(E.key); + HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(E.key); if (V) { //user provided - _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color); + _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->value, data); } else if (E.value.default_value.size()) { //default value @@ -961,7 +983,7 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S //zero because it was not provided if ((E.value.type == ShaderLanguage::TYPE_VEC3 || E.value.type == ShaderLanguage::TYPE_VEC4) && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { //colors must be set as black, with alpha as 1.0 - _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color); + _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data); } else { //else just zero it out _fill_std140_ubo_empty(E.value.type, E.value.array_size, data); @@ -1002,10 +1024,11 @@ MaterialData::~MaterialData() { if (uniform_buffer) { glDeleteBuffers(1, &uniform_buffer); + uniform_buffer = 0; } } -void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { +void MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { TextureStorage *texture_storage = TextureStorage::get_singleton(); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -1033,12 +1056,12 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); } else { - Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name); + HashMap<StringName, uint64_t>::Iterator E = used_global_textures.find(uniform_name); if (!E) { E = used_global_textures.insert(uniform_name, global_textures_pass); v->texture_materials.insert(self); } else { - E->get() = global_textures_pass; + E->value = global_textures_pass; } textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value); @@ -1048,10 +1071,10 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly."); } } else { - const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name); + HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(uniform_name); if (V) { - if (V->get().is_array()) { - Array array = (Array)V->get(); + if (V->value.is_array()) { + Array array = (Array)V->value; if (uniform_array_size > 0) { for (int j = 0; j < array.size(); j++) { textures.push_back(array[j]); @@ -1062,25 +1085,25 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, } } } else { - textures.push_back(V->get()); + textures.push_back(V->value); } } if (uniform_array_size > 0) { if (textures.size() < uniform_array_size) { - const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); + HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name); for (int j = textures.size(); j < uniform_array_size; j++) { - if (W && W->get().has(j)) { - textures.push_back(W->get()[j]); + if (W && W->value.has(j)) { + textures.push_back(W->value[j]); } else { textures.push_back(RID()); } } } } else if (textures.is_empty()) { - const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); - if (W && W->get().has(0)) { - textures.push_back(W->get()[0]); + HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name); + if (W && W->value.has(0)) { + textures.push_back(W->value[0]); } } } @@ -1199,12 +1222,12 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, } { //for textures no longer used, unregister them - List<Map<StringName, uint64_t>::Element *> to_delete; - for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) { - if (E->get() != global_textures_pass) { - to_delete.push_back(E); + List<StringName> to_delete; + for (KeyValue<StringName, uint64_t> &E : used_global_textures) { + if (E.value != global_textures_pass) { + to_delete.push_back(E.key); - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E->key()); + GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); if (v) { v->texture_materials.erase(self); } @@ -1227,7 +1250,7 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, } } -void MaterialData::update_parameters_internal(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size) { +void MaterialData::update_parameters_internal(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size) { if ((uint32_t)ubo_data.size() != p_ubo_size) { p_uniform_dirty = true; if (!uniform_buffer) { @@ -1275,16 +1298,16 @@ MaterialStorage *MaterialStorage::get_singleton() { MaterialStorage::MaterialStorage() { singleton = this; - shader_data_request_func[RS::SHADER_SPATIAL] = nullptr; + shader_data_request_func[RS::SHADER_SPATIAL] = _create_scene_shader_func; shader_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_shader_func; shader_data_request_func[RS::SHADER_PARTICLES] = nullptr; - shader_data_request_func[RS::SHADER_SKY] = nullptr; + shader_data_request_func[RS::SHADER_SKY] = _create_sky_shader_func; shader_data_request_func[RS::SHADER_FOG] = nullptr; - material_data_request_func[RS::SHADER_SPATIAL] = nullptr; + material_data_request_func[RS::SHADER_SPATIAL] = _create_scene_material_func; material_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_material_func; material_data_request_func[RS::SHADER_PARTICLES] = nullptr; - material_data_request_func[RS::SHADER_SKY] = nullptr; + material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func; material_data_request_func[RS::SHADER_FOG] = nullptr; static_assert(sizeof(GlobalVariables::Value) == 16); @@ -1365,16 +1388,12 @@ MaterialStorage::MaterialStorage() { actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; actions.render_mode_defines["light_only"] = "#define MODE_LIGHT_ONLY\n"; - actions.base_texture_binding_index = 1; - actions.base_uniform_string = ""; - actions.global_buffer_array_variable = ""; - shaders.compiler_canvas.initialize(actions); } { // Setup Scene compiler - /* + //shader compiler ShaderCompiler::DefaultIdentifierActions actions; @@ -1529,11 +1548,6 @@ MaterialStorage::MaterialStorage() { actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n"; actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - - actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps - actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]"; - actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter - actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; @@ -1541,19 +1555,10 @@ MaterialStorage::MaterialStorage() { actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; - actions.sampler_array_name = "material_samplers"; - actions.base_texture_binding_index = 1; - actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET; - actions.base_uniform_string = "material."; - actions.base_varying_index = 10; - actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - actions.global_buffer_array_variable = "global_variables.data"; - actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs"; - compiler.initialize(actions); - */ + shaders.compiler_scene.initialize(actions); } { @@ -1626,10 +1631,10 @@ ShaderCompiler::DefaultIdentifierActions actions; actions.renames["COLOR"] = "color"; actions.renames["ALPHA"] = "alpha"; actions.renames["EYEDIR"] = "cube_normal"; - actions.renames["POSITION"] = "params.position_multiplier.xyz"; + actions.renames["POSITION"] = "position"; actions.renames["SKY_COORDS"] = "panorama_coords"; actions.renames["SCREEN_UV"] = "uv"; - actions.renames["TIME"] = "params.time"; + actions.renames["TIME"] = "time"; actions.renames["PI"] = _MKSTR(Math_PI); actions.renames["TAU"] = _MKSTR(Math_TAU); actions.renames["E"] = _MKSTR(Math_E); @@ -1660,20 +1665,12 @@ ShaderCompiler::DefaultIdentifierActions actions; actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS"; actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS"; actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS"; - actions.custom_samplers["RADIANCE"] = "material_samplers[3]"; actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n"; actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n"; actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n"; - actions.sampler_array_name = "material_samplers"; - actions.base_texture_binding_index = 1; - actions.texture_layout_set = 1; - actions.base_uniform_string = "material."; - actions.base_varying_index = 10; - actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - actions.global_buffer_array_variable = "global_variables"; shaders.compiler_sky.initialize(actions); } @@ -1681,9 +1678,6 @@ ShaderCompiler::DefaultIdentifierActions actions; //shaders.copy.initialize(); //shaders.copy_version = shaders.copy.version_create(); //TODO //shaders.copy.version_bind_shader(shaders.copy_version, CopyShaderGLES3::MODE_COPY_SECTION); - //shaders.cubemap_filter.init(); - //bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx"); - //shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq); } MaterialStorage::~MaterialStorage() { @@ -1873,7 +1867,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.a; GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1]; - v = v.srgb_to_linear(); + //v = v.srgb_to_linear(); bv_linear.x = v.r; bv_linear.y = v.g; bv_linear.z = v.b; @@ -2077,10 +2071,9 @@ Vector<StringName> MaterialStorage::global_variable_get_list() const { ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); } - const StringName *K = nullptr; Vector<StringName> names; - while ((K = global_variables.variables.next(K))) { - names.push_back(*K); + for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) { + names.push_back(E.key); } names.sort_custom<StringName::AlphCompare>(); return names; @@ -2098,7 +2091,7 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { Material *material = material_storage->get_material(E->get()); ERR_CONTINUE(!material); material_storage->_material_queue_update(material, false, true); @@ -2130,7 +2123,7 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { Material *material = material_storage->get_material(E->get()); ERR_CONTINUE(!material); material_storage->_material_queue_update(material, false, true); @@ -2312,7 +2305,7 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind pos += p_index; - _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer + _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos]); _global_variable_mark_buffer_dirty(pos, 1); } @@ -2428,7 +2421,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->data = nullptr; } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); material->shader_mode = new_mode; if (material->data) { @@ -2445,7 +2438,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->mode = RS::SHADER_MAX; //invalid } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); if (shader->data) { material->data = material_data_request_func[new_mode](shader->data); @@ -2457,7 +2450,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { } if (shader->data) { - for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) { + for (const KeyValue<StringName, HashMap<int, RID>> &E : shader->default_texture_parameter) { for (const KeyValue<int, RID> &E2 : E.value) { shader->data->set_default_texture_param(E.key, E2.value, E2.key); } @@ -2469,7 +2462,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->data->set_code(p_code); } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); _material_queue_update(material, true, true); @@ -2496,7 +2489,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) { if (!shader->default_texture_parameter.has(p_name)) { - shader->default_texture_parameter[p_name] = Map<int, RID>(); + shader->default_texture_parameter[p_name] = HashMap<int, RID>(); } shader->default_texture_parameter[p_name][p_index] = p_texture; } else { @@ -2511,7 +2504,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin if (shader->data) { shader->data->set_default_texture_param(p_name, p_texture, p_index); } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); _material_queue_update(material, false, true); } @@ -2547,7 +2540,7 @@ RS::ShaderNativeSourceCode MaterialStorage::shader_get_native_source_code(RID p_ /* MATERIAL API */ -void MaterialStorage::_material_queue_update(Material *material, bool p_uniform, bool p_texture) { +void MaterialStorage::_material_queue_update(GLES3::Material *material, bool p_uniform, bool p_texture) { material->uniform_dirty = material->uniform_dirty || p_uniform; material->texture_dirty = material->texture_dirty || p_texture; @@ -2739,7 +2732,8 @@ void MaterialStorage::material_update_dependency(RID p_material, RendererStorage } } -// Canvas Shader Data +/* Canvas Shader Data */ + void CanvasShaderData::set_code(const String &p_code) { // compile the shader @@ -2824,14 +2818,14 @@ void CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { @@ -2912,55 +2906,19 @@ GLES3::ShaderData *GLES3::_create_canvas_shader_func() { return shader_data; } -void CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +void CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size); } -// Look up table to translate ShaderLanguage::DataType to GL_TEXTURE_* -static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = { - GL_TEXTURE_2D, // TYPE_VOID, - GL_TEXTURE_2D, // TYPE_BOOL, - GL_TEXTURE_2D, // TYPE_BVEC2, - GL_TEXTURE_2D, // TYPE_BVEC3, - GL_TEXTURE_2D, // TYPE_BVEC4, - GL_TEXTURE_2D, // TYPE_INT, - GL_TEXTURE_2D, // TYPE_IVEC2, - GL_TEXTURE_2D, // TYPE_IVEC3, - GL_TEXTURE_2D, // TYPE_IVEC4, - GL_TEXTURE_2D, // TYPE_UINT, - GL_TEXTURE_2D, // TYPE_UVEC2, - GL_TEXTURE_2D, // TYPE_UVEC3, - GL_TEXTURE_2D, // TYPE_UVEC4, - GL_TEXTURE_2D, // TYPE_FLOAT, - GL_TEXTURE_2D, // TYPE_VEC2, - GL_TEXTURE_2D, // TYPE_VEC3, - GL_TEXTURE_2D, // TYPE_VEC4, - GL_TEXTURE_2D, // TYPE_MAT2, - GL_TEXTURE_2D, // TYPE_MAT3, - GL_TEXTURE_2D, // TYPE_MAT4, - GL_TEXTURE_2D, // TYPE_SAMPLER2D, - GL_TEXTURE_2D, // TYPE_ISAMPLER2D, - GL_TEXTURE_2D, // TYPE_USAMPLER2D, - GL_TEXTURE_2D_ARRAY, // TYPE_SAMPLER2DARRAY, - GL_TEXTURE_2D_ARRAY, // TYPE_ISAMPLER2DARRAY, - GL_TEXTURE_2D_ARRAY, // TYPE_USAMPLER2DARRAY, - GL_TEXTURE_3D, // TYPE_SAMPLER3D, - GL_TEXTURE_3D, // TYPE_ISAMPLER3D, - GL_TEXTURE_3D, // TYPE_USAMPLER3D, - GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE, - GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY, - GL_TEXTURE_2D, // TYPE_STRUCT -}; - void CanvasMaterialData::bind_uniforms() { // Bind Material Uniforms - glBindBufferBase(GL_UNIFORM_BUFFER, RasterizerCanvasGLES3::MATERIAL_UNIFORM_BUFFER_OBJECT, uniform_buffer); + glBindBufferBase(GL_UNIFORM_BUFFER, RasterizerCanvasGLES3::MATERIAL_UNIFORM_LOCATION, uniform_buffer); RID *textures = texture_cache.ptrw(); ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw(); for (int ti = 0; ti < texture_cache.size(); ti++) { Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]); - glActiveTexture(GL_TEXTURE1 + ti); + glActiveTexture(GL_TEXTURE1 + ti); // Start at GL_TEXTURE1 because texture slot 0 is used by the base texture glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id); // Set sampler state here as the same texture can be used in multiple places with different flags @@ -2982,4 +2940,544 @@ GLES3::MaterialData *GLES3::_create_canvas_material_func(ShaderData *p_shader) { return material_data; } +//////////////////////////////////////////////////////////////////////////////// +// SKY SHADER + +void SkyShaderData::set_code(const String &p_code) { + //compile + + code = p_code; + valid = false; + ubo_size = 0; + uniforms.clear(); + + if (code.is_empty()) { + return; //just invalid, but no error + } + + ShaderCompiler::GeneratedCode gen_code; + ShaderCompiler::IdentifierActions actions; + actions.entry_point_stages["sky"] = ShaderCompiler::STAGE_FRAGMENT; + + uses_time = false; + uses_half_res = false; + uses_quarter_res = false; + uses_position = false; + uses_light = false; + + actions.render_mode_flags["use_half_res_pass"] = &uses_half_res; + actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res; + + actions.usage_flag_pointers["TIME"] = &uses_time; + actions.usage_flag_pointers["POSITION"] = &uses_position; + actions.usage_flag_pointers["LIGHT0_ENABLED"] = &uses_light; + actions.usage_flag_pointers["LIGHT0_ENERGY"] = &uses_light; + actions.usage_flag_pointers["LIGHT0_DIRECTION"] = &uses_light; + actions.usage_flag_pointers["LIGHT0_COLOR"] = &uses_light; + actions.usage_flag_pointers["LIGHT0_SIZE"] = &uses_light; + actions.usage_flag_pointers["LIGHT1_ENABLED"] = &uses_light; + actions.usage_flag_pointers["LIGHT1_ENERGY"] = &uses_light; + actions.usage_flag_pointers["LIGHT1_DIRECTION"] = &uses_light; + actions.usage_flag_pointers["LIGHT1_COLOR"] = &uses_light; + actions.usage_flag_pointers["LIGHT1_SIZE"] = &uses_light; + actions.usage_flag_pointers["LIGHT2_ENABLED"] = &uses_light; + actions.usage_flag_pointers["LIGHT2_ENERGY"] = &uses_light; + actions.usage_flag_pointers["LIGHT2_DIRECTION"] = &uses_light; + actions.usage_flag_pointers["LIGHT2_COLOR"] = &uses_light; + actions.usage_flag_pointers["LIGHT2_SIZE"] = &uses_light; + actions.usage_flag_pointers["LIGHT3_ENABLED"] = &uses_light; + actions.usage_flag_pointers["LIGHT3_ENERGY"] = &uses_light; + actions.usage_flag_pointers["LIGHT3_DIRECTION"] = &uses_light; + actions.usage_flag_pointers["LIGHT3_COLOR"] = &uses_light; + actions.usage_flag_pointers["LIGHT3_SIZE"] = &uses_light; + + actions.uniforms = &uniforms; + + Error err = MaterialStorage::get_singleton()->shaders.compiler_sky.compile(RS::SHADER_SKY, code, &actions, path, gen_code); + ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); + + if (version.is_null()) { + version = MaterialStorage::get_singleton()->shaders.sky_shader.version_create(); + } + +#if 0 + print_line("**compiling shader:"); + print_line("**defines:\n"); + for (int i = 0; i < gen_code.defines.size(); i++) { + print_line(gen_code.defines[i]); + } + print_line("\n**uniforms:\n" + gen_code.uniforms); + // print_line("\n**vertex_globals:\n" + gen_code.vertex_global); + // print_line("\n**vertex_code:\n" + gen_code.vertex); + print_line("\n**fragment_globals:\n" + gen_code.fragment_global); + print_line("\n**fragment_code:\n" + gen_code.fragment); + print_line("\n**light_code:\n" + gen_code.light); +#endif + + Vector<StringName> texture_uniform_names; + for (int i = 0; i < gen_code.texture_uniforms.size(); i++) { + texture_uniform_names.push_back(gen_code.texture_uniforms[i].name); + } + + MaterialStorage::get_singleton()->shaders.sky_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names); + ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.sky_shader.version_is_valid(version)); + + ubo_size = gen_code.uniform_total_size; + ubo_offsets = gen_code.uniform_offsets; + texture_uniforms = gen_code.texture_uniforms; + + valid = true; +} + +void SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { + if (!p_texture.is_valid()) { + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } + } else { + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = HashMap<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; + } +} + +void SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { + RBMap<int, StringName> order; + + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; + } + + if (E.value.texture_order >= 0) { + order[E.value.texture_order + 100000] = E.key; + } else { + order[E.value.order] = E.key; + } + } + + for (const KeyValue<int, StringName> &E : order) { + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); + pi.name = E.value; + p_param_list->push_back(pi); + } +} + +void SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; + } + + RendererMaterialStorage::InstanceShaderParam p; + p.info = ShaderLanguage::uniform_to_property_info(E.value); + p.info.name = E.key; //supply name + p.index = E.value.instance_index; + p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); + p_param_list->push_back(p); + } +} + +bool SkyShaderData::is_param_texture(const StringName &p_param) const { + if (!uniforms.has(p_param)) { + return false; + } + + return uniforms[p_param].texture_order >= 0; +} + +bool SkyShaderData::is_animated() const { + return false; +} + +bool SkyShaderData::casts_shadows() const { + return false; +} + +Variant SkyShaderData::get_default_parameter(const StringName &p_parameter) const { + if (uniforms.has(p_parameter)) { + ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; + Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); + } + return Variant(); +} + +RS::ShaderNativeSourceCode SkyShaderData::get_native_source_code() const { + return MaterialStorage::get_singleton()->shaders.sky_shader.version_get_native_source_code(version); +} + +SkyShaderData::SkyShaderData() { + valid = false; +} + +SkyShaderData::~SkyShaderData() { + if (version.is_valid()) { + MaterialStorage::get_singleton()->shaders.sky_shader.version_free(version); + } +} + +GLES3::ShaderData *GLES3::_create_sky_shader_func() { + SkyShaderData *shader_data = memnew(SkyShaderData); + return shader_data; +} + +//////////////////////////////////////////////////////////////////////////////// +// Sky material + +void SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + uniform_set_updated = true; + return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size); +} + +SkyMaterialData::~SkyMaterialData() { +} +GLES3::MaterialData *GLES3::_create_sky_material_func(ShaderData *p_shader) { + SkyMaterialData *material_data = memnew(SkyMaterialData); + material_data->shader_data = static_cast<SkyShaderData *>(p_shader); + //update will happen later anyway so do nothing. + return material_data; +} + +void SkyMaterialData::bind_uniforms() { + // Bind Material Uniforms + glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MATERIAL_UNIFORM_LOCATION, uniform_buffer); + + RID *textures = texture_cache.ptrw(); + ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw(); + for (int ti = 0; ti < texture_cache.size(); ti++) { + Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]); + glActiveTexture(GL_TEXTURE0 + ti); + glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id); + + // Set sampler state here as the same texture can be used in multiple places with different flags + // Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture* + RS::CanvasItemTextureFilter filter = RS::CanvasItemTextureFilter((int(texture_uniforms[ti].filter) + 1) % RS::CANVAS_ITEM_TEXTURE_FILTER_MAX); + RS::CanvasItemTextureRepeat repeat = RS::CanvasItemTextureRepeat((int(texture_uniforms[ti].repeat) + 1) % RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); + texture->gl_set_filter(filter); + texture->gl_set_repeat(repeat); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Scene SHADER + +void SceneShaderData::set_code(const String &p_code) { + //compile + + code = p_code; + valid = false; + ubo_size = 0; + uniforms.clear(); + uses_screen_texture = false; + + if (code.is_empty()) { + return; //just invalid, but no error + } + + ShaderCompiler::GeneratedCode gen_code; + + int blend_modei = BLEND_MODE_MIX; + int depth_testi = DEPTH_TEST_ENABLED; + int alpha_antialiasing_modei = ALPHA_ANTIALIASING_OFF; + int cull_modei = CULL_BACK; + int depth_drawi = DEPTH_DRAW_OPAQUE; + + uses_point_size = false; + uses_alpha = false; + uses_alpha_clip = false; + uses_blend_alpha = false; + uses_depth_pre_pass = false; + uses_discard = false; + uses_roughness = false; + uses_normal = false; + wireframe = false; + + unshaded = false; + uses_vertex = false; + uses_position = false; + uses_sss = false; + uses_transmittance = false; + uses_screen_texture = false; + uses_depth_texture = false; + uses_normal_texture = false; + uses_time = false; + writes_modelview_or_projection = false; + uses_world_coordinates = false; + uses_particle_trails = false; + + ShaderCompiler::IdentifierActions actions; + actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX; + actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT; + actions.entry_point_stages["light"] = ShaderCompiler::STAGE_FRAGMENT; + + actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_modei, BLEND_MODE_ADD); + actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX); + actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB); + actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL); + + actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE); + actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE); + + actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED); + actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE); + actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS); + + actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED); + + actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED); + actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT); + actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK); + + actions.render_mode_flags["unshaded"] = &unshaded; + actions.render_mode_flags["wireframe"] = &wireframe; + actions.render_mode_flags["particle_trails"] = &uses_particle_trails; + + actions.usage_flag_pointers["ALPHA"] = &uses_alpha; + actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip; + actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; + + actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; + actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; + + actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; + actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; + actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture; + actions.usage_flag_pointers["DISCARD"] = &uses_discard; + actions.usage_flag_pointers["TIME"] = &uses_time; + actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; + actions.usage_flag_pointers["NORMAL"] = &uses_normal; + actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal; + + actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size; + actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size; + + actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection; + actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection; + actions.write_flag_pointers["VERTEX"] = &uses_vertex; + actions.write_flag_pointers["POSITION"] = &uses_position; + + actions.usage_flag_pointers["TANGENT"] = &uses_tangent; + actions.usage_flag_pointers["BINORMAL"] = &uses_tangent; + actions.usage_flag_pointers["COLOR"] = &uses_color; + actions.usage_flag_pointers["UV"] = &uses_uv; + actions.usage_flag_pointers["UV2"] = &uses_uv2; + actions.usage_flag_pointers["CUSTOM0"] = &uses_custom0; + actions.usage_flag_pointers["CUSTOM1"] = &uses_custom1; + actions.usage_flag_pointers["CUSTOM2"] = &uses_custom2; + actions.usage_flag_pointers["CUSTOM3"] = &uses_custom3; + actions.usage_flag_pointers["BONE_INDICES"] = &uses_bones; + actions.usage_flag_pointers["BONE_WEIGHTS"] = &uses_weights; + + actions.uniforms = &uniforms; + + Error err = MaterialStorage::get_singleton()->shaders.compiler_scene.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code); + ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); + + if (version.is_null()) { + version = MaterialStorage::get_singleton()->shaders.scene_shader.version_create(); + } + + depth_draw = DepthDraw(depth_drawi); + depth_test = DepthTest(depth_testi); + cull_mode = Cull(cull_modei); + blend_mode = BlendMode(blend_modei); + alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei); + vertex_input_mask = uint32_t(uses_normal); + vertex_input_mask |= uses_tangent << 1; + vertex_input_mask |= uses_color << 2; + vertex_input_mask |= uses_uv << 3; + vertex_input_mask |= uses_uv2 << 4; + vertex_input_mask |= uses_custom0 << 5; + vertex_input_mask |= uses_custom1 << 6; + vertex_input_mask |= uses_custom2 << 7; + vertex_input_mask |= uses_custom3 << 8; + vertex_input_mask |= uses_bones << 9; + vertex_input_mask |= uses_weights << 10; + +#if 0 + print_line("**compiling shader:"); + print_line("**defines:\n"); + for (int i = 0; i < gen_code.defines.size(); i++) { + print_line(gen_code.defines[i]); + } + + Map<String, String>::Element *el = gen_code.code.front(); + while (el) { + print_line("\n**code " + el->key() + ":\n" + el->value()); + + el = el->next(); + } + + print_line("\n**uniforms:\n" + gen_code.uniforms); + print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]); + print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]); +#endif + + Vector<StringName> texture_uniform_names; + for (int i = 0; i < gen_code.texture_uniforms.size(); i++) { + texture_uniform_names.push_back(gen_code.texture_uniforms[i].name); + } + + MaterialStorage::get_singleton()->shaders.scene_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names); + ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.scene_shader.version_is_valid(version)); + + ubo_size = gen_code.uniform_total_size; + ubo_offsets = gen_code.uniform_offsets; + texture_uniforms = gen_code.texture_uniforms; + + // if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage + if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) { + blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE; + } + + valid = true; +} + +void SceneShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { + if (!p_texture.is_valid()) { + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } + } else { + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = HashMap<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; + } +} + +void SceneShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { + RBMap<int, StringName> order; + + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { + continue; + } + + if (E.value.texture_order >= 0) { + order[E.value.texture_order + 100000] = E.key; + } else { + order[E.value.order] = E.key; + } + } + + for (const KeyValue<int, StringName> &E : order) { + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); + pi.name = E.value; + p_param_list->push_back(pi); + } +} + +void SceneShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; + } + + RendererMaterialStorage::InstanceShaderParam p; + p.info = ShaderLanguage::uniform_to_property_info(E.value); + p.info.name = E.key; //supply name + p.index = E.value.instance_index; + p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); + p_param_list->push_back(p); + } +} + +bool SceneShaderData::is_param_texture(const StringName &p_param) const { + if (!uniforms.has(p_param)) { + return false; + } + + return uniforms[p_param].texture_order >= 0; +} + +bool SceneShaderData::is_animated() const { + return false; +} + +bool SceneShaderData::casts_shadows() const { + return false; +} + +Variant SceneShaderData::get_default_parameter(const StringName &p_parameter) const { + if (uniforms.has(p_parameter)) { + ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; + Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); + } + return Variant(); +} + +RS::ShaderNativeSourceCode SceneShaderData::get_native_source_code() const { + return MaterialStorage::get_singleton()->shaders.scene_shader.version_get_native_source_code(version); +} + +SceneShaderData::SceneShaderData() { + valid = false; + uses_screen_texture = false; +} + +SceneShaderData::~SceneShaderData() { + if (version.is_valid()) { + MaterialStorage::get_singleton()->shaders.scene_shader.version_free(version); + } +} + +GLES3::ShaderData *GLES3::_create_scene_shader_func() { + SceneShaderData *shader_data = memnew(SceneShaderData); + return shader_data; +} + +void SceneMaterialData::set_render_priority(int p_priority) { + priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits +} + +void SceneMaterialData::set_next_pass(RID p_pass) { + next_pass = p_pass; +} + +void SceneMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size); +} + +SceneMaterialData::~SceneMaterialData() { +} + +GLES3::MaterialData *GLES3::_create_scene_material_func(ShaderData *p_shader) { + SceneMaterialData *material_data = memnew(SceneMaterialData); + material_data->shader_data = static_cast<SceneShaderData *>(p_shader); + //update will happen later anyway so do nothing. + return material_data; +} + +void SceneMaterialData::bind_uniforms() { + // Bind Material Uniforms + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_MATERIAL_UNIFORM_LOCATION, uniform_buffer); + + RID *textures = texture_cache.ptrw(); + ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw(); + for (int ti = 0; ti < texture_cache.size(); ti++) { + Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]); + glActiveTexture(GL_TEXTURE0 + ti); + glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id); + + // Set sampler state here as the same texture can be used in multiple places with different flags + // Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture* + RS::CanvasItemTextureFilter filter = RS::CanvasItemTextureFilter((int(texture_uniforms[ti].filter) + 1) % RS::CANVAS_ITEM_TEXTURE_FILTER_MAX); + RS::CanvasItemTextureRepeat repeat = RS::CanvasItemTextureRepeat((int(texture_uniforms[ti].repeat) + 1) % RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); + texture->gl_set_filter(filter); + texture->gl_set_repeat(repeat); + } +} + #endif // !GLES3_ENABLED diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index cc6cbdc152..6a11a10d76 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -45,15 +45,19 @@ #include "drivers/gles3/shaders/copy.glsl.gen.h" #include "../shaders/canvas.glsl.gen.h" +#include "../shaders/cubemap_filter.glsl.gen.h" +#include "../shaders/scene.glsl.gen.h" #include "../shaders/sky.glsl.gen.h" namespace GLES3 { -/* SHADER Structs */ +/* Shader Structs */ struct Shaders { CanvasShaderGLES3 canvas_shader; SkyShaderGLES3 sky_shader; + SceneShaderGLES3 scene_shader; + CubemapFilterShaderGLES3 cubemap_filter_shader; ShaderCompiler compiler_canvas; ShaderCompiler compiler_scene; @@ -84,24 +88,24 @@ struct Shader { ShaderData *data = nullptr; String code; RS::ShaderMode mode; - Map<StringName, Map<int, RID>> default_texture_parameter; - Set<Material *> owners; + HashMap<StringName, HashMap<int, RID>> default_texture_parameter; + RBSet<Material *> owners; }; /* Material structs */ struct MaterialData { - void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); + void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); + void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); virtual void set_render_priority(int p_priority) = 0; virtual void set_next_pass(RID p_pass) = 0; - virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; + virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; virtual void bind_uniforms() = 0; virtual ~MaterialData(); // Used internally by all Materials - void update_parameters_internal(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size); + void update_parameters_internal(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size); protected: Vector<uint8_t> ubo_data; @@ -114,7 +118,7 @@ private: List<RID>::Element *global_buffer_E = nullptr; List<RID>::Element *global_texture_E = nullptr; uint64_t global_textures_pass = 0; - Map<StringName, uint64_t> used_global_textures; + HashMap<StringName, uint64_t> used_global_textures; //internally by update_parameters_internal }; @@ -130,7 +134,7 @@ struct Material { uint32_t shader_id = 0; bool uniform_dirty = false; bool texture_dirty = false; - Map<StringName, Variant> params; + HashMap<StringName, Variant> params; int32_t priority = 0; RID next_pass; SelfList<Material> update_element; @@ -141,7 +145,7 @@ struct Material { update_element(this) {} }; -// CanvasItem Materials +/* CanvasItem Materials */ struct CanvasShaderData : public ShaderData { enum BlendMode { //used internally @@ -158,14 +162,14 @@ struct CanvasShaderData : public ShaderData { //PipelineVariants pipeline_variants; String path; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_screen_texture = false; bool uses_sdf = false; @@ -193,20 +197,194 @@ struct CanvasMaterialData : public MaterialData { virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual void bind_uniforms(); virtual ~CanvasMaterialData(); }; MaterialData *_create_canvas_material_func(ShaderData *p_shader); +/* Sky Materials */ + +struct SkyShaderData : public ShaderData { + bool valid; + RID version; + + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; + + Vector<uint32_t> ubo_offsets; + uint32_t ubo_size; + + String path; + String code; + HashMap<StringName, HashMap<int, RID>> default_texture_params; + + bool uses_time; + bool uses_position; + bool uses_half_res; + bool uses_quarter_res; + bool uses_light; + + virtual void set_code(const String &p_Code); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); + virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; + virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_animated() const; + virtual bool casts_shadows() const; + virtual Variant get_default_parameter(const StringName &p_parameter) const; + virtual RS::ShaderNativeSourceCode get_native_source_code() const; + SkyShaderData(); + virtual ~SkyShaderData(); +}; + +ShaderData *_create_sky_shader_func(); + +struct SkyMaterialData : public MaterialData { + SkyShaderData *shader_data = nullptr; + bool uniform_set_updated = false; + + virtual void set_render_priority(int p_priority) {} + virtual void set_next_pass(RID p_pass) {} + virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual void bind_uniforms(); + virtual ~SkyMaterialData(); +}; + +MaterialData *_create_sky_material_func(ShaderData *p_shader); + +/* Scene Materials */ + +struct SceneShaderData : public ShaderData { + enum BlendMode { //used internally + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + BLEND_MODE_ALPHA_TO_COVERAGE + }; + + enum DepthDraw { + DEPTH_DRAW_DISABLED, + DEPTH_DRAW_OPAQUE, + DEPTH_DRAW_ALWAYS + }; + + enum DepthTest { + DEPTH_TEST_DISABLED, + DEPTH_TEST_ENABLED + }; + + enum Cull { + CULL_DISABLED, + CULL_FRONT, + CULL_BACK + }; + + enum AlphaAntiAliasing { + ALPHA_ANTIALIASING_OFF, + ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE, + ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE + }; + + bool valid; + RID version; + + String path; + + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; + + Vector<uint32_t> ubo_offsets; + uint32_t ubo_size; + + String code; + HashMap<StringName, HashMap<int, RID>> default_texture_params; + + BlendMode blend_mode; + AlphaAntiAliasing alpha_antialiasing_mode; + DepthDraw depth_draw; + DepthTest depth_test; + Cull cull_mode; + + bool uses_point_size; + bool uses_alpha; + bool uses_blend_alpha; + bool uses_alpha_clip; + bool uses_depth_pre_pass; + bool uses_discard; + bool uses_roughness; + bool uses_normal; + bool uses_particle_trails; + bool wireframe; + + bool unshaded; + bool uses_vertex; + bool uses_position; + bool uses_sss; + bool uses_transmittance; + bool uses_screen_texture; + bool uses_depth_texture; + bool uses_normal_texture; + bool uses_time; + bool writes_modelview_or_projection; + bool uses_world_coordinates; + bool uses_tangent; + bool uses_color; + bool uses_uv; + bool uses_uv2; + bool uses_custom0; + bool uses_custom1; + bool uses_custom2; + bool uses_custom3; + bool uses_bones; + bool uses_weights; + + uint32_t vertex_input_mask = 0; + + uint64_t last_pass = 0; + uint32_t index = 0; + + virtual void set_code(const String &p_Code); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); + virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; + + virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_animated() const; + virtual bool casts_shadows() const; + virtual Variant get_default_parameter(const StringName &p_parameter) const; + virtual RS::ShaderNativeSourceCode get_native_source_code() const; + + SceneShaderData(); + virtual ~SceneShaderData(); +}; + +ShaderData *_create_scene_shader_func(); + +struct SceneMaterialData : public MaterialData { + SceneShaderData *shader_data = nullptr; + uint64_t last_pass = 0; + uint32_t index = 0; + RID next_pass; + uint8_t priority = 0; + virtual void set_render_priority(int p_priority); + virtual void set_next_pass(RID p_pass); + virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual void bind_uniforms(); + virtual ~SceneMaterialData(); +}; + +MaterialData *_create_scene_material_func(ShaderData *p_shader); + /* Global variable structs */ struct GlobalVariables { enum { BUFFER_DIRTY_REGION_SIZE = 1024 }; struct Variable { - Set<RID> texture_materials; // materials using this + RBSet<RID> texture_materials; // materials using this RS::GlobalVariableType type; Variant value; @@ -283,8 +461,6 @@ private: SelfList<Material>::List material_update_list; - //static void _material_uniform_set_erased(void *p_material); - public: static MaterialStorage *get_singleton(); diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index 41b5107b6c..5739a63cac 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -68,7 +68,7 @@ void MeshStorage::mesh_free(RID p_rid) { ERR_PRINT("deleting mesh with active instances"); } if (mesh->shadow_owners.size()) { - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + for (RBSet<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { Mesh *shadow_owner = E->get(); shadow_owner->shadow_mesh = RID(); shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); @@ -194,6 +194,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer); glBufferData(GL_ARRAY_BUFFER, p_surface.attribute_data.size(), p_surface.attribute_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + s->attribute_buffer_size = p_surface.attribute_data.size(); } if (p_surface.skin_data.size()) { glGenBuffers(1, &s->skin_buffer); @@ -216,6 +217,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) glBufferData(GL_ELEMENT_ARRAY_BUFFER, p_surface.index_data.size(), p_surface.index_data.ptr(), GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind s->index_count = p_surface.index_count; + s->index_buffer_size = p_surface.index_data.size(); if (p_surface.lods.size()) { s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size()); @@ -266,7 +268,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + for (RBSet<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { Mesh *shadow_owner = E->get(); shadow_owner->shadow_mesh = RID(); shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); @@ -323,7 +325,97 @@ RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const { } RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { - return RS::SurfaceData(); + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, RS::SurfaceData()); + ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData()); + + Mesh::Surface &s = *mesh->surfaces[p_surface]; + + RS::SurfaceData sd; + sd.format = s.format; + { + Vector<uint8_t> ret; + ret.resize(s.vertex_buffer_size); + glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffer); + +#if defined(__EMSCRIPTEN__) + { + uint8_t *w = ret.ptrw(); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, w); + } +#else + void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, GL_MAP_READ_BIT); + ERR_FAIL_NULL_V(data, RS::SurfaceData()); + { + uint8_t *w = ret.ptrw(); + memcpy(w, data, s.vertex_buffer_size); + } + glUnmapBuffer(GL_ARRAY_BUFFER); +#endif + sd.vertex_data = ret; + } + + if (s.attribute_buffer != 0) { + Vector<uint8_t> ret; + ret.resize(s.attribute_buffer_size); + glBindBuffer(GL_ARRAY_BUFFER, s.attribute_buffer); + +#if defined(__EMSCRIPTEN__) + { + uint8_t *w = ret.ptrw(); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, w); + } +#else + void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, GL_MAP_READ_BIT); + ERR_FAIL_NULL_V(data, RS::SurfaceData()); + { + uint8_t *w = ret.ptrw(); + memcpy(w, data, s.attribute_buffer_size); + } + glUnmapBuffer(GL_ARRAY_BUFFER); +#endif + sd.attribute_data = ret; + } + + sd.vertex_count = s.vertex_count; + sd.index_count = s.index_count; + sd.primitive = s.primitive; + + if (sd.index_count) { + Vector<uint8_t> ret; + ret.resize(s.index_buffer_size); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer); + +#if defined(__EMSCRIPTEN__) + { + uint8_t *w = ret.ptrw(); + glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, w); + } +#else + void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, GL_MAP_READ_BIT); + ERR_FAIL_NULL_V(data, RS::SurfaceData()); + { + uint8_t *w = ret.ptrw(); + memcpy(w, data, s.index_buffer_size); + } + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); +#endif + sd.index_data = ret; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + sd.aabb = s.aabb; + for (uint32_t i = 0; i < s.lod_count; i++) { + RS::SurfaceData::LOD lod; + lod.edge_length = s.lods[i].edge_length; + //lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer); + sd.lods.push_back(lod); + } + + sd.bone_aabbs = s.bone_aabbs; + glBindBuffer(GL_ARRAY_BUFFER, 0); + + return sd; } int MeshStorage::mesh_get_surface_count(RID p_mesh) const { @@ -478,25 +570,29 @@ void MeshStorage::mesh_clear(RID p_mesh) { if (s.vertex_buffer != 0) { glDeleteBuffers(1, &s.vertex_buffer); + s.vertex_buffer = 0; } if (s.version_count != 0) { for (uint32_t j = 0; j < s.version_count; j++) { glDeleteVertexArrays(1, &s.versions[j].vertex_array); + s.versions[j].vertex_array = 0; } } if (s.attribute_buffer != 0) { glDeleteBuffers(1, &s.attribute_buffer); + s.attribute_buffer = 0; } if (s.skin_buffer != 0) { glDeleteBuffers(1, &s.skin_buffer); + s.skin_buffer = 0; } if (s.index_buffer != 0) { glDeleteBuffers(1, &s.index_buffer); - glDeleteVertexArrays(1, &s.index_array); + s.index_buffer = 0; } memdelete(mesh->surfaces[i]); } @@ -514,7 +610,7 @@ void MeshStorage::mesh_clear(RID p_mesh) { mesh->has_bone_weights = false; mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + for (RBSet<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { Mesh *shadow_owner = E->get(); shadow_owner->shadow_mesh = RID(); shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); @@ -553,14 +649,14 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V case RS::ARRAY_NORMAL: { attribs[i].offset = vertex_stride; // Will need to change to accommodate octahedral compression - attribs[i].size = 1; + attribs[i].size = 4; attribs[i].type = GL_UNSIGNED_INT_2_10_10_10_REV; vertex_stride += sizeof(float); attribs[i].normalized = GL_TRUE; } break; case RS::ARRAY_TANGENT: { attribs[i].offset = vertex_stride; - attribs[i].size = 1; + attribs[i].size = 4; attribs[i].type = GL_UNSIGNED_INT_2_10_10_10_REV; vertex_stride += sizeof(float); attribs[i].normalized = GL_TRUE; @@ -629,14 +725,17 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V continue; } if (i <= RS::ARRAY_TANGENT) { + attribs[i].stride = vertex_stride; if (mis) { glBindBuffer(GL_ARRAY_BUFFER, mis->vertex_buffer); } else { glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer); } } else if (i <= RS::ARRAY_CUSTOM3) { + attribs[i].stride = attributes_stride; glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer); } else { + attribs[i].stride = skin_stride; glBindBuffer(GL_ARRAY_BUFFER, s->skin_buffer); } @@ -645,7 +744,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V } else { glVertexAttribPointer(i, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset)); } - glEnableVertexAttribArray(attribs[i].index); + glEnableVertexAttribArray(i); } // Do not bind index here as we want to switch between index buffers for LOD @@ -710,17 +809,20 @@ void MeshStorage::_mesh_instance_clear(MeshInstance *mi) { if (mi->surfaces[i].version_count != 0) { for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) { glDeleteVertexArrays(1, &mi->surfaces[i].versions[j].vertex_array); + mi->surfaces[i].versions[j].vertex_array = 0; } memfree(mi->surfaces[i].versions); } if (mi->surfaces[i].vertex_buffer != 0) { glDeleteBuffers(1, &mi->surfaces[i].vertex_buffer); + mi->surfaces[i].vertex_buffer = 0; } } mi->surfaces.clear(); if (mi->blend_weights_buffer != 0) { glDeleteBuffers(1, &mi->blend_weights_buffer); + mi->blend_weights_buffer = 0; } mi->blend_weights.clear(); mi->weights_dirty = false; diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h index f51ec6edbe..856463d45e 100644 --- a/drivers/gles3/storage/mesh_storage.h +++ b/drivers/gles3/storage/mesh_storage.h @@ -54,7 +54,6 @@ struct Mesh { struct Attrib { bool enabled; bool integer; - GLuint index; GLint size; GLenum type; GLboolean normalized; @@ -69,6 +68,7 @@ struct Mesh { GLuint skin_buffer = 0; uint32_t vertex_count = 0; uint32_t vertex_buffer_size = 0; + uint32_t attribute_buffer_size = 0; uint32_t skin_buffer_size = 0; // Cache vertex arrays so they can be created @@ -84,8 +84,8 @@ struct Mesh { uint32_t version_count = 0; GLuint index_buffer = 0; - GLuint index_array = 0; uint32_t index_count = 0; + uint32_t index_buffer_size = 0; struct LOD { float edge_length = 0.0; @@ -123,7 +123,7 @@ struct Mesh { List<MeshInstance *> instances; RID shadow_mesh; - Set<Mesh *> shadow_owners; + RBSet<Mesh *> shadow_owners; RendererStorage::Dependency dependency; }; @@ -357,6 +357,12 @@ public: } } + _FORCE_INLINE_ GLenum mesh_surface_get_index_type(void *p_surface) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + + return s->vertex_count <= 65536 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; + } + // Use this to cache Vertex Array Objects so they are only generated once _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, GLuint &r_vertex_array_gl) { Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); @@ -388,6 +394,9 @@ public: /* MESH INSTANCE API */ + MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); }; + bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); }; + virtual RID mesh_instance_create(RID p_base) override; virtual void mesh_instance_free(RID p_rid) override; virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override; @@ -431,6 +440,9 @@ public: /* MULTIMESH API */ + MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); }; + bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }; + virtual RID multimesh_allocate() override; virtual void multimesh_initialize(RID p_rid) override; virtual void multimesh_free(RID p_rid) override; @@ -483,6 +495,9 @@ public: /* SKELETON API */ + Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); }; + bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); }; + virtual RID skeleton_allocate() override; virtual void skeleton_initialize(RID p_rid) override; virtual void skeleton_free(RID p_rid) override; diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 6f2dc391d8..f932fa8bad 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -62,8 +62,9 @@ TextureStorage::TextureStorage() { Ref<Image> image; image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); + image->create(4, 4, true, Image::FORMAT_RGBA8); image->fill(Color(1, 1, 1, 1)); + image->generate_mipmaps(); default_gl_textures[DEFAULT_GL_TEXTURE_WHITE] = texture_allocate(); texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_WHITE], image); @@ -92,8 +93,9 @@ TextureStorage::TextureStorage() { { // black Ref<Image> image; image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); + image->create(4, 4, true, Image::FORMAT_RGBA8); image->fill(Color(0, 0, 0, 1)); + image->generate_mipmaps(); default_gl_textures[DEFAULT_GL_TEXTURE_BLACK] = texture_allocate(); texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_BLACK], image); @@ -117,8 +119,9 @@ TextureStorage::TextureStorage() { { Ref<Image> image; image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); + image->create(4, 4, true, Image::FORMAT_RGBA8); image->fill(Color(0.5, 0.5, 1, 1)); + image->generate_mipmaps(); default_gl_textures[DEFAULT_GL_TEXTURE_NORMAL] = texture_allocate(); texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_NORMAL], image); @@ -127,8 +130,9 @@ TextureStorage::TextureStorage() { { Ref<Image> image; image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); + image->create(4, 4, true, Image::FORMAT_RGBA8); image->fill(Color(1.0, 0.5, 1, 1)); + image->generate_mipmaps(); default_gl_textures[DEFAULT_GL_TEXTURE_ANISO] = texture_allocate(); texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_ANISO], image); @@ -189,18 +193,7 @@ TextureStorage::~TextureStorage() { } } -void TextureStorage::set_main_thread_id(Thread::ID p_id) { - _main_thread_id = p_id; -} - -bool TextureStorage::_is_main_thread() { - //#if defined DEBUG_ENABLED && defined TOOLS_ENABLED - // must be called from main thread in OpenGL - bool is_main_thread = _main_thread_id == Thread::get_caller_id(); - //#endif - return is_main_thread; -} - +//TODO, move back to storage bool TextureStorage::can_create_resources_async() const { return false; } @@ -561,7 +554,7 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I } break; */ default: { - ERR_FAIL_V(Ref<Image>()); + ERR_FAIL_V_MSG(Ref<Image>(), "Image Format: " + itos(p_format) + " is not supported by the OpenGL3 Renderer"); } } @@ -644,10 +637,14 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im Texture texture; texture.width = p_image->get_width(); texture.height = p_image->get_height(); + texture.alloc_width = texture.width; + texture.alloc_height = texture.height; + texture.mipmaps = p_image->get_mipmap_count(); texture.format = p_image->get_format(); texture.type = Texture::TYPE_2D; texture.target = GL_TEXTURE_2D; - texture.image_cache_2d = p_image; //TODO, remove this once texture_2d_get is implemented + _get_gl_image_and_format(Ref<Image>(), texture.format, 0, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false); + //texture.total_data_size = p_image->get_image_data_size(); // verify that this returns size in bytes texture.active = true; glGenTextures(1, &texture.tex_id); texture_owner.initialize_rid(p_texture, texture); @@ -740,49 +737,66 @@ void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { } Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!texture, Ref<Image>()); #ifdef TOOLS_ENABLED - if (tex->image_cache_2d.is_valid() && !tex->is_render_target) { - return tex->image_cache_2d; + if (texture->image_cache_2d.is_valid() && !texture->is_render_target) { + return texture->image_cache_2d; } #endif - /* -#ifdef TOOLS_ENABLED - if (tex->image_cache_2d.is_valid()) { - return tex->image_cache_2d; +#ifdef GLES_OVER_GL + // OpenGL 3.3 supports glGetTexImage which is faster and simpler than glReadPixels. + Vector<uint8_t> data; + + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->real_format, texture->mipmaps > 1); + + data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers + uint8_t *w = data.ptrw(); + + glActiveTexture(GL_TEXTURE0); + + glBindTexture(texture->target, texture->tex_id); + + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + for (int i = 0; i < texture->mipmaps; i++) { + int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, texture->real_format, i); + + if (texture->compressed) { + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glGetCompressedTexImage(texture->target, i, &w[ofs]); + + } else { + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &w[ofs]); + } } -#endif - Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + + data.resize(data_size); + ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); Ref<Image> image; - image.instance(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->empty(), Ref<Image>()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); + image.instantiate(); + image->create(texture->width, texture->height, texture->mipmaps > 1, texture->real_format, data); + ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); + if (texture->format != texture->real_format) { + image->convert(texture->format); } +#else + // Support for Web and Mobile will come later. + Ref<Image> image; +#endif #ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - tex->image_cache_2d = image; + if (Engine::get_singleton()->is_editor_hint() && !texture->is_render_target) { + texture->image_cache_2d = image; } #endif -*/ - /* - #ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) { - tex->image_cache_2d = image; - } - #endif - */ - - // return image; - - return Ref<Image>(); + return image; } void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { @@ -954,7 +968,7 @@ void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image, Image::Format real_format; Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), 0, real_format, format, internal_format, type, compressed, texture->resize_to_po2); - + ERR_FAIL_COND(img.is_null()); if (texture->resize_to_po2) { if (p_image->is_compressed()) { ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage."); @@ -1311,6 +1325,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { rt->color_internal_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_RGBA8 : GL_RGB10_A2; rt->color_format = GL_RGBA; + rt->color_type = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV; rt->image_format = Image::FORMAT_RGBA8; glDisable(GL_SCISSOR_TEST); @@ -1357,6 +1372,9 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { } texture->format = rt->image_format; + texture->real_format = rt->image_format; + texture->type = Texture::TYPE_2D; + texture->target = GL_TEXTURE_2D; texture->gl_format_cache = rt->color_format; texture->gl_type_cache = GL_UNSIGNED_BYTE; texture->gl_internal_format_cache = rt->color_internal_format; diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index 1e1cd3f9bf..b092a009c1 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -141,6 +141,7 @@ struct Texture { int alloc_width = 0; int alloc_height = 0; Image::Format format = Image::FORMAT_R8; + Image::Format real_format = Image::FORMAT_R8; enum Type { TYPE_2D, @@ -248,7 +249,10 @@ struct Texture { [[fallthrough]]; case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { pmag = GL_NEAREST; - if (config->use_nearest_mip_filter) { + if (mipmaps <= 1) { + pmin = GL_NEAREST; + max_lod = 0; + } else if (config->use_nearest_mip_filter) { pmin = GL_NEAREST_MIPMAP_NEAREST; } else { pmin = GL_NEAREST_MIPMAP_LINEAR; @@ -260,9 +264,11 @@ struct Texture { [[fallthrough]]; case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { pmag = GL_LINEAR; - if (config->use_nearest_mip_filter) { + if (mipmaps <= 1) { + pmin = GL_LINEAR; + max_lod = 0; + } else if (config->use_nearest_mip_filter) { pmin = GL_LINEAR_MIPMAP_NEAREST; - } else { pmin = GL_LINEAR_MIPMAP_LINEAR; } @@ -370,9 +376,6 @@ private: RID default_gl_textures[DEFAULT_GL_TEXTURE_MAX]; - Thread::ID _main_thread_id = 0; - bool _is_main_thread(); - /* Canvas Texture API */ RID_Owner<CanvasTexture, true> canvas_texture_owner; @@ -440,8 +443,6 @@ public: }; bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; - void set_main_thread_id(Thread::ID p_id); - virtual bool can_create_resources_async() const override; RID texture_create(); @@ -574,7 +575,7 @@ public: }; inline String TextureStorage::get_framebuffer_error(GLenum p_status) { -#ifdef DEBUG_ENABLED +#if defined(DEBUG_ENABLED) && defined(GLES_OVER_GL) if (p_status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) { return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; } else if (p_status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) { diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index d442e521bf..2deeb79957 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -128,7 +128,7 @@ void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hos #if defined(UWP_ENABLED) -void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const { +void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const { using namespace Windows::Networking; using namespace Windows::Networking::Connectivity; @@ -143,7 +143,7 @@ void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) con } String name = hostname->RawName->Data(); - Map<String, Interface_Info>::Element *E = r_interfaces->find(name); + HashMap<String, Interface_Info>::Element *E = r_interfaces->find(name); if (!E) { Interface_Info info; info.name = name; @@ -162,7 +162,7 @@ void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) con #else -void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const { +void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const { ULONG buf_size = 1024; IP_ADAPTER_ADDRESSES *addrs; @@ -212,7 +212,7 @@ void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) con #else // UNIX -void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const { +void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const { struct ifaddrs *ifAddrStruct = nullptr; struct ifaddrs *ifa = nullptr; int family; @@ -230,7 +230,7 @@ void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) con continue; } - Map<String, Interface_Info>::Element *E = r_interfaces->find(ifa->ifa_name); + HashMap<String, Interface_Info>::Iterator E = r_interfaces->find(ifa->ifa_name); if (!E) { Interface_Info info; info.name = ifa->ifa_name; @@ -240,7 +240,7 @@ void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) con ERR_CONTINUE(!E); } - Interface_Info &info = E->get(); + Interface_Info &info = E->value; info.ip_addresses.push_front(_sockaddr2ip(ifa->ifa_addr)); } diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index f0ad01d248..06fcdb6e17 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -43,7 +43,7 @@ class IPUnix : public IP { static IP *_create_unix(); public: - virtual void get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const override; + virtual void get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const override; static void make_default(); IPUnix(); diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index 3130d5cae2..f172f31b24 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -256,7 +256,7 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IPAddress p_ip, Str IPAddress if_ip; uint32_t if_v6id = 0; - Map<String, IP::Interface_Info> if_info; + HashMap<String, IP::Interface_Info> if_info; IP::get_singleton()->get_local_interfaces(&if_info); for (KeyValue<String, IP::Interface_Info> &E : if_info) { IP::Interface_Info &c = E.value; diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 5102eab979..23c2d764b8 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -132,13 +132,13 @@ static void update_external_dependency_for_store(VkSubpassDependency &dependency void RenderingDeviceVulkan::_add_dependency(RID p_id, RID p_depends_on) { if (!dependency_map.has(p_depends_on)) { - dependency_map[p_depends_on] = Set<RID>(); + dependency_map[p_depends_on] = RBSet<RID>(); } dependency_map[p_depends_on].insert(p_id); if (!reverse_dependency_map.has(p_id)) { - reverse_dependency_map[p_id] = Set<RID>(); + reverse_dependency_map[p_id] = RBSet<RID>(); } reverse_dependency_map[p_id].insert(p_depends_on); @@ -147,26 +147,26 @@ void RenderingDeviceVulkan::_add_dependency(RID p_id, RID p_depends_on) { void RenderingDeviceVulkan::_free_dependencies(RID p_id) { //direct dependencies must be freed - Map<RID, Set<RID>>::Element *E = dependency_map.find(p_id); + HashMap<RID, RBSet<RID>>::Iterator E = dependency_map.find(p_id); if (E) { - while (E->get().size()) { - free(E->get().front()->get()); + while (E->value.size()) { + free(E->value.front()->get()); } - dependency_map.erase(E); + dependency_map.remove(E); } //reverse dependencies must be unreferenced E = reverse_dependency_map.find(p_id); if (E) { - for (Set<RID>::Element *F = E->get().front(); F; F = F->next()) { - Map<RID, Set<RID>>::Element *G = dependency_map.find(F->get()); + for (RBSet<RID>::Element *F = E->value.front(); F; F = F->next()) { + HashMap<RID, RBSet<RID>>::Iterator G = dependency_map.find(F->get()); ERR_CONTINUE(!G); - ERR_CONTINUE(!G->get().has(p_id)); - G->get().erase(p_id); + ERR_CONTINUE(!G->value.has(p_id)); + G->value.erase(p_id); } - reverse_dependency_map.erase(E); + reverse_dependency_map.remove(E); } } @@ -3856,7 +3856,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c key.passes = p_passes; key.view_count = p_view_count; - const Map<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key); + const RBMap<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key); if (E) { //exists, return return E->get(); @@ -3884,7 +3884,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c FramebufferFormatKey key; key.passes.push_back(FramebufferPass()); - const Map<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key); + const RBMap<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key); if (E) { //exists, return return E->get(); @@ -3935,11 +3935,11 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c } RenderingDevice::TextureSamples RenderingDeviceVulkan::framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass) { - Map<FramebufferFormatID, FramebufferFormat>::Element *E = framebuffer_formats.find(p_format); + HashMap<FramebufferFormatID, FramebufferFormat>::Iterator E = framebuffer_formats.find(p_format); ERR_FAIL_COND_V(!E, TEXTURE_SAMPLES_1); - ERR_FAIL_COND_V(p_pass >= uint32_t(E->get().pass_samples.size()), TEXTURE_SAMPLES_1); + ERR_FAIL_COND_V(p_pass >= uint32_t(E->value.pass_samples.size()), TEXTURE_SAMPLES_1); - return E->get().pass_samples[p_pass]; + return E->value.pass_samples[p_pass]; } /***********************/ @@ -4138,7 +4138,7 @@ RenderingDevice::VertexFormatID RenderingDeviceVulkan::vertex_format_create(cons vdcache.bindings = memnew_arr(VkVertexInputBindingDescription, p_vertex_formats.size()); vdcache.attributes = memnew_arr(VkVertexInputAttributeDescription, p_vertex_formats.size()); - Set<int> used_locations; + RBSet<int> used_locations; for (int i = 0; i < p_vertex_formats.size(); i++) { ERR_CONTINUE(p_vertex_formats[i].format >= DATA_FORMAT_MAX); ERR_FAIL_COND_V(used_locations.has(p_vertex_formats[i].location), INVALID_ID); @@ -5292,7 +5292,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_ //has data, needs an actual format; UniformSetFormat usformat; usformat.uniform_info = set.uniform_info; - Map<UniformSetFormat, uint32_t>::Element *E = uniform_set_format_cache.find(usformat); + RBMap<UniformSetFormat, uint32_t>::Element *E = uniform_set_format_cache.find(usformat); if (E) { format = E->get(); } else { @@ -5468,12 +5468,12 @@ RID RenderingDeviceVulkan::texture_buffer_create(uint32_t p_size_elements, DataF RenderingDeviceVulkan::DescriptorPool *RenderingDeviceVulkan::_descriptor_pool_allocate(const DescriptorPoolKey &p_key) { if (!descriptor_pools.has(p_key)) { - descriptor_pools[p_key] = Set<DescriptorPool *>(); + descriptor_pools[p_key] = RBSet<DescriptorPool *>(); } DescriptorPool *pool = nullptr; - for (Set<DescriptorPool *>::Element *E = descriptor_pools[p_key].front(); E; E = E->next()) { + for (RBSet<DescriptorPool *>::Element *E = descriptor_pools[p_key].front(); E; E = E->next()) { if (E->get()->usage < max_descriptors_per_pool) { pool = E->get(); break; @@ -8349,7 +8349,7 @@ void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) { uint32_t barrier_idx = 0; - for (Set<Texture *>::Element *E = compute_list->state.textures_to_sampled_layout.front(); E; E = E->next()) { + for (RBSet<Texture *>::Element *E = compute_list->state.textures_to_sampled_layout.front(); E; E = E->next()) { VkImageMemoryBarrier &image_memory_barrier = image_barriers[barrier_idx++]; image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; image_memory_barrier.pNext = nullptr; @@ -9477,21 +9477,21 @@ void RenderingDeviceVulkan::finalize() { vmaDestroyBuffer(allocator, staging_buffer_blocks[i].buffer, staging_buffer_blocks[i].allocation); } while (small_allocs_pools.size()) { - Map<uint32_t, VmaPool>::Element *E = small_allocs_pools.front(); - vmaDestroyPool(allocator, E->get()); - small_allocs_pools.erase(E); + HashMap<uint32_t, VmaPool>::Iterator E = small_allocs_pools.begin(); + vmaDestroyPool(allocator, E->value); + small_allocs_pools.remove(E); } vmaDestroyAllocator(allocator); while (vertex_formats.size()) { - Map<VertexFormatID, VertexDescriptionCache>::Element *temp = vertex_formats.front(); - memdelete_arr(temp->get().bindings); - memdelete_arr(temp->get().attributes); - vertex_formats.erase(temp); + HashMap<VertexFormatID, VertexDescriptionCache>::Iterator temp = vertex_formats.begin(); + memdelete_arr(temp->value.bindings); + memdelete_arr(temp->value.attributes); + vertex_formats.remove(temp); } - for (int i = 0; i < framebuffer_formats.size(); i++) { - vkDestroyRenderPass(device, framebuffer_formats[i].render_pass, nullptr); + for (KeyValue<FramebufferFormatID, FramebufferFormat> &E : framebuffer_formats) { + vkDestroyRenderPass(device, E.value.render_pass, nullptr); } framebuffer_formats.clear(); diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 236742c15d..601c44c728 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -101,8 +101,8 @@ class RenderingDeviceVulkan : public RenderingDevice { VkDevice device = VK_NULL_HANDLE; - Map<RID, Set<RID>> dependency_map; //IDs to IDs that depend on it - Map<RID, Set<RID>> reverse_dependency_map; //same as above, but in reverse + HashMap<RID, RBSet<RID>> dependency_map; //IDs to IDs that depend on it + HashMap<RID, RBSet<RID>> reverse_dependency_map; //same as above, but in reverse void _add_dependency(RID p_id, RID p_depends_on); void _free_dependencies(RID p_id); @@ -349,15 +349,15 @@ class RenderingDeviceVulkan : public RenderingDevice { VkRenderPass _render_pass_create(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, InitialAction p_initial_action, FinalAction p_final_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, uint32_t p_view_count = 1, Vector<TextureSamples> *r_samples = nullptr); // This is a cache and it's never freed, it ensures // IDs for a given format are always unique. - Map<FramebufferFormatKey, FramebufferFormatID> framebuffer_format_cache; + RBMap<FramebufferFormatKey, FramebufferFormatID> framebuffer_format_cache; struct FramebufferFormat { - const Map<FramebufferFormatKey, FramebufferFormatID>::Element *E; + const RBMap<FramebufferFormatKey, FramebufferFormatID>::Element *E; VkRenderPass render_pass = VK_NULL_HANDLE; //here for constructing shaders, never used, see section (7.2. Render Pass Compatibility from Vulkan spec) Vector<TextureSamples> pass_samples; uint32_t view_count = 1; // number of views }; - Map<FramebufferFormatID, FramebufferFormat> framebuffer_formats; + HashMap<FramebufferFormatID, FramebufferFormat> framebuffer_formats; struct Framebuffer { FramebufferFormatID format_id = 0; @@ -398,7 +398,7 @@ class RenderingDeviceVulkan : public RenderingDevice { uint32_t subpass_count = 1; }; - Map<VersionKey, Version> framebuffers; + RBMap<VersionKey, Version> framebuffers; Size2 size; uint32_t view_count; }; @@ -488,7 +488,7 @@ class RenderingDeviceVulkan : public RenderingDevice { VkPipelineVertexInputStateCreateInfo create_info; }; - Map<VertexFormatID, VertexDescriptionCache> vertex_formats; + HashMap<VertexFormatID, VertexDescriptionCache> vertex_formats; struct VertexArray { RID buffer; @@ -592,7 +592,7 @@ class RenderingDeviceVulkan : public RenderingDevice { // Always grows, never shrinks, ensuring unique IDs, but we assume // the amount of formats will never be a problem, as the amount of shaders // in a game is limited. - Map<UniformSetFormat, uint32_t> uniform_set_format_cache; + RBMap<UniformSetFormat, uint32_t> uniform_set_format_cache; // Shaders in Vulkan are just pretty much // precompiled blocks of SPIR-V bytecode. They @@ -702,7 +702,7 @@ class RenderingDeviceVulkan : public RenderingDevice { uint32_t usage; }; - Map<DescriptorPoolKey, Set<DescriptorPool *>> descriptor_pools; + RBMap<DescriptorPoolKey, RBSet<DescriptorPool *>> descriptor_pools; uint32_t max_descriptors_per_pool = 0; DescriptorPool *_descriptor_pool_allocate(const DescriptorPoolKey &p_key); @@ -923,7 +923,7 @@ class RenderingDeviceVulkan : public RenderingDevice { }; struct State { - Set<Texture *> textures_to_sampled_layout; + RBSet<Texture *> textures_to_sampled_layout; SetState sets[MAX_UNIFORM_SETS]; uint32_t set_count = 0; RID pipeline; @@ -1016,7 +1016,7 @@ class RenderingDeviceVulkan : public RenderingDevice { void _free_pending_resources(int p_frame); VmaAllocator allocator = nullptr; - Map<uint32_t, VmaPool> small_allocs_pools; + HashMap<uint32_t, VmaPool> small_allocs_pools; VmaPool _find_or_create_small_allocs_pool(uint32_t p_mem_type_index); VulkanContext *context = nullptr; diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index 6858eb7524..236e3bf35f 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/drivers/vulkan/vulkan_context.h @@ -34,7 +34,7 @@ #include "core/error/error_list.h" #include "core/os/mutex.h" #include "core/string/ustring.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/templates/rid_owner.h" #include "servers/display_server.h" #include "servers/rendering/rendering_device.h" @@ -161,7 +161,7 @@ private: RID_Owner<LocalDevice, true> local_device_owner; - Map<DisplayServer::WindowID, Window> windows; + HashMap<DisplayServer::WindowID, Window> windows; uint32_t swapchainImageCount = 0; // Commands. diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 9c8fec26a7..ff8b72274c 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -62,7 +62,7 @@ void AnimationBezierTrackEdit::_draw_track(int p_track, const Color &p_color) { int right_limit = get_size().width; //selection may have altered the order of keys - Map<float, int> key_order; + RBMap<float, int> key_order; for (int i = 0; i < animation->track_get_key_count(p_track); i++) { float ofs = animation->track_get_key_time(p_track, i); @@ -73,7 +73,7 @@ void AnimationBezierTrackEdit::_draw_track(int p_track, const Color &p_color) { key_order[ofs] = i; } - for (Map<float, int>::Element *E = key_order.front(); E; E = E->next()) { + for (RBMap<float, int>::Element *E = key_order.front(); E; E = E->next()) { int i = E->get(); if (!E->next()) { @@ -262,12 +262,12 @@ void AnimationBezierTrackEdit::_notification(int p_what) { int vofs = vsep; int margin = 0; - Map<int, Color> subtrack_colors; + RBMap<int, Color> subtrack_colors; Color selected_track_color; subtracks.clear(); subtrack_icons.clear(); - Map<String, Vector<int>> track_indices; + RBMap<String, Vector<int>> track_indices; int track_count = animation->get_track_count(); for (int i = 0; i < track_count; ++i) { if (animation->track_get_type(i) != Animation::TrackType::TYPE_BEZIER) { @@ -432,7 +432,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { Rect2 solo_rect = Rect2(solo_hpos, icon_start_height - solo->get_height() / 2, solo->get_width(), solo->get_height()); draw_texture(solo, solo_rect.position); - Map<int, Rect2> track_icons; + RBMap<int, Rect2> track_icons; track_icons[REMOVE_ICON] = remove_rect; track_icons[LOCK_ICON] = lock_rect; track_icons[VISIBILITY_ICON] = visible_rect; @@ -747,7 +747,7 @@ void AnimationBezierTrackEdit::_update_locked_tracks_after(int p_track) { } Vector<int> updated_locked_tracks; - for (Set<int>::Element *E = locked_tracks.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = locked_tracks.front(); E; E = E->next()) { updated_locked_tracks.push_back(E->get()); } locked_tracks.clear(); @@ -766,7 +766,7 @@ void AnimationBezierTrackEdit::_update_hidden_tracks_after(int p_track) { } Vector<int> updated_hidden_tracks; - for (Set<int>::Element *E = hidden_tracks.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = hidden_tracks.front(); E; E = E->next()) { updated_hidden_tracks.push_back(E->get()); } hidden_tracks.clear(); @@ -963,9 +963,9 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } } - for (const KeyValue<int, Map<int, Rect2>> &E : subtrack_icons) { + for (const KeyValue<int, RBMap<int, Rect2>> &E : subtrack_icons) { int track = E.key; - Map<int, Rect2> track_icons = E.value; + RBMap<int, Rect2> track_icons = E.value; for (const KeyValue<int, Rect2> &I : track_icons) { if (I.value.has_point(mb->get_position())) { if (I.key == REMOVE_ICON) { diff --git a/editor/animation_bezier_editor.h b/editor/animation_bezier_editor.h index f228f66771..cbbc3cc32a 100644 --- a/editor/animation_bezier_editor.h +++ b/editor/animation_bezier_editor.h @@ -61,7 +61,7 @@ class AnimationBezierTrackEdit : public Control { Ref<Texture2D> bezier_handle_icon; Ref<Texture2D> selected_icon; - Map<int, Rect2> subtracks; + RBMap<int, Rect2> subtracks; enum { REMOVE_ICON, @@ -70,9 +70,9 @@ class AnimationBezierTrackEdit : public Control { VISIBILITY_ICON }; - Map<int, Map<int, Rect2>> subtrack_icons; - Set<int> locked_tracks; - Set<int> hidden_tracks; + RBMap<int, RBMap<int, Rect2>> subtrack_icons; + RBSet<int> locked_tracks; + RBSet<int> hidden_tracks; int solo_track = -1; bool is_filtered = false; @@ -152,7 +152,7 @@ class AnimationBezierTrackEdit : public Control { } }; - typedef Set<IntPair, SelectionCompare> SelectionSet; + typedef RBSet<IntPair, SelectionCompare> SelectionSet; SelectionSet selection; diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index c425613262..7d8197bead 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1353,8 +1353,8 @@ public: Ref<Animation> animation; - Map<int, List<float>> key_ofs_map; - Map<int, NodePath> base_map; + RBMap<int, List<float>> key_ofs_map; + RBMap<int, NodePath> base_map; PropertyInfo hint; Node *root_path = nullptr; @@ -3421,7 +3421,7 @@ Ref<Animation> AnimationTrackEditor::get_current_animation() const { return animation; } -void AnimationTrackEditor::_root_removed(Node *p_root) { +void AnimationTrackEditor::_root_removed() { root = nullptr; } @@ -4382,7 +4382,7 @@ void AnimationTrackEditor::_update_tracks() { return; } - Map<String, VBoxContainer *> group_sort; + RBMap<String, VBoxContainer *> group_sort; bool use_grouping = !view_group->is_pressed(); bool use_filter = selected_filter->is_pressed(); @@ -5199,8 +5199,8 @@ void AnimationTrackEditor::_update_key_edit() { multi_key_edit = memnew(AnimationMultiTrackKeyEdit); multi_key_edit->animation = animation; - Map<int, List<float>> key_ofs_map; - Map<int, NodePath> base_map; + RBMap<int, List<float>> key_ofs_map; + RBMap<int, NodePath> base_map; int first_track = -1; for (const KeyValue<SelectedKey, KeyInfo> &E : selection) { int track = E.key.track; @@ -5261,11 +5261,11 @@ void AnimationTrackEditor::_move_selection_commit() { float motion = moving_selection_offset; // 1 - remove the keys. - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->key().track, E->key().key); } // 2 - Remove overlapped keys. - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { float newtime = snap_time(E->get().pos + motion); int idx = animation->track_find_key(E->key().track, newtime, true); if (idx == -1) { @@ -5290,19 +5290,19 @@ void AnimationTrackEditor::_move_selection_commit() { } // 3 - Move the keys (Reinsert them). - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { float newpos = snap_time(E->get().pos + motion); undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->key().track, newpos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key)); } // 4 - (Undo) Remove inserted keys. - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { float newpos = snap_time(E->get().pos + motion); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newpos); } // 5 - (Undo) Reinsert keys. - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { undo_redo->add_undo_method(animation.ptr(), "track_insert_key", E->key().track, E->get().pos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key)); } @@ -5315,7 +5315,7 @@ void AnimationTrackEditor::_move_selection_commit() { undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation); // 7 - Reselect. - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { float oldpos = E->get().pos; float newpos = snap_time(oldpos + motion); @@ -5488,7 +5488,7 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) { if (selection.size() && animation.is_valid() && (!transpose || (_get_track_selected() >= 0 && _get_track_selected() < animation->get_track_count()))) { int top_track = 0x7FFFFFFF; float top_time = 1e10; - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { const SelectedKey &sk = E->key(); float t = animation->track_get_key_time(sk.track, sk.key); @@ -5509,7 +5509,7 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) { List<Pair<int, float>> new_selection_values; - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { const SelectedKey &sk = E->key(); float t = animation->track_get_key_time(sk.track, sk.key); @@ -5544,7 +5544,7 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) { // Reselect duplicated. - Map<SelectedKey, KeyInfo> new_selection; + RBMap<SelectedKey, KeyInfo> new_selection; for (const Pair<int, float> &E : new_selection_values) { int track = E.first; float time = E.second; @@ -5822,11 +5822,11 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { List<_AnimMoveRestore> to_restore; // 1 - Remove the keys. - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->key().track, E->key().key); } // 2 - Remove overlapped keys. - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { float newtime = (E->get().pos - from_t) * s + from_t; int idx = animation->track_find_key(E->key().track, newtime, true); if (idx == -1) { @@ -5852,19 +5852,19 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { #define NEW_POS(m_ofs) (((s > 0) ? m_ofs : from_t + (len - (m_ofs - from_t))) - pivot) * ABS(s) + from_t // 3 - Move the keys (re insert them). - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { float newpos = NEW_POS(E->get().pos); undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->key().track, newpos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key)); } // 4 - (Undo) Remove inserted keys. - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { float newpos = NEW_POS(E->get().pos); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newpos); } // 5 - (Undo) Reinsert keys. - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { undo_redo->add_undo_method(animation.ptr(), "track_insert_key", E->key().track, E->get().pos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key)); } @@ -5877,7 +5877,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation); // 7-reselect. - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { float oldpos = E->get().pos; float newpos = NEW_POS(oldpos); if (newpos >= 0) { @@ -5906,7 +5906,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { undo_redo->create_action(TTR("Anim Add RESET Keys")); Ref<Animation> reset = _create_and_get_reset_animation(); int reset_tracks = reset->get_track_count(); - Set<int> tracks_added; + RBSet<int> tracks_added; for (const KeyValue<SelectedKey, KeyInfo> &E : selection) { const SelectedKey &sk = E.key; @@ -5960,7 +5960,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { if (selection.size()) { undo_redo->create_action(TTR("Anim Delete Keys")); - for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { + for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->key().track, E->key().key); undo_redo->add_undo_method(animation.ptr(), "track_insert_key", E->key().track, E->get().pos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key)); } diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index bd66a4b2df..07c3ed9990 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -378,7 +378,7 @@ class AnimationTrackEditor : public VBoxContainer { TrackIndices _confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_create_reset, Ref<Animation> p_reset_anim, bool p_create_beziers); void _insert_track(bool p_create_reset, bool p_create_beziers); - void _root_removed(Node *p_root); + void _root_removed(); PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val = nullptr); @@ -410,7 +410,7 @@ class AnimationTrackEditor : public VBoxContainer { float pos = 0; }; - Map<SelectedKey, KeyInfo> selection; + RBMap<SelectedKey, KeyInfo> selection; void _key_selected(int p_key, bool p_single, int p_track); void _key_deselected(int p_key, int p_track); diff --git a/editor/audio_stream_preview.h b/editor/audio_stream_preview.h index bcd80a7c03..307dd93b34 100644 --- a/editor/audio_stream_preview.h +++ b/editor/audio_stream_preview.h @@ -85,7 +85,7 @@ class AudioStreamPreviewGenerator : public Node { Preview() {} }; - Map<ObjectID, Preview> previews; + HashMap<ObjectID, Preview> previews; static void _preview_thread(void *p_preview); diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 5526181c13..4cff0ffd3d 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -1029,27 +1029,27 @@ void ConnectionsDock::update_tree() { String descr; bool found = false; - Map<StringName, Map<StringName, String>>::Element *G = descr_cache.find(base); + HashMap<StringName, HashMap<StringName, String>>::Iterator G = descr_cache.find(base); if (G) { - Map<StringName, String>::Element *F = G->get().find(signal_name); + HashMap<StringName, String>::Iterator F = G->value.find(signal_name); if (F) { found = true; - descr = F->get(); + descr = F->value; } } if (!found) { DocTools *dd = EditorHelp::get_doc_data(); - Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(base); + HashMap<String, DocData::ClassDoc>::Iterator F = dd->class_list.find(base); while (F && descr.is_empty()) { - for (int i = 0; i < F->get().signals.size(); i++) { - if (F->get().signals[i].name == signal_name.operator String()) { - descr = DTR(F->get().signals[i].description); + for (int i = 0; i < F->value.signals.size(); i++) { + if (F->value.signals[i].name == signal_name.operator String()) { + descr = DTR(F->value.signals[i].description); break; } } - if (!F->get().inherits.is_empty()) { - F = dd->class_list.find(F->get().inherits); + if (!F->value.inherits.is_empty()) { + F = dd->class_list.find(F->value.inherits); } else { break; } diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h index f8f15b32af..88d52c83f2 100644 --- a/editor/connections_dialog.h +++ b/editor/connections_dialog.h @@ -197,7 +197,7 @@ class ConnectionsDock : public VBoxContainer { UndoRedo *undo_redo = nullptr; LineEdit *search_box = nullptr; - Map<StringName, Map<StringName, String>> descr_cache; + HashMap<StringName, HashMap<StringName, String>> descr_cache; void _filter_changed(const String &p_text); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index fbb61a1614..fb908ea573 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -125,7 +125,7 @@ bool CreateDialog::_should_hide_type(const String &p_type) const { return true; // Do not show editor nodes. } - if (p_type == base_type) { + if (p_type == base_type && !EditorNode::get_editor_data().get_custom_types().has(p_type)) { return true; // Root is already added. } @@ -138,7 +138,7 @@ bool CreateDialog::_should_hide_type(const String &p_type) const { return true; // Wrong inheritance. } - for (Set<StringName>::Element *E = type_blacklist.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = type_blacklist.front(); E; E = E->next()) { if (ClassDB::is_parent_class(p_type, E->get())) { return true; // Parent type is blacklisted. } diff --git a/editor/create_dialog.h b/editor/create_dialog.h index 31761be6fe..6526116b09 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -64,7 +64,7 @@ class CreateDialog : public ConfirmationDialog { HashMap<String, String> custom_type_parents; HashMap<String, int> custom_type_indices; List<StringName> type_list; - Set<StringName> type_blacklist; + RBSet<StringName> type_blacklist; void _update_search(); bool _should_hide_type(const String &p_type) const; diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.cpp b/editor/debugger/debug_adapter/debug_adapter_parser.cpp index e7baeeeded..0caeb90108 100644 --- a/editor/debugger/debug_adapter/debug_adapter_parser.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_parser.cpp @@ -381,12 +381,12 @@ Dictionary DebugAdapterParser::req_scopes(const Dictionary &p_params) const { DAP::StackFrame frame; frame.id = frame_id; - Map<DAP::StackFrame, List<int>>::Element *E = DebugAdapterProtocol::get_singleton()->stackframe_list.find(frame); + HashMap<DAP::StackFrame, List<int>, DAP::StackFrame>::Iterator E = DebugAdapterProtocol::get_singleton()->stackframe_list.find(frame); if (E) { - ERR_FAIL_COND_V(E->value().size() != 3, prepare_error_response(p_params, DAP::ErrorType::UNKNOWN)); + ERR_FAIL_COND_V(E->value.size() != 3, prepare_error_response(p_params, DAP::ErrorType::UNKNOWN)); for (int i = 0; i < 3; i++) { DAP::Scope scope; - scope.variablesReference = E->value()[i]; + scope.variablesReference = E->value[i]; switch (i) { case 0: scope.name = "Locals"; @@ -424,16 +424,16 @@ Dictionary DebugAdapterParser::req_variables(const Dictionary &p_params) const { Dictionary args = p_params["arguments"]; int variable_id = args["variablesReference"]; - Map<int, Array>::Element *E = DebugAdapterProtocol::get_singleton()->variable_list.find(variable_id); + HashMap<int, Array>::Iterator E = DebugAdapterProtocol::get_singleton()->variable_list.find(variable_id); if (E) { if (!DebugAdapterProtocol::get_singleton()->get_current_peer()->supportsVariableType) { - for (int i = 0; i < E->value().size(); i++) { - Dictionary variable = E->value()[i]; + for (int i = 0; i < E->value.size(); i++) { + Dictionary variable = E->value[i]; variable.erase("type"); } } - body["variables"] = E ? E->value() : Array(); + body["variables"] = E ? E->value : Array(); return response; } else { return Dictionary(); diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp index fea4c2b156..92ea0f15e9 100644 --- a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp @@ -918,11 +918,11 @@ void DebugAdapterProtocol::on_debug_stack_frame_vars(const int &p_size) { DAP::StackFrame frame; frame.id = _current_frame; ERR_FAIL_COND(!stackframe_list.has(frame)); - List<int> scope_ids = stackframe_list.find(frame)->value(); + List<int> scope_ids = stackframe_list.find(frame)->value; for (List<int>::Element *E = scope_ids.front(); E; E = E->next()) { int variable_id = E->get(); if (variable_list.has(variable_id)) { - variable_list.find(variable_id)->value().clear(); + variable_list.find(variable_id)->value.clear(); } else { variable_list.insert(variable_id, Array()); } @@ -937,7 +937,7 @@ void DebugAdapterProtocol::on_debug_stack_frame_var(const Array &p_data) { DAP::StackFrame frame; frame.id = _current_frame; - List<int> scope_ids = stackframe_list.find(frame)->value(); + List<int> scope_ids = stackframe_list.find(frame)->value; ERR_FAIL_COND(scope_ids.size() != 3); ERR_FAIL_INDEX(stack_var.type, 3); int variable_id = scope_ids[stack_var.type]; @@ -949,7 +949,7 @@ void DebugAdapterProtocol::on_debug_stack_frame_var(const Array &p_data) { variable.type = Variant::get_type_name(stack_var.value.get_type()); variable.variablesReference = parse_variant(stack_var.value); - variable_list.find(variable_id)->value().push_back(variable.to_json()); + variable_list.find(variable_id)->value.push_back(variable.to_json()); _remaining_vars--; } diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.h b/editor/debugger/debug_adapter/debug_adapter_protocol.h index 66db75c634..a17e550dfc 100644 --- a/editor/debugger/debug_adapter/debug_adapter_protocol.h +++ b/editor/debugger/debug_adapter/debug_adapter_protocol.h @@ -115,8 +115,8 @@ private: int stackframe_id = 0; int variable_id = 0; List<DAP::Breakpoint> breakpoint_list; - Map<DAP::StackFrame, List<int>> stackframe_list; - Map<int, Array> variable_list; + HashMap<DAP::StackFrame, List<int>, DAP::StackFrame> stackframe_list; + HashMap<int, Array> variable_list; public: friend class DebugAdapterServer; diff --git a/editor/debugger/debug_adapter/debug_adapter_types.h b/editor/debugger/debug_adapter/debug_adapter_types.h index 77b70909b3..4d77b6d51c 100644 --- a/editor/debugger/debug_adapter/debug_adapter_types.h +++ b/editor/debugger/debug_adapter/debug_adapter_types.h @@ -219,8 +219,11 @@ struct StackFrame { int line; int column; - bool operator<(const StackFrame &p_other) const { - return id < p_other.id; + static uint32_t hash(const StackFrame &p_frame) { + return hash_djb2_one_32(p_frame.id); + } + bool operator==(const StackFrame &p_other) const { + return id == p_other.id; } _FORCE_INLINE_ void from_json(const Dictionary &p_params) { diff --git a/editor/debugger/editor_debugger_inspector.cpp b/editor/debugger/editor_debugger_inspector.cpp index 854c050793..6d7f3f4ae2 100644 --- a/editor/debugger/editor_debugger_inspector.cpp +++ b/editor/debugger/editor_debugger_inspector.cpp @@ -146,7 +146,7 @@ ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) { debugObj->prop_list.clear(); int new_props_added = 0; - Set<String> changed; + RBSet<String> changed; for (int i = 0; i < obj.properties.size(); i++) { PropertyInfo &pinfo = obj.properties[i].first; Variant &var = obj.properties[i].second; @@ -193,7 +193,7 @@ ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) { if (old_prop_size == debugObj->prop_list.size() && new_props_added == 0) { //only some may have changed, if so, then update those, if exist - for (Set<String>::Element *E = changed.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = changed.front(); E; E = E->next()) { emit_signal(SNAME("object_property_updated"), debugObj->remote_object_id, E->get()); } } else { @@ -276,8 +276,8 @@ void EditorDebuggerInspector::clear_stack_variables() { } String EditorDebuggerInspector::get_stack_variable(const String &p_var) { - for (Map<StringName, Variant>::Element *E = variables->prop_values.front(); E; E = E->next()) { - String v = E->key().operator String(); + for (KeyValue<StringName, Variant> &E : variables->prop_values) { + String v = E.key.operator String(); if (v.get_slice("/", 1) == p_var) { return variables->get_variant(v); } diff --git a/editor/debugger/editor_debugger_inspector.h b/editor/debugger/editor_debugger_inspector.h index 2bf5bf3419..72b259c8b5 100644 --- a/editor/debugger/editor_debugger_inspector.h +++ b/editor/debugger/editor_debugger_inspector.h @@ -46,7 +46,7 @@ public: ObjectID remote_object_id; String type_name; List<PropertyInfo> prop_list; - Map<StringName, Variant> prop_values; + HashMap<StringName, Variant> prop_values; ObjectID get_remote_object_id() { return remote_object_id; }; String get_title(); @@ -68,8 +68,8 @@ class EditorDebuggerInspector : public EditorInspector { private: ObjectID inspected_object_id; - Map<ObjectID, EditorDebuggerRemoteObject *> remote_objects; - Set<Ref<Resource>> remote_dependencies; + HashMap<ObjectID, EditorDebuggerRemoteObject *> remote_objects; + RBSet<Ref<Resource>> remote_dependencies; EditorDebuggerRemoteObject *variables = nullptr; void _object_selected(ObjectID p_object); diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index c0685af572..de26b56ab6 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -118,7 +118,7 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() { } if (!debugger_plugins.is_empty()) { - for (Set<Ref<Script>>::Element *i = debugger_plugins.front(); i; i = i->next()) { + for (RBSet<Ref<Script>>::Element *i = debugger_plugins.front(); i; i = i->next()) { node->add_debugger_plugin(i->get()); } } diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h index b4fbb90301..40e9cf47f9 100644 --- a/editor/debugger/editor_debugger_node.h +++ b/editor/debugger/editor_debugger_node.h @@ -70,6 +70,14 @@ private: String source; int line = 0; + static uint32_t hash(const Breakpoint &p_val) { + uint32_t h = HashMapHasherDefault::hash(p_val.source); + return hash_djb2_one_32(p_val.line, h); + } + bool operator==(const Breakpoint &p_b) const { + return (line == p_b.line && source == p_b.source); + } + bool operator<(const Breakpoint &p_b) const { if (line == p_b.line) { return source < p_b.source; @@ -102,9 +110,9 @@ private: bool debug_with_external_editor = false; bool hide_on_stop = true; CameraOverride camera_override = OVERRIDE_NONE; - Map<Breakpoint, bool> breakpoints; + HashMap<Breakpoint, bool, Breakpoint> breakpoints; - Set<Ref<Script>> debugger_plugins; + RBSet<Ref<Script>> debugger_plugins; ScriptEditorDebugger *_add_debugger(); EditorDebuggerRemoteObject *get_inspected_remote_object(); diff --git a/editor/debugger/editor_debugger_server.cpp b/editor/debugger/editor_debugger_server.cpp index bce131a5fe..63390825c6 100644 --- a/editor/debugger/editor_debugger_server.cpp +++ b/editor/debugger/editor_debugger_server.cpp @@ -122,7 +122,7 @@ Ref<RemoteDebuggerPeer> EditorDebuggerServerTCP::take_connection() { } /// EditorDebuggerServer -Map<StringName, EditorDebuggerServer::CreateServerFunc> EditorDebuggerServer::protocols; +HashMap<StringName, EditorDebuggerServer::CreateServerFunc> EditorDebuggerServer::protocols; EditorDebuggerServer *EditorDebuggerServer::create(const String &p_protocol) { ERR_FAIL_COND_V(!protocols.has(p_protocol), nullptr); diff --git a/editor/debugger/editor_debugger_server.h b/editor/debugger/editor_debugger_server.h index bda4a1ce7d..adf9a27c71 100644 --- a/editor/debugger/editor_debugger_server.h +++ b/editor/debugger/editor_debugger_server.h @@ -39,7 +39,7 @@ public: typedef EditorDebuggerServer *(*CreateServerFunc)(const String &p_uri); private: - static Map<StringName, CreateServerFunc> protocols; + static HashMap<StringName, CreateServerFunc> protocols; public: static void initialize(); diff --git a/editor/debugger/editor_debugger_tree.h b/editor/debugger/editor_debugger_tree.h index 58af52b01f..8ba03367c9 100644 --- a/editor/debugger/editor_debugger_tree.h +++ b/editor/debugger/editor_debugger_tree.h @@ -48,7 +48,7 @@ private: ObjectID inspected_object_id; int debugger_id = 0; bool updating_scene_tree = false; - Set<ObjectID> unfold_cache; + RBSet<ObjectID> unfold_cache; PopupMenu *item_menu = nullptr; EditorFileDialog *file_dialog = nullptr; String last_filter; diff --git a/editor/debugger/editor_network_profiler.h b/editor/debugger/editor_network_profiler.h index 3a604f5564..d2e70a083d 100644 --- a/editor/debugger/editor_network_profiler.h +++ b/editor/debugger/editor_network_profiler.h @@ -50,7 +50,7 @@ private: Timer *frame_delay = nullptr; - Map<ObjectID, SceneDebugger::RPCNodeInfo> nodes_data; + HashMap<ObjectID, SceneDebugger::RPCNodeInfo> nodes_data; void _update_frame(); diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp index c821561ca6..897c5ae7da 100644 --- a/editor/debugger/editor_performance_profiler.cpp +++ b/editor/debugger/editor_performance_profiler.cpp @@ -97,9 +97,9 @@ void EditorPerformanceProfiler::_monitor_select() { void EditorPerformanceProfiler::_monitor_draw() { Vector<StringName> active; - for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { - if (i.value().item->is_checked(0)) { - active.push_back(i.key()); + for (const KeyValue<StringName, Monitor> &E : monitors) { + if (E.value.item->is_checked(0)) { + active.push_back(E.key); } } @@ -203,23 +203,23 @@ void EditorPerformanceProfiler::_monitor_draw() { } void EditorPerformanceProfiler::_build_monitor_tree() { - Set<StringName> monitor_checked; - for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { - if (i.value().item && i.value().item->is_checked(0)) { - monitor_checked.insert(i.key()); + RBSet<StringName> monitor_checked; + for (KeyValue<StringName, Monitor> &E : monitors) { + if (E.value.item && E.value.item->is_checked(0)) { + monitor_checked.insert(E.key); } } base_map.clear(); monitor_tree->get_root()->clear_children(); - for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { - TreeItem *base = _get_monitor_base(i.value().base); - TreeItem *item = _create_monitor_item(i.value().name, base); - item->set_checked(0, monitor_checked.has(i.key())); - i.value().item = item; - if (!i.value().history.is_empty()) { - i.value().update_value(i.value().history.front()->get()); + for (KeyValue<StringName, Monitor> &E : monitors) { + TreeItem *base = _get_monitor_base(E.value.base); + TreeItem *item = _create_monitor_item(E.value.name, base); + item->set_checked(0, monitor_checked.has(E.key)); + E.value.item = item; + if (!E.value.history.is_empty()) { + E.value.update_value(E.value.history.front()->get()); } } } @@ -252,9 +252,9 @@ void EditorPerformanceProfiler::_marker_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { Vector<StringName> active; - for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { - if (i.value().item->is_checked(0)) { - active.push_back(i.key()); + for (KeyValue<StringName, Monitor> &E : monitors) { + if (E.value.item->is_checked(0)) { + active.push_back(E.key); } } if (active.size() > 0) { @@ -293,12 +293,16 @@ void EditorPerformanceProfiler::_marker_input(const Ref<InputEvent> &p_event) { } void EditorPerformanceProfiler::reset() { - for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { - if (String(i.key()).begins_with("custom:")) { - monitors.erase(i); + HashMap<StringName, Monitor>::Iterator E = monitors.begin(); + while (E != monitors.end()) { + HashMap<StringName, Monitor>::Iterator N = E; + ++N; + if (String(E->key).begins_with("custom:")) { + monitors.remove(E); } else { - i.value().reset(); + E->value.reset(); } + E = N; } _build_monitor_tree(); @@ -308,43 +312,49 @@ void EditorPerformanceProfiler::reset() { } void EditorPerformanceProfiler::update_monitors(const Vector<StringName> &p_names) { - OrderedHashMap<StringName, int> names; + HashMap<StringName, int> names; for (int i = 0; i < p_names.size(); i++) { names.insert("custom:" + p_names[i], Performance::MONITOR_MAX + i); } - for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { - if (String(i.key()).begins_with("custom:")) { - if (!names.has(i.key())) { - monitors.erase(i); - } else { - i.value().frame_index = names[i.key()]; - names.erase(i.key()); + { + HashMap<StringName, Monitor>::Iterator E = monitors.begin(); + while (E != monitors.end()) { + HashMap<StringName, Monitor>::Iterator N = E; + ++N; + if (String(E->key).begins_with("custom:")) { + if (!names.has(E->key)) { + monitors.remove(E); + } else { + E->value.frame_index = names[E->key]; + names.erase(E->key); + } } + E = N; } } - for (OrderedHashMap<StringName, int>::Element i = names.front(); i; i = i.next()) { - String name = String(i.key()).replace_first("custom:", ""); + for (const KeyValue<StringName, int> &E : names) { + String name = String(E.key).replace_first("custom:", ""); String base = "Custom"; if (name.get_slice_count("/") == 2) { base = name.get_slicec('/', 0); name = name.get_slicec('/', 1); } - monitors.insert(i.key(), Monitor(name, base, i.value(), Performance::MONITOR_TYPE_QUANTITY, nullptr)); + monitors.insert(E.key, Monitor(name, base, E.value, Performance::MONITOR_TYPE_QUANTITY, nullptr)); } _build_monitor_tree(); } void EditorPerformanceProfiler::add_profile_frame(const Vector<float> &p_values) { - for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + for (KeyValue<StringName, Monitor> &E : monitors) { float data = 0.0f; - if (i.value().frame_index >= 0 && i.value().frame_index < p_values.size()) { - data = p_values[i.value().frame_index]; + if (E.value.frame_index >= 0 && E.value.frame_index < p_values.size()) { + data = p_values[E.value.frame_index]; } - i.value().history.push_front(data); - i.value().update_value(data); + E.value.history.push_front(data); + E.value.update_value(data); } marker_frame++; monitor_draw->update(); diff --git a/editor/debugger/editor_performance_profiler.h b/editor/debugger/editor_performance_profiler.h index ab0e43de2f..607de5a134 100644 --- a/editor/debugger/editor_performance_profiler.h +++ b/editor/debugger/editor_performance_profiler.h @@ -31,8 +31,8 @@ #ifndef EDITOR_PERFORMANCE_PROFILER_H #define EDITOR_PERFORMANCE_PROFILER_H -#include "core/templates/map.h" -#include "core/templates/ordered_hash_map.h" +#include "core/templates/hash_map.h" +#include "core/templates/rb_map.h" #include "main/performance.h" #include "scene/gui/control.h" #include "scene/gui/label.h" @@ -59,9 +59,9 @@ private: void reset(); }; - OrderedHashMap<StringName, Monitor> monitors; + HashMap<StringName, Monitor> monitors; - Map<StringName, TreeItem *> base_map; + HashMap<StringName, TreeItem *> base_map; Tree *monitor_tree = nullptr; Control *monitor_draw = nullptr; Label *info_message = nullptr; diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index 50f3b19cc2..55c3c7af78 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -198,18 +198,18 @@ void EditorProfiler::_update_plot() { for (int i = 0; i < total_metrics; i++) { const Metric &m = _get_frame_metric(i); - for (Set<StringName>::Element *E = plot_sigs.front(); E; E = E->next()) { - const Map<StringName, Metric::Category *>::Element *F = m.category_ptrs.find(E->get()); + for (RBSet<StringName>::Element *E = plot_sigs.front(); E; E = E->next()) { + HashMap<StringName, Metric::Category *>::ConstIterator F = m.category_ptrs.find(E->get()); if (F) { - highest = MAX(F->get()->total_time, highest); + highest = MAX(F->value->total_time, highest); } - const Map<StringName, Metric::Category::Item *>::Element *G = m.item_ptrs.find(E->get()); + HashMap<StringName, Metric::Category::Item *>::ConstIterator G = m.item_ptrs.find(E->get()); if (G) { if (use_self) { - highest = MAX(G->get()->self, highest); + highest = MAX(G->value->self, highest); } else { - highest = MAX(G->get()->total, highest); + highest = MAX(G->value->total, highest); } } } @@ -225,7 +225,7 @@ void EditorProfiler::_update_plot() { int *column = columnv.ptrw(); - Map<StringName, int> prev_plots; + HashMap<StringName, int> prev_plots; for (int i = 0; i < total_metrics * w / frame_metrics.size() - 1; i++) { for (int j = 0; j < h * 4; j++) { @@ -234,32 +234,32 @@ void EditorProfiler::_update_plot() { int current = i * frame_metrics.size() / w; - for (Set<StringName>::Element *E = plot_sigs.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = plot_sigs.front(); E; E = E->next()) { const Metric &m = _get_frame_metric(current); float value = 0; - const Map<StringName, Metric::Category *>::Element *F = m.category_ptrs.find(E->get()); + HashMap<StringName, Metric::Category *>::ConstIterator F = m.category_ptrs.find(E->get()); if (F) { - value = F->get()->total_time; + value = F->value->total_time; } - const Map<StringName, Metric::Category::Item *>::Element *G = m.item_ptrs.find(E->get()); + HashMap<StringName, Metric::Category::Item *>::ConstIterator G = m.item_ptrs.find(E->get()); if (G) { if (use_self) { - value = G->get()->self; + value = G->value->self; } else { - value = G->get()->total; + value = G->value->total; } } int plot_pos = CLAMP(int(value * h / highest), 0, h - 1); int prev_plot = plot_pos; - Map<StringName, int>::Element *H = prev_plots.find(E->get()); + HashMap<StringName, int>::Iterator H = prev_plots.find(E->get()); if (H) { - prev_plot = H->get(); - H->get() = plot_pos; + prev_plot = H->value; + H->value = plot_pos; } else { prev_plots[E->get()] = plot_pos; } @@ -515,7 +515,7 @@ Vector<Vector<String>> EditorProfiler::get_data_as_csv() const { } // Different metrics may contain different number of categories. - Set<StringName> possible_signatures; + RBSet<StringName> possible_signatures; for (int i = 0; i < frame_metrics.size(); i++) { const Metric &m = frame_metrics[i]; if (!m.valid) { @@ -530,11 +530,11 @@ Vector<Vector<String>> EditorProfiler::get_data_as_csv() const { } // Generate CSV header and cache indices. - Map<StringName, int> sig_map; + HashMap<StringName, int> sig_map; Vector<String> signatures; signatures.resize(possible_signatures.size()); int sig_index = 0; - for (const Set<StringName>::Element *E = possible_signatures.front(); E; E = E->next()) { + for (const RBSet<StringName>::Element *E = possible_signatures.front(); E; E = E->next()) { signatures.write[sig_index] = E->get(); sig_map[E->get()] = sig_index; sig_index++; diff --git a/editor/debugger/editor_profiler.h b/editor/debugger/editor_profiler.h index 2aef654a2f..77fbb254dc 100644 --- a/editor/debugger/editor_profiler.h +++ b/editor/debugger/editor_profiler.h @@ -73,8 +73,8 @@ public: Vector<Category> categories; - Map<StringName, Category *> category_ptrs; - Map<StringName, Category::Item *> item_ptrs; + HashMap<StringName, Category *> category_ptrs; + HashMap<StringName, Category::Item *> item_ptrs; }; enum DisplayMode { @@ -98,7 +98,7 @@ private: Tree *variables = nullptr; HSplitContainer *h_split = nullptr; - Set<StringName> plot_sigs; + RBSet<StringName> plot_sigs; OptionButton *display_mode = nullptr; OptionButton *display_time = nullptr; diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 90679657ba..44a7aade09 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -742,9 +742,9 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da bool parsed = false; const String cap = p_msg.substr(0, colon_index); - Map<StringName, Callable>::Element *element = captures.find(cap); + HashMap<StringName, Callable>::Iterator element = captures.find(cap); if (element) { - Callable &c = element->value(); + Callable &c = element->value; ERR_FAIL_COND_MSG(c.is_null(), "Invalid callable registered: " + cap); Variant cmd = p_msg.substr(colon_index + 1), data = p_data; const Variant *args[2] = { &cmd, &data }; @@ -1050,10 +1050,10 @@ int ScriptEditorDebugger::_get_node_path_cache(const NodePath &p_path) { } int ScriptEditorDebugger::_get_res_path_cache(const String &p_path) { - Map<String, int>::Element *E = res_path_cache.find(p_path); + HashMap<String, int>::Iterator E = res_path_cache.find(p_path); if (E) { - return E->get(); + return E->value; } last_path_id++; diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h index ad90e63c16..d445fe48d1 100644 --- a/editor/debugger/script_editor_debugger.h +++ b/editor/debugger/script_editor_debugger.h @@ -131,7 +131,7 @@ private: // Each debugger should have it's tree in the future I guess. const Tree *editor_remote_tree = nullptr; - Map<int, String> profiler_signature; + HashMap<int, String> profiler_signature; Tree *vmem_tree = nullptr; Button *vmem_refresh = nullptr; @@ -147,7 +147,7 @@ private: HashMap<NodePath, int> node_path_cache; int last_path_id; - Map<String, int> res_path_cache; + HashMap<String, int> res_path_cache; EditorProfiler *profiler = nullptr; EditorVisualProfiler *visual_profiler = nullptr; @@ -163,9 +163,9 @@ private: EditorDebuggerNode::CameraOverride camera_override; - Map<Ref<Script>, EditorDebuggerPlugin *> debugger_plugins; + HashMap<Ref<Script>, EditorDebuggerPlugin *> debugger_plugins; - Map<StringName, Callable> captures; + HashMap<StringName, Callable> captures; void _stack_dump_frame_selected(); diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 54655f53b5..5b5e0203a3 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -40,7 +40,7 @@ #include "scene/gui/margin_container.h" void DependencyEditor::_searched(const String &p_path) { - Map<String, String> dep_rename; + HashMap<String, String> dep_rename; dep_rename[replacing] = p_path; ResourceLoader::rename_dependencies(editing, dep_rename); @@ -64,7 +64,7 @@ void DependencyEditor::_load_pressed(Object *p_item, int p_cell, int p_button) { search->popup_file_dialog(); } -void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, Map<String, Map<String, String>> &candidates) { +void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, HashMap<String, HashMap<String, String>> &candidates) { for (int i = 0; i < efsd->get_subdir_count(); i++) { _fix_and_find(efsd->get_subdir(i), candidates); } @@ -121,12 +121,12 @@ void DependencyEditor::_fix_all() { return; } - Map<String, Map<String, String>> candidates; + HashMap<String, HashMap<String, String>> candidates; for (const String &E : missing) { String base = E.get_file(); if (!candidates.has(base)) { - candidates[base] = Map<String, String>(); + candidates[base] = HashMap<String, String>(); } candidates[base][E] = ""; @@ -134,9 +134,9 @@ void DependencyEditor::_fix_all() { _fix_and_find(EditorFileSystem::get_singleton()->get_filesystem(), candidates); - Map<String, String> remaps; + HashMap<String, String> remaps; - for (KeyValue<String, Map<String, String>> &E : candidates) { + for (KeyValue<String, HashMap<String, String>> &E : candidates) { for (const KeyValue<String, String> &F : E.value) { if (!F.value.is_empty()) { remaps[F.key] = F.value; @@ -414,7 +414,7 @@ void DependencyRemoveDialog::_build_removed_dependency_tree(const Vector<Removed owners->clear(); owners->create_item(); // root - Map<String, TreeItem *> tree_items; + HashMap<String, TreeItem *> tree_items; for (int i = 0; i < p_removed.size(); i++) { RemovedDependency rd = p_removed[i]; diff --git a/editor/dependency_editor.h b/editor/dependency_editor.h index ea86f98193..585143fe0a 100644 --- a/editor/dependency_editor.h +++ b/editor/dependency_editor.h @@ -51,7 +51,7 @@ class DependencyEditor : public AcceptDialog { String editing; List<String> missing; - void _fix_and_find(EditorFileSystemDirectory *efsd, Map<String, Map<String, String>> &candidates); + void _fix_and_find(EditorFileSystemDirectory *efsd, HashMap<String, HashMap<String, String>> &candidates); void _searched(const String &p_path); void _load_pressed(Object *p_item, int p_cell, int p_button); @@ -98,7 +98,7 @@ class DependencyRemoveDialog : public ConfirmationDialog { Label *text = nullptr; Tree *owners = nullptr; - Map<String, String> all_remove_files; + HashMap<String, String> all_remove_files; Vector<String> dirs_to_delete; Vector<String> files_to_delete; diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index 16cbc0f34d..65216d7664 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -331,7 +331,7 @@ void DocTools::generate(bool p_basic_types) { bool skip_setter_getter_methods = true; while (classes.size()) { - Set<StringName> setters_getters; + RBSet<StringName> setters_getters; String name = classes.front()->get(); if (!ClassDB::is_class_exposed(name)) { @@ -1337,7 +1337,7 @@ static void _write_method_doc(Ref<FileAccess> f, const String &p_name, Vector<Do } } -Error DocTools::save_classes(const String &p_default_path, const Map<String, String> &p_class_path) { +Error DocTools::save_classes(const String &p_default_path, const HashMap<String, String> &p_class_path) { for (KeyValue<String, DocData::ClassDoc> &E : class_list) { DocData::ClassDoc &c = E.value; diff --git a/editor/doc_tools.h b/editor/doc_tools.h index 6c3a93de59..843cdf87a6 100644 --- a/editor/doc_tools.h +++ b/editor/doc_tools.h @@ -36,7 +36,7 @@ class DocTools { public: String version; - Map<String, DocData::ClassDoc> class_list; + HashMap<String, DocData::ClassDoc> class_list; static Error erase_classes(const String &p_dir); @@ -47,7 +47,7 @@ public: bool has_doc(const String &p_class_name); void generate(bool p_basic_types = false); Error load_classes(const String &p_dir); - Error save_classes(const String &p_default_path, const Map<String, String> &p_class_path); + Error save_classes(const String &p_default_path, const HashMap<String, String> &p_class_path); Error _load(Ref<XMLParser> parser); Error load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size); diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index 7dcb9a4088..93b155bcd2 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -62,9 +62,10 @@ void EditorAssetInstaller::_check_propagated_to_item(Object *p_obj, int column) void EditorAssetInstaller::open(const String &p_path, int p_depth) { package_path = p_path; - Set<String> files_sorted; + RBSet<String> files_sorted; - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); unzFile pkg = unzOpen2(p_path.utf8().get_data(), &io); if (!pkg) { @@ -86,7 +87,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { ret = unzGoToNextFile(pkg); } - Map<String, Ref<Texture2D>> extension_guess; + HashMap<String, Ref<Texture2D>> extension_guess; { extension_guess["bmp"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")); extension_guess["dds"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")); @@ -149,11 +150,11 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { root->set_icon(0, tree->get_theme_icon(SNAME("folder"), SNAME("FileDialog"))); root->set_text(0, "res://"); root->set_editable(0, true); - Map<String, TreeItem *> dir_map; + HashMap<String, TreeItem *> dir_map; int num_file_conflicts = 0; - for (Set<String>::Element *E = files_sorted.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = files_sorted.front(); E; E = E->next()) { String path = E->get(); int depth = p_depth; bool skip = false; @@ -237,7 +238,8 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { } void EditorAssetInstaller::ok_pressed() { - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); unzFile pkg = unzOpen2(package_path.utf8().get_data(), &io); if (!pkg) { diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h index deb320e7fa..c44f4c5d22 100644 --- a/editor/editor_asset_installer.h +++ b/editor/editor_asset_installer.h @@ -41,7 +41,7 @@ class EditorAssetInstaller : public ConfirmationDialog { String package_path; String asset_name; AcceptDialog *error = nullptr; - Map<String, TreeItem *> status_map; + HashMap<String, TreeItem *> status_map; bool updating = false; void _item_edited(); void _check_propagated_to_item(Object *p_obj, int column); diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 3b38ff9163..4c73e36269 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -428,7 +428,7 @@ void EditorAutoloadSettings::update_autoload() { updating_autoload = true; - Map<String, AutoloadInfo> to_remove; + HashMap<String, AutoloadInfo> to_remove; List<AutoloadInfo *> to_add; for (const AutoloadInfo &info : autoload_cache) { diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp index d13d1a6c68..e3cbd8ad50 100644 --- a/editor/editor_command_palette.cpp +++ b/editor/editor_command_palette.cpp @@ -57,20 +57,19 @@ float EditorCommandPalette::_score_path(const String &p_search, const String &p_ } void EditorCommandPalette::_update_command_search(const String &search_text) { - commands.get_key_list(&command_keys); - ERR_FAIL_COND(command_keys.is_empty()); + ERR_FAIL_COND(commands.size() == 0); - Map<String, TreeItem *> sections; + HashMap<String, TreeItem *> sections; TreeItem *first_section = nullptr; // Filter possible candidates. Vector<CommandEntry> entries; - for (int i = 0; i < command_keys.size(); i++) { + for (const KeyValue<String, Command> &E : commands) { CommandEntry r; - r.key_name = command_keys[i]; - r.display_name = commands[r.key_name].name; - r.shortcut_text = commands[r.key_name].shortcut; - r.last_used = commands[r.key_name].last_used; + r.key_name = E.key; + r.display_name = E.value.name; + r.shortcut_text = E.value.shortcut; + r.last_used = E.value.last_used; if (search_text.is_subsequence_ofn(r.display_name)) { if (!search_text.is_empty()) { @@ -180,7 +179,9 @@ void EditorCommandPalette::open_popup() { } void EditorCommandPalette::get_actions_list(List<String> *p_list) const { - commands.get_key_list(p_list); + for (const KeyValue<String, Command> &E : commands) { + p_list->push_back(E.key); + } } void EditorCommandPalette::remove_command(String p_key_name) { @@ -229,17 +230,14 @@ void EditorCommandPalette::execute_command(String &p_command_key) { } void EditorCommandPalette::register_shortcuts_as_command() { - const String *key = nullptr; - key = unregistered_shortcuts.next(key); - while (key != nullptr) { - String command_name = unregistered_shortcuts[*key].first; - Ref<Shortcut> shortcut = unregistered_shortcuts[*key].second; + for (const KeyValue<String, Pair<String, Ref<Shortcut>>> &E : unregistered_shortcuts) { + String command_name = E.value.first; + Ref<Shortcut> shortcut = E.value.second; Ref<InputEventShortcut> ev; ev.instantiate(); ev->set_shortcut(shortcut); String shortcut_text = String(shortcut->get_as_text()); - add_command(command_name, *key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::push_unhandled_input), varray(ev, false), shortcut_text); - key = unregistered_shortcuts.next(key); + add_command(command_name, E.key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::push_unhandled_input), varray(ev, false), shortcut_text); } unregistered_shortcuts.clear(); @@ -276,12 +274,10 @@ void EditorCommandPalette::_theme_changed() { void EditorCommandPalette::_save_history() const { Dictionary command_history; - List<String> command_keys; - commands.get_key_list(&command_keys); - for (const String &key : command_keys) { - if (commands[key].last_used > 0) { - command_history[key] = commands[key].last_used; + for (const KeyValue<String, Command> &E : commands) { + if (E.value.last_used > 0) { + command_history[E.key] = E.value.last_used; } } EditorSettings::get_singleton()->set_project_metadata("command_palette", "command_history", command_history); diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 7ce483d788..0bb48db09e 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -468,12 +468,12 @@ Variant EditorData::instance_custom_type(const String &p_type, const String &p_i } void EditorData::remove_custom_type(const String &p_type) { - for (Map<String, Vector<CustomType>>::Element *E = custom_types.front(); E; E = E->next()) { - for (int i = 0; i < E->get().size(); i++) { - if (E->get()[i].name == p_type) { - E->get().remove_at(i); - if (E->get().is_empty()) { - custom_types.erase(E->key()); + for (KeyValue<String, Vector<CustomType>> &E : custom_types) { + for (int i = 0; i < E.value.size(); i++) { + if (E.value[i].name == p_type) { + E.value.remove_at(i); + if (E.value.is_empty()) { + custom_types.erase(E.key); } return; } @@ -549,7 +549,7 @@ void EditorData::remove_scene(int p_idx) { edited_scene.remove_at(p_idx); } -bool EditorData::_find_updated_instances(Node *p_root, Node *p_node, Set<String> &checked_paths) { +bool EditorData::_find_updated_instances(Node *p_root, Node *p_node, RBSet<String> &checked_paths) { Ref<SceneState> ss; if (p_node == p_root) { @@ -587,7 +587,7 @@ bool EditorData::check_and_update_scene(int p_idx) { return false; } - Set<String> checked_scenes; + RBSet<String> checked_scenes; bool must_reload = _find_updated_instances(edited_scene[p_idx].root, edited_scene[p_idx].root, checked_scenes); @@ -945,13 +945,10 @@ void EditorData::script_class_set_name(const String &p_path, const StringName &p } void EditorData::script_class_save_icon_paths() { - List<StringName> keys; - _script_class_icon_paths.get_key_list(&keys); - Dictionary d; - for (const StringName &E : keys) { - if (ScriptServer::is_global_class(E)) { - d[E] = _script_class_icon_paths[E]; + for (const KeyValue<StringName, String> &E : _script_class_icon_paths) { + if (ScriptServer::is_global_class(E.key)) { + d[E.key] = E.value; } } @@ -1157,7 +1154,7 @@ List<Node *> EditorSelection::get_full_selected_node_list() { void EditorSelection::clear() { while (!selection.is_empty()) { - remove_node(selection.front()->key()); + remove_node(selection.begin()->key); } changed = true; diff --git a/editor/editor_data.h b/editor/editor_data.h index 1e9b8af490..b9eb199c37 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -129,17 +129,17 @@ private: String name; Variant value; }; - Map<String, Vector<CustomType>> custom_types; + HashMap<String, Vector<CustomType>> custom_types; List<PropertyData> clipboard; UndoRedo undo_redo; Vector<Callable> undo_redo_callbacks; - Map<StringName, Callable> move_element_functions; + HashMap<StringName, Callable> move_element_functions; Vector<EditedScene> edited_scene; int current_edited_scene; - bool _find_updated_instances(Node *p_root, Node *p_node, Set<String> &checked_paths); + bool _find_updated_instances(Node *p_root, Node *p_node, RBSet<String> &checked_paths); HashMap<StringName, String> _script_class_icon_paths; HashMap<String, StringName> _script_class_file_to_path; @@ -181,7 +181,7 @@ public: void add_custom_type(const String &p_type, const String &p_inherits, const Ref<Script> &p_script, const Ref<Texture2D> &p_icon); Variant instance_custom_type(const String &p_type, const String &p_inherits); void remove_custom_type(const String &p_type); - const Map<String, Vector<CustomType>> &get_custom_types() const { return custom_types; } + const HashMap<String, Vector<CustomType>> &get_custom_types() const { return custom_types; } void instantiate_object_properties(Object *p_object); @@ -247,7 +247,7 @@ class EditorSelection : public Object { // Contains the selected nodes and corresponding metadata. // Metadata objects come from calling _get_editor_data on the editor_plugins, passing the selected node. - Map<Node *, Object *> selection; + HashMap<Node *, Object *> selection; // Tracks whether the selection change signal has been emitted. // Prevents multiple signals being called in one frame. @@ -296,7 +296,7 @@ public: // Returns all the selected nodes (list version of "get_selected_nodes"). List<Node *> get_full_selected_node_list(); // Returns the map of selected objects and their metadata. - Map<Node *, Object *> &get_selection() { return selection; } + HashMap<Node *, Object *> &get_selection() { return selection; } EditorSelection(); ~EditorSelection(); diff --git a/editor/editor_dir_dialog.h b/editor/editor_dir_dialog.h index 9baa37793b..60abfeb66f 100644 --- a/editor/editor_dir_dialog.h +++ b/editor/editor_dir_dialog.h @@ -44,7 +44,7 @@ class EditorDirDialog : public ConfirmationDialog { AcceptDialog *mkdirerr = nullptr; Button *makedir = nullptr; - Set<String> opened_paths; + RBSet<String> opened_paths; Tree *tree = nullptr; bool updating = false; diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index a21ee46818..f0eea50d3a 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -95,7 +95,7 @@ Ref<EditorExportPlatform> EditorExportPreset::get_platform() const { void EditorExportPreset::update_files_to_export() { Vector<String> to_remove; - for (Set<String>::Element *E = selected_files.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = selected_files.front(); E; E = E->next()) { if (!FileAccess::exists(E->get())) { to_remove.push_back(E->get()); } @@ -107,7 +107,7 @@ void EditorExportPreset::update_files_to_export() { Vector<String> EditorExportPreset::get_files_to_export() const { Vector<String> files; - for (Set<String>::Element *E = selected_files.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = selected_files.front(); E; E = E->next()) { files.push_back(E->get()); } return files; @@ -446,7 +446,7 @@ Ref<EditorExportPreset> EditorExportPlatform::create_preset() { return preset; } -void EditorExportPlatform::_export_find_resources(EditorFileSystemDirectory *p_dir, Set<String> &p_paths) { +void EditorExportPlatform::_export_find_resources(EditorFileSystemDirectory *p_dir, RBSet<String> &p_paths) { for (int i = 0; i < p_dir->get_subdir_count(); i++) { _export_find_resources(p_dir->get_subdir(i), p_paths); } @@ -459,7 +459,7 @@ void EditorExportPlatform::_export_find_resources(EditorFileSystemDirectory *p_d } } -void EditorExportPlatform::_export_find_dependencies(const String &p_path, Set<String> &p_paths) { +void EditorExportPlatform::_export_find_dependencies(const String &p_path, RBSet<String> &p_paths) { if (p_paths.has(p_path)) { return; } @@ -480,7 +480,7 @@ void EditorExportPlatform::_export_find_dependencies(const String &p_path, Set<S } } -void EditorExportPlatform::_edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude) { +void EditorExportPlatform::_edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, RBSet<String> &r_list, bool exclude) { da->list_dir_begin(); String cur_dir = da->get_current_dir().replace("\\", "/"); if (!cur_dir.ends_with("/")) { @@ -528,7 +528,7 @@ void EditorExportPlatform::_edit_files_with_filter(Ref<DirAccess> &da, const Vec } } -void EditorExportPlatform::_edit_filter_list(Set<String> &r_list, const String &p_filter, bool exclude) { +void EditorExportPlatform::_edit_filter_list(RBSet<String> &r_list, const String &p_filter, bool exclude) { if (p_filter.is_empty()) { return; } @@ -648,10 +648,10 @@ void EditorExportPlugin::_export_end_script() { GDVIRTUAL_CALL(_export_end); } -void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) { +void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const RBSet<String> &p_features) { } -void EditorExportPlugin::_export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags) { +void EditorExportPlugin::_export_begin(const RBSet<String> &p_features, bool p_debug, const String &p_path, int p_flags) { } void EditorExportPlugin::skip() { @@ -739,7 +739,7 @@ EditorExportPlatform::ExportNotifier::~ExportNotifier() { Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) { //figure out paths of files that will be exported - Set<String> paths; + RBSet<String> paths; Vector<String> path_remaps; if (p_preset->get_export_filter() == EditorExportPreset::EXPORT_ALL_RESOURCES) { @@ -872,14 +872,14 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } FeatureContainers feature_containers = get_feature_containers(p_preset, p_debug); - Set<String> &features = feature_containers.features; + RBSet<String> &features = feature_containers.features; Vector<String> &features_pv = feature_containers.features_pv; //store everything in the export medium int idx = 0; int total = paths.size(); - for (Set<String>::Element *E = paths.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = paths.front(); E; E = E->next()) { String path = E->get(); String type = ResourceLoader::get_resource_type(path); @@ -910,7 +910,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & List<String> remaps; config->get_section_keys("remap", &remaps); - Set<String> remap_features; + RBSet<String> remap_features; for (const String &F : remaps) { String remap = F; @@ -1334,7 +1334,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) { EditorProgress ep("savezip", TTR("Packing"), 102, true); - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io); ZipData zd; @@ -1668,7 +1669,7 @@ void EditorExport::load_config() { } void EditorExport::update_export_presets() { - Map<StringName, List<EditorExportPlatform::ExportOption>> platform_options; + HashMap<StringName, List<EditorExportPlatform::ExportOption>> platform_options; for (int i = 0; i < export_platforms.size(); i++) { Ref<EditorExportPlatform> platform = export_platforms[i]; @@ -1690,7 +1691,7 @@ void EditorExport::update_export_presets() { List<EditorExportPlatform::ExportOption> options = platform_options[preset->get_platform()->get_name()]; // Copy the previous preset values - Map<StringName, Variant> previous_values = preset->values; + HashMap<StringName, Variant> previous_values = preset->values; // Clear the preset properties and values prior to reloading preset->properties.clear(); @@ -1933,7 +1934,7 @@ void EditorExportPlatformPC::get_platform_features(List<String> *r_features) { r_features->push_back(get_os_name().to_lower()); //OS name is a feature } -void EditorExportPlatformPC::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) { +void EditorExportPlatformPC::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, RBSet<String> &p_features) { if (p_features.has("bptc")) { if (p_preset->has("texture_format/no_bptc_fallbacks")) { p_features.erase("s3tc"); @@ -1951,7 +1952,7 @@ void EditorExportPlatformPC::set_chmod_flags(int p_flags) { /////////////////////// -void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) { +void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, const String &p_type, const RBSet<String> &p_features) { String extension = p_path.get_extension().to_lower(); if (extension != "tres" && extension != "tscn") { return; diff --git a/editor/editor_export.h b/editor/editor_export.h index 1aca140e79..3b8ff0f686 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -66,14 +66,14 @@ private: String export_path; String exporter; - Set<String> selected_files; + RBSet<String> selected_files; bool runnable = false; friend class EditorExport; friend class EditorExportPlatform; List<PropertyInfo> properties; - Map<StringName, Variant> values; + HashMap<StringName, Variant> values; String name; @@ -196,19 +196,19 @@ private: }; struct FeatureContainers { - Set<String> features; + RBSet<String> features; Vector<String> features_pv; }; - void _export_find_resources(EditorFileSystemDirectory *p_dir, Set<String> &p_paths); - void _export_find_dependencies(const String &p_path, Set<String> &p_paths); + void _export_find_resources(EditorFileSystemDirectory *p_dir, RBSet<String> &p_paths); + void _export_find_dependencies(const String &p_path, RBSet<String> &p_paths); void gen_debug_flags(Vector<String> &r_flags, int p_flags); static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); - void _edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude); - void _edit_filter_list(Set<String> &r_list, const String &p_filter, bool exclude); + void _edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, RBSet<String> &r_list, bool exclude); + void _edit_filter_list(RBSet<String> &r_list, const String &p_filter, bool exclude); static Error _add_shared_object(void *p_userdata, const SharedObject &p_so); @@ -242,7 +242,7 @@ public: virtual void get_export_options(List<ExportOption> *r_options) = 0; virtual bool should_update_export_options() { return false; } - virtual bool get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } + virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } virtual String get_os_name() const = 0; virtual String get_name() const = 0; @@ -279,7 +279,7 @@ public: virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); virtual void get_platform_features(List<String> *r_features) = 0; - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) = 0; + virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, RBSet<String> &p_features) = 0; virtual String get_debug_protocol() const { return "tcp://"; } EditorExportPlatform(); @@ -349,8 +349,8 @@ protected: void skip(); - virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features); - virtual void _export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags); + virtual void _export_file(const String &p_path, const String &p_type, const RBSet<String> &p_features); + virtual void _export_begin(const RBSet<String> &p_features, bool p_debug, const String &p_path, int p_flags); static void _bind_methods(); @@ -454,7 +454,7 @@ public: void add_platform_feature(const String &p_feature); virtual void get_platform_features(List<String> *r_features) override; - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override; + virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, RBSet<String> &p_features) override; int get_chmod_flags() const; void set_chmod_flags(int p_flags); @@ -468,7 +468,7 @@ class EditorExportTextSceneToBinaryPlugin : public EditorExportPlugin { GDCLASS(EditorExportTextSceneToBinaryPlugin, EditorExportPlugin); public: - virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features) override; + virtual void _export_file(const String &p_path, const String &p_type, const RBSet<String> &p_features) override; EditorExportTextSceneToBinaryPlugin(); }; diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index a20f112b2a..7eb5aec5d0 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -101,7 +101,7 @@ bool EditorFeatureProfile::is_class_editor_disabled(const StringName &p_class) c void EditorFeatureProfile::set_disable_class_property(const StringName &p_class, const StringName &p_property, bool p_disabled) { if (p_disabled) { if (!disabled_properties.has(p_class)) { - disabled_properties[p_class] = Set<StringName>(); + disabled_properties[p_class] = RBSet<StringName>(); } disabled_properties[p_class].insert(p_property); @@ -166,14 +166,14 @@ Error EditorFeatureProfile::save_to_file(const String &p_path) { Dictionary data; data["type"] = "feature_profile"; Array dis_classes; - for (Set<StringName>::Element *E = disabled_classes.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = disabled_classes.front(); E; E = E->next()) { dis_classes.push_back(String(E->get())); } dis_classes.sort(); data["disabled_classes"] = dis_classes; Array dis_editors; - for (Set<StringName>::Element *E = disabled_editors.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = disabled_editors.front(); E; E = E->next()) { dis_editors.push_back(String(E->get())); } dis_editors.sort(); @@ -181,8 +181,8 @@ Error EditorFeatureProfile::save_to_file(const String &p_path) { Array dis_props; - for (KeyValue<StringName, Set<StringName>> &E : disabled_properties) { - for (Set<StringName>::Element *F = E.value.front(); F; F = F->next()) { + for (KeyValue<StringName, RBSet<StringName>> &E : disabled_properties) { + for (RBSet<StringName>::Element *F = E.value.front(); F; F = F->next()) { dis_props.push_back(String(E.key) + ":" + String(F->get())); } } @@ -556,9 +556,9 @@ void EditorFeatureProfileManager::_class_list_item_selected() { String class_description; DocTools *dd = EditorHelp::get_doc_data(); - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(class_name); + HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(class_name); if (E) { - class_description = DTR(E->get().brief_description); + class_description = DTR(E->value.brief_description); } description_bit->set_text(class_description); diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h index 19df8a9686..479baf5205 100644 --- a/editor/editor_feature_profile.h +++ b/editor/editor_feature_profile.h @@ -56,11 +56,11 @@ public: }; private: - Set<StringName> disabled_classes; - Set<StringName> disabled_editors; - Map<StringName, Set<StringName>> disabled_properties; + RBSet<StringName> disabled_classes; + RBSet<StringName> disabled_editors; + HashMap<StringName, RBSet<StringName>> disabled_properties; - Set<StringName> collapsed_classes; + RBSet<StringName> collapsed_classes; bool features_disabled[FEATURE_MAX]; static const char *feature_names[FEATURE_MAX]; diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 84d656fc20..13084e2aab 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -529,7 +529,7 @@ void EditorFileDialog::_multi_selected(int p_item, bool p_selected) { get_ok_button()->set_disabled(_is_open_should_be_disabled()); } -void EditorFileDialog::_items_clear_selection(int p_item, const Vector2 &p_pos, MouseButton p_mouse_button_index) { +void EditorFileDialog::_items_clear_selection(const Vector2 &p_pos, MouseButton p_mouse_button_index) { if (p_mouse_button_index != MouseButton::LEFT) { return; } diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h index d9a58a5b7f..5f2e29b690 100644 --- a/editor/editor_file_dialog.h +++ b/editor/editor_file_dialog.h @@ -165,7 +165,7 @@ private: void _item_selected(int p_item); void _multi_selected(int p_item, bool p_selected); - void _items_clear_selection(int p_item, const Vector2 &p_pos, MouseButton p_mouse_button_index); + void _items_clear_selection(const Vector2 &p_pos, MouseButton p_mouse_button_index); void _item_dc_selected(int p_item); void _item_list_item_rmb_clicked(int p_item, const Vector2 &p_pos, MouseButton p_mouse_button_index); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 099dfe69d5..56edb03184 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -514,7 +514,7 @@ bool EditorFileSystem::_scan_import_support(Vector<String> reimports) { if (import_support_queries.size() == 0) { return false; } - Map<String, int> import_support_test; + HashMap<String, int> import_support_test; Vector<bool> import_support_tested; import_support_tested.resize(import_support_queries.size()); for (int i = 0; i < import_support_queries.size(); i++) { @@ -532,9 +532,9 @@ bool EditorFileSystem::_scan_import_support(Vector<String> reimports) { } for (int i = 0; i < reimports.size(); i++) { - Map<String, int>::Element *E = import_support_test.find(reimports[i].get_extension()); + HashMap<String, int>::Iterator E = import_support_test.find(reimports[i].get_extension()); if (E) { - import_support_tested.write[E->get()] = true; + import_support_tested.write[E->value] = true; } } @@ -1458,7 +1458,7 @@ void EditorFileSystem::_save_late_updated_files() { String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4"); Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::WRITE); ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + fscache + "'. Check user write permissions."); - for (Set<String>::Element *E = late_update_files.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = late_update_files.front(); E; E = E->next()) { f->store_line(E->get()); } } @@ -1636,15 +1636,15 @@ void EditorFileSystem::update_file(const String &p_file) { _queue_update_script_classes(); } -Set<String> EditorFileSystem::get_valid_extensions() const { +RBSet<String> EditorFileSystem::get_valid_extensions() const { return valid_extensions; } Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector<String> &p_files) { String importer_name; - Map<String, Map<StringName, Variant>> source_file_options; - Map<String, String> base_paths; + HashMap<String, HashMap<StringName, Variant>> source_file_options; + HashMap<String, String> base_paths; for (int i = 0; i < p_files.size(); i++) { Ref<ConfigFile> config; config.instantiate(); @@ -1659,7 +1659,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector ERR_FAIL_V(ERR_FILE_CORRUPT); } - source_file_options[p_files[i]] = Map<StringName, Variant>(); + source_file_options[p_files[i]] = HashMap<StringName, Variant>(); importer_name = file_importer_name; if (importer_name == "keep") { @@ -1699,7 +1699,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector Error err = importer->import_group_file(p_group_file, source_file_options, base_paths); //all went well, overwrite config files with proper remaps and md5s - for (const KeyValue<String, Map<StringName, Variant>> &E : source_file_options) { + for (const KeyValue<String, HashMap<StringName, Variant>> &E : source_file_options) { const String &file = E.key; String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(file); Vector<String> dest_paths; @@ -1808,7 +1808,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector return err; } -void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName, Variant> *p_custom_options, const String &p_custom_importer) { +void EditorFileSystem::_reimport_file(const String &p_file, const HashMap<StringName, Variant> *p_custom_options, const String &p_custom_importer) { EditorFileSystemDirectory *fs = nullptr; int cpos = -1; bool found = _find_file(p_file, &fs, cpos); @@ -1816,7 +1816,7 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName //try to obtain existing params - Map<StringName, Variant> params; + HashMap<StringName, Variant> params; String importer_name; //empty by default though if (!p_custom_importer.is_empty()) { @@ -2047,7 +2047,7 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName EditorResourcePreview::get_singleton()->check_for_invalidation(p_file); } -void EditorFileSystem::_find_group_files(EditorFileSystemDirectory *efd, Map<String, Vector<String>> &group_files, Set<String> &groups_to_reimport) { +void EditorFileSystem::_find_group_files(EditorFileSystemDirectory *efd, HashMap<String, Vector<String>> &group_files, RBSet<String> &groups_to_reimport) { int fc = efd->files.size(); const EditorFileSystemDirectory::FileInfo *const *files = efd->files.ptr(); for (int i = 0; i < fc; i++) { @@ -2064,7 +2064,7 @@ void EditorFileSystem::_find_group_files(EditorFileSystemDirectory *efd, Map<Str } } -void EditorFileSystem::reimport_file_with_custom_parameters(const String &p_file, const String &p_importer, const Map<StringName, Variant> &p_custom_params) { +void EditorFileSystem::reimport_file_with_custom_parameters(const String &p_file, const String &p_importer, const HashMap<StringName, Variant> &p_custom_params) { _reimport_file(p_file, &p_custom_params, p_importer); } @@ -2079,7 +2079,7 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) { Vector<ImportFile> reimport_files; - Set<String> groups_to_reimport; + RBSet<String> groups_to_reimport; for (int i = 0; i < p_files.size(); i++) { String file = p_files[i]; @@ -2165,7 +2165,7 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) { //reimport groups if (groups_to_reimport.size()) { - Map<String, Vector<String>> group_files; + HashMap<String, Vector<String>> group_files; _find_group_files(filesystem, group_files, groups_to_reimport); for (const KeyValue<String, Vector<String>> &E : group_files) { Error err = _reimport_group(E.key, E.value); @@ -2290,7 +2290,7 @@ ResourceUID::ID EditorFileSystem::_resource_saver_get_resource_id_for_path(const } } -static void _scan_extensions_dir(EditorFileSystemDirectory *d, Set<String> &extensions) { +static void _scan_extensions_dir(EditorFileSystemDirectory *d, RBSet<String> &extensions) { int fc = d->get_file_count(); for (int i = 0; i < fc; i++) { if (d->get_file_type(i) == SNAME("NativeExtension")) { @@ -2304,7 +2304,7 @@ static void _scan_extensions_dir(EditorFileSystemDirectory *d, Set<String> &exte } bool EditorFileSystem::_scan_extensions() { EditorFileSystemDirectory *d = get_filesystem(); - Set<String> extensions; + RBSet<String> extensions; _scan_extensions_dir(d, extensions); @@ -2372,6 +2372,7 @@ void EditorFileSystem::_bind_methods() { ClassDB::bind_method(D_METHOD("get_filesystem_path", "path"), &EditorFileSystem::get_filesystem_path); ClassDB::bind_method(D_METHOD("get_file_type", "path"), &EditorFileSystem::get_file_type); ClassDB::bind_method(D_METHOD("update_script_classes"), &EditorFileSystem::update_script_classes); + ClassDB::bind_method(D_METHOD("reimport_files", "files"), &EditorFileSystem::reimport_files); ADD_SIGNAL(MethodInfo("filesystem_changed")); ADD_SIGNAL(MethodInfo("sources_changed", PropertyInfo(Variant::BOOL, "exist"))); diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 81811d2eb0..743684a9ca 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -34,8 +34,8 @@ #include "core/io/dir_access.h" #include "core/os/thread.h" #include "core/os/thread_safe.h" +#include "core/templates/rb_set.h" #include "core/templates/safe_refcount.h" -#include "core/templates/set.h" #include "core/templates/thread_work_pool.h" #include "scene/main/node.h" @@ -180,7 +180,7 @@ class EditorFileSystem : public Node { void _scan_filesystem(); - Set<String> late_update_files; + RBSet<String> late_update_files; void _save_late_updated_files(); @@ -221,9 +221,9 @@ class EditorFileSystem : public Node { void _delete_internal_files(String p_file); - Set<String> textfile_extensions; - Set<String> valid_extensions; - Set<String> import_extensions; + RBSet<String> textfile_extensions; + RBSet<String> valid_extensions; + RBSet<String> import_extensions; void _scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAccess> &da, const ScanProgress &p_progress); @@ -240,7 +240,7 @@ class EditorFileSystem : public Node { void _update_extensions(); - void _reimport_file(const String &p_file, const Map<StringName, Variant> *p_custom_options = nullptr, const String &p_custom_importer = String()); + void _reimport_file(const String &p_file, const HashMap<StringName, Variant> *p_custom_options = nullptr, const String &p_custom_importer = String()); Error _reimport_group(const String &p_group_file, const Vector<String> &p_files); bool _test_for_reimport(const String &p_path, bool p_only_imported_files); @@ -269,11 +269,11 @@ class EditorFileSystem : public Node { bool using_fat32_or_exfat; // Workaround for projects in FAT32 or exFAT filesystem (pendrives, most of the time) - void _find_group_files(EditorFileSystemDirectory *efd, Map<String, Vector<String>> &group_files, Set<String> &groups_to_reimport); + void _find_group_files(EditorFileSystemDirectory *efd, HashMap<String, Vector<String>> &group_files, RBSet<String> &groups_to_reimport); void _move_group_files(EditorFileSystemDirectory *efd, const String &p_group_file, const String &p_new_location); - Set<String> group_file_cache; + RBSet<String> group_file_cache; ThreadWorkPool import_threads; @@ -306,7 +306,7 @@ public: void scan(); void scan_changes(); void update_file(const String &p_file); - Set<String> get_valid_extensions() const; + RBSet<String> get_valid_extensions() const; EditorFileSystemDirectory *get_filesystem_path(const String &p_path); String get_file_type(const String &p_file) const; @@ -314,7 +314,7 @@ public: void reimport_files(const Vector<String> &p_files); - void reimport_file_with_custom_parameters(const String &p_file, const String &p_importer, const Map<StringName, Variant> &p_custom_params); + void reimport_file_with_custom_parameters(const String &p_file, const String &p_importer, const HashMap<StringName, Variant> &p_custom_params); void update_script_classes(); diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp index 76c7023b46..39dc253429 100644 --- a/editor/editor_folding.cpp +++ b/editor/editor_folding.cpp @@ -40,7 +40,7 @@ Vector<String> EditorFolding::_get_unfolds(const Object *p_object) { if (sections.size()) { String *w = sections.ptrw(); int idx = 0; - for (const Set<String>::Element *E = p_object->editor_get_section_folding().front(); E; E = E->next()) { + for (const RBSet<String>::Element *E = p_object->editor_get_section_folding().front(); E; E = E->next()) { w[idx++] = E->get(); } } @@ -87,7 +87,7 @@ void EditorFolding::load_resource_folding(Ref<Resource> p_resource, const String _set_unfolds(p_resource.ptr(), unfolds); } -void EditorFolding::_fill_folds(const Node *p_root, const Node *p_node, Array &p_folds, Array &resource_folds, Array &nodes_folded, Set<Ref<Resource>> &resources) { +void EditorFolding::_fill_folds(const Node *p_root, const Node *p_node, Array &p_folds, Array &resource_folds, Array &nodes_folded, RBSet<Ref<Resource>> &resources) { if (p_root != p_node) { if (!p_node->get_owner()) { return; //not owned, bye @@ -140,7 +140,7 @@ void EditorFolding::save_scene_folding(const Node *p_scene, const String &p_path config.instantiate(); Array unfolds, res_unfolds; - Set<Ref<Resource>> resources; + RBSet<Ref<Resource>> resources; Array nodes_folded; _fill_folds(p_scene, p_scene, unfolds, res_unfolds, nodes_folded, resources); @@ -220,13 +220,13 @@ bool EditorFolding::has_folding_data(const String &p_path) { return FileAccess::exists(file); } -void EditorFolding::_do_object_unfolds(Object *p_object, Set<Ref<Resource>> &resources) { +void EditorFolding::_do_object_unfolds(Object *p_object, RBSet<Ref<Resource>> &resources) { List<PropertyInfo> plist; p_object->get_property_list(&plist); String group_base; String group; - Set<String> unfold_group; + RBSet<String> unfold_group; for (const PropertyInfo &E : plist) { if (E.usage & PROPERTY_USAGE_CATEGORY) { @@ -270,12 +270,12 @@ void EditorFolding::_do_object_unfolds(Object *p_object, Set<Ref<Resource>> &res } } - for (Set<String>::Element *E = unfold_group.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = unfold_group.front(); E; E = E->next()) { p_object->editor_set_section_unfold(E->get(), true); } } -void EditorFolding::_do_node_unfolds(Node *p_root, Node *p_node, Set<Ref<Resource>> &resources) { +void EditorFolding::_do_node_unfolds(Node *p_root, Node *p_node, RBSet<Ref<Resource>> &resources) { if (p_root != p_node) { if (!p_node->get_owner()) { return; //not owned, bye @@ -293,7 +293,7 @@ void EditorFolding::_do_node_unfolds(Node *p_root, Node *p_node, Set<Ref<Resourc } void EditorFolding::unfold_scene(Node *p_scene) { - Set<Ref<Resource>> resources; + RBSet<Ref<Resource>> resources; _do_node_unfolds(p_scene, p_scene, resources); } diff --git a/editor/editor_folding.h b/editor/editor_folding.h index 86f4643ed8..22df06280a 100644 --- a/editor/editor_folding.h +++ b/editor/editor_folding.h @@ -37,10 +37,10 @@ class EditorFolding { Vector<String> _get_unfolds(const Object *p_object); void _set_unfolds(Object *p_object, const Vector<String> &p_unfolds); - void _fill_folds(const Node *p_root, const Node *p_node, Array &p_folds, Array &resource_folds, Array &nodes_folded, Set<Ref<Resource>> &resources); + void _fill_folds(const Node *p_root, const Node *p_node, Array &p_folds, Array &resource_folds, Array &nodes_folded, RBSet<Ref<Resource>> &resources); - void _do_object_unfolds(Object *p_object, Set<Ref<Resource>> &resources); - void _do_node_unfolds(Node *p_root, Node *p_node, Set<Ref<Resource>> &resources); + void _do_object_unfolds(Object *p_object, RBSet<Ref<Resource>> &resources); + void _do_node_unfolds(Node *p_root, Node *p_node, RBSet<Ref<Resource>> &resources); public: void save_resource_folding(const Ref<Resource> &p_resource, const String &p_path); diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index 3e18499b97..51d4d474c5 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -110,6 +110,32 @@ m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \ MAKE_FALLBACKS(m_name); +#define MAKE_DEFAULT_FONT_MSDF(m_name, m_variations) \ + Ref<Font> m_name; \ + m_name.instantiate(); \ + if (CustomFont.is_valid()) { \ + m_name->add_data(CustomFontMSDF); \ + m_name->add_data(DefaultFontMSDF); \ + } else { \ + m_name->add_data(DefaultFontMSDF); \ + } \ + { \ + Dictionary variations; \ + if (!m_variations.is_empty()) { \ + Vector<String> variation_tags = m_variations.split(","); \ + for (int i = 0; i < variation_tags.size(); i++) { \ + Vector<String> tokens = variation_tags[i].split("="); \ + if (tokens.size() == 2) { \ + variations[tokens[0]] = tokens[1].to_float(); \ + } \ + } \ + } \ + m_name->set_variation_coordinates(variations); \ + } \ + m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \ + m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \ + MAKE_FALLBACKS(m_name); + #define MAKE_SLANTED_FONT(m_name, m_variations) \ Ref<Font> m_name; \ m_name.instantiate(); \ @@ -163,6 +189,32 @@ m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \ MAKE_FALLBACKS_BOLD(m_name); +#define MAKE_BOLD_FONT_MSDF(m_name, m_variations) \ + Ref<Font> m_name; \ + m_name.instantiate(); \ + if (CustomFontBold.is_valid()) { \ + m_name->add_data(CustomFontBoldMSDF); \ + m_name->add_data(DefaultFontBoldMSDF); \ + } else { \ + m_name->add_data(DefaultFontBoldMSDF); \ + } \ + { \ + Dictionary variations; \ + if (!m_variations.is_empty()) { \ + Vector<String> variation_tags = m_variations.split(","); \ + for (int i = 0; i < variation_tags.size(); i++) { \ + Vector<String> tokens = variation_tags[i].split("="); \ + if (tokens.size() == 2) { \ + variations[tokens[0]] = tokens[1].to_float(); \ + } \ + } \ + } \ + m_name->set_variation_coordinates(variations); \ + } \ + m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \ + m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \ + MAKE_FALLBACKS_BOLD(m_name); + #define MAKE_SOURCE_FONT(m_name, m_variations) \ Ref<Font> m_name; \ m_name.instantiate(); \ @@ -189,13 +241,14 @@ m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \ MAKE_FALLBACKS(m_name); -Ref<FontData> load_cached_external_font(const String &p_path, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning) { +Ref<FontData> load_cached_external_font(const String &p_path, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false) { Ref<FontData> font; font.instantiate(); Vector<uint8_t> data = FileAccess::get_file_as_array(p_path); font->set_data(data); + font->set_multichannel_signed_distance_field(p_msdf); font->set_antialiased(p_aa); font->set_hinting(p_hinting); font->set_force_autohinter(p_autohint); @@ -204,11 +257,12 @@ Ref<FontData> load_cached_external_font(const String &p_path, TextServer::Hintin return font; } -Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning) { +Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false) { Ref<FontData> font; font.instantiate(); font->set_data_ptr(p_data, p_size); + font->set_multichannel_signed_distance_field(p_msdf); font->set_antialiased(p_aa); font->set_hinting(p_hinting); font->set_force_autohinter(p_autohint); @@ -261,6 +315,13 @@ void editor_register_fonts(Ref<Theme> p_theme) { EditorSettings::get_singleton()->set_manually("interface/editor/main_font", ""); } + Ref<FontData> CustomFontMSDF; + if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { + CustomFontMSDF = load_cached_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning, true); + } else { + EditorSettings::get_singleton()->set_manually("interface/editor/main_font", ""); + } + Ref<FontData> CustomFontSlanted; if (CustomFont.is_valid()) { CustomFontSlanted = CustomFont->duplicate(); @@ -282,6 +343,13 @@ void editor_register_fonts(Ref<Theme> p_theme) { CustomFontBold->set_embolden(embolden_strength); } + Ref<FontData> CustomFontBoldMSDF; + if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { + CustomFontBoldMSDF = load_cached_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning, true); + } else { + EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", ""); + } + /* Custom source code font */ String custom_font_path_source = EditorSettings::get_singleton()->get("interface/editor/code_font"); @@ -295,7 +363,9 @@ void editor_register_fonts(Ref<Theme> p_theme) { /* Noto Sans */ Ref<FontData> DefaultFont = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontData> DefaultFontMSDF = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true); Ref<FontData> DefaultFontBold = load_cached_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontData> DefaultFontBoldMSDF = load_cached_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true); Ref<FontData> FontArabic = load_cached_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontData> FontArabicBold = load_cached_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontData> FontBengali = load_cached_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning); @@ -347,12 +417,18 @@ void editor_register_fonts(Ref<Theme> p_theme) { p_theme->set_font_size("main_size", "EditorFonts", default_font_size); p_theme->set_font("main", "EditorFonts", df); + MAKE_DEFAULT_FONT_MSDF(df_msdf, String()); + p_theme->set_font("main_msdf", "EditorFonts", df_msdf); + // Bold font MAKE_BOLD_FONT(df_bold, String()); MAKE_SLANTED_FONT(df_italic, String()); p_theme->set_font_size("bold_size", "EditorFonts", default_font_size); p_theme->set_font("bold", "EditorFonts", df_bold); + MAKE_BOLD_FONT_MSDF(df_bold_msdf, String()); + p_theme->set_font("main_bold_msdf", "EditorFonts", df_bold_msdf); + // Title font p_theme->set_font_size("title_size", "EditorFonts", default_font_size + 1 * EDSCALE); p_theme->set_font("title", "EditorFonts", df_bold); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index dfd768d0d0..e33d160762 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -99,7 +99,7 @@ void EditorHelp::_class_desc_select(const String &p_select) { String link = p_select.substr(tag_end + 1, p_select.length()).lstrip(" "); String topic; - Map<String, int> *table = nullptr; + HashMap<String, int> *table = nullptr; if (tag == "method") { topic = "class_method"; @@ -123,37 +123,34 @@ void EditorHelp::_class_desc_select(const String &p_select) { return; } - if (link.contains(".")) { - emit_signal(SNAME("go_to_help"), topic + ":" + link.get_slice(".", 0) + ":" + link.get_slice(".", 1)); - } else { - if (table->has(link)) { - // Found in the current page - class_desc->scroll_to_paragraph((*table)[link]); - } else { - if (topic == "class_enum") { - // Try to find the enum in @GlobalScope - const DocData::ClassDoc &cd = doc->class_list["@GlobalScope"]; - - for (int i = 0; i < cd.constants.size(); i++) { - if (cd.constants[i].enumeration == link) { - // Found in @GlobalScope - emit_signal(SNAME("go_to_help"), topic + ":@GlobalScope:" + link); - break; - } - } - } else if (topic == "class_constant") { - // Try to find the constant in @GlobalScope - const DocData::ClassDoc &cd = doc->class_list["@GlobalScope"]; - - for (int i = 0; i < cd.constants.size(); i++) { - if (cd.constants[i].name == link) { - // Found in @GlobalScope - emit_signal(SNAME("go_to_help"), topic + ":@GlobalScope:" + link); - break; - } - } + // Case order is important here to correctly handle edge cases like Variant.Type in @GlobalScope. + if (table->has(link)) { + // Found in the current page. + class_desc->scroll_to_paragraph((*table)[link]); + } else if (topic == "class_enum") { + // Try to find the enum in @GlobalScope. + const DocData::ClassDoc &cd = doc->class_list["@GlobalScope"]; + + for (int i = 0; i < cd.constants.size(); i++) { + if (cd.constants[i].enumeration == link) { + // Found in @GlobalScope. + emit_signal(SNAME("go_to_help"), topic + ":@GlobalScope:" + link); + break; } } + } else if (topic == "class_constant") { + // Try to find the constant in @GlobalScope. + const DocData::ClassDoc &cd = doc->class_list["@GlobalScope"]; + + for (int i = 0; i < cd.constants.size(); i++) { + if (cd.constants[i].name == link) { + // Found in @GlobalScope. + emit_signal(SNAME("go_to_help"), topic + ":@GlobalScope:" + link); + break; + } + } + } else if (link.contains(".")) { + emit_signal(SNAME("go_to_help"), topic + ":" + link.get_slice(".", 0) + ":" + link.get_slice(".", 1)); } } else if (p_select.begins_with("http")) { OS::get_singleton()->shell_open(p_select); @@ -339,7 +336,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { description_line = 0; if (p_class == edited_class) { - return OK; //already there + return OK; // Already there. } edited_class = p_class; @@ -651,7 +648,7 @@ void EditorHelp::_update_doc() { } // Properties overview - Set<String> skip_methods; + RBSet<String> skip_methods; bool property_descr = false; bool has_properties = cd.properties.size() != 0; @@ -876,7 +873,7 @@ void EditorHelp::_update_doc() { class_desc->push_indent(1); String theme_data_type; - Map<String, String> data_type_names; + HashMap<String, String> data_type_names; data_type_names["color"] = TTR("Colors"); data_type_names["constant"] = TTR("Constants"); data_type_names["font"] = TTR("Fonts"); @@ -885,7 +882,7 @@ void EditorHelp::_update_doc() { data_type_names["style"] = TTR("Styles"); for (int i = 0; i < cd.theme_properties.size(); i++) { - theme_property_line[cd.theme_properties[i].name] = class_desc->get_line_count() - 2; //gets overridden if description + theme_property_line[cd.theme_properties[i].name] = class_desc->get_line_count() - 2; // Gets overridden if description. if (theme_data_type != cd.theme_properties[i].data_type) { theme_data_type = cd.theme_properties[i].data_type; @@ -970,7 +967,7 @@ void EditorHelp::_update_doc() { class_desc->push_indent(1); for (int i = 0; i < cd.signals.size(); i++) { - signal_line[cd.signals[i].name] = class_desc->get_line_count() - 2; //gets overridden if description + signal_line[cd.signals[i].name] = class_desc->get_line_count() - 2; // Gets overridden if description. class_desc->push_font(doc_code_font); // monofont class_desc->push_color(headline_color); @@ -1022,7 +1019,7 @@ void EditorHelp::_update_doc() { // Constants and enums if (!cd.constants.is_empty()) { - Map<String, Vector<DocData::ConstantDoc>> enums; + HashMap<String, Vector<DocData::ConstantDoc>> enums; Vector<DocData::ConstantDoc> constants; for (int i = 0; i < cd.constants.size(); i++) { @@ -1092,7 +1089,7 @@ void EditorHelp::_update_doc() { class_desc->push_indent(1); Vector<DocData::ConstantDoc> enum_list = E.value; - Map<String, int> enumValuesContainer; + HashMap<String, int> enumValuesContainer; int enumStartingLine = enum_line[E.key]; for (int i = 0; i < enum_list.size(); i++) { @@ -1100,7 +1097,7 @@ void EditorHelp::_update_doc() { enumValuesContainer[enum_list[i].name] = enumStartingLine; } - // Add the enum constant line to the constant_line map so we can locate it as a constant + // Add the enum constant line to the constant_line map so we can locate it as a constant. constant_line[enum_list[i].name] = class_desc->get_line_count() - 2; class_desc->push_font(doc_code_font); @@ -1288,7 +1285,7 @@ void EditorHelp::_update_doc() { // Script doc doesn't have setter, getter. if (!cd.is_script_doc) { - Map<String, DocData::MethodDoc> method_map; + HashMap<String, DocData::MethodDoc> method_map; for (int j = 0; j < methods.size(); j++) { method_map[methods[j].name] = methods[j]; } @@ -1417,7 +1414,7 @@ void EditorHelp::_help_callback(const String &p_topic) { name = p_topic.get_slice(":", 2); } - _request_help(clss); //first go to class + _request_help(clss); // First go to class. int line = 0; @@ -1453,15 +1450,15 @@ void EditorHelp::_help_callback(const String &p_topic) { } else if (method_line.has(name)) { line = method_line[name]; } else { - Map<String, Map<String, int>>::Element *iter = enum_values_line.front(); + HashMap<String, HashMap<String, int>>::Iterator iter = enum_values_line.begin(); while (true) { - if (iter->value().has(name)) { - line = iter->value()[name]; + if (iter->value.has(name)) { + line = iter->value[name]; break; - } else if (iter == enum_values_line.back()) { + } else if (iter == enum_values_line.last()) { break; } else { - iter = iter->next(); + ++iter; } } } @@ -1486,7 +1483,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges(); - // Select the correct code examples + // Select the correct code examples. switch ((int)EDITOR_GET("text_editor/help/class_reference_examples")) { case 0: // GDScript bbcode = bbcode.replace("[gdscript]", "[codeblock]"); @@ -1531,13 +1528,13 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { break; } - // Remove codeblocks (they would be printed otherwise) + // Remove codeblocks (they would be printed otherwise). bbcode = bbcode.replace("[codeblocks]\n", ""); bbcode = bbcode.replace("\n[/codeblocks]", ""); bbcode = bbcode.replace("[codeblocks]", ""); bbcode = bbcode.replace("[/codeblocks]", ""); - // remove extra new lines around code blocks + // Remove extra new lines around code blocks. bbcode = bbcode.replace("[codeblock]\n", "[codeblock]"); bbcode = bbcode.replace("\n[/codeblock]", "[/codeblock]"); @@ -1561,7 +1558,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { } if (brk_pos == bbcode.length()) { - break; //nothing else to add + break; // Nothing else to add. } int brk_end = bbcode.find("]", brk_pos + 1); @@ -1627,45 +1624,45 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { pos = brk_end + 1; } else if (tag == "b") { - //use bold font + // Use bold font. p_rt->push_font(doc_bold_font); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "i") { - //use italics font + // Use italics font. p_rt->push_font(doc_italic_font); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "code" || tag == "codeblock") { - //use monospace font + // Use monospace font. p_rt->push_font(doc_code_font); p_rt->push_color(code_color); code_tag = true; pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "kbd") { - //use keyboard font with custom color + // Use keyboard font with custom color. p_rt->push_font(doc_kbd_font); p_rt->push_color(kbd_color); - code_tag = true; // though not strictly a code tag, logic is similar + code_tag = true; // Though not strictly a code tag, logic is similar. pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "center") { - //align to center + // Align to center. p_rt->push_paragraph(HORIZONTAL_ALIGNMENT_CENTER, Control::TEXT_DIRECTION_AUTO, ""); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "br") { - //force a line break + // Force a line break. p_rt->add_newline(); pos = brk_end + 1; } else if (tag == "u") { - //use underline + // Use underline. p_rt->push_underline(); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "s") { - //use strikethrough + // Use strikethrough. p_rt->push_strikethrough(); pos = brk_end + 1; tag_stack.push_front(tag); @@ -1741,7 +1738,7 @@ void EditorHelp::_wait_for_thread() { void EditorHelp::_gen_doc_thread(void *p_udata) { DocTools compdoc; compdoc.load_compressed(_doc_data_compressed, _doc_data_compressed_size, _doc_data_uncompressed_size); - doc->merge_from(compdoc); //ensure all is up to date + doc->merge_from(compdoc); // Ensure all is up to date. } static bool doc_gen_use_threads = true; @@ -1935,7 +1932,7 @@ void EditorHelpBit::_meta_clicked(String p_select) { String m = p_select.substr(1, p_select.length()); if (m.contains(".")) { - _go_to_help("class_method:" + m.get_slice(".", 0) + ":" + m.get_slice(".", 0)); //must go somewhere else + _go_to_help("class_method:" + m.get_slice(".", 0) + ":" + m.get_slice(".", 0)); // Must go somewhere else. } } } diff --git a/editor/editor_help.h b/editor/editor_help.h index e289f91414..b5410f6880 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -105,13 +105,13 @@ class EditorHelp : public VBoxContainer { String edited_class; Vector<Pair<String, int>> section_line; - Map<String, int> method_line; - Map<String, int> signal_line; - Map<String, int> property_line; - Map<String, int> theme_property_line; - Map<String, int> constant_line; - Map<String, int> enum_line; - Map<String, Map<String, int>> enum_values_line; + HashMap<String, int> method_line; + HashMap<String, int> signal_line; + HashMap<String, int> property_line; + HashMap<String, int> theme_property_line; + HashMap<String, int> constant_line; + HashMap<String, int> enum_line; + HashMap<String, HashMap<String, int>> enum_values_line; int description_line = 0; RichTextLabel *class_desc = nullptr; diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index c747ae326f..d6ed2297c7 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -313,7 +313,7 @@ bool EditorHelpSearch::Runner::_slice() { } bool EditorHelpSearch::Runner::_phase_match_classes_init() { - iterator_doc = EditorHelp::get_doc_data()->class_list.front(); + iterator_doc = EditorHelp::get_doc_data()->class_list.begin(); matches.clear(); matched_item = nullptr; match_highest_score = 0; @@ -322,7 +322,7 @@ bool EditorHelpSearch::Runner::_phase_match_classes_init() { } bool EditorHelpSearch::Runner::_phase_match_classes() { - DocData::ClassDoc &class_doc = iterator_doc->value(); + DocData::ClassDoc &class_doc = iterator_doc->value; if (!_is_class_disabled_by_feature_profile(class_doc.name)) { matches[class_doc.name] = ClassMatch(); ClassMatch &match = matches[class_doc.name]; @@ -404,12 +404,12 @@ bool EditorHelpSearch::Runner::_phase_match_classes() { matches[class_doc.name] = match; } - iterator_doc = iterator_doc->next(); + ++iterator_doc; return !iterator_doc; } bool EditorHelpSearch::Runner::_phase_class_items_init() { - iterator_match = matches.front(); + iterator_match = matches.begin(); results_tree->clear(); root_item = results_tree->create_item(); @@ -419,7 +419,7 @@ bool EditorHelpSearch::Runner::_phase_class_items_init() { } bool EditorHelpSearch::Runner::_phase_class_items() { - ClassMatch &match = iterator_match->value(); + ClassMatch &match = iterator_match->value; if (search_flags & SEARCH_SHOW_HIERARCHY) { if (match.required()) { @@ -431,18 +431,18 @@ bool EditorHelpSearch::Runner::_phase_class_items() { } } - iterator_match = iterator_match->next(); + ++iterator_match; return !iterator_match; } bool EditorHelpSearch::Runner::_phase_member_items_init() { - iterator_match = matches.front(); + iterator_match = matches.begin(); return true; } bool EditorHelpSearch::Runner::_phase_member_items() { - ClassMatch &match = iterator_match->value(); + ClassMatch &match = iterator_match->value; TreeItem *parent = (search_flags & SEARCH_SHOW_HIERARCHY) ? class_items[match.doc->name] : root_item; bool constructor_created = false; @@ -473,7 +473,7 @@ bool EditorHelpSearch::Runner::_phase_member_items() { _create_theme_property_item(parent, match.doc, match.theme_properties[i]); } - iterator_match = iterator_match->next(); + ++iterator_match; return !iterator_match; } diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h index d89bb0959c..7b7235145a 100644 --- a/editor/editor_help_search.h +++ b/editor/editor_help_search.h @@ -31,7 +31,7 @@ #ifndef EDITOR_HELP_SEARCH_H #define EDITOR_HELP_SEARCH_H -#include "core/templates/ordered_hash_map.h" +#include "core/templates/rb_map.h" #include "editor/code_editor.h" #include "editor/editor_help.h" #include "editor/editor_plugin.h" @@ -122,11 +122,11 @@ class EditorHelpSearch::Runner : public RefCounted { Ref<Texture2D> empty_icon; Color disabled_color; - Map<String, DocData::ClassDoc>::Element *iterator_doc = nullptr; - Map<String, ClassMatch> matches; - Map<String, ClassMatch>::Element *iterator_match = nullptr; + HashMap<String, DocData::ClassDoc>::Iterator iterator_doc; + HashMap<String, ClassMatch> matches; + HashMap<String, ClassMatch>::Iterator iterator_match; TreeItem *root_item = nullptr; - Map<String, TreeItem *> class_items; + HashMap<String, TreeItem *> class_items; TreeItem *matched_item = nullptr; float match_highest_score = 0; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 5db1ef4b2b..f534130735 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -839,7 +839,7 @@ void EditorProperty::_update_pin_flags() { } pin_hidden = false; { - Set<StringName> storable_properties; + RBSet<StringName> storable_properties; node->get_storable_properties(storable_properties); if (storable_properties.has(node->get_property_store_alias(property))) { can_pin = true; @@ -2445,8 +2445,8 @@ void EditorInspector::update_tree() { object->get_property_list(&plist, true); _update_script_class_properties(*object, plist); - Map<VBoxContainer *, HashMap<String, VBoxContainer *>> vbox_per_path; - Map<String, EditorInspectorArray *> editor_inspector_array_per_prefix; + HashMap<VBoxContainer *, HashMap<String, VBoxContainer *>> vbox_per_path; + HashMap<String, EditorInspectorArray *> editor_inspector_array_per_prefix; Color sscolor = get_theme_color(SNAME("prop_subsection"), SNAME("Editor")); @@ -2563,9 +2563,9 @@ void EditorInspector::update_tree() { if (!class_descr_cache.has(type2)) { String descr; DocTools *dd = EditorHelp::get_doc_data(); - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(type2); + HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(type2); if (E) { - descr = DTR(E->get().brief_description); + descr = DTR(E->value.brief_description); } class_descr_cache[type2] = descr; } @@ -2607,9 +2607,9 @@ void EditorInspector::update_tree() { // First check if we have an array that fits the prefix. String array_prefix = ""; int array_index = -1; - for (Map<String, EditorInspectorArray *>::Element *E = editor_inspector_array_per_prefix.front(); E; E = E->next()) { - if (p.name.begins_with(E->key()) && E->key().length() > array_prefix.length()) { - array_prefix = E->key(); + for (KeyValue<String, EditorInspectorArray *> &E : editor_inspector_array_per_prefix) { + if (p.name.begins_with(E.key) && E.key.length() > array_prefix.length()) { + array_prefix = E.key; } } @@ -2851,39 +2851,39 @@ void EditorInspector::update_tree() { bool found = false; // Search for the property description in the cache. - Map<StringName, Map<StringName, String>>::Element *E = descr_cache.find(classname); + HashMap<StringName, HashMap<StringName, String>>::Iterator E = descr_cache.find(classname); if (E) { - Map<StringName, String>::Element *F = E->get().find(propname); + HashMap<StringName, String>::Iterator F = E->value.find(propname); if (F) { found = true; - descr = F->get(); + descr = F->value; } } if (!found) { // Build the property description String and add it to the cache. DocTools *dd = EditorHelp::get_doc_data(); - Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(classname); + HashMap<String, DocData::ClassDoc>::Iterator F = dd->class_list.find(classname); while (F && descr.is_empty()) { - for (int i = 0; i < F->get().properties.size(); i++) { - if (F->get().properties[i].name == propname.operator String()) { - descr = DTR(F->get().properties[i].description); + for (int i = 0; i < F->value.properties.size(); i++) { + if (F->value.properties[i].name == propname.operator String()) { + descr = DTR(F->value.properties[i].description); break; } } Vector<String> slices = propname.operator String().split("/"); if (slices.size() == 2 && slices[0].begins_with("theme_override_")) { - for (int i = 0; i < F->get().theme_properties.size(); i++) { - if (F->get().theme_properties[i].name == slices[1]) { - descr = DTR(F->get().theme_properties[i].description); + for (int i = 0; i < F->value.theme_properties.size(); i++) { + if (F->value.theme_properties[i].name == slices[1]) { + descr = DTR(F->value.theme_properties[i].description); break; } } } - if (!F->get().inherits.is_empty()) { - F = dd->class_list.find(F->get().inherits); + if (!F->value.inherits.is_empty()) { + F = dd->class_list.find(F->value.inherits); } else { break; } @@ -3638,7 +3638,7 @@ void EditorInspector::_update_script_class_properties(const Object &p_object, Li break; } - Set<StringName> added; + RBSet<StringName> added; for (const Ref<Script> &s : classes) { String path = s->get_path(); String name = EditorNode::get_editor_data().script_class_get_name(path); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 75536a5a24..7609f4fdcc 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -117,7 +117,7 @@ private: mutable String tooltip_text; - Map<StringName, Variant> cache; + HashMap<StringName, Variant> cache; GDVIRTUAL0(_update_property) void _update_pin_flags(); @@ -435,9 +435,9 @@ class EditorInspector : public ScrollContainer { VBoxContainer *main_vbox = nullptr; //map use to cache the instantiated editors - Map<StringName, List<EditorProperty *>> editor_property_map; + HashMap<StringName, List<EditorProperty *>> editor_property_map; List<EditorInspectorSection *> sections; - Set<StringName> pending; + RBSet<StringName> pending; void _clear(); Object *object = nullptr; @@ -468,11 +468,11 @@ class EditorInspector : public ScrollContainer { int property_focusable; int update_scroll_request; - Map<StringName, Map<StringName, String>> descr_cache; - Map<StringName, String> class_descr_cache; - Set<StringName> restart_request_props; + HashMap<StringName, HashMap<StringName, String>> descr_cache; + HashMap<StringName, String> class_descr_cache; + RBSet<StringName> restart_request_props; - Map<ObjectID, int> scroll_cache; + HashMap<ObjectID, int> scroll_cache; String property_prefix; //used for sectioned inspector String object_class; @@ -496,7 +496,7 @@ class EditorInspector : public ScrollContainer { void _node_removed(Node *p_node); - Map<StringName, int> per_array_page; + HashMap<StringName, int> per_array_page; void _page_change_request(int p_new_page, const StringName &p_array_prefix); void _changed_callback(); diff --git a/editor/editor_log.h b/editor/editor_log.h index 267ad406d4..de0368501c 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -115,7 +115,7 @@ private: Vector<LogMessage> messages; // Maps MessageTypes to LogFilters for convenient access and storage (don't need 1 member per filter). - Map<MessageType, LogFilter *> type_filter_map; + HashMap<MessageType, LogFilter *> type_filter_map; RichTextLabel *log = nullptr; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 194021669f..0b96900053 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -215,12 +215,12 @@ static const String META_TEXT_TO_COPY = "text_to_copy"; void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames) { // Keep track of a list of "index sets," i.e. sets of indices // within disambiguated_scene_names which contain the same name. - Vector<Set<int>> index_sets; - Map<String, int> scene_name_to_set_index; + Vector<RBSet<int>> index_sets; + HashMap<String, int> scene_name_to_set_index; for (int i = 0; i < r_filenames.size(); i++) { String scene_name = r_filenames[i]; if (!scene_name_to_set_index.has(scene_name)) { - index_sets.append(Set<int>()); + index_sets.append(RBSet<int>()); scene_name_to_set_index.insert(r_filenames[i], index_sets.size() - 1); } index_sets.write[scene_name_to_set_index[scene_name]].insert(i); @@ -228,10 +228,10 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto // For each index set with a size > 1, we need to disambiguate. for (int i = 0; i < index_sets.size(); i++) { - Set<int> iset = index_sets[i]; + RBSet<int> iset = index_sets[i]; while (iset.size() > 1) { // Append the parent folder to each scene name. - for (Set<int>::Element *E = iset.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = iset.front(); E; E = E->next()) { int set_idx = E->get(); String scene_name = r_filenames[set_idx]; String full_path = p_full_paths[set_idx]; @@ -266,11 +266,11 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto // Loop back through scene names and remove non-ambiguous names. bool can_proceed = false; - Set<int>::Element *E = iset.front(); + RBSet<int>::Element *E = iset.front(); while (E) { String scene_name = r_filenames[E->get()]; bool duplicate_found = false; - for (Set<int>::Element *F = iset.front(); F; F = F->next()) { + for (RBSet<int>::Element *F = iset.front(); F; F = F->next()) { if (E->get() == F->get()) { continue; } @@ -281,7 +281,7 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto } } - Set<int>::Element *to_erase = duplicate_found ? nullptr : E; + RBSet<int>::Element *to_erase = duplicate_found ? nullptr : E; // We need to check that we could actually append anymore names // if we wanted to for disambiguation. If we can't, then we have @@ -623,8 +623,6 @@ void EditorNode::_notification(int p_what) { ResourceImporterTexture::get_singleton()->update_imports(); - // if using a main thread only renderer, we need to update the resource previews - EditorResourcePreview::get_singleton()->update(); } break; case NOTIFICATION_ENTER_TREE: { @@ -802,7 +800,7 @@ void EditorNode::_notification(int p_what) { main_editor_buttons.write[i]->add_theme_font_size_override("font_size", gui_base->get_theme_font_size(SNAME("main_button_font_size"), SNAME("EditorFonts"))); } - Set<String> updated_textfile_extensions; + RBSet<String> updated_textfile_extensions; bool extensions_match = true; const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); for (const String &E : textfile_ext) { @@ -909,11 +907,11 @@ void EditorNode::_resources_changed(const Vector<String> &p_resources) { } void EditorNode::_fs_changed() { - for (Set<FileDialog *>::Element *E = file_dialogs.front(); E; E = E->next()) { + for (RBSet<FileDialog *>::Element *E = file_dialogs.front(); E; E = E->next()) { E->get()->invalidate(); } - for (Set<EditorFileDialog *>::Element *E = editor_file_dialogs.front(); E; E = E->next()) { + for (RBSet<EditorFileDialog *>::Element *E = editor_file_dialogs.front(); E; E = E->next()) { E->get()->invalidate(); } @@ -1187,7 +1185,7 @@ Error EditorNode::load_resource(const String &p_resource, bool p_ignore_broken_d if (!p_ignore_broken_deps && dependency_errors.has(p_resource)) { Vector<String> errors; - for (Set<String>::Element *E = dependency_errors[p_resource].front(); E; E = E->next()) { + for (RBSet<String>::Element *E = dependency_errors[p_resource].front(); E; E = E->next()) { errors.push_back(E->get()); } dependency_error->show(DependencyErrorDialog::MODE_RESOURCE, p_resource, errors); @@ -1419,7 +1417,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) { ERR_FAIL_COND_MSG(err != OK, "Cannot save config file to '" + path + "'."); } -bool EditorNode::_find_and_save_resource(Ref<Resource> p_res, Map<Ref<Resource>, bool> &processed, int32_t flags) { +bool EditorNode::_find_and_save_resource(Ref<Resource> p_res, HashMap<Ref<Resource>, bool> &processed, int32_t flags) { if (p_res.is_null()) { return false; } @@ -1445,7 +1443,7 @@ bool EditorNode::_find_and_save_resource(Ref<Resource> p_res, Map<Ref<Resource>, } } -bool EditorNode::_find_and_save_edited_subresources(Object *obj, Map<Ref<Resource>, bool> &processed, int32_t flags) { +bool EditorNode::_find_and_save_edited_subresources(Object *obj, HashMap<Ref<Resource>, bool> &processed, int32_t flags) { bool ret_changed = false; List<PropertyInfo> pi; obj->get_property_list(&pi); @@ -1495,7 +1493,7 @@ bool EditorNode::_find_and_save_edited_subresources(Object *obj, Map<Ref<Resourc return ret_changed; } -void EditorNode::_save_edited_subresources(Node *scene, Map<Ref<Resource>, bool> &processed, int32_t flags) { +void EditorNode::_save_edited_subresources(Node *scene, HashMap<Ref<Resource>, bool> &processed, int32_t flags) { _find_and_save_edited_subresources(scene, processed, flags); for (int i = 0; i < scene->get_child_count(); i++) { @@ -1624,7 +1622,7 @@ bool EditorNode::_validate_scene_recursive(const String &p_filename, Node *p_nod return false; } -static bool _find_edited_resources(const Ref<Resource> &p_resource, Set<Ref<Resource>> &edited_resources) { +static bool _find_edited_resources(const Ref<Resource> &p_resource, RBSet<Ref<Resource>> &edited_resources) { if (p_resource->is_edited()) { edited_resources.insert(p_resource); return true; @@ -1661,7 +1659,7 @@ int EditorNode::_save_external_resources() { } flg |= ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS; - Set<Ref<Resource>> edited_subresources; + RBSet<Ref<Resource>> edited_subresources; int saved = 0; List<Ref<Resource>> cached; ResourceCache::get_cached_resources(&cached); @@ -1679,7 +1677,7 @@ int EditorNode::_save_external_resources() { // Clear later, because user may have put the same subresource in two different resources, // which will be shared until the next reload. - for (Set<Ref<Resource>>::Element *E = edited_subresources.front(); E; E = E->next()) { + for (RBSet<Ref<Resource>>::Element *E = edited_subresources.front(); E; E = E->next()) { Ref<Resource> res = E->get(); res->set_edited(false); } @@ -2127,7 +2125,7 @@ void EditorNode::_save_default_environment() { Ref<Environment> fallback = get_tree()->get_root()->get_world_3d()->get_fallback_environment(); if (fallback.is_valid() && fallback->get_path().is_resource_file()) { - Map<Ref<Resource>, bool> processed; + HashMap<Ref<Resource>, bool> processed; _find_and_save_edited_subresources(fallback.ptr(), processed, 0); save_resource_in_path(fallback, fallback->get_path()); } @@ -2305,7 +2303,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) { if (main_plugin) { // Special case if use of external editor is true. Resource *current_res = Object::cast_to<Resource>(current_obj); - if (main_plugin->get_name() == "Script" && current_obj->is_class("VisualScript") && current_res && !current_res->is_built_in() && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { + if (main_plugin->get_name() == "Script" && !current_obj->is_class("VisualScript") && current_res && !current_res->is_built_in() && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { if (!changing_scene) { main_plugin->edit(current_obj); } @@ -3665,7 +3663,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b if (!p_ignore_broken_deps && dependency_errors.has(lpath)) { current_menu_option = -1; Vector<String> errors; - for (Set<String>::Element *E = dependency_errors[lpath].front(); E; E = E->next()) { + for (RBSet<String>::Element *E = dependency_errors[lpath].front(); E; E = E->next()) { errors.push_back(E->get()); } dependency_error->show(DependencyErrorDialog::MODE_SCENE, lpath, errors); @@ -3680,9 +3678,9 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b dependency_errors.erase(lpath); // At least not self path. - for (KeyValue<String, Set<String>> &E : dependency_errors) { + for (KeyValue<String, RBSet<String>> &E : dependency_errors) { String txt = vformat(TTR("Scene '%s' has broken dependencies:"), E.key) + "\n"; - for (Set<String>::Element *F = E.value.front(); F; F = F->next()) { + for (RBSet<String>::Element *F = E.value.front(); F; F = F->next()) { txt += "\t" + F->get() + "\n"; } add_io_error(txt); @@ -4145,7 +4143,7 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } } - const Map<String, Vector<EditorData::CustomType>> &p_map = EditorNode::get_editor_data().get_custom_types(); + const HashMap<String, Vector<EditorData::CustomType>> &p_map = EditorNode::get_editor_data().get_custom_types(); for (const KeyValue<String, Vector<EditorData::CustomType>> &E : p_map) { const Vector<EditorData::CustomType> &ct = E.value; for (int i = 0; i < ct.size(); ++i) { diff --git a/editor/editor_node.h b/editor/editor_node.h index 0d154123b3..9cd96050e3 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -273,7 +273,7 @@ private: Vector<EditorPlugin *> editor_plugins; bool _initializing_plugins = false; - Map<String, EditorPlugin *> addon_name_to_plugin; + HashMap<String, EditorPlugin *> addon_name_to_plugin; PanelContainer *scene_root_parent = nullptr; Control *theme_base = nullptr; @@ -394,7 +394,7 @@ private: BackgroundProgress *progress_hb = nullptr; DependencyErrorDialog *dependency_error = nullptr; - Map<String, Set<String>> dependency_errors; + HashMap<String, RBSet<String>> dependency_errors; DependencyEditor *dependency_fixer = nullptr; OrphanResourcesDialog *orphan_resources = nullptr; ConfirmationDialog *open_imported = nullptr; @@ -470,15 +470,15 @@ private: String import_reload_fn; - Set<String> textfile_extensions; - Set<FileDialog *> file_dialogs; - Set<EditorFileDialog *> editor_file_dialogs; + RBSet<String> textfile_extensions; + RBSet<FileDialog *> file_dialogs; + RBSet<EditorFileDialog *> editor_file_dialogs; Vector<Ref<EditorResourceConversionPlugin>> resource_conversion_plugins; PrintHandlerList print_handler; - Map<String, Ref<Texture2D>> icon_type_cache; - Map<Ref<Script>, Ref<Texture>> script_icon_cache; + HashMap<String, Ref<Texture2D>> icon_type_cache; + HashMap<Ref<Script>, Ref<Texture>> script_icon_cache; static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS]; static EditorPluginInitializeCallback plugin_init_callbacks[MAX_INIT_CALLBACKS]; @@ -489,7 +489,7 @@ private: static void _dependency_error_report(void *ud, const String &p_path, const String &p_dep, const String &p_type) { EditorNode *en = static_cast<EditorNode *>(ud); if (!en->dependency_errors.has(p_path)) { - en->dependency_errors[p_path] = Set<String>(); + en->dependency_errors[p_path] = RBSet<String>(); } en->dependency_errors[p_path].insert(p_dep + "::" + p_type); } @@ -594,9 +594,9 @@ private: void _remove_edited_scene(bool p_change_tab = true); void _remove_scene(int index, bool p_change_tab = true); - bool _find_and_save_resource(Ref<Resource> p_res, Map<Ref<Resource>, bool> &processed, int32_t flags); - bool _find_and_save_edited_subresources(Object *obj, Map<Ref<Resource>, bool> &processed, int32_t flags); - void _save_edited_subresources(Node *scene, Map<Ref<Resource>, bool> &processed, int32_t flags); + bool _find_and_save_resource(Ref<Resource> p_res, HashMap<Ref<Resource>, bool> &processed, int32_t flags); + bool _find_and_save_edited_subresources(Object *obj, HashMap<Ref<Resource>, bool> &processed, int32_t flags); + void _save_edited_subresources(Node *scene, HashMap<Ref<Resource>, bool> &processed, int32_t flags); void _mark_unsaved_scenes(); void _find_node_types(Node *p_node, int &count_2d, int &count_3d); diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index b728ce64c9..85a906ef51 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -200,12 +200,9 @@ EditorPluginSettings::EditorPluginSettings() { l->set_theme_type_variation("HeaderSmall"); title_hb->add_child(l); title_hb->add_spacer(); - create_plugin = memnew(Button(TTR("Create"))); + Button *create_plugin = memnew(Button(TTR("Create New Plugin"))); create_plugin->connect("pressed", callable_mp(this, &EditorPluginSettings::_create_clicked)); title_hb->add_child(create_plugin); - update_list = memnew(Button(TTR("Update"))); - update_list->connect("pressed", callable_mp(this, &EditorPluginSettings::update_plugins)); - title_hb->add_child(update_list); add_child(title_hb); plugin_list = memnew(Tree); diff --git a/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h index 826bb8c00f..121534b613 100644 --- a/editor/editor_plugin_settings.h +++ b/editor/editor_plugin_settings.h @@ -45,8 +45,6 @@ class EditorPluginSettings : public VBoxContainer { }; PluginConfigDialog *plugin_config_dialog = nullptr; - Button *create_plugin = nullptr; - Button *update_list = nullptr; Tree *plugin_list = nullptr; bool updating = false; diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp index 1e222c02a3..ba6585dfcc 100644 --- a/editor/editor_property_name_processor.cpp +++ b/editor/editor_property_name_processor.cpp @@ -57,16 +57,16 @@ bool EditorPropertyNameProcessor::is_localization_available() { } String EditorPropertyNameProcessor::_capitalize_name(const String &p_name) const { - const Map<String, String>::Element *cached = capitalize_string_cache.find(p_name); + HashMap<String, String>::ConstIterator cached = capitalize_string_cache.find(p_name); if (cached) { - return cached->value(); + return cached->value; } Vector<String> parts = p_name.split("_", false); for (int i = 0; i < parts.size(); i++) { - const Map<String, String>::Element *remap = capitalize_string_remaps.find(parts[i]); + HashMap<String, String>::ConstIterator remap = capitalize_string_remaps.find(parts[i]); if (remap) { - parts.write[i] = remap->get(); + parts.write[i] = remap->value; } else { parts.write[i] = parts[i].capitalize(); } @@ -207,6 +207,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["ssh"] = "SSH"; capitalize_string_remaps["ssil"] = "SSIL"; capitalize_string_remaps["ssl"] = "SSL"; + capitalize_string_remaps["sss"] = "SSS"; capitalize_string_remaps["stderr"] = "stderr"; capitalize_string_remaps["stdout"] = "stdout"; capitalize_string_remaps["sv"] = "SV"; diff --git a/editor/editor_property_name_processor.h b/editor/editor_property_name_processor.h index 351736550f..37d905c806 100644 --- a/editor/editor_property_name_processor.h +++ b/editor/editor_property_name_processor.h @@ -38,8 +38,8 @@ class EditorPropertyNameProcessor : public Node { static EditorPropertyNameProcessor *singleton; - mutable Map<String, String> capitalize_string_cache; - Map<String, String> capitalize_string_remaps; + mutable HashMap<String, String> capitalize_string_cache; + HashMap<String, String> capitalize_string_remaps; // Capitalizes property path segments. String _capitalize_name(const String &p_name) const; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 3158c03dcc..41d769ad1f 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -240,7 +240,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) { ResourceLoader::get_recognized_extensions_for_type(base, &extensions); } - Set<String> valid_extensions; + RBSet<String> valid_extensions; for (const String &E : extensions) { valid_extensions.insert(E); } @@ -253,7 +253,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) { } file_dialog->clear_filters(); - for (Set<String>::Element *E = valid_extensions.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = valid_extensions.front(); E; E = E->next()) { file_dialog->add_filter("*." + E->get() + " ; " + E->get().to_upper()); } @@ -409,7 +409,7 @@ void EditorResourcePicker::set_create_options(Object *p_menu_node) { if (!base_type.is_empty()) { int idx = 0; - Set<String> allowed_types; + RBSet<String> allowed_types; _get_allowed_types(false, &allowed_types); Vector<EditorData::CustomType> custom_resources; @@ -417,7 +417,7 @@ void EditorResourcePicker::set_create_options(Object *p_menu_node) { custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"]; } - for (Set<String>::Element *E = allowed_types.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = allowed_types.front(); E; E = E->next()) { const String &t = E->get(); bool is_custom_resource = false; @@ -491,7 +491,7 @@ void EditorResourcePicker::_button_input(const Ref<InputEvent> &p_event) { } } -void EditorResourcePicker::_get_allowed_types(bool p_with_convert, Set<String> *p_vector) const { +void EditorResourcePicker::_get_allowed_types(bool p_with_convert, RBSet<String> *p_vector) const { Vector<String> allowed_types = base_type.split(","); int size = allowed_types.size(); @@ -568,7 +568,7 @@ bool EditorResourcePicker::_is_drop_valid(const Dictionary &p_drag_data) const { res = drag_data["resource"]; } - Set<String> allowed_types; + RBSet<String> allowed_types; _get_allowed_types(true, &allowed_types); if (res.is_valid() && _is_type_valid(res->get_class(), allowed_types)) { @@ -598,8 +598,8 @@ bool EditorResourcePicker::_is_drop_valid(const Dictionary &p_drag_data) const { return false; } -bool EditorResourcePicker::_is_type_valid(const String p_type_name, Set<String> p_allowed_types) const { - for (Set<String>::Element *E = p_allowed_types.front(); E; E = E->next()) { +bool EditorResourcePicker::_is_type_valid(const String p_type_name, RBSet<String> p_allowed_types) const { + for (RBSet<String>::Element *E = p_allowed_types.front(); E; E = E->next()) { String at = E->get().strip_edges(); if (p_type_name == at || ClassDB::is_parent_class(p_type_name, at) || EditorNode::get_editor_data().script_class_is_parent(p_type_name, at)) { return true; @@ -646,12 +646,12 @@ void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_ } if (dropped_resource.is_valid()) { - Set<String> allowed_types; + RBSet<String> allowed_types; _get_allowed_types(false, &allowed_types); // If the accepted dropped resource is from the extended list, it requires conversion. if (!_is_type_valid(dropped_resource->get_class(), allowed_types)) { - for (Set<String>::Element *E = allowed_types.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = allowed_types.front(); E; E = E->next()) { String at = E->get().strip_edges(); if (at == "BaseMaterial3D" && Ref<Texture2D>(dropped_resource).is_valid()) { @@ -768,7 +768,7 @@ void EditorResourcePicker::set_base_type(const String &p_base_type) { // There is a possibility that the new base type is conflicting with the existing value. // Keep the value, but warn the user that there is a potential mistake. if (!base_type.is_empty() && edited_resource.is_valid()) { - Set<String> allowed_types; + RBSet<String> allowed_types; _get_allowed_types(true, &allowed_types); StringName custom_class; @@ -784,7 +784,7 @@ void EditorResourcePicker::set_base_type(const String &p_base_type) { } } else { // Call the method to build the cache immediately. - Set<String> allowed_types; + RBSet<String> allowed_types; _get_allowed_types(false, &allowed_types); } } @@ -794,7 +794,7 @@ String EditorResourcePicker::get_base_type() const { } Vector<String> EditorResourcePicker::get_allowed_types() const { - Set<String> allowed_types; + RBSet<String> allowed_types; _get_allowed_types(false, &allowed_types); Vector<String> types; @@ -802,7 +802,7 @@ Vector<String> EditorResourcePicker::get_allowed_types() const { int i = 0; String *w = types.ptrw(); - for (Set<String>::Element *E = allowed_types.front(); E; E = E->next(), i++) { + for (RBSet<String>::Element *E = allowed_types.front(); E; E = E->next(), i++) { w[i] = E->get(); } @@ -817,7 +817,7 @@ void EditorResourcePicker::set_edited_resource(Ref<Resource> p_resource) { } if (!base_type.is_empty()) { - Set<String> allowed_types; + RBSet<String> allowed_types; _get_allowed_types(true, &allowed_types); StringName custom_class; diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h index e63280e3b6..f2dc45513d 100644 --- a/editor/editor_resource_picker.h +++ b/editor/editor_resource_picker.h @@ -89,9 +89,9 @@ class EditorResourcePicker : public HBoxContainer { void _button_draw(); void _button_input(const Ref<InputEvent> &p_event); - void _get_allowed_types(bool p_with_convert, Set<String> *p_vector) const; + void _get_allowed_types(bool p_with_convert, RBSet<String> *p_vector) const; bool _is_drop_valid(const Dictionary &p_drag_data) const; - bool _is_type_valid(const String p_type_name, Set<String> p_allowed_types) const; + bool _is_type_valid(const String p_type_name, RBSet<String> p_allowed_types) const; Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 6d5b20e591..dffb378408 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -430,12 +430,8 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) { } void EditorResourcePreview::start() { - if (OS::get_singleton()->get_render_main_thread_mode() == OS::RENDER_ANY_THREAD) { - ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started."); - thread.start(_thread_func, this); - } else { - _mainthread_only = true; - } + ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started."); + thread.start(_thread_func, this); } void EditorResourcePreview::stop() { @@ -458,18 +454,3 @@ EditorResourcePreview::EditorResourcePreview() { EditorResourcePreview::~EditorResourcePreview() { stop(); } - -void EditorResourcePreview::update() { - if (!_mainthread_only) { - return; - } - - if (!exit.is_set()) { - // no need to even lock the mutex if the size is zero - // there is no problem if queue.size() is wrong, even if - // there was a race condition. - if (queue.size()) { - _iterate(); - } - } -} diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h index 769340c36f..820e22bdc8 100644 --- a/editor/editor_resource_preview.h +++ b/editor/editor_resource_preview.h @@ -81,11 +81,6 @@ class EditorResourcePreview : public Node { SafeFlag exit; SafeFlag exited; - // when running from GLES, we want to run the previews - // in the main thread using an update, rather than create - // a separate thread - bool _mainthread_only = false; - struct Item { Ref<Texture2D> preview; Ref<Texture2D> small_preview; @@ -96,7 +91,7 @@ class EditorResourcePreview : public Node { int order; - Map<String, Item> cache; + HashMap<String, Item> cache; void _preview_ready(const String &p_str, const Ref<Texture2D> &p_texture, const Ref<Texture2D> &p_small_texture, ObjectID id, const StringName &p_func, const Variant &p_ud); void _generate_preview(Ref<ImageTexture> &r_texture, Ref<ImageTexture> &r_small_texture, const QueueItem &p_item, const String &cache_base); @@ -125,9 +120,6 @@ public: void start(); void stop(); - // for single threaded mode - void update(); - EditorResourcePreview(); ~EditorResourcePreview(); }; diff --git a/editor/editor_run_native.h b/editor/editor_run_native.h index 4cb5779350..798a0371a4 100644 --- a/editor/editor_run_native.h +++ b/editor/editor_run_native.h @@ -37,7 +37,7 @@ class EditorRunNative : public HBoxContainer { GDCLASS(EditorRunNative, HBoxContainer); - Map<int, MenuButton *> menus; + HashMap<int, MenuButton *> menus; bool first = true; int resume_idx; diff --git a/editor/editor_sectioned_inspector.h b/editor/editor_sectioned_inspector.h index 0ccffa0048..babd11eb69 100644 --- a/editor/editor_sectioned_inspector.h +++ b/editor/editor_sectioned_inspector.h @@ -45,7 +45,7 @@ class SectionedInspector : public HSplitContainer { Tree *sections = nullptr; SectionedInspectorFilter *filter = nullptr; - Map<String, TreeItem *> section_map; + HashMap<String, TreeItem *> section_map; EditorInspector *inspector = nullptr; LineEdit *search_box = nullptr; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index bdabff20f9..e251a66610 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -141,7 +141,7 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const { if (p_name == "shortcuts") { Array save_array; - const OrderedHashMap<String, List<Ref<InputEvent>>> &builtin_list = InputMap::get_singleton()->get_builtins(); + const HashMap<String, List<Ref<InputEvent>>> &builtin_list = InputMap::get_singleton()->get_builtins(); for (const KeyValue<String, Ref<Shortcut>> &shortcut_definition : shortcuts) { Ref<Shortcut> sc = shortcut_definition.value; @@ -244,18 +244,17 @@ struct _EVCSort { void EditorSettings::_get_property_list(List<PropertyInfo> *p_list) const { _THREAD_SAFE_METHOD_ - const String *k = nullptr; - Set<_EVCSort> vclist; + RBSet<_EVCSort> vclist; - while ((k = props.next(k))) { - const VariantContainer *v = props.getptr(*k); + for (const KeyValue<String, VariantContainer> &E : props) { + const VariantContainer *v = &E.value; if (v->hide_from_editor) { continue; } _EVCSort vc; - vc.name = *k; + vc.name = E.key; vc.order = v->order; vc.type = v->variant.get_type(); vc.save = v->save; @@ -269,7 +268,7 @@ void EditorSettings::_get_property_list(List<PropertyInfo> *p_list) const { vclist.insert(vc); } - for (Set<_EVCSort>::Element *E = vclist.front(); E; E = E->next()) { + for (RBSet<_EVCSort>::Element *E = vclist.front(); E; E = E->next()) { uint32_t pusage = PROPERTY_USAGE_NONE; if (E->get().save || !optimize_save) { pusage |= PROPERTY_USAGE_STORAGE; @@ -682,6 +681,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Visual editors EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/minimap_opacity", 0.85, "0.0,1.0,0.01") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/visual_editors/visualshader/port_preview_size", 160, "100,400,0.01") /* Run */ @@ -789,7 +789,11 @@ bool EditorSettings::_save_text_editor_theme(String p_file) { Ref<ConfigFile> cf = memnew(ConfigFile); // hex is better? List<String> keys; - props.get_key_list(&keys); + + for (const KeyValue<String, VariantContainer> &E : props) { + keys.push_back(E.key); + } + keys.sort(); for (const String &key : keys) { @@ -1396,35 +1400,35 @@ void EditorSettings::add_shortcut(const String &p_name, const Ref<Shortcut> &p_s } bool EditorSettings::is_shortcut(const String &p_name, const Ref<InputEvent> &p_event) const { - const Map<String, Ref<Shortcut>>::Element *E = shortcuts.find(p_name); + HashMap<String, Ref<Shortcut>>::ConstIterator E = shortcuts.find(p_name); ERR_FAIL_COND_V_MSG(!E, false, "Unknown Shortcut: " + p_name + "."); - return E->get()->matches_event(p_event); + return E->value->matches_event(p_event); } Ref<Shortcut> EditorSettings::get_shortcut(const String &p_name) const { - const Map<String, Ref<Shortcut>>::Element *SC = shortcuts.find(p_name); + HashMap<String, Ref<Shortcut>>::ConstIterator SC = shortcuts.find(p_name); if (SC) { - return SC->get(); + return SC->value; } // If no shortcut with the provided name is found in the list, check the built-in shortcuts. // Use the first item in the action list for the shortcut event, since a shortcut can only have 1 linked event. Ref<Shortcut> sc; - const Map<String, List<Ref<InputEvent>>>::Element *builtin_override = builtin_action_overrides.find(p_name); + HashMap<String, List<Ref<InputEvent>>>::ConstIterator builtin_override = builtin_action_overrides.find(p_name); if (builtin_override) { sc.instantiate(); - sc->set_events_list(&builtin_override->get()); + sc->set_events_list(&builtin_override->value); sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name)); } // If there was no override, check the default builtins to see if it has an InputEvent for the provided name. if (sc.is_null()) { - const OrderedHashMap<String, List<Ref<InputEvent>>>::ConstElement builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name); + HashMap<String, List<Ref<InputEvent>>>::ConstIterator builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name); if (builtin_default) { sc.instantiate(); - sc->set_events_list(&builtin_default.get()); + sc->set_events_list(&builtin_default->value); sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name)); } } @@ -1562,9 +1566,9 @@ void EditorSettings::set_builtin_action_override(const String &p_name, const Arr // Check if the provided event array is same as built-in. If it is, it does not need to be added to the overrides. // Note that event order must also be the same. bool same_as_builtin = true; - OrderedHashMap<String, List<Ref<InputEvent>>>::ConstElement builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name); + HashMap<String, List<Ref<InputEvent>>>::ConstIterator builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name); if (builtin_default) { - List<Ref<InputEvent>> builtin_events = builtin_default.get(); + const List<Ref<InputEvent>> &builtin_events = builtin_default->value; // In the editor we only care about key events. List<Ref<InputEventKey>> builtin_key_events; @@ -1603,11 +1607,11 @@ void EditorSettings::set_builtin_action_override(const String &p_name, const Arr } const Array EditorSettings::get_builtin_action_overrides(const String &p_name) const { - const Map<String, List<Ref<InputEvent>>>::Element *AO = builtin_action_overrides.find(p_name); + HashMap<String, List<Ref<InputEvent>>>::ConstIterator AO = builtin_action_overrides.find(p_name); if (AO) { Array event_array; - List<Ref<InputEvent>> events_list = AO->get(); + List<Ref<InputEvent>> events_list = AO->value; for (const Ref<InputEvent> &E : events_list) { event_array.push_back(E); } diff --git a/editor/editor_settings.h b/editor/editor_settings.h index d1b9cabfb7..e270a882e2 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -77,15 +77,15 @@ private: static Ref<EditorSettings> singleton; - Set<String> changed_settings; + RBSet<String> changed_settings; HashMap<String, PropertyInfo> hints; HashMap<String, VariantContainer> props; int last_order; Ref<Resource> clipboard; - mutable Map<String, Ref<Shortcut>> shortcuts; - Map<String, List<Ref<InputEvent>>> builtin_action_overrides; + mutable HashMap<String, Ref<Shortcut>> shortcuts; + HashMap<String, List<Ref<InputEvent>>> builtin_action_overrides; String config_file_path; diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index ab029c1d30..fd578bd365 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -248,11 +248,11 @@ void EditorSettingsDialog::_update_shortcut_events(const String &p_path, const A undo_redo->commit_action(); } -Array EditorSettingsDialog::_event_list_to_array_helper(List<Ref<InputEvent>> &p_events) { +Array EditorSettingsDialog::_event_list_to_array_helper(const List<Ref<InputEvent>> &p_events) { Array events; // Convert the list to an array, and only keep key events as this is for the editor. - for (List<Ref<InputEvent>>::Element *E = p_events.front(); E; E = E->next()) { + for (const List<Ref<InputEvent>>::Element *E = p_events.front(); E; E = E->next()) { Ref<InputEventKey> k = E->get(); if (k.is_valid()) { events.append(E->get()); @@ -327,7 +327,7 @@ void EditorSettingsDialog::_create_shortcut_treeitem(TreeItem *p_parent, const S void EditorSettingsDialog::_update_shortcuts() { // Before clearing the tree, take note of which categories are collapsed so that this state can be maintained when the tree is repopulated. - Map<String, bool> collapsed; + HashMap<String, bool> collapsed; if (shortcuts->get_root() && shortcuts->get_root()->get_first_child()) { TreeItem *ti = shortcuts->get_root()->get_first_child(); @@ -359,7 +359,7 @@ void EditorSettingsDialog::_update_shortcuts() { shortcuts->clear(); TreeItem *root = shortcuts->create_item(); - Map<String, TreeItem *> sections; + HashMap<String, TreeItem *> sections; // Set up section for Common/Built-in actions TreeItem *common_section = shortcuts->create_item(root); @@ -374,10 +374,9 @@ void EditorSettingsDialog::_update_shortcuts() { common_section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor"))); // Get the action map for the editor, and add each item to the "Common" section. - OrderedHashMap<StringName, InputMap::Action> action_map = InputMap::get_singleton()->get_action_map(); - for (OrderedHashMap<StringName, InputMap::Action>::Element E = action_map.front(); E; E = E.next()) { - String action_name = E.key(); - InputMap::Action action = E.get(); + for (const KeyValue<StringName, InputMap::Action> &E : InputMap::get_singleton()->get_action_map()) { + const String &action_name = E.key; + const InputMap::Action &action = E.value; Array events; // Need to get the list of events into an array so it can be set as metadata on the item. Vector<String> event_strings; @@ -387,10 +386,10 @@ void EditorSettingsDialog::_update_shortcuts() { continue; } - List<Ref<InputEvent>> all_default_events = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(action_name).value(); + const List<Ref<InputEvent>> &all_default_events = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(action_name)->value; List<Ref<InputEventKey>> key_default_events; // Remove all non-key events from the defaults. Only check keys, since we are in the editor. - for (List<Ref<InputEvent>>::Element *I = all_default_events.front(); I; I = I->next()) { + for (const List<Ref<InputEvent>>::Element *I = all_default_events.front(); I; I = I->next()) { Ref<InputEventKey> k = I->get(); if (k.is_valid()) { key_default_events.push_back(k); diff --git a/editor/editor_settings_dialog.h b/editor/editor_settings_dialog.h index 9a34eac7ef..294186a509 100644 --- a/editor/editor_settings_dialog.h +++ b/editor/editor_settings_dialog.h @@ -89,7 +89,7 @@ class EditorSettingsDialog : public AcceptDialog { void _event_config_confirmed(); void _create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_common, bool p_is_collapsed); - Array _event_list_to_array_helper(List<Ref<InputEvent>> &p_events); + Array _event_list_to_array_helper(const List<Ref<InputEvent>> &p_events); void _update_builtin_action(const String &p_name, const Array &p_events); void _update_shortcut_events(const String &p_path, const Array &p_events); diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index ec8130e862..09e407de57 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -627,10 +627,14 @@ void EditorSpinSlider::_bind_methods() { ClassDB::bind_method(D_METHOD("set_flat", "flat"), &EditorSpinSlider::set_flat); ClassDB::bind_method(D_METHOD("is_flat"), &EditorSpinSlider::is_flat); + ClassDB::bind_method(D_METHOD("set_hide_slider", "hide_slider"), &EditorSpinSlider::set_hide_slider); + ClassDB::bind_method(D_METHOD("is_hiding_slider"), &EditorSpinSlider::is_hiding_slider); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "label"), "set_label", "get_label"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "read_only"), "set_read_only", "is_read_only"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_slider"), "set_hide_slider", "is_hiding_slider"); } void EditorSpinSlider::_ensure_input_popup() { diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 0400aa74b5..3b159d9f3d 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -148,7 +148,7 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = // The names of the icons to never convert, even if one of their colors // are contained in the dictionary above. - Set<StringName> exceptions; + RBSet<StringName> exceptions; // Some of the colors below are listed for completeness sake. // This can be a basis for proper palette validation later. @@ -290,7 +290,7 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = // Use the accent color for some icons (checkbox, radio, toggle, etc.). Dictionary accent_color_icon_color_dictionary; - Set<StringName> accent_color_icons; + RBSet<StringName> accent_color_icons; const Color accent_color = p_theme->get_color(SNAME("accent_color"), SNAME("Editor")); accent_color_icon_color_dictionary[Color::html("699ce8")] = accent_color; @@ -741,17 +741,28 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("pressed", "EditorLogFilterButton", editor_log_button_pressed); // OptionButton - theme->set_stylebox("focus", "OptionButton", style_widget_focus); - + Ref<StyleBoxFlat> style_option_button_focus = style_widget_focus->duplicate(); + Ref<StyleBoxFlat> style_option_button_normal = style_widget->duplicate(); + Ref<StyleBoxFlat> style_option_button_hover = style_widget_hover->duplicate(); + Ref<StyleBoxFlat> style_option_button_pressed = style_widget_pressed->duplicate(); + Ref<StyleBoxFlat> style_option_button_disabled = style_widget_disabled->duplicate(); + + style_option_button_focus->set_default_margin(SIDE_RIGHT, 4 * EDSCALE); + style_option_button_normal->set_default_margin(SIDE_RIGHT, 4 * EDSCALE); + style_option_button_hover->set_default_margin(SIDE_RIGHT, 4 * EDSCALE); + style_option_button_pressed->set_default_margin(SIDE_RIGHT, 4 * EDSCALE); + style_option_button_disabled->set_default_margin(SIDE_RIGHT, 4 * EDSCALE); + + theme->set_stylebox("focus", "OptionButton", style_option_button_focus); theme->set_stylebox("normal", "OptionButton", style_widget); theme->set_stylebox("hover", "OptionButton", style_widget_hover); theme->set_stylebox("pressed", "OptionButton", style_widget_pressed); theme->set_stylebox("disabled", "OptionButton", style_widget_disabled); - theme->set_stylebox("normal_mirrored", "OptionButton", style_widget); - theme->set_stylebox("hover_mirrored", "OptionButton", style_widget_hover); - theme->set_stylebox("pressed_mirrored", "OptionButton", style_widget_pressed); - theme->set_stylebox("disabled_mirrored", "OptionButton", style_widget_disabled); + theme->set_stylebox("normal_mirrored", "OptionButton", style_option_button_normal); + theme->set_stylebox("hover_mirrored", "OptionButton", style_option_button_hover); + theme->set_stylebox("pressed_mirrored", "OptionButton", style_option_button_pressed); + theme->set_stylebox("disabled_mirrored", "OptionButton", style_option_button_disabled); theme->set_color("font_color", "OptionButton", font_color); theme->set_color("font_hover_color", "OptionButton", font_hover_color); @@ -1435,7 +1446,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_minimap_node = make_flat_stylebox(Color(0, 0, 0), 0, 0, 0, 0); } style_minimap_camera->set_border_width_all(1); - style_minimap_node->set_corner_radius_all(1); theme->set_stylebox("camera", "GraphEditMinimap", style_minimap_camera); theme->set_stylebox("node", "GraphEditMinimap", style_minimap_node); @@ -1450,20 +1460,26 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("resizer_color", "GraphEditMinimap", minimap_resizer_color); // GraphNode - const int gn_margin_side = 28; + const int gn_margin_side = 2; + const int gn_margin_bottom = 2; - Ref<StyleBoxFlat> graphsb = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.7), gn_margin_side, 24, gn_margin_side, 5, corner_width); + Color graphnode_bg = dark_color_3; + if (!dark_theme) { + graphnode_bg = prop_section_color; + } + + Ref<StyleBoxFlat> graphsb = make_flat_stylebox(graphnode_bg.lerp(style_tree_bg->get_bg_color(), 0.3), gn_margin_side, 24, gn_margin_side, gn_margin_bottom, corner_width); graphsb->set_border_width_all(border_width); - graphsb->set_border_color(dark_color_3); - Ref<StyleBoxFlat> graphsbselected = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.9), gn_margin_side, 24, gn_margin_side, 5, corner_width); + graphsb->set_border_color(graphnode_bg); + Ref<StyleBoxFlat> graphsbselected = make_flat_stylebox(graphnode_bg * Color(1, 1, 1, 1), gn_margin_side, 24, gn_margin_side, gn_margin_bottom, corner_width); graphsbselected->set_border_width_all(2 * EDSCALE + border_width); - graphsbselected->set_border_color(Color(accent_color.r, accent_color.g, accent_color.b, 0.9)); - Ref<StyleBoxFlat> graphsbcomment = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.3), gn_margin_side, 24, gn_margin_side, 5, corner_width); + graphsbselected->set_border_color(Color(accent_color.r, accent_color.g, accent_color.b, 0.6)); + Ref<StyleBoxFlat> graphsbcomment = make_flat_stylebox(graphnode_bg * Color(1, 1, 1, 0.3), gn_margin_side, 24, gn_margin_side, gn_margin_bottom, corner_width); graphsbcomment->set_border_width_all(border_width); - graphsbcomment->set_border_color(dark_color_3); - Ref<StyleBoxFlat> graphsbcommentselected = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.4), gn_margin_side, 24, gn_margin_side, 5, corner_width); + graphsbcomment->set_border_color(graphnode_bg); + Ref<StyleBoxFlat> graphsbcommentselected = make_flat_stylebox(graphnode_bg * Color(1, 1, 1, 0.4), gn_margin_side, 24, gn_margin_side, gn_margin_bottom, corner_width); graphsbcommentselected->set_border_width_all(border_width); - graphsbcommentselected->set_border_color(dark_color_3); + graphsbcommentselected->set_border_color(graphnode_bg); Ref<StyleBoxFlat> graphsbbreakpoint = graphsbselected->duplicate(); graphsbbreakpoint->set_draw_center(false); graphsbbreakpoint->set_border_color(warning_color); @@ -1472,10 +1488,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { graphsbposition->set_draw_center(false); graphsbposition->set_border_color(error_color); graphsbposition->set_shadow_color(error_color * Color(1.0, 1.0, 1.0, 0.2)); - Ref<StyleBoxFlat> smgraphsb = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.7), gn_margin_side, 24, gn_margin_side, 5, corner_width); + Ref<StyleBoxEmpty> graphsbslot = make_empty_stylebox(12, 0, 12, 0); + Ref<StyleBoxFlat> smgraphsb = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.7), gn_margin_side, 24, gn_margin_side, gn_margin_bottom, corner_width); smgraphsb->set_border_width_all(border_width); - smgraphsb->set_border_color(dark_color_3); - Ref<StyleBoxFlat> smgraphsbselected = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.9), gn_margin_side, 24, gn_margin_side, 5, corner_width); + smgraphsb->set_border_color(graphnode_bg); + Ref<StyleBoxFlat> smgraphsbselected = make_flat_stylebox(graphnode_bg * Color(1, 1, 1, 0.9), gn_margin_side, 24, gn_margin_side, gn_margin_bottom, corner_width); smgraphsbselected->set_border_width_all(2 * EDSCALE + border_width); smgraphsbselected->set_border_color(Color(accent_color.r, accent_color.g, accent_color.b, 0.9)); smgraphsbselected->set_shadow_size(8 * EDSCALE); @@ -1492,19 +1509,20 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("comment_focus", "GraphNode", graphsbcommentselected); theme->set_stylebox("breakpoint", "GraphNode", graphsbbreakpoint); theme->set_stylebox("position", "GraphNode", graphsbposition); + theme->set_stylebox("slot", "GraphNode", graphsbslot); theme->set_stylebox("state_machine_frame", "GraphNode", smgraphsb); theme->set_stylebox("state_machine_selected_frame", "GraphNode", smgraphsbselected); - Color default_node_color = dark_color_1.inverted(); - theme->set_color("title_color", "GraphNode", default_node_color); - default_node_color.a = 0.7; - theme->set_color("close_color", "GraphNode", default_node_color); - theme->set_color("resizer_color", "GraphNode", default_node_color); + Color node_decoration_color = dark_color_1.inverted(); + theme->set_color("title_color", "GraphNode", node_decoration_color); + node_decoration_color.a = 0.7; + theme->set_color("close_color", "GraphNode", node_decoration_color); + theme->set_color("resizer_color", "GraphNode", node_decoration_color); - theme->set_constant("port_offset", "GraphNode", 14 * EDSCALE); - theme->set_constant("title_h_offset", "GraphNode", -16 * EDSCALE); - theme->set_constant("title_offset", "GraphNode", 20 * EDSCALE); - theme->set_constant("close_h_offset", "GraphNode", 20 * EDSCALE); + theme->set_constant("port_offset", "GraphNode", 0); + theme->set_constant("title_h_offset", "GraphNode", 12 * EDSCALE); + theme->set_constant("title_offset", "GraphNode", 21 * EDSCALE); + theme->set_constant("close_h_offset", "GraphNode", -2 * EDSCALE); theme->set_constant("close_offset", "GraphNode", 20 * EDSCALE); theme->set_constant("separation", "GraphNode", 1 * EDSCALE); @@ -1512,6 +1530,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("resizer", "GraphNode", theme->get_icon(SNAME("GuiResizer"), SNAME("EditorIcons"))); theme->set_icon("port", "GraphNode", theme->get_icon(SNAME("GuiGraphNodePort"), SNAME("EditorIcons"))); + theme->set_font("title_font", "GraphNode", theme->get_font(SNAME("main_bold_msdf"), SNAME("EditorFonts"))); + // GridContainer theme->set_constant("v_separation", "GridContainer", Math::round(widget_default_margin.y - 2 * EDSCALE)); diff --git a/editor/editor_toaster.h b/editor/editor_toaster.h index 791a146a8d..39db518258 100644 --- a/editor/editor_toaster.h +++ b/editor/editor_toaster.h @@ -80,7 +80,7 @@ private: String tooltip; int count = 0; }; - Map<Control *, Toast> toasts; + HashMap<Control *, Toast> toasts; bool is_processing_error = false; // Makes sure that we don't handle errors that are triggered within the EditorToaster error processing. diff --git a/editor/editor_translation_parser.cpp b/editor/editor_translation_parser.cpp index 27b8c3fd5d..13dff08c14 100644 --- a/editor/editor_translation_parser.cpp +++ b/editor/editor_translation_parser.cpp @@ -33,7 +33,7 @@ #include "core/error/error_macros.h" #include "core/io/file_access.h" #include "core/object/script_language.h" -#include "core/templates/set.h" +#include "core/templates/rb_set.h" EditorTranslationParser *EditorTranslationParser::singleton = nullptr; @@ -84,7 +84,7 @@ void EditorTranslationParserPlugin::_bind_methods() { ///////////////////////// void EditorTranslationParser::get_recognized_extensions(List<String> *r_extensions) const { - Set<String> extensions; + RBSet<String> extensions; List<String> temp; for (int i = 0; i < standard_parsers.size(); i++) { standard_parsers[i]->get_recognized_extensions(&temp); @@ -96,7 +96,7 @@ void EditorTranslationParser::get_recognized_extensions(List<String> *r_extensio for (int i = 0; i < temp.size(); i++) { extensions.insert(temp[i]); } - for (Set<String>::Element *E = extensions.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = extensions.front(); E; E = E->next()) { r_extensions->push_back(E->get()); } } diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 3526b4ce4c..50f03652ee 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -50,7 +50,7 @@ void ExportTemplateManager::_update_template_status() { Error err = da->change_dir(templates_dir); ERR_FAIL_COND_MSG(err != OK, "Could not access templates directory at '" + templates_dir + "'."); - Set<String> templates; + RBSet<String> templates; da->list_dir_begin(); if (err == OK) { String c = da->get_next(); @@ -97,7 +97,7 @@ void ExportTemplateManager::_update_template_status() { installed_table->clear(); TreeItem *installed_root = installed_table->create_item(); - for (Set<String>::Element *E = templates.back(); E; E = E->prev()) { + for (RBSet<String>::Element *E = templates.back(); E; E = E->prev()) { String version_string = E->get(); if (version_string == current_version) { continue; @@ -374,7 +374,8 @@ void ExportTemplateManager::_install_file() { } bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_skip_progress) { - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); unzFile pkg = unzOpen2(p_file.utf8().get_data(), &io); if (!pkg) { @@ -676,7 +677,8 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_ // Uncompress source template. - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); unzFile pkg = unzOpen2(p_file.utf8().get_data(), &io); ERR_FAIL_COND_V_MSG(!pkg, ERR_CANT_OPEN, "Android sources not in ZIP format."); @@ -692,7 +694,7 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_ ProgressDialog::get_singleton()->add_task("uncompress_src", TTR("Uncompressing Android Build Sources"), total_files); - Set<String> dirs_tested; + RBSet<String> dirs_tested; int idx = 0; while (ret == UNZ_OK) { // Get file path. diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp index 0a59ecf1b3..eed3917845 100644 --- a/editor/fileserver/editor_file_server.cpp +++ b/editor/fileserver/editor_file_server.cpp @@ -46,7 +46,7 @@ void EditorFileServer::_close_client(ClientData *cd) { cd->efs->to_wait.insert(cd->thread); } while (cd->files.size()) { - cd->files.erase(cd->files.front()); + cd->files.remove(cd->files.begin()); } memdelete(cd); } diff --git a/editor/fileserver/editor_file_server.h b/editor/fileserver/editor_file_server.h index 7e771db55f..21abbc3f8c 100644 --- a/editor/fileserver/editor_file_server.h +++ b/editor/fileserver/editor_file_server.h @@ -49,13 +49,13 @@ class EditorFileServer : public Object { struct ClientData { Thread *thread = nullptr; Ref<StreamPeerTCP> connection; - Map<int, Ref<FileAccess>> files; + HashMap<int, Ref<FileAccess>> files; EditorFileServer *efs = nullptr; bool quit = false; }; Ref<TCPServer> server; - Set<Thread *> to_wait; + RBSet<Thread *> to_wait; static void _close_client(ClientData *cd); static void _subthread_start(void *s); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 47c016803c..4c4d38c074 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -726,7 +726,7 @@ void FileSystemDock::_sort_file_info_list(List<FileSystemDock::FileInfo> &r_file void FileSystemDock::_update_file_list(bool p_keep_selection) { // Register the previously selected items. - Set<String> cselection; + RBSet<String> cselection; if (p_keep_selection) { for (int i = 0; i < files->get_item_count(); i++) { if (files->is_selected(i)) { @@ -1161,7 +1161,7 @@ void FileSystemDock::_get_all_items_in_dir(EditorFileSystemDirectory *efsd, Vect } } -void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const { +void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd, const HashMap<String, String> &renames, Vector<String> &to_remaps) const { for (int i = 0; i < efsd->get_subdir_count(); i++) { _find_remaps(efsd->get_subdir(i), renames, to_remaps); } @@ -1177,7 +1177,7 @@ void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd, const Map<Str } void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_new_path, - Map<String, String> &p_file_renames, Map<String, String> &p_folder_renames) { + HashMap<String, String> &p_file_renames, HashMap<String, String> &p_folder_renames) { // Ensure folder paths end with "/". String old_path = (p_item.is_file || p_item.path.ends_with("/")) ? p_item.path : (p_item.path + "/"); String new_path = (p_item.is_file || p_new_path.ends_with("/")) ? p_new_path : (p_new_path + "/"); @@ -1301,7 +1301,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin } } -void FileSystemDock::_update_resource_paths_after_move(const Map<String, String> &p_renames) const { +void FileSystemDock::_update_resource_paths_after_move(const HashMap<String, String> &p_renames) const { // Rename all resources loaded, be it subresources or actual resources. List<Ref<Resource>> cached; ResourceCache::get_cached_resources(&cached); @@ -1346,7 +1346,7 @@ void FileSystemDock::_update_resource_paths_after_move(const Map<String, String> } } -void FileSystemDock::_update_dependencies_after_move(const Map<String, String> &p_renames) const { +void FileSystemDock::_update_dependencies_after_move(const HashMap<String, String> &p_renames) const { // The following code assumes that the following holds: // 1) EditorFileSystem contains the old paths/folder structure from before the rename/move. // 2) ResourceLoader can use the new paths without needing to call rescan. @@ -1367,9 +1367,9 @@ void FileSystemDock::_update_dependencies_after_move(const Map<String, String> & } } -void FileSystemDock::_update_project_settings_after_move(const Map<String, String> &p_renames) const { +void FileSystemDock::_update_project_settings_after_move(const HashMap<String, String> &p_renames) const { // Find all project settings of type FILE and replace them if needed. - const Map<StringName, PropertyInfo> prop_info = ProjectSettings::get_singleton()->get_custom_property_info(); + const HashMap<StringName, PropertyInfo> prop_info = ProjectSettings::get_singleton()->get_custom_property_info(); for (const KeyValue<StringName, PropertyInfo> &E : prop_info) { if (E.value.hint == PROPERTY_HINT_FILE) { String old_path = GLOBAL_GET(E.key); @@ -1398,7 +1398,7 @@ void FileSystemDock::_update_project_settings_after_move(const Map<String, Strin ProjectSettings::get_singleton()->save(); } -void FileSystemDock::_update_favorites_list_after_move(const Map<String, String> &p_files_renames, const Map<String, String> &p_folders_renames) const { +void FileSystemDock::_update_favorites_list_after_move(const HashMap<String, String> &p_files_renames, const HashMap<String, String> &p_folders_renames) const { Vector<String> favorites = EditorSettings::get_singleton()->get_favorites(); Vector<String> new_favorites; @@ -1416,7 +1416,7 @@ void FileSystemDock::_update_favorites_list_after_move(const Map<String, String> EditorSettings::get_singleton()->set_favorites(new_favorites); } -void FileSystemDock::_save_scenes_after_move(const Map<String, String> &p_renames) const { +void FileSystemDock::_save_scenes_after_move(const HashMap<String, String> &p_renames) const { Vector<String> remaps; _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), p_renames, remaps); Vector<String> new_filenames; @@ -1577,8 +1577,8 @@ void FileSystemDock::_rename_operation_confirm() { return; } - Map<String, String> file_renames; - Map<String, String> folder_renames; + HashMap<String, String> file_renames; + HashMap<String, String> folder_renames; _try_move_item(to_rename, new_path, file_renames, folder_renames); int current_tab = EditorNode::get_singleton()->get_current_tab(); @@ -1677,8 +1677,8 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_ove } } - Map<String, String> file_renames; - Map<String, String> folder_renames; + HashMap<String, String> file_renames; + HashMap<String, String> folder_renames; bool is_moved = false; for (int i = 0; i < to_move.size(); i++) { String old_path = to_move[i].path.ends_with("/") ? to_move[i].path.substr(0, to_move[i].path.length() - 1) : to_move[i].path; @@ -2637,7 +2637,7 @@ void FileSystemDock::_tree_empty_selected() { tree->deselect_all(); } -void FileSystemDock::_file_list_rmb_clicked(int p_item, const Vector2 &p_pos, MouseButton p_mouse_button_index) { +void FileSystemDock::_file_list_item_clicked(int p_item, const Vector2 &p_pos, MouseButton p_mouse_button_index) { if (p_mouse_button_index != MouseButton::RIGHT) { return; } @@ -2665,7 +2665,11 @@ void FileSystemDock::_file_list_rmb_clicked(int p_item, const Vector2 &p_pos, Mo } } -void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) { +void FileSystemDock::_file_list_empty_clicked(const Vector2 &p_pos, MouseButton p_mouse_button_index) { + if (p_mouse_button_index != MouseButton::RIGHT) { + return; + } + // Right click on empty space for file list. if (searched_string.length() > 0) { return; @@ -3132,10 +3136,10 @@ FileSystemDock::FileSystemDock() { files->set_v_size_flags(SIZE_EXPAND_FILL); files->set_select_mode(ItemList::SELECT_MULTI); files->set_drag_forwarding(this); - files->connect("item_clicked", callable_mp(this, &FileSystemDock::_file_list_rmb_clicked)); + files->connect("item_clicked", callable_mp(this, &FileSystemDock::_file_list_item_clicked)); files->connect("gui_input", callable_mp(this, &FileSystemDock::_file_list_gui_input)); files->connect("multi_selected", callable_mp(this, &FileSystemDock::_file_multi_selected)); - files->connect("rmb_clicked", callable_mp(this, &FileSystemDock::_file_list_rmb_pressed)); + files->connect("empty_clicked", callable_mp(this, &FileSystemDock::_file_list_empty_clicked)); files->set_custom_minimum_size(Size2(0, 15 * EDSCALE)); files->set_allow_rmb_select(true); file_list_vb->add_child(files); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index f6c4e271bf..df3dd3fd69 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -108,7 +108,7 @@ private: VSplitContainer *split_box = nullptr; VBoxContainer *file_list_vb = nullptr; - Set<String> favorites; + RBSet<String> favorites; Button *button_toggle_display_mode = nullptr; Button *button_reload = nullptr; @@ -217,14 +217,14 @@ private: void _update_import_dock(); void _get_all_items_in_dir(EditorFileSystemDirectory *efsd, Vector<String> &files, Vector<String> &folders) const; - void _find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const; - void _try_move_item(const FileOrFolder &p_item, const String &p_new_path, Map<String, String> &p_file_renames, Map<String, String> &p_folder_renames); + void _find_remaps(EditorFileSystemDirectory *efsd, const HashMap<String, String> &renames, Vector<String> &to_remaps) const; + void _try_move_item(const FileOrFolder &p_item, const String &p_new_path, HashMap<String, String> &p_file_renames, HashMap<String, String> &p_folder_renames); void _try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const; - void _update_dependencies_after_move(const Map<String, String> &p_renames) const; - void _update_resource_paths_after_move(const Map<String, String> &p_renames) const; - void _save_scenes_after_move(const Map<String, String> &p_renames) const; - void _update_favorites_list_after_move(const Map<String, String> &p_files_renames, const Map<String, String> &p_folders_renames) const; - void _update_project_settings_after_move(const Map<String, String> &p_renames) const; + void _update_dependencies_after_move(const HashMap<String, String> &p_renames) const; + void _update_resource_paths_after_move(const HashMap<String, String> &p_renames) const; + void _save_scenes_after_move(const HashMap<String, String> &p_renames) const; + void _update_favorites_list_after_move(const HashMap<String, String> &p_files_renames, const HashMap<String, String> &p_folders_renames) const; + void _update_project_settings_after_move(const HashMap<String, String> &p_renames) const; void _file_removed(String p_file); void _folder_removed(String p_folder); @@ -260,8 +260,8 @@ private: void _file_and_folders_fill_popup(PopupMenu *p_popup, Vector<String> p_paths, bool p_display_path_dependent_options = true); void _tree_rmb_select(const Vector2 &p_pos); void _tree_rmb_empty(const Vector2 &p_pos); - void _file_list_rmb_clicked(int p_item, const Vector2 &p_pos, MouseButton p_mouse_button_index); - void _file_list_rmb_pressed(const Vector2 &p_pos); + void _file_list_item_clicked(int p_item, const Vector2 &p_pos, MouseButton p_mouse_button_index); + void _file_list_empty_clicked(const Vector2 &p_pos, MouseButton p_mouse_button_index); void _tree_empty_selected(); struct FileInfo { diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 41191271a1..aafaccf5be 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -99,7 +99,7 @@ void FindInFiles::set_folder(String folder) { _root_dir = folder; } -void FindInFiles::set_filter(const Set<String> &exts) { +void FindInFiles::set_filter(const RBSet<String> &exts) { _extension_filter = exts; } @@ -443,9 +443,9 @@ String FindInFilesDialog::get_folder() const { return text.strip_edges(); } -Set<String> FindInFilesDialog::get_filter() const { +RBSet<String> FindInFilesDialog::get_filter() const { // Could check the _filters_preferences but it might not have been generated yet. - Set<String> filters; + RBSet<String> filters; for (int i = 0; i < _filters_container->get_child_count(); ++i) { CheckBox *cb = static_cast<CheckBox *>(_filters_container->get_child(i)); if (cb->is_pressed()) { @@ -701,9 +701,9 @@ void FindInFilesPanel::_notification(int p_what) { void FindInFilesPanel::_on_result_found(String fpath, int line_number, int begin, int end, String text) { TreeItem *file_item; - Map<String, TreeItem *>::Element *E = _file_items.find(fpath); + HashMap<String, TreeItem *>::Iterator E = _file_items.find(fpath); - if (E == nullptr) { + if (!E) { file_item = _results_display->create_item(); file_item->set_text(0, fpath); file_item->set_metadata(0, fpath); @@ -715,7 +715,7 @@ void FindInFilesPanel::_on_result_found(String fpath, int line_number, int begin _file_items[fpath] = file_item; } else { - file_item = E->value(); + file_item = E->value; } int text_index = _with_replace ? 1 : 0; @@ -754,11 +754,11 @@ void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) { return; } - Map<TreeItem *, Result>::Element *E = _result_items.find(item); + HashMap<TreeItem *, Result>::Iterator E = _result_items.find(item); if (!E) { return; } - Result r = E->value(); + Result r = E->value; String item_text = item->get_text(_with_replace ? 1 : 0); Ref<Font> font = _results_display->get_theme_font(SNAME("font")); int font_size = _results_display->get_theme_font_size(SNAME("font_size")); @@ -818,12 +818,12 @@ void FindInFilesPanel::_on_cancel_button_clicked() { void FindInFilesPanel::_on_result_selected() { TreeItem *item = _results_display->get_selected(); - Map<TreeItem *, Result>::Element *E = _result_items.find(item); + HashMap<TreeItem *, Result>::Iterator E = _result_items.find(item); - if (E == nullptr) { + if (!E) { return; } - Result r = E->value(); + Result r = E->value; TreeItem *file_item = item->get_parent(); String fpath = file_item->get_metadata(0); @@ -850,9 +850,9 @@ void FindInFilesPanel::_on_replace_all_clicked() { continue; } - Map<TreeItem *, Result>::Element *F = _result_items.find(item); - ERR_FAIL_COND(F == nullptr); - locations.push_back(F->value()); + HashMap<TreeItem *, Result>::Iterator F = _result_items.find(item); + ERR_FAIL_COND(!F); + locations.push_back(F->value); } if (locations.size() != 0) { diff --git a/editor/find_in_files.h b/editor/find_in_files.h index 9def190b5b..8bc7b506d0 100644 --- a/editor/find_in_files.h +++ b/editor/find_in_files.h @@ -46,7 +46,7 @@ public: void set_whole_words(bool p_whole_word); void set_match_case(bool p_match_case); void set_folder(String folder); - void set_filter(const Set<String> &exts); + void set_filter(const RBSet<String> &exts); String get_search_text() const { return _pattern; } @@ -72,7 +72,7 @@ private: // Config String _pattern; - Set<String> _extension_filter; + RBSet<String> _extension_filter; String _root_dir; bool _whole_words = true; bool _match_case = true; @@ -115,7 +115,7 @@ public: bool is_match_case() const; bool is_whole_words() const; String get_folder() const; - Set<String> get_filter() const; + RBSet<String> get_filter() const; protected: void _notification(int p_what); @@ -208,8 +208,8 @@ private: Button *_refresh_button = nullptr; Button *_cancel_button = nullptr; ProgressBar *_progress_bar = nullptr; - Map<String, TreeItem *> _file_items; - Map<TreeItem *, Result> _result_items; + HashMap<String, TreeItem *> _file_items; + HashMap<TreeItem *, Result> _result_items; bool _with_replace = false; HBoxContainer *_replace_container = nullptr; diff --git a/editor/icons/TextMesh.svg b/editor/icons/TextMesh.svg new file mode 100644 index 0000000000..234ce7568e --- /dev/null +++ b/editor/icons/TextMesh.svg @@ -0,0 +1 @@ +<svg stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io"><g fill="#ffca5f" fill-rule="evenodd" vectornator:layerName="Untitled"><path d="M1 1h14v2H1V1Z"/><path d="M7 1h2v14H7V1Z"/><path d="M5 14h6v1H5v-1ZM2 1v4H1V1h1Zm13 0v4h-1V1h1ZM2 3v2a2 2 0 0 1 2-2H2Zm10 0a2 2 0 0 1 2 2V3h-2ZM5 14a2 2 0 0 0 2-2v2H5Zm6 0a2 2 0 0 1-2-2v2h2Z"/></g></svg> diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp index e68c5e9a22..71b5ddc216 100644 --- a/editor/import/collada.cpp +++ b/editor/import/collada.cpp @@ -1645,12 +1645,12 @@ void Collada::_parse_animation(XMLParser &parser) { return; } - Map<String, Vector<float>> float_sources; - Map<String, Vector<String>> string_sources; - Map<String, int> source_strides; - Map<String, Map<String, String>> samplers; - Map<String, Vector<String>> source_param_names; - Map<String, Vector<String>> source_param_types; + HashMap<String, Vector<float>> float_sources; + HashMap<String, Vector<String>> string_sources; + HashMap<String, int> source_strides; + HashMap<String, HashMap<String, String>> samplers; + HashMap<String, Vector<String>> source_param_names; + HashMap<String, Vector<String>> source_param_types; String id = ""; if (parser.has_attribute("id")) { @@ -1685,7 +1685,7 @@ void Collada::_parse_animation(XMLParser &parser) { } } else if (name == "sampler") { current_sampler = parser.get_attribute_value("id"); - samplers[current_sampler] = Map<String, String>(); + samplers[current_sampler] = HashMap<String, String>(); } else if (name == "param") { if (parser.has_attribute("name")) { source_param_names[current_source].push_back(parser.get_attribute_value("name")); @@ -1718,7 +1718,7 @@ void Collada::_parse_animation(XMLParser &parser) { String source = _uri_to_id(channel_sources[i]); String target = channel_targets[i]; ERR_CONTINUE(!samplers.has(source)); - Map<String, String> &sampler = samplers[source]; + HashMap<String, String> &sampler = samplers[source]; ERR_CONTINUE(!sampler.has("INPUT")); //no input semantic? wtf? String input_id = _uri_to_id(sampler["INPUT"]); @@ -2029,7 +2029,7 @@ void Collada::_merge_skeletons(VisualScene *p_vscene, Node *p_node) { NodeGeometry *gnode = static_cast<NodeGeometry *>(p_node); if (gnode->controller) { // recount skeletons used - Set<NodeSkeleton *> skeletons; + RBSet<NodeSkeleton *> skeletons; for (int i = 0; i < gnode->skeletons.size(); i++) { String nodeid = gnode->skeletons[i]; @@ -2049,7 +2049,7 @@ void Collada::_merge_skeletons(VisualScene *p_vscene, Node *p_node) { if (skeletons.size() > 1) { //do the merger!! - Set<NodeSkeleton *>::Element *E = skeletons.front(); + RBSet<NodeSkeleton *>::Element *E = skeletons.front(); NodeSkeleton *base = E->get(); for (E = E->next(); E; E = E->next()) { diff --git a/editor/import/collada.h b/editor/import/collada.h index df2b789081..6ac6181769 100644 --- a/editor/import/collada.h +++ b/editor/import/collada.h @@ -33,7 +33,7 @@ #include "core/config/project_settings.h" #include "core/io/xml_parser.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "scene/resources/material.h" class Collada { @@ -54,7 +54,7 @@ public: struct Effect { String name; - Map<String, Variant> params; + HashMap<String, Variant> params; struct Channel { int uv_idx = 0; @@ -131,13 +131,13 @@ public: int stride = 0; }; - Map<String, Source> sources; + HashMap<String, Source> sources; struct Vertices { - Map<String, String> sources; + HashMap<String, String> sources; }; - Map<String, Vertices> vertices; + HashMap<String, Vertices> vertices; struct Primitives { struct SourceRef { @@ -146,7 +146,7 @@ public: }; String material; - Map<String, SourceRef> sources; + HashMap<String, SourceRef> sources; Vector<float> polygons; Vector<float> indices; int count = 0; @@ -171,9 +171,9 @@ public: int stride = 0; }; - Map<String, Source> sources; + HashMap<String, Source> sources; - Map<String, String> control_vertices; + HashMap<String, String> control_vertices; CurveData() {} }; @@ -191,10 +191,10 @@ public: Source() {} }; - Map<String, Source> sources; + HashMap<String, Source> sources; struct Joints { - Map<String, String> sources; + HashMap<String, String> sources; } joints; struct Weights { @@ -204,13 +204,13 @@ public: }; String material; - Map<String, SourceRef> sources; + HashMap<String, SourceRef> sources; Vector<float> sets; Vector<float> indices; int count = 0; } weights; - Map<String, Transform3D> bone_rest_map; + HashMap<String, Transform3D> bone_rest_map; SkinControllerData() {} }; @@ -226,9 +226,9 @@ public: Source() {} }; - Map<String, Source> sources; + HashMap<String, Source> sources; - Map<String, String> targets; + HashMap<String, String> targets; MorphControllerData() {} }; @@ -382,7 +382,7 @@ public: String target; }; - Map<String, Material> material_map; + HashMap<String, Material> material_map; Vector<String> skeletons; NodeGeometry() { type = TYPE_GEOMETRY; } @@ -476,28 +476,28 @@ public: } } version; - Map<String, CameraData> camera_data_map; - Map<String, MeshData> mesh_data_map; - Map<String, LightData> light_data_map; - Map<String, CurveData> curve_data_map; + HashMap<String, CameraData> camera_data_map; + HashMap<String, MeshData> mesh_data_map; + HashMap<String, LightData> light_data_map; + HashMap<String, CurveData> curve_data_map; - Map<String, String> mesh_name_map; - Map<String, String> morph_name_map; - Map<String, String> morph_ownership_map; - Map<String, SkinControllerData> skin_controller_data_map; - Map<String, MorphControllerData> morph_controller_data_map; + HashMap<String, String> mesh_name_map; + HashMap<String, String> morph_name_map; + HashMap<String, String> morph_ownership_map; + HashMap<String, SkinControllerData> skin_controller_data_map; + HashMap<String, MorphControllerData> morph_controller_data_map; - Map<String, Image> image_map; - Map<String, Material> material_map; - Map<String, Effect> effect_map; + HashMap<String, Image> image_map; + HashMap<String, Material> material_map; + HashMap<String, Effect> effect_map; - Map<String, VisualScene> visual_scene_map; - Map<String, Node *> scene_map; - Set<String> idref_joints; - Map<String, String> sid_to_node_map; - //Map<String,NodeJoint*> bone_map; + HashMap<String, VisualScene> visual_scene_map; + HashMap<String, Node *> scene_map; + RBSet<String> idref_joints; + HashMap<String, String> sid_to_node_map; + //RBMap<String,NodeJoint*> bone_map; - Map<String, Transform3D> bone_rest_map; + HashMap<String, Transform3D> bone_rest_map; String local_path; String root_visual_scene; @@ -505,8 +505,8 @@ public: Vector<AnimationClip> animation_clips; Vector<AnimationTrack> animation_tracks; - Map<String, Vector<int>> referenced_tracks; - Map<String, Vector<int>> by_id_tracks; + HashMap<String, Vector<int>> referenced_tracks; + HashMap<String, Vector<int>> by_id_tracks; float animation_length = 0; @@ -524,7 +524,7 @@ public: int get_uv_channel(String p_name); private: // private stuff - Map<String, int> channel_map; + HashMap<String, int> channel_map; void _parse_asset(XMLParser &parser); void _parse_image(XMLParser &parser); diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index 451cb245dd..815366b279 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -45,8 +45,8 @@ class DynamicFontImportSettingsData : public RefCounted { GDCLASS(DynamicFontImportSettingsData, RefCounted) friend class DynamicFontImportSettings; - Map<StringName, Variant> settings; - Map<StringName, Variant> defaults; + HashMap<StringName, Variant> settings; + HashMap<StringName, Variant> defaults; List<ResourceImporter::ImportOption> options; DynamicFontImportSettings *owner = nullptr; @@ -581,10 +581,10 @@ void DynamicFontImportSettings::_variations_validate() { for (TreeItem *vars_item_b = vars_list_root->get_first_child(); vars_item_b; vars_item_b = vars_item_b->get_next()) { if (vars_item_b != vars_item_a) { bool match = true; - for (Map<StringName, Variant>::Element *E = import_variation_data_a->settings.front(); E; E = E->next()) { + for (const KeyValue<StringName, Variant> &E : import_variation_data_a->settings) { Ref<DynamicFontImportSettingsData> import_variation_data_b = vars_item_b->get_metadata(0); ERR_FAIL_NULL(import_variation_data_b); - match = match && (import_variation_data_b->settings[E->key()] == E->get()); + match = match && (import_variation_data_b->settings[E.key] == E.value); } if (match) { warn = TTR("Warning: Multiple configurations have identical settings. Duplicates will be ignored."); @@ -927,7 +927,7 @@ void DynamicFontImportSettings::_notification(int p_what) { } void DynamicFontImportSettings::_re_import() { - Map<StringName, Variant> main_settings; + HashMap<StringName, Variant> main_settings; main_settings["antialiased"] = import_settings_data->get("antialiased"); main_settings["generate_mipmaps"] = import_settings_data->get("generate_mipmaps"); @@ -950,11 +950,11 @@ void DynamicFontImportSettings::_re_import() { String name = vars_item->get_text(0); variation += ("name=" + name); - for (Map<StringName, Variant>::Element *E = import_variation_data->settings.front(); E; E = E->next()) { + for (const KeyValue<StringName, Variant> &E : import_variation_data->settings) { if (!variation.is_empty()) { variation += ","; } - variation += (String(E->key()) + "=" + String(E->get())); + variation += (String(E.key) + "=" + String(E.value)); } variations.push_back(variation); } @@ -991,7 +991,7 @@ void DynamicFontImportSettings::_re_import() { if (!selected_chars.is_empty()) { Vector<String> ranges; char32_t start = selected_chars.front()->get(); - for (Set<char32_t>::Element *E = selected_chars.front()->next(); E; E = E->next()) { + for (RBSet<char32_t>::Element *E = selected_chars.front()->next(); E; E = E->next()) { if (E->prev() && ((E->prev()->get() + 1) != E->get())) { ranges.push_back(String("0x") + String::num_int64(start, 16) + String("-0x") + String::num_int64(E->prev()->get(), 16)); start = E->get(); @@ -1004,7 +1004,7 @@ void DynamicFontImportSettings::_re_import() { if (!selected_glyphs.is_empty()) { Vector<String> ranges; int32_t start = selected_glyphs.front()->get(); - for (Set<int32_t>::Element *E = selected_glyphs.front()->next(); E; E = E->next()) { + for (RBSet<int32_t>::Element *E = selected_glyphs.front()->next(); E; E = E->next()) { if (E->prev() && ((E->prev()->get() + 1) != E->get())) { ranges.push_back(String("0x") + String::num_int64(start, 16) + String("-0x") + String::num_int64(E->prev()->get(), 16)); start = E->get(); @@ -1024,8 +1024,8 @@ void DynamicFontImportSettings::_re_import() { if (OS::get_singleton()->is_stdout_verbose()) { print_line("Import settings:"); - for (Map<StringName, Variant>::Element *E = main_settings.front(); E; E = E->next()) { - print_line(String(" ") + String(E->key()).utf8().get_data() + " == " + String(E->get()).utf8().get_data()); + for (const KeyValue<StringName, Variant> &E : main_settings) { + print_line(String(" ") + String(E.key).utf8().get_data() + " == " + String(E.value).utf8().get_data()); } } diff --git a/editor/import/dynamic_font_import_settings.h b/editor/import/dynamic_font_import_settings.h index c1e868403f..4e2135a13c 100644 --- a/editor/import/dynamic_font_import_settings.h +++ b/editor/import/dynamic_font_import_settings.h @@ -161,8 +161,8 @@ class DynamicFontImportSettings : public ConfirmationDialog { Ref<Font> font_preview; Ref<Font> font_main; - Set<char32_t> selected_chars; - Set<int32_t> selected_glyphs; + RBSet<char32_t> selected_chars; + RBSet<int32_t> selected_glyphs; void _re_import(); diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 013dcb5deb..8ee47cb6f4 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -67,34 +67,34 @@ struct ColladaImport { bool use_mesh_builtin_materials = false; float bake_fps = 15; - Map<String, NodeMap> node_map; //map from collada node to engine node - Map<String, String> node_name_map; //map from collada node to engine node - Map<String, Ref<ImporterMesh>> mesh_cache; - Map<String, Ref<Curve3D>> curve_cache; - Map<String, Ref<Material>> material_cache; - Map<Collada::Node *, Skeleton3D *> skeleton_map; + HashMap<String, NodeMap> node_map; //map from collada node to engine node + HashMap<String, String> node_name_map; //map from collada node to engine node + HashMap<String, Ref<ImporterMesh>> mesh_cache; + HashMap<String, Ref<Curve3D>> curve_cache; + HashMap<String, Ref<Material>> material_cache; + HashMap<Collada::Node *, Skeleton3D *> skeleton_map; - Map<Skeleton3D *, Map<String, int>> skeleton_bone_map; + HashMap<Skeleton3D *, HashMap<String, int>> skeleton_bone_map; - Set<String> valid_animated_nodes; + RBSet<String> valid_animated_nodes; Vector<int> valid_animated_properties; - Map<String, bool> bones_with_animation; + HashMap<String, bool> bones_with_animation; - Set<String> mesh_unique_names; - Set<String> material_unique_names; + RBSet<String> mesh_unique_names; + RBSet<String> material_unique_names; Error _populate_skeleton(Skeleton3D *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent); Error _create_scene_skeletons(Collada::Node *p_node); Error _create_scene(Collada::Node *p_node, Node3D *p_parent); Error _create_resources(Collada::Node *p_node, bool p_use_compression); Error _create_material(const String &p_target); - Error _create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ImporterMesh>> p_morph_meshes = Vector<Ref<ImporterMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false); + Error _create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p_mesh, const HashMap<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ImporterMesh>> p_morph_meshes = Vector<Ref<ImporterMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false); Error load(const String &p_path, int p_flags, bool p_force_make_tangents = false, bool p_use_compression = false); void _fix_param_animation_tracks(); void create_animation(int p_clip, bool p_import_value_tracks); void create_animations(bool p_import_value_tracks); - Set<String> tracks_in_clips; + RBSet<String> tracks_in_clips; Vector<String> missing_textures; void _pre_process_lights(Collada::Node *p_node); @@ -467,7 +467,7 @@ Error ColladaImport::_create_material(const String &p_target) { return OK; } -Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ImporterMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) { +Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p_mesh, const HashMap<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ImporterMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) { bool local_xform_mirror = p_local_xform.basis.determinant() < 0; if (p_morph_data) { @@ -637,7 +637,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p /* ADD WEIGHTS IF EXIST */ /************************/ - Map<int, Vector<Collada::Vertex::Weight>> pre_weights; + HashMap<int, Vector<Collada::Vertex::Weight>> pre_weights; bool has_weights = false; @@ -727,7 +727,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p has_weights = true; } - Set<Collada::Vertex> vertex_set; //vertex set will be the vertices + RBSet<Collada::Vertex> vertex_set; //vertex set will be the vertices List<int> indices_list; //indices will be the indices /**************************/ @@ -875,7 +875,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p Vector<Collada::Vertex> vertex_array; //there we go, vertex array vertex_array.resize(vertex_set.size()); - for (Set<Collada::Vertex>::Element *F = vertex_set.front(); F; F = F->next()) { + for (RBSet<Collada::Vertex>::Element *F = vertex_set.front(); F; F = F->next()) { vertex_array.write[F->get().idx] = F->get(); } @@ -1127,7 +1127,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres Skeleton3D *sk = Object::cast_to<Skeleton3D>(nmsk.node); ERR_FAIL_COND_V(!sk, ERR_INVALID_DATA); ERR_FAIL_COND_V(!skeleton_bone_map.has(sk), ERR_INVALID_DATA); - Map<String, int> &bone_remap_map = skeleton_bone_map[sk]; + HashMap<String, int> &bone_remap_map = skeleton_bone_map[sk]; meshid = skin->base; @@ -1452,7 +1452,7 @@ void ColladaImport::create_animation(int p_clip, bool p_import_value_tracks) { //main anim } - Set<int> track_filter; + RBSet<int> track_filter; if (p_clip == -1) { for (int i = 0; i < collada.state.animation_clips.size(); i++) { @@ -1507,7 +1507,7 @@ void ColladaImport::create_animation(int p_clip, bool p_import_value_tracks) { bool tracks_found = false; - for (Set<String>::Element *E = valid_animated_nodes.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = valid_animated_nodes.front(); E; E = E->next()) { // take snapshots if (!collada.state.scene_map.has(E->get())) { @@ -1754,7 +1754,7 @@ void EditorSceneFormatImporterCollada::get_extensions(List<String> *r_extensions r_extensions->push_back("dae"); } -Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { if (r_err) { *r_err = OK; } diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h index be3f74d821..e45db47440 100644 --- a/editor/import/editor_import_collada.h +++ b/editor/import/editor_import_collada.h @@ -39,7 +39,7 @@ class EditorSceneFormatImporterCollada : public EditorSceneFormatImporter { public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr) override; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr) override; EditorSceneFormatImporterCollada(); }; diff --git a/editor/import/editor_import_plugin.cpp b/editor/import/editor_import_plugin.cpp index f7d373ef60..e822b4963a 100644 --- a/editor/import/editor_import_plugin.cpp +++ b/editor/import/editor_import_plugin.cpp @@ -147,12 +147,12 @@ void EditorImportPlugin::get_import_options(const String &p_path, List<ResourceI ERR_FAIL_MSG("Unimplemented _get_import_options in add-on."); } -bool EditorImportPlugin::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool EditorImportPlugin::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { Dictionary d; - Map<StringName, Variant>::Element *E = p_options.front(); + HashMap<StringName, Variant>::ConstIterator E = p_options.begin(); while (E) { - d[E->key()] = E->get(); - E = E->next(); + d[E->key] = E->value; + ++E; } bool visible; if (GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, d, visible)) { @@ -162,14 +162,14 @@ bool EditorImportPlugin::get_option_visibility(const String &p_path, const Strin ERR_FAIL_V_MSG(false, "Unimplemented _get_option_visibility in add-on."); } -Error EditorImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error EditorImportPlugin::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { Dictionary options; Array platform_variants, gen_files; - Map<StringName, Variant>::Element *E = p_options.front(); + HashMap<StringName, Variant>::ConstIterator E = p_options.begin(); while (E) { - options[E->key()] = E->get(); - E = E->next(); + options[E->key] = E->value; + ++E; } int err; diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h index 6cff8fb917..44fbd41962 100644 --- a/editor/import/editor_import_plugin.h +++ b/editor/import/editor_import_plugin.h @@ -64,8 +64,8 @@ public: virtual float get_priority() const override; virtual int get_import_order() const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata = nullptr) override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata = nullptr) override; }; #endif //EDITOR_IMPORT_PLUGIN_H diff --git a/editor/import/resource_importer_bitmask.cpp b/editor/import/resource_importer_bitmask.cpp index 46d15e8989..966719dc48 100644 --- a/editor/import/resource_importer_bitmask.cpp +++ b/editor/import/resource_importer_bitmask.cpp @@ -55,7 +55,7 @@ String ResourceImporterBitMap::get_resource_type() const { return "BitMap"; } -bool ResourceImporterBitMap::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterBitMap::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } @@ -72,7 +72,7 @@ void ResourceImporterBitMap::get_import_options(const String &p_path, List<Impor r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.5)); } -Error ResourceImporterBitMap::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterBitMap::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { int create_from = p_options["create_from"]; float threshold = p_options["threshold"]; Ref<Image> image; diff --git a/editor/import/resource_importer_bitmask.h b/editor/import/resource_importer_bitmask.h index 6dd6843171..8682ab80a3 100644 --- a/editor/import/resource_importer_bitmask.h +++ b/editor/import/resource_importer_bitmask.h @@ -47,8 +47,8 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterBitMap(); ~ResourceImporterBitMap(); diff --git a/editor/import/resource_importer_bmfont.cpp b/editor/import/resource_importer_bmfont.cpp index 8a655fbc0c..8a40b113b9 100644 --- a/editor/import/resource_importer_bmfont.cpp +++ b/editor/import/resource_importer_bmfont.cpp @@ -55,7 +55,7 @@ String ResourceImporterBMFont::get_resource_type() const { return "FontData"; } -bool ResourceImporterBMFont::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterBMFont::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } @@ -63,7 +63,7 @@ void ResourceImporterBMFont::get_import_options(const String &p_path, List<Impor r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true)); } -Error ResourceImporterBMFont::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterBMFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { print_verbose("Importing BMFont font from: " + p_source_file); Ref<FontData> font; diff --git a/editor/import/resource_importer_bmfont.h b/editor/import/resource_importer_bmfont.h index e5a96e2c40..0711302bd5 100644 --- a/editor/import/resource_importer_bmfont.h +++ b/editor/import/resource_importer_bmfont.h @@ -46,9 +46,9 @@ public: virtual String get_resource_type() const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterBMFont(); }; diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index ee6500a643..0b3622e3c0 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -55,7 +55,7 @@ String ResourceImporterCSVTranslation::get_resource_type() const { return "Translation"; } -bool ResourceImporterCSVTranslation::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterCSVTranslation::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } @@ -72,7 +72,7 @@ void ResourceImporterCSVTranslation::get_import_options(const String &p_path, Li r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "delimiter", PROPERTY_HINT_ENUM, "Comma,Semicolon,Tab"), 0)); } -Error ResourceImporterCSVTranslation::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterCSVTranslation::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { bool compress = p_options["compress"]; String delimiter; diff --git a/editor/import/resource_importer_csv_translation.h b/editor/import/resource_importer_csv_translation.h index 8f6cf94984..306aafa843 100644 --- a/editor/import/resource_importer_csv_translation.h +++ b/editor/import/resource_importer_csv_translation.h @@ -47,9 +47,9 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterCSVTranslation(); }; diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp index 2dc24c9d44..04f6a0b7af 100644 --- a/editor/import/resource_importer_dynamic_font.cpp +++ b/editor/import/resource_importer_dynamic_font.cpp @@ -67,7 +67,7 @@ String ResourceImporterDynamicFont::get_resource_type() const { return "FontData"; } -bool ResourceImporterDynamicFont::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterDynamicFont::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { if (p_option == "msdf_pixel_range" && !bool(p_options["multichannel_signed_distance_field"])) { return false; } @@ -176,7 +176,7 @@ void ResourceImporterDynamicFont::show_advanced_options(const String &p_path) { DynamicFontImportSettings::get_singleton()->open_settings(p_path); } -Error ResourceImporterDynamicFont::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterDynamicFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { print_verbose("Importing dynamic font from: " + p_source_file); bool antialiased = p_options["antialiased"]; diff --git a/editor/import/resource_importer_dynamic_font.h b/editor/import/resource_importer_dynamic_font.h index 2761b418e1..c0b6c094b0 100644 --- a/editor/import/resource_importer_dynamic_font.h +++ b/editor/import/resource_importer_dynamic_font.h @@ -56,12 +56,12 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; bool has_advanced_options() const override; void show_advanced_options(const String &p_path) override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterDynamicFont(); }; diff --git a/editor/import/resource_importer_image.cpp b/editor/import/resource_importer_image.cpp index 8514df76bb..fa7c4cd24f 100644 --- a/editor/import/resource_importer_image.cpp +++ b/editor/import/resource_importer_image.cpp @@ -55,7 +55,7 @@ String ResourceImporterImage::get_resource_type() const { return "Image"; } -bool ResourceImporterImage::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterImage::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } @@ -70,7 +70,7 @@ String ResourceImporterImage::get_preset_name(int p_idx) const { void ResourceImporterImage::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { } -Error ResourceImporterImage::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterImage::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ); ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file from path '" + p_source_file + "'."); diff --git a/editor/import/resource_importer_image.h b/editor/import/resource_importer_image.h index 81aedc91e8..a1a345287e 100644 --- a/editor/import/resource_importer_image.h +++ b/editor/import/resource_importer_image.h @@ -48,9 +48,9 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterImage(); }; diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp index 2b67a171cc..bbcd336575 100644 --- a/editor/import/resource_importer_imagefont.cpp +++ b/editor/import/resource_importer_imagefont.cpp @@ -55,7 +55,7 @@ String ResourceImporterImageFont::get_resource_type() const { return "FontData"; } -bool ResourceImporterImageFont::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterImageFont::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } @@ -85,7 +85,7 @@ bool ResourceImporterImageFont::_decode_range(const String &p_token, int32_t &r_ } } -Error ResourceImporterImageFont::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterImageFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { print_verbose("Importing image font from: " + p_source_file); int columns = p_options["columns"]; diff --git a/editor/import/resource_importer_imagefont.h b/editor/import/resource_importer_imagefont.h index c1116d5a83..f46bc8c19b 100644 --- a/editor/import/resource_importer_imagefont.h +++ b/editor/import/resource_importer_imagefont.h @@ -48,9 +48,9 @@ public: virtual String get_resource_type() const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterImageFont(); }; diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index 7c0c99cd29..bacd09592e 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -119,7 +119,7 @@ String ResourceImporterLayeredTexture::get_resource_type() const { ERR_FAIL_V(String()); } -bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { if (p_option == "compress/lossy_quality" && p_options.has("compress/mode")) { return int(p_options["compress/mode"]) == COMPRESS_LOSSY; } @@ -282,7 +282,7 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons } } -Error ResourceImporterLayeredTexture::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterLayeredTexture::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { int compress_mode = p_options["compress/mode"]; float lossy = p_options["compress/lossy_quality"]; int hdr_compression = p_options["compress/hdr_compression"]; diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 5791914a9b..5a29010c3b 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -43,7 +43,7 @@ class LayeredTextureImport : public RefCounted { public: Image::CompressSource *csource = nullptr; String save_path; - Map<StringName, Variant> options; + HashMap<StringName, Variant> options; List<String> *platform_variants = nullptr; Ref<Image> image = nullptr; Array formats_imported; @@ -108,11 +108,11 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; void _save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2); - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; virtual bool are_import_settings_valid(const String &p_path) const override; virtual String get_import_settings_string() const override; diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index 88837d089a..6fbfecfdfa 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -43,7 +43,7 @@ uint32_t EditorOBJImporter::get_import_flags() const { return IMPORT_SCENE; } -static Error _parse_material_library(const String &p_path, Map<String, Ref<StandardMaterial3D>> &material_map, List<String> *r_missing_deps) { +static Error _parse_material_library(const String &p_path, HashMap<String, Ref<StandardMaterial3D>> &material_map, List<String> *r_missing_deps) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Couldn't open MTL file '%s', it may not exist or not be readable.", p_path)); @@ -219,7 +219,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ Vector<Vector2> uvs; String name; - Map<String, Map<String, Ref<StandardMaterial3D>>> material_map; + HashMap<String, HashMap<String, Ref<StandardMaterial3D>>> material_map; Ref<SurfaceTool> surf_tool = memnew(SurfaceTool); surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES); @@ -402,7 +402,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ current_material_library = l.replace("mtllib", "").strip_edges(); if (!material_map.has(current_material_library)) { - Map<String, Ref<StandardMaterial3D>> lib; + HashMap<String, Ref<StandardMaterial3D>> lib; String lib_path = current_material_library; if (lib_path.is_relative_path()) { lib_path = p_path.get_base_dir().plus_file(current_material_library); @@ -422,7 +422,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ return OK; } -Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { +Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { List<Ref<Mesh>> meshes; Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, false, Vector3(1, 1, 1), Vector3(0, 0, 0), r_missing_deps); @@ -505,11 +505,11 @@ void ResourceImporterOBJ::get_import_options(const String &p_path, List<ImportOp r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "optimize_mesh"), true)); } -bool ResourceImporterOBJ::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterOBJ::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } -Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { List<Ref<Mesh>> meshes; Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["optimize_mesh"], p_options["scale_mesh"], p_options["offset_mesh"], nullptr); diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h index 1b5e8bbdc1..3da9f02adb 100644 --- a/editor/import/resource_importer_obj.h +++ b/editor/import/resource_importer_obj.h @@ -39,7 +39,7 @@ class EditorOBJImporter : public EditorSceneFormatImporter { public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; EditorOBJImporter(); }; @@ -59,9 +59,9 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; // Threaded import can currently cause deadlocks, see GH-48265. virtual bool can_import_threaded() const override { return false; } diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 06a84ff23c..647eb1344b 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -74,7 +74,7 @@ void EditorSceneFormatImporter::get_extensions(List<String> *r_extensions) const ERR_FAIL(); } -Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { Dictionary options_dict; for (const KeyValue<StringName, Variant> &elem : p_options) { options_dict[elem.key] = elem.value; @@ -91,7 +91,7 @@ void EditorSceneFormatImporter::get_import_options(const String &p_path, List<Re GDVIRTUAL_CALL(_get_import_options, p_path); } -Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) { +Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const HashMap<StringName, Variant> &p_options) { Variant ret; GDVIRTUAL_CALL(_get_option_visibility, p_path, p_for_animation, p_option, ret); return ret; @@ -166,14 +166,14 @@ void EditorScenePostImportPlugin::get_internal_import_options(InternalImportCate GDVIRTUAL_CALL(_get_internal_import_options, p_category); current_option_list = nullptr; } -Variant EditorScenePostImportPlugin::get_internal_option_visibility(InternalImportCategory p_category, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const { +Variant EditorScenePostImportPlugin::get_internal_option_visibility(InternalImportCategory p_category, bool p_for_animation, const String &p_option, const HashMap<StringName, Variant> &p_options) const { current_options = &p_options; Variant ret; GDVIRTUAL_CALL(_get_internal_option_visibility, p_category, p_for_animation, p_option, ret); current_options = nullptr; return ret; } -Variant EditorScenePostImportPlugin::get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { +Variant EditorScenePostImportPlugin::get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const HashMap<StringName, Variant> &p_options) const { current_options = &p_options; Variant ret; GDVIRTUAL_CALL(_get_internal_option_update_view_required, p_category, p_option, ret); @@ -192,7 +192,7 @@ void EditorScenePostImportPlugin::get_import_options(const String &p_path, List< GDVIRTUAL_CALL(_get_import_options, p_path); current_option_list = nullptr; } -Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const { +Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const HashMap<StringName, Variant> &p_options) const { current_options = &p_options; Variant ret; GDVIRTUAL_CALL(_get_option_visibility, p_path, p_for_animation, p_option, ret); @@ -200,12 +200,12 @@ Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, return ret; } -void EditorScenePostImportPlugin::pre_process(Node *p_scene, const Map<StringName, Variant> &p_options) { +void EditorScenePostImportPlugin::pre_process(Node *p_scene, const HashMap<StringName, Variant> &p_options) { current_options = &p_options; GDVIRTUAL_CALL(_pre_process, p_scene); current_options = nullptr; } -void EditorScenePostImportPlugin::post_process(Node *p_scene, const Map<StringName, Variant> &p_options) { +void EditorScenePostImportPlugin::post_process(Node *p_scene, const HashMap<StringName, Variant> &p_options) { current_options = &p_options; GDVIRTUAL_CALL(_post_process, p_scene); current_options = nullptr; @@ -263,7 +263,7 @@ int ResourceImporterScene::get_format_version() const { return 1; } -bool ResourceImporterScene::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterScene::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { if (animation_importer) { if (p_option == "animation/import") { // Option ignored, animation always imported. return false; @@ -367,7 +367,7 @@ static void _pre_gen_shape_list(Ref<ImporterMesh> &mesh, Vector<Ref<Shape3D>> &r } } -Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &r_collision_map, Pair<PackedVector3Array, PackedInt32Array> *r_occluder_arrays, List<Pair<NodePath, Node *>> &r_node_renames) { +Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &r_collision_map, Pair<PackedVector3Array, PackedInt32Array> *r_occluder_arrays, List<Pair<NodePath, Node *>> &r_node_renames) { // Children first. for (int i = 0; i < p_node->get_child_count(); i++) { Node *r = _pre_fix_node(p_node->get_child(i), p_root, r_collision_map, r_occluder_arrays, r_node_renames); @@ -704,7 +704,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I return p_node; } -Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, Set<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { +Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, RBSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_occluder_arrays, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps); @@ -1356,7 +1356,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p } } -bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const HashMap<StringName, Variant> &p_options) const { if (p_options.has("import/skip_import") && p_option != "import/skip_import" && bool(p_options["import/skip_import"])) { return false; //if skip import } @@ -1475,7 +1475,7 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor return true; } -bool ResourceImporterScene::get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterScene::get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const HashMap<StringName, Variant> &p_options) const { switch (p_category) { case INTERNAL_IMPORT_CATEGORY_NODE: { } break; @@ -1531,7 +1531,7 @@ void ResourceImporterScene::get_import_options(const String &p_path, List<Import r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/generate_lods"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/create_shadow_meshes"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI),Static Lightmaps (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI only)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1)); - r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.2)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 30)); @@ -1737,7 +1737,7 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani p_player->get_animation_list(&anims); Node *parent = p_player->get_parent(); ERR_FAIL_COND(parent == nullptr); - OrderedHashMap<NodePath, uint32_t> used_tracks[TRACK_CHANNEL_MAX]; + HashMap<NodePath, uint32_t> used_tracks[TRACK_CHANNEL_MAX]; bool tracks_to_add = false; static const Animation::TrackType track_types[TRACK_CHANNEL_MAX] = { Animation::TYPE_POSITION_3D, Animation::TYPE_ROTATION_3D, Animation::TYPE_SCALE_3D, Animation::TYPE_BLEND_SHAPE }; for (const StringName &I : anims) { @@ -1790,12 +1790,12 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani used_tracks[j][path] = pass; } - for (OrderedHashMap<NodePath, uint32_t>::Element J = used_tracks[j].front(); J; J = J.next()) { - if (J.get() == pass) { + for (const KeyValue<NodePath, uint32_t> &J : used_tracks[j]) { + if (J.value == pass) { continue; } - NodePath path = J.key(); + NodePath path = J.key; Node *n = parent->get_node(path); if (j == TRACK_CHANNEL_BLEND_SHAPE) { @@ -1909,19 +1909,19 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) { ERR_FAIL_COND_V(!importer.is_valid(), nullptr); Error err = OK; - Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, Map<StringName, Variant>(), 15, nullptr, &err); + Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, HashMap<StringName, Variant>(), 15, nullptr, &err); if (!scene || err != OK) { return nullptr; } - Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map; + HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map; List<Pair<NodePath, Node *>> node_renames; _pre_fix_node(scene, scene, collision_map, nullptr, node_renames); return scene; } -Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { const String &src_path = p_source_file; Ref<EditorSceneFormatImporter> importer; @@ -1994,8 +1994,8 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p animation_data = subresources["animations"]; } - Set<Ref<ImporterMesh>> scanned_meshes; - Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map; + RBSet<Ref<ImporterMesh>> scanned_meshes; + HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map; Pair<PackedVector3Array, PackedInt32Array> occluder_arrays; List<Pair<NodePath, Node *>> node_renames; @@ -2223,7 +2223,7 @@ void EditorSceneFormatImporterESCN::get_extensions(List<String> *r_extensions) c r_extensions->push_back("escn"); } -Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { Error error; Ref<PackedScene> ps = ResourceFormatLoaderText::singleton->load(p_path, p_path, &error); ERR_FAIL_COND_V_MSG(!ps.is_valid(), nullptr, "Cannot load scene as text resource from path '" + p_path + "'."); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index ac72a8f39d..92bd267216 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -71,9 +71,9 @@ public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options); - virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options); + virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const HashMap<StringName, Variant> &p_options); EditorSceneFormatImporter() {} }; @@ -110,7 +110,7 @@ public: }; private: - mutable const Map<StringName, Variant> *current_options = nullptr; + mutable const HashMap<StringName, Variant> *current_options = nullptr; mutable const Dictionary *current_options_dict = nullptr; List<ResourceImporter::ImportOption> *current_option_list = nullptr; InternalImportCategory current_category = INTERNAL_IMPORT_CATEGORY_MAX; @@ -133,16 +133,16 @@ public: void add_import_option_advanced(Variant::Type p_type, const String &p_name, Variant p_default_value, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = String(), int p_usage_flags = PROPERTY_USAGE_DEFAULT); virtual void get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options); - virtual Variant get_internal_option_visibility(InternalImportCategory p_category, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const; - virtual Variant get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; + virtual Variant get_internal_option_visibility(InternalImportCategory p_category, bool p_for_animation, const String &p_option, const HashMap<StringName, Variant> &p_options) const; + virtual Variant get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const HashMap<StringName, Variant> &p_options) const; virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options); virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options); - virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const; + virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const HashMap<StringName, Variant> &p_options) const; - virtual void pre_process(Node *p_scene, const Map<StringName, Variant> &p_options); - virtual void post_process(Node *p_scene, const Map<StringName, Variant> &p_options); + virtual void pre_process(Node *p_scene, const HashMap<StringName, Variant> &p_options); + virtual void post_process(Node *p_scene, const HashMap<StringName, Variant> &p_options); EditorScenePostImportPlugin() {} }; @@ -263,16 +263,16 @@ public: }; void get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const; - bool get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; - bool get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; + bool get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const HashMap<StringName, Variant> &p_options) const; + bool get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const HashMap<StringName, Variant> &p_options) const; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; // Import scenes *after* everything else (such as textures). virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; } - Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &r_collision_map, Pair<PackedVector3Array, PackedInt32Array> *r_occluder_arrays, List<Pair<NodePath, Node *>> &r_node_renames); - Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, Set<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); + Node *_pre_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &r_collision_map, Pair<PackedVector3Array, PackedInt32Array> *r_occluder_arrays, List<Pair<NodePath, Node *>> &r_node_renames); + Node *_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, RBSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks); void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all); @@ -280,7 +280,7 @@ public: void _compress_animations(AnimationPlayer *anim, int p_page_size_kb); Node *pre_import(const String &p_source_file); - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; virtual bool has_advanced_options() const override; virtual void show_advanced_options(const String &p_path) override; @@ -302,7 +302,7 @@ class EditorSceneFormatImporterESCN : public EditorSceneFormatImporter { public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; }; #include "scene/resources/box_shape_3d.h" diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp index 1d70a47daa..64839bf199 100644 --- a/editor/import/resource_importer_shader_file.cpp +++ b/editor/import/resource_importer_shader_file.cpp @@ -68,7 +68,7 @@ String ResourceImporterShaderFile::get_preset_name(int p_idx) const { void ResourceImporterShaderFile::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { } -bool ResourceImporterShaderFile::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterShaderFile::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } @@ -89,7 +89,7 @@ static String _include_function(const String &p_path, void *userpointer) { return file_inc->get_as_utf8_string(); } -Error ResourceImporterShaderFile::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterShaderFile::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { /* STEP 1, Read shader code */ Error err; diff --git a/editor/import/resource_importer_shader_file.h b/editor/import/resource_importer_shader_file.h index 858c2e783c..9d0ef88b05 100644 --- a/editor/import/resource_importer_shader_file.h +++ b/editor/import/resource_importer_shader_file.h @@ -47,9 +47,9 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterShaderFile(); }; diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 6770eef543..5364b53b57 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -160,7 +160,7 @@ String ResourceImporterTexture::get_resource_type() const { return "CompressedTexture2D"; } -bool ResourceImporterTexture::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterTexture::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { if (p_option == "compress/lossy_quality") { int compress_mode = int(p_options["compress/mode"]); if (compress_mode != COMPRESS_LOSSY && compress_mode != COMPRESS_VRAM_COMPRESSED) { @@ -402,7 +402,7 @@ void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String save_to_ctex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality); } -Error ResourceImporterTexture::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterTexture::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { CompressMode compress_mode = CompressMode(int(p_options["compress/mode"])); const float lossy = p_options["compress/lossy_quality"]; const int pack_channels = p_options["compress/channel_pack"]; diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index b932c598a2..7def2d4f77 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -65,7 +65,7 @@ protected: RS::TextureDetectRoughnessChannel channel_for_roughness = RS::TEXTURE_DETECT_ROUGHNESS_R; }; - Map<StringName, MakeInfo> make_flags; + HashMap<StringName, MakeInfo> make_flags; static void _texture_reimport_roughness(const Ref<CompressedTexture2D> &p_tex, const String &p_normal_path, RenderingServer::TextureDetectRoughnessChannel p_channel); static void _texture_reimport_3d(const Ref<CompressedTexture2D> &p_tex); @@ -96,9 +96,9 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; void update_imports(); diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index cd481e009e..aa338a6c0d 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -59,7 +59,7 @@ String ResourceImporterTextureAtlas::get_resource_type() const { return "Texture2D"; } -bool ResourceImporterTextureAtlas::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterTextureAtlas::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } @@ -82,7 +82,7 @@ String ResourceImporterTextureAtlas::get_option_group_file() const { return "atlas_file"; } -Error ResourceImporterTextureAtlas::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterTextureAtlas::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { /* If this happens, it's because the atlas_file field was not filled, so just import a broken texture */ //use an xpm because it's size independent, the editor images are vector and size dependent @@ -188,7 +188,7 @@ static void _plot_triangle(Vector2i *vertices, const Vector2i &p_offset, bool p_ } } -Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file, const Map<String, Map<StringName, Variant>> &p_source_file_options, const Map<String, String> &p_base_paths) { +Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file, const HashMap<String, HashMap<StringName, Variant>> &p_source_file_options, const HashMap<String, String> &p_base_paths) { ERR_FAIL_COND_V(p_source_file_options.size() == 0, ERR_BUG); //should never happen Vector<EditorAtlasPacker::Chart> charts; @@ -197,10 +197,10 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file pack_data_files.resize(p_source_file_options.size()); int idx = 0; - for (const Map<String, Map<StringName, Variant>>::Element *E = p_source_file_options.front(); E; E = E->next(), idx++) { + for (const KeyValue<String, HashMap<StringName, Variant>> &E : p_source_file_options) { PackData &pack_data = pack_data_files.write[idx]; - const String &source = E->key(); - const Map<StringName, Variant> &options = E->get(); + const String &source = E.key; + const HashMap<StringName, Variant> &options = E.value; Ref<Image> image; image.instantiate(); @@ -271,6 +271,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file pack_data.chart_vertices.push_back(polygons[j]); } } + idx++; } //pack the charts @@ -318,7 +319,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file //save the images idx = 0; - for (const Map<String, Map<StringName, Variant>>::Element *E = p_source_file_options.front(); E; E = E->next(), idx++) { + for (const KeyValue<String, HashMap<StringName, Variant>> &E : p_source_file_options) { PackData &pack_data = pack_data_files.write[idx]; Ref<Texture2D> texture; @@ -394,8 +395,9 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file //mesh } - String save_path = p_base_paths[E->key()] + ".res"; + String save_path = p_base_paths[E.key] + ".res"; ResourceSaver::save(save_path, texture); + idx++; } return OK; diff --git a/editor/import/resource_importer_texture_atlas.h b/editor/import/resource_importer_texture_atlas.h index a5e47dee99..971eb067df 100644 --- a/editor/import/resource_importer_texture_atlas.h +++ b/editor/import/resource_importer_texture_atlas.h @@ -61,11 +61,11 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; virtual String get_option_group_file() const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; - virtual Error import_group_file(const String &p_group_file, const Map<String, Map<StringName, Variant>> &p_source_file_options, const Map<String, String> &p_base_paths) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import_group_file(const String &p_group_file, const HashMap<String, HashMap<StringName, Variant>> &p_source_file_options, const HashMap<String, String> &p_base_paths) override; ResourceImporterTextureAtlas(); }; diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index 154970f7ed..362940dc17 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -58,7 +58,7 @@ String ResourceImporterWAV::get_resource_type() const { return "AudioStreamSample"; } -bool ResourceImporterWAV::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterWAV::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { if (p_option == "force/max_rate_hz" && !bool(p_options["force/max_rate"])) { return false; } @@ -93,7 +93,7 @@ void ResourceImporterWAV::get_import_options(const String &p_path, List<ImportOp r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Disabled,RAM (Ima-ADPCM)"), 0)); } -Error ResourceImporterWAV::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterWAV::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { /* STEP 1, READ WAVE FILE */ Error err; diff --git a/editor/import/resource_importer_wav.h b/editor/import/resource_importer_wav.h index 2316ce80e5..739ec9b181 100644 --- a/editor/import/resource_importer_wav.h +++ b/editor/import/resource_importer_wav.h @@ -47,7 +47,7 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; static void _compress_ima_adpcm(const Vector<float> &p_data, Vector<uint8_t> &dst_data) { static const int16_t _ima_adpcm_step_table[89] = { @@ -140,7 +140,7 @@ public: } } - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterWAV(); }; diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 8866794505..3c68477564 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -43,9 +43,9 @@ class SceneImportSettingsData : public Object { GDCLASS(SceneImportSettingsData, Object) friend class SceneImportSettings; - Map<StringName, Variant> *settings = nullptr; - Map<StringName, Variant> current; - Map<StringName, Variant> defaults; + HashMap<StringName, Variant> *settings = nullptr; + HashMap<StringName, Variant> current; + HashMap<StringName, Variant> defaults; List<ResourceImporter::ImportOption> options; bool hide_options = false; String path; @@ -501,7 +501,7 @@ void SceneImportSettings::_update_camera() { camera->set_transform(xf); } -void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Variant> &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category) { +void SceneImportSettings::_load_default_subresource_settings(HashMap<StringName, Variant> &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category) { if (base_subresource_settings.has(p_type)) { Dictionary d = base_subresource_settings[p_type]; if (d.has(p_import_id)) { @@ -852,7 +852,7 @@ void SceneImportSettings::_viewport_input(const Ref<InputEvent> &p_input) { } void SceneImportSettings::_re_import() { - Map<StringName, Variant> main_settings; + HashMap<StringName, Variant> main_settings; main_settings = defaults; main_settings.erase("_subresources"); diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h index ec24a8a5a5..cbd105045a 100644 --- a/editor/import/scene_import_settings.h +++ b/editor/import/scene_import_settings.h @@ -103,9 +103,9 @@ class SceneImportSettings : public ConfirmationDialog { float cam_rot_y = -Math_PI / 4; float cam_zoom = 1; - Map<StringName, Variant> settings; + HashMap<StringName, Variant> settings; }; - Map<String, MaterialData> material_map; + HashMap<String, MaterialData> material_map; struct MeshData { bool has_import_id; @@ -116,31 +116,31 @@ class SceneImportSettings : public ConfirmationDialog { float cam_rot_x = -Math_PI / 4; float cam_rot_y = -Math_PI / 4; float cam_zoom = 1; - Map<StringName, Variant> settings; + HashMap<StringName, Variant> settings; }; - Map<String, MeshData> mesh_map; + HashMap<String, MeshData> mesh_map; struct AnimationData { Ref<Animation> animation; TreeItem *scene_node = nullptr; - Map<StringName, Variant> settings; + HashMap<StringName, Variant> settings; }; - Map<String, AnimationData> animation_map; + HashMap<String, AnimationData> animation_map; struct NodeData { Node *node = nullptr; TreeItem *scene_node = nullptr; - Map<StringName, Variant> settings; + HashMap<StringName, Variant> settings; }; - Map<String, NodeData> node_map; + HashMap<String, NodeData> node_map; void _fill_material(Tree *p_tree, const Ref<Material> &p_material, TreeItem *p_parent); void _fill_mesh(Tree *p_tree, const Ref<Mesh> &p_mesh, TreeItem *p_parent); void _fill_animation(Tree *p_tree, const Ref<Animation> &p_anim, const String &p_name, TreeItem *p_parent); void _fill_scene(Node *p_node, TreeItem *p_parent_item); - Set<Ref<Mesh>> mesh_set; - Set<Ref<Material>> material_set; + RBSet<Ref<Mesh>> mesh_set; + RBSet<Ref<Material>> material_set; String selected_type; String selected_id; @@ -156,7 +156,7 @@ class SceneImportSettings : public ConfirmationDialog { void _viewport_input(const Ref<InputEvent> &p_input); - Map<StringName, Variant> defaults; + HashMap<StringName, Variant> defaults; SceneImportSettingsData *scene_import_settings_data = nullptr; @@ -187,7 +187,7 @@ class SceneImportSettings : public ConfirmationDialog { Dictionary base_subresource_settings; - void _load_default_subresource_settings(Map<StringName, Variant> &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category); + void _load_default_subresource_settings(HashMap<StringName, Variant> &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category); bool editing_animation = false; diff --git a/editor/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp index ff6b34dd36..9d96822aef 100644 --- a/editor/import_defaults_editor.cpp +++ b/editor/import_defaults_editor.cpp @@ -44,8 +44,8 @@ class ImportDefaultsEditorSettings : public Object { GDCLASS(ImportDefaultsEditorSettings, Object) friend class ImportDefaultsEditor; List<PropertyInfo> properties; - Map<StringName, Variant> values; - Map<StringName, Variant> default_values; + HashMap<StringName, Variant> values; + HashMap<StringName, Variant> default_values; Ref<ResourceImporter> importer; diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 4df46f2348..56b15c3b1a 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -39,11 +39,11 @@ class ImportDockParameters : public Object { GDCLASS(ImportDockParameters, Object); public: - Map<StringName, Variant> values; + HashMap<StringName, Variant> values; List<PropertyInfo> properties; Ref<ResourceImporter> importer; Vector<String> paths; - Set<StringName> checked; + RBSet<StringName> checked; bool checking; String base_options_path; @@ -193,8 +193,8 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) { clear(); // Use the value that is repeated the most. - Map<String, Dictionary> value_frequency; - Set<String> extensions; + HashMap<String, Dictionary> value_frequency; + RBSet<String> extensions; for (int i = 0; i < p_paths.size(); i++) { Ref<ConfigFile> config; diff --git a/editor/import_dock.h b/editor/import_dock.h index f522b0bced..7f4aa1ddb3 100644 --- a/editor/import_dock.h +++ b/editor/import_dock.h @@ -51,7 +51,7 @@ class ImportDock : public VBoxContainer { EditorInspector *import_opts = nullptr; List<PropertyInfo> properties; - Map<StringName, Variant> property_values; + HashMap<StringName, Variant> property_values; ConfirmationDialog *reimport_confirm = nullptr; Label *label_warning = nullptr; diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index a62d1af477..c5dacd8d21 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -149,7 +149,7 @@ void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) { if (current) { List<PropertyInfo> props; current->get_property_list(&props); - Map<Ref<Resource>, Ref<Resource>> duplicates; + HashMap<Ref<Resource>, Ref<Resource>> duplicates; for (const PropertyInfo &prop_info : props) { if (!(prop_info.usage & PROPERTY_USAGE_STORAGE)) { continue; @@ -307,7 +307,7 @@ void InspectorDock::_prepare_history() { history_menu->get_popup()->clear(); Ref<Texture2D> base_icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons")); - Set<ObjectID> already; + RBSet<ObjectID> already; for (int i = editor_history->get_history_len() - 1; i >= history_to; i--) { ObjectID id = editor_history->get_history_obj(i); Object *obj = ObjectDB::get_instance(id); diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 755bf7ce07..77e4905341 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -47,7 +47,7 @@ void PluginConfigDialog::_clear_fields() { } void PluginConfigDialog::_on_confirmed() { - String path = "res://addons/" + subfolder_edit->get_text(); + String path = "res://addons/" + _get_subfolder(); if (!_edit_mode) { Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES); @@ -56,32 +56,35 @@ void PluginConfigDialog::_on_confirmed() { } } + int lang_idx = script_option_edit->get_selected(); + String ext = ScriptServer::get_language(lang_idx)->get_extension(); + String script_name = script_edit->get_text().is_empty() ? _get_subfolder() : script_edit->get_text(); + if (script_name.get_extension().is_empty()) { + script_name += "." + ext; + } + String script_path = path.plus_file(script_name); + Ref<ConfigFile> cf = memnew(ConfigFile); cf->set_value("plugin", "name", name_edit->get_text()); cf->set_value("plugin", "description", desc_edit->get_text()); cf->set_value("plugin", "author", author_edit->get_text()); cf->set_value("plugin", "version", version_edit->get_text()); - cf->set_value("plugin", "script", script_edit->get_text()); + cf->set_value("plugin", "script", script_name); cf->save(path.plus_file("plugin.cfg")); if (!_edit_mode) { - int lang_idx = script_option_edit->get_selected(); - String lang_name = ScriptServer::get_language(lang_idx)->get_name(); - - Ref<Script> script; - String script_path = path.plus_file(script_edit->get_text()); - String class_name = script_path.get_file().get_basename(); + String class_name = script_name.get_basename(); String template_content = ""; Vector<ScriptLanguage::ScriptTemplate> templates = ScriptServer::get_language(lang_idx)->get_built_in_templates("EditorPlugin"); - if (templates.size() > 0) { - template_content = templates.get(0).content; + if (!templates.is_empty()) { + template_content = templates[0].content; } - script = ScriptServer::get_language(lang_idx)->make_template(template_content, class_name, "EditorPlugin"); + Ref<Script> script = ScriptServer::get_language(lang_idx)->make_template(template_content, class_name, "EditorPlugin"); script->set_path(script_path); ResourceSaver::save(script_path, script); - emit_signal(SNAME("plugin_ready"), script.operator->(), active_edit->is_pressed() ? _to_absolute_plugin_path(subfolder_edit->get_text()) : ""); + emit_signal(SNAME("plugin_ready"), script.ptr(), active_edit->is_pressed() ? _to_absolute_plugin_path(_get_subfolder()) : ""); } else { EditorNode::get_singleton()->get_project_settings()->update_plugins(); } @@ -119,27 +122,18 @@ void PluginConfigDialog::_on_required_text_changed(const String &) { name_validation->set_texture(invalid_icon); name_validation->set_tooltip(TTR("Plugin name cannot be blank.")); } - if (script_edit->get_text().get_extension() != ext) { + if ((!script_edit->get_text().get_extension().is_empty() && script_edit->get_text().get_extension() != ext) || script_edit->get_text().ends_with(".")) { is_valid = false; script_validation->set_texture(invalid_icon); script_validation->set_tooltip(vformat(TTR("Script extension must match chosen language extension (.%s)."), ext)); } - if (script_edit->get_text().get_basename().is_empty()) { + if (!subfolder_edit->get_text().is_empty() && !subfolder_edit->get_text().is_valid_filename()) { is_valid = false; - script_validation->set_texture(invalid_icon); - script_validation->set_tooltip(TTR("Script name cannot be blank.")); - } - if (subfolder_edit->get_text().is_empty()) { - is_valid = false; - subfolder_validation->set_texture(invalid_icon); - subfolder_validation->set_tooltip(TTR("Subfolder cannot be blank.")); - } else if (!subfolder_edit->get_text().is_valid_filename()) { subfolder_validation->set_texture(invalid_icon); subfolder_validation->set_tooltip(TTR("Subfolder name is not a valid folder name.")); } else { - Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_RESOURCES); - String path = "res://addons/" + subfolder_edit->get_text(); - if (dir->dir_exists(path) && !_edit_mode) { // Only show this error if in "create" mode. + String path = "res://addons/" + _get_subfolder(); + if (!_edit_mode && DirAccess::exists(path)) { // Only show this error if in "create" mode. is_valid = false; subfolder_validation->set_texture(invalid_icon); subfolder_validation->set_tooltip(TTR("Subfolder cannot be one which already exists.")); @@ -149,6 +143,10 @@ void PluginConfigDialog::_on_required_text_changed(const String &) { get_ok_button()->set_disabled(!is_valid); } +String PluginConfigDialog::_get_subfolder() { + return subfolder_edit->get_text().is_empty() ? name_edit->get_text().replace(" ", "_").to_lower() : subfolder_edit->get_text(); +} + String PluginConfigDialog::_to_absolute_plugin_path(const String &p_plugin_name) { return "res://addons/" + p_plugin_name + "/plugin.cfg"; } @@ -225,6 +223,7 @@ PluginConfigDialog::PluginConfigDialog() { // Plugin Name Label *name_lb = memnew(Label); name_lb->set_text(TTR("Plugin Name:")); + name_lb->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); grid->add_child(name_lb); name_validation = memnew(TextureRect); @@ -239,6 +238,7 @@ PluginConfigDialog::PluginConfigDialog() { // Subfolder Label *subfolder_lb = memnew(Label); subfolder_lb->set_text(TTR("Subfolder:")); + subfolder_lb->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); grid->add_child(subfolder_lb); subfolder_validation = memnew(TextureRect); @@ -253,6 +253,7 @@ PluginConfigDialog::PluginConfigDialog() { // Description Label *desc_lb = memnew(Label); desc_lb->set_text(TTR("Description:")); + desc_lb->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); grid->add_child(desc_lb); Control *desc_spacer = memnew(Control); @@ -266,6 +267,7 @@ PluginConfigDialog::PluginConfigDialog() { // Author Label *author_lb = memnew(Label); author_lb->set_text(TTR("Author:")); + author_lb->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); grid->add_child(author_lb); Control *author_spacer = memnew(Control); @@ -278,6 +280,7 @@ PluginConfigDialog::PluginConfigDialog() { // Version Label *version_lb = memnew(Label); version_lb->set_text(TTR("Version:")); + version_lb->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); grid->add_child(version_lb); Control *version_spacer = memnew(Control); @@ -290,6 +293,7 @@ PluginConfigDialog::PluginConfigDialog() { // Language dropdown Label *script_option_lb = memnew(Label); script_option_lb->set_text(TTR("Language:")); + script_option_lb->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); grid->add_child(script_option_lb); Control *script_opt_spacer = memnew(Control); @@ -311,6 +315,7 @@ PluginConfigDialog::PluginConfigDialog() { // Plugin Script Name Label *script_lb = memnew(Label); script_lb->set_text(TTR("Script Name:")); + script_lb->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); grid->add_child(script_lb); script_validation = memnew(TextureRect); @@ -326,6 +331,7 @@ PluginConfigDialog::PluginConfigDialog() { // TODO Make this option work better with languages like C#. Right now, it does not work because the C# project must be compiled first. Label *active_lb = memnew(Label); active_lb->set_text(TTR("Activate now?")); + active_lb->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); grid->add_child(active_lb); Control *active_spacer = memnew(Control); diff --git a/editor/plugin_config_dialog.h b/editor/plugin_config_dialog.h index 5c6043da12..6e0cbea378 100644 --- a/editor/plugin_config_dialog.h +++ b/editor/plugin_config_dialog.h @@ -61,6 +61,7 @@ class PluginConfigDialog : public ConfirmationDialog { void _on_cancelled(); void _on_language_changed(const int p_language); void _on_required_text_changed(const String &p_text); + String _get_subfolder(); static String _to_absolute_plugin_path(const String &p_plugin_name); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 0b3164aada..08df704f44 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -459,16 +459,22 @@ void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) { undo_redo->commit_action(); } -void AnimationNodeBlendTreeEditor::_delete_nodes_request() { +void AnimationNodeBlendTreeEditor::_delete_nodes_request(const TypedArray<StringName> &p_nodes) { List<StringName> to_erase; - for (int i = 0; i < graph->get_child_count(); i++) { - GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); - if (gn) { - if (gn->is_selected() && gn->is_close_button_visible()) { - to_erase.push_back(gn->get_name()); + if (p_nodes.is_empty()) { + for (int i = 0; i < graph->get_child_count(); i++) { + GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); + if (gn) { + if (gn->is_selected() && gn->is_close_button_visible()) { + to_erase.push_back(gn->get_name()); + } } } + } else { + for (int i = 0; i < p_nodes.size(); i++) { + to_erase.push_back(p_nodes[i]); + } } if (to_erase.is_empty()) { @@ -557,8 +563,8 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano updating = true; - Set<String> paths; - HashMap<String, Set<String>> types; + RBSet<String> paths; + HashMap<String, RBSet<String>> types; { List<StringName> animations; player->get_animation_list(&animations); @@ -595,9 +601,9 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano filters->clear(); TreeItem *root = filters->create_item(); - Map<String, TreeItem *> parenthood; + HashMap<String, TreeItem *> parenthood; - for (Set<String>::Element *E = paths.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = paths.front(); E; E = E->next()) { NodePath path = E->get(); TreeItem *ti = nullptr; String accum; @@ -692,7 +698,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano //just a node, not a property track String types_text = "["; if (types.has(path)) { - Set<String>::Element *F = types[path].front(); + RBSet<String>::Element *F = types[path].front(); types_text += F->get(); while (F->next()) { F = F->next(); @@ -903,8 +909,8 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima } //update animations - for (Map<StringName, ProgressBar *>::Element *E = animations.front(); E; E = E->next()) { - if (E->key() == prev_name) { + for (const KeyValue<StringName, ProgressBar *> &E : animations) { + if (E.key == prev_name) { animations[new_name] = animations[prev_name]; animations.erase(prev_name); break; diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index cacf8379f9..b5bf91a1da 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -61,7 +61,7 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { Tree *filters = nullptr; CheckBox *filter_enabled = nullptr; - Map<StringName, ProgressBar *> animations; + HashMap<StringName, ProgressBar *> animations; Vector<EditorProperty *> visible_properties; String to_node = ""; @@ -103,7 +103,7 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { void _open_in_editor(const String &p_which); void _anim_selected(int p_index, Array p_options, const String &p_node); void _delete_request(const String &p_which); - void _delete_nodes_request(); + void _delete_nodes_request(const TypedArray<StringName> &p_nodes); bool _update_filters(const Ref<AnimationNode> &anode); void _edit_filters(const String &p_which); diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 920fe347ca..2b90b4cdd6 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -609,7 +609,7 @@ void AnimationNodeStateMachineEditor::_group_selected_nodes() { void AnimationNodeStateMachineEditor::_ungroup_selected_nodes() { bool find = false; - Set<StringName> new_selected_nodes; + RBSet<StringName> new_selected_nodes; for (const StringName &E : selected_nodes) { Ref<AnimationNodeStateMachine> group_sm = state_machine->get_node(E); diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index 1247d99389..3db4d91367 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -64,7 +64,7 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { PanelContainer *panel = nullptr; StringName selected_node; - Set<StringName> selected_nodes; + RBSet<StringName> selected_nodes; HScrollBar *h_scroll = nullptr; VScrollBar *v_scroll = nullptr; @@ -105,7 +105,7 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { Point2 box_selecting_from; Point2 box_selecting_to; Rect2 box_selecting_rect; - Set<StringName> previous_selected; + RBSet<StringName> previous_selected; bool dragging_selected_attempt = false; bool dragging_selected = false; diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index 24d7c1d24c..af961e1403 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -252,7 +252,7 @@ class EditorAssetLibrary : public PanelContainer { }; int last_queue_id; - Map<int, ImageQueue> image_queue; + HashMap<int, ImageQueue> image_queue; void _image_update(bool use_cache, bool final, const PackedByteArray &p_data, int p_queue_id); void _image_request_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data, int p_queue_id); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index c129d705c9..a7e3d17fdc 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -562,7 +562,11 @@ void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, c } if (canvas_item && canvas_item->is_visible_in_tree() && (include_locked_nodes || !_is_node_locked(canvas_item))) { - Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform(); + Transform2D xform = p_canvas_xform; + if (!canvas_item->is_set_as_top_level()) { + xform *= p_parent_xform; + } + xform *= canvas_item->get_transform(); Rect2 rect = canvas_item->_edit_get_rect(); if (r_first) { r_rect = Rect2(xform.xform(rect.get_center()), Size2()); @@ -608,7 +612,11 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no } if (canvas_item && canvas_item->is_visible_in_tree()) { - Transform2D xform = (p_parent_xform * p_canvas_xform * canvas_item->get_transform()).affine_inverse(); + Transform2D xform = p_canvas_xform; + if (!canvas_item->is_set_as_top_level()) { + xform *= p_parent_xform; + } + xform = (xform * canvas_item->get_transform()).affine_inverse(); const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length() / zoom; if (canvas_item->_edit_is_selected_on_click(xform.xform(p_pos), local_grab_distance)) { Node2D *node = Object::cast_to<Node2D>(canvas_item); @@ -698,7 +706,11 @@ void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_n } if (canvas_item && canvas_item->is_visible_in_tree() && !locked && editable) { - Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform(); + Transform2D xform = p_canvas_xform; + if (!canvas_item->is_set_as_top_level()) { + xform *= p_parent_xform; + } + xform *= canvas_item->get_transform(); if (canvas_item->_edit_use_rect()) { Rect2 rect = canvas_item->_edit_get_rect(); @@ -4085,7 +4097,7 @@ void CanvasItemEditor::_button_tool_select(int p_index) { } void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation, bool p_scale, bool p_on_existing) { - const Map<Node *, Object *> &selection = editor_selection->get_selection(); + const HashMap<Node *, Object *> &selection = editor_selection->get_selection(); for (const KeyValue<Node *, Object *> &E : selection) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key); @@ -4396,7 +4408,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { case ANIM_COPY_POSE: { pose_clipboard.clear(); - const Map<Node *, Object *> &selection = editor_selection->get_selection(); + const HashMap<Node *, Object *> &selection = editor_selection->get_selection(); for (const KeyValue<Node *, Object *> &E : selection) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key); @@ -4442,7 +4454,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { } break; case ANIM_CLEAR_POSE: { - Map<Node *, Object *> &selection = editor_selection->get_selection(); + HashMap<Node *, Object *> &selection = editor_selection->get_selection(); for (const KeyValue<Node *, Object *> &E : selection) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key); @@ -4511,7 +4523,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { } break; case SKELETON_MAKE_BONES: { - Map<Node *, Object *> &selection = editor_selection->get_selection(); + HashMap<Node *, Object *> &selection = editor_selection->get_selection(); Node *editor_root = EditorNode::get_singleton()->get_edited_scene()->get_tree()->get_edited_scene_root(); undo_redo->create_action(TTR("Create Custom Bone2D(s) from Node(s)")); @@ -4559,7 +4571,7 @@ void CanvasItemEditor::_focus_selection(int p_op) { Rect2 rect; int count = 0; - const Map<Node *, Object *> &selection = editor_selection->get_selection(); + const HashMap<Node *, Object *> &selection = editor_selection->get_selection(); for (const KeyValue<Node *, Object *> &E : selection) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key); if (!canvas_item) { diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 7a49041131..a4099079f3 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -283,7 +283,7 @@ private: } }; - Map<BoneKey, BoneList> bone_list; + HashMap<BoneKey, BoneList> bone_list; struct PoseClipboard { Vector2 pos; diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index 4ab03c123b..ebb0da1ad7 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -335,7 +335,7 @@ void EditorPropertySizeFlags::setup(const Vector<String> &p_options, bool p_vert return; } - Map<int, String> flags; + HashMap<int, String> flags; for (int i = 0, j = 0; i < p_options.size(); i++, j++) { Vector<String> text_split = p_options[i].split(":"); int64_t current_val = text_split[1].to_int(); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 80fc1c64d0..0560365a58 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -481,8 +481,8 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from, List<String> kwors; scr->get_language()->get_reserved_words(&kwors); - Set<String> control_flow_keywords; - Set<String> keywords; + RBSet<String> control_flow_keywords; + RBSet<String> keywords; for (const String &E : kwors) { if (scr->get_language()->is_control_flow_keyword(E)) { diff --git a/editor/plugins/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h index 8ed72b1c42..28c37fed52 100644 --- a/editor/plugins/gdextension_export_plugin.h +++ b/editor/plugins/gdextension_export_plugin.h @@ -35,10 +35,10 @@ class GDExtensionExportPlugin : public EditorExportPlugin { protected: - virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features); + virtual void _export_file(const String &p_path, const String &p_type, const RBSet<String> &p_features); }; -void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) { +void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p_type, const RBSet<String> &p_features) { if (p_type != "NativeExtension") { return; } diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp index 4b1081ed92..b022fcc1c9 100644 --- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp @@ -42,7 +42,7 @@ bool GPUParticles3DEditorBase::_generate(Vector<Vector3> &points, Vector<Vector3 if (emission_fill->get_selected() < 2) { float area_accum = 0; - Map<float, int> triangle_area_map; + RBMap<float, int> triangle_area_map; for (int i = 0; i < geometry.size(); i++) { float area = geometry[i].get_area(); @@ -63,9 +63,9 @@ bool GPUParticles3DEditorBase::_generate(Vector<Vector3> &points, Vector<Vector3 for (int i = 0; i < emissor_count; i++) { float areapos = Math::random(0.0f, area_accum); - Map<float, int>::Element *E = triangle_area_map.find_closest(areapos); + RBMap<float, int>::Iterator E = triangle_area_map.find_closest(areapos); ERR_FAIL_COND_V(!E, false); - int index = E->get(); + int index = E->value; ERR_FAIL_INDEX_V(index, geometry.size(), false); // ok FINALLY get face diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index d33803213a..3094e24659 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -77,12 +77,14 @@ void MeshInstance3DEditor::_menu_option(int p_option) { StaticBody3D *body = memnew(StaticBody3D); body->add_child(cshape, true); - Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner(); + Node *owner = get_tree()->get_edited_scene_root(); ur->create_action(TTR("Create Static Trimesh Body")); ur->add_do_method(node, "add_child", body, true); ur->add_do_method(body, "set_owner", owner); ur->add_do_method(cshape, "set_owner", owner); + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", body); + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape); ur->add_do_reference(body); ur->add_undo_method(node, "remove_child", body); ur->commit_action(); @@ -112,11 +114,13 @@ void MeshInstance3DEditor::_menu_option(int p_option) { StaticBody3D *body = memnew(StaticBody3D); body->add_child(cshape, true); - Node *owner = instance == get_tree()->get_edited_scene_root() ? instance : instance->get_owner(); + Node *owner = get_tree()->get_edited_scene_root(); ur->add_do_method(instance, "add_child", body, true); ur->add_do_method(body, "set_owner", owner); ur->add_do_method(cshape, "set_owner", owner); + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", body); + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape); ur->add_do_reference(body); ur->add_undo_method(instance, "remove_child", body); } @@ -141,7 +145,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) { cshape->set_shape(shape); cshape->set_transform(node->get_transform()); - Node *owner = node->get_owner(); + Node *owner = get_tree()->get_edited_scene_root(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); @@ -150,6 +154,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) { ur->add_do_method(node->get_parent(), "add_child", cshape, true); ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); ur->add_do_method(cshape, "set_owner", owner); + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape); ur->add_do_reference(cshape); ur->add_undo_method(node->get_parent(), "remove_child", cshape); ur->commit_action(); @@ -184,11 +189,12 @@ void MeshInstance3DEditor::_menu_option(int p_option) { cshape->set_shape(shape); cshape->set_transform(node->get_transform()); - Node *owner = node->get_owner(); + Node *owner = get_tree()->get_edited_scene_root(); ur->add_do_method(node->get_parent(), "add_child", cshape, true); ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); ur->add_do_method(cshape, "set_owner", owner); + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape); ur->add_do_reference(cshape); ur->add_undo_method(node->get_parent(), "remove_child", cshape); @@ -217,14 +223,17 @@ void MeshInstance3DEditor::_menu_option(int p_option) { for (int i = 0; i < shapes.size(); i++) { CollisionShape3D *cshape = memnew(CollisionShape3D); + cshape->set_name("CollisionShape3D"); + cshape->set_shape(shapes[i]); cshape->set_transform(node->get_transform()); - Node *owner = node->get_owner(); + Node *owner = get_tree()->get_edited_scene_root(); ur->add_do_method(node->get_parent(), "add_child", cshape); ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); ur->add_do_method(cshape, "set_owner", owner); + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape); ur->add_do_reference(cshape); ur->add_undo_method(node->get_parent(), "remove_child", cshape); } @@ -243,13 +252,14 @@ void MeshInstance3DEditor::_menu_option(int p_option) { NavigationRegion3D *nmi = memnew(NavigationRegion3D); nmi->set_navigation_mesh(nmesh); - Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner(); + Node *owner = get_tree()->get_edited_scene_root(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Create Navigation Mesh")); ur->add_do_method(node, "add_child", nmi, true); ur->add_do_method(nmi, "set_owner", owner); + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", nmi); ur->add_do_reference(nmi); ur->add_undo_method(node, "remove_child", nmi); @@ -267,13 +277,52 @@ void MeshInstance3DEditor::_menu_option(int p_option) { return; } - Error err = mesh2->lightmap_unwrap(node->get_global_transform()); + String path = mesh2->get_path(); + int srpos = path.find("::"); + if (srpos != -1) { + String base = path.substr(0, srpos); + if (ResourceLoader::get_resource_type(base) == "PackedScene") { + if (!get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->get_scene_file_path() != base) { + err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it does not belong to the edited scene. Make it unique first.")); + err_dialog->popup_centered(); + return; + } + } else { + if (FileAccess::exists(path + ".import")) { + err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it belongs to another resource which was imported from another file type. Make it unique first.")); + err_dialog->popup_centered(); + return; + } + } + } else { + if (FileAccess::exists(path + ".import")) { + err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it was imported from another file type. Make it unique first.")); + err_dialog->popup_centered(); + return; + } + } + + Ref<ArrayMesh> unwrapped_mesh = mesh2->duplicate(false); + + Error err = unwrapped_mesh->lightmap_unwrap(node->get_global_transform()); if (err != OK) { err_dialog->set_text(TTR("UV Unwrap failed, mesh may not be manifold?")); err_dialog->popup_centered(); return; } + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Unwrap UV2")); + + ur->add_do_method(node, "set_mesh", unwrapped_mesh); + ur->add_do_reference(node); + ur->add_do_reference(mesh2.ptr()); + + ur->add_undo_method(node, "set_mesh", mesh2); + ur->add_undo_reference(unwrapped_mesh.ptr()); + + ur->commit_action(); + } break; case MENU_OPTION_DEBUG_UV1: { Ref<Mesh> mesh2 = node->get_mesh(); @@ -324,7 +373,7 @@ void MeshInstance3DEditor::_create_uv_lines(int p_layer) { Ref<Mesh> mesh = node->get_mesh(); ERR_FAIL_COND(!mesh.is_valid()); - Set<MeshInstance3DEditorEdgeSort> edges; + RBSet<MeshInstance3DEditorEdgeSort> edges; uv_lines.clear(); for (int i = 0; i < mesh->get_surface_count(); i++) { if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { @@ -418,10 +467,7 @@ void MeshInstance3DEditor::_create_outline_mesh() { MeshInstance3D *mi = memnew(MeshInstance3D); mi->set_mesh(mesho); - Node *owner = node->get_owner(); - if (get_tree()->get_edited_scene_root() == node) { - owner = node; - } + Node *owner = get_tree()->get_edited_scene_root(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); @@ -429,6 +475,7 @@ void MeshInstance3DEditor::_create_outline_mesh() { ur->add_do_method(node, "add_child", mi, true); ur->add_do_method(mi, "set_owner", owner); + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", mi); ur->add_do_reference(mi); ur->add_undo_method(node, "remove_child", mi); diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index 423ec5f4ed..914ccb54c1 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -71,7 +71,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, p_library->clear(); } - Map<int, MeshInstance3D *> mesh_instances; + HashMap<int, MeshInstance3D *> mesh_instances; for (int i = 0; i < p_scene->get_child_count(); i++) { Node *child = p_scene->get_child(i); diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp index b54fa41e88..0fab3aed0d 100644 --- a/editor/plugins/multimesh_editor_plugin.cpp +++ b/editor/plugins/multimesh_editor_plugin.cpp @@ -141,7 +141,7 @@ void MultiMeshEditor::_populate() { const Face3 *r = faces.ptr(); float area_accum = 0; - Map<float, int> triangle_area_map; + RBMap<float, int> triangle_area_map; for (int i = 0; i < facecount; i++) { float area = r[i].get_area(); if (area < CMP_EPSILON) { @@ -180,9 +180,9 @@ void MultiMeshEditor::_populate() { for (int i = 0; i < instance_count; i++) { float areapos = Math::random(0.0f, area_accum); - Map<float, int>::Element *E = triangle_area_map.find_closest(areapos); + RBMap<float, int>::Iterator E = triangle_area_map.find_closest(areapos); ERR_FAIL_COND(!E); - int index = E->get(); + int index = E->value; ERR_FAIL_INDEX(index, facecount); // ok FINALLY get face diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 6829e25ef3..58cdf3533c 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -2993,10 +2993,15 @@ void GPUParticles3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { //// GPUParticlesCollision3DGizmoPlugin::GPUParticlesCollision3DGizmoPlugin() { - Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particle_collision", Color(0.5, 0.7, 1)); - create_material("shape_material", gizmo_color); - gizmo_color.a = 0.15; - create_material("shape_material_internal", gizmo_color); + Color gizmo_color_attractor = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particle_attractor", Color(1, 0.7, 0.5)); + create_material("shape_material_attractor", gizmo_color_attractor); + gizmo_color_attractor.a = 0.15; + create_material("shape_material_attractor_internal", gizmo_color_attractor); + + Color gizmo_color_collision = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particle_collision", Color(0.5, 0.7, 1)); + create_material("shape_material_collision", gizmo_color_collision); + gizmo_color_collision.a = 0.15; + create_material("shape_material_collision_internal", gizmo_color_collision); create_handle_material("handles"); } @@ -3122,12 +3127,17 @@ void GPUParticlesCollision3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->clear(); - const Ref<Material> material = - get_material("shape_material", p_gizmo); - const Ref<Material> material_internal = - get_material("shape_material_internal", p_gizmo); + Ref<Material> material; + Ref<Material> material_internal; + if (Object::cast_to<GPUParticlesAttractor3D>(cs)) { + material = get_material("shape_material_attractor", p_gizmo); + material_internal = get_material("shape_material_attractor_internal", p_gizmo); + } else { + material = get_material("shape_material_collision", p_gizmo); + material_internal = get_material("shape_material_collision_internal", p_gizmo); + } - Ref<Material> handles_material = get_material("handles"); + const Ref<Material> handles_material = get_material("handles"); if (Object::cast_to<GPUParticlesCollisionSphere3D>(cs) || Object::cast_to<GPUParticlesAttractorSphere3D>(cs)) { float r = cs->call("get_radius"); @@ -3789,7 +3799,7 @@ void LightmapGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->clear(); Vector<Vector3> lines; - Set<Vector2i> lines_found; + RBSet<Vector2i> lines_found; Vector<Vector3> points = data->get_capture_points(); if (points.size() == 0) { @@ -4755,7 +4765,7 @@ void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { return; } - Map<_EdgeKey, bool> edge_map; + HashMap<_EdgeKey, bool, _EdgeKey> edge_map; Vector<Vector3> tmeshfaces; tmeshfaces.resize(faces.size() * 3); @@ -4773,10 +4783,10 @@ void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { SWAP(ek.from, ek.to); } - Map<_EdgeKey, bool>::Element *F = edge_map.find(ek); + HashMap<_EdgeKey, bool, _EdgeKey>::Iterator F = edge_map.find(ek); if (F) { - F->get() = false; + F->value = false; } else { edge_map[ek] = true; diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h index f859ceda3b..a0d7715347 100644 --- a/editor/plugins/node_3d_editor_gizmos.h +++ b/editor/plugins/node_3d_editor_gizmos.h @@ -31,8 +31,8 @@ #ifndef NODE_3D_EDITOR_GIZMOS_H #define NODE_3D_EDITOR_GIZMOS_H +#include "core/templates/hash_map.h" #include "core/templates/local_vector.h" -#include "core/templates/ordered_hash_map.h" #include "scene/3d/camera_3d.h" #include "scene/3d/node_3d.h" #include "scene/3d/skeleton_3d.h" @@ -601,7 +601,13 @@ class NavigationRegion3DGizmoPlugin : public EditorNode3DGizmoPlugin { Vector3 from; Vector3 to; - bool operator<(const _EdgeKey &p_with) const { return from == p_with.from ? to < p_with.to : from < p_with.from; } + static uint32_t hash(const _EdgeKey &p_key) { + return HashMapHasherDefault::hash(p_key.from) ^ HashMapHasherDefault::hash(p_key.to); + } + + bool operator==(const _EdgeKey &p_with) const { + return HashMapComparatorDefault<Vector3>::compare(from, p_with.from) && HashMapComparatorDefault<Vector3>::compare(to, p_with.to); + } }; public: diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index d2af13d7fa..1d85e80331 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -369,7 +369,7 @@ Transform3D Node3DEditorViewport::to_camera_transform(const Cursor &p_cursor) co } int Node3DEditorViewport::get_selected_count() const { - const Map<Node *, Object *> &selection = editor_selection->get_selection(); + const HashMap<Node *, Object *> &selection = editor_selection->get_selection(); int count = 0; @@ -518,7 +518,7 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) { } Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, pos + ray * camera->get_far(), get_tree()->get_root()->get_world_3d()->get_scenario()); - Set<Ref<EditorNode3DGizmo>> found_gizmos; + RBSet<Ref<EditorNode3DGizmo>> found_gizmos; Node *edited_scene = get_tree()->get_edited_scene_root(); ObjectID closest; @@ -581,7 +581,7 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, Vector<_RayRe Vector3 pos = _get_ray_pos(p_pos); Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, pos + ray * camera->get_far(), get_tree()->get_root()->get_world_3d()->get_scenario()); - Set<Node3D *> found_nodes; + RBSet<Node3D *> found_nodes; for (int i = 0; i < instances.size(); i++) { Node3D *spat = Object::cast_to<Node3D>(ObjectDB::get_instance(instances[i])); @@ -764,7 +764,7 @@ void Node3DEditorViewport::_select_region() { } Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world_3d()->get_scenario()); - Set<Node3D *> found_nodes; + RBSet<Node3D *> found_nodes; Vector<Node *> selected; Node *edited_scene = get_tree()->get_edited_scene_root(); @@ -2465,7 +2465,7 @@ void Node3DEditorViewport::_notification(int p_what) { _update_camera(delta); - const Map<Node *, Object *> &selection = editor_selection->get_selection(); + const HashMap<Node *, Object *> &selection = editor_selection->get_selection(); bool changed = false; bool exist = false; @@ -6685,8 +6685,8 @@ void Node3DEditor::_refresh_menu_icons() { } template <typename T> -Set<T *> _get_child_nodes(Node *parent_node) { - Set<T *> nodes = Set<T *>(); +RBSet<T *> _get_child_nodes(Node *parent_node) { + RBSet<T *> nodes = RBSet<T *>(); T *node = Node::cast_to<T>(parent_node); if (node) { nodes.insert(node); @@ -6694,8 +6694,8 @@ Set<T *> _get_child_nodes(Node *parent_node) { for (int i = 0; i < parent_node->get_child_count(); i++) { Node *child_node = parent_node->get_child(i); - Set<T *> child_nodes = _get_child_nodes<T>(child_node); - for (typename Set<T *>::Element *I = child_nodes.front(); I; I = I->next()) { + RBSet<T *> child_nodes = _get_child_nodes<T>(child_node); + for (typename RBSet<T *>::Element *I = child_nodes.front(); I; I = I->next()) { nodes.insert(I->get()); } } @@ -6703,14 +6703,14 @@ Set<T *> _get_child_nodes(Node *parent_node) { return nodes; } -Set<RID> _get_physics_bodies_rid(Node *node) { - Set<RID> rids = Set<RID>(); +RBSet<RID> _get_physics_bodies_rid(Node *node) { + RBSet<RID> rids = RBSet<RID>(); PhysicsBody3D *pb = Node::cast_to<PhysicsBody3D>(node); if (pb) { rids.insert(pb->get_rid()); } - Set<PhysicsBody3D *> child_nodes = _get_child_nodes<PhysicsBody3D>(node); - for (Set<PhysicsBody3D *>::Element *I = child_nodes.front(); I; I = I->next()) { + RBSet<PhysicsBody3D *> child_nodes = _get_child_nodes<PhysicsBody3D>(node); + for (RBSet<PhysicsBody3D *>::Element *I = child_nodes.front(); I; I = I->next()) { rids.insert(I->get()->get_rid()); } @@ -6728,13 +6728,13 @@ void Node3DEditor::snap_selected_nodes_to_floor() { Vector3 position_offset = Vector3(); // Priorities for snapping to floor are CollisionShapes, VisualInstances and then origin - Set<VisualInstance3D *> vi = _get_child_nodes<VisualInstance3D>(sp); - Set<CollisionShape3D *> cs = _get_child_nodes<CollisionShape3D>(sp); + RBSet<VisualInstance3D *> vi = _get_child_nodes<VisualInstance3D>(sp); + RBSet<CollisionShape3D *> cs = _get_child_nodes<CollisionShape3D>(sp); bool found_valid_shape = false; if (cs.size()) { AABB aabb; - Set<CollisionShape3D *>::Element *I = cs.front(); + RBSet<CollisionShape3D *>::Element *I = cs.front(); if (I->get()->get_shape().is_valid()) { CollisionShape3D *collision_shape = cs.front()->get(); aabb = collision_shape->get_global_transform().xform(collision_shape->get_shape()->get_debug_mesh()->get_aabb()); @@ -6755,7 +6755,7 @@ void Node3DEditor::snap_selected_nodes_to_floor() { } if (!found_valid_shape && vi.size()) { AABB aabb = vi.front()->get()->get_transformed_aabb(); - for (Set<VisualInstance3D *>::Element *I = vi.front(); I; I = I->next()) { + for (RBSet<VisualInstance3D *>::Element *I = vi.front(); I; I = I->next()) { aabb.merge_with(I->get()->get_transformed_aabb()); } Vector3 size = aabb.size * Vector3(0.5, 0.0, 0.5); @@ -6798,7 +6798,7 @@ void Node3DEditor::snap_selected_nodes_to_floor() { Dictionary d = snap_data[node]; Vector3 from = d["from"]; Vector3 to = from - Vector3(0.0, max_snap_height, 0.0); - Set<RID> excluded = _get_physics_bodies_rid(sp); + RBSet<RID> excluded = _get_physics_bodies_rid(sp); PhysicsDirectSpaceState3D::RayParameters ray_params; ray_params.from = from; @@ -6820,7 +6820,7 @@ void Node3DEditor::snap_selected_nodes_to_floor() { Dictionary d = snap_data[node]; Vector3 from = d["from"]; Vector3 to = from - Vector3(0.0, max_snap_height, 0.0); - Set<RID> excluded = _get_physics_bodies_rid(sp); + RBSet<RID> excluded = _get_physics_bodies_rid(sp); PhysicsDirectSpaceState3D::RayParameters ray_params; ray_params.from = from; diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 43efdeec72..511135a5f1 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -461,7 +461,7 @@ public: RID sbox_instance_xray; RID sbox_instance_xray_offset; Ref<EditorNode3DGizmo> gizmo; - Map<int, Transform3D> subgizmos; // map ID -> initial transform + HashMap<int, Transform3D> subgizmos; // map ID -> initial transform Node3DEditorSelectedItem() { sp = nullptr; diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp index ffa74173be..f8526fb715 100644 --- a/editor/plugins/ot_features_plugin.cpp +++ b/editor/plugins/ot_features_plugin.cpp @@ -31,6 +31,7 @@ #include "ot_features_plugin.h" #include "scene/3d/label_3d.h" +#include "scene/resources/primitive_meshes.h" void OpenTypeFeaturesEditor::_value_changed(double val) { if (setting) { @@ -124,11 +125,14 @@ void OpenTypeFeaturesAdd::setup(Object *p_object) { Control *ctrl = Object::cast_to<Control>(edited_object); if (ctrl != nullptr) { font = ctrl->get_theme_font(SNAME("font")); - } else { - Label3D *l3d = Object::cast_to<Label3D>(edited_object); - if (l3d != nullptr) { - font = l3d->_get_font_or_default(); - } + } + Label3D *l3d = Object::cast_to<Label3D>(edited_object); + if (l3d != nullptr) { + font = l3d->_get_font_or_default(); + } + TextMesh *tm = Object::cast_to<TextMesh>(edited_object); + if (tm != nullptr) { + font = tm->_get_font_or_default(); } if (font.is_null()) { @@ -205,7 +209,7 @@ OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() { /*************************************************************************/ bool EditorInspectorPluginOpenTypeFeatures::can_handle(Object *p_object) { - return (Object::cast_to<Control>(p_object) != nullptr) || (Object::cast_to<Label3D>(p_object) != nullptr); + return (Object::cast_to<Control>(p_object) != nullptr) || (Object::cast_to<Label3D>(p_object) != nullptr) || (Object::cast_to<TextMesh>(p_object) != nullptr); } bool EditorInspectorPluginOpenTypeFeatures::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { diff --git a/editor/plugins/packed_scene_translation_parser_plugin.h b/editor/plugins/packed_scene_translation_parser_plugin.h index ecd090b31b..9135498333 100644 --- a/editor/plugins/packed_scene_translation_parser_plugin.h +++ b/editor/plugins/packed_scene_translation_parser_plugin.h @@ -37,9 +37,9 @@ class PackedSceneEditorTranslationParserPlugin : public EditorTranslationParserP GDCLASS(PackedSceneEditorTranslationParserPlugin, EditorTranslationParserPlugin); // Scene Node's properties that contain translation strings. - Set<String> lookup_properties; + RBSet<String> lookup_properties; // Properties from specific Nodes that should be ignored. - Map<String, Vector<String>> exception_list; + HashMap<String, Vector<String>> exception_list; public: virtual Error parse_file(const String &p_path, Vector<String> *r_ids, Vector<Vector<String>> *r_ids_ctx_plural) override; diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index bfb672d694..b632b0d641 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -65,7 +65,7 @@ void EditorPropertyRootMotion::_node_assign() { return; } - Set<String> paths; + RBSet<String> paths; { List<StringName> animations; player->get_animation_list(&animations); @@ -81,9 +81,9 @@ void EditorPropertyRootMotion::_node_assign() { filters->clear(); TreeItem *root = filters->create_item(); - Map<String, TreeItem *> parenthood; + HashMap<String, TreeItem *> parenthood; - for (Set<String>::Element *E = paths.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = paths.front(); E; E = E->next()) { NodePath path = E->get(); TreeItem *ti = nullptr; String accum; diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 5240fdf836..115c6f43dd 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -119,9 +119,9 @@ void EditorStandardSyntaxHighlighter::_update_cache() { } /* Autoloads. */ - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - const ProjectSettings::AutoloadInfo &info = E.value(); + HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) { + const ProjectSettings::AutoloadInfo &info = E.value; if (info.is_singleton) { highlighter->add_keyword_color(info.name, usertype_color); } @@ -235,21 +235,21 @@ class EditorScriptCodeCompletionCache : public ScriptCodeCompletionCache { Ref<Resource> cache; }; - Map<String, Cache> cached; + HashMap<String, Cache> cached; public: uint64_t max_time_cache = 5 * 60 * 1000; //minutes, five - int max_cache_size = 128; + uint32_t max_cache_size = 128; void cleanup() { - List<Map<String, Cache>::Element *> to_clean; + List<String> to_clean; - Map<String, Cache>::Element *I = cached.front(); + HashMap<String, Cache>::Iterator I = cached.begin(); while (I) { - if ((OS::get_singleton()->get_ticks_msec() - I->get().time_loaded) > max_time_cache) { - to_clean.push_back(I); + if ((OS::get_singleton()->get_ticks_msec() - I->value.time_loaded) > max_time_cache) { + to_clean.push_back(I->key); } - I = I->next(); + ++I; } while (to_clean.front()) { @@ -259,34 +259,34 @@ public: } virtual Ref<Resource> get_cached_resource(const String &p_path) { - Map<String, Cache>::Element *E = cached.find(p_path); + HashMap<String, Cache>::Iterator E = cached.find(p_path); if (!E) { Cache c; c.cache = ResourceLoader::load(p_path); E = cached.insert(p_path, c); } - E->get().time_loaded = OS::get_singleton()->get_ticks_msec(); + E->value.time_loaded = OS::get_singleton()->get_ticks_msec(); if (cached.size() > max_cache_size) { uint64_t older; - Map<String, Cache>::Element *O = cached.front(); - older = O->get().time_loaded; - Map<String, Cache>::Element *I = O; + HashMap<String, Cache>::Iterator O = cached.begin(); + older = O->value.time_loaded; + HashMap<String, Cache>::Iterator I = O; while (I) { - if (I->get().time_loaded < older) { - older = I->get().time_loaded; + if (I->value.time_loaded < older) { + older = I->value.time_loaded; O = I; } - I = I->next(); + ++I; } if (O != E) { //should never happen.. - cached.erase(O); + cached.remove(O); } } - return E->get().cache; + return E->value.cache; } virtual ~EditorScriptCodeCompletionCache() {} @@ -966,7 +966,7 @@ void ScriptEditor::_reload_scripts() { ERR_CONTINUE(!rel_script.is_valid()); script->set_source_code(rel_script->get_source_code()); script->set_last_modified_time(rel_script->get_last_modified_time()); - script->reload(); + script->reload(true); } Ref<TextFile> text_file = edited_res; @@ -1365,9 +1365,17 @@ void ScriptEditor::_menu_option(int p_option) { } } break; - case FILE_TOOL_RELOAD: case FILE_TOOL_RELOAD_SOFT: { - current->reload(p_option == FILE_TOOL_RELOAD_SOFT); + Ref<Script> scr = current->get_edited_resource(); + if (scr == nullptr || scr.is_null()) { + EditorNode::get_singleton()->show_warning(TTR("Can't obtain the script for reloading.")); + break; + } + if (!scr->is_tool()) { + EditorNode::get_singleton()->show_warning(TTR("Reload only takes effect on tool scripts.")); + return; + } + scr->reload(true); } break; case FILE_RUN: { @@ -1376,6 +1384,10 @@ void ScriptEditor::_menu_option(int p_option) { EditorNode::get_singleton()->show_warning(TTR("Can't obtain the script for running.")); break; } + if (!scr->is_tool()) { + EditorNode::get_singleton()->show_warning(TTR("Script is not in tool mode, will not be able to run.")); + return; + } current->apply_code(); Error err = scr->reload(false); //hard reload script before running always @@ -1384,10 +1396,6 @@ void ScriptEditor::_menu_option(int p_option) { EditorNode::get_singleton()->show_warning(TTR("Script failed reloading, check console for errors.")); return; } - if (!scr->is_tool()) { - EditorNode::get_singleton()->show_warning(TTR("Script is not in tool mode, will not be able to run.")); - return; - } if (!ClassDB::is_parent_class(scr->get_instance_base_type(), "EditorScript")) { EditorNode::get_singleton()->show_warning(TTR("To run this script, it must inherit EditorScript and be set to tool mode.")); @@ -1707,7 +1715,7 @@ void ScriptEditor::notify_script_changed(const Ref<Script> &p_script) { } void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) { - Set<String> loaded_scripts; + RBSet<String> loaded_scripts; for (int i = 0; i < tab_container->get_tab_count(); i++) { ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_tab_control(i)); if (!se) { @@ -1792,7 +1800,7 @@ void ScriptEditor::ensure_select_current() { _update_selected_editor_menu(); } -void ScriptEditor::_find_scripts(Node *p_base, Node *p_current, Set<Ref<Script>> &used) { +void ScriptEditor::_find_scripts(Node *p_base, Node *p_current, RBSet<Ref<Script>> &used) { if (p_current != p_base && p_current->get_owner() != p_base) { return; } @@ -1972,7 +1980,7 @@ void ScriptEditor::_update_script_names() { return; } - Set<Ref<Script>> used; + RBSet<Ref<Script>> used; Node *edited = EditorNode::get_singleton()->get_edited_scene(); if (edited) { _find_scripts(edited, edited, used); @@ -3091,8 +3099,8 @@ void ScriptEditor::_make_script_list_context_menu() { if (se) { Ref<Script> scr = se->get_edited_resource(); if (scr != nullptr) { - context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/reload_script_soft"), FILE_TOOL_RELOAD_SOFT); if (!scr.is_null() && scr->is_tool()) { + context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/reload_script_soft"), FILE_TOOL_RELOAD_SOFT); context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/run_file"), FILE_RUN); context_menu->add_separator(); } @@ -3135,7 +3143,7 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) { restoring_layout = true; - Set<String> loaded_scripts; + RBSet<String> loaded_scripts; List<String> extensions; ResourceLoader::get_recognized_extensions_for_type("Script", &extensions); @@ -3774,7 +3782,7 @@ ScriptEditor::ScriptEditor() { file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_as", TTR("Save As...")), FILE_SAVE_AS); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KeyModifierMask::SHIFT | KeyModifierMask::ALT | Key::S), FILE_SAVE_ALL); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KeyModifierMask::CMD | KeyModifierMask::ALT | Key::R), FILE_TOOL_RELOAD_SOFT); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Tool Script"), KeyModifierMask::CMD | KeyModifierMask::ALT | Key::R), FILE_TOOL_RELOAD_SOFT); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy_path", TTR("Copy Script Path")), FILE_COPY_PATH); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/show_in_file_system", TTR("Show in FileSystem")), SHOW_IN_FILE_SYSTEM); file_menu->get_popup()->add_separator(); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 41b311f745..ff71c8b484 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -206,7 +206,6 @@ class ScriptEditor : public PanelContainer { TOGGLE_SCRIPTS_PANEL, SHOW_IN_FILE_SYSTEM, FILE_COPY_PATH, - FILE_TOOL_RELOAD, FILE_TOOL_RELOAD_SOFT, SEARCH_IN_FILES, REPLACE_IN_FILES, @@ -415,7 +414,7 @@ class ScriptEditor : public PanelContainer { void _update_help_overview(); void _help_overview_selected(int p_idx); - void _find_scripts(Node *p_base, Node *p_current, Set<Ref<Script>> &used); + void _find_scripts(Node *p_base, Node *p_current, RBSet<Ref<Script>> &used); void _tree_changed(); @@ -455,7 +454,7 @@ class ScriptEditor : public PanelContainer { Ref<Script> _get_current_script(); Array _get_open_scripts() const; - Set<String> textfile_extensions; + RBSet<String> textfile_extensions; Ref<TextFile> _load_text_file(const String &p_path, Error *r_error) const; Error _save_text_file(Ref<TextFile> p_text_file, const String &p_path); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 981881fb9b..e7b4aa6b68 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -664,7 +664,7 @@ static Node *_find_node_for_script(Node *p_base, Node *p_current, const Ref<Scri return nullptr; } -static void _find_changed_scripts_for_external_editor(Node *p_base, Node *p_current, Set<Ref<Script>> &r_scripts) { +static void _find_changed_scripts_for_external_editor(Node *p_base, Node *p_current, RBSet<Ref<Script>> &r_scripts) { if (p_current->get_owner() != p_base && p_base != p_current) { return; } @@ -686,14 +686,14 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo ERR_FAIL_COND(!get_tree()); - Set<Ref<Script>> scripts; + RBSet<Ref<Script>> scripts; Node *base = get_tree()->get_edited_scene_root(); if (base) { _find_changed_scripts_for_external_editor(base, base, scripts); } - for (Set<Ref<Script>>::Element *E = scripts.front(); E; E = E->next()) { + for (RBSet<Ref<Script>>::Element *E = scripts.front(); E; E = E->next()) { Ref<Script> script = E->get(); if (p_for_script.is_valid() && p_for_script != script) { @@ -855,6 +855,21 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c emit_signal(SNAME("go_to_help"), "class_method:" + result.class_name + ":" + result.class_member); } break; + case ScriptLanguage::LOOKUP_RESULT_CLASS_SIGNAL: { + StringName cname = result.class_name; + + while (true) { + if (ClassDB::has_signal(cname, result.class_member)) { + result.class_name = cname; + cname = ClassDB::get_parent_class(cname); + } else { + break; + } + } + + emit_signal(SNAME("go_to_help"), "class_signal:" + result.class_name + ":" + result.class_member); + + } break; case ScriptLanguage::LOOKUP_RESULT_CLASS_ENUM: { StringName cname = result.class_name; StringName success; @@ -955,7 +970,7 @@ void ScriptTextEditor::_update_connected_methods() { } Vector<Node *> nodes = _find_all_node_for_script(base, base, script); - Set<StringName> methods_found; + RBSet<StringName> methods_found; for (int i = 0; i < nodes.size(); i++) { List<Connection> connections; nodes[i]->get_signals_connected_to_this(&connections); @@ -1356,11 +1371,11 @@ void ScriptTextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_hig void ScriptTextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) { ERR_FAIL_COND(p_highlighter.is_null()); - Map<String, Ref<EditorSyntaxHighlighter>>::Element *el = highlighters.front(); - while (el != nullptr) { - int highlighter_index = highlighter_menu->get_item_idx_from_text(el->key()); - highlighter_menu->set_item_checked(highlighter_index, el->value() == p_highlighter); - el = el->next(); + HashMap<String, Ref<EditorSyntaxHighlighter>>::Iterator el = highlighters.begin(); + while (el) { + int highlighter_index = highlighter_menu->get_item_idx_from_text(el->key); + highlighter_menu->set_item_checked(highlighter_index, el->value == p_highlighter); + ++el; } CodeEdit *te = code_editor->get_text_editor(); @@ -1543,19 +1558,46 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data Array nodes = d["nodes"]; String text_to_drop; - for (int i = 0; i < nodes.size(); i++) { - if (i > 0) { - text_to_drop += ","; - } - NodePath np = nodes[i]; - Node *node = get_node(np); - if (!node) { - continue; + if (Input::get_singleton()->is_key_pressed(Key::CTRL)) { + bool use_type = EDITOR_GET("text_editor/completion/add_type_hints"); + for (int i = 0; i < nodes.size(); i++) { + NodePath np = nodes[i]; + Node *node = get_node(np); + if (!node) { + continue; + } + + String path = sn->get_path_to(node); + for (const String &segment : path.split("/")) { + if (!segment.is_valid_identifier()) { + path = path.c_escape().quote(quote_style); + break; + } + } + + String variable_name = String(node->get_name()).camelcase_to_underscore(true).validate_identifier(); + if (use_type) { + text_to_drop += vformat("@onready var %s: %s = $%s\n", variable_name, node->get_class_name(), path); + } else { + text_to_drop += vformat("@onready var %s = $%s\n", variable_name, path); + } } + } else { + for (int i = 0; i < nodes.size(); i++) { + if (i > 0) { + text_to_drop += ","; + } - String path = sn->get_path_to(node); - text_to_drop += path.c_escape().quote(quote_style); + NodePath np = nodes[i]; + Node *node = get_node(np); + if (!node) { + continue; + } + + String path = sn->get_path_to(node); + text_to_drop += path.c_escape().quote(quote_style); + } } te->set_caret_line(row); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index b3e0c28bb1..ff13b38832 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -64,7 +64,7 @@ class ScriptTextEditor : public ScriptEditorBase { Vector<String> functions; List<ScriptLanguage::Warning> warnings; List<ScriptLanguage::ScriptError> errors; - Set<int> safe_lines; + RBSet<int> safe_lines; List<Connection> missing_connections; @@ -175,7 +175,7 @@ protected: void _notification(int p_what); static void _bind_methods(); - Map<String, Ref<EditorSyntaxHighlighter>> highlighters; + HashMap<String, Ref<EditorSyntaxHighlighter>> highlighters; void _change_syntax_highlighter(int p_idx); void _edit_option(int p_op); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 1bf78cc107..c13d0dc197 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -47,7 +47,7 @@ static bool saved_warnings_enabled = false; static bool saved_treat_warning_as_errors = false; -static Map<ShaderWarning::Code, bool> saved_warnings; +static HashMap<ShaderWarning::Code, bool> saved_warnings; static uint32_t saved_warning_flags = 0U; void ShaderTextEditor::_notification(int p_what) { diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 1b703a097c..1ebdf466fe 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -357,7 +357,7 @@ void Skeleton3DEditor::pose_to_rest(const bool p_all_bones) { void Skeleton3DEditor::create_physical_skeleton() { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ERR_FAIL_COND(!get_tree()); - Node *owner = skeleton == get_tree()->get_edited_scene_root() ? skeleton : skeleton->get_owner(); + Node *owner = get_tree()->get_edited_scene_root(); const int bc = skeleton->get_bone_count(); @@ -368,37 +368,47 @@ void Skeleton3DEditor::create_physical_skeleton() { Vector<BoneInfo> bones_infos; bones_infos.resize(bc); - for (int bone_id = 0; bc > bone_id; ++bone_id) { - const int parent = skeleton->get_bone_parent(bone_id); + if (bc > 0) { + ur->create_action(TTR("Create physical bones"), UndoRedo::MERGE_ALL); + for (int bone_id = 0; bc > bone_id; ++bone_id) { + const int parent = skeleton->get_bone_parent(bone_id); - if (parent < 0) { - bones_infos.write[bone_id].relative_rest = skeleton->get_bone_rest(bone_id); - - } else { - const int parent_parent = skeleton->get_bone_parent(parent); - - bones_infos.write[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id); - - // Create physical bone on parent. - if (!bones_infos[parent].physical_bone) { - bones_infos.write[parent].physical_bone = create_physical_bone(parent, bone_id, bones_infos); - - ur->create_action(TTR("Create physical bones"), UndoRedo::MERGE_ALL); - ur->add_do_method(skeleton, "add_child", bones_infos[parent].physical_bone); - ur->add_do_reference(bones_infos[parent].physical_bone); - ur->add_undo_method(skeleton, "remove_child", bones_infos[parent].physical_bone); - ur->commit_action(); + if (parent < 0) { + bones_infos.write[bone_id].relative_rest = skeleton->get_bone_rest(bone_id); + } else { + const int parent_parent = skeleton->get_bone_parent(parent); + + bones_infos.write[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id); + + // Create physical bone on parent. + if (!bones_infos[parent].physical_bone) { + PhysicalBone3D *physical_bone = create_physical_bone(parent, bone_id, bones_infos); + if (physical_bone && physical_bone->get_child(0)) { + CollisionShape3D *collision_shape = Object::cast_to<CollisionShape3D>(physical_bone->get_child(0)); + if (collision_shape) { + bones_infos.write[parent].physical_bone = physical_bone; + + ur->add_do_method(skeleton, "add_child", physical_bone); + ur->add_do_method(physical_bone, "set_owner", owner); + ur->add_do_method(collision_shape, "set_owner", owner); + ur->add_do_property(physical_bone, "bone_name", skeleton->get_bone_name(parent)); + + // Create joint between parent of parent. + if (parent_parent != -1) { + ur->add_do_method(physical_bone, "set_joint_type", PhysicalBone3D::JOINT_TYPE_PIN); + } - bones_infos[parent].physical_bone->set_bone_name(skeleton->get_bone_name(parent)); - bones_infos[parent].physical_bone->set_owner(owner); - bones_infos[parent].physical_bone->get_child(0)->set_owner(owner); // set shape owner + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", physical_bone); + ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", collision_shape); - // Create joint between parent of parent. - if (-1 != parent_parent) { - bones_infos[parent].physical_bone->set_joint_type(PhysicalBone3D::JOINT_TYPE_PIN); + ur->add_do_reference(physical_bone); + ur->add_undo_method(skeleton, "remove_child", physical_bone); + } + } } } } + ur->commit_action(); } } @@ -414,6 +424,7 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi CollisionShape3D *bone_shape = memnew(CollisionShape3D); bone_shape->set_shape(bone_shape_capsule); + bone_shape->set_name("CollisionShape3D"); Transform3D capsule_transform; capsule_transform.basis = Basis(Vector3(1, 0, 0), Vector3(0, 0, 1), Vector3(0, -1, 0)); @@ -577,7 +588,7 @@ void Skeleton3DEditor::update_joint_tree() { TreeItem *root = joint_tree->create_item(); - Map<int, TreeItem *> items; + HashMap<int, TreeItem *> items; items.insert(-1, root); @@ -589,7 +600,7 @@ void Skeleton3DEditor::update_joint_tree() { bones_to_process.erase(current_bone_idx); const int parent_idx = skeleton->get_bone_parent(current_bone_idx); - TreeItem *parent_item = items.find(parent_idx)->get(); + TreeItem *parent_item = items.find(parent_idx)->value; TreeItem *joint_item = joint_tree->create_item(parent_item); items.insert(current_bone_idx, joint_item); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 7b6aeb3679..cb8d59dfe4 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -125,7 +125,7 @@ void SpriteFramesEditor::_sheet_preview_draw() { Color accent = get_theme_color("accent_color", "Editor"); - for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = frames_selected.front(); E; E = E->next()) { const int idx = E->get(); const int x = idx % frame_count.x; const int y = idx / frame_count.x; @@ -248,7 +248,7 @@ void SpriteFramesEditor::_sheet_add_frames() { int fc = frames->get_frame_count(edited_anim); - for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = frames_selected.front(); E; E = E->next()) { int idx = E->get(); const Point2 frame_coords(idx % frame_count.x, idx / frame_count.x); diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 3230228fdd..6f16ff2bd1 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -103,8 +103,8 @@ class SpriteFramesEditor : public HSplitContainer { Button *split_sheet_zoom_reset = nullptr; Button *split_sheet_zoom_in = nullptr; EditorFileDialog *file_split_sheet = nullptr; - Set<int> frames_selected; - Set<int> frames_toggled_by_mouse_hover; + RBSet<int> frames_selected; + RBSet<int> frames_toggled_by_mouse_hover; int last_frame_selected = 0; float scale_ratio; diff --git a/editor/plugins/text_control_editor_plugin.cpp b/editor/plugins/text_control_editor_plugin.cpp index 4290888e94..2a5faba4a2 100644 --- a/editor/plugins/text_control_editor_plugin.cpp +++ b/editor/plugins/text_control_editor_plugin.cpp @@ -92,8 +92,8 @@ void TextControlEditor::_update_fonts_menu() { } int id = FONT_INFO_ID; - for (Map<String, Map<String, String>>::Element *E = fonts.front(); E; E = E->next()) { - font_list->add_item(E->key(), id++); + for (const KeyValue<String, HashMap<String, String>> &E : fonts) { + font_list->add_item(E.key, id++); } if (font_list->get_item_count() > 1) { @@ -107,8 +107,8 @@ void TextControlEditor::_update_styles_menu() { font_style_list->clear(); if ((font_list->get_selected_id() >= FONT_INFO_ID)) { const String &name = font_list->get_item_text(font_list->get_selected()); - for (Map<String, String>::Element *E = fonts[name].front(); E; E = E->next()) { - font_style_list->add_item(E->key()); + for (KeyValue<String, String> &E : fonts[name]) { + font_style_list->add_item(E.key); } } else if (font_list->get_selected() >= 0) { font_style_list->add_item("Default"); diff --git a/editor/plugins/text_control_editor_plugin.h b/editor/plugins/text_control_editor_plugin.h index a475f6eba3..cf069338b6 100644 --- a/editor/plugins/text_control_editor_plugin.h +++ b/editor/plugins/text_control_editor_plugin.h @@ -52,7 +52,7 @@ class TextControlEditor : public HBoxContainer { FONT_INFO_ID = 100, }; - Map<String, Map<String, String>> fonts; + HashMap<String, HashMap<String, String>> fonts; OptionButton *font_list = nullptr; SpinBox *font_size_list = nullptr; diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 97ecc234e6..7ca65c073d 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -43,11 +43,11 @@ void TextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlight void TextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) { ERR_FAIL_COND(p_highlighter.is_null()); - Map<String, Ref<EditorSyntaxHighlighter>>::Element *el = highlighters.front(); - while (el != nullptr) { - int highlighter_index = highlighter_menu->get_item_idx_from_text(el->key()); - highlighter_menu->set_item_checked(highlighter_index, el->value() == p_highlighter); - el = el->next(); + HashMap<String, Ref<EditorSyntaxHighlighter>>::Iterator el = highlighters.begin(); + while (el) { + int highlighter_index = highlighter_menu->get_item_idx_from_text(el->key); + highlighter_menu->set_item_checked(highlighter_index, el->value == p_highlighter); + ++el; } CodeEdit *te = code_editor->get_text_editor(); diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index 9b6d568382..4f0121da52 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -92,7 +92,7 @@ protected: void _text_edit_gui_input(const Ref<InputEvent> &ev); void _prepare_edit_menu(); - Map<String, Ref<EditorSyntaxHighlighter>> highlighters; + HashMap<String, Ref<EditorSyntaxHighlighter>> highlighters; void _change_syntax_highlighter(int p_idx); void _load_theme_settings(); diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 455592aa26..74c96e19d0 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -921,12 +921,6 @@ void TextureRegionEditor::edit(Object *p_obj) { atlas_tex = Ref<AtlasTexture>(nullptr); } edit_draw->update(); - if ((node_sprite_2d && !node_sprite_2d->is_region_enabled()) || (node_sprite_3d && !node_sprite_3d->is_region_enabled())) { - set_process(true); - } - if (!p_obj) { - set_process(false); - } } void TextureRegionEditor::_texture_changed() { diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index 2493446303..2c4ab72743 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -89,7 +89,7 @@ class TextureRegionEditor : public VBoxContainer { Rect2 rect_prev; float prev_margin = 0.0f; int edited_margin; - Map<RID, List<Rect2>> cache_map; + HashMap<RID, List<Rect2>> cache_map; List<Rect2> autoslice_cache; bool autoslice_is_dirty; diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 87f8c4b165..7b2c7d2a82 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -2339,8 +2339,8 @@ void ThemeTypeEditor::_update_type_list_debounced() { update_debounce_timer->start(); } -OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default) { - OrderedHashMap<StringName, bool> items; +HashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default) { + HashMap<StringName, bool> items; List<StringName> names; if (include_default) { @@ -2367,12 +2367,12 @@ OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_ } List<StringName> keys; - for (OrderedHashMap<StringName, bool>::Element E = items.front(); E; E = E.next()) { - keys.push_back(E.key()); + for (const KeyValue<StringName, bool> &E : items) { + keys.push_back(E.key); } keys.sort_custom<StringName::AlphCompare>(); - OrderedHashMap<StringName, bool> ordered_items; + HashMap<StringName, bool> ordered_items; for (const StringName &E : keys) { ordered_items[E] = items[E]; } @@ -2464,18 +2464,18 @@ void ThemeTypeEditor::_update_type_items() { color_items_list->remove_child(node); } - OrderedHashMap<StringName, bool> color_items = _get_type_items(edited_type, &Theme::get_color_list, show_default); - for (OrderedHashMap<StringName, bool>::Element E = color_items.front(); E; E = E.next()) { - HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_COLOR, E.key(), E.get()); + HashMap<StringName, bool> color_items = _get_type_items(edited_type, &Theme::get_color_list, show_default); + for (const KeyValue<StringName, bool> &E : color_items) { + HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_COLOR, E.key, E.value); ColorPickerButton *item_editor = memnew(ColorPickerButton); item_editor->set_h_size_flags(SIZE_EXPAND_FILL); item_control->add_child(item_editor); - if (E.get()) { - item_editor->set_pick_color(edited_theme->get_color(E.key(), edited_type)); - item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed), varray(E.key())); + if (E.value) { + item_editor->set_pick_color(edited_theme->get_color(E.key, edited_type)); + item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed), varray(E.key)); } else { - item_editor->set_pick_color(Theme::get_default()->get_color(E.key(), edited_type)); + item_editor->set_pick_color(Theme::get_default()->get_color(E.key, edited_type)); item_editor->set_disabled(true); } @@ -2492,9 +2492,9 @@ void ThemeTypeEditor::_update_type_items() { constant_items_list->remove_child(node); } - OrderedHashMap<StringName, bool> constant_items = _get_type_items(edited_type, &Theme::get_constant_list, show_default); - for (OrderedHashMap<StringName, bool>::Element E = constant_items.front(); E; E = E.next()) { - HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_CONSTANT, E.key(), E.get()); + HashMap<StringName, bool> constant_items = _get_type_items(edited_type, &Theme::get_constant_list, show_default); + for (const KeyValue<StringName, bool> &E : constant_items) { + HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_CONSTANT, E.key, E.value); SpinBox *item_editor = memnew(SpinBox); item_editor->set_h_size_flags(SIZE_EXPAND_FILL); item_editor->set_min(-100000); @@ -2504,11 +2504,11 @@ void ThemeTypeEditor::_update_type_items() { item_editor->set_allow_greater(true); item_control->add_child(item_editor); - if (E.get()) { - item_editor->set_value(edited_theme->get_constant(E.key(), edited_type)); - item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed), varray(E.key())); + if (E.value) { + item_editor->set_value(edited_theme->get_constant(E.key, edited_type)); + item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed), varray(E.key)); } else { - item_editor->set_value(Theme::get_default()->get_constant(E.key(), edited_type)); + item_editor->set_value(Theme::get_default()->get_constant(E.key, edited_type)); item_editor->set_editable(false); } @@ -2525,25 +2525,25 @@ void ThemeTypeEditor::_update_type_items() { font_items_list->remove_child(node); } - OrderedHashMap<StringName, bool> font_items = _get_type_items(edited_type, &Theme::get_font_list, show_default); - for (OrderedHashMap<StringName, bool>::Element E = font_items.front(); E; E = E.next()) { - HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_FONT, E.key(), E.get()); + HashMap<StringName, bool> font_items = _get_type_items(edited_type, &Theme::get_font_list, show_default); + for (const KeyValue<StringName, bool> &E : font_items) { + HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_FONT, E.key, E.value); EditorResourcePicker *item_editor = memnew(EditorResourcePicker); item_editor->set_h_size_flags(SIZE_EXPAND_FILL); item_editor->set_base_type("Font"); item_control->add_child(item_editor); - if (E.get()) { - if (edited_theme->has_font(E.key(), edited_type)) { - item_editor->set_edited_resource(edited_theme->get_font(E.key(), edited_type)); + if (E.value) { + if (edited_theme->has_font(E.key, edited_type)) { + item_editor->set_edited_resource(edited_theme->get_font(E.key, edited_type)); } else { item_editor->set_edited_resource(Ref<Resource>()); } item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item)); - item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed), varray(E.key())); + item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed), varray(E.key)); } else { - if (Theme::get_default()->has_font(E.key(), edited_type)) { - item_editor->set_edited_resource(Theme::get_default()->get_font(E.key(), edited_type)); + if (Theme::get_default()->has_font(E.key, edited_type)) { + item_editor->set_edited_resource(Theme::get_default()->get_font(E.key, edited_type)); } else { item_editor->set_edited_resource(Ref<Resource>()); } @@ -2563,9 +2563,9 @@ void ThemeTypeEditor::_update_type_items() { font_size_items_list->remove_child(node); } - OrderedHashMap<StringName, bool> font_size_items = _get_type_items(edited_type, &Theme::get_font_size_list, show_default); - for (OrderedHashMap<StringName, bool>::Element E = font_size_items.front(); E; E = E.next()) { - HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_FONT_SIZE, E.key(), E.get()); + HashMap<StringName, bool> font_size_items = _get_type_items(edited_type, &Theme::get_font_size_list, show_default); + for (const KeyValue<StringName, bool> &E : font_size_items) { + HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_FONT_SIZE, E.key, E.value); SpinBox *item_editor = memnew(SpinBox); item_editor->set_h_size_flags(SIZE_EXPAND_FILL); item_editor->set_min(-100000); @@ -2575,11 +2575,11 @@ void ThemeTypeEditor::_update_type_items() { item_editor->set_allow_greater(true); item_control->add_child(item_editor); - if (E.get()) { - item_editor->set_value(edited_theme->get_font_size(E.key(), edited_type)); - item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed), varray(E.key())); + if (E.value) { + item_editor->set_value(edited_theme->get_font_size(E.key, edited_type)); + item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed), varray(E.key)); } else { - item_editor->set_value(Theme::get_default()->get_font_size(E.key(), edited_type)); + item_editor->set_value(Theme::get_default()->get_font_size(E.key, edited_type)); item_editor->set_editable(false); } @@ -2596,25 +2596,25 @@ void ThemeTypeEditor::_update_type_items() { icon_items_list->remove_child(node); } - OrderedHashMap<StringName, bool> icon_items = _get_type_items(edited_type, &Theme::get_icon_list, show_default); - for (OrderedHashMap<StringName, bool>::Element E = icon_items.front(); E; E = E.next()) { - HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_ICON, E.key(), E.get()); + HashMap<StringName, bool> icon_items = _get_type_items(edited_type, &Theme::get_icon_list, show_default); + for (const KeyValue<StringName, bool> &E : icon_items) { + HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_ICON, E.key, E.value); EditorResourcePicker *item_editor = memnew(EditorResourcePicker); item_editor->set_h_size_flags(SIZE_EXPAND_FILL); item_editor->set_base_type("Texture2D"); item_control->add_child(item_editor); - if (E.get()) { - if (edited_theme->has_icon(E.key(), edited_type)) { - item_editor->set_edited_resource(edited_theme->get_icon(E.key(), edited_type)); + if (E.value) { + if (edited_theme->has_icon(E.key, edited_type)) { + item_editor->set_edited_resource(edited_theme->get_icon(E.key, edited_type)); } else { item_editor->set_edited_resource(Ref<Resource>()); } item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item)); - item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed), varray(E.key())); + item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed), varray(E.key)); } else { - if (Theme::get_default()->has_icon(E.key(), edited_type)) { - item_editor->set_edited_resource(Theme::get_default()->get_icon(E.key(), edited_type)); + if (Theme::get_default()->has_icon(E.key, edited_type)) { + item_editor->set_edited_resource(Theme::get_default()->get_icon(E.key, edited_type)); } else { item_editor->set_edited_resource(Ref<Resource>()); } @@ -2664,26 +2664,26 @@ void ThemeTypeEditor::_update_type_items() { stylebox_items_list->add_child(memnew(HSeparator)); } - OrderedHashMap<StringName, bool> stylebox_items = _get_type_items(edited_type, &Theme::get_stylebox_list, show_default); - for (OrderedHashMap<StringName, bool>::Element E = stylebox_items.front(); E; E = E.next()) { - if (leading_stylebox.pinned && leading_stylebox.item_name == E.key()) { + HashMap<StringName, bool> stylebox_items = _get_type_items(edited_type, &Theme::get_stylebox_list, show_default); + for (const KeyValue<StringName, bool> &E : stylebox_items) { + if (leading_stylebox.pinned && leading_stylebox.item_name == E.key) { continue; } - HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_STYLEBOX, E.key(), E.get()); + HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_STYLEBOX, E.key, E.value); EditorResourcePicker *item_editor = memnew(EditorResourcePicker); item_editor->set_h_size_flags(SIZE_EXPAND_FILL); item_editor->set_stretch_ratio(1.5); item_editor->set_base_type("StyleBox"); - if (E.get()) { - if (edited_theme->has_stylebox(E.key(), edited_type)) { - item_editor->set_edited_resource(edited_theme->get_stylebox(E.key(), edited_type)); + if (E.value) { + if (edited_theme->has_stylebox(E.key, edited_type)) { + item_editor->set_edited_resource(edited_theme->get_stylebox(E.key, edited_type)); } else { item_editor->set_edited_resource(Ref<Resource>()); } item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item)); - item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed), varray(E.key())); + item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed), varray(E.key)); Button *pin_leader_button = memnew(Button); pin_leader_button->set_flat(true); @@ -2691,10 +2691,10 @@ void ThemeTypeEditor::_update_type_items() { pin_leader_button->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons"))); pin_leader_button->set_tooltip(TTR("Pin this StyleBox as a main style. Editing its properties will update the same properties in all other StyleBoxes of this type.")); item_control->add_child(pin_leader_button); - pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed), varray(item_editor, E.key())); + pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed), varray(item_editor, E.key)); } else { - if (Theme::get_default()->has_stylebox(E.key(), edited_type)) { - item_editor->set_edited_resource(Theme::get_default()->get_stylebox(E.key(), edited_type)); + if (Theme::get_default()->has_stylebox(E.key, edited_type)) { + item_editor->set_edited_resource(Theme::get_default()->get_stylebox(E.key, edited_type)); } else { item_editor->set_edited_resource(Ref<Resource>()); } @@ -3211,11 +3211,13 @@ void ThemeTypeEditor::_update_stylebox_from_leading() { edited_theme->get_stylebox_list(edited_type, &names); List<Ref<StyleBox>> styleboxes; for (const StringName &E : names) { - if (E == leading_stylebox.item_name) { + Ref<StyleBox> sb = edited_theme->get_stylebox(E, edited_type); + + // Avoid itself, stylebox can be shared between items. + if (sb == leading_stylebox.stylebox) { continue; } - Ref<StyleBox> sb = edited_theme->get_stylebox(E, edited_type); if (sb->get_class() == leading_stylebox.stylebox->get_class()) { styleboxes.push_back(sb); } diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index 3894ca31e5..323cfceb7e 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -73,7 +73,7 @@ class ThemeItemImportTree : public VBoxContainer { SELECT_IMPORT_FULL, }; - Map<ThemeItem, ItemCheckedState> selected_items; + RBMap<ThemeItem, ItemCheckedState> selected_items; LineEdit *import_items_filter = nullptr; @@ -363,7 +363,7 @@ class ThemeTypeEditor : public MarginContainer { VBoxContainer *_create_item_list(Theme::DataType p_data_type); void _update_type_list(); void _update_type_list_debounced(); - OrderedHashMap<StringName, bool> _get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default); + HashMap<StringName, bool> _get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default); HBoxContainer *_create_property_control(Theme::DataType p_data_type, String p_item_name, bool p_editable); void _add_focusable(Control *p_control); void _update_type_items(); diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp index 086588f5a5..e37878ff98 100644 --- a/editor/plugins/tiles/atlas_merging_dialog.cpp +++ b/editor/plugins/tiles/atlas_merging_dialog.cpp @@ -62,7 +62,7 @@ void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atla int line_height = 0; for (int source_index = 0; source_index < p_atlas_sources.size(); source_index++) { Ref<TileSetAtlasSource> atlas_source = p_atlas_sources[source_index]; - merged_mapping.push_back(Map<Vector2i, Vector2i>()); + merged_mapping.push_back(HashMap<Vector2i, Vector2i>()); // Layout the tiles. Vector2i atlas_size; diff --git a/editor/plugins/tiles/atlas_merging_dialog.h b/editor/plugins/tiles/atlas_merging_dialog.h index 9502d93f6b..c54e259594 100644 --- a/editor/plugins/tiles/atlas_merging_dialog.h +++ b/editor/plugins/tiles/atlas_merging_dialog.h @@ -46,7 +46,7 @@ private: int commited_actions_count = 0; bool delete_original_atlases = true; Ref<TileSetAtlasSource> merged; - LocalVector<Map<Vector2i, Vector2i>> merged_mapping; + LocalVector<HashMap<Vector2i, Vector2i>> merged_mapping; Ref<TileSet> tile_set; UndoRedo *undo_redo = nullptr; diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 4de2f42fe0..3073c8a7f2 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -480,7 +480,7 @@ void TileAtlasView::_update_alternative_tiles_rect_cache() { // Update the rect. if (!alternative_tiles_rect_cache.has(tile_id)) { - alternative_tiles_rect_cache[tile_id] = Map<int, Rect2i>(); + alternative_tiles_rect_cache[tile_id] = HashMap<int, Rect2i>(); } alternative_tiles_rect_cache[tile_id][alternative_id] = current; @@ -494,7 +494,7 @@ void TileAtlasView::_update_alternative_tiles_rect_cache() { } Vector3i TileAtlasView::get_alternative_tile_at_pos(const Vector2 p_pos) const { - for (const KeyValue<Vector2, Map<int, Rect2i>> &E_coords : alternative_tiles_rect_cache) { + for (const KeyValue<Vector2, HashMap<int, Rect2i>> &E_coords : alternative_tiles_rect_cache) { for (const KeyValue<int, Rect2i> &E_alternative : E_coords.value) { if (E_alternative.value.has_point(p_pos)) { return Vector3i(E_coords.key.x, E_coords.key.y, E_alternative.key); diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h index 6e74858b08..ff46b7871f 100644 --- a/editor/plugins/tiles/tile_atlas_view.h +++ b/editor/plugins/tiles/tile_atlas_view.h @@ -69,7 +69,7 @@ private: void _pan_callback(Vector2 p_scroll_vec); void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); - Map<Vector2, Map<int, Rect2i>> alternative_tiles_rect_cache; + HashMap<Vector2, HashMap<int, Rect2i>> alternative_tiles_rect_cache; void _update_alternative_tiles_rect_cache(); MarginContainer *margin_container = nullptr; diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 70bcd7e39a..eda05b1005 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -862,7 +862,7 @@ Variant TileDataDefaultEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_s return tile_data->get(property); } -void TileDataDefaultEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { +void TileDataDefaultEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) { for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { Vector2i coords = E.key.get_atlas_coords(); undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E.key.alternative_tile, property), E.value); @@ -882,7 +882,7 @@ void TileDataDefaultEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas_ rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(p_transform.affine_inverse().xform(p_canvas_item->get_local_mouse_position()))); rect = rect.abs(); - Set<TileMapCell> edited; + RBSet<TileMapCell> edited; for (int x = rect.get_position().x; x <= rect.get_end().x; x++) { for (int y = rect.get_position().y; y <= rect.get_end().y; y++) { Vector2i coords = Vector2i(x, y); @@ -897,7 +897,7 @@ void TileDataDefaultEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas_ } } - for (Set<TileMapCell>::Element *E = edited.front(); E; E = E->next()) { + for (RBSet<TileMapCell>::Element *E = edited.front(); E; E = E->next()) { Vector2i coords = E->get().get_atlas_coords(); p_canvas_item->draw_rect(p_tile_set_atlas_source->get_tile_texture_region(coords), selection_color, false); } @@ -1299,7 +1299,7 @@ Variant TileDataOcclusionShapeEditor::_get_value(TileSetAtlasSource *p_tile_set_ return tile_data->get_occluder(occlusion_layer); } -void TileDataOcclusionShapeEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { +void TileDataOcclusionShapeEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) { for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { Vector2i coords = E.key.get_atlas_coords(); undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, occlusion_layer), E.value); @@ -1479,7 +1479,7 @@ Variant TileDataCollisionEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas return dict; } -void TileDataCollisionEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { +void TileDataCollisionEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) { Array new_array = p_new_value; for (KeyValue<TileMapCell, Variant> &E : p_previous_values) { Array old_array = E.value; @@ -1740,7 +1740,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(p_transform.affine_inverse().xform(p_canvas_item->get_local_mouse_position()))); rect = rect.abs(); - Set<TileMapCell> edited; + RBSet<TileMapCell> edited; for (int x = rect.get_position().x; x <= rect.get_end().x; x++) { for (int y = rect.get_position().y; y <= rect.get_end().y; y++) { Vector2i coords = Vector2i(x, y); @@ -1755,7 +1755,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas } } - for (Set<TileMapCell>::Element *E = edited.front(); E; E = E->next()) { + for (RBSet<TileMapCell>::Element *E = edited.front(); E; E = E->next()) { Vector2i coords = E->get().get_atlas_coords(); p_canvas_item->draw_rect(p_tile_set_atlas_source->get_tile_texture_region(coords), selection_color, false); } @@ -1770,7 +1770,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(p_transform.affine_inverse().xform(p_canvas_item->get_local_mouse_position()))); rect = rect.abs(); - Set<TileMapCell> edited; + RBSet<TileMapCell> edited; for (int x = rect.get_position().x; x <= rect.get_end().x; x++) { for (int y = rect.get_position().y; y <= rect.get_end().y; y++) { Vector2i coords = Vector2i(x, y); @@ -1800,7 +1800,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas p_canvas_item->draw_set_transform_matrix(p_transform); - for (Set<TileMapCell>::Element *E = edited.front(); E; E = E->next()) { + for (RBSet<TileMapCell>::Element *E = edited.front(); E; E = E->next()) { Vector2i coords = E->get().get_atlas_coords(); Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords); @@ -2118,7 +2118,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position())); rect = rect.abs(); - Set<TileMapCell> edited; + RBSet<TileMapCell> edited; for (int x = rect.get_position().x; x <= rect.get_end().x; x++) { for (int y = rect.get_position().y; y <= rect.get_end().y; y++) { Vector2i coords = Vector2i(x, y); @@ -2133,7 +2133,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t } } undo_redo->create_action(TTR("Painting Terrain Set")); - for (Set<TileMapCell>::Element *E = edited.front(); E; E = E->next()) { + for (RBSet<TileMapCell>::Element *E = edited.front(); E; E = E->next()) { Vector2i coords = E->get().get_atlas_coords(); TileData *tile_data = p_tile_set_atlas_source->get_tile_data(coords, 0); undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->get().alternative_tile), tile_data->get_terrain_set()); @@ -2195,7 +2195,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t rect.set_end(p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position())); rect = rect.abs(); - Set<TileMapCell> edited; + RBSet<TileMapCell> edited; for (int x = rect.get_position().x; x <= rect.get_end().x; x++) { for (int y = rect.get_position().y; y <= rect.get_end().y; y++) { Vector2i coords = Vector2i(x, y); @@ -2220,7 +2220,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t mouse_pos_rect_polygon.push_back(Vector2(drag_start_pos.x, mb->get_position().y)); undo_redo->create_action(TTR("Painting Terrain")); - for (Set<TileMapCell>::Element *E = edited.front(); E; E = E->next()) { + for (RBSet<TileMapCell>::Element *E = edited.front(); E; E = E->next()) { Vector2i coords = E->get().get_atlas_coords(); TileData *tile_data = p_tile_set_atlas_source->get_tile_data(coords, 0); @@ -2571,7 +2571,7 @@ Variant TileDataNavigationEditor::_get_value(TileSetAtlasSource *p_tile_set_atla return tile_data->get_navigation_polygon(navigation_layer); } -void TileDataNavigationEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { +void TileDataNavigationEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) { for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { Vector2i coords = E.key.get_atlas_coords(); undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, navigation_layer), E.value); diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h index 2c849637f0..f9b8948d0a 100644 --- a/editor/plugins/tiles/tile_data_editors.h +++ b/editor/plugins/tiles/tile_data_editors.h @@ -71,7 +71,7 @@ public: class DummyObject : public Object { GDCLASS(DummyObject, Object) private: - Map<String, Variant> properties; + HashMap<String, Variant> properties; protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -206,7 +206,7 @@ private: DragType drag_type = DRAG_TYPE_NONE; Vector2 drag_start_pos; Vector2 drag_last_pos; - Map<TileMapCell, Variant> drag_modified; + HashMap<TileMapCell, Variant, TileMapCell> drag_modified; Variant drag_painted_value; void _property_value_changed(StringName p_property, Variant p_value, StringName p_field); @@ -224,7 +224,7 @@ protected: virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile); virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value); virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile); - virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value); + virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value); public: virtual Control *get_toolbar() override { return toolbar; }; @@ -276,7 +276,7 @@ private: virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) override; virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; - virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) override; + virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override; protected: UndoRedo *undo_redo = nullptr; @@ -301,7 +301,7 @@ class TileDataCollisionEditor : public TileDataDefaultEditor { // UI GenericTilePolygonEditor *polygon_editor = nullptr; DummyObject *dummy_object = memnew(DummyObject); - Map<StringName, EditorProperty *> property_editors; + HashMap<StringName, EditorProperty *> property_editors; void _property_value_changed(StringName p_property, Variant p_value, StringName p_field); void _property_selected(StringName p_path, int p_focusable); @@ -311,7 +311,7 @@ class TileDataCollisionEditor : public TileDataDefaultEditor { virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) override; virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; - virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) override; + virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override; protected: UndoRedo *undo_redo = nullptr; @@ -348,7 +348,7 @@ private: DragType drag_type = DRAG_TYPE_NONE; Vector2 drag_start_pos; Vector2 drag_last_pos; - Map<TileMapCell, Variant> drag_modified; + HashMap<TileMapCell, Variant, TileMapCell> drag_modified; Variant drag_painted_value; // UI @@ -396,7 +396,7 @@ private: virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) override; virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; - virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) override; + virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override; protected: UndoRedo *undo_redo = nullptr; diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index ac90333e1d..12e1f10750 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -501,7 +501,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p if (!tile_map_selection.is_empty()) { tile_map_clipboard.instantiate(); TypedArray<Vector2i> coords_array; - for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { coords_array.push_back(E->get()); } tile_map_clipboard = tile_map->get_pattern(tile_map_layer, coords_array); @@ -511,7 +511,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p // Delete selected tiles. if (!tile_map_selection.is_empty()) { undo_redo->create_action(TTR("Delete tiles")); - for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->get(), tile_map->get_cell_source_id(tile_map_layer, E->get()), tile_map->get_cell_atlas_coords(tile_map_layer, E->get()), tile_map->get_cell_alternative_tile(tile_map_layer, E->get())); } @@ -542,7 +542,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p // Delete selected tiles. if (!tile_map_selection.is_empty()) { undo_redo->create_action(TTR("Delete tiles")); - for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->get(), tile_map->get_cell_source_id(tile_map_layer, E->get()), tile_map->get_cell_atlas_coords(tile_map_layer, E->get()), tile_map->get_cell_alternative_tile(tile_map_layer, E->get())); } @@ -562,7 +562,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p switch (drag_type) { case DRAG_TYPE_PAINT: { - Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_last_mouse_pos, mpos, drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_last_mouse_pos, mpos, drag_erasing); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { continue; @@ -579,7 +579,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos)); for (int i = 0; i < line.size(); i++) { if (!drag_modified.has(line[i])) { - Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { continue; @@ -628,7 +628,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p _update_selection_pattern_from_tilemap_selection(); // Make sure the pattern is up to date before moving. drag_type = DRAG_TYPE_MOVE; drag_modified.clear(); - for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { Vector2i coords = E->get(); drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords)); tile_map->set_cell(tile_map_layer, coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); @@ -648,7 +648,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p drag_type = DRAG_TYPE_PAINT; drag_start_mouse_pos = mpos; drag_modified.clear(); - Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, mpos, mpos, drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, mpos, mpos, drag_erasing); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { continue; @@ -675,7 +675,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos)); for (int i = 0; i < line.size(); i++) { if (!drag_modified.has(line[i])) { - Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { continue; @@ -746,7 +746,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Handle the preview of the tiles to be placed. if ((tiles_bottom_panel->is_visible_in_tree() || patterns_bottom_panel->is_visible_in_tree()) && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered. - Map<Vector2i, TileMapCell> preview; + HashMap<Vector2i, TileMapCell> preview; Rect2i drawn_grid_rect; if (drag_type == DRAG_TYPE_PICK) { @@ -768,7 +768,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Draw the area being selected. Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(drag_last_mouse_pos) - tile_map->world_to_map(drag_start_mouse_pos)).abs(); rect.size += Vector2i(1, 1); - Set<Vector2i> to_draw; + RBSet<Vector2i> to_draw; for (int x = rect.position.x; x < rect.get_end().x; x++) { for (int y = rect.position.y; y < rect.get_end().y; y++) { Vector2i coords = Vector2i(x, y); @@ -785,7 +785,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over if (!tile_map_selection.is_empty()) { top_left = tile_map_selection.front()->get(); } - for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { top_left = top_left.min(E->get()); } Vector2i offset = drag_start_mouse_pos - tile_map->map_to_world(top_left); @@ -832,7 +832,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Expand the grid if needed if (expand_grid && !preview.is_empty()) { - drawn_grid_rect = Rect2i(preview.front()->key(), Vector2i(1, 1)); + drawn_grid_rect = Rect2i(preview.begin()->key, Vector2i(1, 1)); for (const KeyValue<Vector2i, TileMapCell> &E : preview) { drawn_grid_rect.expand_to(E.key); } @@ -986,15 +986,15 @@ TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(Ref<TileMapPattern> p_pa return TileMapCell(); } -Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos, bool p_erase) { +HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos, bool p_erase) { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } Ref<TileSet> tile_set = tile_map->get_tileset(); if (!tile_set.is_valid()) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } // Get or create the pattern. @@ -1003,7 +1003,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_ erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); Ref<TileMapPattern> pattern = p_erase ? erase_pattern : selection_pattern; - Map<Vector2i, TileMapCell> output; + HashMap<Vector2i, TileMapCell> output; if (!pattern->is_empty()) { // Paint the tiles on the tile map. if (!p_erase && random_tile_toggle->is_pressed()) { @@ -1035,15 +1035,15 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_ return output; } -Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) { +HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } Ref<TileSet> tile_set = tile_map->get_tileset(); if (!tile_set.is_valid()) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } // Create the rect to draw. @@ -1056,7 +1056,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); Ref<TileMapPattern> pattern = p_erase ? erase_pattern : selection_pattern; - Map<Vector2i, TileMapCell> err_output; + HashMap<Vector2i, TileMapCell> err_output; ERR_FAIL_COND_V(pattern->is_empty(), err_output); // Compute the offset to align things to the bottom or right. @@ -1064,7 +1064,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start bool valigned_bottom = p_end_cell.y < p_start_cell.y; Vector2i offset = Vector2i(aligned_right ? -(pattern->get_size().x - (rect.get_size().x % pattern->get_size().x)) : 0, valigned_bottom ? -(pattern->get_size().y - (rect.get_size().y % pattern->get_size().y)) : 0); - Map<Vector2i, TileMapCell> output; + HashMap<Vector2i, TileMapCell> output; if (!pattern->is_empty()) { if (!p_erase && random_tile_toggle->is_pressed()) { // Paint a random tile. @@ -1094,21 +1094,21 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start return output; } -Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase) { +HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase) { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } if (tile_map_layer < 0) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } - Map<Vector2i, TileMapCell> output; + HashMap<Vector2i, TileMapCell> output; ERR_FAIL_INDEX_V(tile_map_layer, tile_map->get_layers_count(), output); Ref<TileSet> tile_set = tile_map->get_tileset(); if (!tile_set.is_valid()) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } // Get or create the pattern. @@ -1128,7 +1128,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i if (p_contiguous) { // Replace continuous tiles like the source. - Set<Vector2i> already_checked; + RBSet<Vector2i> already_checked; List<Vector2i> to_check; to_check.push_back(p_coords); while (!to_check.is_empty()) { @@ -1278,7 +1278,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() { if (!tile_map_selection.is_empty()) { top_left = tile_map_selection.front()->get(); } - for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { top_left = top_left.min(E->get()); } @@ -1290,7 +1290,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() { // Build the list of cells to undo. Vector2i coords; - Map<Vector2i, TileMapCell> cells_undo; + HashMap<Vector2i, TileMapCell> cells_undo; for (int i = 0; i < selection_used_cells.size(); i++) { coords = tile_map->map_pattern(top_left, selection_used_cells[i], selection_pattern); cells_undo[coords] = TileMapCell(drag_modified[coords].source_id, drag_modified[coords].get_atlas_coords(), drag_modified[coords].alternative_tile); @@ -1299,7 +1299,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() { } // Build the list of cells to do. - Map<Vector2i, TileMapCell> cells_do; + HashMap<Vector2i, TileMapCell> cells_do; for (int i = 0; i < selection_used_cells.size(); i++) { coords = tile_map->map_pattern(top_left, selection_used_cells[i], selection_pattern); cells_do[coords] = TileMapCell(); @@ -1311,11 +1311,11 @@ void TileMapEditorTilesPlugin::_stop_dragging() { // Move the tiles. undo_redo->create_action(TTR("Move tiles")); - for (Map<Vector2i, TileMapCell>::Element *E = cells_do.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : cells_do) { + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } - for (Map<Vector2i, TileMapCell>::Element *E = cells_undo.front(); E; E = E->next()) { - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : cells_undo) { + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } // Update the selection. @@ -1378,7 +1378,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() { undo_redo->commit_action(false); } break; case DRAG_TYPE_LINE: { - Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_start_mouse_pos, mpos, drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_start_mouse_pos, mpos, drag_erasing); undo_redo->create_action(TTR("Paint tiles")); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { @@ -1390,7 +1390,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() { undo_redo->commit_action(); } break; case DRAG_TYPE_RECT: { - Map<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); undo_redo->create_action(TTR("Paint tiles")); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { @@ -1476,7 +1476,7 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() { } // Selection if needed. - for (Set<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) { + for (RBSet<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) { const TileMapCell *selected = &(E->get()); if (!tile_set->has_source(selected->source_id) || !tile_set->get_source(selected->source_id)->has_tile(selected->get_atlas_coords()) || @@ -1500,7 +1500,7 @@ void TileMapEditorTilesPlugin::_fix_invalid_tiles_in_tile_map_selection() { return; } - Set<Vector2i> to_remove; + RBSet<Vector2i> to_remove; for (Vector2i selected : tile_map_selection) { TileMapCell cell = tile_map->get_cell(tile_map_layer, selected); if (cell.source_id == TileSet::INVALID_SOURCE && cell.get_atlas_coords() == TileSetSource::INVALID_ATLAS_COORDS && cell.alternative_tile == TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) { @@ -1534,7 +1534,7 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tilemap_selection( selection_pattern.instantiate(); TypedArray<Vector2i> coords_array; - for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { coords_array.push_back(E->get()); } selection_pattern = tile_map->get_pattern(tile_map_layer, coords_array); @@ -1558,8 +1558,8 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_tiles_sele selection_pattern.instantiate(); // Group per source. - Map<int, List<const TileMapCell *>> per_source; - for (Set<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) { + HashMap<int, List<const TileMapCell *>> per_source; + for (RBSet<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) { per_source[E->get().source_id].push_back(&(E->get())); } @@ -1568,7 +1568,7 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_tiles_sele // Per source. List<const TileMapCell *> unorganized; Rect2i encompassing_rect_coords; - Map<Vector2i, const TileMapCell *> organized_pattern; + HashMap<Vector2i, const TileMapCell *> organized_pattern; TileSetSource *source = *tile_set->get_source(E_source.key); TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); @@ -1583,12 +1583,12 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_tiles_sele } // Compute the encompassing rect for the organized pattern. - Map<Vector2i, const TileMapCell *>::Element *E_cell = organized_pattern.front(); + HashMap<Vector2i, const TileMapCell *>::Iterator E_cell = organized_pattern.begin(); if (E_cell) { - encompassing_rect_coords = Rect2i(E_cell->key(), Vector2i(1, 1)); - for (; E_cell; E_cell = E_cell->next()) { - encompassing_rect_coords.expand_to(E_cell->key() + Vector2i(1, 1)); - encompassing_rect_coords.expand_to(E_cell->key()); + encompassing_rect_coords = Rect2i(E_cell->key, Vector2i(1, 1)); + for (; E_cell; ++E_cell) { + encompassing_rect_coords.expand_to(E_cell->key + Vector2i(1, 1)); + encompassing_rect_coords.expand_to(E_cell->key); } } } else { @@ -1680,7 +1680,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() { // Draw the selection. Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color"); Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0); - for (Set<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) { + for (RBSet<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) { if (E->get().source_id == source_id && E->get().alternative_tile == 0) { for (int frame = 0; frame < atlas->get_tile_animation_frames_count(E->get().get_atlas_coords()); frame++) { Color color = selection_color; @@ -1711,7 +1711,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() { Rect2i region = Rect2i(start_tile, end_tile - start_tile).abs(); region.size += Vector2i(1, 1); - Set<Vector2i> to_draw; + RBSet<Vector2i> to_draw; for (int x = region.position.x; x < region.get_end().x; x++) { for (int y = region.position.y; y < region.get_end().y; y++) { Vector2i tile = atlas->get_tile_at_coords(Vector2i(x, y)); @@ -1721,7 +1721,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() { } } Color selection_rect_color = selection_color.lightened(0.2); - for (Set<Vector2i>::Element *E = to_draw.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = to_draw.front(); E; E = E->next()) { tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E->get()), selection_rect_color, false); } } @@ -1868,7 +1868,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() { } // Draw the selection. - for (Set<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) { + for (RBSet<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) { if (E->get().source_id == source_id && E->get().get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && E->get().alternative_tile > 0) { Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E->get().get_atlas_coords(), E->get().alternative_tile); if (rect != Rect2i()) { @@ -1972,7 +1972,7 @@ void TileMapEditorTilesPlugin::_set_tile_map_selection(const TypedArray<Vector2i TypedArray<Vector2i> TileMapEditorTilesPlugin::_get_tile_map_selection() const { TypedArray<Vector2i> output; - for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { output.push_back(E->get()); } return output; @@ -2321,33 +2321,33 @@ Vector<TileMapEditorPlugin::TabData> TileMapEditorTerrainsPlugin::get_tabs() con return tabs; } -Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map<Vector2i, TileSet::TerrainsPattern> &p_to_paint, int p_terrain_set) const { +HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const HashMap<Vector2i, TileSet::TerrainsPattern> &p_to_paint, int p_terrain_set) const { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } Ref<TileSet> tile_set = tile_map->get_tileset(); if (!tile_set.is_valid()) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } - Map<Vector2i, TileMapCell> output; + HashMap<Vector2i, TileMapCell> output; // Add the constraints from the added tiles. - Set<TileMap::TerrainConstraint> added_tiles_constraints_set; + RBSet<TileMap::TerrainConstraint> added_tiles_constraints_set; for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E_to_paint : p_to_paint) { Vector2i coords = E_to_paint.key; TileSet::TerrainsPattern terrains_pattern = E_to_paint.value; - Set<TileMap::TerrainConstraint> cell_constraints = tile_map->get_terrain_constraints_from_added_tile(coords, p_terrain_set, terrains_pattern); - for (Set<TileMap::TerrainConstraint>::Element *E = cell_constraints.front(); E; E = E->next()) { + RBSet<TileMap::TerrainConstraint> cell_constraints = tile_map->get_terrain_constraints_from_added_tile(coords, p_terrain_set, terrains_pattern); + for (RBSet<TileMap::TerrainConstraint>::Element *E = cell_constraints.front(); E; E = E->next()) { added_tiles_constraints_set.insert(E->get()); } } // Build the list of potential tiles to replace. - Set<Vector2i> potential_to_replace; + RBSet<Vector2i> potential_to_replace; for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E_to_paint : p_to_paint) { Vector2i coords = E_to_paint.key; for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { @@ -2361,7 +2361,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map } // Set of tiles to replace - Set<Vector2i> to_replace; + RBSet<Vector2i> to_replace; // Add the central tiles to the one to replace. for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E_to_paint : p_to_paint) { @@ -2369,16 +2369,16 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map } // Add the constraints from the surroundings of the modified areas. - Set<TileMap::TerrainConstraint> removed_cells_constraints_set; + RBSet<TileMap::TerrainConstraint> removed_cells_constraints_set; bool to_replace_modified = true; while (to_replace_modified) { // Get the constraints from the removed cells. removed_cells_constraints_set = tile_map->get_terrain_constraints_from_removed_cells_list(tile_map_layer, to_replace, p_terrain_set, false); // Filter the sources to make sure they are in the potential_to_replace. - Map<TileMap::TerrainConstraint, Set<Vector2i>> per_constraint_tiles; - for (Set<TileMap::TerrainConstraint>::Element *E = removed_cells_constraints_set.front(); E; E = E->next()) { - Map<Vector2i, TileSet::CellNeighbor> sources_of_constraint = E->get().get_overlapping_coords_and_peering_bits(); + RBMap<TileMap::TerrainConstraint, RBSet<Vector2i>> per_constraint_tiles; + for (RBSet<TileMap::TerrainConstraint>::Element *E = removed_cells_constraints_set.front(); E; E = E->next()) { + HashMap<Vector2i, TileSet::CellNeighbor> sources_of_constraint = E->get().get_overlapping_coords_and_peering_bits(); for (const KeyValue<Vector2i, TileSet::CellNeighbor> &E_source_tile_of_constraint : sources_of_constraint) { if (potential_to_replace.has(E_source_tile_of_constraint.key)) { per_constraint_tiles[E->get()].insert(E_source_tile_of_constraint.key); @@ -2387,7 +2387,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map } to_replace_modified = false; - for (Set<TileMap::TerrainConstraint>::Element *E = added_tiles_constraints_set.front(); E; E = E->next()) { + for (RBSet<TileMap::TerrainConstraint>::Element *E = added_tiles_constraints_set.front(); E; E = E->next()) { TileMap::TerrainConstraint c = E->get(); // Check if we have a conflict in constraints. if (removed_cells_constraints_set.has(c) && removed_cells_constraints_set.find(c)->get().get_terrain() != c.get_terrain()) { @@ -2398,7 +2398,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map potential_to_replace.erase(to_add_to_remove); to_replace.insert(to_add_to_remove); to_replace_modified = true; - for (KeyValue<TileMap::TerrainConstraint, Set<Vector2i>> &E_source_tiles_of_constraint : per_constraint_tiles) { + for (KeyValue<TileMap::TerrainConstraint, RBSet<Vector2i>> &E_source_tiles_of_constraint : per_constraint_tiles) { E_source_tiles_of_constraint.value.erase(to_add_to_remove); } break; @@ -2408,8 +2408,8 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map } // Combine all constraints together. - Set<TileMap::TerrainConstraint> constraints = removed_cells_constraints_set; - for (Set<TileMap::TerrainConstraint>::Element *E = added_tiles_constraints_set.front(); E; E = E->next()) { + RBSet<TileMap::TerrainConstraint> constraints = removed_cells_constraints_set; + for (RBSet<TileMap::TerrainConstraint>::Element *E = added_tiles_constraints_set.front(); E; E = E->next()) { constraints.insert(E->get()); } @@ -2419,7 +2419,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map } // Run WFC to fill the holes with the constraints. - Map<Vector2i, TileSet::TerrainsPattern> wfc_output = tile_map->terrain_wave_function_collapse(to_replace, p_terrain_set, constraints); + HashMap<Vector2i, TileSet::TerrainsPattern> wfc_output = tile_map->terrain_wave_function_collapse(to_replace, p_terrain_set, constraints); // Actually paint the tiles. for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E_to_paint : p_to_paint) { @@ -2434,15 +2434,15 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map return output; } -Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_line(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) { +HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_line(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } Ref<TileSet> tile_set = tile_map->get_tileset(); if (!tile_set.is_valid()) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } TileSet::TerrainsPattern terrains_pattern; @@ -2453,22 +2453,22 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_line(Vector2i p_st } Vector<Vector2i> line = TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell); - Map<Vector2i, TileSet::TerrainsPattern> to_draw; + HashMap<Vector2i, TileSet::TerrainsPattern> to_draw; for (int i = 0; i < line.size(); i++) { to_draw[line[i]] = terrains_pattern; } return _draw_terrains(to_draw, selected_terrain_set); } -Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) { +HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } Ref<TileSet> tile_set = tile_map->get_tileset(); if (!tile_set.is_valid()) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } TileSet::TerrainsPattern terrains_pattern; @@ -2483,7 +2483,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_rect(Vector2i p_st rect.set_end(p_end_cell); rect = rect.abs(); - Map<Vector2i, TileSet::TerrainsPattern> to_draw; + HashMap<Vector2i, TileSet::TerrainsPattern> to_draw; for (int x = rect.position.x; x <= rect.get_end().x; x++) { for (int y = rect.position.y; y <= rect.get_end().y; y++) { to_draw[Vector2i(x, y)] = terrains_pattern; @@ -2492,15 +2492,15 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_rect(Vector2i p_st return _draw_terrains(to_draw, selected_terrain_set); } -Set<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i p_coords, bool p_contiguous) { +RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i p_coords, bool p_contiguous) { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { - return Set<Vector2i>(); + return RBSet<Vector2i>(); } Ref<TileSet> tile_set = tile_map->get_tileset(); if (!tile_set.is_valid()) { - return Set<Vector2i>(); + return RBSet<Vector2i>(); } TileMapCell source_cell = tile_map->get_cell(tile_map_layer, p_coords); @@ -2514,7 +2514,7 @@ Set<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i p tile_data = atlas_source->get_tile_data(source_cell.get_atlas_coords(), source_cell.alternative_tile); } if (!tile_data) { - return Set<Vector2i>(); + return RBSet<Vector2i>(); } source_pattern = tile_data->get_terrains_pattern(); } @@ -2525,10 +2525,10 @@ Set<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i p boundaries = tile_map->get_used_rect(); } - Set<Vector2i> output; + RBSet<Vector2i> output; if (p_contiguous) { // Replace continuous tiles like the source. - Set<Vector2i> already_checked; + RBSet<Vector2i> already_checked; List<Vector2i> to_check; to_check.push_back(p_coords); while (!to_check.is_empty()) { @@ -2603,15 +2603,15 @@ Set<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i p return output; } -Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase) { +HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase) { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } Ref<TileSet> tile_set = tile_map->get_tileset(); if (!tile_set.is_valid()) { - return Map<Vector2i, TileMapCell>(); + return HashMap<Vector2i, TileMapCell>(); } TileSet::TerrainsPattern terrains_pattern; @@ -2621,8 +2621,8 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_bucket_fill(Vector terrains_pattern = selected_terrains_pattern; } - Set<Vector2i> cells_to_draw = _get_cells_for_bucket_fill(p_coords, p_contiguous); - Map<Vector2i, TileSet::TerrainsPattern> to_draw; + RBSet<Vector2i> cells_to_draw = _get_cells_for_bucket_fill(p_coords, p_contiguous); + HashMap<Vector2i, TileSet::TerrainsPattern> to_draw; for (const Vector2i &coords : cells_to_draw) { to_draw[coords] = terrains_pattern; } @@ -2718,7 +2718,7 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() { undo_redo->commit_action(false); } break; case DRAG_TYPE_LINE: { - Map<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); undo_redo->create_action(TTR("Paint terrain")); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { @@ -2730,7 +2730,7 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() { undo_redo->commit_action(); } break; case DRAG_TYPE_RECT: { - Map<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); undo_redo->create_action(TTR("Paint terrain")); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { @@ -2829,7 +2829,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> switch (drag_type) { case DRAG_TYPE_PAINT: { if (selected_terrain_set >= 0) { - Map<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_modified.has(E.key)) { drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key); @@ -2874,7 +2874,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> drag_modified.clear(); Vector2i cell = tile_map->world_to_map(mpos); - Map<Vector2i, TileMapCell> to_draw = _draw_line(cell, cell, drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_line(cell, cell, drag_erasing); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key); tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); @@ -2903,7 +2903,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos)); for (int i = 0; i < line.size(); i++) { if (!drag_modified.has(line[i])) { - Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { continue; @@ -2959,7 +2959,7 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o // Handle the preview of the tiles to be placed. if (main_vbox_container->is_visible_in_tree() && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered. - Set<Vector2i> preview; + RBSet<Vector2i> preview; Rect2i drawn_grid_rect; if (drag_type == DRAG_TYPE_PICK) { @@ -2996,7 +2996,7 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o rect.set_end(tile_map->world_to_map(drag_last_mouse_pos)); rect = rect.abs(); - Map<Vector2i, TileSet::TerrainsPattern> to_draw; + HashMap<Vector2i, TileSet::TerrainsPattern> to_draw; for (int x = rect.position.x; x <= rect.get_end().x; x++) { for (int y = rect.position.y; y <= rect.get_end().y; y++) { preview.insert(Vector2i(x, y)); @@ -3192,9 +3192,9 @@ void TileMapEditorTerrainsPlugin::_update_tiles_list() { ERR_FAIL_INDEX(selected_terrain_id, tile_set->get_terrains_count(selected_terrain_set)); // Sort the items in a map by the number of corresponding terrains. - Map<int, Set<TileSet::TerrainsPattern>> sorted; + RBMap<int, RBSet<TileSet::TerrainsPattern>> sorted; - for (Set<TileSet::TerrainsPattern>::Element *E = per_terrain_terrains_patterns[selected_terrain_set][selected_terrain_id].front(); E; E = E->next()) { + for (RBSet<TileSet::TerrainsPattern>::Element *E = per_terrain_terrains_patterns[selected_terrain_set][selected_terrain_id].front(); E; E = E->next()) { // Count the number of matching sides/terrains. int count = 0; @@ -3207,8 +3207,8 @@ void TileMapEditorTerrainsPlugin::_update_tiles_list() { sorted[count].insert(E->get()); } - for (Map<int, Set<TileSet::TerrainsPattern>>::Element *E_set = sorted.back(); E_set; E_set = E_set->prev()) { - for (Set<TileSet::TerrainsPattern>::Element *E = E_set->get().front(); E; E = E->next()) { + for (RBMap<int, RBSet<TileSet::TerrainsPattern>>::Element *E_set = sorted.back(); E_set; E_set = E_set->prev()) { + for (RBSet<TileSet::TerrainsPattern>::Element *E = E_set->get().front(); E; E = E->next()) { TileSet::TerrainsPattern terrains_pattern = E->get(); // Get the icon. diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h index f265052200..7158ebff59 100644 --- a/editor/plugins/tiles/tile_map_editor.h +++ b/editor/plugins/tiles/tile_map_editor.h @@ -120,22 +120,22 @@ private: bool drag_erasing = false; Vector2 drag_start_mouse_pos; Vector2 drag_last_mouse_pos; - Map<Vector2i, TileMapCell> drag_modified; + HashMap<Vector2i, TileMapCell> drag_modified; TileMapCell _pick_random_tile(Ref<TileMapPattern> p_pattern); - Map<Vector2i, TileMapCell> _draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos, bool p_erase); - Map<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase); - Map<Vector2i, TileMapCell> _draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase); + HashMap<Vector2i, TileMapCell> _draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos, bool p_erase); + HashMap<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase); + HashMap<Vector2i, TileMapCell> _draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase); void _stop_dragging(); ///// Selection system. ///// - Set<Vector2i> tile_map_selection; + RBSet<Vector2i> tile_map_selection; Ref<TileMapPattern> tile_map_clipboard; Ref<TileMapPattern> selection_pattern; void _set_tile_map_selection(const TypedArray<Vector2i> &p_selection); TypedArray<Vector2i> _get_tile_map_selection() const; - Set<TileMapCell> tile_set_selection; + RBSet<TileMapCell> tile_set_selection; void _update_selection_pattern_from_tilemap_selection(); void _update_selection_pattern_from_tileset_tiles_selection(); @@ -265,14 +265,14 @@ private: bool drag_erasing = false; Vector2 drag_start_mouse_pos; Vector2 drag_last_mouse_pos; - Map<Vector2i, TileMapCell> drag_modified; + HashMap<Vector2i, TileMapCell> drag_modified; // Painting - Map<Vector2i, TileMapCell> _draw_terrains(const Map<Vector2i, TileSet::TerrainsPattern> &p_to_paint, int p_terrain_set) const; - Map<Vector2i, TileMapCell> _draw_line(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase); - Map<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase); - Set<Vector2i> _get_cells_for_bucket_fill(Vector2i p_coords, bool p_contiguous); - Map<Vector2i, TileMapCell> _draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase); + HashMap<Vector2i, TileMapCell> _draw_terrains(const HashMap<Vector2i, TileSet::TerrainsPattern> &p_to_paint, int p_terrain_set) const; + HashMap<Vector2i, TileMapCell> _draw_line(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase); + HashMap<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase); + RBSet<Vector2i> _get_cells_for_bucket_fill(Vector2i p_coords, bool p_contiguous); + HashMap<Vector2i, TileMapCell> _draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase); void _stop_dragging(); int selected_terrain_set = -1; @@ -284,7 +284,7 @@ private: ItemList *terrains_tile_list = nullptr; // Cache. - LocalVector<LocalVector<Set<TileSet::TerrainsPattern>>> per_terrain_terrains_patterns; + LocalVector<LocalVector<RBSet<TileSet::TerrainsPattern>>> per_terrain_terrains_patterns; // Update functions. void _update_terrains_cache(); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index 44b18f48fc..dc3fa87565 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -270,7 +270,7 @@ bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_na // Other properties. bool any_valid = false; - for (Set<TileSelection>::Element *E = tiles.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = tiles.front(); E; E = E->next()) { const Vector2i &coords = E->get().tile; const int &alternative = E->get().alternative; @@ -354,7 +354,7 @@ bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_get(const StringName &p_na } } - for (Set<TileSelection>::Element *E = tiles.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = tiles.front(); E; E = E->next()) { // Return the first tile with a property matching the name. // Note: It's a little bit annoying, but the behavior is the same the one in MultiNodeEdit. const Vector2i &coords = E->get().tile; @@ -426,10 +426,10 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro int uses = 0; PropertyInfo property_info; }; - Map<PropertyId, PLData> usage; + RBMap<PropertyId, PLData> usage; List<PLData *> data_list; - for (Set<TileSelection>::Element *E = tiles.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = tiles.front(); E; E = E->next()) { const Vector2i &coords = E->get().tile; const int &alternative = E->get().alternative; @@ -439,7 +439,7 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro List<PropertyInfo> list; tile_data->get_property_list(&list); - Map<String, int> counts; // Counts the number of time a property appears (useful for groups that may appear more than once) + HashMap<String, int> counts; // Counts the number of time a property appears (useful for groups that may appear more than once) for (List<PropertyInfo>::Element *E_property = list.front(); E_property; E_property = E_property->next()) { const String &property_string = E_property->get().name; if (!tile_data->is_allowing_transform() && (property_string == "flip_h" || property_string == "flip_v" || property_string == "transpose")) { @@ -473,16 +473,16 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro } } -void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(TileSetAtlasSource *p_tile_set_atlas_source, Set<TileSelection> p_tiles) { +void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(TileSetAtlasSource *p_tile_set_atlas_source, RBSet<TileSelection> p_tiles) { ERR_FAIL_COND(!p_tile_set_atlas_source); ERR_FAIL_COND(p_tiles.is_empty()); - for (Set<TileSelection>::Element *E = p_tiles.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = p_tiles.front(); E; E = E->next()) { ERR_FAIL_COND(E->get().tile == TileSetSource::INVALID_ATLAS_COORDS); ERR_FAIL_COND(E->get().alternative < 0); } // Disconnect to changes. - for (Set<TileSelection>::Element *E = tiles.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = tiles.front(); E; E = E->next()) { const Vector2i &coords = E->get().tile; const int &alternative = E->get().alternative; @@ -495,10 +495,10 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(TileSetAtlasSource *p_ } tile_set_atlas_source = p_tile_set_atlas_source; - tiles = Set<TileSelection>(p_tiles); + tiles = RBSet<TileSelection>(p_tiles); // Connect to changes. - for (Set<TileSelection>::Element *E = p_tiles.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = p_tiles.front(); E; E = E->next()) { const Vector2i &coords = E->get().tile; const int &alternative = E->get().alternative; @@ -541,7 +541,7 @@ void TileSetAtlasSourceEditor::_update_source_inspector() { void TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles() { // Fix selected. - for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = selection.front(); E; E = E->next()) { TileSelection selected = E->get(); if (!tile_set_atlas_source->has_tile(selected.tile) || !tile_set_atlas_source->has_alternative_tile(selected.tile, selected.alternative)) { selection.erase(E); @@ -1313,7 +1313,7 @@ void TileSetAtlasSourceEditor::_end_dragging() { switch (drag_type) { case DRAG_TYPE_CREATE_TILES: undo_redo->create_action(TTR("Create tiles")); - for (Set<Vector2i>::Element *E = drag_modified_tiles.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = drag_modified_tiles.front(); E; E = E->next()) { undo_redo->add_do_method(tile_set_atlas_source, "create_tile", E->get()); undo_redo->add_undo_method(tile_set_atlas_source, "remove_tile", E->get()); } @@ -1328,9 +1328,9 @@ void TileSetAtlasSourceEditor::_end_dragging() { case DRAG_TYPE_REMOVE_TILES: { List<PropertyInfo> list; tile_set_atlas_source->get_property_list(&list); - Map<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source); + HashMap<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source); undo_redo->create_action(TTR("Remove tiles")); - for (Set<Vector2i>::Element *E = drag_modified_tiles.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = drag_modified_tiles.front(); E; E = E->next()) { Vector2i coords = E->get(); undo_redo->add_do_method(tile_set_atlas_source, "remove_tile", coords); undo_redo->add_undo_method(tile_set_atlas_source, "create_tile", coords); @@ -1370,9 +1370,9 @@ void TileSetAtlasSourceEditor::_end_dragging() { area.set_end((area.get_end() + Vector2i(1, 1)).min(tile_set_atlas_source->get_atlas_grid_size())); List<PropertyInfo> list; tile_set_atlas_source->get_property_list(&list); - Map<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source); + HashMap<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source); - Set<Vector2i> to_delete; + RBSet<Vector2i> to_delete; for (int x = area.get_position().x; x < area.get_end().x; x++) { for (int y = area.get_position().y; y < area.get_end().y; y++) { Vector2i coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y)); @@ -1384,7 +1384,7 @@ void TileSetAtlasSourceEditor::_end_dragging() { undo_redo->create_action(TTR("Remove tiles")); undo_redo->add_do_method(this, "_set_selection_from_array", Array()); - for (Set<Vector2i>::Element *E = to_delete.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = to_delete.front(); E; E = E->next()) { Vector2i coords = E->get(); undo_redo->add_do_method(tile_set_atlas_source, "remove_tile", coords); undo_redo->add_undo_method(tile_set_atlas_source, "create_tile", coords); @@ -1523,9 +1523,9 @@ void TileSetAtlasSourceEditor::_end_dragging() { tile_atlas_control->set_default_cursor_shape(CURSOR_ARROW); } -Map<Vector2i, List<const PropertyInfo *>> TileSetAtlasSourceEditor::_group_properties_per_tiles(const List<PropertyInfo> &r_list, const TileSetAtlasSource *p_atlas) { +HashMap<Vector2i, List<const PropertyInfo *>> TileSetAtlasSourceEditor::_group_properties_per_tiles(const List<PropertyInfo> &r_list, const TileSetAtlasSource *p_atlas) { // Group properties per tile. - Map<Vector2i, List<const PropertyInfo *>> per_tile; + HashMap<Vector2i, List<const PropertyInfo *>> per_tile; for (const List<PropertyInfo>::Element *E_property = r_list.front(); E_property; E_property = E_property->next()) { Vector<String> components = String(E_property->get().name).split("/", true, 1); if (components.size() >= 1) { @@ -1544,12 +1544,12 @@ void TileSetAtlasSourceEditor::_menu_option(int p_option) { case TILE_DELETE: { List<PropertyInfo> list; tile_set_atlas_source->get_property_list(&list); - Map<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source); + HashMap<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source); undo_redo->create_action(TTR("Remove tile")); // Remove tiles - Set<Vector2i> removed; - for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) { + RBSet<Vector2i> removed; + for (RBSet<TileSelection>::Element *E = selection.front(); E; E = E->next()) { TileSelection selected = E->get(); if (selected.alternative == 0) { // Remove a tile. @@ -1569,7 +1569,7 @@ void TileSetAtlasSourceEditor::_menu_option(int p_option) { } // Remove alternatives - for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = selection.front(); E; E = E->next()) { TileSelection selected = E->get(); if (selected.alternative > 0 && !removed.has(selected.tile)) { // Remove an alternative tile. @@ -1608,7 +1608,7 @@ void TileSetAtlasSourceEditor::_menu_option(int p_option) { case TILE_CREATE_ALTERNATIVE: { undo_redo->create_action(TTR("Create tile alternatives")); Array array; - for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = selection.front(); E; E = E->next()) { if (E->get().alternative == 0) { int next_id = tile_set_atlas_source->get_next_alternative_tile_id(E->get().tile); undo_redo->add_do_method(tile_set_atlas_source, "create_alternative_tile", E->get().tile, next_id); @@ -1658,7 +1658,7 @@ void TileSetAtlasSourceEditor::_set_selection_from_array(Array p_selection) { Array TileSetAtlasSourceEditor::_get_selection_as_array() { Array output; - for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = selection.front(); E; E = E->next()) { output.push_back(E->get().tile); output.push_back(E->get().alternative); } @@ -1672,7 +1672,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { // Draw the selected tile. if (tools_button_group->get_pressed_button() == tool_select_button) { - for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = selection.front(); E; E = E->next()) { TileSelection selected = E->get(); if (selected.alternative == 0) { // Draw the rect. @@ -1722,7 +1722,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { if (drag_type == DRAG_TYPE_REMOVE_TILES) { // Draw the tiles to be removed. - for (Set<Vector2i>::Element *E = drag_modified_tiles.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = drag_modified_tiles.front(); E; E = E->next()) { for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(E->get()); frame++) { tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(E->get(), frame), Color(0.0, 0.0, 0.0), false); } @@ -1739,7 +1739,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { color = selection_color.lightened(0.2); } - Set<Vector2i> to_paint; + RBSet<Vector2i> to_paint; for (int x = area.get_position().x; x < area.get_end().x; x++) { for (int y = area.get_position().y; y < area.get_end().y; y++) { Vector2i coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y)); @@ -1749,7 +1749,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { } } - for (Set<Vector2i>::Element *E = to_paint.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = to_paint.front(); E; E = E->next()) { Vector2i coords = E->get(); tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(coords), color, false); } @@ -1837,7 +1837,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() { // Draw the selection on top of other. if (tools_button_group->get_pressed_button() == tool_select_button) { - for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = selection.front(); E; E = E->next()) { if (E->get().alternative != 0) { continue; } @@ -1962,7 +1962,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() { } // Draw selected tile. - for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = selection.front(); E; E = E->next()) { TileSelection selected = E->get(); if (selected.alternative >= 1) { Rect2i rect = tile_atlas_view->get_alternative_tile_rect(selected.tile, selected.alternative); @@ -2005,7 +2005,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() { // Draw the selection on top of other. if (tools_button_group->get_pressed_button() == tool_select_button) { - for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) { + for (RBSet<TileSelection>::Element *E = selection.front(); E; E = E->next()) { if (E->get().alternative == 0) { continue; } @@ -2222,7 +2222,7 @@ void TileSetAtlasSourceEditor::_auto_remove_tiles() { List<PropertyInfo> list; tile_set_atlas_source->get_property_list(&list); - Map<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source); + HashMap<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source); for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) { Vector2i coords = tile_set_atlas_source->get_tile_id(i); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h index b26b7edbfa..738fe1044d 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.h +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h @@ -88,7 +88,7 @@ public: TileSetAtlasSourceEditor *tiles_set_atlas_source_editor = nullptr; TileSetAtlasSource *tile_set_atlas_source = nullptr; - Set<TileSelection> tiles = Set<TileSelection>(); + RBSet<TileSelection> tiles = RBSet<TileSelection>(); protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -99,10 +99,10 @@ public: public: TileSetAtlasSource *get_edited_tile_set_atlas_source() const { return tile_set_atlas_source; }; - Set<TileSelection> get_edited_tiles() const { return tiles; }; + RBSet<TileSelection> get_edited_tiles() const { return tiles; }; // Update the proxyed object. - void edit(TileSetAtlasSource *p_tile_set_atlas_source, Set<TileSelection> p_tiles = Set<TileSelection>()); + void edit(TileSetAtlasSource *p_tile_set_atlas_source, RBSet<TileSelection> p_tiles = RBSet<TileSelection>()); AtlasTileProxyObject(TileSetAtlasSourceEditor *p_tiles_set_atlas_source_editor) { tiles_set_atlas_source_editor = p_tiles_set_atlas_source_editor; @@ -130,7 +130,7 @@ private: // -- Tile data editors -- String current_property; Control *current_tile_data_editor_toolbar = nullptr; - Map<String, TileDataEditor *> tile_data_editors; + HashMap<String, TileDataEditor *> tile_data_editors; TileDataEditor *current_tile_data_editor = nullptr; void _tile_data_editors_tree_selected(); @@ -182,10 +182,10 @@ private: Vector2i drag_current_tile; Rect2i drag_start_tile_shape; - Set<Vector2i> drag_modified_tiles; + RBSet<Vector2i> drag_modified_tiles; void _end_dragging(); - Map<Vector2i, List<const PropertyInfo *>> _group_properties_per_tiles(const List<PropertyInfo> &r_list, const TileSetAtlasSource *p_atlas); + HashMap<Vector2i, List<const PropertyInfo *>> _group_properties_per_tiles(const List<PropertyInfo> &r_list, const TileSetAtlasSource *p_atlas); // Popup functions. enum MenuOptions { @@ -215,7 +215,7 @@ private: MenuButton *tool_advanced_menu_buttom = nullptr; // Selection. - Set<TileSelection> selection; + RBSet<TileSelection> selection; void _set_selection_from_array(Array p_selection); Array _get_selection_as_array(); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index f184049d41..c5669f3eda 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -148,6 +148,7 @@ void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p if (links[p_node_id].preview_pos != -1) { links[p_node_id].graph_node->move_child(vbox, links[p_node_id].preview_pos); } + links[p_node_id].graph_node->set_slot_draw_stylebox(vbox->get_index(), false); Control *offset = memnew(Control); offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE)); @@ -324,7 +325,7 @@ void VisualShaderGraphPlugin::make_dirty(bool p_enabled) { } void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node) { - links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr, { nullptr, nullptr, nullptr } }); + links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, HashMap<int, InputPort>(), HashMap<int, Port>(), nullptr, nullptr, nullptr, { nullptr, nullptr, nullptr } }); } void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) { @@ -386,6 +387,14 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { "alpha" }; + // Visual shader specific theme for MSDF font. + Ref<Theme> vstheme; + vstheme.instantiate(); + Ref<Font> label_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_msdf", "EditorFonts"); + vstheme->set_font("font", "Label", label_font); + vstheme->set_font("font", "LineEdit", label_font); + vstheme->set_font("font", "Button", label_font); + Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id); Ref<VisualShaderNodeResizableBase> resizable_node = Object::cast_to<VisualShaderNodeResizableBase>(vsnode.ptr()); @@ -406,8 +415,10 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { custom_node->_set_initialized(true); } + // Create graph node. GraphNode *node = memnew(GraphNode); graph->add_child(node); + node->set_theme(vstheme); editor->_update_created_node(node); register_link(p_type, p_id, vsnode.ptr(), node); @@ -942,12 +953,12 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { if (vsnode->get_output_port_for_preview() >= 0) { show_port_preview(p_type, p_id, vsnode->get_output_port_for_preview()); + } else { + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); + node->add_child(offset); } - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); - node->add_child(offset); - String error = vsnode->get_warning(mode, p_type); if (!error.is_empty()) { Label *error_label = memnew(Label); @@ -1359,7 +1370,7 @@ void VisualShaderEditor::_update_options_menu() { static bool low_driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name") == "opengl3"; - Map<String, TreeItem *> folders; + HashMap<String, TreeItem *> folders; int current_func = -1; @@ -1659,7 +1670,7 @@ void VisualShaderEditor::_update_uniforms(bool p_update_refs) { } } -void VisualShaderEditor::_update_uniform_refs(Set<String> &p_deleted_names) { +void VisualShaderEditor::_update_uniform_refs(RBSet<String> &p_deleted_names) { for (int i = 0; i < VisualShader::TYPE_MAX; i++) { VisualShader::Type type = VisualShader::Type(i); @@ -2277,7 +2288,7 @@ void VisualShaderEditor::_uniform_line_edit_changed(const String &p_text, int p_ undo_redo->add_do_method(this, "_update_uniforms", true); undo_redo->add_undo_method(this, "_update_uniforms", true); - Set<String> changed_names; + RBSet<String> changed_names; changed_names.insert(node->get_uniform_name()); _update_uniform_refs(changed_names); @@ -3097,7 +3108,7 @@ void VisualShaderEditor::_delete_nodes(int p_type, const List<int> &p_nodes) { } } - Set<String> uniform_names; + RBSet<String> uniform_names; for (const int &F : p_nodes) { Ref<VisualShaderNode> node = visual_shader->get_node(type, F); @@ -3201,10 +3212,10 @@ void VisualShaderEditor::_convert_constants_to_uniforms(bool p_vice_versa) { undo_redo->create_action(TTR("Convert Uniform Node(s) To Constant(s)")); } - const Set<int> ¤t_set = p_vice_versa ? selected_uniforms : selected_constants; - Set<String> deleted_names; + const RBSet<int> ¤t_set = p_vice_versa ? selected_uniforms : selected_constants; + RBSet<String> deleted_names; - for (Set<int>::Element *E = current_set.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = current_set.front(); E; E = E->next()) { int node_id = E->get(); Ref<VisualShaderNode> node = visual_shader->get_node(type_id, node_id); bool caught = false; @@ -3398,16 +3409,23 @@ void VisualShaderEditor::_delete_node_request(int p_type, int p_node) { undo_redo->commit_action(); } -void VisualShaderEditor::_delete_nodes_request() { +void VisualShaderEditor::_delete_nodes_request(const TypedArray<StringName> &p_nodes) { List<int> to_erase; - for (int i = 0; i < graph->get_child_count(); i++) { - GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); - if (gn) { - if (gn->is_selected() && gn->is_close_button_visible()) { - to_erase.push_back(gn->get_name().operator String().to_int()); + if (p_nodes.is_empty()) { + // Called from context menu. + for (int i = 0; i < graph->get_child_count(); i++) { + GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); + if (gn) { + if (gn->is_selected() && gn->is_close_button_visible()) { + to_erase.push_back(gn->get_name().operator String().to_int()); + } } } + } else { + for (int i = 0; i < p_nodes.size(); i++) { + to_erase.push_back(p_nodes[i].operator String().to_int()); + } } if (to_erase.is_empty()) { @@ -3771,7 +3789,7 @@ void VisualShaderEditor::_dup_copy_nodes(int p_type, List<CopyItem> &r_items, Li selection_center.x = 0.0f; selection_center.y = 0.0f; - Set<int> nodes; + RBSet<int> nodes; for (int i = 0; i < graph->get_child_count(); i++) { GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); @@ -3850,9 +3868,9 @@ void VisualShaderEditor::_dup_paste_nodes(int p_type, List<CopyItem> &r_items, c int base_id = visual_shader->get_valid_node_id(type); int id_from = base_id; - Map<int, int> connection_remap; - Set<int> unsupported_set; - Set<int> added_set; + HashMap<int, int> connection_remap; + RBSet<int> unsupported_set; + RBSet<int> added_set; for (CopyItem &item : r_items) { if (item.disabled) { @@ -4400,7 +4418,7 @@ void VisualShaderEditor::_node_menu_id_pressed(int p_idx) { _paste_nodes(true, menu_point); break; case NodeMenuOptions::DELETE: - _delete_nodes_request(); + _delete_nodes_request(TypedArray<StringName>()); break; case NodeMenuOptions::DUPLICATE: _duplicate_nodes(); @@ -4652,6 +4670,7 @@ VisualShaderEditor::VisualShaderEditor() { graph->get_zoom_hbox()->set_h_size_flags(SIZE_EXPAND_FILL); graph->set_v_size_flags(SIZE_EXPAND_FILL); graph->set_h_size_flags(SIZE_EXPAND_FILL); + graph->set_show_zoom_label(true); add_child(graph); graph->set_drag_forwarding(this); float graph_minimap_opacity = EditorSettings::get_singleton()->get("editors/visual_editors/minimap_opacity"); @@ -4801,7 +4820,7 @@ VisualShaderEditor::VisualShaderEditor() { /////////////////////////////////////// preview_window = memnew(Window); - preview_window->set_title(TTR("Generated shader code")); + preview_window->set_title(TTR("Generated Shader Code")); preview_window->set_visible(preview_showed); preview_window->connect("close_requested", callable_mp(this, &VisualShaderEditor::_preview_close_requested)); preview_window->connect("size_changed", callable_mp(this, &VisualShaderEditor::_preview_size_changed)); @@ -5027,8 +5046,8 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ColorOp", "Color", "Common", "VisualShaderNodeColorOp", TTR("Color operator."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Grayscale", "Color", "Functions", "VisualShaderNodeColorFunc", TTR("Grayscale function."), { VisualShaderNodeColorFunc::FUNC_GRAYSCALE }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); - add_options.push_back(AddOption("HSV2RGB", "Color", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts HSV vector to RGB equivalent."), { VisualShaderNodeVectorFunc::FUNC_HSV2RGB, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); - add_options.push_back(AddOption("RGB2HSV", "Color", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts RGB vector to HSV equivalent."), { VisualShaderNodeVectorFunc::FUNC_RGB2HSV, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("HSV2RGB", "Color", "Functions", "VisualShaderNodeColorFunc", TTR("Converts HSV vector to RGB equivalent."), { VisualShaderNodeColorFunc::FUNC_HSV2RGB, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("RGB2HSV", "Color", "Functions", "VisualShaderNodeColorFunc", TTR("Converts RGB vector to HSV equivalent."), { VisualShaderNodeColorFunc::FUNC_RGB2HSV, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Sepia", "Color", "Functions", "VisualShaderNodeColorFunc", TTR("Sepia function."), { VisualShaderNodeColorFunc::FUNC_SEPIA }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Burn", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Burn operator."), { VisualShaderNodeColorOp::OP_BURN }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); @@ -5041,8 +5060,8 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Screen", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Screen operator."), { VisualShaderNodeColorOp::OP_SCREEN }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("SoftLight", "Color", "Operators", "VisualShaderNodeColorOp", TTR("SoftLight operator."), { VisualShaderNodeColorOp::OP_SOFT_LIGHT }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); - add_options.push_back(AddOption("ColorConstant", "Color", "Variables", "VisualShaderNodeColorConstant", TTR("Color constant."))); - add_options.push_back(AddOption("ColorUniform", "Color", "Variables", "VisualShaderNodeColorUniform", TTR("Color uniform."))); + add_options.push_back(AddOption("ColorConstant", "Color", "Variables", "VisualShaderNodeColorConstant", TTR("Color constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D)); + add_options.push_back(AddOption("ColorUniform", "Color", "Variables", "VisualShaderNodeColorUniform", TTR("Color uniform."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D)); // COMMON @@ -5368,25 +5387,25 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("UVFunc", "Textures", "Common", "VisualShaderNodeUVFunc", TTR("Function to be applied on texture coordinates."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D)); cubemap_node_option_idx = add_options.size(); - add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."))); + add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D)); curve_node_option_idx = add_options.size(); - add_options.push_back(AddOption("CurveTexture", "Textures", "Functions", "VisualShaderNodeCurveTexture", TTR("Perform the curve texture lookup."))); + add_options.push_back(AddOption("CurveTexture", "Textures", "Functions", "VisualShaderNodeCurveTexture", TTR("Perform the curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_SCALAR)); curve_xyz_node_option_idx = add_options.size(); - add_options.push_back(AddOption("CurveXYZTexture", "Textures", "Functions", "VisualShaderNodeCurveXYZTexture", TTR("Perform the three components curve texture lookup."))); + add_options.push_back(AddOption("CurveXYZTexture", "Textures", "Functions", "VisualShaderNodeCurveXYZTexture", TTR("Perform the three components curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D)); texture2d_node_option_idx = add_options.size(); - add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."))); + add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D)); texture2d_array_node_option_idx = add_options.size(); - add_options.push_back(AddOption("Texture2DArray", "Textures", "Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."))); + add_options.push_back(AddOption("Texture2DArray", "Textures", "Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D)); texture3d_node_option_idx = add_options.size(); - add_options.push_back(AddOption("Texture3D", "Textures", "Functions", "VisualShaderNodeTexture3D", TTR("Perform the 3D texture lookup."))); + add_options.push_back(AddOption("Texture3D", "Textures", "Functions", "VisualShaderNodeTexture3D", TTR("Perform the 3D texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D)); add_options.push_back(AddOption("UVPanning", "Textures", "Functions", "VisualShaderNodeUVFunc", TTR("Apply panning function on texture coordinates."), { VisualShaderNodeUVFunc::FUNC_PANNING }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); add_options.push_back(AddOption("UVScaling", "Textures", "Functions", "VisualShaderNodeUVFunc", TTR("Apply scaling function on texture coordinates."), { VisualShaderNodeUVFunc::FUNC_SCALING }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); - add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubemapUniform", TTR("Cubic texture uniform lookup."))); - add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform lookup."))); + add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubemapUniform", TTR("Cubic texture uniform lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER)); + add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER)); add_options.push_back(AddOption("TextureUniformTriplanar", "Textures", "Variables", "VisualShaderNodeTextureUniformTriplanar", TTR("2D texture uniform lookup with triplanar."), {}, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Texture2DArrayUniform", "Textures", "Variables", "VisualShaderNodeTexture2DArrayUniform", TTR("2D array of textures uniform lookup."))); - add_options.push_back(AddOption("Texture3DUniform", "Textures", "Variables", "VisualShaderNodeTexture3DUniform", TTR("3D texture uniform lookup."))); + add_options.push_back(AddOption("Texture2DArrayUniform", "Textures", "Variables", "VisualShaderNodeTexture2DArrayUniform", TTR("2D array of textures uniform lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER)); + add_options.push_back(AddOption("Texture3DUniform", "Textures", "Variables", "VisualShaderNodeTexture3DUniform", TTR("3D texture uniform lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER)); // TRANSFORM @@ -5938,7 +5957,7 @@ public: } } - void setup(Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, const Map<StringName, String> &p_overrided_names, Ref<VisualShaderNode> p_node) { + void setup(Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, const HashMap<StringName, String> &p_overrided_names, Ref<VisualShaderNode> p_node) { parent_resource = p_parent_resource; updating = false; node = p_node; @@ -6252,7 +6271,8 @@ void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, Visua } Size2 VisualShaderNodePortPreview::get_minimum_size() const { - return Size2(100, 100) * EDSCALE; + int port_preview_size = EditorSettings::get_singleton()->get("editors/visual_editors/visualshader/port_preview_size"); + return Size2(port_preview_size, port_preview_size) * EDSCALE; } void VisualShaderNodePortPreview::_notification(int p_what) { diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 540cb709b3..003c8b15a8 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -72,8 +72,8 @@ private: GraphNode *graph_node = nullptr; bool preview_visible = false; int preview_pos = 0; - Map<int, InputPort> input_ports; - Map<int, Port> output_ports; + HashMap<int, InputPort> input_ports; + HashMap<int, Port> output_ports; VBoxContainer *preview_box = nullptr; LineEdit *uniform_name = nullptr; CodeEdit *expression_edit = nullptr; @@ -81,7 +81,7 @@ private: }; Ref<VisualShader> visual_shader; - Map<int, Link> links; + HashMap<int, Link> links; List<VisualShader::Connection> connections; bool dirty = false; @@ -346,7 +346,7 @@ class VisualShaderEditor : public VBoxContainer { void _delete_nodes(int p_type, const List<int> &p_nodes); void _delete_node_request(int p_type, int p_node); - void _delete_nodes_request(); + void _delete_nodes_request(const TypedArray<StringName> &p_nodes); void _node_changed(int p_id); @@ -358,8 +358,8 @@ class VisualShaderEditor : public VBoxContainer { int from_node = -1; int from_slot = -1; - Set<int> selected_constants; - Set<int> selected_uniforms; + RBSet<int> selected_constants; + RBSet<int> selected_uniforms; int selected_comment = -1; int selected_float_constant = -1; @@ -468,7 +468,7 @@ class VisualShaderEditor : public VBoxContainer { bool _is_available(int p_mode); void _update_created_node(GraphNode *node); void _update_uniforms(bool p_update_refs); - void _update_uniform_refs(Set<String> &p_names); + void _update_uniform_refs(RBSet<String> &p_names); void _update_varyings(); void _visibility_changed(); diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp index 0835d0212f..c46a4f5a86 100644 --- a/editor/pot_generator.cpp +++ b/editor/pot_generator.cpp @@ -39,14 +39,14 @@ POTGenerator *POTGenerator::singleton = nullptr; #ifdef DEBUG_POT void POTGenerator::_print_all_translation_strings() { - for (OrderedHashMap<String, Vector<POTGenerator::MsgidData>>::Element E = all_translation_strings.front(); E; E = E.next()) { + for (HashMap<String, Vector<POTGenerator::MsgidData>>::Element E = all_translation_strings.front(); E; E = E.next()) { Vector<MsgidData> v_md = all_translation_strings[E.key()]; for (int i = 0; i < v_md.size(); i++) { print_line("++++++"); print_line("msgid: " + E.key()); print_line("context: " + v_md[i].ctx); print_line("msgid_plural: " + v_md[i].plural); - for (Set<String>::Element *F = v_md[i].locations.front(); F; F = F->next()) { + for (RBSet<String>::Element *F = v_md[i].locations.front(); F; F = F->next()) { print_line("location: " + F->get()); } } @@ -121,19 +121,19 @@ void POTGenerator::_write_to_pot(const String &p_file) { file->store_string(header); - for (OrderedHashMap<String, Vector<MsgidData>>::Element E_pair = all_translation_strings.front(); E_pair; E_pair = E_pair.next()) { - String msgid = E_pair.key(); - Vector<MsgidData> v_msgid_data = E_pair.value(); + for (const KeyValue<String, Vector<MsgidData>> &E_pair : all_translation_strings) { + String msgid = E_pair.key; + const Vector<MsgidData> &v_msgid_data = E_pair.value; for (int i = 0; i < v_msgid_data.size(); i++) { String context = v_msgid_data[i].ctx; String plural = v_msgid_data[i].plural; - const Set<String> &locations = v_msgid_data[i].locations; + const RBSet<String> &locations = v_msgid_data[i].locations; // Put the blank line at the start, to avoid a double at the end when closing the file. file->store_line(""); // Write file locations. - for (Set<String>::Element *E = locations.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = locations.front(); E; E = E->next()) { file->store_line("#: " + E->get().trim_prefix("res://")); } diff --git a/editor/pot_generator.h b/editor/pot_generator.h index e7a5f90cee..b24eadfd95 100644 --- a/editor/pot_generator.h +++ b/editor/pot_generator.h @@ -32,8 +32,8 @@ #define POT_GENERATOR_H #include "core/io/file_access.h" -#include "core/templates/ordered_hash_map.h" -#include "core/templates/set.h" +#include "core/templates/hash_map.h" +#include "core/templates/rb_set.h" //#define DEBUG_POT @@ -43,10 +43,10 @@ class POTGenerator { struct MsgidData { String ctx; String plural; - Set<String> locations; + RBSet<String> locations; }; // Store msgid as key and the additional data around the msgid - if it's under a context, has plurals and its file locations. - OrderedHashMap<String, Vector<MsgidData>> all_translation_strings; + HashMap<String, Vector<MsgidData>> all_translation_strings; void _write_to_pot(const String &p_file); void _write_msgid(Ref<FileAccess> r_file, const String &p_id, bool p_plural); diff --git a/editor/progress_dialog.h b/editor/progress_dialog.h index 23a77ea201..a29696cc0d 100644 --- a/editor/progress_dialog.h +++ b/editor/progress_dialog.h @@ -47,8 +47,8 @@ class BackgroundProgress : public HBoxContainer { ProgressBar *progress = nullptr; }; - Map<String, Task> tasks; - Map<String, int> updates; + HashMap<String, Task> tasks; + HashMap<String, int> updates; void _update(); protected: @@ -77,7 +77,7 @@ class ProgressDialog : public PopupPanel { HBoxContainer *cancel_hb = nullptr; Button *cancel = nullptr; - Map<String, Task> tasks; + HashMap<String, Task> tasks; VBoxContainer *main = nullptr; uint64_t last_progress_tick; diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 1344afbd3a..839378dad2 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -346,7 +346,7 @@ void ProjectExportDialog::_update_feature_list() { Ref<EditorExportPreset> current = get_current_preset(); ERR_FAIL_COND(current.is_null()); - Set<String> fset; + RBSet<String> fset; List<String> features; current->get_platform()->get_platform_features(&features); @@ -366,7 +366,7 @@ void ProjectExportDialog::_update_feature_list() { } custom_feature_display->clear(); - for (Set<String>::Element *E = fset.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = fset.front(); E; E = E->next()) { String f = E->get(); if (E->next()) { f += ", "; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 9c745e6a41..d74cfe4ec0 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -186,7 +186,8 @@ private: if (mode == MODE_IMPORT || mode == MODE_RENAME) { if (!valid_path.is_empty() && !d->file_exists("project.godot")) { if (valid_path.ends_with(".zip")) { - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); unzFile pkg = unzOpen2(valid_path.utf8().get_data(), &io); if (!pkg) { @@ -499,7 +500,8 @@ private: zip_path = project_path->get_text(); } - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); unzFile pkg = unzOpen2(zip_path.utf8().get_data(), &io); if (!pkg) { @@ -1062,7 +1064,7 @@ public: void select_first_visible_project(); void erase_selected_projects(bool p_delete_project_contents); Vector<Item> get_selected_projects() const; - const Set<String> &get_selected_project_keys() const; + const RBSet<String> &get_selected_project_keys() const; void ensure_project_visible(int p_index); int get_single_selected_index() const; bool is_any_project_missing() const; @@ -1088,7 +1090,7 @@ private: String _search_term; FilterOption _order_option; - Set<String> _selected_project_keys; + RBSet<String> _selected_project_keys; String _last_clicked; // Project key VBoxContainer *_scroll_children; int _icon_load_index; @@ -1256,7 +1258,7 @@ void ProjectList::load_projects() { List<PropertyInfo> properties; EditorSettings::get_singleton()->get_property_list(&properties); - Set<String> favorites; + RBSet<String> favorites; // Find favourites... for (const PropertyInfo &E : properties) { String property_key = E.name; @@ -1401,7 +1403,7 @@ void ProjectList::create_project_item_control(int p_index) { title->set_clip_text(true); title_hb->add_child(title); - String unsupported_features_str = Variant(item.unsupported_features).operator String().trim_prefix("[").trim_suffix("]"); + String unsupported_features_str = String(", ").join(item.unsupported_features); int length = unsupported_features_str.length(); if (length > 0) { Label *unsupported_label = memnew(Label(unsupported_features_str)); @@ -1502,7 +1504,7 @@ void ProjectList::sort_projects() { update_dock_menu(); } -const Set<String> &ProjectList::get_selected_project_keys() const { +const RBSet<String> &ProjectList::get_selected_project_keys() const { // Faster if that's all you need return _selected_project_keys; } @@ -2095,9 +2097,9 @@ void ProjectManager::_open_selected_projects() { // This is especially important for the HTML5 project manager. loading_label->set_modulate(Color(1, 1, 1)); - const Set<String> &selected_list = _project_list->get_selected_project_keys(); + const RBSet<String> &selected_list = _project_list->get_selected_project_keys(); - for (const Set<String>::Element *E = selected_list.front(); E; E = E->next()) { + for (const RBSet<String>::Element *E = selected_list.front(); E; E = E->next()) { const String &selected = E->get(); String path = EditorSettings::get_singleton()->get("projects/" + selected); String conf = path.plus_file("project.godot"); @@ -2144,7 +2146,7 @@ void ProjectManager::_open_selected_projects() { } void ProjectManager::_open_selected_projects_ask() { - const Set<String> &selected_list = _project_list->get_selected_project_keys(); + const RBSet<String> &selected_list = _project_list->get_selected_project_keys(); if (selected_list.size() < 1) { return; @@ -2207,7 +2209,7 @@ void ProjectManager::_open_selected_projects_ask() { } } if (!unsupported_features.is_empty()) { - String unsupported_features_str = Variant(unsupported_features).operator String().trim_prefix("[").trim_suffix("]"); + String unsupported_features_str = String(", ").join(unsupported_features); warning_message += vformat(TTR("Warning: This project uses the following features not supported by this build of Godot:\n\n%s\n\n"), unsupported_features_str); } warning_message += TTR("Open anyway? Project will be modified."); @@ -2259,7 +2261,7 @@ void ProjectManager::_run_project_confirm() { } void ProjectManager::_run_project() { - const Set<String> &selected_list = _project_list->get_selected_project_keys(); + const RBSet<String> &selected_list = _project_list->get_selected_project_keys(); if (selected_list.size() < 1) { return; @@ -2319,13 +2321,13 @@ void ProjectManager::_import_project() { } void ProjectManager::_rename_project() { - const Set<String> &selected_list = _project_list->get_selected_project_keys(); + const RBSet<String> &selected_list = _project_list->get_selected_project_keys(); if (selected_list.size() == 0) { return; } - for (Set<String>::Element *E = selected_list.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = selected_list.front(); E; E = E->next()) { const String &selected = E->get(); String path = EditorSettings::get_singleton()->get("projects/" + selected); npdialog->set_project_path(path); @@ -2345,7 +2347,7 @@ void ProjectManager::_erase_missing_projects_confirm() { } void ProjectManager::_erase_project() { - const Set<String> &selected_list = _project_list->get_selected_project_keys(); + const RBSet<String> &selected_list = _project_list->get_selected_project_keys(); if (selected_list.size() == 0) { return; @@ -2402,7 +2404,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files) { _install_project(p_files[0], file.substr(0, file.length() - 4).capitalize()); return; } - Set<String> folders_set; + RBSet<String> folders_set; Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); for (int i = 0; i < p_files.size(); i++) { String file = p_files[i]; @@ -2410,7 +2412,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files) { } if (folders_set.size() > 0) { PackedStringArray folders; - for (Set<String>::Element *E = folders_set.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = folders_set.front(); E; E = E->next()) { folders.push_back(E->get()); } diff --git a/editor/project_manager.h b/editor/project_manager.h index a68cc4350c..93a6e1c405 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -50,7 +50,7 @@ enum FilterOption { class ProjectManager : public Control { GDCLASS(ProjectManager, Control); - Map<String, Ref<Texture2D>> icon_type_cache; + HashMap<String, Ref<Texture2D>> icon_type_cache; void _build_icon_type_cache(Ref<Theme> p_theme); static ProjectManager *singleton; diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index f684c0e0c9..bd0affbcc3 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -249,7 +249,7 @@ String ProjectSettingsEditor::_get_setting_name() const { } void ProjectSettingsEditor::_add_feature_overrides() { - Set<String> presets; + RBSet<String> presets; presets.insert("bptc"); presets.insert("s3tc"); @@ -292,7 +292,7 @@ void ProjectSettingsEditor::_add_feature_overrides() { feature_box->clear(); feature_box->add_item(TTR("(All)"), 0); // So it is always on top. int id = 1; - for (Set<String>::Element *E = presets.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = presets.front(); E; E = E->next()) { feature_box->add_item(E->get(), id++); } } @@ -420,7 +420,7 @@ void ProjectSettingsEditor::_action_reordered(const String &p_action_name, const Variant target_value = ps->get(target_name); List<PropertyInfo> props; - OrderedHashMap<String, Variant> action_values; + HashMap<String, Variant> action_values; ProjectSettings::get_singleton()->get_property_list(&props); undo_redo->create_action(TTR("Update Input Action Order")); @@ -437,9 +437,9 @@ void ProjectSettingsEditor::_action_reordered(const String &p_action_name, const undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", prop.name); } - for (OrderedHashMap<String, Variant>::Element E = action_values.front(); E; E = E.next()) { - String name = E.key(); - Variant value = E.get(); + for (const KeyValue<String, Variant> &E : action_values) { + String name = E.key; + const Variant &value = E.value; if (name == target_name) { if (p_before) { diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 5effdf0b36..71cdcc2580 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -137,13 +137,13 @@ void CustomPropertyEditor::_menu_option(int p_which) { ResourceLoader::get_recognized_extensions_for_type(type.get_slice(",", i), &extensions); } - Set<String> valid_extensions; + RBSet<String> valid_extensions; for (const String &E : extensions) { valid_extensions.insert(E); } file->clear_filters(); - for (Set<String>::Element *E = valid_extensions.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = valid_extensions.front(); E; E = E->next()) { file->add_filter("*." + E->get() + " ; " + E->get().to_upper()); } @@ -875,7 +875,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: for (int i = 0; i < hint_text.get_slice_count(","); i++) { String base = hint_text.get_slice(",", i); - Set<String> valid_inheritors; + RBSet<String> valid_inheritors; valid_inheritors.insert(base); List<StringName> inheritors; ClassDB::get_inheriters_from_class(base.strip_edges(), &inheritors); @@ -890,7 +890,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: E = E->next(); } - for (Set<String>::Element *j = valid_inheritors.front(); j; j = j->next()) { + for (RBSet<String>::Element *j = valid_inheritors.front(); j; j = j->next()) { const String &t = j->get(); bool is_custom_resource = false; diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index 1ac15a0a9d..c136eae1bc 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -366,11 +366,11 @@ void PropertySelector::_item_selected() { String text; if (properties) { while (!class_type.is_empty()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(class_type); + HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(class_type); if (E) { - for (int i = 0; i < E->get().properties.size(); i++) { - if (E->get().properties[i].name == name) { - text = DTR(E->get().properties[i].description); + for (int i = 0; i < E->value.properties.size(); i++) { + if (E->value.properties[i].name == name) { + text = DTR(E->value.properties[i].description); break; } } @@ -385,11 +385,11 @@ void PropertySelector::_item_selected() { } } else { while (!class_type.is_empty()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(class_type); + HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(class_type); if (E) { - for (int i = 0; i < E->get().methods.size(); i++) { - if (E->get().methods[i].name == name) { - text = DTR(E->get().methods[i].description); + for (int i = 0; i < E->value.methods.size(); i++) { + if (E->value.methods[i].name == name) { + text = DTR(E->value.methods[i].description); break; } } diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index 1d9e799a30..e47250fcf8 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -356,6 +356,8 @@ void RenameDialog::_update_substitute() { } void RenameDialog::_post_popup() { + ConfirmationDialog::_post_popup(); + EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection(); preview_node = nullptr; diff --git a/editor/reparent_dialog.cpp b/editor/reparent_dialog.cpp index 8879085d86..38d909038f 100644 --- a/editor/reparent_dialog.cpp +++ b/editor/reparent_dialog.cpp @@ -57,7 +57,7 @@ void ReparentDialog::_reparent() { } } -void ReparentDialog::set_current(const Set<Node *> &p_selection) { +void ReparentDialog::set_current(const RBSet<Node *> &p_selection) { tree->set_marked(p_selection, false, false); //tree->set_selected(p_node->get_parent()); } diff --git a/editor/reparent_dialog.h b/editor/reparent_dialog.h index 121a86e9f0..a5a9818e7f 100644 --- a/editor/reparent_dialog.h +++ b/editor/reparent_dialog.h @@ -52,7 +52,7 @@ protected: static void _bind_methods(); public: - void set_current(const Set<Node *> &p_selection); + void set_current(const RBSet<Node *> &p_selection); ReparentDialog(); ~ReparentDialog(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index b385460232..afb3ac7c15 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -460,7 +460,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { selection.sort_custom<Node::Comparator>(); for (Node *node : selection) { - Map<const Node *, Node *> duplimap; + HashMap<const Node *, Node *> duplimap; Node *dup = node->duplicate_from_editor(duplimap); ERR_CONTINUE(!dup); @@ -658,7 +658,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { List<Node *> owned; node->get_owned_by(node->get_owner(), &owned); - Map<const Node *, Node *> duplimap; + HashMap<const Node *, Node *> duplimap; Node *dup = node->duplicate_from_editor(duplimap); ERR_CONTINUE(!dup); @@ -717,7 +717,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } List<Node *> nodes = editor_selection->get_selected_node_list(); - Set<Node *> nodeset; + RBSet<Node *> nodeset; for (Node *E : nodes) { nodeset.insert(E); } @@ -1402,7 +1402,7 @@ void SceneTreeDock::_set_owners(Node *p_owner, const Array &p_nodes) { } } -void SceneTreeDock::_fill_path_renames(Vector<StringName> base_path, Vector<StringName> new_base_path, Node *p_node, Map<Node *, NodePath> *p_renames) { +void SceneTreeDock::_fill_path_renames(Vector<StringName> base_path, Vector<StringName> new_base_path, Node *p_node, HashMap<Node *, NodePath> *p_renames) { base_path.push_back(p_node->get_name()); if (new_base_path.size()) { new_base_path.push_back(p_node->get_name()); @@ -1420,7 +1420,7 @@ void SceneTreeDock::_fill_path_renames(Vector<StringName> base_path, Vector<Stri } } -void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, Map<Node *, NodePath> *p_renames) { +void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, HashMap<Node *, NodePath> *p_renames) { Vector<StringName> base_path; Node *n = p_node->get_parent(); while (n) { @@ -1443,24 +1443,24 @@ void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, Map<Node _fill_path_renames(base_path, new_base_path, p_node, p_renames); } -bool SceneTreeDock::_update_node_path(Node *p_root_node, NodePath &r_node_path, Map<Node *, NodePath> *p_renames) const { +bool SceneTreeDock::_update_node_path(Node *p_root_node, NodePath &r_node_path, HashMap<Node *, NodePath> *p_renames) const { Node *target_node = p_root_node->get_node_or_null(r_node_path); ERR_FAIL_NULL_V_MSG(target_node, false, "Found invalid node path '" + String(r_node_path) + "' on node '" + String(scene_root->get_path_to(p_root_node)) + "'"); // Try to find the target node in modified node paths. - Map<Node *, NodePath>::Element *found_node_path = p_renames->find(target_node); + HashMap<Node *, NodePath>::Iterator found_node_path = p_renames->find(target_node); if (found_node_path) { - Map<Node *, NodePath>::Element *found_root_path = p_renames->find(p_root_node); - NodePath root_path_new = found_root_path ? found_root_path->get() : p_root_node->get_path(); - r_node_path = root_path_new.rel_path_to(found_node_path->get()); + HashMap<Node *, NodePath>::Iterator found_root_path = p_renames->find(p_root_node); + NodePath root_path_new = found_root_path ? found_root_path->value : p_root_node->get_path(); + r_node_path = root_path_new.rel_path_to(found_node_path->value); return true; } // Update the path if the base node has changed and has not been deleted. - Map<Node *, NodePath>::Element *found_root_path = p_renames->find(p_root_node); + HashMap<Node *, NodePath>::Iterator found_root_path = p_renames->find(p_root_node); if (found_root_path) { - NodePath root_path_new = found_root_path->get(); + NodePath root_path_new = found_root_path->value; if (!root_path_new.is_empty()) { NodePath old_abs_path = NodePath(String(p_root_node->get_path()).plus_file(r_node_path)); old_abs_path.simplify(); @@ -1473,7 +1473,7 @@ bool SceneTreeDock::_update_node_path(Node *p_root_node, NodePath &r_node_path, return false; } -bool SceneTreeDock::_check_node_path_recursive(Node *p_root_node, Variant &r_variant, Map<Node *, NodePath> *p_renames) const { +bool SceneTreeDock::_check_node_path_recursive(Node *p_root_node, Variant &r_variant, HashMap<Node *, NodePath> *p_renames) const { switch (r_variant.get_type()) { case Variant::NODE_PATH: { NodePath node_path = r_variant; @@ -1528,8 +1528,8 @@ bool SceneTreeDock::_check_node_path_recursive(Node *p_root_node, Variant &r_var return false; } -void SceneTreeDock::perform_node_renames(Node *p_base, Map<Node *, NodePath> *p_renames, Map<Ref<Animation>, Set<int>> *r_rem_anims) { - Map<Ref<Animation>, Set<int>> rem_anims; +void SceneTreeDock::perform_node_renames(Node *p_base, HashMap<Node *, NodePath> *p_renames, HashMap<Ref<Animation>, RBSet<int>> *r_rem_anims) { + HashMap<Ref<Animation>, RBSet<int>> rem_anims; if (!r_rem_anims) { r_rem_anims = &rem_anims; } @@ -1543,8 +1543,8 @@ void SceneTreeDock::perform_node_renames(Node *p_base, Map<Node *, NodePath> *p_ } // No renaming if base node is deleted. - Map<Node *, NodePath>::Element *found_base_path = p_renames->find(p_base); - if (found_base_path && found_base_path->get().is_empty()) { + HashMap<Node *, NodePath>::Iterator found_base_path = p_renames->find(p_base); + if (found_base_path && found_base_path->value.is_empty()) { return; } @@ -1575,20 +1575,20 @@ void SceneTreeDock::perform_node_renames(Node *p_base, Map<Node *, NodePath> *p_ Node *root = ap->get_node(ap->get_root()); if (root) { - Map<Node *, NodePath>::Element *found_root_path = p_renames->find(root); - NodePath new_root_path = found_root_path ? found_root_path->get() : root->get_path(); + HashMap<Node *, NodePath>::Iterator found_root_path = p_renames->find(root); + NodePath new_root_path = found_root_path ? found_root_path->value : root->get_path(); if (!new_root_path.is_empty()) { // No renaming if root node is deleted. for (const StringName &E : anims) { Ref<Animation> anim = ap->get_animation(E); if (!r_rem_anims->has(anim)) { - r_rem_anims->insert(anim, Set<int>()); - Set<int> &ran = r_rem_anims->find(anim)->get(); + r_rem_anims->insert(anim, RBSet<int>()); + RBSet<int> &ran = r_rem_anims->find(anim)->value; for (int i = 0; i < anim->get_track_count(); i++) { ran.insert(i); } } - Set<int> &ran = r_rem_anims->find(anim)->get(); + RBSet<int> &ran = r_rem_anims->find(anim)->value; if (anim.is_null()) { continue; @@ -1605,13 +1605,13 @@ void SceneTreeDock::perform_node_renames(Node *p_base, Map<Node *, NodePath> *p_ continue; //channel was removed } - Map<Node *, NodePath>::Element *found_path = p_renames->find(n); + HashMap<Node *, NodePath>::Iterator found_path = p_renames->find(n); if (found_path) { - if (found_path->get() == NodePath()) { + if (found_path->value == NodePath()) { //will be erased int idx = 0; - Set<int>::Element *EI = ran.front(); + RBSet<int>::Element *EI = ran.front(); ERR_FAIL_COND(!EI); //bug while (EI->get() != i) { idx++; @@ -1631,7 +1631,7 @@ void SceneTreeDock::perform_node_renames(Node *p_base, Map<Node *, NodePath> *p_ } else { //will be renamed - NodePath rel_path = new_root_path.rel_path_to(found_path->get()); + NodePath rel_path = new_root_path.rel_path_to(found_path->value); NodePath new_path = NodePath(rel_path.get_names(), track_np.get_subnames(), false); if (new_path == track_np) { @@ -1653,7 +1653,7 @@ void SceneTreeDock::perform_node_renames(Node *p_base, Map<Node *, NodePath> *p_ } void SceneTreeDock::_node_prerenamed(Node *p_node, const String &p_new_name) { - Map<Node *, NodePath> path_renames; + HashMap<Node *, NodePath> path_renames; Vector<StringName> base_path; Node *n = p_node->get_parent(); @@ -1774,7 +1774,7 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V editor_data->get_undo_redo().create_action(TTR("Reparent Node")); - Map<Node *, NodePath> path_renames; + HashMap<Node *, NodePath> path_renames; Vector<StringName> former_names; int inc = 0; @@ -1811,9 +1811,9 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V // Name was modified, fix the path renames. if (old_name.casecmp_to(new_name) != 0) { // Fix the to name to have the new name. - Map<Node *, NodePath>::Element *found_path = path_renames.find(node); + HashMap<Node *, NodePath>::Iterator found_path = path_renames.find(node); if (found_path) { - NodePath old_new_name = found_path->get(); + NodePath old_new_name = found_path->value; Vector<StringName> unfixed_new_names = old_new_name.get_names(); Vector<StringName> fixed_new_names; @@ -2058,7 +2058,7 @@ void SceneTreeDock::_delete_confirm(bool p_cut) { } else { remove_list.sort_custom<Node::Comparator>(); //sort nodes to keep positions - Map<Node *, NodePath> path_renames; + HashMap<Node *, NodePath> path_renames; //delete from animation for (Node *n : remove_list) { @@ -2148,7 +2148,7 @@ void SceneTreeDock::_selection_changed() { //automatically turn on multi-edit _tool_selected(TOOL_MULTI_EDIT); } else if (selection_size == 1) { - _push_item(editor_selection->get_selection().front()->key()); + _push_item(editor_selection->get_selection().begin()->key); } else if (selection_size == 0) { _push_item(nullptr); } @@ -2407,7 +2407,7 @@ void SceneTreeDock::_new_scene_from(String p_file) { Node *base = selection.front()->get(); - Map<const Node *, Node *> duplimap; + HashMap<const Node *, Node *> duplimap; Node *copy = base->duplicate_from_editor(duplimap); if (copy) { @@ -3038,14 +3038,14 @@ List<Node *> SceneTreeDock::paste_nodes() { ur.create_action(TTR("Paste Node(s)")); ur.add_do_method(editor_selection, "clear"); - Map<Ref<Resource>, Ref<Resource>> resource_remap; + HashMap<Ref<Resource>, Ref<Resource>> resource_remap; String target_scene; if (edited_scene) { target_scene = edited_scene->get_scene_file_path(); } if (target_scene != clipboard_source_scene) { if (!clipboard_resource_remap.has(target_scene)) { - Map<Ref<Resource>, Ref<Resource>> remap; + HashMap<Ref<Resource>, Ref<Resource>> remap; for (Node *E : node_clipboard) { _create_remap_for_node(E, remap); } @@ -3055,7 +3055,7 @@ List<Node *> SceneTreeDock::paste_nodes() { } for (Node *node : node_clipboard) { - Map<const Node *, Node *> duplimap; + HashMap<const Node *, Node *> duplimap; Node *dup = node->duplicate_from_editor(duplimap, resource_remap); ERR_CONTINUE(!dup); @@ -3241,7 +3241,7 @@ void SceneTreeDock::_clear_clipboard() { clipboard_resource_remap.clear(); } -void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<Ref<Resource>, Ref<Resource>> &r_remap) { +void SceneTreeDock::_create_remap_for_node(Node *p_node, HashMap<Ref<Resource>, Ref<Resource>> &r_remap) { List<PropertyInfo> props; p_node->get_property_list(&props); @@ -3280,7 +3280,7 @@ void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<Ref<Resource>, Ref< } } -void SceneTreeDock::_create_remap_for_resource(Ref<Resource> p_resource, Map<Ref<Resource>, Ref<Resource>> &r_remap) { +void SceneTreeDock::_create_remap_for_resource(Ref<Resource> p_resource, HashMap<Ref<Resource>, Ref<Resource>> &r_remap) { r_remap[p_resource] = p_resource->duplicate(); List<PropertyInfo> props; diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index a1d300d3d6..1e58a7a66a 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -145,7 +145,7 @@ class SceneTreeDock : public VBoxContainer { List<Node *> node_clipboard; String clipboard_source_scene; - HashMap<String, Map<Ref<Resource>, Ref<Resource>>> clipboard_resource_remap; + HashMap<String, HashMap<Ref<Resource>, Ref<Resource>>> clipboard_resource_remap; ScriptCreateDialog *script_create_dialog = nullptr; ShaderCreateDialog *shader_create_dialog = nullptr; @@ -232,7 +232,7 @@ class SceneTreeDock : public VBoxContainer { void _selection_changed(); void _update_script_button(); - void _fill_path_renames(Vector<StringName> base_path, Vector<StringName> new_base_path, Node *p_node, Map<Node *, NodePath> *p_renames); + void _fill_path_renames(Vector<StringName> base_path, Vector<StringName> new_base_path, Node *p_node, HashMap<Node *, NodePath> *p_renames); void _normalize_drop(Node *&to_node, int &to_pos, int p_type); @@ -258,16 +258,16 @@ class SceneTreeDock : public VBoxContainer { void _feature_profile_changed(); void _clear_clipboard(); - void _create_remap_for_node(Node *p_node, Map<Ref<Resource>, Ref<Resource>> &r_remap); - void _create_remap_for_resource(Ref<Resource> p_resource, Map<Ref<Resource>, Ref<Resource>> &r_remap); + void _create_remap_for_node(Node *p_node, HashMap<Ref<Resource>, Ref<Resource>> &r_remap); + void _create_remap_for_resource(Ref<Resource> p_resource, HashMap<Ref<Resource>, Ref<Resource>> &r_remap); bool profile_allow_editing = true; bool profile_allow_script_editing = true; static void _update_configuration_warning(); - bool _update_node_path(Node *p_root_node, NodePath &r_node_path, Map<Node *, NodePath> *p_renames) const; - bool _check_node_path_recursive(Node *p_root_node, Variant &r_variant, Map<Node *, NodePath> *p_renames) const; + bool _update_node_path(Node *p_root_node, NodePath &r_node_path, HashMap<Node *, NodePath> *p_renames) const; + bool _check_node_path_recursive(Node *p_root_node, Variant &r_variant, HashMap<Node *, NodePath> *p_renames) const; private: static SceneTreeDock *singleton; @@ -292,8 +292,8 @@ public: void instantiate(const String &p_file); void instantiate_scenes(const Vector<String> &p_files, Node *p_parent = nullptr); void set_selected(Node *p_node, bool p_emit_selected = false); - void fill_path_renames(Node *p_node, Node *p_new_parent, Map<Node *, NodePath> *p_renames); - void perform_node_renames(Node *p_base, Map<Node *, NodePath> *p_renames, Map<Ref<Animation>, Set<int>> *r_rem_anims = nullptr); + void fill_path_renames(Node *p_node, Node *p_new_parent, HashMap<Node *, NodePath> *p_renames); + void perform_node_renames(Node *p_base, HashMap<Node *, NodePath> *p_renames, HashMap<Ref<Animation>, RBSet<int>> *r_rem_anims = nullptr); SceneTreeEditor *get_tree_editor() { return scene_tree; } EditorData *get_editor_data() { return editor_data; } @@ -317,7 +317,9 @@ public: List<Node *> paste_nodes(); List<Node *> get_node_clipboard() const; - ScriptCreateDialog *get_script_create_dialog() { return script_create_dialog; } + ScriptCreateDialog *get_script_create_dialog() { + return script_create_dialog; + } SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data); ~SceneTreeDock(); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index b588c01bce..afb42efa76 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -279,15 +279,26 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll Array arr; arr.push_back(num_connections); msg_temp += TTRN("Node has one connection.", "Node has {num} connections.", num_connections).format(arr, "{num}"); - msg_temp += " "; + if (num_groups >= 1) { + msg_temp += "\n"; + } } if (num_groups >= 1) { - Array arr; - arr.push_back(num_groups); - msg_temp += TTRN("Node is in one group.", "Node is in {num} groups.", num_groups).format(arr, "{num}"); + msg_temp += TTRN("Node is in this group:", "Node is in the following groups:", num_groups) + "\n"; + + List<GroupInfo> groups; + p_node->get_groups(&groups); + for (const GroupInfo &E : groups) { + if (E.persistent) { + msg_temp += String::utf8("• ") + String(E.name) + "\n"; + } + } } if (num_connections >= 1 || num_groups >= 1) { - msg_temp += "\n" + TTR("Click to show signals dock."); + if (num_groups < 1) { + msg_temp += "\n"; + } + msg_temp += TTR("Click to show signals dock."); } Ref<Texture2D> icon_temp; @@ -863,7 +874,7 @@ Node *SceneTreeEditor::get_selected() { return selected; } -void SceneTreeEditor::set_marked(const Set<Node *> &p_marked, bool p_selectable, bool p_children_selectable) { +void SceneTreeEditor::set_marked(const RBSet<Node *> &p_marked, bool p_selectable, bool p_children_selectable) { if (tree_dirty) { _update_tree(); } @@ -874,7 +885,7 @@ void SceneTreeEditor::set_marked(const Set<Node *> &p_marked, bool p_selectable, } void SceneTreeEditor::set_marked(Node *p_marked, bool p_selectable, bool p_children_selectable) { - Set<Node *> s; + RBSet<Node *> s; if (p_marked) { s.insert(p_marked); } diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index 3d88081ab1..604d77cf76 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -99,7 +99,7 @@ class SceneTreeEditor : public Control { void _renamed(); UndoRedo *undo_redo = nullptr; - Set<Node *> marked; + RBSet<Node *> marked; bool marked_selectable = false; bool marked_children_selectable = false; bool display_foreign = false; @@ -140,7 +140,7 @@ public: void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; }; void set_display_foreign_nodes(bool p_display); - void set_marked(const Set<Node *> &p_marked, bool p_selectable = false, bool p_children_selectable = true); + void set_marked(const RBSet<Node *> &p_marked, bool p_selectable = false, bool p_children_selectable = true); void set_marked(Node *p_marked, bool p_selectable = false, bool p_children_selectable = true); void set_selected(Node *p_node, bool p_emit_selected = true); Node *get_selected(); diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp index 3a2c4fb17b..046e8fcdfc 100644 --- a/editor/shader_create_dialog.cpp +++ b/editor/shader_create_dialog.cpp @@ -382,7 +382,7 @@ String ShaderCreateDialog::_validate_path(const String &p_path) { } String extension = p.get_extension(); - Set<String> extensions; + RBSet<String> extensions; for (int i = 0; i < SHADER_TYPE_MAX; i++) { for (const String &ext : language_data[i].extensions) { diff --git a/main/main.cpp b/main/main.cpp index 75c4433b41..191f4d684f 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -342,9 +342,9 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n"); OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n"); OS::get_singleton()->print(" --gpu-profile Show a GPU profile of the tasks that took the most time during frame rendering.\n"); - OS::get_singleton()->print(" --vk-layers Enable Vulkan validation layers for debugging.\n"); + OS::get_singleton()->print(" --gpu-validation Enable graphics API validation layers for debugging.\n"); #if DEBUG_ENABLED - OS::get_singleton()->print(" --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes.\n"); + OS::get_singleton()->print(" --gpu-abort Abort on graphics API usage errors (usually validation layer errors). May help see the problem if your system freezes.\n"); #endif OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n"); #if defined(DEBUG_ENABLED) @@ -641,6 +641,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph bool found_project = false; #endif + String default_renderer = ""; + String renderer_hints = ""; + packed_data = PackedData::get_singleton(); if (!packed_data) { packed_data = memnew(PackedData); @@ -828,7 +831,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->print("Missing GPU index argument, aborting.\n"); goto error; } - } else if (I->get() == "--vk-layers") { + } else if (I->get() == "--gpu-validation") { Engine::singleton->use_validation_layers = true; #ifdef DEBUG_ENABLED } else if (I->get() == "--gpu-abort") { @@ -1306,14 +1309,33 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph // possibly be worth changing the default from vulkan to something lower spec, // for the project manager, depending on how smooth the fallback is. - GLOBAL_DEF_RST("rendering/driver/driver_name", "vulkan"); // this list is hard coded, which makes it more difficult to add new backends. // can potentially be changed to more of a plugin system at a later date. + + // Start with Vulkan, which will be the default if enabled. +#ifdef VULKAN_ENABLED + renderer_hints = "vulkan"; +#endif + + // And OpenGL3 next, or first if Vulkan is disabled. +#ifdef GLES3_ENABLED + if (!renderer_hints.is_empty()) { + renderer_hints += ","; + } + renderer_hints += "opengl3"; +#endif + if (renderer_hints.is_empty()) { + ERR_PRINT("No rendering driver available."); + } + + default_renderer = renderer_hints.get_slice(",", 0); + GLOBAL_DEF_RST("rendering/driver/driver_name", default_renderer); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/driver/driver_name", PropertyInfo(Variant::STRING, "rendering/driver/driver_name", - PROPERTY_HINT_ENUM, "vulkan,opengl3")); + PROPERTY_HINT_ENUM, renderer_hints)); // if not set on the command line if (rendering_driver.is_empty()) { @@ -1328,35 +1350,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph // always convert to lower case for consistency in the code rendering_driver = rendering_driver.to_lower(); - GLOBAL_DEF_BASIC("display/window/size/viewport_width", 1024); - ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/viewport_width", - PropertyInfo(Variant::INT, "display/window/size/viewport_width", - PROPERTY_HINT_RANGE, - "0,7680,1,or_greater")); // 8K resolution - - GLOBAL_DEF_BASIC("display/window/size/viewport_height", 600); - ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/viewport_height", - PropertyInfo(Variant::INT, "display/window/size/viewport_height", - PROPERTY_HINT_RANGE, - "0,4320,1,or_greater")); // 8K resolution - - GLOBAL_DEF_BASIC("display/window/size/resizable", true); - GLOBAL_DEF_BASIC("display/window/size/borderless", false); - GLOBAL_DEF_BASIC("display/window/size/fullscreen", false); - GLOBAL_DEF("display/window/size/always_on_top", false); - GLOBAL_DEF("display/window/size/window_width_override", 0); - ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/window_width_override", - PropertyInfo(Variant::INT, - "display/window/size/window_width_override", - PROPERTY_HINT_RANGE, - "0,7680,1,or_greater")); // 8K resolution - GLOBAL_DEF("display/window/size/window_height_override", 0); - ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/window_height_override", - PropertyInfo(Variant::INT, - "display/window/size/window_height_override", - PROPERTY_HINT_RANGE, - "0,4320,1,or_greater")); // 8K resolution - if (use_custom_res) { if (!force_res) { window_size.width = GLOBAL_GET("display/window/size/viewport_width"); @@ -1513,7 +1506,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph ProjectSettings::get_singleton()->set_custom_property_info("xr/openxr/default_action_map", PropertyInfo(Variant::STRING, "xr/openxr/default_action_map", PROPERTY_HINT_FILE, "*.tres")); GLOBAL_DEF_BASIC("xr/openxr/form_factor", "0"); - ProjectSettings::get_singleton()->set_custom_property_info("xr/openxr/form_factor", PropertyInfo(Variant::INT, "xr/openxr/form_factor", PROPERTY_HINT_ENUM, "Head mounted,Handheld")); + ProjectSettings::get_singleton()->set_custom_property_info("xr/openxr/form_factor", PropertyInfo(Variant::INT, "xr/openxr/form_factor", PROPERTY_HINT_ENUM, "Head Mounted,Handheld")); GLOBAL_DEF_BASIC("xr/openxr/view_configuration", "1"); ProjectSettings::get_singleton()->set_custom_property_info("xr/openxr/view_configuration", PropertyInfo(Variant::INT, "xr/openxr/view_configuration", PROPERTY_HINT_ENUM, "Mono,Stereo")); // "Mono,Stereo,Quad,Observer" @@ -2156,8 +2149,8 @@ bool Main::start() { doc.generate(doc_base); DocTools docsrc; - Map<String, String> doc_data_classes; - Set<String> checked_paths; + HashMap<String, String> doc_data_classes; + RBSet<String> checked_paths; print_line("Loading docs..."); for (int i = 0; i < _doc_data_class_path_count; i++) { @@ -2196,7 +2189,7 @@ bool Main::start() { print_line("Merging docs..."); doc.merge_from(docsrc); - for (Set<String>::Element *E = checked_paths.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = checked_paths.front(); E; E = E->next()) { print_line("Erasing old docs at: " + E->get()); err = DocTools::erase_classes(E->get()); ERR_FAIL_COND_V_MSG(err != OK, false, "Error erasing old docs at: " + E->get() + ": " + itos(err)); @@ -2329,11 +2322,11 @@ bool Main::start() { if (!project_manager && !editor) { // game if (!game_path.is_empty() || !script.is_empty()) { //autoload - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); //first pass, add the constants so they exist before any script is loaded - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - const ProjectSettings::AutoloadInfo &info = E.get(); + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) { + const ProjectSettings::AutoloadInfo &info = E.value; if (info.is_singleton) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { @@ -2344,8 +2337,8 @@ bool Main::start() { //second pass, load into global constants List<Node *> to_add; - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - const ProjectSettings::AutoloadInfo &info = E.get(); + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) { + const ProjectSettings::AutoloadInfo &info = E.value; Ref<Resource> res = ResourceLoader::load(info.path); ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + info.path); @@ -2641,6 +2634,7 @@ bool Main::start() { uint64_t Main::last_ticks = 0; uint32_t Main::frames = 0; +uint32_t Main::hide_print_fps_attempts = 3; uint32_t Main::frame = 0; bool Main::force_redraw_requested = false; int Main::iterating = 0; @@ -2781,12 +2775,17 @@ bool Main::iteration() { Engine::get_singleton()->_process_frames++; if (frame > 1000000) { - if (editor || project_manager) { - if (print_fps) { - print_line(vformat("Editor FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(2))); + // Wait a few seconds before printing FPS, as FPS reporting just after the engine has started is inaccurate. + if (hide_print_fps_attempts == 0) { + if (editor || project_manager) { + if (print_fps) { + print_line(vformat("Editor FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(2))); + } + } else if (print_fps || GLOBAL_GET("debug/settings/stdout/print_fps")) { + print_line(vformat("Project FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(2))); } - } else if (GLOBAL_GET("debug/settings/stdout/print_fps") || print_fps) { - print_line(vformat("Project FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(2))); + } else { + hide_print_fps_attempts--; } Engine::get_singleton()->_fps = frames; diff --git a/main/main.h b/main/main.h index 14a8fb4147..d1870ab8df 100644 --- a/main/main.h +++ b/main/main.h @@ -38,6 +38,7 @@ class Main { static void print_help(const char *p_binary); static uint64_t last_ticks; + static uint32_t hide_print_fps_attempts; static uint32_t frames; static uint32_t frame; static bool force_redraw_requested; diff --git a/main/performance.cpp b/main/performance.cpp index e80906b4a7..25659b999f 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -247,8 +247,8 @@ Array Performance::get_custom_monitor_names() { Array return_array; return_array.resize(_monitor_map.size()); int index = 0; - for (OrderedHashMap<StringName, MonitorCall>::Element i = _monitor_map.front(); i; i = i.next()) { - return_array.set(index, i.key()); + for (KeyValue<StringName, MonitorCall> i : _monitor_map) { + return_array.set(index, i.key); index++; } return return_array; diff --git a/main/performance.h b/main/performance.h index 927b5b0389..2837d8f512 100644 --- a/main/performance.h +++ b/main/performance.h @@ -32,7 +32,7 @@ #define PERFORMANCE_H #include "core/object/class_db.h" -#include "core/templates/ordered_hash_map.h" +#include "core/templates/hash_map.h" #define PERF_WARN_OFFLINE_FUNCTION #define PERF_WARN_PROCESS_SYNC @@ -58,7 +58,7 @@ class Performance : public Object { Variant call(bool &r_error, String &r_error_message); }; - OrderedHashMap<StringName, MonitorCall> _monitor_map; + HashMap<StringName, MonitorCall> _monitor_map; uint64_t _monitor_modification_time; public: diff --git a/misc/dist/html/editor.html b/misc/dist/html/editor.html index 8d436038c1..7c44dd45a1 100644 --- a/misc/dist/html/editor.html +++ b/misc/dist/html/editor.html @@ -68,6 +68,11 @@ height: 100%; overflow: auto; background-color: hsla(0, 0%, 0%, 0.5); + text-align: left; + } + + .welcome-modal-title { + text-align: center; } .welcome-modal-content { @@ -238,7 +243,7 @@ onclick="if (event.target === this) closeWelcomeModal(false)" > <div class="welcome-modal-content"> - <h2 id="welcome-modal-title">Important - Please read before continuing</h2> + <h2 id="welcome-modal-title" class="welcome-modal-title">Important - Please read before continuing</h2> <div id="welcome-modal-description"> <p> The Godot Web Editor has some limitations compared to the native version. @@ -254,9 +259,38 @@ >Web editor documentation</a> for usage instructions and limitations. </p> </div> - <button id="welcome-modal-dismiss" class="btn" type="button" onclick="closeWelcomeModal(true)" style="margin-top: 1rem"> - OK, don't show again - </button> + <div id="welcome-modal-description-no-cross-origin-isolation" style="display: none"> + <p> + The web server does not support cross-origin isolation, + which is required for the Godot Web Editor to function. + </p> + <p> + <strong>Reasons for cross-origin isolation being disabled:</strong> + <ul> + <li id="welcome-modal-reason-not-secure"> + This page is not served from a secure context (HTTPS <i>or</i> localhost). + </li> + <li> + This page may not be served with cross-origin isolation headers + (check with the developer tools' Network tab). + </li> + </ul> + </p> + <p> + If you are self-hosting the web editor, + refer to + <a + href="https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_web.html#threads" + target="_blank" + rel="noopener" + >Exporting for the Web - Threads</a> for more information. + </p> + </div> + <div style="text-align: center"> + <button id="welcome-modal-dismiss" class="btn" type="button" onclick="closeWelcomeModal(true)" style="margin-top: 1rem"> + OK, don't show again + </button> + </div> </div> </div> <div id="tabs-buttons"> @@ -360,7 +394,16 @@ }); } - if (localStorage.getItem("welcomeModalDismissed") !== 'true') { + if (!crossOriginIsolated) { + // Display error dialog as threading support is required for the editor. + setButtonEnabled('startButton', false); + document.getElementById("welcome-modal-description").style.display = "none"; + document.getElementById("welcome-modal-description-no-cross-origin-isolation").style.display = "block"; + document.getElementById("welcome-modal-dismiss").style.display = "none"; + document.getElementById("welcome-modal-reason-not-secure").style.display = window.isSecureContext ? "none" : "list-item"; + } + + if (!crossOriginIsolated || localStorage.getItem("welcomeModalDismissed") !== 'true') { document.getElementById("welcome-modal").style.display = "block"; document.getElementById("welcome-modal-dismiss").focus(); } diff --git a/misc/dist/shell/_godot.zsh-completion b/misc/dist/shell/_godot.zsh-completion index aaa5fe0a06..6444ca337e 100644 --- a/misc/dist/shell/_godot.zsh-completion +++ b/misc/dist/shell/_godot.zsh-completion @@ -61,8 +61,8 @@ _arguments \ '(-b --breakpoints)'{-b,--breakpoints}'[specify the breakpoint list as source::line comma-separated pairs, no spaces (use %20 instead)]:breakpoint list' \ '--profiling[enable profiling in the script debugger]' \ '--gpu-profile[show a GPU profile of the tasks that took the most time during frame rendering]' \ - '--vk-layers[enable Vulkan validation layers for debugging]' \ - '--gpu-abort[abort on GPU errors (usually validation layer errors)]' \ + '--gpu-validation[enable graphics API validation layers for debugging]' \ + '--gpu-abort[abort on graphics API usage errors (usually validation layer errors)]' \ '--remote-debug[enable remote debugging]:remote debugger address' \ '--debug-collisions[show collision shapes when running the scene]' \ '--debug-navigation[show navigation polygons when running the scene]' \ diff --git a/misc/dist/shell/godot.bash-completion b/misc/dist/shell/godot.bash-completion index 7927d26171..31e067e29a 100644 --- a/misc/dist/shell/godot.bash-completion +++ b/misc/dist/shell/godot.bash-completion @@ -64,7 +64,7 @@ _complete_godot_options() { --breakpoints --profiling --gpu-profile ---vk-layers +--gpu-validation --gpu-abort --remote-debug --debug-collisions diff --git a/misc/dist/shell/godot.fish b/misc/dist/shell/godot.fish index c05aa74017..da4ce1190c 100644 --- a/misc/dist/shell/godot.fish +++ b/misc/dist/shell/godot.fish @@ -74,8 +74,8 @@ complete -c godot -s d -l debug -d "Debug (local stdout debugger)" complete -c godot -s b -l breakpoints -d "Specify the breakpoint list as source::line comma-separated pairs, no spaces (use %20 instead)" -x complete -c godot -l profiling -d "Enable profiling in the script debugger" complete -c godot -l gpu-profile -d "Show a GPU profile of the tasks that took the most time during frame rendering" -complete -c godot -l vk-layers -d "Enable Vulkan validation layers for debugging" -complete -c godot -l gpu-abort -d "Abort on GPU errors (usually validation layer errors)" +complete -c godot -l gpu-validation -d "Enable graphics API validation layers for debugging" +complete -c godot -l gpu-abort -d "Abort on graphics API usage errors (usually validation layer errors)" complete -c godot -l remote-debug -d "Enable remote debugging" complete -c godot -l debug-collisions -d "Show collision shapes when running the scene" complete -c godot -l debug-navigation -d "Show navigation polygons when running the scene" diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index e0cc0f8234..93533e1690 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -211,7 +211,7 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector< int ic = p_flip_faces.size(); const bool *ri = p_flip_faces.ptr(); - Map<Ref<Material>, int> material_map; + HashMap<Ref<Material>, int> material_map; faces.resize(p_vertices.size() / 3); @@ -242,10 +242,10 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector< if (mc == vc / 3) { Ref<Material> mat = rm[i]; if (mat.is_valid()) { - const Map<Ref<Material>, int>::Element *E = material_map.find(mat); + HashMap<Ref<Material>, int>::ConstIterator E = material_map.find(mat); if (E) { - f.material = E->get(); + f.material = E->value; } else { f.material = material_map.size(); material_map[mat] = f.material; @@ -1387,13 +1387,13 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face } // Ensure B has points either side of or in the plane of A. - int in_plane_count = 0, over_count = 0, under_count = 0; + int over_count = 0, under_count = 0; Plane plane_a(vertices_a[0], vertices_a[1], vertices_a[2]); ERR_FAIL_COND_MSG(plane_a.normal == Vector3(), "Couldn't form plane from Brush A face."); for (int i = 0; i < 3; i++) { if (plane_a.has_point(vertices_b[i])) { - in_plane_count++; + // In plane. } else if (plane_a.is_point_over(vertices_b[i])) { over_count++; } else { @@ -1406,7 +1406,6 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face } // Ensure A has points either side of or in the plane of B. - in_plane_count = 0; over_count = 0; under_count = 0; Plane plane_b(vertices_b[0], vertices_b[1], vertices_b[2]); @@ -1414,7 +1413,7 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face for (int i = 0; i < 3; i++) { if (plane_b.has_point(vertices_a[i])) { - in_plane_count++; + // In plane. } else if (plane_b.is_point_over(vertices_a[i])) { over_count++; } else { diff --git a/modules/csg/csg.h b/modules/csg/csg.h index 9ff7b13a44..53a9e5d722 100644 --- a/modules/csg/csg.h +++ b/modules/csg/csg.h @@ -38,8 +38,8 @@ #include "core/math/vector3.h" #include "core/object/ref_counted.h" #include "core/templates/list.h" -#include "core/templates/map.h" #include "core/templates/oa_hash_map.h" +#include "core/templates/rb_map.h" #include "core/templates/vector.h" #include "scene/resources/material.h" @@ -139,8 +139,8 @@ struct CSGBrushOperation { Vector<Vector3> points; Vector<Face> faces; - Map<Ref<Material>, int> materials; - Map<Vector3, int> vertex_map; + HashMap<Ref<Material>, int> materials; + HashMap<Vector3, int> vertex_map; OAHashMap<VertexKey, int, VertexKeyHash> snap_cache; float vertex_snap = 0.0; @@ -184,8 +184,8 @@ struct CSGBrushOperation { }; struct Build2DFaceCollection { - Map<int, Build2DFaces> build2DFacesA; - Map<int, Build2DFaces> build2DFacesB; + HashMap<int, Build2DFaces> build2DFacesA; + HashMap<int, Build2DFaces> build2DFacesB; }; void update_faces(const CSGBrush &p_brush_a, const int p_face_idx_a, const CSGBrush &p_brush_b, const int p_face_idx_b, Build2DFaceCollection &p_collection, float p_vertex_snap); diff --git a/modules/enet/enet_multiplayer_peer.h b/modules/enet/enet_multiplayer_peer.h index e7b61169fb..18eca18e51 100644 --- a/modules/enet/enet_multiplayer_peer.h +++ b/modules/enet/enet_multiplayer_peer.h @@ -70,8 +70,8 @@ private: ConnectionStatus connection_status = CONNECTION_DISCONNECTED; - Map<int, Ref<ENetConnection>> hosts; - Map<int, Ref<ENetPacketPeer>> peers; + HashMap<int, Ref<ENetConnection>> hosts; + HashMap<int, Ref<ENetPacketPeer>> peers; struct Packet { ENetPacket *packet = nullptr; diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index d23c4b637c..4b2ea6faa5 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -49,6 +49,7 @@ if env["builtin_freetype"]: "src/psnames/psnames.c", "src/raster/raster.c", "src/sdf/sdf.c", + "src/svg/svg.c", "src/smooth/smooth.c", "src/truetype/truetype.c", "src/type1/type1.c", @@ -87,7 +88,7 @@ if env["builtin_freetype"]: # Also needed in main env for scene/ env.Prepend(CPPPATH=[thirdparty_dir + "/include"]) - env_freetype.Append(CPPDEFINES=["FT2_BUILD_LIBRARY", "FT_CONFIG_OPTION_USE_PNG"]) + env_freetype.Append(CPPDEFINES=["FT2_BUILD_LIBRARY", "FT_CONFIG_OPTION_USE_PNG", "FT_CONFIG_OPTION_SYSTEM_ZLIB"]) if env["target"] == "debug": env_freetype.Append(CPPDEFINES=["ZLIB_DEBUG"]) diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index d0926d317b..70151c4d21 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -184,27 +184,24 @@ <method name="range" qualifiers="vararg"> <return type="Array" /> <description> - Returns an array with the given range. Range can be 1 argument [code]N[/code] (0 to [code]N[/code] - 1), two arguments ([code]initial[/code], [code]final - 1[/code]) or three arguments ([code]initial[/code], [code]final - 1[/code], [code]increment[/code]). Returns an empty array if the range isn't valid (e.g. [code]range(2, 5, -1)[/code] or [code]range(5, 5, 1)[/code]). - Returns an array with the given range. [code]range()[/code] can have 1 argument N ([code]0[/code] to [code]N - 1[/code]), two arguments ([code]initial[/code], [code]final - 1[/code]) or three arguments ([code]initial[/code], [code]final - 1[/code], [code]increment[/code]). [code]increment[/code] can be negative. If [code]increment[/code] is negative, [code]final - 1[/code] will become [code]final + 1[/code]. Also, the initial value must be greater than the final value for the loop to run. - [code]range()[/code] converts all arguments to [int] before processing. + Returns an array with the given range. [method range] can be called in three ways: + [code]range(n: int)[/code]: Starts from 0, increases by steps of 1, and stops [i]before[/i] [code]n[/code]. The argument [code]n[/code] is [b]exclusive[/b]. + [code]range(b: int, n: int)[/code]: Starts from [code]b[/code], increases by steps of 1, and stops [i]before[/i] [code]n[/code]. The arguments [code]b[/code] and [code]n[/code] are [b]inclusive[/b] and [b]exclusive[/b], respectively. + [code]range(b: int, n: int, s: int)[/code]: Starts from [code]b[/code], increases/decreases by steps of [code]s[/code], and stops [i]before[/i] [code]n[/code]. The arguments [code]b[/code] and [code]n[/code] are [b]inclusive[/b] and [b]exclusive[/b], respectively. The argument [code]s[/code] [b]can[/b] be negative, but not [code]0[/code]. If [code]s[/code] is [code]0[/code], an error message is printed. + [method range] converts all arguments to [int] before processing. + [b]Note:[/b] Returns an empty array if no value meets the value constraint (e.g. [code]range(2, 5, -1)[/code] or [code]range(5, 5, 1)[/code]). + Examples: [codeblock] - print(range(4)) - print(range(2, 5)) - print(range(0, 6, 2)) - [/codeblock] - Output: - [codeblock] - [0, 1, 2, 3] - [2, 3, 4] - [0, 2, 4] + print(range(4)) # Prints [0, 1, 2, 3] + print(range(2, 5)) # Prints [2, 3, 4] + print(range(0, 6, 2)) # Prints [0, 2, 4] + print(range(4, 1, -1)) # Prints [4, 3, 2] [/codeblock] To iterate over an [Array] backwards, use: [codeblock] var array = [3, 6, 9] - var i := array.size() - 1 - while i >= 0: - print(array[i]) - i -= 1 + for i in range(array.size(), 0, -1): + print(array[i - 1]) [/codeblock] Output: [codeblock] diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index e3f0ddfc35..191568661d 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -510,9 +510,8 @@ void GDScriptSyntaxHighlighter::_update_cache() { } /* Autoloads. */ - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - const ProjectSettings::AutoloadInfo &info = E.value(); + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { + const ProjectSettings::AutoloadInfo &info = E.value; if (info.is_singleton) { keywords[info.name] = usertype_color; } diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h index 1ae0d72896..92764e3891 100644 --- a/modules/gdscript/editor/gdscript_highlighter.h +++ b/modules/gdscript/editor/gdscript_highlighter.h @@ -45,7 +45,7 @@ private: bool line_only = false; }; Vector<ColorRegion> color_regions; - Map<int, int> color_region_cache; + HashMap<int, int> color_region_cache; HashMap<StringName, Color> keywords; HashMap<StringName, Color> member_keywords; diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.h b/modules/gdscript/editor/gdscript_translation_parser_plugin.h index e7b40aa367..4633a431d8 100644 --- a/modules/gdscript/editor/gdscript_translation_parser_plugin.h +++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.h @@ -31,7 +31,7 @@ #ifndef GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H #define GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H -#include "core/templates/set.h" +#include "core/templates/rb_set.h" #include "editor/editor_translation_parser.h" #include "modules/gdscript/gdscript_parser.h" @@ -44,9 +44,9 @@ class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlug // List of patterns used for extracting translation strings. StringName tr_func = "tr"; StringName trn_func = "tr_n"; - Set<StringName> assignment_patterns; - Set<StringName> first_arg_patterns; - Set<StringName> second_arg_patterns; + RBSet<StringName> assignment_patterns; + RBSet<StringName> first_arg_patterns; + RBSet<StringName> second_arg_patterns; // FileDialog patterns. StringName fd_add_filter = "add_filter"; StringName fd_set_filter = "set_filters"; diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 1b4711804c..e400d0bf94 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -340,14 +340,14 @@ bool GDScript::has_method(const StringName &p_method) const { } MethodInfo GDScript::get_method_info(const StringName &p_method) const { - const Map<StringName, GDScriptFunction *>::Element *E = member_functions.find(p_method); + HashMap<StringName, GDScriptFunction *>::ConstIterator E = member_functions.find(p_method); if (!E) { return MethodInfo(); } - GDScriptFunction *func = E->get(); + GDScriptFunction *func = E->value; MethodInfo mi; - mi.name = E->key(); + mi.name = E->key; for (int i = 0; i < func->get_argument_count(); i++) { mi.arguments.push_back(func->get_argument_type(i)); } @@ -359,9 +359,9 @@ MethodInfo GDScript::get_method_info(const StringName &p_method) const { bool GDScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { #ifdef TOOLS_ENABLED - const Map<StringName, Variant>::Element *E = member_default_values_cache.find(p_property); + HashMap<StringName, Variant>::ConstIterator E = member_default_values_cache.find(p_property); if (E) { - r_value = E->get(); + r_value = E->value; return true; } @@ -427,7 +427,7 @@ void GDScript::set_source_code(const String &p_code) { } #ifdef TOOLS_ENABLED -void GDScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) { +void GDScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) { if (base_cache.is_valid()) { base_cache->_update_exports_values(values, propnames); } @@ -759,12 +759,12 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc if ((changed || p_instance_to_update) && placeholders.size()) { //hm :( // update placeholders if any - Map<StringName, Variant> values; + HashMap<StringName, Variant> values; List<PropertyInfo> propnames; _update_exports_values(values, propnames); if (changed) { - for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { + for (RBSet<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { E->get()->update(propnames, values); } } else { @@ -788,9 +788,9 @@ void GDScript::update_exports() { return; } - Set<ObjectID> copy = inheriters_cache; //might get modified + RBSet<ObjectID> copy = inheriters_cache; //might get modified - for (Set<ObjectID>::Element *E = copy.front(); E; E = E->next()) { + for (RBSet<ObjectID>::Element *E = copy.front(); E; E = E->next()) { Object *id = ObjectDB::get_instance(E->get()); GDScript *s = Object::cast_to<GDScript>(id); if (!s) { @@ -929,7 +929,7 @@ ScriptLanguage *GDScript::get_language() const { return GDScriptLanguage::get_singleton(); } -void GDScript::get_constants(Map<StringName, Variant> *p_constants) { +void GDScript::get_constants(HashMap<StringName, Variant> *p_constants) { if (p_constants) { for (const KeyValue<StringName, Variant> &E : constants) { (*p_constants)[E.key] = E.value; @@ -937,9 +937,9 @@ void GDScript::get_constants(Map<StringName, Variant> *p_constants) { } } -void GDScript::get_members(Set<StringName> *p_members) { +void GDScript::get_members(RBSet<StringName> *p_members) { if (p_members) { - for (Set<StringName>::Element *E = members.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = members.front(); E; E = E->next()) { p_members->insert(E->get()); } } @@ -952,11 +952,11 @@ const Vector<Multiplayer::RPCConfig> GDScript::get_rpc_methods() const { Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { GDScript *top = this; while (top) { - Map<StringName, GDScriptFunction *>::Element *E = top->member_functions.find(p_method); + HashMap<StringName, GDScriptFunction *>::Iterator E = top->member_functions.find(p_method); if (E) { - ERR_FAIL_COND_V_MSG(!E->get()->is_static(), Variant(), "Can't call non-static function '" + String(p_method) + "' in script."); + ERR_FAIL_COND_V_MSG(!E->value->is_static(), Variant(), "Can't call non-static function '" + String(p_method) + "' in script."); - return E->get()->call(nullptr, p_args, p_argcount, r_error); + return E->value->call(nullptr, p_args, p_argcount, r_error); } top = top->_base; } @@ -971,17 +971,17 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const { const GDScript *top = this; while (top) { { - const Map<StringName, Variant>::Element *E = top->constants.find(p_name); + HashMap<StringName, Variant>::ConstIterator E = top->constants.find(p_name); if (E) { - r_ret = E->get(); + r_ret = E->value; return true; } } { - const Map<StringName, Ref<GDScript>>::Element *E = subclasses.find(p_name); + HashMap<StringName, Ref<GDScript>>::ConstIterator E = subclasses.find(p_name); if (E) { - r_ret = E->get(); + r_ret = E->value; return true; } } @@ -1061,7 +1061,7 @@ Error GDScript::load_source_code(const String &p_path) { return OK; } -const Map<StringName, GDScriptFunction *> &GDScript::debug_get_member_functions() const { +const HashMap<StringName, GDScriptFunction *> &GDScript::debug_get_member_functions() const { return member_functions; } @@ -1209,7 +1209,7 @@ void GDScript::_init_rpc_methods_properties() { } GDScript *cscript = this; - Map<StringName, Ref<GDScript>>::Element *sub_E = subclasses.front(); + HashMap<StringName, Ref<GDScript>>::Iterator sub_E = subclasses.begin(); while (cscript) { // RPC Methods for (KeyValue<StringName, GDScriptFunction *> &E : cscript->member_functions) { @@ -1223,11 +1223,11 @@ void GDScript::_init_rpc_methods_properties() { } if (cscript != this) { - sub_E = sub_E->next(); + ++sub_E; } if (sub_E) { - cscript = sub_E->get().ptr(); + cscript = sub_E->value.ptr(); } else { cscript = nullptr; } @@ -1282,9 +1282,9 @@ GDScript::~GDScript() { bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { //member { - const Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name); + HashMap<StringName, GDScript::MemberInfo>::Iterator E = script->member_indices.find(p_name); if (E) { - const GDScript::MemberInfo *member = &E->get(); + const GDScript::MemberInfo *member = &E->value; if (member->setter) { const Variant *val = &p_value; Callable::CallError err; @@ -1325,13 +1325,13 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { GDScript *sptr = script.ptr(); while (sptr) { - Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set); + HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set); if (E) { Variant name = p_name; const Variant *args[2] = { &name, &p_value }; Callable::CallError err; - Variant ret = E->get()->call(this, (const Variant **)args, 2, err); + Variant ret = E->value->call(this, (const Variant **)args, 2, err); if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) { return true; } @@ -1346,16 +1346,16 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { const GDScript *sptr = script.ptr(); while (sptr) { { - const Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name); + HashMap<StringName, GDScript::MemberInfo>::ConstIterator E = script->member_indices.find(p_name); if (E) { - if (E->get().getter) { + if (E->value.getter) { Callable::CallError err; - r_ret = const_cast<GDScriptInstance *>(this)->callp(E->get().getter, nullptr, 0, err); + r_ret = const_cast<GDScriptInstance *>(this)->callp(E->value.getter, nullptr, 0, err); if (err.error == Callable::CallError::CALL_OK) { return true; } } - r_ret = members[E->get().index]; + r_ret = members[E->value.index]; return true; //index found } } @@ -1363,9 +1363,9 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { { const GDScript *sl = sptr; while (sl) { - const Map<StringName, Variant>::Element *E = sl->constants.find(p_name); + HashMap<StringName, Variant>::ConstIterator E = sl->constants.find(p_name); if (E) { - r_ret = E->get(); + r_ret = E->value; return true; //index found } sl = sl->_base; @@ -1376,9 +1376,9 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { // Signals. const GDScript *sl = sptr; while (sl) { - const Map<StringName, Vector<StringName>>::Element *E = sl->_signals.find(p_name); + HashMap<StringName, Vector<StringName>>::ConstIterator E = sl->_signals.find(p_name); if (E) { - r_ret = Signal(this->owner, E->key()); + r_ret = Signal(this->owner, E->key); return true; //index found } sl = sl->_base; @@ -1389,14 +1389,14 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { // Methods. const GDScript *sl = sptr; while (sl) { - const Map<StringName, GDScriptFunction *>::Element *E = sl->member_functions.find(p_name); + HashMap<StringName, GDScriptFunction *>::ConstIterator E = sl->member_functions.find(p_name); if (E) { Multiplayer::RPCConfig config; config.name = p_name; if (sptr->rpc_functions.find(config) != -1) { - r_ret = Callable(memnew(GDScriptRPCCallable(this->owner, E->key()))); + r_ret = Callable(memnew(GDScriptRPCCallable(this->owner, E->key))); } else { - r_ret = Callable(this->owner, E->key()); + r_ret = Callable(this->owner, E->key); } return true; //index found } @@ -1405,13 +1405,13 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { } { - const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get); + HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get); if (E) { Variant name = p_name; const Variant *args[1] = { &name }; Callable::CallError err; - Variant ret = const_cast<GDScriptFunction *>(E->get())->call(const_cast<GDScriptInstance *>(this), (const Variant **)args, 1, err); + Variant ret = const_cast<GDScriptFunction *>(E->value)->call(const_cast<GDScriptInstance *>(this), (const Variant **)args, 1, err); if (err.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) { r_ret = ret; return true; @@ -1449,10 +1449,10 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const List<PropertyInfo> props; while (sptr) { - const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list); + HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list); if (E) { Callable::CallError err; - Variant ret = const_cast<GDScriptFunction *>(E->get())->call(const_cast<GDScriptInstance *>(this), nullptr, 0, err); + Variant ret = const_cast<GDScriptFunction *>(E->value)->call(const_cast<GDScriptInstance *>(this), nullptr, 0, err); if (err.error == Callable::CallError::CALL_OK) { ERR_FAIL_COND_MSG(ret.get_type() != Variant::ARRAY, "Wrong type for _get_property_list, must be an array of dictionaries."); @@ -1525,7 +1525,7 @@ void GDScriptInstance::get_method_list(List<MethodInfo> *p_list) const { bool GDScriptInstance::has_method(const StringName &p_method) const { const GDScript *sptr = script.ptr(); while (sptr) { - const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method); + HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(p_method); if (E) { return true; } @@ -1538,9 +1538,9 @@ bool GDScriptInstance::has_method(const StringName &p_method) const { Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { GDScript *sptr = script.ptr(); while (sptr) { - Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method); + HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(p_method); if (E) { - return E->get()->call(this, p_args, p_argcount, r_error); + return E->value->call(this, p_args, p_argcount, r_error); } sptr = sptr->_base; } @@ -1555,10 +1555,10 @@ void GDScriptInstance::notification(int p_notification) { GDScript *sptr = script.ptr(); while (sptr) { - Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification); + HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification); if (E) { Callable::CallError err; - E->get()->call(this, args, 1, err); + E->value->call(this, args, 1, err); if (err.error != Callable::CallError::CALL_OK) { //print error about notification call } @@ -1882,7 +1882,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so //when someone asks you why dynamically typed languages are easier to write.... - Map<Ref<GDScript>, Map<ObjectID, List<Pair<StringName, Variant>>>> to_reload; + HashMap<Ref<GDScript>, HashMap<ObjectID, List<Pair<StringName, Variant>>>> to_reload; //as scripts are going to be reloaded, must proceed without locking here @@ -1895,11 +1895,11 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so continue; } - to_reload.insert(script, Map<ObjectID, List<Pair<StringName, Variant>>>()); + to_reload.insert(script, HashMap<ObjectID, List<Pair<StringName, Variant>>>()); if (!p_soft_reload) { //save state and remove script from instances - Map<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[script]; + HashMap<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[script]; while (script->instances.front()) { Object *obj = script->instances.front()->get(); @@ -1938,7 +1938,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so } } - for (KeyValue<Ref<GDScript>, Map<ObjectID, List<Pair<StringName, Variant>>>> &E : to_reload) { + for (KeyValue<Ref<GDScript>, HashMap<ObjectID, List<Pair<StringName, Variant>>>> &E : to_reload) { Ref<GDScript> scr = E.key; scr->reload(p_soft_reload); @@ -2277,13 +2277,13 @@ void GDScriptLanguage::add_orphan_subclass(const String &p_qualified_name, const } Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_name) { - Map<String, ObjectID>::Element *orphan_subclass_element = orphan_subclasses.find(p_qualified_name); + HashMap<String, ObjectID>::Iterator orphan_subclass_element = orphan_subclasses.find(p_qualified_name); if (!orphan_subclass_element) { return Ref<GDScript>(); } - ObjectID orphan_subclass = orphan_subclass_element->get(); + ObjectID orphan_subclass = orphan_subclass_element->value; Object *obj = ObjectDB::get_instance(orphan_subclass); - orphan_subclasses.erase(orphan_subclass_element); + orphan_subclasses.remove(orphan_subclass_element); if (!obj) { return Ref<GDScript>(); } @@ -2372,7 +2372,7 @@ Error ResourceFormatSaverGDScript::save(const String &p_path, const Ref<Resource } if (ScriptServer::is_reload_scripts_on_save_enabled()) { - GDScriptLanguage::get_singleton()->reload_tool_script(p_resource, false); + GDScriptLanguage::get_singleton()->reload_tool_script(p_resource, true); } return OK; diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index a20f3b2fca..5199d3215d 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -80,48 +80,48 @@ class GDScript : public Script { GDScript *_base = nullptr; //fast pointer access GDScript *_owner = nullptr; //for subclasses - Set<StringName> members; //members are just indices to the instantiated script. - Map<StringName, Variant> constants; - Map<StringName, GDScriptFunction *> member_functions; - Map<StringName, MemberInfo> member_indices; //members are just indices to the instantiated script. - Map<StringName, Ref<GDScript>> subclasses; - Map<StringName, Vector<StringName>> _signals; + RBSet<StringName> members; //members are just indices to the instantiated script. + HashMap<StringName, Variant> constants; + HashMap<StringName, GDScriptFunction *> member_functions; + HashMap<StringName, MemberInfo> member_indices; //members are just indices to the instantiated script. + HashMap<StringName, Ref<GDScript>> subclasses; + HashMap<StringName, Vector<StringName>> _signals; Vector<Multiplayer::RPCConfig> rpc_functions; #ifdef TOOLS_ENABLED - Map<StringName, int> member_lines; - Map<StringName, Variant> member_default_values; + HashMap<StringName, int> member_lines; + HashMap<StringName, Variant> member_default_values; List<PropertyInfo> members_cache; - Map<StringName, Variant> member_default_values_cache; + HashMap<StringName, Variant> member_default_values_cache; Ref<GDScript> base_cache; - Set<ObjectID> inheriters_cache; + RBSet<ObjectID> inheriters_cache; bool source_changed_cache = false; bool placeholder_fallback_enabled = false; - void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames); + void _update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames); DocData::ClassDoc doc; Vector<DocData::ClassDoc> docs; String doc_brief_description; String doc_description; Vector<DocData::TutorialDoc> doc_tutorials; - Map<String, String> doc_functions; - Map<String, String> doc_variables; - Map<String, String> doc_constants; - Map<String, String> doc_signals; - Map<String, DocData::EnumDoc> doc_enums; + HashMap<String, String> doc_functions; + HashMap<String, String> doc_variables; + HashMap<String, String> doc_constants; + HashMap<String, String> doc_signals; + HashMap<String, DocData::EnumDoc> doc_enums; void _clear_doc(); void _update_doc(); void _add_doc(const DocData::ClassDoc &p_inner_class); #endif - Map<StringName, PropertyInfo> member_info; + HashMap<StringName, PropertyInfo> member_info; GDScriptFunction *implicit_initializer = nullptr; GDScriptFunction *initializer = nullptr; //direct pointer to new , faster to locate int subclass_count = 0; - Set<Object *> instances; + RBSet<Object *> instances; //exported members String source; String path; @@ -139,14 +139,14 @@ class GDScript : public Script { String _get_debug_path() const; #ifdef TOOLS_ENABLED - Set<PlaceHolderScriptInstance *> placeholders; + RBSet<PlaceHolderScriptInstance *> placeholders; //void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override; #endif #ifdef DEBUG_ENABLED - Map<ObjectID, List<Pair<StringName, Variant>>> pending_reload_state; + HashMap<ObjectID, List<Pair<StringName, Variant>>> pending_reload_state; #endif @@ -176,14 +176,14 @@ public: bool inherits_script(const Ref<Script> &p_script) const override; - const Map<StringName, Ref<GDScript>> &get_subclasses() const { return subclasses; } - const Map<StringName, Variant> &get_constants() const { return constants; } - const Set<StringName> &get_members() const { return members; } + const HashMap<StringName, Ref<GDScript>> &get_subclasses() const { return subclasses; } + const HashMap<StringName, Variant> &get_constants() const { return constants; } + const RBSet<StringName> &get_members() const { return members; } const GDScriptDataType &get_member_type(const StringName &p_member) const { CRASH_COND(!member_indices.has(p_member)); return member_indices[p_member].data_type; } - const Map<StringName, GDScriptFunction *> &get_member_functions() const { return member_functions; } + const HashMap<StringName, GDScriptFunction *> &get_member_functions() const { return member_functions; } const Ref<GDScriptNativeClass> &get_native() const { return native; } const String &get_script_class_name() const { return name; } @@ -193,8 +193,8 @@ public: bool is_tool() const override { return tool; } Ref<GDScript> get_base() const; - const Map<StringName, MemberInfo> &debug_get_member_indices() const { return member_indices; } - const Map<StringName, GDScriptFunction *> &debug_get_member_functions() const; //this is debug only + const HashMap<StringName, MemberInfo> &debug_get_member_indices() const { return member_indices; } + const HashMap<StringName, GDScriptFunction *> &debug_get_member_functions() const; //this is debug only StringName debug_get_member_by_index(int p_idx) const; Variant _new(const Variant **p_args, int p_argcount, Callable::CallError &r_error); @@ -245,8 +245,8 @@ public: return -1; } - virtual void get_constants(Map<StringName, Variant> *p_constants) override; - virtual void get_members(Set<StringName> *p_members) override; + virtual void get_constants(HashMap<StringName, Variant> *p_constants) override; + virtual void get_members(RBSet<StringName> *p_members) override; virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override; @@ -270,7 +270,7 @@ class GDScriptInstance : public ScriptInstance { Object *owner = nullptr; Ref<GDScript> script; #ifdef DEBUG_ENABLED - Map<StringName, int> member_indices_cache; //used only for hot script reloading + HashMap<StringName, int> member_indices_cache; //used only for hot script reloading #endif Vector<Variant> members; bool base_ref_counted; @@ -315,8 +315,8 @@ class GDScriptLanguage : public ScriptLanguage { Variant *_global_array = nullptr; Vector<Variant> global_array; - Map<StringName, int> globals; - Map<StringName, Variant> named_globals; + HashMap<StringName, int> globals; + HashMap<StringName, Variant> named_globals; struct CallLevel { Variant *stack = nullptr; @@ -348,7 +348,7 @@ class GDScriptLanguage : public ScriptLanguage { bool profiling; uint64_t script_frame_time; - Map<String, ObjectID> orphan_subclasses; + HashMap<String, ObjectID> orphan_subclasses; public: int calls; @@ -427,8 +427,8 @@ public: _FORCE_INLINE_ int get_global_array_size() const { return global_array.size(); } _FORCE_INLINE_ Variant *get_global_array() { return _global_array; } - _FORCE_INLINE_ const Map<StringName, int> &get_global_map() const { return globals; } - _FORCE_INLINE_ const Map<StringName, Variant> &get_named_globals_map() const { return named_globals; } + _FORCE_INLINE_ const HashMap<StringName, int> &get_global_map() const { return globals; } + _FORCE_INLINE_ const HashMap<StringName, Variant> &get_named_globals_map() const { return named_globals; } _FORCE_INLINE_ static GDScriptLanguage *get_singleton() { return singleton; } @@ -449,7 +449,7 @@ public: virtual bool is_using_templates() override; virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override; virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) override; - virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const override; + virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, RBSet<int> *r_safe_lines = nullptr) const override; virtual Script *create_script() const override; virtual bool has_named_classes() const override; virtual bool supports_builtin_mode() const override; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index d346264933..32fa3b8c87 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -898,7 +898,7 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) { } #ifdef DEBUG_ENABLED - Set<uint32_t> previously_ignored = parser->ignored_warning_codes; + RBSet<uint32_t> previously_ignored = parser->ignored_warning_codes; for (uint32_t ignored_warning : member.function->ignored_warnings) { parser->ignored_warning_codes.insert(ignored_warning); } @@ -947,7 +947,7 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) { GDScriptParser::ClassNode::Member member = p_class->members[i]; if (member.type == GDScriptParser::ClassNode::Member::VARIABLE) { #ifdef DEBUG_ENABLED - Set<uint32_t> previously_ignored = parser->ignored_warning_codes; + RBSet<uint32_t> previously_ignored = parser->ignored_warning_codes; for (uint32_t ignored_warning : member.function->ignored_warnings) { parser->ignored_warning_codes.insert(ignored_warning); } @@ -1279,7 +1279,7 @@ void GDScriptAnalyzer::resolve_suite(GDScriptParser::SuiteNode *p_suite) { } #ifdef DEBUG_ENABLED - Set<uint32_t> previously_ignored = parser->ignored_warning_codes; + RBSet<uint32_t> previously_ignored = parser->ignored_warning_codes; for (uint32_t ignored_warning : stmt->ignored_warnings) { parser->ignored_warning_codes.insert(ignored_warning); } @@ -2174,7 +2174,7 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_await, bool p_is_root) { bool all_is_constant = true; - Map<int, GDScriptParser::ArrayNode *> arrays; // For array literal to potentially type when passing. + HashMap<int, GDScriptParser::ArrayNode *> arrays; // For array literal to potentially type when passing. for (int i = 0; i < p_call->arguments.size(); i++) { reduce_expression(p_call->arguments[i]); if (p_call->arguments[i]->type == GDScriptParser::Node::ARRAY) { @@ -4218,13 +4218,11 @@ Error GDScriptAnalyzer::resolve_program() { resolve_class_interface(parser->head); resolve_class_body(parser->head); - List<String> parser_keys; - depended_parsers.get_key_list(&parser_keys); - for (const String &E : parser_keys) { - if (depended_parsers[E].is_null()) { + for (KeyValue<String, Ref<GDScriptParserRef>> &K : depended_parsers) { + if (K.value.is_null()) { return ERR_PARSE_ERROR; } - depended_parsers[E]->raise_status(GDScriptParserRef::FULLY_SOLVED); + K.value->raise_status(GDScriptParserRef::FULLY_SOLVED); } return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR; } diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index 519e1975c4..5b03f6dbb4 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -33,7 +33,7 @@ #include "core/object/object.h" #include "core/object/ref_counted.h" -#include "core/templates/set.h" +#include "core/templates/rb_set.h" #include "gdscript_cache.h" #include "gdscript_parser.h" diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index e72069bcd5..3d5a39bf38 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -196,10 +196,8 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() { function->_constant_count = constant_map.size(); function->constants.resize(constant_map.size()); function->_constants_ptr = function->constants.ptrw(); - const Variant *K = nullptr; - while ((K = constant_map.next(K))) { - int idx = constant_map[*K]; - function->constants.write[idx] = *K; + for (const KeyValue<Variant, int> &K : constant_map) { + function->constants.write[K.value] = K.key; } } else { function->_constants_ptr = nullptr; diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index 0503f66161..6ee8fda533 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -53,19 +53,19 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { bool debug_stack = false; Vector<int> opcodes; - List<Map<StringName, int>> stack_id_stack; - Map<StringName, int> stack_identifiers; + List<RBMap<StringName, int>> stack_id_stack; + RBMap<StringName, int> stack_identifiers; List<int> stack_identifiers_counts; - Map<StringName, int> local_constants; + RBMap<StringName, int> local_constants; Vector<StackSlot> locals; Vector<StackSlot> temporaries; List<int> used_temporaries; - Map<Variant::Type, List<int>> temporaries_pool; + RBMap<Variant::Type, List<int>> temporaries_pool; List<GDScriptFunction::StackDebug> stack_debug; - List<Map<StringName, int>> block_identifier_stack; - Map<StringName, int> block_identifiers; + List<RBMap<StringName, int>> block_identifier_stack; + RBMap<StringName, int> block_identifiers; int max_locals = 0; int current_line = 0; @@ -77,23 +77,23 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { #endif HashMap<Variant, int, VariantHasher, VariantComparator> constant_map; - Map<StringName, int> name_map; + RBMap<StringName, int> name_map; #ifdef TOOLS_ENABLED Vector<StringName> named_globals; #endif - Map<Variant::ValidatedOperatorEvaluator, int> operator_func_map; - Map<Variant::ValidatedSetter, int> setters_map; - Map<Variant::ValidatedGetter, int> getters_map; - Map<Variant::ValidatedKeyedSetter, int> keyed_setters_map; - Map<Variant::ValidatedKeyedGetter, int> keyed_getters_map; - Map<Variant::ValidatedIndexedSetter, int> indexed_setters_map; - Map<Variant::ValidatedIndexedGetter, int> indexed_getters_map; - Map<Variant::ValidatedBuiltInMethod, int> builtin_method_map; - Map<Variant::ValidatedConstructor, int> constructors_map; - Map<Variant::ValidatedUtilityFunction, int> utilities_map; - Map<GDScriptUtilityFunctions::FunctionPtr, int> gds_utilities_map; - Map<MethodBind *, int> method_bind_map; - Map<GDScriptFunction *, int> lambdas_map; + RBMap<Variant::ValidatedOperatorEvaluator, int> operator_func_map; + RBMap<Variant::ValidatedSetter, int> setters_map; + RBMap<Variant::ValidatedGetter, int> getters_map; + RBMap<Variant::ValidatedKeyedSetter, int> keyed_setters_map; + RBMap<Variant::ValidatedKeyedGetter, int> keyed_getters_map; + RBMap<Variant::ValidatedIndexedSetter, int> indexed_setters_map; + RBMap<Variant::ValidatedIndexedGetter, int> indexed_getters_map; + RBMap<Variant::ValidatedBuiltInMethod, int> builtin_method_map; + RBMap<Variant::ValidatedConstructor, int> constructors_map; + RBMap<Variant::ValidatedUtilityFunction, int> utilities_map; + RBMap<GDScriptUtilityFunctions::FunctionPtr, int> gds_utilities_map; + RBMap<MethodBind *, int> method_bind_map; + RBMap<GDScriptFunction *, int> lambdas_map; // Lists since these can be nested. List<int> if_jmp_addrs; @@ -135,7 +135,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { stack_identifiers_counts.push_back(locals.size()); stack_id_stack.push_back(stack_identifiers); if (debug_stack) { - Map<StringName, int> block_ids(block_identifiers); + RBMap<StringName, int> block_ids(block_identifiers); block_identifier_stack.push_back(block_ids); block_identifiers.clear(); } diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp index 8c198345c2..bd98d66fcc 100644 --- a/modules/gdscript/gdscript_cache.cpp +++ b/modules/gdscript/gdscript_cache.cpp @@ -223,10 +223,10 @@ Error GDScriptCache::finish_compiling(const String &p_owner) { singleton->full_gdscript_cache[p_owner] = script.ptr(); singleton->shallow_gdscript_cache.erase(p_owner); - Set<String> depends = singleton->dependencies[p_owner]; + RBSet<String> depends = singleton->dependencies[p_owner]; Error err = OK; - for (const Set<String>::Element *E = depends.front(); E != nullptr; E = E->next()) { + for (const RBSet<String>::Element *E = depends.front(); E != nullptr; E = E->next()) { Error this_err = OK; // No need to save the script. We assume it's already referenced in the owner. get_full_script(E->get(), this_err); diff --git a/modules/gdscript/gdscript_cache.h b/modules/gdscript/gdscript_cache.h index 3ce976ee14..8abae7d4ad 100644 --- a/modules/gdscript/gdscript_cache.h +++ b/modules/gdscript/gdscript_cache.h @@ -34,7 +34,7 @@ #include "core/object/ref_counted.h" #include "core/os/mutex.h" #include "core/templates/hash_map.h" -#include "core/templates/set.h" +#include "core/templates/rb_set.h" #include "gdscript.h" class GDScriptAnalyzer; @@ -74,7 +74,7 @@ class GDScriptCache { HashMap<String, GDScriptParserRef *> parser_map; HashMap<String, GDScript *> shallow_gdscript_cache; HashMap<String, GDScript *> full_gdscript_cache; - HashMap<String, Set<String>> dependencies; + HashMap<String, RBSet<String>> dependencies; friend class GDScript; friend class GDScriptParserRef; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 37a988ee4c..cb389fd86a 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -336,7 +336,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) { // If it's an autoload singleton, we postpone to load it at runtime. // This is so one autoload doesn't try to load another before it's compiled. - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); if (autoloads.has(identifier) && autoloads[identifier].is_singleton) { GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype())); int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier]; @@ -703,10 +703,10 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code } else if (subscript->is_attribute) { if (subscript->base->type == GDScriptParser::Node::SELF && codegen.script) { GDScriptParser::IdentifierNode *identifier = subscript->attribute; - const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(identifier->name); + HashMap<StringName, GDScript::MemberInfo>::Iterator MI = codegen.script->member_indices.find(identifier->name); #ifdef DEBUG_ENABLED - if (MI && MI->get().getter == codegen.function_name) { + if (MI && MI->value.getter == codegen.function_name) { String n = identifier->name; _set_error("Must use '" + n + "' instead of 'self." + n + "' in getter.", identifier); r_error = ERR_COMPILATION_FAILED; @@ -714,11 +714,11 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code } #endif - if (MI && MI->get().getter == "") { + if (MI && MI->value.getter == "") { // Remove result temp as we don't need it. gen->pop_temporary(); // Faster than indexing self (as if no self. had been used). - return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::MEMBER, MI->get().index, _gdtype_from_datatype(subscript->get_datatype())); + return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::MEMBER, MI->value.index, _gdtype_from_datatype(subscript->get_datatype())); } } @@ -894,8 +894,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code const GDScriptParser::SubscriptNode *subscript = static_cast<GDScriptParser::SubscriptNode *>(assignment->assignee); #ifdef DEBUG_ENABLED if (subscript->is_attribute && subscript->base->type == GDScriptParser::Node::SELF && codegen.script) { - const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(subscript->attribute->name); - if (MI && MI->get().setter == codegen.function_name) { + HashMap<StringName, GDScript::MemberInfo>::Iterator MI = codegen.script->member_indices.find(subscript->attribute->name); + if (MI && MI->value.setter == codegen.function_name) { String n = subscript->attribute->name; _set_error("Must use '" + n + "' instead of 'self." + n + "' in setter.", subscript); r_error = ERR_COMPILATION_FAILED; @@ -2500,8 +2500,8 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa //validate instances if keeping state if (p_keep_state) { - for (Set<Object *>::Element *E = p_script->instances.front(); E;) { - Set<Object *>::Element *N = E->next(); + for (RBSet<Object *>::Element *E = p_script->instances.front(); E;) { + RBSet<Object *>::Element *N = E->next(); ScriptInstance *si = E->get()->get_script_instance(); if (si->is_placeholder()) { @@ -2563,7 +2563,7 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa } void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) { - Map<StringName, Ref<GDScript>> old_subclasses; + HashMap<StringName, Ref<GDScript>> old_subclasses; if (p_keep_state) { old_subclasses = p_script->subclasses; diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index 8d71437344..c9ffb04fb8 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -31,7 +31,7 @@ #ifndef GDSCRIPT_COMPILER_H #define GDSCRIPT_COMPILER_H -#include "core/templates/set.h" +#include "core/templates/rb_set.h" #include "gdscript.h" #include "gdscript_codegen.h" #include "gdscript_function.h" @@ -39,8 +39,8 @@ class GDScriptCompiler { const GDScriptParser *parser = nullptr; - Set<GDScript *> parsed_classes; - Set<GDScript *> parsing_classes; + RBSet<GDScript *> parsed_classes; + RBSet<GDScript *> parsing_classes; GDScript *main_script = nullptr; struct CodeGen { @@ -49,9 +49,9 @@ class GDScriptCompiler { const GDScriptParser::FunctionNode *function_node = nullptr; StringName function_name; GDScriptCodeGenerator *generator = nullptr; - Map<StringName, GDScriptCodeGenerator::Address> parameters; - Map<StringName, GDScriptCodeGenerator::Address> locals; - List<Map<StringName, GDScriptCodeGenerator::Address>> locals_stack; + HashMap<StringName, GDScriptCodeGenerator::Address> parameters; + HashMap<StringName, GDScriptCodeGenerator::Address> locals; + List<HashMap<StringName, GDScriptCodeGenerator::Address>> locals_stack; GDScriptCodeGenerator::Address add_local(const StringName &p_name, const GDScriptDataType &p_type) { uint32_t addr = generator->add_local(p_name, p_type); @@ -101,7 +101,7 @@ class GDScriptCompiler { } void start_block() { - Map<StringName, GDScriptCodeGenerator::Address> old_locals = locals; + HashMap<StringName, GDScriptCodeGenerator::Address> old_locals = locals; locals_stack.push_back(old_locals); generator->start_block(); } diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 0197bf9ea3..72f54626e3 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -98,7 +98,7 @@ Vector<ScriptLanguage::ScriptTemplate> GDScriptLanguage::get_built_in_templates( return templates; } -static void get_function_names_recursively(const GDScriptParser::ClassNode *p_class, const String &p_prefix, Map<int, String> &r_funcs) { +static void get_function_names_recursively(const GDScriptParser::ClassNode *p_class, const String &p_prefix, HashMap<int, String> &r_funcs) { for (int i = 0; i < p_class->members.size(); i++) { if (p_class->members[i].type == GDScriptParser::ClassNode::Member::FUNCTION) { const GDScriptParser::FunctionNode *function = p_class->members[i].function; @@ -110,7 +110,7 @@ static void get_function_names_recursively(const GDScriptParser::ClassNode *p_cl } } -bool GDScriptLanguage::validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const { +bool GDScriptLanguage::validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors, List<ScriptLanguage::Warning> *r_warnings, RBSet<int> *r_safe_lines) const { GDScriptParser parser; GDScriptAnalyzer analyzer(&parser); @@ -148,7 +148,7 @@ bool GDScriptLanguage::validate(const String &p_script, const String &p_path, Li return false; } else { const GDScriptParser::ClassNode *cl = parser.get_tree(); - Map<int, String> funcs; + HashMap<int, String> funcs; get_function_names_recursively(cl, "", funcs); @@ -159,7 +159,7 @@ bool GDScriptLanguage::validate(const String &p_script, const String &p_path, Li #ifdef DEBUG_ENABLED if (r_safe_lines) { - const Set<int> &unsafe_lines = parser.get_unsafe_lines(); + const RBSet<int> &unsafe_lines = parser.get_unsafe_lines(); for (int i = 1; i <= parser.get_last_line_number(); i++) { if (!unsafe_lines.has(i)) { r_safe_lines->insert(i); @@ -321,7 +321,7 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> * Ref<GDScript> script = instance->get_script(); ERR_FAIL_COND(script.is_null()); - const Map<StringName, GDScript::MemberInfo> &mi = script->debug_get_member_indices(); + const HashMap<StringName, GDScript::MemberInfo> &mi = script->debug_get_member_indices(); for (const KeyValue<StringName, GDScript::MemberInfo> &E : mi) { p_members->push_back(E.key); @@ -343,7 +343,7 @@ ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) { } void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { - const Map<StringName, int> &name_idx = GDScriptLanguage::get_singleton()->get_global_map(); + const HashMap<StringName, int> &name_idx = GDScriptLanguage::get_singleton()->get_global_map(); const Variant *globals = GDScriptLanguage::get_singleton()->get_global_array(); List<Pair<String, Variant>> cinfo; @@ -722,7 +722,7 @@ static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_functio return arghint; } -static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Map<String, ScriptLanguage::CodeCompletionOption> &r_list) { +static void _get_directory_contents(EditorFileSystemDirectory *p_dir, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_list) { const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\""; for (int i = 0; i < p_dir->get_file_count(); i++) { @@ -736,7 +736,7 @@ static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Map<String } } -static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_annotation, int p_argument, const String p_quote_style, Map<String, ScriptLanguage::CodeCompletionOption> &r_result) { +static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_annotation, int p_argument, const String p_quote_style, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result) { if (p_annotation->name == SNAME("@export_range")) { if (p_argument == 3 || p_argument == 4) { // Slider hint. @@ -777,7 +777,7 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a } } -static void _find_built_in_variants(Map<String, ScriptLanguage::CodeCompletionOption> &r_result, bool exclude_nil = false) { +static void _find_built_in_variants(HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, bool exclude_nil = false) { for (int i = 0; i < Variant::VARIANT_MAX; i++) { if (!exclude_nil && Variant::Type(i) == Variant::Type::NIL) { ScriptLanguage::CodeCompletionOption option("null", ScriptLanguage::CODE_COMPLETION_KIND_CLASS); @@ -789,7 +789,7 @@ static void _find_built_in_variants(Map<String, ScriptLanguage::CodeCompletionOp } } -static void _list_available_types(bool p_inherit_only, GDScriptParser::CompletionContext &p_context, Map<String, ScriptLanguage::CodeCompletionOption> &r_result) { +static void _list_available_types(bool p_inherit_only, GDScriptParser::CompletionContext &p_context, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result) { // Built-in Variant Types _find_built_in_variants(r_result, true); @@ -851,9 +851,10 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio } // Autoload singletons - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - const ProjectSettings::AutoloadInfo &info = E.get(); + HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) { + const ProjectSettings::AutoloadInfo &info = E.value; if (!info.is_singleton || info.path.get_extension().to_lower() != "gd") { continue; } @@ -862,7 +863,7 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio } } -static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite, Map<String, ScriptLanguage::CodeCompletionOption> &r_result) { +static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result) { for (int i = 0; i < p_suite->locals.size(); i++) { ScriptLanguage::CodeCompletionOption option; if (p_suite->locals[i].type == GDScriptParser::SuiteNode::Local::CONSTANT) { @@ -878,9 +879,9 @@ static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite, } } -static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth); +static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth); -static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, bool p_only_functions, bool p_static, bool p_parent_only, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) { +static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, bool p_only_functions, bool p_static, bool p_parent_only, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) { ERR_FAIL_COND(p_recursion_depth > COMPLETION_RECURSION_LIMIT); if (!p_parent_only) { @@ -965,7 +966,7 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, _find_identifiers_in_base(base_type, p_only_functions, r_result, p_recursion_depth + 1); } -static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) { +static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) { ERR_FAIL_COND(p_recursion_depth > COMPLETION_RECURSION_LIMIT); GDScriptParser::DataType base_type = p_base.type; @@ -997,7 +998,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base r_result.insert(option.display, option); } } - Map<StringName, Variant> constants; + HashMap<StringName, Variant> constants; scr->get_constants(&constants); for (const KeyValue<StringName, Variant> &E : constants) { int location = p_recursion_depth + _get_constant_location(scr->get_class_name(), E.key); @@ -1056,6 +1057,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base r_result.insert(option.display, option); } + List<MethodInfo> signals; + ClassDB::get_signal_list(type, &signals); + for (const MethodInfo &E : signals) { + int location = p_recursion_depth + _get_signal_location(type, StringName(E.name)); + ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL, location); + r_result.insert(option.display, option); + } + if (!_static || Engine::get_singleton()->has_singleton(type)) { List<PropertyInfo> pinfo; ClassDB::get_property_list(type, &pinfo); @@ -1140,7 +1149,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base } } -static void _find_identifiers(const GDScriptParser::CompletionContext &p_context, bool p_only_functions, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) { +static void _find_identifiers(const GDScriptParser::CompletionContext &p_context, bool p_only_functions, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) { if (!p_only_functions && p_context.current_suite) { // This includes function parameters, since they are also locals. _find_identifiers_in_suite(p_context.current_suite, r_result); @@ -1219,12 +1228,11 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context r_result.insert(option.display, option); } - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - if (!E.value().is_singleton) { + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { + if (!E.value.is_singleton) { continue; } - ScriptLanguage::CodeCompletionOption option(E.key(), ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); + ScriptLanguage::CodeCompletionOption option(E.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); r_result.insert(option.display, option); } @@ -1517,12 +1525,10 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[which]); found = true; } else { - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - String name = E.key(); + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { + String name = E.key; if (name == which) { - String script = E.value().path; + String script = E.value.path; if (!script.begins_with("res://")) { script = "res://" + script; @@ -2083,7 +2089,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & case GDScriptParser::DataType::SCRIPT: { Ref<Script> scr = base_type.script_type; if (scr.is_valid()) { - Map<StringName, Variant> constants; + HashMap<StringName, Variant> constants; scr->get_constants(&constants); if (constants.has(p_identifier)) { r_type = _type_from_variant(constants[p_identifier]); @@ -2312,7 +2318,7 @@ static bool _guess_method_return_type_from_base(GDScriptParser::CompletionContex return false; } -static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_context, const String &p_enum_hint, Map<String, ScriptLanguage::CodeCompletionOption> &r_result) { +static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_context, const String &p_enum_hint, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result) { if (!p_enum_hint.contains(".")) { // Global constant or in the current class. StringName current_enum = p_enum_hint; @@ -2349,7 +2355,7 @@ static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_co } } -static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, String &r_arghint) { +static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, String &r_arghint) { Variant base = p_base.value; GDScriptParser::DataType base_type = p_base.type; @@ -2468,7 +2474,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c } } -static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptParser::Node *p_call, int p_argidx, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) { +static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptParser::Node *p_call, int p_argidx, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) { if (p_call->type == GDScriptParser::Node::PRELOAD) { if (p_argidx == 0 && bool(EditorSettings::get_singleton()->get("text_editor/completion/complete_file_paths"))) { _get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), r_result); @@ -2583,7 +2589,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c analyzer.analyze(); r_forced = false; - Map<String, ScriptLanguage::CodeCompletionOption> options; + HashMap<String, ScriptLanguage::CodeCompletionOption> options; GDScriptParser::CompletionContext completion_context = parser.get_completion_context(); completion_context.base = p_owner; @@ -2882,10 +2888,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c } // Get autoloads. - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - String path = "/root/" + E.key(); + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { + String path = "/root/" + E.key; ScriptLanguage::CodeCompletionOption option(path.quote(quote_style), ScriptLanguage::CODE_COMPLETION_KIND_NODE_PATH); options.insert(option.display, option); } @@ -3062,6 +3066,13 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co } } + if (ClassDB::has_signal(class_name, p_symbol, true)) { + r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_SIGNAL; + r_result.class_name = base_type.native_type; + r_result.class_member = p_symbol; + return OK; + } + StringName enum_name = ClassDB::get_integer_constant_enum(class_name, p_symbol, true); if (enum_name != StringName()) { r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_ENUM; @@ -3268,7 +3279,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co } // Global. - Map<StringName, int> classes = GDScriptLanguage::get_singleton()->get_global_map(); + HashMap<StringName, int> classes = GDScriptLanguage::get_singleton()->get_global_map(); if (classes.has(p_symbol)) { Variant value = GDScriptLanguage::get_singleton()->get_global_array()[classes[p_symbol]]; if (value.get_type() == Variant::OBJECT) { diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 3d708955ed..deef593f34 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -93,7 +93,7 @@ struct _GDFKCS { void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<StringName, int>> *r_stackvars) const { int oc = 0; - Map<StringName, _GDFKC> sdmap; + HashMap<StringName, _GDFKC> sdmap; for (const StackDebug &sd : stack_debug) { if (sd.line >= p_line) { break; @@ -279,7 +279,8 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) { void GDScriptFunctionState::_clear_stack() { if (state.stack_size) { Variant *stack = (Variant *)state.stack.ptr(); - for (int i = 0; i < state.stack_size; i++) { + // The first 3 are special addresses and not copied to the state, so we skip them here. + for (int i = 3; i < state.stack_size; i++) { stack[i].~Variant(); } state.stack_size = 0; @@ -300,8 +301,6 @@ GDScriptFunctionState::GDScriptFunctionState() : } GDScriptFunctionState::~GDScriptFunctionState() { - _clear_stack(); - { MutexLock lock(GDScriptLanguage::singleton->lock); scripts_list.remove_from_list(); diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index ba0d51c5cc..d2ca795977 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -495,7 +495,7 @@ private: Vector<GDScriptDataType> argument_types; GDScriptDataType return_type; - Map<int, Variant::Type> temporary_slots; + HashMap<int, Variant::Type> temporary_slots; #ifdef TOOLS_ENABLED Vector<StringName> arg_names; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 67f6b61f14..8563f2b432 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -100,10 +100,8 @@ void GDScriptParser::cleanup() { } void GDScriptParser::get_annotation_list(List<MethodInfo> *r_annotations) const { - List<StringName> keys; - valid_annotations.get_key_list(&keys); - for (const StringName &E : keys) { - r_annotations->push_back(valid_annotations[E].info); + for (const KeyValue<StringName, AnnotationInfo> &E : valid_annotations) { + r_annotations->push_back(E.value.info); } } @@ -1863,7 +1861,7 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() { if (pattern == nullptr) { continue; } - if (pattern->pattern_type == PatternNode::PT_BIND) { + if (pattern->binds.size() > 0) { has_bind = true; } if (branch->patterns.size() > 0 && has_bind) { @@ -1894,11 +1892,9 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() { SuiteNode *suite = alloc_node<SuiteNode>(); if (branch->patterns.size() > 0) { - List<StringName> binds; - branch->patterns[0]->binds.get_key_list(&binds); - - for (const StringName &E : binds) { - SuiteNode::Local local(branch->patterns[0]->binds[E], current_function); + for (const KeyValue<StringName, IdentifierNode *> &E : branch->patterns[0]->binds) { + SuiteNode::Local local(E.value, current_function); + local.type = SuiteNode::Local::PATTERN_BIND; suite->add_local(local); } } @@ -2319,6 +2315,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(Expression operation->operation = BinaryOpNode::OP_MODULO; operation->variant_op = Variant::OP_MODULE; break; + case GDScriptTokenizer::Token::STAR_STAR: + operation->operation = BinaryOpNode::OP_POWER; + operation->variant_op = Variant::OP_POWER; + break; case GDScriptTokenizer::Token::LESS_LESS: operation->operation = BinaryOpNode::OP_BIT_LEFT_SHIFT; operation->variant_op = Variant::OP_SHIFT_LEFT; @@ -2482,6 +2482,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode assignment->operation = AssignmentNode::OP_MULTIPLICATION; assignment->variant_op = Variant::OP_MULTIPLY; break; + case GDScriptTokenizer::Token::STAR_STAR_EQUAL: + assignment->operation = AssignmentNode::OP_POWER; + assignment->variant_op = Variant::OP_POWER; + break; case GDScriptTokenizer::Token::SLASH_EQUAL: assignment->operation = AssignmentNode::OP_DIVISION; assignment->variant_op = Variant::OP_DIVIDE; @@ -3049,7 +3053,7 @@ bool GDScriptParser::has_comment(int p_line) { } String GDScriptParser::get_doc_comment(int p_line, bool p_single_line) { - const Map<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments(); + const HashMap<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments(); ERR_FAIL_COND_V(!comments.has(p_line), String()); if (p_single_line) { @@ -3101,7 +3105,7 @@ String GDScriptParser::get_doc_comment(int p_line, bool p_single_line) { } void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String &p_desc, Vector<Pair<String, String>> &p_tutorials, bool p_inner_class) { - const Map<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments(); + const HashMap<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments(); if (!comments.has(p_line)) { return; } @@ -3264,6 +3268,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty { &GDScriptParser::parse_unary_operator, &GDScriptParser::parse_binary_operator, PREC_ADDITION_SUBTRACTION }, // PLUS, { &GDScriptParser::parse_unary_operator, &GDScriptParser::parse_binary_operator, PREC_ADDITION_SUBTRACTION }, // MINUS, { nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // STAR, + { nullptr, &GDScriptParser::parse_binary_operator, PREC_POWER }, // STAR_STAR, { nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // SLASH, { nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // PERCENT, // Assignment @@ -3271,6 +3276,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty { nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // PLUS_EQUAL, { nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // MINUS_EQUAL, { nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // STAR_EQUAL, + { nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // STAR_STAR_EQUAL, { nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // SLASH_EQUAL, { nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // PERCENT_EQUAL, { nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // LESS_LESS_EQUAL, @@ -3555,14 +3561,16 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node variable->export_info.hint = PROPERTY_HINT_ENUM; String enum_hint_string; - for (OrderedHashMap<StringName, int>::Element E = export_type.enum_values.front(); E; E = E.next()) { - enum_hint_string += E.key().operator String().capitalize().xml_escape(); - enum_hint_string += ":"; - enum_hint_string += String::num_int64(E.value()).xml_escape(); - - if (E.next()) { + bool first = true; + for (const KeyValue<StringName, int> &E : export_type.enum_values) { + if (!first) { enum_hint_string += ","; + } else { + first = false; } + enum_hint_string += E.key.operator String().capitalize().xml_escape(); + enum_hint_string += ":"; + enum_hint_string += String::num_int64(E.value).xml_escape(); } variable->export_info.hint_string = enum_hint_string; @@ -3895,6 +3903,9 @@ void GDScriptParser::TreePrinter::print_assignment(AssignmentNode *p_assignment) case AssignmentNode::OP_MODULO: push_text("%"); break; + case AssignmentNode::OP_POWER: + push_text("**"); + break; case AssignmentNode::OP_BIT_SHIFT_LEFT: push_text("<<"); break; @@ -3943,6 +3954,9 @@ void GDScriptParser::TreePrinter::print_binary_op(BinaryOpNode *p_binary_op) { case BinaryOpNode::OP_MODULO: push_text(" % "); break; + case BinaryOpNode::OP_POWER: + push_text(" ** "); + break; case BinaryOpNode::OP_BIT_LEFT_SHIFT: push_text(" << "); break; diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 10474db02f..17f87edeeb 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -39,7 +39,7 @@ #include "core/string/ustring.h" #include "core/templates/hash_map.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/templates/vector.h" #include "core/variant/variant.h" #include "gdscript_cache.h" @@ -132,7 +132,7 @@ public: ClassNode *class_type = nullptr; MethodInfo method_info; // For callable/signals. - OrderedHashMap<StringName, int> enum_values; // For enums. + HashMap<StringName, int> enum_values; // For enums. _FORCE_INLINE_ bool is_set() const { return kind != UNRESOLVED; } _FORCE_INLINE_ bool has_no_type() const { return type_source == UNDETECTED; } @@ -360,6 +360,7 @@ public: OP_MULTIPLICATION, OP_DIVISION, OP_MODULO, + OP_POWER, OP_BIT_SHIFT_LEFT, OP_BIT_SHIFT_RIGHT, OP_BIT_AND, @@ -393,6 +394,7 @@ public: OP_MULTIPLICATION, OP_DIVISION, OP_MODULO, + OP_POWER, OP_BIT_LEFT_SHIFT, OP_BIT_RIGHT_SHIFT, OP_BIT_AND, @@ -800,7 +802,7 @@ public: FunctionNode *function = nullptr; FunctionNode *parent_function = nullptr; Vector<IdentifierNode *> captures; - Map<StringName, int> captures_indices; + HashMap<StringName, int> captures_indices; bool use_self = false; bool has_name() const { @@ -1203,9 +1205,9 @@ private: List<ParserError> errors; #ifdef DEBUG_ENABLED List<GDScriptWarning> warnings; - Set<String> ignored_warnings; - Set<uint32_t> ignored_warning_codes; - Set<int> unsafe_lines; + RBSet<String> ignored_warnings; + RBSet<uint32_t> ignored_warning_codes; + RBSet<int> unsafe_lines; #endif GDScriptTokenizer tokenizer; @@ -1263,6 +1265,7 @@ private: PREC_FACTOR, PREC_SIGN, PREC_BIT_NOT, + PREC_POWER, PREC_TYPE_TEST, PREC_AWAIT, PREC_CALL, @@ -1416,7 +1419,7 @@ public: } #ifdef DEBUG_ENABLED const List<GDScriptWarning> &get_warnings() const { return warnings; } - const Set<int> &get_unsafe_lines() const { return unsafe_lines; } + const RBSet<int> &get_unsafe_lines() const { return unsafe_lines; } int get_last_line_number() const { return current.end_line; } #endif diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 63fad0d9bb..6c17afe939 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -67,6 +67,7 @@ static const char *token_names[] = { "+", // PLUS, "-", // MINUS, "*", // STAR, + "**", // STAR_STAR, "/", // SLASH, "%", // PERCENT, // Assignment @@ -74,6 +75,7 @@ static const char *token_names[] = { "+=", // PLUS_EQUAL, "-=", // MINUS_EQUAL, "*=", // STAR_EQUAL, + "**=", // STAR_STAR_EQUAL, "/=", // SLASH_EQUAL, "%=", // PERCENT_EQUAL, "<<=", // LESS_LESS_EQUAL, @@ -1403,6 +1405,14 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() { if (_peek() == '=') { _advance(); return make_token(Token::STAR_EQUAL); + } else if (_peek() == '*') { + if (_peek(1) == '=') { + _advance(); + _advance(); // Advance both '*' and '=' + return make_token(Token::STAR_STAR_EQUAL); + } + _advance(); + return make_token(Token::STAR_STAR); } else { return make_token(Token::STAR); } diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index abd090e381..ad818cf812 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -31,9 +31,9 @@ #ifndef GDSCRIPT_TOKENIZER_H #define GDSCRIPT_TOKENIZER_H +#include "core/templates/hash_map.h" #include "core/templates/list.h" -#include "core/templates/map.h" -#include "core/templates/set.h" +#include "core/templates/rb_set.h" #include "core/templates/vector.h" #include "core/variant/variant.h" @@ -78,6 +78,7 @@ public: PLUS, MINUS, STAR, + STAR_STAR, SLASH, PERCENT, // Assignment @@ -85,6 +86,7 @@ public: PLUS_EQUAL, MINUS_EQUAL, STAR_EQUAL, + STAR_STAR_EQUAL, SLASH_EQUAL, PERCENT_EQUAL, LESS_LESS_EQUAL, @@ -191,7 +193,7 @@ public: new_line = p_new_line; } }; - const Map<int, CommentData> &get_comments() const { + const HashMap<int, CommentData> &get_comments() const { return comments; } #endif // TOOLS_ENABLED @@ -224,7 +226,7 @@ private: int length = 0; #ifdef TOOLS_ENABLED - Map<int, CommentData> comments; + HashMap<int, CommentData> comments; #endif // TOOLS_ENABLED _FORCE_INLINE_ bool _is_at_end() { return position >= length; } diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index e28dd26c28..8f85d8159b 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -546,33 +546,32 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a memnew_placement(&stack[i], Variant); } - memnew_placement(&stack[ADDR_STACK_NIL], Variant); - if (_instruction_args_size) { instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size]; } else { instruction_args = nullptr; } - if (p_instance) { - memnew_placement(&stack[ADDR_STACK_SELF], Variant(p_instance->owner)); - script = p_instance->script.ptr(); - } else { - memnew_placement(&stack[ADDR_STACK_SELF], Variant); - script = _script; + for (const KeyValue<int, Variant::Type> &E : temporary_slots) { + type_init_function_table[E.value](&stack[E.key]); } } + if (_ptrcall_args_size) { call_args_ptr = (const void **)alloca(_ptrcall_args_size * sizeof(void *)); } else { call_args_ptr = nullptr; } - memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script)); - - for (const KeyValue<int, Variant::Type> &E : temporary_slots) { - type_init_function_table[E.value](&stack[E.key]); + if (p_instance) { + memnew_placement(&stack[ADDR_STACK_SELF], Variant(p_instance->owner)); + script = p_instance->script.ptr(); + } else { + memnew_placement(&stack[ADDR_STACK_SELF], Variant); + script = _script; } + memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script)); + memnew_placement(&stack[ADDR_STACK_NIL], Variant); String err_text; @@ -2104,7 +2103,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a const GDScript *gds = _script; - const Map<StringName, GDScriptFunction *>::Element *E = nullptr; + HashMap<StringName, GDScriptFunction *>::ConstIterator E; while (gds->base.ptr()) { gds = gds->base.ptr(); E = gds->member_functions.find(*methodname); @@ -2116,7 +2115,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a Callable::CallError err; if (E) { - *dst = E->get()->call(p_instance, (const Variant **)argptrs, argc, err); + *dst = E->value->call(p_instance, (const Variant **)argptrs, argc, err); } else if (gds->native.ptr()) { if (*methodname != GDScriptLanguage::get_singleton()->strings._init) { MethodBind *mb = ClassDB::get_method(gds->native->get_name(), *methodname); @@ -2171,8 +2170,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a // Is this even possible to be null at this point? if (obj) { if (obj->is_class_ptr(GDScriptFunctionState::get_class_ptr_static())) { - static StringName completed = _scs_create("completed"); - result = Signal(obj, completed); + result = Signal(obj, "completed"); } } } @@ -2193,8 +2191,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a gdfs->function = this; gdfs->state.stack.resize(alloca_size); - //copy variant stack - for (int i = 0; i < _stack_size; i++) { + + // First 3 stack addresses are special, so we just skip them here. + for (int i = 3; i < _stack_size; i++) { memnew_placement(&gdfs->state.stack.write[sizeof(Variant) * i], Variant(stack[i])); } gdfs->state.stack_size = _stack_size; @@ -3451,26 +3450,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GDScriptLanguage::get_singleton()->script_frame_time += time_taken - function_call_time; } - // Check if this is the last time the function is resuming from await - // Will be true if never awaited as well - // When it's the last resume it will postpone the exit from stack, - // so the debugger knows which function triggered the resume of the next function (if any) - if (!p_state || awaited) { + // Check if this function has been interrupted by `await`. + // If that is the case we want to keep it in the debugger until it actually exits. + // This ensures the call stack can be properly shown when using `await`, showing what resumed the function. + if (!awaited) { if (EngineDebugger::is_active()) { GDScriptLanguage::get_singleton()->exit_function(); } + } #endif - if (_stack_size) { - //free stack - for (int i = 0; i < _stack_size; i++) { - stack[i].~Variant(); - } + // Clear the stack even if there was an `await`. + // The stack saved in the state is a copy, so this needs to be destructed to avoid leaks. + if (_stack_size) { + // Free stack. + for (int i = 0; i < _stack_size; i++) { + stack[i].~Variant(); } - -#ifdef DEBUG_ENABLED } -#endif return retvalue; } diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 5516f59fe9..d3c5fed95a 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -89,16 +89,16 @@ void ExtendGDScriptParser::update_symbols() { for (int i = 0; i < class_symbol.children.size(); i++) { const lsp::DocumentSymbol &symbol = class_symbol.children[i]; - members.set(symbol.name, &symbol); + members.insert(symbol.name, &symbol); // cache level one inner classes if (symbol.kind == lsp::SymbolKind::Class) { ClassMembers inner_class; for (int j = 0; j < symbol.children.size(); j++) { const lsp::DocumentSymbol &s = symbol.children[j]; - inner_class.set(s.name, &s); + inner_class.insert(s.name, &s); } - inner_classes.set(symbol.name, inner_class); + inner_classes.insert(symbol.name, inner_class); } } } @@ -216,8 +216,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p if (res.is_valid() && !res->get_path().is_empty()) { value_text = "preload(\"" + res->get_path() + "\")"; if (symbol.documentation.is_empty()) { - if (Map<String, ExtendGDScriptParser *>::Element *S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) { - symbol.documentation = S->get()->class_symbol.documentation; + if (HashMap<String, ExtendGDScriptParser *>::Iterator S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) { + symbol.documentation = S->value->class_symbol.documentation; } } } else { @@ -661,30 +661,22 @@ const List<lsp::DocumentLink> &ExtendGDScriptParser::get_document_links() const const Array &ExtendGDScriptParser::get_member_completions() { if (member_completions.is_empty()) { - const String *name = members.next(nullptr); - while (name) { - const lsp::DocumentSymbol *symbol = members.get(*name); + for (const KeyValue<String, const lsp::DocumentSymbol *> &E : members) { + const lsp::DocumentSymbol *symbol = E.value; lsp::CompletionItem item = symbol->make_completion_item(); - item.data = JOIN_SYMBOLS(path, *name); + item.data = JOIN_SYMBOLS(path, E.key); member_completions.push_back(item.to_json()); - - name = members.next(name); } - const String *_class = inner_classes.next(nullptr); - while (_class) { - const ClassMembers *inner_class = inner_classes.getptr(*_class); - const String *member_name = inner_class->next(nullptr); - while (member_name) { - const lsp::DocumentSymbol *symbol = inner_class->get(*member_name); + for (const KeyValue<String, ClassMembers> &E : inner_classes) { + const ClassMembers *inner_class = &E.value; + + for (const KeyValue<String, const lsp::DocumentSymbol *> &F : *inner_class) { + const lsp::DocumentSymbol *symbol = F.value; lsp::CompletionItem item = symbol->make_completion_item(); - item.data = JOIN_SYMBOLS(path, JOIN_SYMBOLS(*_class, *member_name)); + item.data = JOIN_SYMBOLS(path, JOIN_SYMBOLS(E.key, F.key)); member_completions.push_back(item.to_json()); - - member_name = inner_class->next(member_name); } - - _class = inner_classes.next(_class); } } diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index cdddab319d..7460f8edff 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -126,7 +126,7 @@ Error GDScriptLanguageProtocol::on_client_connected() { ERR_FAIL_COND_V_MSG(clients.size() >= LSP_MAX_CLIENTS, FAILED, "Max client limits reached"); Ref<LSPeer> peer = memnew(LSPeer); peer->connection = tcp_peer; - clients.set(next_client_id, peer); + clients.insert(next_client_id, peer); next_client_id++; EditorNode::get_log()->add_message("[LSP] Connection Taken", EditorLog::MSG_TYPE_EDITOR); return OK; @@ -229,28 +229,33 @@ void GDScriptLanguageProtocol::poll() { if (server->is_connection_available()) { on_client_connected(); } - const int *id = nullptr; - while ((id = clients.next(id))) { - Ref<LSPeer> peer = clients.get(*id); + + HashMap<int, Ref<LSPeer>>::Iterator E = clients.begin(); + while (E != clients.end()) { + Ref<LSPeer> peer = E->value; StreamPeerTCP::Status status = peer->connection->get_status(); if (status == StreamPeerTCP::STATUS_NONE || status == StreamPeerTCP::STATUS_ERROR) { - on_client_disconnected(*id); - id = nullptr; + on_client_disconnected(E->key); + E = clients.begin(); + continue; } else { if (peer->connection->get_available_bytes() > 0) { - latest_client_id = *id; + latest_client_id = E->key; Error err = peer->handle_data(); if (err != OK && err != ERR_BUSY) { - on_client_disconnected(*id); - id = nullptr; + on_client_disconnected(E->key); + E = clients.begin(); + continue; } } Error err = peer->send_data(); if (err != OK && err != ERR_BUSY) { - on_client_disconnected(*id); - id = nullptr; + on_client_disconnected(E->key); + E = clients.begin(); + continue; } } + ++E; } } @@ -259,9 +264,8 @@ Error GDScriptLanguageProtocol::start(int p_port, const IPAddress &p_bind_ip) { } void GDScriptLanguageProtocol::stop() { - const int *id = nullptr; - while ((id = clients.next(id))) { - Ref<LSPeer> peer = clients.get(*id); + for (const KeyValue<int, Ref<LSPeer>> &E : clients) { + Ref<LSPeer> peer = clients.get(E.key); peer->connection->disconnect_from_host(); } diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index c42bd58aeb..d763701911 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -109,23 +109,15 @@ void GDScriptTextDocument::notify_client_show_symbol(const lsp::DocumentSymbol * void GDScriptTextDocument::initialize() { if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) { - const HashMap<StringName, ClassMembers> &native_members = GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members; + for (const KeyValue<StringName, ClassMembers> &E : GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members) { + const ClassMembers &members = E.value; - const StringName *class_ptr = native_members.next(nullptr); - while (class_ptr) { - const ClassMembers &members = native_members.get(*class_ptr); - - const String *name = members.next(nullptr); - while (name) { - const lsp::DocumentSymbol *symbol = members.get(*name); + for (const KeyValue<String, const lsp::DocumentSymbol *> &F : members) { + const lsp::DocumentSymbol *symbol = members.get(F.key); lsp::CompletionItem item = symbol->make_completion_item(); - item.data = JOIN_SYMBOLS(String(*class_ptr), *name); + item.data = JOIN_SYMBOLS(String(E.key), F.key); native_member_completions.push_back(item.to_json()); - - name = members.next(name); } - - class_ptr = native_members.next(class_ptr); } } } @@ -149,9 +141,9 @@ Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) { String uri = params["uri"]; String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(uri); Array arr; - if (const Map<String, ExtendGDScriptParser *>::Element *parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(path)) { + if (HashMap<String, ExtendGDScriptParser *>::ConstIterator parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(path)) { Vector<lsp::DocumentedSymbolInformation> list; - parser->get()->get_symbols().symbol_tree_as_list(uri, list); + parser->value->get_symbols().symbol_tree_as_list(uri, list); for (int i = 0; i < list.size(); i++) { arr.push_back(list[i].to_json()); } @@ -275,8 +267,8 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) { } if (!symbol) { - if (const Map<String, ExtendGDScriptParser *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(class_name)) { - symbol = E->get()->get_member_symbol(member_name, inner_class_name); + if (HashMap<String, ExtendGDScriptParser *>::ConstIterator E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(class_name)) { + symbol = E->value->get_member_symbol(member_name, inner_class_name); } } } diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index 89ee6b35e5..d9de112bb0 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -116,22 +116,22 @@ void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) { } void GDScriptWorkspace::remove_cache_parser(const String &p_path) { - Map<String, ExtendGDScriptParser *>::Element *parser = parse_results.find(p_path); - Map<String, ExtendGDScriptParser *>::Element *script = scripts.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator parser = parse_results.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator script = scripts.find(p_path); if (parser && script) { - if (script->get() && script->get() == parser->get()) { - memdelete(script->get()); + if (script->value && script->value == parser->value) { + memdelete(script->value); } else { - memdelete(script->get()); - memdelete(parser->get()); + memdelete(script->value); + memdelete(parser->value); } parse_results.erase(p_path); scripts.erase(p_path); } else if (parser) { - memdelete(parser->get()); + memdelete(parser->value); parse_results.erase(p_path); } else if (script) { - memdelete(script->get()); + memdelete(script->value); scripts.erase(p_path); } } @@ -141,8 +141,8 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_ StringName empty; while (class_name != empty) { - if (const Map<StringName, lsp::DocumentSymbol>::Element *E = native_symbols.find(class_name)) { - const lsp::DocumentSymbol &class_symbol = E->value(); + if (HashMap<StringName, lsp::DocumentSymbol>::ConstIterator E = native_symbols.find(class_name)) { + const lsp::DocumentSymbol &class_symbol = E->value; if (p_member.is_empty()) { return &class_symbol; @@ -162,9 +162,9 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_ } const lsp::DocumentSymbol *GDScriptWorkspace::get_script_symbol(const String &p_path) const { - const Map<String, ExtendGDScriptParser *>::Element *S = scripts.find(p_path); + HashMap<String, ExtendGDScriptParser *>::ConstIterator S = scripts.find(p_path); if (S) { - return &(S->get()->get_symbols()); + return &(S->value->get_symbols()); } return nullptr; } @@ -209,10 +209,10 @@ void GDScriptWorkspace::reload_all_workspace_scripts() { err = parse_script(path, content); if (err != OK) { - Map<String, ExtendGDScriptParser *>::Element *S = parse_results.find(path); + HashMap<String, ExtendGDScriptParser *>::Iterator S = parse_results.find(path); String err_msg = "Failed parse script " + path; if (S) { - err_msg += "\n" + S->get()->get_errors()[0].message; + err_msg += "\n" + S->value->get_errors()[0].message; } ERR_CONTINUE_MSG(err != OK, err_msg); } @@ -238,25 +238,25 @@ void GDScriptWorkspace::list_script_files(const String &p_root_dir, List<String> } ExtendGDScriptParser *GDScriptWorkspace::get_parse_successed_script(const String &p_path) { - const Map<String, ExtendGDScriptParser *>::Element *S = scripts.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator S = scripts.find(p_path); if (!S) { parse_local_script(p_path); S = scripts.find(p_path); } if (S) { - return S->get(); + return S->value; } return nullptr; } ExtendGDScriptParser *GDScriptWorkspace::get_parse_result(const String &p_path) { - const Map<String, ExtendGDScriptParser *>::Element *S = parse_results.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator S = parse_results.find(p_path); if (!S) { parse_local_script(p_path); S = parse_results.find(p_path); } if (S) { - return S->get(); + return S->value; } return nullptr; } @@ -404,9 +404,9 @@ Error GDScriptWorkspace::initialize() { const lsp::DocumentSymbol &class_symbol = E.value; for (int i = 0; i < class_symbol.children.size(); i++) { const lsp::DocumentSymbol &symbol = class_symbol.children[i]; - members.set(symbol.name, &symbol); + members.insert(symbol.name, &symbol); } - native_members.set(E.key, members); + native_members.insert(E.key, members); } // cache member completions @@ -424,8 +424,8 @@ Error GDScriptWorkspace::initialize() { Error GDScriptWorkspace::parse_script(const String &p_path, const String &p_content) { ExtendGDScriptParser *parser = memnew(ExtendGDScriptParser); Error err = parser->parse(p_content, p_path); - Map<String, ExtendGDScriptParser *>::Element *last_parser = parse_results.find(p_path); - Map<String, ExtendGDScriptParser *>::Element *last_script = scripts.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator last_parser = parse_results.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator last_script = scripts.find(p_path); if (err == OK) { remove_cache_parser(p_path); @@ -433,8 +433,8 @@ Error GDScriptWorkspace::parse_script(const String &p_path, const String &p_cont scripts[p_path] = parser; } else { - if (last_parser && last_script && last_parser->get() != last_script->get()) { - memdelete(last_parser->get()); + if (last_parser && last_script && last_parser->value != last_script->value) { + memdelete(last_parser->value); } parse_results[p_path] = parser; } @@ -513,9 +513,9 @@ String GDScriptWorkspace::get_file_uri(const String &p_path) const { void GDScriptWorkspace::publish_diagnostics(const String &p_path) { Dictionary params; Array errors; - const Map<String, ExtendGDScriptParser *>::Element *ele = parse_results.find(p_path); + HashMap<String, ExtendGDScriptParser *>::ConstIterator ele = parse_results.find(p_path); if (ele) { - const Vector<lsp::Diagnostic> &list = ele->get()->get_diagnostics(); + const Vector<lsp::Diagnostic> &list = ele->value->get_diagnostics(); errors.resize(list.size()); for (int i = 0; i < list.size(); ++i) { errors[i] = list[i].to_json(); @@ -682,13 +682,11 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP Vector2i offset; symbol_identifier = parser->get_identifier_under_position(p_doc_pos.position, offset); - const StringName *class_ptr = native_members.next(nullptr); - while (class_ptr) { - const ClassMembers &members = native_members.get(*class_ptr); + for (const KeyValue<StringName, ClassMembers> &E : native_members) { + const ClassMembers &members = native_members.get(E.key); if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) { r_list.push_back(*symbol); } - class_ptr = native_members.next(class_ptr); } for (const KeyValue<String, ExtendGDScriptParser *> &E : scripts) { @@ -698,23 +696,19 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP r_list.push_back(*symbol); } - const HashMap<String, ClassMembers> &inner_classes = script->get_inner_classes(); - const String *_class = inner_classes.next(nullptr); - while (_class) { - const ClassMembers *inner_class = inner_classes.getptr(*_class); + for (const KeyValue<String, ClassMembers> &F : script->get_inner_classes()) { + const ClassMembers *inner_class = &F.value; if (const lsp::DocumentSymbol *const *symbol = inner_class->getptr(symbol_identifier)) { r_list.push_back(*symbol); } - - _class = inner_classes.next(_class); } } } } const lsp::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const lsp::NativeSymbolInspectParams &p_params) { - if (Map<StringName, lsp::DocumentSymbol>::Element *E = native_symbols.find(p_params.native_class)) { - const lsp::DocumentSymbol &symbol = E->get(); + if (HashMap<StringName, lsp::DocumentSymbol>::Iterator E = native_symbols.find(p_params.native_class)) { + const lsp::DocumentSymbol &symbol = E->value; if (p_params.symbol_name.is_empty() || p_params.symbol_name == symbol.name) { return &symbol; } @@ -790,7 +784,7 @@ GDScriptWorkspace::GDScriptWorkspace() { } GDScriptWorkspace::~GDScriptWorkspace() { - Set<String> cached_parsers; + RBSet<String> cached_parsers; for (const KeyValue<String, ExtendGDScriptParser *> &E : parse_results) { cached_parsers.insert(E.key); @@ -800,7 +794,7 @@ GDScriptWorkspace::~GDScriptWorkspace() { cached_parsers.insert(E.key); } - for (Set<String>::Element *E = cached_parsers.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = cached_parsers.front(); E; E = E->next()) { remove_cache_parser(E->get()); } } diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h index 92e78f8992..7bff5db81f 100644 --- a/modules/gdscript/language_server/gdscript_workspace.h +++ b/modules/gdscript/language_server/gdscript_workspace.h @@ -48,7 +48,7 @@ protected: static void _bind_methods(); void remove_cache_parser(const String &p_path); bool initialized = false; - Map<StringName, lsp::DocumentSymbol> native_symbols; + HashMap<StringName, lsp::DocumentSymbol> native_symbols; const lsp::DocumentSymbol *get_native_symbol(const String &p_class, const String &p_member = "") const; const lsp::DocumentSymbol *get_script_symbol(const String &p_path) const; @@ -68,8 +68,8 @@ public: String root; String root_uri; - Map<String, ExtendGDScriptParser *> scripts; - Map<String, ExtendGDScriptParser *> parse_results; + HashMap<String, ExtendGDScriptParser *> scripts; + HashMap<String, ExtendGDScriptParser *> parse_results; HashMap<StringName, ClassMembers> native_members; public: diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp index a63f9df918..d4aa207972 100644 --- a/modules/gdscript/language_server/lsp.hpp +++ b/modules/gdscript/language_server/lsp.hpp @@ -261,7 +261,7 @@ struct WorkspaceEdit { /** * Holds changes to existing resources. */ - Map<String, Vector<TextEdit>> changes; + HashMap<String, Vector<TextEdit>> changes; _FORCE_INLINE_ void add_edit(const String &uri, const TextEdit &edit) { if (changes.has(uri)) { @@ -293,8 +293,8 @@ struct WorkspaceEdit { } _FORCE_INLINE_ void add_change(const String &uri, const int &line, const int &start_character, const int &end_character, const String &new_text) { - if (Map<String, Vector<TextEdit>>::Element *E = changes.find(uri)) { - Vector<TextEdit> edit_list = E->value(); + if (HashMap<String, Vector<TextEdit>>::Iterator E = changes.find(uri)) { + Vector<TextEdit> edit_list = E->value; for (int i = 0; i < edit_list.size(); ++i) { TextEdit edit = edit_list[i]; if (edit.range.start.character == start_character) { @@ -310,8 +310,8 @@ struct WorkspaceEdit { new_edit.range.end.line = line; new_edit.range.end.character = end_character; - if (Map<String, Vector<TextEdit>>::Element *E = changes.find(uri)) { - E->value().push_back(new_edit); + if (HashMap<String, Vector<TextEdit>>::Iterator E = changes.find(uri)) { + E->value.push_back(new_edit); } else { Vector<TextEdit> edit_list; edit_list.push_back(new_edit); diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 59acb1c064..7cedbda804 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -70,7 +70,7 @@ class EditorExportGDScript : public EditorExportPlugin { GDCLASS(EditorExportGDScript, EditorExportPlugin); public: - virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features) override { + virtual void _export_file(const String &p_path, const String &p_type, const RBSet<String> &p_features) override { int script_mode = EditorExportPreset::MODE_SCRIPT_COMPILED; String script_key; diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index ea51990237..de5cd10e7c 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -48,11 +48,11 @@ namespace GDScriptTests { void init_autoloads() { - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); // First pass, add the constants so they exist before any script is loaded. - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - const ProjectSettings::AutoloadInfo &info = E.get(); + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { + const ProjectSettings::AutoloadInfo &info = E.value; if (info.is_singleton) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { @@ -62,8 +62,8 @@ void init_autoloads() { } // Second pass, load into global constants. - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - const ProjectSettings::AutoloadInfo &info = E.get(); + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { + const ProjectSettings::AutoloadInfo &info = E.value; if (!info.is_singleton) { // Skip non-singletons since we don't have a scene tree here anyway. @@ -543,8 +543,8 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) { return result; } // Test running. - const Map<StringName, GDScriptFunction *>::Element *test_function_element = script->get_member_functions().find(GDScriptTestRunner::test_function_name); - if (test_function_element == nullptr) { + const HashMap<StringName, GDScriptFunction *>::ConstIterator test_function_element = script->get_member_functions().find(GDScriptTestRunner::test_function_name); + if (!test_function_element) { enable_stdout(); result.status = GDTEST_LOAD_ERROR; result.output = ""; diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.gd b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.gd new file mode 100644 index 0000000000..631e7be5ce --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.gd @@ -0,0 +1,14 @@ +func test(): + var instance := Parent.new() + instance.my_function({"a": 1}) + instance = Child.new() + instance.my_function({"a": 1}) + print("No failure") + +class Parent: + func my_function(_par1: Dictionary = {}) -> void: + pass + +class Child extends Parent: + func my_function(_par1: Dictionary = {}) -> void: + pass diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.out b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.out new file mode 100644 index 0000000000..67f0045867 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.out @@ -0,0 +1,2 @@ +GDTEST_OK +No failure diff --git a/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd new file mode 100644 index 0000000000..4608c778aa --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd @@ -0,0 +1,4 @@ +func test(): + match 1: + [[[var a]]], 2: + pass diff --git a/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.out b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.out new file mode 100644 index 0000000000..1cdc24683b --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Cannot use a variable bind with multiple patterns. diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd new file mode 100644 index 0000000000..a0ae7fb17c --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd @@ -0,0 +1,6 @@ +func test(): + match [1, 2, 3]: + [var a, var b, var c]: + print(a == 1) + print(b == 2) + print(c == 3) diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.out b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.out new file mode 100644 index 0000000000..316db6d748 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.out @@ -0,0 +1,4 @@ +GDTEST_OK +true +true +true diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 173d5131cf..63f446561a 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -58,7 +58,7 @@ void EditorSceneFormatImporterBlend::get_extensions(List<String> *r_extensions) } Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_t p_flags, - const Map<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { // Get global paths for source and sink. @@ -239,7 +239,7 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ } Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, - const Map<StringName, Variant> &p_options) { + const HashMap<StringName, Variant> &p_options) { if (p_path.get_extension().to_lower() != "blend") { return true; } diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h index 0925333a28..dd1c1b9889 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.h +++ b/modules/gltf/editor/editor_scene_importer_blend.h @@ -66,12 +66,12 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, - const Map<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) override; virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, - const Map<StringName, Variant> &p_options) override; + const HashMap<StringName, Variant> &p_options) override; }; class LineEdit; diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp index 893d2efcec..faad2d315d 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.cpp +++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp @@ -30,7 +30,7 @@ #include "editor_scene_importer_fbx.h" -#if TOOLS_ENABLED +#ifdef TOOLS_ENABLED #include "../gltf_document.h" #include "../gltf_state.h" @@ -49,7 +49,7 @@ void EditorSceneFormatImporterFBX::get_extensions(List<String> *r_extensions) co } Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t p_flags, - const Map<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { // Get global paths for source and sink. @@ -106,7 +106,7 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t } Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, bool p_for_animation, - const String &p_option, const Map<StringName, Variant> &p_options) { + const String &p_option, const HashMap<StringName, Variant> &p_options) { return true; } diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/editor/editor_scene_importer_fbx.h index 84de7fd1cc..b0039b1c8f 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.h +++ b/modules/gltf/editor/editor_scene_importer_fbx.h @@ -45,12 +45,12 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, - const Map<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) override; virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, - const Map<StringName, Variant> &p_options) override; + const HashMap<StringName, Variant> &p_options) override; }; #endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor/editor_scene_importer_gltf.cpp index 5e7811ad2b..d5b247fc6e 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.cpp +++ b/modules/gltf/editor/editor_scene_importer_gltf.cpp @@ -48,7 +48,7 @@ void EditorSceneFormatImporterGLTF::get_extensions(List<String> *r_extensions) c } Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t p_flags, - const Map<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { Ref<GLTFDocument> doc; doc.instantiate(); diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor/editor_scene_importer_gltf.h index b714ada124..edca038532 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.h +++ b/modules/gltf/editor/editor_scene_importer_gltf.h @@ -45,7 +45,7 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, - const Map<StringName, Variant> &p_options, int p_bake_fps, + const HashMap<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; }; diff --git a/modules/gltf/gltf_animation.cpp b/modules/gltf/gltf_animation.cpp index c857be4b2c..e598c870ab 100644 --- a/modules/gltf/gltf_animation.cpp +++ b/modules/gltf/gltf_animation.cpp @@ -45,7 +45,7 @@ void GLTFAnimation::set_loop(bool p_val) { loop = p_val; } -Map<int, GLTFAnimation::Track> &GLTFAnimation::get_tracks() { +HashMap<int, GLTFAnimation::Track> &GLTFAnimation::get_tracks() { return tracks; } diff --git a/modules/gltf/gltf_animation.h b/modules/gltf/gltf_animation.h index ba8ae8a273..8688ddb937 100644 --- a/modules/gltf/gltf_animation.h +++ b/modules/gltf/gltf_animation.h @@ -64,11 +64,11 @@ public: public: bool get_loop() const; void set_loop(bool p_val); - Map<int, GLTFAnimation::Track> &get_tracks(); + HashMap<int, GLTFAnimation::Track> &get_tracks(); GLTFAnimation(); private: bool loop = false; - Map<int, Track> tracks; + HashMap<int, Track> tracks; }; #endif // GLTF_ANIMATION_H diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 082b4ce1ec..f440a29f28 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -2294,7 +2294,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { attributes["COLOR_0"] = _encode_accessor_as_color(state, a, true); } } - Map<int, int> joint_i_to_bone_i; + HashMap<int, int> joint_i_to_bone_i; for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) { GLTFSkinIndex skin_i = -1; if (state->nodes[node_i]->mesh == gltf_mesh_i) { @@ -2468,9 +2468,9 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { mat = import_mesh->get_surface_material(surface_i); } if (mat.is_valid()) { - Map<Ref<BaseMaterial3D>, GLTFMaterialIndex>::Element *material_cache_i = state->material_cache.find(mat); - if (material_cache_i && material_cache_i->get() != -1) { - primitive["material"] = material_cache_i->get(); + HashMap<Ref<BaseMaterial3D>, GLTFMaterialIndex>::Iterator material_cache_i = state->material_cache.find(mat); + if (material_cache_i && material_cache_i->value != -1) { + primitive["material"] = material_cache_i->value; } else { GLTFMaterialIndex mat_i = state->materials.size(); state->materials.push_back(mat); @@ -5904,9 +5904,9 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, Node *root = ap->get_parent(); ERR_FAIL_COND(root == nullptr); - Map<GLTFNodeIndex, Node *>::Element *node_element = state->scene_nodes.find(node_index); - ERR_CONTINUE_MSG(node_element == nullptr, vformat("Unable to find node %d for animation", node_index)); - node_path = root->get_path_to(node_element->get()); + HashMap<GLTFNodeIndex, Node *>::Iterator node_element = state->scene_nodes.find(node_index); + ERR_CONTINUE_MSG(!node_element, vformat("Unable to find node %d for animation", node_index)); + node_path = root->get_path_to(node_element->value); if (gltf_node->skeleton >= 0) { const Skeleton3D *sk = state->skeletons[gltf_node->skeleton]->godot_skeleton; @@ -6116,11 +6116,11 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) { if (node->mesh < 0) { continue; } - Map<GLTFNodeIndex, Node *>::Element *mi_element = state->scene_nodes.find(mi_node_i); + HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = state->scene_nodes.find(mi_node_i); if (!mi_element) { continue; } - MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->get()); + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->value); if (!mi) { continue; } @@ -6250,11 +6250,11 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_roo if (node->skin >= 0 && node->mesh >= 0) { const GLTFSkinIndex skin_i = node->skin; - Map<GLTFNodeIndex, Node *>::Element *mi_element = state->scene_nodes.find(node_i); - ERR_CONTINUE_MSG(mi_element == nullptr, vformat("Unable to find node %d", node_i)); + HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = state->scene_nodes.find(node_i); + ERR_CONTINUE_MSG(!mi_element, vformat("Unable to find node %d", node_i)); - ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(mi_element->get()); - ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to ImporterMeshInstance3D", node_i, mi_element->get()->get_class_name())); + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(mi_element->value); + ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to ImporterMeshInstance3D", node_i, mi_element->value->get_class_name())); const GLTFSkeletonIndex skel_i = state->skins.write[node->skin]->skeleton; Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i]; @@ -6436,10 +6436,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, for (const KeyValue<GLTFNodeIndex, Node *> &position_scene_node_i : state->scene_nodes) { if (position_scene_node_i.value == node) { GLTFNodeIndex node_index = position_scene_node_i.key; - Map<int, GLTFAnimation::Track>::Element *position_track_i = gltf_animation->get_tracks().find(node_index); + HashMap<int, GLTFAnimation::Track>::Iterator position_track_i = gltf_animation->get_tracks().find(node_index); GLTFAnimation::Track track; if (position_track_i) { - track = position_track_i->get(); + track = position_track_i->value; } track = _convert_animation_track(state, track, animation, track_i, node_index); gltf_animation->get_tracks().insert(node_index, track); @@ -6452,10 +6452,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, for (const KeyValue<GLTFNodeIndex, Node *> &rotation_degree_scene_node_i : state->scene_nodes) { if (rotation_degree_scene_node_i.value == node) { GLTFNodeIndex node_index = rotation_degree_scene_node_i.key; - Map<int, GLTFAnimation::Track>::Element *rotation_degree_track_i = gltf_animation->get_tracks().find(node_index); + HashMap<int, GLTFAnimation::Track>::Iterator rotation_degree_track_i = gltf_animation->get_tracks().find(node_index); GLTFAnimation::Track track; if (rotation_degree_track_i) { - track = rotation_degree_track_i->get(); + track = rotation_degree_track_i->value; } track = _convert_animation_track(state, track, animation, track_i, node_index); gltf_animation->get_tracks().insert(node_index, track); @@ -6468,10 +6468,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, for (const KeyValue<GLTFNodeIndex, Node *> &scale_scene_node_i : state->scene_nodes) { if (scale_scene_node_i.value == node) { GLTFNodeIndex node_index = scale_scene_node_i.key; - Map<int, GLTFAnimation::Track>::Element *scale_track_i = gltf_animation->get_tracks().find(node_index); + HashMap<int, GLTFAnimation::Track>::Iterator scale_track_i = gltf_animation->get_tracks().find(node_index); GLTFAnimation::Track track; if (scale_track_i) { - track = scale_track_i->get(); + track = scale_track_i->value; } track = _convert_animation_track(state, track, animation, track_i, node_index); gltf_animation->get_tracks().insert(node_index, track); @@ -6503,7 +6503,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, } } ERR_CONTINUE(mesh_index == -1); - Map<int, GLTFAnimation::Track> &tracks = gltf_animation->get_tracks(); + HashMap<int, GLTFAnimation::Track> &tracks = gltf_animation->get_tracks(); GLTFAnimation::Track track = gltf_animation->get_tracks().has(mesh_index) ? gltf_animation->get_tracks()[mesh_index] : GLTFAnimation::Track(); if (!tracks.has(mesh_index)) { for (int32_t shape_i = 0; shape_i < mesh->get_blend_shape_count(); shape_i++) { @@ -6565,10 +6565,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, continue; } GLTFNodeIndex node_i = skeleton_gltf->godot_bone_node[bone]; - Map<int, GLTFAnimation::Track>::Element *property_track_i = gltf_animation->get_tracks().find(node_i); + HashMap<int, GLTFAnimation::Track>::Iterator property_track_i = gltf_animation->get_tracks().find(node_i); GLTFAnimation::Track track; if (property_track_i) { - track = property_track_i->get(); + track = property_track_i->value; } track = _convert_animation_track(state, track, animation, track_i, node_i); gltf_animation->get_tracks()[node_i] = track; @@ -6580,10 +6580,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : state->scene_nodes) { if (scene_node_i.value == godot_node) { GLTFNodeIndex node_i = scene_node_i.key; - Map<int, GLTFAnimation::Track>::Element *node_track_i = gltf_animation->get_tracks().find(node_i); + HashMap<int, GLTFAnimation::Track>::Iterator node_track_i = gltf_animation->get_tracks().find(node_i); GLTFAnimation::Track track; if (node_track_i) { - track = node_track_i->get(); + track = node_track_i->value; } track = _convert_animation_track(state, track, animation, track_i, node_i); gltf_animation->get_tracks()[node_i] = track; diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index 19bc507a8d..9db824a0d4 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -135,9 +135,9 @@ private: } template <class T> - static Array to_array(const Set<T> &p_inp) { + static Array to_array(const RBSet<T> &p_inp) { Array ret; - typename Set<T>::Element *elem = p_inp.front(); + typename RBSet<T>::Element *elem = p_inp.front(); while (elem) { ret.push_back(elem->get()); elem = elem->next(); @@ -154,23 +154,23 @@ private: } template <class T> - static void set_from_array(Set<T> &r_out, const Array &p_inp) { + static void set_from_array(RBSet<T> &r_out, const Array &p_inp) { r_out.clear(); for (int i = 0; i < p_inp.size(); i++) { r_out.insert(p_inp[i]); } } template <class K, class V> - static Dictionary to_dict(const Map<K, V> &p_inp) { + static Dictionary to_dict(const HashMap<K, V> &p_inp) { Dictionary ret; - for (typename Map<K, V>::Element *E = p_inp.front(); E; E = E->next()) { - ret[E->key()] = E->value(); + for (const KeyValue<K, V> &E : p_inp) { + ret[E.key] = E.value; } return ret; } template <class K, class V> - static void set_from_dict(Map<K, V> &r_out, const Dictionary &p_inp) { + static void set_from_dict(HashMap<K, V> &r_out, const Dictionary &p_inp) { r_out.clear(); Array keys = p_inp.keys(); for (int i = 0; i < keys.size(); i++) { diff --git a/modules/gltf/gltf_skeleton.cpp b/modules/gltf/gltf_skeleton.cpp index e80376f130..b813f39a27 100644 --- a/modules/gltf/gltf_skeleton.cpp +++ b/modules/gltf/gltf_skeleton.cpp @@ -46,7 +46,7 @@ void GLTFSkeleton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "joints"), "set_joints", "get_joints"); // Vector<GLTFNodeIndex> ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "roots"), "set_roots", "get_roots"); // Vector<GLTFNodeIndex> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_names", "get_unique_names"); // Set<String> - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "godot_bone_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_godot_bone_node", "get_godot_bone_node"); // Map<int32_t, + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "godot_bone_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_godot_bone_node", "get_godot_bone_node"); // RBMap<int32_t, } Vector<GLTFNodeIndex> GLTFSkeleton::get_joints() { diff --git a/modules/gltf/gltf_skeleton.h b/modules/gltf/gltf_skeleton.h index 7d07d528cb..4dcee41465 100644 --- a/modules/gltf/gltf_skeleton.h +++ b/modules/gltf/gltf_skeleton.h @@ -50,9 +50,9 @@ private: Skeleton3D *godot_skeleton = nullptr; // Set of unique bone names for the skeleton - Set<String> unique_names; + RBSet<String> unique_names; - Map<int32_t, GLTFNodeIndex> godot_bone_node; + HashMap<int32_t, GLTFNodeIndex> godot_bone_node; Vector<BoneAttachment3D *> bone_attachments; @@ -78,10 +78,10 @@ public: Array get_unique_names(); void set_unique_names(Array p_unique_names); - //Map<int32_t, GLTFNodeIndex> get_godot_bone_node() { + //RBMap<int32_t, GLTFNodeIndex> get_godot_bone_node() { // return this->godot_bone_node; //} - //void set_godot_bone_node(Map<int32_t, GLTFNodeIndex> p_godot_bone_node) { + //void set_godot_bone_node(RBMap<int32_t, GLTFNodeIndex> p_godot_bone_node) { // this->godot_bone_node = p_godot_bone_node; //} Dictionary get_godot_bone_node(); diff --git a/modules/gltf/gltf_skin.cpp b/modules/gltf/gltf_skin.cpp index 283fc34ff5..e8005aa0c1 100644 --- a/modules/gltf/gltf_skin.cpp +++ b/modules/gltf/gltf_skin.cpp @@ -59,8 +59,8 @@ void GLTFSkin::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "non_joints"), "set_non_joints", "get_non_joints"); // Vector<GLTFNodeIndex> ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "roots"), "set_roots", "get_roots"); // Vector<GLTFNodeIndex> ADD_PROPERTY(PropertyInfo(Variant::INT, "skeleton"), "set_skeleton", "get_skeleton"); // int - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "joint_i_to_bone_i", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_joint_i_to_bone_i", "get_joint_i_to_bone_i"); // Map<int, - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "joint_i_to_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_joint_i_to_name", "get_joint_i_to_name"); // Map<int, + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "joint_i_to_bone_i", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_joint_i_to_bone_i", "get_joint_i_to_bone_i"); // RBMap<int, + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "joint_i_to_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_joint_i_to_name", "get_joint_i_to_name"); // RBMap<int, ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "godot_skin"), "set_godot_skin", "get_godot_skin"); // Ref<Skin> } @@ -130,16 +130,16 @@ void GLTFSkin::set_joint_i_to_bone_i(Dictionary p_joint_i_to_bone_i) { Dictionary GLTFSkin::get_joint_i_to_name() { Dictionary ret; - Map<int, StringName>::Element *elem = joint_i_to_name.front(); + HashMap<int, StringName>::Iterator elem = joint_i_to_name.begin(); while (elem) { - ret[elem->key()] = String(elem->value()); - elem = elem->next(); + ret[elem->key] = String(elem->value); + ++elem; } return ret; } void GLTFSkin::set_joint_i_to_name(Dictionary p_joint_i_to_name) { - joint_i_to_name = Map<int, StringName>(); + joint_i_to_name = HashMap<int, StringName>(); Array keys = p_joint_i_to_name.keys(); for (int i = 0; i < keys.size(); i++) { joint_i_to_name[keys[i]] = p_joint_i_to_name[keys[i]]; diff --git a/modules/gltf/gltf_skin.h b/modules/gltf/gltf_skin.h index 31cb892f19..d946324756 100644 --- a/modules/gltf/gltf_skin.h +++ b/modules/gltf/gltf_skin.h @@ -65,8 +65,8 @@ private: // A mapping from the joint indices (in the order of joints_original) to the // Godot Skeleton's bone_indices - Map<int, int> joint_i_to_bone_i; - Map<int, StringName> joint_i_to_name; + HashMap<int, int> joint_i_to_bone_i; + HashMap<int, StringName> joint_i_to_name; // The Actual Skin that will be created as a mapping between the IBM's of // this skin to the generated skeleton for the mesh instances. diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index 6ead2f69c3..e959a640b4 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -102,7 +102,7 @@ void GLTFState::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_names", "get_unique_names"); // Set<String> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_animation_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_animation_names", "get_unique_animation_names"); // Set<String> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skeletons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeletons", "get_skeletons"); // Vector<Ref<GLTFSkeleton>> - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "skeleton_to_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeleton_to_node", "get_skeleton_to_node"); // Map<GLTFSkeletonIndex, + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "skeleton_to_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeleton_to_node", "get_skeleton_to_node"); // RBMap<GLTFSkeletonIndex, ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_animations", "get_animations"); // Vector<Ref<GLTFAnimation>> } diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 42ca079f1c..f695b20b49 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -45,8 +45,8 @@ #include "gltf_texture.h" #include "core/io/resource.h" -#include "core/templates/map.h" #include "core/templates/pair.h" +#include "core/templates/rb_map.h" #include "core/templates/vector.h" #include "scene/animation/animation_player.h" #include "scene/resources/texture.h" @@ -72,7 +72,7 @@ class GLTFState : public Resource { Vector<Ref<GLTFMesh>> meshes; // meshes are loaded directly, no reason not to. Vector<AnimationPlayer *> animation_players; - Map<Ref<BaseMaterial3D>, GLTFMaterialIndex> material_cache; + HashMap<Ref<BaseMaterial3D>, GLTFMaterialIndex> material_cache; Vector<Ref<BaseMaterial3D>> materials; String scene_name; @@ -83,16 +83,16 @@ class GLTFState : public Resource { Vector<Ref<GLTFSkin>> skins; Vector<Ref<GLTFCamera>> cameras; Vector<Ref<GLTFLight>> lights; - Set<String> unique_names; - Set<String> unique_animation_names; + RBSet<String> unique_names; + RBSet<String> unique_animation_names; Vector<Ref<GLTFSkeleton>> skeletons; - Map<GLTFSkeletonIndex, GLTFNodeIndex> skeleton_to_node; + HashMap<GLTFSkeletonIndex, GLTFNodeIndex> skeleton_to_node; Vector<Ref<GLTFAnimation>> animations; - Map<GLTFNodeIndex, Node *> scene_nodes; + HashMap<GLTFNodeIndex, Node *> scene_nodes; - Map<ObjectID, GLTFSkeletonIndex> skeleton3d_to_gltf_skeleton; - Map<ObjectID, Map<ObjectID, GLTFSkinIndex>> skin_and_skeleton3d_to_gltf_skin; + HashMap<ObjectID, GLTFSkeletonIndex> skeleton3d_to_gltf_skeleton; + HashMap<ObjectID, HashMap<ObjectID, GLTFSkinIndex>> skin_and_skeleton3d_to_gltf_skin; protected: static void _bind_methods(); @@ -176,7 +176,7 @@ public: AnimationPlayer *get_animation_player(int idx); - //void set_scene_nodes(Map<GLTFNodeIndex, Node *> p_scene_nodes) { + //void set_scene_nodes(RBMap<GLTFNodeIndex, Node *> p_scene_nodes) { // this->scene_nodes = p_scene_nodes; //} @@ -184,10 +184,10 @@ public: // this->animation_players = p_animation_players; //} - //Map<Ref<Material>, GLTFMaterialIndex> get_material_cache() { + //RBMap<Ref<Material>, GLTFMaterialIndex> get_material_cache() { // return this->material_cache; //} - //void set_material_cache(Map<Ref<Material>, GLTFMaterialIndex> p_material_cache) { + //void set_material_cache(RBMap<Ref<Material>, GLTFMaterialIndex> p_material_cache) { // this->material_cache = p_material_cache; //} }; diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index 2f613768ee..4902adb827 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -930,6 +930,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) { } update_palette(); + _update_cursor_instance(); set_process(true); diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 3c7bd5eb70..9da137f9d5 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -103,9 +103,10 @@ bool GridMap::_get(const StringName &p_name, Variant &r_ret) const { { int *w = cells.ptrw(); int i = 0; - for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next(), i++) { - encode_uint64(E->key().key, (uint8_t *)&w[i * 3]); - encode_uint32(E->get().cell, (uint8_t *)&w[i * 3 + 2]); + for (const KeyValue<IndexKey, Cell> &E : cell_map) { + encode_uint64(E.key.key, (uint8_t *)&w[i * 3]); + encode_uint32(E.value.cell, (uint8_t *)&w[i * 3 + 2]); + i++; } } @@ -480,9 +481,9 @@ bool GridMap::_octant_update(const OctantKey &p_key) { * and set said multimesh bounding box to one containing all cells which have this item */ - Map<int, List<Pair<Transform3D, IndexKey>>> multimesh_items; + HashMap<int, List<Pair<Transform3D, IndexKey>>> multimesh_items; - for (Set<IndexKey>::Element *E = g.cells.front(); E; E = E->next()) { + for (RBSet<IndexKey>::Element *E = g.cells.front(); E; E = E->next()) { ERR_CONTINUE(!cell_map.has(E->get())); const Cell &c = cell_map[E->get()]; @@ -770,7 +771,7 @@ void GridMap::_queue_octants_dirty() { void GridMap::_recreate_octant_data() { recreating_octants = true; - Map<IndexKey, Cell> cell_copy = cell_map; + HashMap<IndexKey, Cell, IndexKey> cell_copy = cell_map; _clear_internal(); for (const KeyValue<IndexKey, Cell> &E : cell_copy) { set_cell_item(Vector3i(E.key), E.value.item, E.value.rot); @@ -998,7 +999,7 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe } //generate - Map<OctantKey, Map<Ref<Material>, Ref<SurfaceTool>>> surface_map; + HashMap<OctantKey, HashMap<Ref<Material>, Ref<SurfaceTool>>, OctantKey> surface_map; for (KeyValue<IndexKey, Cell> &E : cell_map) { IndexKey key = E.key; @@ -1028,10 +1029,10 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe ok.z = key.z / octant_size; if (!surface_map.has(ok)) { - surface_map[ok] = Map<Ref<Material>, Ref<SurfaceTool>>(); + surface_map[ok] = HashMap<Ref<Material>, Ref<SurfaceTool>>(); } - Map<Ref<Material>, Ref<SurfaceTool>> &mat_map = surface_map[ok]; + HashMap<Ref<Material>, Ref<SurfaceTool>> &mat_map = surface_map[ok]; for (int i = 0; i < mesh->get_surface_count(); i++) { if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { @@ -1051,7 +1052,7 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe } } - for (KeyValue<OctantKey, Map<Ref<Material>, Ref<SurfaceTool>>> &E : surface_map) { + for (KeyValue<OctantKey, HashMap<Ref<Material>, Ref<SurfaceTool>>> &E : surface_map) { Ref<ArrayMesh> mesh; mesh.instantiate(); for (KeyValue<Ref<Material>, Ref<SurfaceTool>> &F : E.value) { diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index 5e367e149d..88e16bce82 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -56,9 +56,15 @@ class GridMap : public Node3D { }; uint64_t key = 0; + static uint32_t hash(const IndexKey &p_key) { + return hash_one_uint64(p_key.key); + } _FORCE_INLINE_ bool operator<(const IndexKey &p_key) const { return key < p_key.key; } + _FORCE_INLINE_ bool operator==(const IndexKey &p_key) const { + return key == p_key.key; + } _FORCE_INLINE_ operator Vector3i() const { return Vector3i(x, y, z); @@ -107,13 +113,13 @@ class GridMap : public Node3D { }; Vector<MultimeshInstance> multimesh_instances; - Set<IndexKey> cells; + RBSet<IndexKey> cells; RID collision_debug; RID collision_debug_instance; bool dirty = false; RID static_body; - Map<IndexKey, NavMesh> navmesh_ids; + HashMap<IndexKey, NavMesh> navmesh_ids; }; union OctantKey { @@ -126,8 +132,11 @@ class GridMap : public Node3D { uint64_t key = 0; - _FORCE_INLINE_ bool operator<(const OctantKey &p_key) const { - return key < p_key.key; + static uint32_t hash(const OctantKey &p_key) { + return hash_one_uint64(p_key.key); + } + _FORCE_INLINE_ bool operator==(const OctantKey &p_key) const { + return key == p_key.key; } //OctantKey(const IndexKey& p_k, int p_item) { indexkey=p_k.key; item=p_item; } @@ -154,8 +163,8 @@ class GridMap : public Node3D { Ref<MeshLibrary> mesh_library; - Map<OctantKey, Octant *> octant_map; - Map<IndexKey, Cell> cell_map; + HashMap<OctantKey, Octant *, OctantKey> octant_map; + HashMap<IndexKey, Cell, IndexKey> cell_map; void _recreate_octant_data(); diff --git a/modules/jsonrpc/jsonrpc.h b/modules/jsonrpc/jsonrpc.h index 3144746f6d..f57d6aef42 100644 --- a/modules/jsonrpc/jsonrpc.h +++ b/modules/jsonrpc/jsonrpc.h @@ -37,7 +37,7 @@ class JSONRPC : public Object { GDCLASS(JSONRPC, Object) - Map<String, Object *> method_scopes; + HashMap<String, Object *> method_scopes; protected: static void _bind_methods(); diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp index 6cd710e792..e03940f963 100644 --- a/modules/minimp3/resource_importer_mp3.cpp +++ b/modules/minimp3/resource_importer_mp3.cpp @@ -54,7 +54,7 @@ String ResourceImporterMP3::get_resource_type() const { return "AudioStreamMP3"; } -bool ResourceImporterMP3::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterMP3::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } @@ -71,7 +71,7 @@ void ResourceImporterMP3::get_import_options(const String &p_path, List<ImportOp r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0)); } -Error ResourceImporterMP3::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterMP3::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { bool loop = p_options["loop"]; float loop_offset = p_options["loop_offset"]; diff --git a/modules/minimp3/resource_importer_mp3.h b/modules/minimp3/resource_importer_mp3.h index 75890228b9..678a3773bb 100644 --- a/modules/minimp3/resource_importer_mp3.h +++ b/modules/minimp3/resource_importer_mp3.h @@ -48,9 +48,9 @@ public: virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterMP3(); }; diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp index 9253f105bb..3afde1e8d3 100644 --- a/modules/mono/class_db_api_json.cpp +++ b/modules/mono/class_db_api_json.cpp @@ -40,17 +40,12 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { Dictionary classes_dict; - List<StringName> names; + List<StringName> class_list; + ClassDB::get_class_list(&class_list); + // Must be alphabetically sorted for hash to compute. + class_list.sort_custom<StringName::AlphCompare>(); - const StringName *k = nullptr; - - while ((k = ClassDB::classes.next(k))) { - names.push_back(*k); - } - //must be alphabetically sorted for hash to compute - names.sort_custom<StringName::AlphCompare>(); - - for (const StringName &E : names) { + for (const StringName &E : class_list) { ClassDB::ClassInfo *t = ClassDB::classes.getptr(E); ERR_FAIL_COND(!t); if (t->api != p_api || !t->exposed) { @@ -66,10 +61,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->method_map.next(k))) { - String name = k->operator String(); + for (const KeyValue<StringName, MethodBind *> &F : t->method_map) { + String name = F.key.operator String(); ERR_CONTINUE(name.is_empty()); @@ -77,7 +70,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { continue; // Ignore non-virtual methods that start with an underscore } - snames.push_back(*k); + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -131,10 +124,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->constant_map.next(k))) { - snames.push_back(*k); + for (const KeyValue<StringName, int> &F : t->constant_map) { + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -158,10 +149,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->signal_map.next(k))) { - snames.push_back(*k); + for (const KeyValue<StringName, MethodInfo> &F : t->signal_map) { + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -193,10 +182,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->property_setget.next(k))) { - snames.push_back(*k); + for (const KeyValue<StringName, ClassDB::PropertySetGet> &F : t->property_setget) { + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 5875a0fbd4..d0140f117c 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -686,10 +686,10 @@ void CSharpLanguage::pre_unsafe_unreference(Object *p_obj) { #ifdef DEBUG_ENABLED MutexLock lock(unsafe_object_references_lock); ObjectID id = p_obj->get_instance_id(); - Map<ObjectID, int>::Element *elem = unsafe_object_references.find(id); + HashMap<ObjectID, int>::Iterator elem = unsafe_object_references.find(id); ERR_FAIL_NULL(elem); - if (--elem->value() == 0) { - unsafe_object_references.erase(elem); + if (--elem->value == 0) { + unsafe_object_references.remove(elem); } #endif } @@ -897,7 +897,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { #endif // Save state and remove script from instances - Map<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state; + RBMap<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state; for (Object *&obj : script->instances) { ERR_CONTINUE(!obj->get_script_instance()); @@ -1099,14 +1099,14 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { const StringName &name = G.first; const Array &serialized_data = G.second; - Map<StringName, CSharpScript::EventSignal>::Element *match = script->event_signals.find(name); + HashMap<StringName, CSharpScript::EventSignal>::Iterator match = script->event_signals.find(name); if (!match) { // The event or its signal attribute were removed continue; } - const CSharpScript::EventSignal &event_signal = match->value(); + const CSharpScript::EventSignal &event_signal = match->value; MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data); MonoDelegate *delegate = nullptr; @@ -1428,7 +1428,7 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b return true; } -Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) { +RBMap<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) { return script_bindings.insert(p_object, p_script_binding); } @@ -1437,7 +1437,7 @@ void *CSharpLanguage::_instance_binding_create_callback(void *, void *p_instance MutexLock lock(csharp_lang->language_bind_mutex); - Map<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance); + RBMap<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance); if (match) { return (void *)match; } @@ -1467,7 +1467,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin { MutexLock lock(csharp_lang->language_bind_mutex); - Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_binding; + RBMap<Object *, CSharpScriptBinding>::Element *data = (RBMap<Object *, CSharpScriptBinding>::Element *)p_binding; CSharpScriptBinding &script_binding = data->value(); @@ -1488,7 +1488,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin GDNativeBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference) { CRASH_COND(!p_binding); - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)p_binding)->get(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)p_binding)->get(); RefCounted *rc_owner = Object::cast_to<RefCounted>(script_binding.owner); @@ -1558,7 +1558,7 @@ void *CSharpLanguage::get_instance_binding(Object *p_object) { // `setup_csharp_script_binding` may call `reference()`. It was moved here outside to fix that. if (binding) { - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)binding)->value(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)binding)->value(); if (!script_binding.inited) { MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex()); @@ -1798,8 +1798,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName, void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const { List<PropertyInfo> props; - for (OrderedHashMap<StringName, PropertyInfo>::ConstElement E = script->member_info.front(); E; E = E.next()) { - props.push_front(E.value()); + for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) { + props.push_front(E.value); } // Call _get_property_list @@ -2301,7 +2301,7 @@ CSharpInstance::~CSharpInstance() { void *data = CSharpLanguage::get_instance_binding(owner); CRASH_COND(data == nullptr); - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get(); CRASH_COND(!script_binding.inited); #ifdef DEBUG_ENABLED @@ -2315,7 +2315,7 @@ CSharpInstance::~CSharpInstance() { #ifdef DEBUG_ENABLED // CSharpInstance must not be created unless it's going to be added to the list for sure - Set<Object *>::Element *match = script->instances.find(owner); + RBSet<Object *>::Element *match = script->instances.find(owner); CRASH_COND(!match); script->instances.erase(match); #else @@ -2331,7 +2331,7 @@ void CSharpScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) #endif #ifdef TOOLS_ENABLED -void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) { +void CSharpScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) { if (base_cache.is_valid()) { base_cache->_update_exports_values(values, propnames); } @@ -2567,7 +2567,7 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda if ((changed || p_instance_to_update) && placeholders.size()) { // Update placeholders if any - Map<StringName, Variant> values; + HashMap<StringName, Variant> values; List<PropertyInfo> propnames; _update_exports_values(values, propnames); @@ -3144,7 +3144,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg void *data = CSharpLanguage::get_existing_instance_binding(p_owner); CRASH_COND(data == nullptr); - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get(); if (script_binding.inited && !script_binding.gchandle.is_released()) { MonoObject *mono_object = script_binding.gchandle.get_target(); if (mono_object) { @@ -3401,9 +3401,9 @@ ScriptLanguage *CSharpScript::get_language() const { bool CSharpScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { #ifdef TOOLS_ENABLED - const Map<StringName, Variant>::Element *E = exported_members_defval_cache.find(p_property); + HashMap<StringName, Variant>::ConstIterator E = exported_members_defval_cache.find(p_property); if (E) { - r_value = E->get(); + r_value = E->value; return true; } @@ -3491,8 +3491,8 @@ Ref<Script> CSharpScript::get_base_script() const { void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const { List<PropertyInfo> props; - for (OrderedHashMap<StringName, PropertyInfo>::ConstElement E = member_info.front(); E; E = E.next()) { - props.push_front(E.value()); + for (const KeyValue<StringName, PropertyInfo> &E : member_info) { + props.push_front(E.value); } for (const PropertyInfo &prop : props) { @@ -3574,7 +3574,7 @@ CSharpScript::~CSharpScript() { #endif } -void CSharpScript::get_members(Set<StringName> *p_members) { +void CSharpScript::get_members(RBSet<StringName> *p_members) { #if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) if (p_members) { for (const StringName &member_name : exported_members_names) { diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 41b54248a3..6e600bb47a 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -110,7 +110,7 @@ private: Ref<CSharpScript> base_cache; // TODO what's this for? - Set<Object *> instances; + RBSet<Object *> instances; #ifdef GD_MONO_HOT_RELOAD struct StateBackup { @@ -121,8 +121,8 @@ private: List<Pair<StringName, Array>> event_signals; }; - Set<ObjectID> pending_reload_instances; - Map<ObjectID, StateBackup> pending_reload_state; + RBSet<ObjectID> pending_reload_instances; + RBMap<ObjectID, StateBackup> pending_reload_state; StringName tied_class_name_for_reload; StringName tied_class_namespace_for_reload; #endif @@ -132,29 +132,29 @@ private: SelfList<CSharpScript> script_list = this; - Map<StringName, Vector<SignalParameter>> _signals; - Map<StringName, EventSignal> event_signals; + HashMap<StringName, Vector<SignalParameter>> _signals; + HashMap<StringName, EventSignal> event_signals; bool signals_invalidated = true; Vector<Multiplayer::RPCConfig> rpc_functions; #ifdef TOOLS_ENABLED List<PropertyInfo> exported_members_cache; // members_cache - Map<StringName, Variant> exported_members_defval_cache; // member_default_values_cache - Set<PlaceHolderScriptInstance *> placeholders; + HashMap<StringName, Variant> exported_members_defval_cache; // member_default_values_cache + RBSet<PlaceHolderScriptInstance *> placeholders; bool source_changed_cache = false; bool placeholder_fallback_enabled = false; bool exports_invalidated = true; - void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames); + void _update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames); void _update_member_info_no_exports(); void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override; #endif #if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) - Set<StringName> exported_members_names; + RBSet<StringName> exported_members_names; #endif - OrderedHashMap<StringName, PropertyInfo> member_info; + HashMap<StringName, PropertyInfo> member_info; void _clear(); @@ -218,7 +218,7 @@ public: void get_script_property_list(List<PropertyInfo> *r_list) const override; void update_exports() override; - void get_members(Set<StringName> *p_members) override; + void get_members(RBSet<StringName> *p_members) override; bool is_tool() const override { return tool; } bool is_valid() const override { return valid; } @@ -356,11 +356,11 @@ class CSharpLanguage : public ScriptLanguage { Mutex script_gchandle_release_mutex; Mutex language_bind_mutex; - Map<Object *, CSharpScriptBinding> script_bindings; + RBMap<Object *, CSharpScriptBinding> script_bindings; #ifdef DEBUG_ENABLED // List of unsafe object references - Map<ObjectID, int> unsafe_object_references; + HashMap<ObjectID, int> unsafe_object_references; Mutex unsafe_object_references_lock; #endif @@ -467,7 +467,7 @@ public: virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override; virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) override; /* TODO */ bool validate(const String &p_script, const String &p_path, List<String> *r_functions, - List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const override { + List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, RBSet<int> *r_safe_lines = nullptr) const override { return true; } String validate_path(const String &p_path) const override; @@ -518,7 +518,7 @@ public: void thread_enter() override; void thread_exit() override; - Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding); + RBMap<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding); bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object); #ifdef DEBUG_ENABLED diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs index bac7a2e6db..02e9d98647 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs @@ -63,6 +63,7 @@ namespace GodotTools.Build startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; startInfo.UseShellExecute = false; + startInfo.CreateNoWindow = true; if (UsingMonoMsBuildOnWindows) { diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index 93a1360cb6..2db549c623 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -184,7 +184,8 @@ namespace GodotTools.Utils { RedirectStandardOutput = true, RedirectStandardError = true, - UseShellExecute = false + UseShellExecute = false, + CreateNoWindow = true }; using (Process process = Process.Start(startInfo)) diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 54c65c21e8..e602396ede 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -604,14 +604,14 @@ void BindingsGenerator::_append_xml_signal(StringBuilder &p_xml_output, const Ty void BindingsGenerator::_append_xml_enum(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) { const StringName search_cname = !p_target_itype ? p_target_cname : StringName(p_target_itype->name + "." + (String)p_target_cname); - const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(search_cname); + HashMap<StringName, TypeInterface>::ConstIterator enum_match = enum_types.find(search_cname); if (!enum_match && search_cname != p_target_cname) { enum_match = enum_types.find(p_target_cname); } if (enum_match) { - const TypeInterface &target_enum_itype = enum_match->value(); + const TypeInterface &target_enum_itype = enum_match->value; p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE "."); p_xml_output.append(target_enum_itype.proxy_name); // Includes nesting class if any @@ -1078,8 +1078,8 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { compile_items.push_back(output_file); } - for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { - const TypeInterface &itype = E.get(); + for (const KeyValue<StringName, TypeInterface> &E : obj_types) { + const TypeInterface &itype = E.value; if (itype.api_type == ClassDB::API_EDITOR) { continue; @@ -1187,8 +1187,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { Vector<String> compile_items; - for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { - const TypeInterface &itype = E.get(); + for (const KeyValue<StringName, TypeInterface> &E : obj_types) { + const TypeInterface &itype = E.value; if (itype.api_type != ClassDB::API_EDITOR) { continue; @@ -1573,9 +1573,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte // Search it in base types too const TypeInterface *current_type = &p_itype; while (!setter && current_type->base_name != StringName()) { - OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name); + HashMap<StringName, TypeInterface>::Iterator base_match = obj_types.find(current_type->base_name); ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'."); - current_type = &base_match.get(); + current_type = &base_match->value; setter = current_type->find_method_by_name(p_iprop.setter); } @@ -1584,9 +1584,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte // Search it in base types too current_type = &p_itype; while (!getter && current_type->base_name != StringName()) { - OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name); + HashMap<StringName, TypeInterface>::Iterator base_match = obj_types.find(current_type->base_name); ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'."); - current_type = &base_match.get(); + current_type = &base_match->value; getter = current_type->find_method_by_name(p_iprop.getter); } @@ -1938,10 +1938,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf return OK; // Won't increment method bind count } - const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod); + HashMap<const MethodInterface *, const InternalCall *>::ConstIterator match = method_icalls_map.find(&p_imethod); ERR_FAIL_NULL_V(match, ERR_BUG); - const InternalCall *im_icall = match->value(); + const InternalCall *im_icall = match->value; String im_call = im_icall->editor_only ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS; im_call += "."; @@ -2096,8 +2096,8 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { generated_icall_funcs.clear(); - for (OrderedHashMap<StringName, TypeInterface>::Element type_elem = obj_types.front(); type_elem; type_elem = type_elem.next()) { - const TypeInterface &itype = type_elem.get(); + for (const KeyValue<StringName, TypeInterface> &type_elem : obj_types) { + const TypeInterface &itype = type_elem.value; bool is_derived_type = itype.base_name != StringName(); @@ -2322,10 +2322,10 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte i++; } - const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod); + HashMap<const MethodInterface *, const InternalCall *>::ConstIterator match = method_icalls_map.find(&p_imethod); ERR_FAIL_NULL_V(match, ERR_BUG); - const InternalCall *im_icall = match->value(); + const InternalCall *im_icall = match->value; String icall_method = im_icall->name; if (!generated_icall_funcs.find(im_icall)) { @@ -2468,29 +2468,29 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte } const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_null(const TypeReference &p_typeref) { - const Map<StringName, TypeInterface>::Element *builtin_type_match = builtin_types.find(p_typeref.cname); + HashMap<StringName, TypeInterface>::ConstIterator builtin_type_match = builtin_types.find(p_typeref.cname); if (builtin_type_match) { - return &builtin_type_match->get(); + return &builtin_type_match->value; } - const OrderedHashMap<StringName, TypeInterface>::Element obj_type_match = obj_types.find(p_typeref.cname); + HashMap<StringName, TypeInterface>::ConstIterator obj_type_match = obj_types.find(p_typeref.cname); if (obj_type_match) { - return &obj_type_match.get(); + return &obj_type_match->value; } if (p_typeref.is_enum) { - const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(p_typeref.cname); + HashMap<StringName, TypeInterface>::ConstIterator enum_match = enum_types.find(p_typeref.cname); if (enum_match) { - return &enum_match->get(); + return &enum_match->value; } // Enum not found. Most likely because none of its constants were bound, so it's empty. That's fine. Use int instead. - const Map<StringName, TypeInterface>::Element *int_match = builtin_types.find(name_cache.type_int); + HashMap<StringName, TypeInterface>::ConstIterator int_match = builtin_types.find(name_cache.type_int); ERR_FAIL_NULL_V(int_match, nullptr); - return &int_match->get(); + return &int_match->value; } return nullptr; @@ -2505,16 +2505,16 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placehol ERR_PRINT(String() + "Type not found. Creating placeholder: '" + p_typeref.cname.operator String() + "'."); - const Map<StringName, TypeInterface>::Element *match = placeholder_types.find(p_typeref.cname); + HashMap<StringName, TypeInterface>::ConstIterator match = placeholder_types.find(p_typeref.cname); if (match) { - return &match->get(); + return &match->value; } TypeInterface placeholder; TypeInterface::create_placeholder_type(placeholder, p_typeref.cname); - return &placeholder_types.insert(placeholder.cname, placeholder)->get(); + return &placeholder_types.insert(placeholder.cname, placeholder)->value; } StringName BindingsGenerator::_get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta) { @@ -2708,7 +2708,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { List<PropertyInfo> property_list; ClassDB::get_property_list(type_cname, &property_list, true); - Map<StringName, StringName> accessor_methods; + HashMap<StringName, StringName> accessor_methods; for (const PropertyInfo &property : property_list) { if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY || (property.type == Variant::NIL && property.usage & PROPERTY_USAGE_ARRAY)) { @@ -2903,9 +2903,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() { imethod.proxy_name += "_"; } - Map<StringName, StringName>::Element *accessor = accessor_methods.find(imethod.cname); + HashMap<StringName, StringName>::Iterator accessor = accessor_methods.find(imethod.cname); if (accessor) { - const PropertyInterface *accessor_property = itype.find_property_by_name(accessor->value()); + const PropertyInterface *accessor_property = itype.find_property_by_name(accessor->value); // We only deprecate an accessor method if it's in the same class as the property. It's easier this way, but also // we don't know if an accessor method in a different class could have other purposes, so better leave those untouched. @@ -2942,12 +2942,11 @@ bool BindingsGenerator::_populate_object_type_interfaces() { // Populate signals const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map; - const StringName *k = nullptr; - while ((k = signal_map.next(k))) { + for (const KeyValue<StringName, MethodInfo> &E : signal_map) { SignalInterface isignal; - const MethodInfo &method_info = signal_map.get(*k); + const MethodInfo &method_info = E.value; isignal.name = method_info.name; isignal.cname = method_info.name; @@ -3024,10 +3023,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ClassDB::get_integer_constant_list(type_cname, &constants, true); const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map; - k = nullptr; - while ((k = enum_map.next(k))) { - StringName enum_proxy_cname = *k; + for (const KeyValue<StringName, List<StringName>> &E : enum_map) { + StringName enum_proxy_cname = E.key; String enum_proxy_name = enum_proxy_cname.operator String(); if (itype.find_property_by_proxy_name(enum_proxy_cname)) { // We have several conflicts between enums and PascalCase properties, @@ -3036,7 +3034,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { enum_proxy_cname = StringName(enum_proxy_name); } EnumInterface ienum(enum_proxy_cname); - const List<StringName> &enum_constants = enum_map.get(*k); + const List<StringName> &enum_constants = E.value; for (const StringName &constant_cname : enum_constants) { String constant_name = constant_cname.operator String(); int *value = class_info->constant_map.getptr(constant_cname); @@ -3066,7 +3064,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { TypeInterface enum_itype; enum_itype.is_enum = true; - enum_itype.name = itype.name + "." + String(*k); + enum_itype.name = itype.name + "." + String(E.key); enum_itype.cname = StringName(enum_itype.name); enum_itype.proxy_name = itype.proxy_name + "." + enum_proxy_name; TypeInterface::postsetup_enum_type(enum_itype); @@ -3596,11 +3594,11 @@ void BindingsGenerator::_populate_global_constants() { int global_constants_count = CoreConstants::get_global_constant_count(); if (global_constants_count > 0) { - Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope"); + HashMap<String, DocData::ClassDoc>::Iterator match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope"); CRASH_COND_MSG(!match, "Could not find '@GlobalScope' in DocData."); - const DocData::ClassDoc &global_scope_doc = match->value(); + const DocData::ClassDoc &global_scope_doc = match->value; for (int i = 0; i < global_constants_count; i++) { String constant_name = CoreConstants::get_global_constant_name(i); @@ -3715,8 +3713,8 @@ void BindingsGenerator::_initialize() { core_custom_icalls.clear(); editor_custom_icalls.clear(); - for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { - _generate_method_icalls(E.get()); + for (const KeyValue<StringName, TypeInterface> &E : obj_types) { + _generate_method_icalls(E.value); } initialized = true; diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index dec4fae8cd..fb7e0e5a81 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -533,24 +533,24 @@ class BindingsGenerator { bool log_print_enabled = true; bool initialized = false; - OrderedHashMap<StringName, TypeInterface> obj_types; + HashMap<StringName, TypeInterface> obj_types; - Map<StringName, TypeInterface> placeholder_types; - Map<StringName, TypeInterface> builtin_types; - Map<StringName, TypeInterface> enum_types; + HashMap<StringName, TypeInterface> placeholder_types; + HashMap<StringName, TypeInterface> builtin_types; + HashMap<StringName, TypeInterface> enum_types; List<EnumInterface> global_enums; List<ConstantInterface> global_constants; List<InternalCall> method_icalls; - Map<const MethodInterface *, const InternalCall *> method_icalls_map; + HashMap<const MethodInterface *, const InternalCall *> method_icalls_map; List<const InternalCall *> generated_icall_funcs; List<InternalCall> core_custom_icalls; List<InternalCall> editor_custom_icalls; - Map<StringName, List<StringName>> blacklisted_methods; + HashMap<StringName, List<StringName>> blacklisted_methods; void _initialize_blacklisted_methods(); diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp index 79015686c3..a1789412f4 100644 --- a/modules/mono/editor/code_completion.cpp +++ b/modules/mono/editor/code_completion.cpp @@ -121,10 +121,10 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr case CompletionKind::NODE_PATHS: { { // Autoloads. - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { - const ProjectSettings::AutoloadInfo &info = E.value(); + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) { + const ProjectSettings::AutoloadInfo &info = E.value; suggestions.push_back(quoted("/root/" + String(info.name))); } } diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp index b10d78c593..7b9dbc87cf 100644 --- a/modules/mono/glue/base_object_glue.cpp +++ b/modules/mono/glue/base_object_glue.cpp @@ -68,7 +68,7 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) { void *data = CSharpLanguage::get_existing_instance_binding(p_ptr); if (data) { - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get(); if (script_binding.inited) { MonoGCHandleData &gchandle = script_binding.gchandle; if (!gchandle.is_released()) { @@ -115,7 +115,7 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole void *data = CSharpLanguage::get_existing_instance_binding(rc); if (data) { - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get(); if (script_binding.inited) { MonoGCHandleData &gchandle = script_binding.gchandle; if (!gchandle.is_released()) { diff --git a/modules/mono/managed_callable.cpp b/modules/mono/managed_callable.cpp index 8ed21c323f..4f7783b765 100644 --- a/modules/mono/managed_callable.cpp +++ b/modules/mono/managed_callable.cpp @@ -36,7 +36,7 @@ #ifdef GD_MONO_HOT_RELOAD SelfList<ManagedCallable>::List ManagedCallable::instances; -Map<ManagedCallable *, Array> ManagedCallable::instances_pending_reload; +RBMap<ManagedCallable *, Array> ManagedCallable::instances_pending_reload; Mutex ManagedCallable::instances_mutex; #endif diff --git a/modules/mono/managed_callable.h b/modules/mono/managed_callable.h index d50a8a7b08..11bee6cf60 100644 --- a/modules/mono/managed_callable.h +++ b/modules/mono/managed_callable.h @@ -48,7 +48,7 @@ class ManagedCallable : public CallableCustom { #ifdef GD_MONO_HOT_RELOAD SelfList<ManagedCallable> self_instance = this; static SelfList<ManagedCallable>::List instances; - static Map<ManagedCallable *, Array> instances_pending_reload; + static RBMap<ManagedCallable *, Array> instances_pending_reload; static Mutex instances_mutex; #endif diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index e98ce8f6c1..39a8ef22b7 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -1167,9 +1167,8 @@ GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) { int32_t domain_id = mono_domain_get_id(mono_domain_get()); HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id]; - const String *k = nullptr; - while ((k = domain_assemblies.next(k))) { - GDMonoAssembly *assembly = domain_assemblies.get(*k); + for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) { + GDMonoAssembly *assembly = E.value; if (assembly->get_image() == image) { GDMonoClass *klass = assembly->get_class(p_raw_class); if (klass) { @@ -1190,9 +1189,8 @@ GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName & int32_t domain_id = mono_domain_get_id(mono_domain_get()); HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id]; - const String *k = nullptr; - while ((k = domain_assemblies.next(k))) { - GDMonoAssembly *assembly = domain_assemblies.get(*k); + for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) { + GDMonoAssembly *assembly = E.value; klass = assembly->get_class(p_namespace, p_name); if (klass) { return klass; @@ -1205,9 +1203,8 @@ GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName & void GDMono::_domain_assemblies_cleanup(int32_t p_domain_id) { HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[p_domain_id]; - const String *k = nullptr; - while ((k = domain_assemblies.next(k))) { - memdelete(domain_assemblies.get(*k)); + for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) { + memdelete(E.value); } assemblies.erase(p_domain_id); @@ -1298,13 +1295,11 @@ GDMono::~GDMono() { // Leave the rest to 'mono_jit_cleanup' #endif - const int32_t *k = nullptr; - while ((k = assemblies.next(k))) { - HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies.get(*k); + for (const KeyValue<int32_t, HashMap<String, GDMonoAssembly *>> &E : assemblies) { + const HashMap<String, GDMonoAssembly *> &domain_assemblies = E.value; - const String *kk = nullptr; - while ((kk = domain_assemblies.next(kk))) { - memdelete(domain_assemblies.get(*kk)); + for (const KeyValue<String, GDMonoAssembly *> &F : domain_assemblies) { + memdelete(F.value); } } assemblies.clear(); diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 3991b14612..42c6b6305f 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -412,10 +412,10 @@ GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const Stri GDMonoClass *GDMonoAssembly::get_class(MonoClass *p_mono_class) { ERR_FAIL_NULL_V(image, nullptr); - Map<MonoClass *, GDMonoClass *>::Element *match = cached_raw.find(p_mono_class); + HashMap<MonoClass *, GDMonoClass *>::Iterator match = cached_raw.find(p_mono_class); if (match) { - return match->value(); + return match->value; } StringName namespace_name = String::utf8(mono_class_get_namespace(p_mono_class)); diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index a96357b082..0a3ae6c4fe 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -36,7 +36,7 @@ #include "core/string/ustring.h" #include "core/templates/hash_map.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "gd_mono_utils.h" class GDMonoAssembly { @@ -79,7 +79,7 @@ class GDMonoAssembly { #endif HashMap<ClassKey, GDMonoClass *, ClassKey::Hasher> cached_classes; - Map<MonoClass *, GDMonoClass *> cached_raw; + HashMap<MonoClass *, GDMonoClass *> cached_raw; static Vector<String> search_dirs; diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index 3fc0f16e05..51c5aa3542 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -247,7 +247,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base if (existing_method) { memdelete(*existing_method); // Must delete old one } - methods.set(key, method); + methods.insert(key, method); break; } @@ -266,11 +266,9 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base GDMonoMethod *GDMonoClass::get_fetched_method_unknown_params(const StringName &p_name) { ERR_FAIL_COND_V(!methods_fetched, nullptr); - const MethodKey *k = nullptr; - - while ((k = methods.next(k))) { - if (k->name == p_name) { - return methods.get(*k); + for (const KeyValue<MethodKey, GDMonoMethod *> &E : methods) { + if (E.key.name == p_name) { + return E.value; } } @@ -307,7 +305,7 @@ GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, uint16_t p_param if (raw_method) { GDMonoMethod *method = memnew(GDMonoMethod(p_name, raw_method)); - methods.set(key, method); + methods.insert(key, method); return method; } @@ -342,7 +340,7 @@ GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName } GDMonoMethod *method = memnew(GDMonoMethod(p_name, p_raw_method)); - methods.set(key, method); + methods.insert(key, method); return method; } @@ -362,10 +360,10 @@ GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, boo } GDMonoField *GDMonoClass::get_field(const StringName &p_name) { - Map<StringName, GDMonoField *>::Element *result = fields.find(p_name); + HashMap<StringName, GDMonoField *>::Iterator result = fields.find(p_name); if (result) { - return result->value(); + return result->value; } if (fields_fetched) { @@ -394,10 +392,10 @@ const Vector<GDMonoField *> &GDMonoClass::get_all_fields() { while ((raw_field = mono_class_get_fields(mono_class, &iter)) != nullptr) { StringName name = String::utf8(mono_field_get_name(raw_field)); - Map<StringName, GDMonoField *>::Element *match = fields.find(name); + HashMap<StringName, GDMonoField *>::Iterator match = fields.find(name); if (match) { - fields_list.push_back(match->get()); + fields_list.push_back(match->value); } else { GDMonoField *field = memnew(GDMonoField(raw_field, this)); fields.insert(name, field); @@ -411,10 +409,10 @@ const Vector<GDMonoField *> &GDMonoClass::get_all_fields() { } GDMonoProperty *GDMonoClass::get_property(const StringName &p_name) { - Map<StringName, GDMonoProperty *>::Element *result = properties.find(p_name); + HashMap<StringName, GDMonoProperty *>::Iterator result = properties.find(p_name); if (result) { - return result->value(); + return result->value; } if (properties_fetched) { @@ -443,10 +441,10 @@ const Vector<GDMonoProperty *> &GDMonoClass::get_all_properties() { while ((raw_property = mono_class_get_properties(mono_class, &iter)) != nullptr) { StringName name = String::utf8(mono_property_get_name(raw_property)); - Map<StringName, GDMonoProperty *>::Element *match = properties.find(name); + HashMap<StringName, GDMonoProperty *>::Iterator match = properties.find(name); if (match) { - properties_list.push_back(match->get()); + properties_list.push_back(match->value); } else { GDMonoProperty *property = memnew(GDMonoProperty(raw_property, this)); properties.insert(name, property); @@ -479,10 +477,10 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() { if (mono_class_is_delegate(raw_class)) { StringName name = String::utf8(mono_class_get_name(raw_class)); - Map<StringName, GDMonoClass *>::Element *match = delegates.find(name); + HashMap<StringName, GDMonoClass *>::Iterator match = delegates.find(name); if (match) { - delegates_list.push_back(match->get()); + delegates_list.push_back(match->value); } else { GDMonoClass *delegate = memnew(GDMonoClass(String::utf8(mono_class_get_namespace(raw_class)), String::utf8(mono_class_get_name(raw_class)), raw_class, assembly)); delegates.insert(name, delegate); @@ -549,9 +547,8 @@ GDMonoClass::~GDMonoClass() { Vector<GDMonoMethod *> deleted_methods; deleted_methods.resize(methods.size()); - const MethodKey *k = nullptr; - while ((k = methods.next(k))) { - GDMonoMethod *method = methods.get(*k); + for (const KeyValue<MethodKey, GDMonoMethod *> &E : methods) { + GDMonoMethod *method = E.value; if (method) { for (int i = 0; i < offset; i++) { diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index b32d561f61..6b35da30f9 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -32,7 +32,7 @@ #define GD_MONO_CLASS_H #include "core/string/ustring.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "gd_mono_field.h" #include "gd_mono_header.h" @@ -85,15 +85,15 @@ class GDMonoClass { Vector<GDMonoMethod *> method_list; bool fields_fetched; - Map<StringName, GDMonoField *> fields; + HashMap<StringName, GDMonoField *> fields; Vector<GDMonoField *> fields_list; bool properties_fetched; - Map<StringName, GDMonoProperty *> properties; + HashMap<StringName, GDMonoProperty *> properties; Vector<GDMonoProperty *> properties_list; bool delegates_fetched; - Map<StringName, GDMonoClass *> delegates; + HashMap<StringName, GDMonoClass *> delegates; Vector<GDMonoClass *> delegates_list; friend class GDMonoAssembly; diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index a884bf4da0..25678be624 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -70,7 +70,7 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { void *data = CSharpLanguage::get_instance_binding(unmanaged); ERR_FAIL_NULL_V(data, nullptr); - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->value(); ERR_FAIL_COND_V(!script_binding.inited, nullptr); MonoGCHandleData &gchandle = script_binding.gchandle; diff --git a/modules/mono/utils/osx_utils.cpp b/modules/mono/utils/osx_utils.cpp index 835c611709..abb59420eb 100644 --- a/modules/mono/utils/osx_utils.cpp +++ b/modules/mono/utils/osx_utils.cpp @@ -34,8 +34,8 @@ #include "core/string/print_string.h" -#include <CoreFoundation/CoreFoundation.h> -#include <CoreServices/CoreServices.h> +#import <CoreFoundation/CoreFoundation.h> +#import <CoreServices/CoreServices.h> bool osx_is_app_bundle_installed(const String &p_bundle_id) { CFStringRef bundle_id = CFStringCreateWithCString(nullptr, p_bundle_id.utf8(), kCFStringEncodingUTF8); diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index d16d41b438..42aad77979 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -233,6 +233,38 @@ RID GodotNavigationServer::map_get_closest_point_owner(RID p_map, const Vector3 return map->get_closest_point_owner(p_point); } +Array GodotNavigationServer::map_get_regions(RID p_map) const { + Array regions_rids; + const NavMap *map = map_owner.get_or_null(p_map); + ERR_FAIL_COND_V(map == nullptr, regions_rids); + for (NavRegion *region : map->get_regions()) { + regions_rids.push_back(region->get_self()); + } + return regions_rids; +} + +Array GodotNavigationServer::map_get_agents(RID p_map) const { + Array agents_rids; + const NavMap *map = map_owner.get_or_null(p_map); + ERR_FAIL_COND_V(map == nullptr, agents_rids); + for (RvoAgent *agent : map->get_agents()) { + agents_rids.push_back(agent->get_self()); + } + return agents_rids; +} + +RID GodotNavigationServer::region_get_map(RID p_region) const { + NavRegion *region = region_owner.get_or_null(p_region); + ERR_FAIL_COND_V(region == nullptr, RID()); + return region->get_map()->get_self(); +} + +RID GodotNavigationServer::agent_get_map(RID p_agent) const { + RvoAgent *agent = agent_owner.get_or_null(p_agent); + ERR_FAIL_COND_V(agent == nullptr, RID()); + return agent->get_map()->get_self(); +} + RID GodotNavigationServer::region_create() const { GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this); MutexLock lock(mut_this->operations_mutex); diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h index 7ad5e2d501..89e7311e51 100644 --- a/modules/navigation/godot_navigation_server.h +++ b/modules/navigation/godot_navigation_server.h @@ -105,8 +105,12 @@ public: virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const override; virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const override; + virtual Array map_get_regions(RID p_map) const override; + virtual Array map_get_agents(RID p_map) const override; + virtual RID region_create() const override; COMMAND_2(region_set_map, RID, p_region, RID, p_map); + virtual RID region_get_map(RID p_region) const override; COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers); virtual uint32_t region_get_layers(RID p_region) const override; COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform); @@ -118,6 +122,7 @@ public: virtual RID agent_create() const override; COMMAND_2(agent_set_map, RID, p_agent, RID, p_map); + virtual RID agent_get_map(RID p_agent) const override; COMMAND_2(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist); COMMAND_2(agent_set_max_neighbors, RID, p_agent, int, p_count); COMMAND_2(agent_set_time_horizon, RID, p_agent, real_t, p_time); diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index cbc0adc574..344475fb37 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -541,7 +541,7 @@ void NavMap::sync() { } // Group all edges per key. - Map<gd::EdgeKey, Vector<gd::Edge::Connection>> connections; + HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey> connections; for (size_t poly_id(0); poly_id < polygons.size(); poly_id++) { gd::Polygon &poly(polygons[poly_id]); @@ -549,7 +549,7 @@ void NavMap::sync() { int next_point = (p + 1) % poly.points.size(); gd::EdgeKey ek(poly.points[p].key, poly.points[next_point].key); - Map<gd::EdgeKey, Vector<gd::Edge::Connection>>::Element *connection = connections.find(ek); + HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey>::Iterator connection = connections.find(ek); if (!connection) { connections[ek] = Vector<gd::Edge::Connection>(); } diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index 5232e42bed..0ebdea30e1 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -34,7 +34,7 @@ #include "nav_rid.h" #include "core/math/math_defs.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/templates/thread_work_pool.h" #include "nav_utils.h" diff --git a/modules/navigation/nav_utils.h b/modules/navigation/nav_utils.h index 5b6c695ca4..a9f4e0e2fc 100644 --- a/modules/navigation/nav_utils.h +++ b/modules/navigation/nav_utils.h @@ -32,8 +32,9 @@ #define NAV_UTILS_H #include "core/math/vector3.h" +#include "core/templates/hash_map.h" +#include "core/templates/hashfuncs.h" #include "core/templates/vector.h" - #include <vector> class NavRegion; @@ -49,15 +50,18 @@ union PointKey { }; uint64_t key = 0; - bool operator<(const PointKey &p_key) const { return key < p_key.key; } }; struct EdgeKey { PointKey a; PointKey b; - bool operator<(const EdgeKey &p_key) const { - return (a.key == p_key.a.key) ? (b.key < p_key.b.key) : (a.key < p_key.a.key); + static uint32_t hash(const EdgeKey &p_val) { + return hash_one_uint64(p_val.a.key) ^ hash_one_uint64(p_val.b.key); + } + + bool operator==(const EdgeKey &p_key) const { + return (a.key == p_key.a.key) && (b.key == p_key.b.key); } EdgeKey(const PointKey &p_a = PointKey(), const PointKey &p_b = PointKey()) : diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp index 2d6c78f704..5cbaded6c1 100644 --- a/modules/navigation/navigation_mesh_generator.cpp +++ b/modules/navigation/navigation_mesh_generator.cpp @@ -445,7 +445,7 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh( cfg.minRegionArea = (int)(p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size()); cfg.mergeRegionArea = (int)(p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size()); cfg.maxVertsPerPoly = (int)p_nav_mesh->get_verts_per_poly(); - cfg.detailSampleDist = p_nav_mesh->get_detail_sample_distance() < 0.9f ? 0 : p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance(); + cfg.detailSampleDist = MAX(p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance(), 0.1f); cfg.detailSampleMaxError = p_nav_mesh->get_cell_height() * p_nav_mesh->get_detail_sample_max_error(); cfg.bmin[0] = bmin[0]; @@ -462,6 +462,14 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh( #endif rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height); + // ~30000000 seems to be around sweetspot where Editor baking breaks + if ((cfg.width * cfg.height) > 30000000) { + WARN_PRINT("NavigationMesh baking process will likely fail." + "\nSource geometry is suspiciously big for the current Cell Size and Cell Height in the NavMesh Resource bake settings." + "\nIf baking does not fail, the resulting NavigationMesh will create serious pathfinding performance issues." + "\nIt is advised to increase Cell Size and/or Cell Height in the NavMesh Resource bake settings or reduce the size / scale of the source geometry."); + } + #ifdef TOOLS_ENABLED if (ep) { ep->step(TTR("Creating heightfield..."), 3); diff --git a/modules/noise/fastnoise_lite.cpp b/modules/noise/fastnoise_lite.cpp index a8d38dee62..914cdec24c 100644 --- a/modules/noise/fastnoise_lite.cpp +++ b/modules/noise/fastnoise_lite.cpp @@ -30,6 +30,24 @@ #include "fastnoise_lite.h" +_FastNoiseLite::FractalType FastNoiseLite::_convert_domain_warp_fractal_type_enum(DomainWarpFractalType p_domain_warp_fractal_type) { + _FastNoiseLite::FractalType type; + switch (p_domain_warp_fractal_type) { + case DOMAIN_WARP_FRACTAL_NONE: + type = _FastNoiseLite::FractalType_None; + break; + case DOMAIN_WARP_FRACTAL_PROGRESSIVE: + type = _FastNoiseLite::FractalType_DomainWarpProgressive; + break; + case DOMAIN_WARP_FRACTAL_INDEPENDENT: + type = _FastNoiseLite::FractalType_DomainWarpIndependent; + break; + default: + type = _FastNoiseLite::FractalType_None; + } + return type; +} + FastNoiseLite::FastNoiseLite() { _noise.SetNoiseType((_FastNoiseLite::NoiseType)noise_type); _noise.SetSeed(seed); @@ -50,7 +68,7 @@ FastNoiseLite::FastNoiseLite() { _domain_warp_noise.SetSeed(seed); _domain_warp_noise.SetDomainWarpAmp(domain_warp_amplitude); _domain_warp_noise.SetFrequency(domain_warp_frequency); - _domain_warp_noise.SetFractalType(_FastNoiseLite::FractalType_None); + _domain_warp_noise.SetFractalType(_convert_domain_warp_fractal_type_enum(domain_warp_fractal_type)); _domain_warp_noise.SetFractalOctaves(domain_warp_fractal_octaves); _domain_warp_noise.SetFractalLacunarity(domain_warp_fractal_lacunarity); _domain_warp_noise.SetFractalGain(domain_warp_fractal_gain); @@ -241,23 +259,7 @@ real_t FastNoiseLite::get_domain_warp_frequency() const { void FastNoiseLite::set_domain_warp_fractal_type(DomainWarpFractalType p_domain_warp_fractal_type) { domain_warp_fractal_type = p_domain_warp_fractal_type; - // This needs manual conversion because Godots Inspector property API does not support discontiguous enum indices. - _FastNoiseLite::FractalType type; - switch (p_domain_warp_fractal_type) { - case DOMAIN_WARP_FRACTAL_NONE: - type = _FastNoiseLite::FractalType_None; - break; - case DOMAIN_WARP_FRACTAL_PROGRESSIVE: - type = _FastNoiseLite::FractalType_DomainWarpProgressive; - break; - case DOMAIN_WARP_FRACTAL_INDEPENDENT: - type = _FastNoiseLite::FractalType_DomainWarpIndependent; - break; - default: - type = _FastNoiseLite::FractalType_None; - } - - _domain_warp_noise.SetFractalType(type); + _domain_warp_noise.SetFractalType(_convert_domain_warp_fractal_type_enum(p_domain_warp_fractal_type)); emit_changed(); } diff --git a/modules/noise/fastnoise_lite.h b/modules/noise/fastnoise_lite.h index 0a4251868b..fe8cd7ce6e 100644 --- a/modules/noise/fastnoise_lite.h +++ b/modules/noise/fastnoise_lite.h @@ -127,6 +127,9 @@ private: real_t domain_warp_fractal_lacunarity = 6; real_t domain_warp_fractal_gain = 0.5; + // This needs manual conversion because Godots Inspector property API does not support discontiguous enum indices. + _FastNoiseLite::FractalType _convert_domain_warp_fractal_type_enum(DomainWarpFractalType p_domain_warp_fractal_type); + public: FastNoiseLite(); ~FastNoiseLite(); diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h index f3064041b8..0f7c0ba0bc 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper.h +++ b/modules/openxr/extensions/openxr_extension_wrapper.h @@ -33,7 +33,7 @@ #include "core/error/error_macros.h" #include "core/math/camera_matrix.h" -#include "core/templates/map.h" +#include "core/templates/hash_map.h" #include "core/templates/rid.h" #include "thirdparty/openxr/src/common/xr_linear.h" @@ -49,10 +49,10 @@ protected: // Store extension we require. // If bool pointer is a nullptr this means this extension is mandatory and initialisation will fail if it is not available // If bool pointer is set, value will be set to true or false depending on whether extension is available - Map<const char *, bool *> request_extensions; + HashMap<String, bool *> request_extensions; public: - virtual Map<const char *, bool *> get_request_extensions() { + virtual HashMap<String, bool *> get_request_extensions() { return request_extensions; } diff --git a/modules/openxr/extensions/openxr_vulkan_extension.cpp b/modules/openxr/extensions/openxr_vulkan_extension.cpp index 1eb7635a82..2ddf3b8a7d 100644 --- a/modules/openxr/extensions/openxr_vulkan_extension.cpp +++ b/modules/openxr/extensions/openxr_vulkan_extension.cpp @@ -33,6 +33,7 @@ #include "../extensions/openxr_vulkan_extension.h" #include "../openxr_api.h" #include "../openxr_util.h" +#include "servers/rendering/renderer_rd/effects/copy_effects.h" #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_globals.h" @@ -450,11 +451,9 @@ bool OpenXRVulkanExtension::copy_render_target_to_image(RID p_from_render_target ERR_FAIL_COND_V(fb.is_null(), false); // Our vulkan extension can only be used in conjunction with our vulkan renderer. - // We need access to the effects object in order to have access to our copy logic. - // Breaking all the rules but there is no nice way to do this. - EffectsRD *effects = RendererStorageRD::base_singleton->get_effects(); - ERR_FAIL_NULL_V(effects, false); - effects->copy_to_fb_rect(source_image, fb, Rect2i(), false, false, false, false, depth_image, data->is_multiview); + RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); + ERR_FAIL_NULL_V(copy_effects, false); + copy_effects->copy_to_fb_rect(source_image, fb, Rect2i(), false, false, false, false, depth_image, data->is_multiview); return true; } diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 2e9be48f01..6e94e3b444 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -170,9 +170,9 @@ bool OpenXRAPI::load_supported_extensions() { return true; } -bool OpenXRAPI::is_extension_supported(const char *p_extension) const { +bool OpenXRAPI::is_extension_supported(const String &p_extension) const { for (uint32_t i = 0; i < num_supported_extensions; i++) { - if (strcmp(supported_extensions[i].extensionName, p_extension) == 0) { + if ((supported_extensions[i].extensionName == p_extension) == 0) { #ifdef DEBUG print_line("OpenXR: requested extension", p_extension, "is supported"); #endif @@ -204,9 +204,9 @@ bool OpenXRAPI::create_instance() { // Create our OpenXR instance, this will query any registered extension wrappers for extensions we need to enable. // Append the extensions requested by the registered extension wrappers. - Map<const char *, bool *> requested_extensions; + HashMap<String, bool *> requested_extensions; for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { - Map<const char *, bool *> wrapper_request_extensions = wrapper->get_request_extensions(); + const HashMap<String, bool *> &wrapper_request_extensions = wrapper->get_request_extensions(); // requested_extensions.insert(wrapper_request_extensions.begin(), wrapper_request_extensions.end()); for (auto &requested_extension : wrapper_request_extensions) { @@ -224,6 +224,7 @@ bool OpenXRAPI::create_instance() { // Check which extensions are supported enabled_extensions.clear(); + for (auto &requested_extension : requested_extensions) { if (!is_extension_supported(requested_extension.key)) { if (requested_extension.value == nullptr) { @@ -238,13 +239,18 @@ bool OpenXRAPI::create_instance() { *requested_extension.value = true; // and record that we want to enable it - enabled_extensions.push_back(requested_extension.key); + enabled_extensions.push_back(requested_extension.key.ascii()); } else { // record that we want to enable this - enabled_extensions.push_back(requested_extension.key); + enabled_extensions.push_back(requested_extension.key.ascii()); } } + Vector<const char *> extension_ptrs; + for (int i = 0; i < enabled_extensions.size(); i++) { + extension_ptrs.push_back(enabled_extensions[i].get_data()); + } + // Get our project name String project_name = GLOBAL_GET("application/config/name"); @@ -264,8 +270,8 @@ bool OpenXRAPI::create_instance() { application_info, // applicationInfo 0, // enabledApiLayerCount, need to find out if we need support for this? nullptr, // enabledApiLayerNames - uint32_t(enabled_extensions.size()), // enabledExtensionCount - enabled_extensions.ptr() // enabledExtensionNames + uint32_t(extension_ptrs.size()), // enabledExtensionCount + extension_ptrs.ptr() // enabledExtensionNames }; copy_string_to_char_buffer(project_name, instance_create_info.applicationInfo.applicationName, XR_MAX_APPLICATION_NAME_SIZE); @@ -1001,7 +1007,7 @@ bool OpenXRAPI::initialize(const String &p_rendering_driver) { ERR_FAIL_V(false); #endif } else if (p_rendering_driver == "opengl3") { -#ifdef OPENGL3_ENABLED +#ifdef GLES3_ENABLED // graphics_extension = memnew(OpenXROpenGLExtension(this)); // register_extension_wrapper(graphics_extension); ERR_FAIL_V_MSG(false, "OpenXR: OpenGL is not supported at this time."); diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index 702f6b9b1d..bd71f0e1c2 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -37,7 +37,7 @@ #include "core/math/vector2.h" #include "core/os/memory.h" #include "core/string/ustring.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/templates/rid_owner.h" #include "core/templates/vector.h" #include "servers/xr/xr_pose.h" @@ -73,7 +73,7 @@ private: uint32_t num_supported_extensions = 0; XrExtensionProperties *supported_extensions = nullptr; Vector<OpenXRExtensionWrapper *> registered_extension_wrappers; - Vector<const char *> enabled_extensions; + Vector<CharString> enabled_extensions; bool ext_hp_mixed_reality_available = false; bool ext_samsung_odyssey_available = false; @@ -132,7 +132,7 @@ private: bool load_layer_properties(); bool load_supported_extensions(); - bool is_extension_supported(const char *p_extension) const; + bool is_extension_supported(const String &p_extension) const; // instance bool create_instance(); diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 41ce8c019e..ab06583932 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -113,7 +113,7 @@ void OpenXRInterface::_load_action_map() { // process our action map if (action_map.is_valid()) { - Map<Ref<OpenXRAction>, Action *> xr_actions; + HashMap<Ref<OpenXRAction>, Action *> xr_actions; Array action_sets = action_map->get_action_sets(); for (int i = 0; i < action_sets.size(); i++) { diff --git a/modules/raycast/lightmap_raycaster.cpp b/modules/raycast/lightmap_raycaster.cpp index ecc256bff9..7e7c3f9067 100644 --- a/modules/raycast/lightmap_raycaster.cpp +++ b/modules/raycast/lightmap_raycaster.cpp @@ -152,8 +152,8 @@ void LightmapRaycasterEmbree::commit() { rtcCommitScene(embree_scene); } -void LightmapRaycasterEmbree::set_mesh_filter(const Set<int> &p_mesh_ids) { - for (Set<int>::Element *E = p_mesh_ids.front(); E; E = E->next()) { +void LightmapRaycasterEmbree::set_mesh_filter(const RBSet<int> &p_mesh_ids) { + for (RBSet<int>::Element *E = p_mesh_ids.front(); E; E = E->next()) { rtcDisableGeometry(rtcGetGeometry(embree_scene, E->get())); } rtcCommitScene(embree_scene); @@ -161,7 +161,7 @@ void LightmapRaycasterEmbree::set_mesh_filter(const Set<int> &p_mesh_ids) { } void LightmapRaycasterEmbree::clear_mesh_filter() { - for (Set<int>::Element *E = filter_meshes.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = filter_meshes.front(); E; E = E->next()) { rtcEnableGeometry(rtcGetGeometry(embree_scene, E->get())); } rtcCommitScene(embree_scene); diff --git a/modules/raycast/lightmap_raycaster.h b/modules/raycast/lightmap_raycaster.h index c420e617e5..4c52758fd8 100644 --- a/modules/raycast/lightmap_raycaster.h +++ b/modules/raycast/lightmap_raycaster.h @@ -52,8 +52,8 @@ private: static void filter_function(const struct RTCFilterFunctionNArguments *p_args); - Map<unsigned int, AlphaTextureData> alpha_textures; - Set<int> filter_meshes; + HashMap<unsigned int, AlphaTextureData> alpha_textures; + RBSet<int> filter_meshes; public: virtual bool intersect(Ray &p_ray) override; @@ -64,7 +64,7 @@ public: virtual void set_mesh_alpha_texture(Ref<Image> p_alpha_texture, unsigned int p_id) override; virtual void commit() override; - virtual void set_mesh_filter(const Set<int> &p_mesh_ids) override; + virtual void set_mesh_filter(const RBSet<int> &p_mesh_ids) override; virtual void clear_mesh_filter() override; static LightmapRaycaster *create_embree_raycaster(); diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp index 1550f0ef8b..c165354c7b 100644 --- a/modules/raycast/raycast_occlusion_cull.cpp +++ b/modules/raycast/raycast_occlusion_cull.cpp @@ -223,7 +223,7 @@ void RaycastOcclusionCull::occluder_set_mesh(RID p_occluder, const PackedVector3 occluder->vertices = p_vertices; occluder->indices = p_indices; - for (Set<InstanceID>::Element *E = occluder->users.front(); E; E = E->next()) { + for (RBSet<InstanceID>::Element *E = occluder->users.front(); E; E = E->next()) { RID scenario_rid = E->get().scenario; RID instance_rid = E->get().instance; ERR_CONTINUE(!scenarios.has(scenario_rid)); @@ -454,10 +454,9 @@ bool RaycastOcclusionCull::Scenario::update(ThreadWorkPool &p_thread_pool) { next_scene = rtcNewScene(raycast_singleton->ebr_device); rtcSetSceneBuildQuality(next_scene, RTCBuildQuality(raycast_singleton->build_quality)); - const RID *inst_rid = nullptr; - while ((inst_rid = instances.next(inst_rid))) { - OccluderInstance *occ_inst = instances.getptr(*inst_rid); - Occluder *occ = raycast_singleton->occluder_owner.get_or_null(occ_inst->occluder); + for (const KeyValue<RID, OccluderInstance> &E : instances) { + const OccluderInstance *occ_inst = &E.value; + const Occluder *occ = raycast_singleton->occluder_owner.get_or_null(occ_inst->occluder); if (!occ || !occ_inst->enabled) { continue; @@ -573,9 +572,8 @@ void RaycastOcclusionCull::set_build_quality(RS::ViewportOcclusionCullingBuildQu build_quality = p_quality; - const RID *scenario_rid = nullptr; - while ((scenario_rid = scenarios.next(scenario_rid))) { - scenarios[*scenario_rid].dirty = true; + for (KeyValue<RID, Scenario> &K : scenarios) { + K.value.dirty = true; } } @@ -596,9 +594,8 @@ RaycastOcclusionCull::RaycastOcclusionCull() { } RaycastOcclusionCull::~RaycastOcclusionCull() { - const RID *scenario_rid = nullptr; - while ((scenario_rid = scenarios.next(scenario_rid))) { - Scenario &scenario = scenarios[*scenario_rid]; + for (KeyValue<RID, Scenario> &K : scenarios) { + Scenario &scenario = K.value; if (scenario.commit_thread) { scenario.commit_thread->wait_to_finish(); memdelete(scenario.commit_thread); diff --git a/modules/raycast/raycast_occlusion_cull.h b/modules/raycast/raycast_occlusion_cull.h index 8453c5341d..779f6fb3c4 100644 --- a/modules/raycast/raycast_occlusion_cull.h +++ b/modules/raycast/raycast_occlusion_cull.h @@ -101,7 +101,7 @@ private: struct Occluder { PackedVector3Array vertices; PackedInt32Array indices; - Set<InstanceID> users; + RBSet<InstanceID> users; }; struct OccluderInstance { @@ -136,7 +136,7 @@ private: int current_scene_idx = 0; HashMap<RID, OccluderInstance> instances; - Set<RID> dirty_instances; // To avoid duplicates + RBSet<RID> dirty_instances; // To avoid duplicates LocalVector<RID> dirty_instances_array; // To iterate and split into threads LocalVector<RID> removed_instances; diff --git a/modules/raycast/static_raycaster.cpp b/modules/raycast/static_raycaster.cpp index 9df6d5ff43..f2e944a82d 100644 --- a/modules/raycast/static_raycaster.cpp +++ b/modules/raycast/static_raycaster.cpp @@ -94,8 +94,8 @@ void StaticRaycasterEmbree::commit() { rtcCommitScene(embree_scene); } -void StaticRaycasterEmbree::set_mesh_filter(const Set<int> &p_mesh_ids) { - for (Set<int>::Element *E = p_mesh_ids.front(); E; E = E->next()) { +void StaticRaycasterEmbree::set_mesh_filter(const RBSet<int> &p_mesh_ids) { + for (RBSet<int>::Element *E = p_mesh_ids.front(); E; E = E->next()) { rtcDisableGeometry(rtcGetGeometry(embree_scene, E->get())); } rtcCommitScene(embree_scene); @@ -103,7 +103,7 @@ void StaticRaycasterEmbree::set_mesh_filter(const Set<int> &p_mesh_ids) { } void StaticRaycasterEmbree::clear_mesh_filter() { - for (Set<int>::Element *E = filter_meshes.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = filter_meshes.front(); E; E = E->next()) { rtcEnableGeometry(rtcGetGeometry(embree_scene, E->get())); } rtcCommitScene(embree_scene); diff --git a/modules/raycast/static_raycaster.h b/modules/raycast/static_raycaster.h index cce19ba60d..b52b5bccfc 100644 --- a/modules/raycast/static_raycaster.h +++ b/modules/raycast/static_raycaster.h @@ -41,7 +41,7 @@ private: static RTCDevice embree_device; RTCScene embree_scene; - Set<int> filter_meshes; + RBSet<int> filter_meshes; public: virtual bool intersect(Ray &p_ray) override; @@ -50,7 +50,7 @@ public: virtual void add_mesh(const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices, unsigned int p_id) override; virtual void commit() override; - virtual void set_mesh_filter(const Set<int> &p_mesh_ids) override; + virtual void set_mesh_filter(const RBSet<int> &p_mesh_ids) override; virtual void clear_mesh_filter() override; static StaticRaycaster *create_embree_raycaster(); diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp index ee1137b71f..bbe92139e0 100644 --- a/modules/regex/regex.cpp +++ b/modules/regex/regex.cpp @@ -52,9 +52,9 @@ int RegExMatch::_find(const Variant &p_name) const { return i; } else if (p_name.get_type() == Variant::STRING) { - const Map<String, int>::Element *found = names.find((String)p_name); + HashMap<String, int>::ConstIterator found = names.find((String)p_name); if (found) { - return found->value(); + return found->value; } } @@ -75,8 +75,8 @@ int RegExMatch::get_group_count() const { Dictionary RegExMatch::get_names() const { Dictionary result; - for (const Map<String, int>::Element *i = names.front(); i != nullptr; i = i->next()) { - result[i->key()] = i->value(); + for (const KeyValue<String, int> &E : names) { + result[E.key] = E.value; } return result; diff --git a/modules/regex/regex.h b/modules/regex/regex.h index e7221f4070..1455188670 100644 --- a/modules/regex/regex.h +++ b/modules/regex/regex.h @@ -33,7 +33,7 @@ #include "core/object/ref_counted.h" #include "core/string/ustring.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/templates/vector.h" #include "core/variant/array.h" #include "core/variant/dictionary.h" @@ -48,7 +48,7 @@ class RegExMatch : public RefCounted { String subject; Vector<Range> data; - Map<String, int> names; + HashMap<String, int> names; friend class RegEx; diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index 7fe2e589b1..dcb1f1d744 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -94,7 +94,7 @@ void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_strin ERR_FAIL_MSG("ImageLoaderSVG can't create image."); } - res = sw_canvas->push(move(picture)); + res = sw_canvas->push(std::move(picture)); if (res != tvg::Result::Success) { memfree(buffer); ERR_FAIL_MSG("ImageLoaderSVG can't create image."); diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 525d4d3efb..a46f17311a 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -442,7 +442,7 @@ if env["builtin_icu"]: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - icu_data_name = "icudt70l.dat" + icu_data_name = "icudt71l.dat" if env_icu["tools"]: env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name) diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct index 1c38398c88..0e36ef6805 100644 --- a/modules/text_server_adv/gdextension_build/SConstruct +++ b/modules/text_server_adv/gdextension_build/SConstruct @@ -116,6 +116,7 @@ if env["freetype_enabled"]: "src/psnames/psnames.c", "src/raster/raster.c", "src/sdf/sdf.c", + "src/svg/svg.c", "src/smooth/smooth.c", "src/truetype/truetype.c", "src/type1/type1.c", @@ -164,7 +165,14 @@ if env["freetype_enabled"]: env_freetype.Append(CPPPATH=[thirdparty_freetype_dir + "/include", thirdparty_zlib_dir, thirdparty_png_dir]) env.Append(CPPPATH=[thirdparty_freetype_dir + "/include"]) - env_freetype.Append(CPPDEFINES=["FT2_BUILD_LIBRARY", "FT_CONFIG_OPTION_USE_PNG", ("PNG_ARM_NEON_OPT", 0)]) + env_freetype.Append( + CPPDEFINES=[ + "FT2_BUILD_LIBRARY", + "FT_CONFIG_OPTION_USE_PNG", + ("PNG_ARM_NEON_OPT", 0), + "FT_CONFIG_OPTION_SYSTEM_ZLIB", + ] + ) if env["target"] == "debug": env_freetype.Append(CPPDEFINES=["ZLIB_DEBUG"]) @@ -564,7 +572,7 @@ thirdparty_icu_sources = [ ] thirdparty_icu_sources = [thirdparty_icu_dir + file for file in thirdparty_icu_sources] -icu_data_name = "icudt70l.dat" +icu_data_name = "icudt71l.dat" if env["static_icu_data"]: env_icu.Depends("../../../thirdparty/icu4c/icudata.gen.h", "../../../thirdparty/icu4c/" + icu_data_name) diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index ba249aff7a..bd14b15561 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -2172,6 +2172,11 @@ void TextServerAdvanced::font_set_scale(const RID &p_font_rid, int64_t p_size, d Vector2i size = _get_size(fd, p_size); ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); +#ifdef MODULE_FREETYPE_ENABLED + if (fd->cache[size]->face) { + return; // Do not override scale for dynamic fonts, it's calculated automatically. + } +#endif fd->cache[size]->scale = p_scale; } @@ -2366,9 +2371,8 @@ Array TextServerAdvanced::font_get_glyph_list(const RID &p_font_rid, const Vecto Array ret; const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; - const int32_t *E = nullptr; - while ((E = gl.next(E))) { - ret.push_back(*E); + for (const KeyValue<int32_t, FontGlyph> &E : gl) { + ret.push_back(E.key); } return ret; } @@ -2684,13 +2688,22 @@ Dictionary TextServerAdvanced::font_get_glyph_contours(const RID &p_font_rid, in int error = FT_Load_Glyph(fd->cache[size]->face, index, FT_LOAD_NO_BITMAP | (fd->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); ERR_FAIL_COND_V(error, Dictionary()); - double h = fd->cache[size]->ascent; + if (fd->embolden != 0.f) { + FT_Pos strength = fd->embolden * p_size * 4; // 26.6 fractional units (1 / 64). + FT_Outline_Embolden(&fd->cache[size]->face->glyph->outline, strength); + } + + if (fd->transform != Transform2D()) { + FT_Matrix mat = { FT_Fixed(fd->transform[0][0] * 65536), FT_Fixed(fd->transform[0][1] * 65536), FT_Fixed(fd->transform[1][0] * 65536), FT_Fixed(fd->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536). + FT_Outline_Transform(&fd->cache[size]->face->glyph->outline, &mat); + } + double scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale; if (fd->msdf) { scale = scale * (double)p_size / (double)fd->msdf_source_size; } for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_points; i++) { - points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, h - fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i]))); + points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, -fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i]))); } for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_contours; i++) { contours.push_back(fd->cache[size]->face->glyph->outline.contours[i]); @@ -2765,7 +2778,7 @@ Vector2 TextServerAdvanced::font_get_kerning(const RID &p_font_rid, int64_t p_si ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - const Map<Vector2i, Vector2> &kern = fd->cache[size]->kerning_map; + const HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> &kern = fd->cache[size]->kerning_map; if (kern.has(p_glyph_pair)) { if (fd->msdf) { @@ -2823,7 +2836,7 @@ bool TextServerAdvanced::font_has_char(const RID &p_font_rid, int64_t p_char) co if (fd->cache.is_empty()) { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), false); } - FontDataForSizeAdvanced *at_size = fd->cache.front()->get(); + FontDataForSizeAdvanced *at_size = fd->cache.begin()->value; #ifdef MODULE_FREETYPE_ENABLED if (at_size && at_size->face) { @@ -2841,7 +2854,7 @@ String TextServerAdvanced::font_get_supported_chars(const RID &p_font_rid) const if (fd->cache.is_empty()) { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), String()); } - FontDataForSizeAdvanced *at_size = fd->cache.front()->get(); + FontDataForSizeAdvanced *at_size = fd->cache.begin()->value; String chars; #ifdef MODULE_FREETYPE_ENABLED @@ -2859,9 +2872,8 @@ String TextServerAdvanced::font_get_supported_chars(const RID &p_font_rid) const #endif if (at_size) { const HashMap<int32_t, FontGlyph> &gl = at_size->glyph_map; - const int32_t *E = nullptr; - while ((E = gl.next(E))) { - chars = chars + String::chr(*E); + for (const KeyValue<int32_t, FontGlyph> &E : gl) { + chars = chars + String::chr(E.key); } } return chars; @@ -4572,7 +4584,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(const RID &p_shape Glyph *sd_glyphs = sd->glyphs.ptrw(); int sd_size = sd->glyphs.size(); - if (sd->jstops.size() > 0) { + if (!sd->jstops.is_empty()) { for (int i = 0; i < sd_size; i++) { if (sd_glyphs[i].count > 0) { char32_t c = sd->text[sd_glyphs[i].start - sd->start]; @@ -5572,7 +5584,7 @@ PackedInt32Array TextServerAdvanced::string_get_word_breaks(const String &p_stri // Convert to UTF-16. Char16String utf16 = p_string.utf16(); - Set<int> breaks; + RBSet<int> breaks; UErrorCode err = U_ZERO_ERROR; UBreakIterator *bi = ubrk_open(UBRK_LINE, p_language.ascii().get_data(), (const UChar *)utf16.ptr(), utf16.length(), &err); if (U_FAILURE(err)) { diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 1b4293aa72..897c27b6fa 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -67,7 +67,6 @@ #include <godot_cpp/classes/ref.hpp> #include <godot_cpp/templates/hash_map.hpp> -#include <godot_cpp/templates/map.hpp> #include <godot_cpp/templates/rid_owner.hpp> #include <godot_cpp/templates/set.hpp> #include <godot_cpp/templates/thread_work_pool.hpp> @@ -78,6 +77,7 @@ using namespace godot; #else // Headers for building as built-in module. +#include "core/templates/hash_map.h" #include "core/templates/rid_owner.h" #include "core/templates/thread_work_pool.h" #include "scene/resources/texture.h" @@ -126,15 +126,15 @@ class TextServerAdvanced : public TextServerExtension { _THREAD_SAFE_CLASS_ struct NumSystemData { - Set<StringName> lang; + RBSet<StringName> lang; String digits; String percent_sign; String exp; }; Vector<NumSystemData> num_systems; - Map<StringName, int32_t> feature_sets; - Map<int32_t, StringName> feature_sets_inv; + HashMap<StringName, int32_t> feature_sets; + HashMap<int32_t, StringName> feature_sets_inv; void _insert_num_systems_lang(); void _insert_feature_sets(); @@ -191,8 +191,7 @@ class TextServerAdvanced : public TextServerExtension { Vector<FontTexture> textures; HashMap<int32_t, FontGlyph> glyph_map; - Map<Vector2i, Vector2> kerning_map; - + HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> kerning_map; hb_font_t *hb_handle = nullptr; #ifdef MODULE_FREETYPE_ENABLED @@ -233,17 +232,17 @@ class TextServerAdvanced : public TextServerExtension { String font_name; String style_name; - Map<Vector2i, FontDataForSizeAdvanced *> cache; + HashMap<Vector2i, FontDataForSizeAdvanced *, VariantHasher, VariantComparator> cache; bool face_init = false; - Set<uint32_t> supported_scripts; + RBSet<uint32_t> supported_scripts; Dictionary supported_features; Dictionary supported_varaitions; Dictionary feature_overrides; // Language/script support override. - Map<String, bool> language_support_overrides; - Map<String, bool> script_support_overrides; + HashMap<String, bool> language_support_overrides; + HashMap<String, bool> script_support_overrides; PackedByteArray data; const uint8_t *data_ptr; @@ -334,7 +333,7 @@ class TextServerAdvanced : public TextServerExtension { InlineAlignment inline_align = INLINE_ALIGNMENT_CENTER; Rect2 rect; }; - Map<Variant, EmbeddedObject> objects; + HashMap<Variant, EmbeddedObject, VariantHasher, VariantComparator> objects; /* Shaped data */ TextServer::Direction para_direction = DIRECTION_LTR; // Detected text direction. diff --git a/modules/text_server_fb/gdextension_build/SConstruct b/modules/text_server_fb/gdextension_build/SConstruct index 1753bc8b86..6c9e10db18 100644 --- a/modules/text_server_fb/gdextension_build/SConstruct +++ b/modules/text_server_fb/gdextension_build/SConstruct @@ -111,6 +111,7 @@ if env["freetype_enabled"]: "src/psnames/psnames.c", "src/raster/raster.c", "src/sdf/sdf.c", + "src/svg/svg.c", "src/smooth/smooth.c", "src/truetype/truetype.c", "src/type1/type1.c", @@ -159,7 +160,14 @@ if env["freetype_enabled"]: env_freetype.Append(CPPPATH=[thirdparty_freetype_dir + "/include", thirdparty_zlib_dir, thirdparty_png_dir]) env.Append(CPPPATH=[thirdparty_freetype_dir + "/include"]) - env_freetype.Append(CPPDEFINES=["FT2_BUILD_LIBRARY", "FT_CONFIG_OPTION_USE_PNG", ("PNG_ARM_NEON_OPT", 0)]) + env_freetype.Append( + CPPDEFINES=[ + "FT2_BUILD_LIBRARY", + "FT_CONFIG_OPTION_USE_PNG", + ("PNG_ARM_NEON_OPT", 0), + "FT_CONFIG_OPTION_SYSTEM_ZLIB", + ] + ) if env["target"] == "debug": env_freetype.Append(CPPDEFINES=["ZLIB_DEBUG"]) diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 8ae56aa64d..c53ca7766a 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -1334,6 +1334,11 @@ void TextServerFallback::font_set_scale(const RID &p_font_rid, int64_t p_size, d Vector2i size = _get_size(fd, p_size); ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); +#ifdef MODULE_FREETYPE_ENABLED + if (fd->cache[size]->face) { + return; // Do not override scale for dynamic fonts, it's calculated automatically. + } +#endif fd->cache[size]->scale = p_scale; } @@ -1528,9 +1533,8 @@ Array TextServerFallback::font_get_glyph_list(const RID &p_font_rid, const Vecto Array ret; const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; - const int32_t *E = nullptr; - while ((E = gl.next(E))) { - ret.push_back(*E); + for (const KeyValue<int32_t, FontGlyph> &E : gl) { + ret.push_back(E.key); } return ret; } @@ -1832,13 +1836,22 @@ Dictionary TextServerFallback::font_get_glyph_contours(const RID &p_font_rid, in int error = FT_Load_Glyph(fd->cache[size]->face, FT_Get_Char_Index(fd->cache[size]->face, index), FT_LOAD_NO_BITMAP | (fd->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); ERR_FAIL_COND_V(error, Dictionary()); - double h = fd->cache[size]->ascent; + if (fd->embolden != 0.f) { + FT_Pos strength = fd->embolden * p_size * 4; // 26.6 fractional units (1 / 64). + FT_Outline_Embolden(&fd->cache[size]->face->glyph->outline, strength); + } + + if (fd->transform != Transform2D()) { + FT_Matrix mat = { FT_Fixed(fd->transform[0][0] * 65536), FT_Fixed(fd->transform[0][1] * 65536), FT_Fixed(fd->transform[1][0] * 65536), FT_Fixed(fd->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536). + FT_Outline_Transform(&fd->cache[size]->face->glyph->outline, &mat); + } + double scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale; if (fd->msdf) { scale = scale * (double)p_size / (double)fd->msdf_source_size; } for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_points; i++) { - points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, h - fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i]))); + points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, -fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i]))); } for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_contours; i++) { contours.push_back(fd->cache[size]->face->glyph->outline.contours[i]); @@ -1913,7 +1926,7 @@ Vector2 TextServerFallback::font_get_kerning(const RID &p_font_rid, int64_t p_si ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - const Map<Vector2i, Vector2> &kern = fd->cache[size]->kerning_map; + const HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> &kern = fd->cache[size]->kerning_map; if (kern.has(p_glyph_pair)) { if (fd->msdf) { @@ -1953,7 +1966,7 @@ bool TextServerFallback::font_has_char(const RID &p_font_rid, int64_t p_char) co if (fd->cache.is_empty()) { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), false); } - FontDataForSizeFallback *at_size = fd->cache.front()->get(); + FontDataForSizeFallback *at_size = fd->cache.begin()->value; #ifdef MODULE_FREETYPE_ENABLED if (at_size && at_size->face) { @@ -1971,7 +1984,7 @@ String TextServerFallback::font_get_supported_chars(const RID &p_font_rid) const if (fd->cache.is_empty()) { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), String()); } - FontDataForSizeFallback *at_size = fd->cache.front()->get(); + FontDataForSizeFallback *at_size = fd->cache.begin()->value; String chars; #ifdef MODULE_FREETYPE_ENABLED @@ -1989,9 +2002,8 @@ String TextServerFallback::font_get_supported_chars(const RID &p_font_rid) const #endif if (at_size) { const HashMap<int32_t, FontGlyph> &gl = at_size->glyph_map; - const int32_t *E = nullptr; - while ((E = gl.next(E))) { - chars = chars + String::chr(*E); + for (const KeyValue<int32_t, FontGlyph> &E : gl) { + chars = chars + String::chr(E.key); } } return chars; diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index c837029623..0d2fc2628d 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -67,7 +67,6 @@ #include <godot_cpp/classes/ref.hpp> #include <godot_cpp/templates/hash_map.hpp> -#include <godot_cpp/templates/map.hpp> #include <godot_cpp/templates/rid_owner.hpp> #include <godot_cpp/templates/set.hpp> #include <godot_cpp/templates/thread_work_pool.hpp> @@ -80,6 +79,7 @@ using namespace godot; #include "servers/text/text_server_extension.h" +#include "core/templates/hash_map.h" #include "core/templates/rid_owner.h" #include "core/templates/thread_work_pool.h" #include "scene/resources/texture.h" @@ -106,8 +106,8 @@ class TextServerFallback : public TextServerExtension { GDCLASS(TextServerFallback, TextServerExtension); _THREAD_SAFE_CLASS_ - Map<StringName, int32_t> feature_sets; - Map<int32_t, StringName> feature_sets_inv; + HashMap<StringName, int32_t> feature_sets; + HashMap<int32_t, StringName> feature_sets_inv; void _insert_feature_sets(); _FORCE_INLINE_ void _insert_feature(const StringName &p_name, int32_t p_tag); @@ -159,7 +159,7 @@ class TextServerFallback : public TextServerExtension { Vector<FontTexture> textures; HashMap<int32_t, FontGlyph> glyph_map; - Map<Vector2i, Vector2> kerning_map; + HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> kerning_map; #ifdef MODULE_FREETYPE_ENABLED FT_Face face = nullptr; @@ -196,15 +196,15 @@ class TextServerFallback : public TextServerExtension { String font_name; String style_name; - Map<Vector2i, FontDataForSizeFallback *> cache; + HashMap<Vector2i, FontDataForSizeFallback *, VariantHasher, VariantComparator> cache; bool face_init = false; Dictionary supported_varaitions; Dictionary feature_overrides; // Language/script support override. - Map<String, bool> language_support_overrides; - Map<String, bool> script_support_overrides; + HashMap<String, bool> language_support_overrides; + HashMap<String, bool> script_support_overrides; PackedByteArray data; const uint8_t *data_ptr; @@ -294,7 +294,7 @@ class TextServerFallback : public TextServerExtension { InlineAlignment inline_align = INLINE_ALIGNMENT_CENTER; Rect2 rect; }; - Map<Variant, EmbeddedObject> objects; + HashMap<Variant, EmbeddedObject, VariantHasher, VariantComparator> objects; /* Shaped data */ TextServer::Direction para_direction = DIRECTION_LTR; // Detected text direction. diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp index 3e6680d8d8..4847b24f61 100644 --- a/modules/visual_script/editor/visual_script_editor.cpp +++ b/modules/visual_script/editor/visual_script_editor.cpp @@ -647,6 +647,14 @@ void VisualScriptEditor::_update_graph(int p_only_id) { Control::get_theme_icon(SNAME("PackedColorArray"), SNAME("EditorIcons")) }; + // Visual script specific theme for MSDF font. + Ref<Theme> vstheme; + vstheme.instantiate(); + Ref<Font> label_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_msdf", "EditorFonts"); + vstheme->set_font("font", "Label", label_font); + vstheme->set_font("font", "LineEdit", label_font); + vstheme->set_font("font", "Button", label_font); + Ref<Texture2D> seq_port = Control::get_theme_icon(SNAME("VisualShaderPort"), SNAME("EditorIcons")); List<int> node_ids; script->get_node_list(&node_ids); @@ -960,9 +968,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) { slot_idx++; } - graph->add_child(gnode); - + gnode->set_theme(vstheme); if (gnode->is_comment()) { graph->move_child(gnode, 0); } @@ -1603,12 +1610,12 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) { List<VisualScript::DataConnection> data_connections; script->get_data_connection_list(&data_connections); - HashMap<int, Set<int>> conn_map; + HashMap<int, RBSet<int>> conn_map; for (const VisualScript::DataConnection &E : data_connections) { if (E.from_node == p_id && E.from_port == p_port) { // Push into the connections map. if (!conn_map.has(E.to_node)) { - conn_map.set(E.to_node, Set<int>()); + conn_map.insert(E.to_node, RBSet<int>()); } conn_map[E.to_node].insert(E.to_port); } @@ -1617,11 +1624,9 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) { undo_redo->add_do_method(vsn.ptr(), "remove_output_data_port", p_port); undo_redo->add_do_method(this, "_update_graph", p_id); - List<int> keys; - conn_map.get_key_list(&keys); - for (const int &E : keys) { - for (const Set<int>::Element *F = conn_map[E].front(); F; F = F->next()) { - undo_redo->add_undo_method(script.ptr(), "data_connect", p_id, p_port, E, F->get()); + for (const KeyValue<int, RBSet<int>> &E : conn_map) { + for (const RBSet<int>::Element *F = E.value.front(); F; F = F->next()) { + undo_redo->add_undo_method(script.ptr(), "data_connect", p_id, p_port, E.key, F->get()); } } @@ -1762,14 +1767,14 @@ void VisualScriptEditor::_on_nodes_paste() { return; } - Map<int, int> remap; + HashMap<int, int> remap; undo_redo->create_action(TTR("Paste VisualScript Nodes")); int idc = script->get_available_id() + 1; - Set<int> to_select; + RBSet<int> to_select; - Set<Vector2> existing_positions; + RBSet<Vector2> existing_positions; { List<int> nodes; @@ -1808,12 +1813,12 @@ void VisualScriptEditor::_on_nodes_paste() { undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); } - for (Set<VisualScript::SequenceConnection>::Element *E = clipboard->sequence_connections.front(); E; E = E->next()) { + for (RBSet<VisualScript::SequenceConnection>::Element *E = clipboard->sequence_connections.front(); E; E = E->next()) { undo_redo->add_do_method(script.ptr(), "sequence_connect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); } - for (Set<VisualScript::DataConnection>::Element *E = clipboard->data_connections.front(); E; E = E->next()) { + for (RBSet<VisualScript::DataConnection>::Element *E = clipboard->data_connections.front(); E; E = E->next()) { undo_redo->add_do_method(script.ptr(), "data_connect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); undo_redo->add_undo_method(script.ptr(), "data_disconnect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); } @@ -1883,7 +1888,7 @@ void VisualScriptEditor::_on_nodes_delete() { } void VisualScriptEditor::_on_nodes_duplicate() { - Set<int> to_duplicate; + RBSet<int> to_duplicate; for (int i = 0; i < graph->get_child_count(); i++) { GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); @@ -1902,17 +1907,17 @@ void VisualScriptEditor::_on_nodes_duplicate() { undo_redo->create_action(TTR("Duplicate VisualScript Nodes")); int idc = script->get_available_id() + 1; - Set<int> to_select; + RBSet<int> to_select; HashMap<int, int> remap; - for (Set<int>::Element *F = to_duplicate.front(); F; F = F->next()) { + for (RBSet<int>::Element *F = to_duplicate.front(); F; F = F->next()) { // Duplicate from the specific function but place it into the default func as it would lack the connections. Ref<VisualScriptNode> node = script->get_node(F->get()); Ref<VisualScriptNode> dupe = node->duplicate(true); int new_id = idc++; - remap.set(F->get(), new_id); + remap.insert(F->get(), new_id); to_select.insert(new_id); undo_redo->add_do_method(script.ptr(), "add_node", new_id, dupe, script->get_node_position(F->get()) + Vector2(20, 20)); @@ -3177,7 +3182,7 @@ void VisualScriptEditor::_graph_connect_to_empty(const String &p_from, int p_fro } } -VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &visited_nodes) { +VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_action_node, int p_port_action_output, RBSet<int> &visited_nodes) { VisualScriptNode::TypeGuess tg; tg.type = Variant::NIL; @@ -3228,7 +3233,7 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac } void VisualScriptEditor::_port_action_menu(int p_option) { - Set<int> vn; + RBSet<int> vn; switch (p_option) { case CREATE_CALL_SET_GET: { @@ -3340,7 +3345,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri #endif Vector2 pos = _get_pos_in_graph(port_action_pos); - Set<int> vn; + RBSet<int> vn; bool port_node_exists = true; if (drop_position != Vector2()) { @@ -4096,8 +4101,8 @@ void VisualScriptEditor::_menu_option(int p_what) { } break; case EDIT_CREATE_FUNCTION: { // Create Function. - Map<int, Ref<VisualScriptNode>> nodes; - Set<int> selections; + HashMap<int, Ref<VisualScriptNode>> nodes; + RBSet<int> selections; for (int i = 0; i < graph->get_child_count(); i++) { GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); if (gn) { @@ -4120,18 +4125,18 @@ void VisualScriptEditor::_menu_option(int p_what) { return; // nothing to be done if there are no valid nodes selected } - Set<VisualScript::SequenceConnection> seqmove; - Set<VisualScript::DataConnection> datamove; + RBSet<VisualScript::SequenceConnection> seqmove; + RBSet<VisualScript::DataConnection> datamove; - Set<VisualScript::SequenceConnection> seqext; - Set<VisualScript::DataConnection> dataext; + RBSet<VisualScript::SequenceConnection> seqext; + RBSet<VisualScript::DataConnection> dataext; int start_node = -1; - Set<int> end_nodes; + RBSet<int> end_nodes; if (nodes.size() == 1) { - Ref<VisualScriptNode> nd = script->get_node(nodes.front()->key()); + Ref<VisualScriptNode> nd = script->get_node(nodes.begin()->key); if (nd.is_valid() && nd->has_input_sequence_port()) { - start_node = nodes.front()->key(); + start_node = nodes.begin()->key; } else { EditorNode::get_singleton()->show_warning(TTR("Select at least one node with sequence port.")); return; @@ -4169,8 +4174,8 @@ void VisualScriptEditor::_menu_option(int p_what) { } } else { // Pick the node with input sequence. - Set<int> nodes_from; - Set<int> nodes_to; + RBSet<int> nodes_from; + RBSet<int> nodes_to; for (const VisualScript::SequenceConnection &E : seqs) { if (nodes.has(E.from_node) && nodes.has(E.to_node)) { seqmove.insert(E); @@ -4196,7 +4201,7 @@ void VisualScriptEditor::_menu_option(int p_what) { // If we still don't have a start node then, // run through the nodes and select the first tree node, // i.e. node without any input sequence but output sequence. - for (Set<int>::Element *E = nodes_from.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = nodes_from.front(); E; E = E->next()) { if (!nodes_to.has(E->get())) { start_node = E->get(); } @@ -4267,11 +4272,11 @@ void VisualScriptEditor::_menu_option(int p_what) { // Move the nodes. // Handles reconnection of sequence connections on undo, start here in case of issues. - for (Set<VisualScript::SequenceConnection>::Element *E = seqext.front(); E; E = E->next()) { + for (RBSet<VisualScript::SequenceConnection>::Element *E = seqext.front(); E; E = E->next()) { undo_redo->add_do_method(script.ptr(), "sequence_disconnect", E->get().from_node, E->get().from_output, E->get().to_node); undo_redo->add_undo_method(script.ptr(), "sequence_connect", E->get().from_node, E->get().from_output, E->get().to_node); } - for (Set<VisualScript::DataConnection>::Element *E = dataext.front(); E; E = E->next()) { + for (RBSet<VisualScript::DataConnection>::Element *E = dataext.front(); E; E = E->next()) { undo_redo->add_do_method(script.ptr(), "data_disconnect", E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); undo_redo->add_undo_method(script.ptr(), "data_connect", E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } @@ -4281,7 +4286,7 @@ void VisualScriptEditor::_menu_option(int p_what) { // Could fail with the new changes, start here when searching for bugs in create function shortcut. int m = 1; - for (Set<int>::Element *G = end_nodes.front(); G; G = G->next()) { + for (RBSet<int>::Element *G = end_nodes.front(); G; G = G->next()) { Ref<VisualScriptReturn> ret_node; ret_node.instantiate(); @@ -4333,7 +4338,7 @@ void VisualScriptEditor::_menu_option(int p_what) { // This is likely going to be very slow and I am not sure if I should keep it, // but I hope that it will not be a problem considering that we won't be creating functions so frequently, // and cyclic connections would be a problem but hopefully we won't let them get to this point. -void VisualScriptEditor::_get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const Set<int> &p_selected, Set<int> &r_end_nodes) { +void VisualScriptEditor::_get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const RBSet<int> &p_selected, RBSet<int> &r_end_nodes) { for (const VisualScript::SequenceConnection &E : p_seqs) { int from = E.from_node; int to = E.to_node; @@ -4577,6 +4582,7 @@ VisualScriptEditor::VisualScriptEditor() { add_child(graph); graph->set_v_size_flags(Control::SIZE_EXPAND_FILL); graph->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + graph->set_show_zoom_label(true); graph->connect("node_selected", callable_mp(this, &VisualScriptEditor::_node_selected)); graph->connect("begin_node_move", callable_mp(this, &VisualScriptEditor::_begin_node_move)); graph->connect("end_node_move", callable_mp(this, &VisualScriptEditor::_end_node_move)); @@ -4839,7 +4845,7 @@ Ref<VisualScriptNode> VisualScriptCustomNodes::create_node_custom(const String & } VisualScriptCustomNodes *VisualScriptCustomNodes::singleton = nullptr; -Map<String, Ref<RefCounted>> VisualScriptCustomNodes::custom_nodes; +HashMap<String, Ref<RefCounted>> VisualScriptCustomNodes::custom_nodes; VisualScriptCustomNodes::VisualScriptCustomNodes() { singleton = this; diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h index e63539ac5b..c7fd8c4a78 100644 --- a/modules/visual_script/editor/visual_script_editor.h +++ b/modules/visual_script/editor/visual_script_editor.h @@ -142,9 +142,9 @@ class VisualScriptEditor : public ScriptEditorBase { Vector<Pair<Variant::Type, String>> args; }; - Map<StringName, Color> node_colors; + HashMap<StringName, Color> node_colors; HashMap<StringName, Ref<StyleBox>> node_styles; - Map<StringName, Variant::Type> base_type_map; + HashMap<StringName, Variant::Type> base_type_map; void _update_graph_connections(); void _update_graph(int p_only_id = -1); @@ -159,11 +159,11 @@ class VisualScriptEditor : public ScriptEditorBase { String _validate_name(const String &p_name) const; struct Clipboard { - Map<int, Ref<VisualScriptNode>> nodes; - Map<int, Vector2> nodes_positions; + HashMap<int, Ref<VisualScriptNode>> nodes; + HashMap<int, Vector2> nodes_positions; - Set<VisualScript::SequenceConnection> sequence_connections; - Set<VisualScript::DataConnection> data_connections; + RBSet<VisualScript::SequenceConnection> sequence_connections; + RBSet<VisualScript::DataConnection> data_connections; }; static Clipboard *clipboard; @@ -213,7 +213,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _end_node_move(); void _move_node(int p_id, const Vector2 &p_to); - void _get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const Set<int> &p_selected, Set<int> &r_end_nodes); + void _get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const RBSet<int> &p_selected, RBSet<int> &r_end_nodes); void _node_moved(Vector2 p_from, Vector2 p_to, int p_id); void _remove_node(int p_id); @@ -287,7 +287,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _draw_color_over_button(Object *obj, Color p_color); void _button_resource_previewed(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud); - VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &p_visited_nodes); + VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, RBSet<int> &p_visited_nodes); void _member_rmb_selected(const Vector2 &p_pos); void _member_option(int p_option); @@ -359,7 +359,7 @@ protected: static void _bind_methods(); static VisualScriptCustomNodes *singleton; - static Map<String, Ref<RefCounted>> custom_nodes; + static HashMap<String, Ref<RefCounted>> custom_nodes; static Ref<VisualScriptNode> create_node_custom(const String &p_name); public: diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp index c8549ddb53..7557d12526 100644 --- a/modules/visual_script/editor/visual_script_property_selector.cpp +++ b/modules/visual_script/editor/visual_script_property_selector.cpp @@ -182,7 +182,7 @@ void VisualScriptPropertySelector::select_method_from_base_type(const String &p_ void VisualScriptPropertySelector::select_from_base_type(const String &p_base, const String &p_base_script, bool p_virtuals_only, const bool p_connecting, bool clear_text) { set_title(TTR("Select from base type")); base_type = p_base; - base_script = p_base_script.lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name + base_script = p_base_script.trim_prefix("res://").quote(); // filepath to EditorHelp::get_doc_data().name type = Variant::NIL; connecting = p_connecting; @@ -217,7 +217,7 @@ void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_scrip ERR_FAIL_COND(p_script.is_null()); base_type = p_script->get_instance_base_type(); - base_script = p_script->get_path().lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name + base_script = p_script->get_path().trim_prefix("res://").quote(); // filepath to EditorHelp::get_doc_data().name type = Variant::NIL; script = p_script->get_instance_id(); connecting = p_connecting; @@ -312,7 +312,7 @@ void VisualScriptPropertySelector::select_from_instance(Object *p_instance, cons if (p_script == nullptr) { base_script = ""; } else { - base_script = p_script->get_path().lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name + base_script = p_script->get_path().trim_prefix("res://").quote(); // filepath to EditorHelp::get_doc_data().name } type = Variant::NIL; @@ -346,7 +346,7 @@ void VisualScriptPropertySelector::select_from_visual_script(const Ref<Script> & if (p_script == nullptr) { base_script = ""; } else { - base_script = p_script->get_path().lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name + base_script = p_script->get_path().trim_prefix("res://").quote(); // filepath to EditorHelp::get_doc_data().name } type = Variant::NIL; connecting = false; @@ -726,7 +726,7 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_match_classes_init() { combined_docs.insert(class_doc.name, class_doc); } } - iterator_doc = combined_docs.front(); + iterator_doc = combined_docs.begin(); return true; } @@ -787,7 +787,7 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_node_classes_build() { } bool VisualScriptPropertySelector::SearchRunner::_phase_match_classes() { - DocData::ClassDoc &class_doc = iterator_doc->value(); + DocData::ClassDoc &class_doc = iterator_doc->value; if ( (!_is_class_disabled_by_feature_profile(class_doc.name) && !_is_class_disabled_by_scope(class_doc.name)) || _match_visual_script(class_doc)) { @@ -909,13 +909,13 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_match_classes() { } } - iterator_doc = iterator_doc->next(); + ++iterator_doc; return !iterator_doc; } bool VisualScriptPropertySelector::SearchRunner::_phase_class_items_init() { results_tree->clear(); - iterator_match = matches.front(); + iterator_match = matches.begin(); root_item = results_tree->create_item(); class_items.clear(); @@ -928,7 +928,7 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_class_items() { return true; } - ClassMatch &match = iterator_match->value(); + ClassMatch &match = iterator_match->value; if (search_flags & SEARCH_SHOW_HIERARCHY) { if (match.required()) { @@ -940,12 +940,12 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_class_items() { } } - iterator_match = iterator_match->next(); + ++iterator_match; return !iterator_match; } bool VisualScriptPropertySelector::SearchRunner::_phase_member_items_init() { - iterator_match = matches.front(); + iterator_match = matches.begin(); return true; } @@ -955,7 +955,7 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_member_items() { return true; } - ClassMatch &match = iterator_match->value(); + ClassMatch &match = iterator_match->value; TreeItem *parent = (search_flags & SEARCH_SHOW_HIERARCHY) ? class_items[match.doc->name] : root_item; bool constructor_created = false; @@ -986,7 +986,7 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_member_items() { _create_theme_property_item(parent, match.doc, match.theme_properties[i]); } - iterator_match = iterator_match->next(); + ++iterator_match; return !iterator_match; } diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h index 90a6265ab7..91d81bba47 100644 --- a/modules/visual_script/editor/visual_script_property_selector.h +++ b/modules/visual_script/editor/visual_script_property_selector.h @@ -179,15 +179,15 @@ class VisualScriptPropertySelector::SearchRunner : public RefCounted { Ref<Texture2D> empty_icon; Color disabled_color; - Map<String, DocData::ClassDoc>::Element *iterator_doc = nullptr; - Map<String, ClassMatch> matches; - Map<String, ClassMatch>::Element *iterator_match = nullptr; + HashMap<String, DocData::ClassDoc>::Iterator iterator_doc; + HashMap<String, ClassMatch> matches; + HashMap<String, ClassMatch>::Iterator iterator_match; TreeItem *root_item = nullptr; - Map<String, TreeItem *> class_items; + HashMap<String, TreeItem *> class_items; TreeItem *matched_item = nullptr; float match_highest_score = 0; - Map<String, DocData::ClassDoc> combined_docs; + HashMap<String, DocData::ClassDoc> combined_docs; List<String> vs_nodes; bool _is_class_disabled_by_feature_profile(const StringName &p_class); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 7028fead9a..a287b8e69f 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -209,8 +209,9 @@ Vector2 VisualScript::get_scroll() const { } void VisualScript::get_function_list(List<StringName> *r_functions) const { - functions.get_key_list(r_functions); - // r_functions->sort_custom<StringName::AlphCompare>(); // Don't force sorting. + for (const KeyValue<StringName, Function> &E : functions) { + r_functions->push_back(E.key); + } } int VisualScript::get_function_node_id(const StringName &p_name) const { @@ -229,7 +230,7 @@ void VisualScript::_node_ports_changed(int p_id) { { List<SequenceConnection> to_remove; - for (Set<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { + for (RBSet<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id && E->get().from_output >= vsn->get_output_sequence_port_count()) { to_remove.push_back(E->get()); } @@ -247,7 +248,7 @@ void VisualScript::_node_ports_changed(int p_id) { { List<DataConnection> to_remove; - for (Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { + for (RBSet<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id && E->get().from_port >= vsn->get_output_value_port_count()) { to_remove.push_back(E->get()); } @@ -291,7 +292,7 @@ void VisualScript::remove_node(int p_id) { { List<SequenceConnection> to_remove; - for (Set<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { + for (RBSet<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id || E->get().to_node == p_id) { to_remove.push_back(E->get()); } @@ -306,7 +307,7 @@ void VisualScript::remove_node(int p_id) { { List<DataConnection> to_remove; - for (Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { + for (RBSet<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id || E->get().to_node == p_id) { to_remove.push_back(E->get()); } @@ -346,7 +347,9 @@ Point2 VisualScript::get_node_position(int p_id) const { } void VisualScript::get_node_list(List<int> *r_nodes) const { - nodes.get_key_list(r_nodes); + for (const KeyValue<int, NodeData> &E : nodes) { + r_nodes->push_back(E.key); + } } void VisualScript::sequence_connect(int p_from_node, int p_from_output, int p_to_node) { @@ -381,7 +384,7 @@ bool VisualScript::has_sequence_connection(int p_from_node, int p_from_output, i } void VisualScript::get_sequence_connection_list(List<SequenceConnection> *r_connection) const { - for (const Set<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { + for (const RBSet<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { r_connection->push_back(E->get()); } } @@ -423,7 +426,7 @@ bool VisualScript::has_data_connection(int p_from_node, int p_from_port, int p_t } bool VisualScript::is_input_value_port_connected(int p_node, int p_port) const { - for (const Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { + for (const RBSet<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { if (E->get().to_node == p_node && E->get().to_port == p_port) { return true; } @@ -432,7 +435,7 @@ bool VisualScript::is_input_value_port_connected(int p_node, int p_port) const { } bool VisualScript::get_input_value_port_connection_source(int p_node, int p_port, int *r_node, int *r_port) const { - for (const Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { + for (const RBSet<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { if (E->get().to_node == p_node && E->get().to_port == p_port) { *r_node = E->get().from_node; *r_port = E->get().from_port; @@ -443,7 +446,7 @@ bool VisualScript::get_input_value_port_connection_source(int p_node, int p_port } void VisualScript::get_data_connection_list(List<DataConnection> *r_connection) const { - for (const Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { + for (const RBSet<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { r_connection->push_back(E->get()); } } @@ -563,8 +566,9 @@ Dictionary VisualScript::_get_variable_info(const StringName &p_name) const { } void VisualScript::get_variable_list(List<StringName> *r_variables) const { - variables.get_key_list(r_variables); - // r_variables->sort_custom<StringName::AlphCompare>(); // Don't force it. + for (const KeyValue<StringName, Variable> &E : variables) { + r_variables->push_back(E.key); + } } void VisualScript::set_instance_base_type(const StringName &p_type) { @@ -713,12 +717,11 @@ int VisualScript::get_available_id() const { // This is infinitely increasing, // so one might want to implement a better solution, // if the there is a case for huge number of nodes to be added to visual script. - List<int> nds; - nodes.get_key_list(&nds); + int max = -1; - for (const int &E : nds) { - if (E > max) { - max = E; + for (const KeyValue<int, NodeData> &E : nodes) { + if (E.key > max) { + max = E.key; } } return (max + 1); @@ -748,23 +751,20 @@ void VisualScript::_update_placeholders() { return; // No bother if no placeholders. } List<PropertyInfo> pinfo; - Map<StringName, Variant> values; - - List<StringName> keys; - variables.get_key_list(&keys); + HashMap<StringName, Variant> values; - for (const StringName &E : keys) { - if (!variables[E]._export) { + for (const KeyValue<StringName, Variable> &E : variables) { + if (!variables[E.key]._export) { continue; } - PropertyInfo p = variables[E].info; - p.name = String(E); + PropertyInfo p = variables[E.key].info; + p.name = String(E.key); pinfo.push_back(p); - values[p.name] = variables[E].default_value; + values[p.name] = variables[E.key].default_value; } - for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { + for (RBSet<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { E->get()->update(pinfo, values); } } @@ -779,20 +779,17 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) { placeholders.insert(sins); List<PropertyInfo> pinfo; - Map<StringName, Variant> values; + HashMap<StringName, Variant> values; - List<StringName> keys; - variables.get_key_list(&keys); - - for (const StringName &E : keys) { - if (!variables[E]._export) { + for (const KeyValue<StringName, Variable> &E : variables) { + if (!variables[E.key]._export) { continue; } - PropertyInfo p = variables[E].info; - p.name = String(E); + PropertyInfo p = variables[E.key].info; + p.name = String(E.key); pinfo.push_back(p); - values[p.name] = variables[E].default_value; + values[p.name] = variables[E.key].default_value; } sins->update(pinfo, values); @@ -872,14 +869,11 @@ bool VisualScript::get_property_default_value(const StringName &p_property, Vari } void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const { - List<StringName> funcs; - functions.get_key_list(&funcs); - - for (const StringName &E : funcs) { + for (const KeyValue<StringName, Function> &E : functions) { MethodInfo mi; - mi.name = E; - if (functions[E].func_id >= 0) { - Ref<VisualScriptFunction> func = nodes[functions[E].func_id].node; + mi.name = E.key; + if (functions[E.key].func_id >= 0) { + Ref<VisualScriptFunction> func = nodes[functions[E.key].func_id].node; if (func.is_valid()) { for (int i = 0; i < func->get_argument_count(); i++) { PropertyInfo arg; @@ -945,10 +939,8 @@ int VisualScript::get_member_line(const StringName &p_member) const { #ifdef TOOLS_ENABLED bool VisualScript::are_subnodes_edited() const { - List<int> keys; - nodes.get_key_list(&keys); - for (const int &F : keys) { - if (nodes[F].node->is_edited()) { + for (const KeyValue<int, NodeData> &F : nodes) { + if (F.value.node->is_edited()) { return true; } } @@ -1017,15 +1009,13 @@ void VisualScript::_set_data(const Dictionary &p_data) { // Takes all the rpc methods. rpc_functions.clear(); - List<StringName> fns; - functions.get_key_list(&fns); - for (const StringName &E : fns) { - if (functions[E].func_id >= 0 && nodes.has(functions[E].func_id)) { - Ref<VisualScriptFunction> vsf = nodes[functions[E].func_id].node; + for (const KeyValue<StringName, Function> &E : functions) { + if (E.value.func_id >= 0 && nodes.has(E.value.func_id)) { + Ref<VisualScriptFunction> vsf = nodes[E.value.func_id].node; if (vsf.is_valid()) { if (vsf->get_rpc_mode() != Multiplayer::RPC_MODE_DISABLED) { Multiplayer::RPCConfig nd; - nd.name = E; + nd.name = E.key; nd.rpc_mode = vsf->get_rpc_mode(); nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; // TODO if (rpc_functions.find(nd) == -1) { @@ -1045,13 +1035,11 @@ Dictionary VisualScript::_get_data() const { d["base_type"] = base_type; Array vars; - List<StringName> var_names; - variables.get_key_list(&var_names); - for (const StringName &E : var_names) { - Dictionary var = _get_variable_info(E); - var["name"] = E; // Make sure it's the right one. - var["default_value"] = variables[E].default_value; - var["export"] = variables[E]._export; + for (const KeyValue<StringName, Variable> &E : variables) { + Dictionary var = _get_variable_info(E.key); + var["name"] = E.key; // Make sure it's the right one. + var["default_value"] = E.value.default_value; + var["export"] = E.value._export; vars.push_back(var); } d["variables"] = vars; @@ -1073,28 +1061,24 @@ Dictionary VisualScript::_get_data() const { d["signals"] = sigs; Array funcs; - List<StringName> func_names; - functions.get_key_list(&func_names); - for (const StringName &E : func_names) { + for (const KeyValue<StringName, Function> &E : functions) { Dictionary func; - func["name"] = E; - func["function_id"] = functions[E].func_id; + func["name"] = E.key; + func["function_id"] = E.value.func_id; funcs.push_back(func); } d["functions"] = funcs; Array nds; - List<int> node_ids; - nodes.get_key_list(&node_ids); - for (const int &F : node_ids) { - nds.push_back(F); - nds.push_back(nodes[F].pos); - nds.push_back(nodes[F].node); + for (const KeyValue<int, NodeData> &F : nodes) { + nds.push_back(F.key); + nds.push_back(F.value.pos); + nds.push_back(F.value.node); } d["nodes"] = nds; Array seqconns; - for (const Set<SequenceConnection>::Element *F = sequence_connections.front(); F; F = F->next()) { + for (const RBSet<SequenceConnection>::Element *F = sequence_connections.front(); F; F = F->next()) { seqconns.push_back(F->get().from_node); seqconns.push_back(F->get().from_output); seqconns.push_back(F->get().to_node); @@ -1102,7 +1086,7 @@ Dictionary VisualScript::_get_data() const { d["sequence_connections"] = seqconns; Array dataconns; - for (const Set<DataConnection>::Element *F = data_connections.front(); F; F = F->next()) { + for (const RBSet<DataConnection>::Element *F = data_connections.front(); F; F = F->next()) { dataconns.push_back(F->get().from_node); dataconns.push_back(F->get().from_port); dataconns.push_back(F->get().to_node); @@ -1184,10 +1168,10 @@ bool VisualScript::inherits_script(const Ref<Script> &p_script) const { return this == p_script.ptr(); // There is no inheritance in visual scripts, so this is enough. } -Set<int> VisualScript::get_output_sequence_ports_connected(int from_node) { +RBSet<int> VisualScript::get_output_sequence_ports_connected(int from_node) { List<VisualScript::SequenceConnection> *sc = memnew(List<VisualScript::SequenceConnection>); get_sequence_connection_list(sc); - Set<int> connected; + RBSet<int> connected; for (List<VisualScript::SequenceConnection>::Element *E = sc->front(); E; E = E->next()) { if (E->get().from_node == from_node) { connected.insert(E->get().from_output); @@ -1199,45 +1183,41 @@ Set<int> VisualScript::get_output_sequence_ports_connected(int from_node) { VisualScript::~VisualScript() { // Remove all nodes and stuff that hold data refs. - List<int> nds; - nodes.get_key_list(&nds); - for (const int &E : nds) { - remove_node(E); + for (const KeyValue<int, NodeData> &E : nodes) { + remove_node(E.key); } } //////////////////////////////////////////// bool VisualScriptInstance::set(const StringName &p_name, const Variant &p_value) { - Map<StringName, Variant>::Element *E = variables.find(p_name); + HashMap<StringName, Variant>::Iterator E = variables.find(p_name); if (!E) { return false; } - E->get() = p_value; + E->value = p_value; return true; } bool VisualScriptInstance::get(const StringName &p_name, Variant &r_ret) const { - const Map<StringName, Variant>::Element *E = variables.find(p_name); + HashMap<StringName, Variant>::ConstIterator E = variables.find(p_name); if (!E) { return false; } - r_ret = E->get(); + r_ret = E->value; return true; } void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { - List<StringName> vars; - script->variables.get_key_list(&vars); - for (const StringName &E : vars) { - if (!script->variables[E]._export) { + for (const KeyValue<StringName, VisualScript::Variable> &E : script->variables) { + if (!E.value._export) { continue; } - PropertyInfo p = script->variables[E].info; - p.name = String(E); + PropertyInfo p = E.value.info; + p.name = String(E.key); p.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; p_properties->push_back(p); } @@ -1259,13 +1239,11 @@ Variant::Type VisualScriptInstance::get_property_type(const StringName &p_name, } void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const { - List<StringName> fns; - script->functions.get_key_list(&fns); - for (const StringName &E : fns) { + for (const KeyValue<StringName, VisualScript::Function> &E : script->functions) { MethodInfo mi; - mi.name = E; - if (script->functions[E].func_id >= 0 && script->nodes.has(script->functions[E].func_id)) { - Ref<VisualScriptFunction> vsf = script->nodes[script->functions[E].func_id].node; + mi.name = E.key; + if (E.value.func_id >= 0 && script->nodes.has(E.value.func_id)) { + Ref<VisualScriptFunction> vsf = script->nodes[E.value.func_id].node; if (vsf.is_valid()) { for (int i = 0; i < vsf->get_argument_count(); i++) { PropertyInfo arg; @@ -1337,9 +1315,9 @@ void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int } Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p_stack, int p_stack_size, VisualScriptNodeInstance *p_node, int p_flow_stack_pos, int p_pass, bool p_resuming_yield, Callable::CallError &r_error) { - Map<StringName, Function>::Element *F = functions.find(p_method); + HashMap<StringName, Function>::Iterator F = functions.find(p_method); ERR_FAIL_COND_V(!F, Variant()); - Function *f = &F->get(); + Function *f = &F->value; // This call goes separate, so it can be yielded and suspended. Variant *variant_stack = (Variant *)p_stack; @@ -1711,7 +1689,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p Variant VisualScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; //ok by default - Map<StringName, Function>::Element *F = functions.find(p_method); + HashMap<StringName, Function>::Iterator F = functions.find(p_method); if (!F) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; return Variant(); @@ -1719,7 +1697,7 @@ Variant VisualScriptInstance::callp(const StringName &p_method, const Variant ** VSDEBUG("CALLING: " + String(p_method)); - Function *f = &F->get(); + Function *f = &F->value; int total_stack_size = 0; @@ -1753,14 +1731,14 @@ Variant VisualScriptInstance::callp(const StringName &p_method, const Variant ** memset(pass_stack, 0, f->pass_stack_size * sizeof(int)); - Map<int, VisualScriptNodeInstance *>::Element *E = instances.find(f->node); + HashMap<int, VisualScriptNodeInstance *>::Iterator E = instances.find(f->node); if (!E) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; ERR_FAIL_V_MSG(Variant(), "No VisualScriptFunction node in function."); } - VisualScriptNodeInstance *node = E->get(); + VisualScriptNodeInstance *node = E->value; if (flow_stack) { flow_stack[0] = node->get_id(); @@ -1845,19 +1823,15 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o // Setup variables. { - List<StringName> keys; - script->variables.get_key_list(&keys); - for (const StringName &E : keys) { - variables[E] = script->variables[E].default_value; + for (const KeyValue<StringName, VisualScript::Variable> &E : script->variables) { + variables[E.key] = E.value.default_value; } } // Setup functions from sequence trees. { - List<StringName> keys; - script->functions.get_key_list(&keys); - for (const StringName &E : keys) { - const VisualScript::Function vsfn = p_script->functions[E]; + for (const KeyValue<StringName, VisualScript::Function> &E : script->functions) { + const VisualScript::Function &vsfn = E.value; Function function; function.node = vsfn.func_id; function.max_stack = 0; @@ -1865,10 +1839,10 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o function.pass_stack_size = 0; function.node_count = 0; - Map<StringName, int> local_var_indices; + HashMap<StringName, int> local_var_indices; if (function.node < 0) { - VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No start node in function: " + String(E)); + VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No start node in function: " + String(E.key)); ERR_CONTINUE(function.node < 0); } @@ -1876,7 +1850,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o Ref<VisualScriptFunction> func_node = script->get_node(vsfn.func_id); if (func_node.is_null()) { - VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No VisualScriptFunction typed start node in function: " + String(E)); + VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No VisualScriptFunction typed start node in function: " + String(E.key)); } ERR_CONTINUE(!func_node.is_valid()); @@ -1887,15 +1861,15 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o max_input_args = MAX(max_input_args, function.argument_count); } // Function nodes graphs. - Set<VisualScript::SequenceConnection> seqconns; - Set<VisualScript::DataConnection> dataconns; - Set<int> node_ids; + RBSet<VisualScript::SequenceConnection> seqconns; + RBSet<VisualScript::DataConnection> dataconns; + RBSet<int> node_ids; node_ids.insert(function.node); { List<int> nd_queue; nd_queue.push_back(function.node); while (!nd_queue.is_empty()) { - for (const Set<VisualScript::SequenceConnection>::Element *F = script->sequence_connections.front(); F; F = F->next()) { + for (const RBSet<VisualScript::SequenceConnection>::Element *F = script->sequence_connections.front(); F; F = F->next()) { if (nd_queue.front()->get() == F->get().from_node && !node_ids.has(F->get().to_node)) { nd_queue.push_back(F->get().to_node); node_ids.insert(F->get().to_node); @@ -1907,22 +1881,21 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o nd_queue.pop_front(); } HashMap<int, HashMap<int, Pair<int, int>>> dc_lut; // :: to -> to_port -> (from, from_port) - for (const Set<VisualScript::DataConnection>::Element *F = script->data_connections.front(); F; F = F->next()) { + for (const RBSet<VisualScript::DataConnection>::Element *F = script->data_connections.front(); F; F = F->next()) { dc_lut[F->get().to_node][F->get().to_port] = Pair<int, int>(F->get().from_node, F->get().from_port); } - for (const Set<int>::Element *F = node_ids.front(); F; F = F->next()) { + for (const RBSet<int>::Element *F = node_ids.front(); F; F = F->next()) { nd_queue.push_back(F->get()); } List<int> dc_keys; while (!nd_queue.is_empty()) { int ky = nd_queue.front()->get(); - dc_lut[ky].get_key_list(&dc_keys); - for (const int &F : dc_keys) { + for (const KeyValue<int, Pair<int, int>> &F : dc_lut[ky]) { VisualScript::DataConnection dc; - dc.from_node = dc_lut[ky][F].first; - dc.from_port = dc_lut[ky][F].second; + dc.from_node = F.value.first; + dc.from_port = F.value.second; dc.to_node = ky; - dc.to_port = F; + dc.to_port = F.key; dataconns.insert(dc); nd_queue.push_back(dc.from_node); node_ids.insert(dc.from_node); @@ -1934,7 +1907,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o //Multiple passes are required to set up this complex thing.. //First create the nodes. - for (const Set<int>::Element *F = node_ids.front(); F; F = F->next()) { + for (const RBSet<int>::Element *F = node_ids.front(); F; F = F->next()) { Ref<VisualScriptNode> node = script->nodes[F->get()].node; VisualScriptNodeInstance *instance = node->instantiate(this); // Create instance. @@ -2008,7 +1981,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o function.trash_pos = function.max_stack++; // create pos for trash // Second pass, do data connections. - for (const Set<VisualScript::DataConnection>::Element *F = dataconns.front(); F; F = F->next()) { + for (const RBSet<VisualScript::DataConnection>::Element *F = dataconns.front(); F; F = F->next()) { VisualScript::DataConnection dc = F->get(); ERR_CONTINUE(!instances.has(dc.from_node)); VisualScriptNodeInstance *from = instances[dc.from_node]; @@ -2035,7 +2008,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o } // Third pass, do sequence connections. - for (const Set<VisualScript::SequenceConnection>::Element *F = seqconns.front(); F; F = F->next()) { + for (const RBSet<VisualScript::SequenceConnection>::Element *F = seqconns.front(); F; F = F->next()) { VisualScript::SequenceConnection sc = F->get(); ERR_CONTINUE(!instances.has(sc.from_node)); VisualScriptNodeInstance *from = instances[sc.from_node]; @@ -2049,7 +2022,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o //fourth pass: // 1) unassigned input ports to default values // 2) connect unassigned output ports to trash - for (const Set<int>::Element *F = node_ids.front(); F; F = F->next()) { + for (const RBSet<int>::Element *F = node_ids.front(); F; F = F->next()) { ERR_CONTINUE(!instances.has(F->get())); Ref<VisualScriptNode> node = script->nodes[F->get()].node; @@ -2072,7 +2045,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o } } - functions[E] = function; + functions[E.key] = function; } } } @@ -2250,7 +2223,7 @@ Ref<Script> VisualScriptLanguage::make_template(const String &p_template, const return script; } -bool VisualScriptLanguage::validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const { +bool VisualScriptLanguage::validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors, List<ScriptLanguage::Warning> *r_warnings, RBSet<int> *r_safe_lines) const { return false; } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index 6b27af15f6..c28ec2268b 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -214,8 +214,8 @@ private: HashMap<int, NodeData> nodes; // Can be a sparse map. - Set<SequenceConnection> sequence_connections; - Set<DataConnection> data_connections; + RBSet<SequenceConnection> sequence_connections; + RBSet<DataConnection> data_connections; Vector2 scroll; @@ -233,15 +233,15 @@ private: HashMap<StringName, Function> functions; HashMap<StringName, Variable> variables; - Map<StringName, Vector<Argument>> custom_signals; + HashMap<StringName, Vector<Argument>> custom_signals; Vector<Multiplayer::RPCConfig> rpc_functions; - Map<Object *, VisualScriptInstance *> instances; + HashMap<Object *, VisualScriptInstance *> instances; bool is_tool_script; #ifdef TOOLS_ENABLED - Set<PlaceHolderScriptInstance *> placeholders; + RBSet<PlaceHolderScriptInstance *> placeholders; // void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override; void _update_placeholders(); @@ -283,7 +283,7 @@ public: void sequence_disconnect(int p_from_node, int p_from_output, int p_to_node); bool has_sequence_connection(int p_from_node, int p_from_output, int p_to_node) const; void get_sequence_connection_list(List<SequenceConnection> *r_connection) const; - Set<int> get_output_sequence_ports_connected(int from_node); + RBSet<int> get_output_sequence_ports_connected(int from_node); void data_connect(int p_from_node, int p_from_port, int p_to_node, int p_to_port); void data_disconnect(int p_from_node, int p_from_port, int p_to_node, int p_to_port); @@ -317,7 +317,7 @@ public: void custom_signal_swap_argument(const StringName &p_func, int p_argidx, int p_with_argidx); void remove_custom_signal(const StringName &p_name); void rename_custom_signal(const StringName &p_name, const StringName &p_new_name); - Set<int> get_output_sequence_ports_connected(const String &edited_func, int from_node); + RBSet<int> get_output_sequence_ports_connected(const String &edited_func, int from_node); void get_custom_signal_list(List<StringName> *r_custom_signals) const; @@ -376,8 +376,8 @@ class VisualScriptInstance : public ScriptInstance { Object *owner = nullptr; Ref<VisualScript> script; - Map<StringName, Variant> variables; // Using variable path, not script. - Map<int, VisualScriptNodeInstance *> instances; + HashMap<StringName, Variant> variables; // Using variable path, not script. + HashMap<int, VisualScriptNodeInstance *> instances; struct Function { int node = 0; @@ -389,7 +389,7 @@ class VisualScriptInstance : public ScriptInstance { int argument_count = 0; }; - Map<StringName, Function> functions; + HashMap<StringName, Function> functions; Vector<Variant> default_values; int max_input_args = 0; @@ -415,22 +415,22 @@ public: String to_string(bool *r_valid); bool set_variable(const StringName &p_variable, const Variant &p_value) { - Map<StringName, Variant>::Element *E = variables.find(p_variable); + HashMap<StringName, Variant>::Iterator E = variables.find(p_variable); if (!E) { return false; } - E->get() = p_value; + E->value = p_value; return true; } bool get_variable(const StringName &p_variable, Variant *r_variable) const { - const Map<StringName, Variant>::Element *E = variables.find(p_variable); + HashMap<StringName, Variant>::ConstIterator E = variables.find(p_variable); if (!E) { return false; } - *r_variable = E->get(); + *r_variable = E->value; return true; } @@ -480,7 +480,7 @@ public: typedef Ref<VisualScriptNode> (*VisualScriptNodeRegisterFunc)(const String &p_type); class VisualScriptLanguage : public ScriptLanguage { - Map<String, VisualScriptNodeRegisterFunc> register_funcs; + HashMap<String, VisualScriptNodeRegisterFunc> register_funcs; struct CallLevel { Variant *stack = nullptr; @@ -570,7 +570,7 @@ public: virtual void get_string_delimiters(List<String> *p_delimiters) const override; virtual bool is_using_templates() override; virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override; - virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const override; + virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, RBSet<int> *r_safe_lines = nullptr) const override; virtual Script *create_script() const override; virtual bool has_named_classes() const override; virtual bool supports_builtin_mode() const override; diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index dbbe74f3d5..ac33526ddc 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -3416,7 +3416,7 @@ VisualScriptConstructor::VisualScriptConstructor() { type = Variant::NIL; } -static Map<String, Pair<Variant::Type, MethodInfo>> constructor_map; +static HashMap<String, Pair<Variant::Type, MethodInfo>> constructor_map; static Ref<VisualScriptNode> create_constructor_node(const String &p_name) { ERR_FAIL_COND_V(!constructor_map.has(p_name), Ref<VisualScriptNode>()); diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp index 5ff5b2339c..b645a48c88 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp @@ -350,7 +350,6 @@ void AudioStreamOGGVorbis::maybe_update_info() { vorbis_info_init(&info); vorbis_comment_init(&comment); - int packet_count = 0; Ref<OGGPacketSequencePlayback> packet_sequence_playback = packet_sequence->instance_playback(); for (int i = 0; i < 3; i++) { @@ -369,8 +368,6 @@ void AudioStreamOGGVorbis::maybe_update_info() { err = vorbis_synthesis_headerin(&info, &comment, packet); ERR_FAIL_COND_MSG(err != 0, "Error parsing header packet " + itos(i) + ": " + itos(err)); - - packet_count++; } packet_sequence->set_sampling_rate(info.rate); diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp index 03e145216a..7ee6446313 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp @@ -57,7 +57,7 @@ String ResourceImporterOGGVorbis::get_resource_type() const { return "AudioStreamOGGVorbis"; } -bool ResourceImporterOGGVorbis::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterOGGVorbis::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } @@ -74,7 +74,7 @@ void ResourceImporterOGGVorbis::get_import_options(const String &p_path, List<Im r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0)); } -Error ResourceImporterOGGVorbis::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { +Error ResourceImporterOGGVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { bool loop = p_options["loop"]; float loop_offset = p_options["loop_offset"]; diff --git a/modules/vorbis/resource_importer_ogg_vorbis.h b/modules/vorbis/resource_importer_ogg_vorbis.h index 07291803a1..3b4a68a1fd 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.h +++ b/modules/vorbis/resource_importer_ogg_vorbis.h @@ -52,9 +52,9 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterOGGVorbis(); }; diff --git a/modules/webrtc/webrtc_multiplayer_peer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp index 0bc42b104c..6f68b84ad3 100644 --- a/modules/webrtc/webrtc_multiplayer_peer.cpp +++ b/modules/webrtc/webrtc_multiplayer_peer.cpp @@ -140,41 +140,41 @@ void WebRTCMultiplayerPeer::poll() { } void WebRTCMultiplayerPeer::_find_next_peer() { - Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.find(next_packet_peer); + HashMap<int, Ref<ConnectedPeer>>::Iterator E = peer_map.find(next_packet_peer); if (E) { - E = E->next(); + ++E; } // After last. while (E) { - if (!E->get()->connected) { - E = E->next(); + if (!E->value->connected) { + ++E; continue; } - for (const Ref<WebRTCDataChannel> &F : E->get()->channels) { + for (const Ref<WebRTCDataChannel> &F : E->value->channels) { if (F->get_available_packet_count()) { - next_packet_peer = E->key(); + next_packet_peer = E->key; return; } } - E = E->next(); + ++E; } - E = peer_map.front(); + E = peer_map.begin(); // Before last while (E) { - if (!E->get()->connected) { - E = E->next(); + if (!E->value->connected) { + ++E; continue; } - for (const Ref<WebRTCDataChannel> &F : E->get()->channels) { + for (const Ref<WebRTCDataChannel> &F : E->value->channels) { if (F->get_available_packet_count()) { - next_packet_peer = E->key(); + next_packet_peer = E->key; return; } } - if (E->key() == (int)next_packet_peer) { + if (E->key == (int)next_packet_peer) { break; } - E = E->next(); + ++E; } // No packet found next_packet_peer = 0; @@ -354,12 +354,12 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si } if (target_peer > 0) { - Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.find(target_peer); + HashMap<int, Ref<ConnectedPeer>>::Iterator E = peer_map.find(target_peer); ERR_FAIL_COND_V_MSG(!E, ERR_INVALID_PARAMETER, "Invalid target peer: " + itos(target_peer) + "."); - ERR_FAIL_COND_V_MSG(E->value()->channels.size() <= ch, ERR_INVALID_PARAMETER, vformat("Unable to send packet on channel %d, max channels: %d", ch, E->value()->channels.size())); - ERR_FAIL_COND_V(E->value()->channels[ch].is_null(), ERR_BUG); - return E->value()->channels[ch]->put_packet(p_buffer, p_buffer_size); + ERR_FAIL_COND_V_MSG(E->value->channels.size() <= ch, ERR_INVALID_PARAMETER, vformat("Unable to send packet on channel %d, max channels: %d", ch, E->value->channels.size())); + ERR_FAIL_COND_V(E->value->channels[ch].is_null(), ERR_BUG); + return E->value->channels[ch]->put_packet(p_buffer, p_buffer_size); } else { int exclude = -target_peer; diff --git a/modules/webrtc/webrtc_multiplayer_peer.h b/modules/webrtc/webrtc_multiplayer_peer.h index 6675c67867..97550a3e9d 100644 --- a/modules/webrtc/webrtc_multiplayer_peer.h +++ b/modules/webrtc/webrtc_multiplayer_peer.h @@ -69,7 +69,7 @@ private: int next_packet_peer = 0; bool server_compat = false; - Map<int, Ref<ConnectedPeer>> peer_map; + HashMap<int, Ref<ConnectedPeer>> peer_map; List<Dictionary> channels_config; void _peer_to_dict(Ref<ConnectedPeer> p_connected_peer, Dictionary &r_dict); diff --git a/modules/websocket/websocket_multiplayer_peer.h b/modules/websocket/websocket_multiplayer_peer.h index 43d9d59f38..db529a669d 100644 --- a/modules/websocket/websocket_multiplayer_peer.h +++ b/modules/websocket/websocket_multiplayer_peer.h @@ -62,7 +62,7 @@ protected: }; List<Packet> _incoming_packets; - Map<int, Ref<WebSocketPeer>> _peer_map; + HashMap<int, Ref<WebSocketPeer>> _peer_map; Packet _current_packet; bool _is_multiplayer = false; diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp index 894ba7766f..478dbb9d47 100644 --- a/modules/websocket/wsl_client.cpp +++ b/modules/websocket/wsl_client.cpp @@ -113,7 +113,7 @@ bool WSLClient::_verify_headers(String &r_protocol) { ERR_FAIL_COND_V_MSG(req[0] != "HTTP/1.1", false, "Invalid protocol. Got: '" + req[0] + "', expected 'HTTP/1.1'."); ERR_FAIL_COND_V_MSG(req[1] != "101", false, "Invalid status code. Got: '" + req[1] + "', expected '101'."); - Map<String, String> headers; + HashMap<String, String> headers; for (int i = 1; i < len; i++) { Vector<String> header = psa[i].split(":", false, 1); ERR_FAIL_COND_V_MSG(header.size() != 2, false, "Invalid header -> " + psa[i] + "."); diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp index b58b2e4724..517b9643f8 100644 --- a/modules/websocket/wsl_server.cpp +++ b/modules/websocket/wsl_server.cpp @@ -46,7 +46,7 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols, St ERR_FAIL_COND_V_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", false, "Invalid method or HTTP version."); r_resource_name = req[1]; - Map<String, String> headers; + HashMap<String, String> headers; for (int i = 1; i < len; i++) { Vector<String> header = psa[i].split(":", false, 1); ERR_FAIL_COND_V_MSG(header.size() != 2, false, "Invalid header -> " + psa[i]); diff --git a/platform/android/api/java_class_wrapper.h b/platform/android/api/java_class_wrapper.h index 96b7b48e48..ac8d6585d3 100644 --- a/platform/android/api/java_class_wrapper.h +++ b/platform/android/api/java_class_wrapper.h @@ -63,7 +63,7 @@ class JavaClass : public RefCounted { ARG_TYPE_MASK = (1 << 16) - 1 }; - Map<StringName, Variant> constant_map; + RBMap<StringName, Variant> constant_map; struct MethodInfo { bool _static = false; @@ -174,7 +174,7 @@ class JavaClass : public RefCounted { bool _call_method(JavaObject *p_instance, const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error, Variant &ret); friend class JavaClassWrapper; - Map<StringName, List<MethodInfo>> methods; + HashMap<StringName, List<MethodInfo>> methods; jclass _class; #endif @@ -207,7 +207,7 @@ class JavaClassWrapper : public Object { GDCLASS(JavaClassWrapper, Object); #ifdef ANDROID_ENABLED - Map<String, Ref<JavaClass>> class_cache; + RBMap<String, Ref<JavaClass>> class_cache; friend class JavaClass; jclass activityClass; jmethodID findClass; diff --git a/platform/android/api/jni_singleton.h b/platform/android/api/jni_singleton.h index 74ca10e5e2..8a0e021157 100644 --- a/platform/android/api/jni_singleton.h +++ b/platform/android/api/jni_singleton.h @@ -48,13 +48,13 @@ class JNISingleton : public Object { }; jobject instance; - Map<StringName, MethodData> method_map; + RBMap<StringName, MethodData> method_map; #endif public: virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override { #ifdef ANDROID_ENABLED - Map<StringName, MethodData>::Element *E = method_map.find(p_method); + RBMap<StringName, MethodData>::Element *E = method_map.find(p_method); // Check the method we're looking for is in the JNISingleton map and that // the arguments match. diff --git a/platform/android/detect.py b/platform/android/detect.py index 3319d5890c..0099ac7e0d 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -188,8 +188,11 @@ def configure(env): if env["target"].startswith("release"): if env["optimize"] == "speed": # optimize for speed (default) - env.Append(LINKFLAGS=["-O2"]) - env.Append(CCFLAGS=["-O2", "-fomit-frame-pointer"]) + # `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces + # when using `target=release_debug`. + opt = "-O3" if env["target"] == "release" else "-O2" + env.Append(LINKFLAGS=[opt]) + env.Append(CCFLAGS=[opt, "-fomit-frame-pointer"]) elif env["optimize"] == "size": # optimize for size env.Append(CCFLAGS=["-Os"]) env.Append(LINKFLAGS=["-Os"]) diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index d357cd586e..a893571e54 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -2775,7 +2775,8 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP return ERR_FILE_BAD_PATH; } - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); if (ep.step(TTR("Creating APK..."), 0)) { return ERR_SKIP; @@ -2789,7 +2790,8 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP int ret = unzGoToFirstFile(pkg); - zlib_filefunc_def io2 = zipio_create_io(); + Ref<FileAccess> io2_fa; + zlib_filefunc_def io2 = zipio_create_io(&io2_fa); String tmp_unaligned_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned." + uitos(OS::get_singleton()->get_unix_time()) + ".apk"); @@ -2985,7 +2987,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP ret = unzGoToFirstFile(tmp_unaligned); - io2 = zipio_create_io(); + io2 = zipio_create_io(&io2_fa); zipFile final_apk = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io2); // Take files from the unaligned APK and write them out to the aligned one @@ -3065,7 +3067,7 @@ void EditorExportPlatformAndroid::get_platform_features(List<String> *r_features r_features->push_back("android"); } -void EditorExportPlatformAndroid::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) { +void EditorExportPlatformAndroid::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, RBSet<String> &p_features) { } EditorExportPlatformAndroid::EditorExportPlatformAndroid() { diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index 0f267cf13a..c857850007 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -228,7 +228,7 @@ public: virtual void get_platform_features(List<String> *r_features) override; - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override; + virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, RBSet<String> &p_features) override; EditorExportPlatformAndroid(); diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index 1805807f90..349c3a3ab3 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -34,7 +34,7 @@ #include "thread_jandroid.h" bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error, Variant &ret) { - Map<StringName, List<MethodInfo>>::Element *M = methods.find(p_method); + HashMap<StringName, List<MethodInfo>>::Iterator M = methods.find(p_method); if (!M) { return false; } @@ -43,7 +43,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, ERR_FAIL_COND_V(env == nullptr, false); MethodInfo *method = nullptr; - for (MethodInfo &E : M->get()) { + for (MethodInfo &E : M->value) { if (!p_instance && !E._static) { r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; continue; diff --git a/platform/android/tts_android.cpp b/platform/android/tts_android.cpp index 528878f14e..d3f3773344 100644 --- a/platform/android/tts_android.cpp +++ b/platform/android/tts_android.cpp @@ -46,7 +46,7 @@ jmethodID TTS_Android::_pause_speaking = 0; jmethodID TTS_Android::_resume_speaking = 0; jmethodID TTS_Android::_stop_speaking = 0; -Map<int, Char16String> TTS_Android::ids; +HashMap<int, Char16String> TTS_Android::ids; void TTS_Android::setup(jobject p_tts) { JNIEnv *env = get_jni_env(); @@ -175,8 +175,8 @@ void TTS_Android::resume() { } void TTS_Android::stop() { - for (Map<int, Char16String>::Element *E = ids.front(); E; E = E->next()) { - DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, E->key()); + for (const KeyValue<int, Char16String> &E : ids) { + DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, E.key); } ids.clear(); diff --git a/platform/android/tts_android.h b/platform/android/tts_android.h index efeed94856..bc0cdb8d55 100644 --- a/platform/android/tts_android.h +++ b/platform/android/tts_android.h @@ -49,7 +49,7 @@ class TTS_Android { static jmethodID _resume_speaking; static jmethodID _stop_speaking; - static Map<int, Char16String> ids; + static HashMap<int, Char16String> ids; public: static void setup(jobject p_tts); diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index f442235e7c..392a0151be 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -47,8 +47,11 @@ def configure(env): if env["target"].startswith("release"): env.Append(CPPDEFINES=["NDEBUG", ("NS_BLOCK_ASSERTIONS", 1)]) if env["optimize"] == "speed": # optimize for speed (default) - env.Append(CCFLAGS=["-O2", "-ftree-vectorize", "-fomit-frame-pointer"]) - env.Append(LINKFLAGS=["-O2"]) + # `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces + # when using `target=release_debug`. + opt = "-O3" if env["target"] == "release" else "-O2" + env.Append(CCFLAGS=[opt, "-ftree-vectorize", "-fomit-frame-pointer"]) + env.Append(LINKFLAGS=[opt]) elif env["optimize"] == "size": # optimize for size env.Append(CCFLAGS=["-Os", "-ftree-vectorize"]) env.Append(LINKFLAGS=["-Os"]) diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp index 57bee59523..09191c958d 100644 --- a/platform/iphone/export/export_plugin.cpp +++ b/platform/iphone/export/export_plugin.cpp @@ -102,21 +102,18 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false)); } - Set<String> plist_keys; + RBSet<String> plist_keys; for (int i = 0; i < found_plugins.size(); i++) { // Editable plugin plist values PluginConfigIOS plugin = found_plugins[i]; - const String *K = nullptr; - while ((K = plugin.plist.next(K))) { - String key = *K; - PluginConfigIOS::PlistItem item = plugin.plist[key]; - switch (item.type) { + for (const KeyValue<String, PluginConfigIOS::PlistItem> &E : plugin.plist) { + switch (E.value.type) { case PluginConfigIOS::PlistItemType::STRING_INPUT: { - String preset_name = "plugins_plist/" + key; + String preset_name = "plugins_plist/" + E.key; if (!plist_keys.has(preset_name)) { - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), item.value)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), E.value.value)); plist_keys.insert(preset_name); } } break; @@ -1181,7 +1178,7 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> Vector<String> added_embedded_dependenciy_names; HashMap<String, String> plist_values; - Set<String> plugin_linker_flags; + RBSet<String> plugin_linker_flags; Error err; @@ -1258,11 +1255,10 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> // Plist // Using hash map container to remove duplicates - const String *K = nullptr; - while ((K = plugin.plist.next(K))) { - String key = *K; - PluginConfigIOS::PlistItem item = plugin.plist[key]; + for (const KeyValue<String, PluginConfigIOS::PlistItem> &E : plugin.plist) { + String key = E.key; + const PluginConfigIOS::PlistItem &item = E.value; String value; @@ -1301,10 +1297,9 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> // Updating `Info.plist` { - const String *K = nullptr; - while ((K = plist_values.next(K))) { - String key = *K; - String value = plist_values[key]; + for (const KeyValue<String, String> &E : plist_values) { + String key = E.key; + String value = E.value; if (key.is_empty() || value.is_empty()) { continue; @@ -1355,7 +1350,7 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> // Update Linker Flag Values { String result_linker_flags = " "; - for (Set<String>::Element *E = plugin_linker_flags.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = plugin_linker_flags.front(); E; E = E->next()) { const String &flag = E->get(); if (flag.length() == 0) { @@ -1458,7 +1453,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p bool found_library = false; const String project_file = "godot_ios.xcodeproj/project.pbxproj"; - Set<String> files_to_parse; + RBSet<String> files_to_parse; files_to_parse.insert("godot_ios/godot_ios-Info.plist"); files_to_parse.insert(project_file); files_to_parse.insert("godot_ios/export_options.plist"); @@ -1488,7 +1483,8 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p ERR_FAIL_COND_V(tmp_app_path.is_null(), ERR_CANT_CREATE); print_line("Unzipping..."); - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io); if (!src_pkg_zip) { EditorNode::add_io_error("Could not open export template (not a zip file?):\n" + src_pkg_name); diff --git a/platform/iphone/export/export_plugin.h b/platform/iphone/export/export_plugin.h index 2c6faed691..10a17c4bf1 100644 --- a/platform/iphone/export/export_plugin.h +++ b/platform/iphone/export/export_plugin.h @@ -204,7 +204,7 @@ public: r_features->push_back("ios"); } - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override { + virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, RBSet<String> &p_features) override { } EditorExportPlatformIOS(); diff --git a/platform/iphone/ios.mm b/platform/iphone/ios.mm index cca28cc055..79baae028a 100644 --- a/platform/iphone/ios.mm +++ b/platform/iphone/ios.mm @@ -77,7 +77,7 @@ void iOS::vibrate_haptic_engine(float p_duration_seconds) API_AVAILABLE(ios(13)) NSDictionary *hapticDict = @{ CHHapticPatternKeyPattern : @[ @{CHHapticPatternKeyEvent : @{ - CHHapticPatternKeyEventType : CHHapticEventTypeHapticTransient, + CHHapticPatternKeyEventType : CHHapticEventTypeHapticContinuous, CHHapticPatternKeyTime : @(CHHapticTimeImmediate), CHHapticPatternKeyEventDuration : @(p_duration_seconds) }, diff --git a/platform/iphone/tts_ios.h b/platform/iphone/tts_ios.h index c7defeb98f..064316b0b2 100644 --- a/platform/iphone/tts_ios.h +++ b/platform/iphone/tts_ios.h @@ -31,17 +31,21 @@ #ifndef TTS_IOS_H #define TTS_IOS_H -#include <AVFAudio/AVSpeechSynthesis.h> +#if __has_include(<AVFAudio/AVSpeechSynthesis.h>) +#import <AVFAudio/AVSpeechSynthesis.h> +#else +#import <AVFoundation/AVFoundation.h> +#endif #include "core/string/ustring.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/variant/array.h" #include "servers/display_server.h" @interface TTS_IOS : NSObject <AVSpeechSynthesizerDelegate> { bool speaking; - Map<id, int> ids; + HashMap<id, int> ids; AVSpeechSynthesizer *av_synth; List<DisplayServer::TTSUtterance> queue; diff --git a/platform/javascript/api/javascript_tools_editor_plugin.cpp b/platform/javascript/api/javascript_tools_editor_plugin.cpp index 31ce71127d..1507f32375 100644 --- a/platform/javascript/api/javascript_tools_editor_plugin.cpp +++ b/platform/javascript/api/javascript_tools_editor_plugin.cpp @@ -64,7 +64,8 @@ void JavaScriptToolsEditorPlugin::_download_zip(Variant p_v) { } String resource_path = ProjectSettings::get_singleton()->get_resource_path(); - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); // Name the downloaded ZIP file to contain the project name and download date for easier organization. // Replace characters not allowed (or risky) in Windows file names with safe characters. @@ -122,7 +123,7 @@ void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, z void JavaScriptToolsEditorPlugin::_zip_recursive(String p_path, String p_base_path, zipFile p_zip) { Ref<DirAccess> dir = DirAccess::open(p_path); - if (!dir) { + if (dir.is_null()) { WARN_PRINT("Unable to open directory for zipping: " + p_path); return; } diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index 312707c3b5..4013f80d6b 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -326,8 +326,8 @@ void DisplayServerJavaScript::tts_resume() { } void DisplayServerJavaScript::tts_stop() { - for (Map<int, CharString>::Element *E = utterance_ids.front(); E; E = E->next()) { - tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, E->key()); + for (const KeyValue<int, CharString> &E : utterance_ids) { + tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, E.key); } utterance_ids.clear(); godot_js_tts_stop(); diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h index 623546bbd0..79b0fbb652 100644 --- a/platform/javascript/display_server_javascript.h +++ b/platform/javascript/display_server_javascript.h @@ -55,7 +55,7 @@ private: EMSCRIPTEN_WEBGL_CONTEXT_HANDLE webgl_ctx = 0; #endif - Map<int, CharString> utterance_ids; + HashMap<int, CharString> utterance_ids; WindowMode window_mode = WINDOW_MODE_WINDOWED; ObjectID window_attached_instance_id = {}; diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp index 66d93d7c49..3334e7394b 100644 --- a/platform/javascript/export/export_plugin.cpp +++ b/platform/javascript/export/export_plugin.cpp @@ -33,7 +33,8 @@ #include "core/config/project_settings.h" Error EditorExportPlatformJavaScript::_extract_template(const String &p_template, const String &p_dir, const String &p_name, bool pwa) { - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); unzFile pkg = unzOpen2(p_template.utf8().get_data(), &io); if (!pkg) { @@ -92,7 +93,7 @@ Error EditorExportPlatformJavaScript::_write_or_error(const uint8_t *p_content, return OK; } -void EditorExportPlatformJavaScript::_replace_strings(Map<String, String> p_replaces, Vector<uint8_t> &r_template) { +void EditorExportPlatformJavaScript::_replace_strings(HashMap<String, String> p_replaces, Vector<uint8_t> &r_template) { String str_template = String::utf8(reinterpret_cast<const char *>(r_template.ptr()), r_template.size()); String out; Vector<String> lines = str_template.split("\n"); @@ -144,7 +145,7 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re // Replaces HTML string const String str_config = Variant(config).to_json_string(); const String custom_head_include = p_preset->get("html/head_include"); - Map<String, String> replaces; + HashMap<String, String> replaces; replaces["$GODOT_URL"] = p_name + ".js"; replaces["$GODOT_PROJECT_NAME"] = ProjectSettings::get_singleton()->get_setting("application/config/name"); replaces["$GODOT_HEAD_INCLUDE"] = head_include + custom_head_include; @@ -195,7 +196,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> & const String dir = p_path.get_base_dir(); const String name = p_path.get_file().get_basename(); const ExportMode mode = (ExportMode)(int)p_preset->get("variant/export_type"); - Map<String, String> replaces; + HashMap<String, String> replaces; replaces["@GODOT_VERSION@"] = String::num_int64(OS::get_singleton()->get_unix_time()) + "|" + String::num_int64(OS::get_singleton()->get_ticks_usec()); replaces["@GODOT_NAME@"] = proj_name.substr(0, 16); replaces["@GODOT_OFFLINE_PAGE@"] = name + ".offline.html"; diff --git a/platform/javascript/export/export_plugin.h b/platform/javascript/export/export_plugin.h index d17fd2f674..d38d6e7073 100644 --- a/platform/javascript/export/export_plugin.h +++ b/platform/javascript/export/export_plugin.h @@ -104,7 +104,7 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform { } Error _extract_template(const String &p_template, const String &p_dir, const String &p_name, bool pwa); - void _replace_strings(Map<String, String> p_replaces, Vector<uint8_t> &r_template); + void _replace_strings(HashMap<String, String> p_replaces, Vector<uint8_t> &r_template); void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, int p_flags, const Vector<SharedObject> p_shared_objects, const Dictionary &p_file_sizes); Error _add_manifest_icon(const String &p_path, const String &p_icon, int p_size, Array &r_arr); Error _build_pwa(const Ref<EditorExportPreset> &p_preset, const String p_path, const Vector<SharedObject> &p_shared_objects); @@ -138,7 +138,7 @@ public: r_features->push_back(get_os_name().to_lower()); } - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override { + virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, RBSet<String> &p_features) override { } String get_debug_protocol() const override { return "ws://"; } diff --git a/platform/javascript/export/export_server.h b/platform/javascript/export/export_server.h index f77ac3d1ad..a831b76076 100644 --- a/platform/javascript/export/export_server.h +++ b/platform/javascript/export/export_server.h @@ -41,7 +41,7 @@ class EditorHTTPServer : public RefCounted { private: Ref<TCPServer> server; - Map<String, String> mimes; + HashMap<String, String> mimes; Ref<StreamPeerTCP> tcp; Ref<StreamPeerSSL> ssl; Ref<StreamPeer> peer; diff --git a/platform/javascript/godot_webgl2.h b/platform/javascript/godot_webgl2.h new file mode 100644 index 0000000000..7c357ff66d --- /dev/null +++ b/platform/javascript/godot_webgl2.h @@ -0,0 +1,37 @@ +/*************************************************************************/ +/* godot_webgl2.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 GODOT_WEBGL2_H +#define GODOT_WEBGL2_H + +#include "GLES3/gl3.h" +#include "webgl/webgl2.h" + +#endif diff --git a/platform/javascript/js/libs/library_godot_os.js b/platform/javascript/js/libs/library_godot_os.js index 12d06a8d51..377eec3234 100644 --- a/platform/javascript/js/libs/library_godot_os.js +++ b/platform/javascript/js/libs/library_godot_os.js @@ -305,7 +305,9 @@ const GodotOS = { godot_js_os_hw_concurrency_get__sig: 'i', godot_js_os_hw_concurrency_get: function () { - return navigator.hardwareConcurrency || 1; + // TODO Godot core needs fixing to avoid spawning too many threads (> 24). + const concurrency = navigator.hardwareConcurrency || 1; + return concurrency < 2 ? concurrency : 2; }, godot_js_os_download_buffer__sig: 'viiii', diff --git a/platform/javascript/platform_config.h b/platform/javascript/platform_config.h index ba1b0d459e..1970fe0fa0 100644 --- a/platform/javascript/platform_config.h +++ b/platform/javascript/platform_config.h @@ -29,3 +29,5 @@ /*************************************************************************/ #include <alloca.h> + +#define OPENGL_INCLUDE_H "platform/javascript/godot_webgl2.h" diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index b35f0daec6..5829711698 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -2360,10 +2360,10 @@ void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu _THREAD_SAFE_METHOD_ if (p_cursor.is_valid()) { - Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); + HashMap<CursorShape, Vector<Variant>>::Iterator cursor_c = cursors_cache.find(p_shape); if (cursor_c) { - if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { + if (cursor_c->value[0] == p_cursor && cursor_c->value[1] == p_hotspot) { cursor_set_shape(p_shape); return; } @@ -3456,9 +3456,9 @@ void DisplayServerX11::process_events() { } if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_PRESSURE)) { - Map<int, Vector2>::Element *pen_pressure = xi.pen_pressure_range.find(device_id); + HashMap<int, Vector2>::Iterator pen_pressure = xi.pen_pressure_range.find(device_id); if (pen_pressure) { - Vector2 pen_pressure_range = pen_pressure->value(); + Vector2 pen_pressure_range = pen_pressure->value; if (pen_pressure_range != Vector2()) { xi.pressure_supported = true; xi.pressure = (*values - pen_pressure_range[0]) / @@ -3470,9 +3470,9 @@ void DisplayServerX11::process_events() { } if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_TILTX)) { - Map<int, Vector2>::Element *pen_tilt_x = xi.pen_tilt_x_range.find(device_id); + HashMap<int, Vector2>::Iterator pen_tilt_x = xi.pen_tilt_x_range.find(device_id); if (pen_tilt_x) { - Vector2 pen_tilt_x_range = pen_tilt_x->value(); + Vector2 pen_tilt_x_range = pen_tilt_x->value; if (pen_tilt_x_range[0] != 0 && *values < 0) { xi.tilt.x = *values / -pen_tilt_x_range[0]; } else if (pen_tilt_x_range[1] != 0) { @@ -3484,9 +3484,9 @@ void DisplayServerX11::process_events() { } if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_TILTY)) { - Map<int, Vector2>::Element *pen_tilt_y = xi.pen_tilt_y_range.find(device_id); + HashMap<int, Vector2>::Iterator pen_tilt_y = xi.pen_tilt_y_range.find(device_id); if (pen_tilt_y) { - Vector2 pen_tilt_y_range = pen_tilt_y->value(); + Vector2 pen_tilt_y_range = pen_tilt_y->value; if (pen_tilt_y_range[0] != 0 && *values < 0) { xi.tilt.y = *values / -pen_tilt_y_range[0]; } else if (pen_tilt_y_range[1] != 0) { @@ -3508,11 +3508,11 @@ void DisplayServerX11::process_events() { xi.raw_pos.x = rel_x; xi.raw_pos.y = rel_y; - Map<int, Vector2>::Element *abs_info = xi.absolute_devices.find(device_id); + HashMap<int, Vector2>::Iterator abs_info = xi.absolute_devices.find(device_id); if (abs_info) { // Absolute mode device - Vector2 mult = abs_info->value(); + Vector2 mult = abs_info->value; xi.relative_motion.x += (xi.raw_pos.x - xi.old_raw_pos.x) * mult.x; xi.relative_motion.y += (xi.raw_pos.y - xi.old_raw_pos.y) * mult.y; @@ -3557,21 +3557,21 @@ void DisplayServerX11::process_events() { } break; case XI_TouchUpdate: { - Map<int, Vector2>::Element *curr_pos_elem = xi.state.find(index); + HashMap<int, Vector2>::Iterator curr_pos_elem = xi.state.find(index); if (!curr_pos_elem) { // Defensive break; } - if (curr_pos_elem->value() != pos) { + if (curr_pos_elem->value != pos) { Ref<InputEventScreenDrag> sd; sd.instantiate(); sd->set_window_id(window_id); sd->set_index(index); sd->set_position(pos); - sd->set_relative(pos - curr_pos_elem->value()); + sd->set_relative(pos - curr_pos_elem->value); Input::get_singleton()->parse_input_event(sd); - curr_pos_elem->value() = pos; + curr_pos_elem->value = pos; } } break; #endif @@ -4112,13 +4112,13 @@ void DisplayServerX11::process_events() { void DisplayServerX11::release_rendering_thread() { #if defined(GLES3_ENABLED) -// gl_manager->release_current(); + gl_manager->release_current(); #endif } void DisplayServerX11::make_rendering_thread() { #if defined(GLES3_ENABLED) -// gl_manager->make_current(); + gl_manager->make_current(); #endif } diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index ee47d1a12c..66941fbe29 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -137,7 +137,7 @@ class DisplayServerX11 : public DisplayServer { Callable drop_files_callback; WindowID transient_parent = INVALID_WINDOW_ID; - Set<WindowID> transient_children; + RBSet<WindowID> transient_children; ObjectID instance_id; @@ -159,7 +159,7 @@ class DisplayServerX11 : public DisplayServer { unsigned int focus_order = 0; }; - Map<WindowID, WindowData> windows; + HashMap<WindowID, WindowData> windows; unsigned int last_mouse_monitor_mask = 0; Vector2i last_mouse_monitor_pos; @@ -197,12 +197,12 @@ class DisplayServerX11 : public DisplayServer { struct { int opcode; Vector<int> touch_devices; - Map<int, Vector2> absolute_devices; - Map<int, Vector2> pen_pressure_range; - Map<int, Vector2> pen_tilt_x_range; - Map<int, Vector2> pen_tilt_y_range; + HashMap<int, Vector2> absolute_devices; + HashMap<int, Vector2> pen_pressure_range; + HashMap<int, Vector2> pen_tilt_x_range; + HashMap<int, Vector2> pen_tilt_y_range; XIEventMask all_event_mask; - Map<int, Vector2> state; + HashMap<int, Vector2> state; double pressure; bool pressure_supported; Vector2 tilt; @@ -241,7 +241,7 @@ class DisplayServerX11 : public DisplayServer { Cursor cursors[CURSOR_MAX]; Cursor null_cursor; CursorShape current_cursor = CURSOR_ARROW; - Map<CursorShape, Vector<Variant>> cursors_cache; + HashMap<CursorShape, Vector<Variant>> cursors_cache; bool layered_window = false; diff --git a/platform/linuxbsd/export/export_plugin.h b/platform/linuxbsd/export/export_plugin.h index f46fc68e1d..9ae5cf827a 100644 --- a/platform/linuxbsd/export/export_plugin.h +++ b/platform/linuxbsd/export/export_plugin.h @@ -38,7 +38,7 @@ #include "scene/resources/texture.h" class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC { - Map<String, String> extensions; + HashMap<String, String> extensions; Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path); public: diff --git a/platform/linuxbsd/tts_linux.h b/platform/linuxbsd/tts_linux.h index 4d39af8970..4e3f348ae4 100644 --- a/platform/linuxbsd/tts_linux.h +++ b/platform/linuxbsd/tts_linux.h @@ -35,7 +35,7 @@ #include "core/os/thread_safe.h" #include "core/string/ustring.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/variant/array.h" #include "servers/display_server.h" @@ -49,7 +49,7 @@ class TTS_Linux { bool speaking = false; bool paused = false; int last_msg_id = -1; - Map<int, int> ids; + HashMap<int, int> ids; Thread init_thread; diff --git a/platform/osx/dir_access_osx.mm b/platform/osx/dir_access_osx.mm index d26f35e847..6bafb9470d 100644 --- a/platform/osx/dir_access_osx.mm +++ b/platform/osx/dir_access_osx.mm @@ -34,8 +34,8 @@ #include <errno.h> -#include <AppKit/NSWorkspace.h> -#include <Foundation/Foundation.h> +#import <AppKit/NSWorkspace.h> +#import <Foundation/Foundation.h> String DirAccessOSX::fix_unicode_name(const char *p_name) const { String fname; diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h index e1e5aea715..76df8b400a 100644 --- a/platform/osx/display_server_osx.h +++ b/platform/osx/display_server_osx.h @@ -45,10 +45,11 @@ #include "platform/osx/vulkan_context_osx.h" #endif // VULKAN_ENABLED -#include <AppKit/AppKit.h> -#include <AppKit/NSCursor.h> -#include <ApplicationServices/ApplicationServices.h> -#include <CoreVideo/CoreVideo.h> +#import <AppKit/AppKit.h> +#import <AppKit/NSCursor.h> +#import <ApplicationServices/ApplicationServices.h> +#import <CoreVideo/CoreVideo.h> +#import <Foundation/Foundation.h> #undef BitMap #undef CursorShape @@ -96,7 +97,7 @@ public: WindowID transient_parent = INVALID_WINDOW_ID; bool exclusive = false; - Set<WindowID> transient_children; + RBSet<WindowID> transient_children; bool layered_window = false; bool fullscreen = false; @@ -124,7 +125,7 @@ private: NSMenu *apple_menu = nullptr; NSMenu *dock_menu = nullptr; - Map<String, NSMenu *> submenu; + HashMap<String, NSMenu *> submenu; struct WarpEvent { NSTimeInterval timestamp; @@ -166,9 +167,9 @@ private: CursorShape cursor_shape = CURSOR_ARROW; NSCursor *cursors[CURSOR_MAX]; - Map<CursorShape, Vector<Variant>> cursors_cache; + HashMap<CursorShape, Vector<Variant>> cursors_cache; - Map<WindowID, WindowData> windows; + HashMap<WindowID, WindowData> windows; const NSMenu *_get_menu_root(const String &p_menu_root) const; NSMenu *_get_menu_root(const String &p_menu_root); diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 548acba923..536751432b 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -45,12 +45,12 @@ #include "main/main.h" #include "scene/resources/texture.h" -#include <Carbon/Carbon.h> -#include <Cocoa/Cocoa.h> -#include <IOKit/IOCFPlugIn.h> -#include <IOKit/IOKitLib.h> -#include <IOKit/hid/IOHIDKeys.h> -#include <IOKit/hid/IOHIDLib.h> +#import <Carbon/Carbon.h> +#import <Cocoa/Cocoa.h> +#import <IOKit/IOCFPlugIn.h> +#import <IOKit/IOKitLib.h> +#import <IOKit/hid/IOHIDKeys.h> +#import <IOKit/hid/IOHIDLib.h> #if defined(GLES3_ENABLED) #include "drivers/gles3/rasterizer_gles3.h" @@ -146,7 +146,7 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, V [wd.window_object setTabbingMode:NSWindowTabbingModeDisallowed]; } - CALayer *layer = [wd.window_view layer]; + CALayer *layer = [(NSView *)wd.window_view layer]; if (layer) { layer.contentsScale = scale; } @@ -174,7 +174,7 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, V wd.size.width = contentRect.size.width * scale; wd.size.height = contentRect.size.height * scale; - CALayer *layer = [wd.window_view layer]; + CALayer *layer = [(NSView *)wd.window_view layer]; if (layer) { layer.contentsScale = scale; } @@ -209,16 +209,16 @@ void DisplayServerOSX::_update_window_style(WindowData p_wd) { if (borderless_full) { // If the window covers up the screen set the level to above the main menu and hide on deactivate. - [p_wd.window_object setLevel:NSMainMenuWindowLevel + 1]; - [p_wd.window_object setHidesOnDeactivate:YES]; + [(NSWindow *)p_wd.window_object setLevel:NSMainMenuWindowLevel + 1]; + [(NSWindow *)p_wd.window_object setHidesOnDeactivate:YES]; } else { // Reset these when our window is not a borderless window that covers up the screen. if (p_wd.on_top && !p_wd.fullscreen) { - [p_wd.window_object setLevel:NSFloatingWindowLevel]; + [(NSWindow *)p_wd.window_object setLevel:NSFloatingWindowLevel]; } else { - [p_wd.window_object setLevel:NSNormalWindowLevel]; + [(NSWindow *)p_wd.window_object setLevel:NSNormalWindowLevel]; } - [p_wd.window_object setHidesOnDeactivate:NO]; + [(NSWindow *)p_wd.window_object setHidesOnDeactivate:NO]; } } @@ -234,7 +234,7 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled [wd.window_object setBackgroundColor:[NSColor clearColor]]; [wd.window_object setOpaque:NO]; [wd.window_object setHasShadow:NO]; - CALayer *layer = [wd.window_view layer]; + CALayer *layer = [(NSView *)wd.window_view layer]; if (layer) { [layer setBackgroundColor:[NSColor clearColor].CGColor]; [layer setOpaque:NO]; @@ -249,7 +249,7 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled [wd.window_object setBackgroundColor:[NSColor colorWithCalibratedWhite:1 alpha:1]]; [wd.window_object setOpaque:YES]; [wd.window_object setHasShadow:YES]; - CALayer *layer = [wd.window_view layer]; + CALayer *layer = [(NSView *)wd.window_view layer]; if (layer) { [layer setBackgroundColor:[NSColor colorWithCalibratedWhite:1 alpha:1].CGColor]; [layer setOpaque:YES]; @@ -1071,9 +1071,9 @@ String DisplayServerOSX::global_menu_get_item_submenu(const String &p_menu_root, if (menu_item) { const NSMenu *sub_menu = [menu_item submenu]; if (sub_menu) { - for (Map<String, NSMenu *>::Element *E = submenu.front(); E; E = E->next()) { - if (E->get() == sub_menu) { - return E->key(); + for (const KeyValue<String, NSMenu *> &E : submenu) { + if (E.value == sub_menu) { + return E.key; } } } @@ -1901,8 +1901,8 @@ Vector<DisplayServer::WindowID> DisplayServerOSX::get_window_list() const { _THREAD_SAFE_METHOD_ Vector<int> ret; - for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { - ret.push_back(E->key()); + for (const KeyValue<WindowID, WindowData> &E : windows) { + ret.push_back(E.key); } return ret; } @@ -2256,7 +2256,7 @@ void DisplayServerOSX::window_set_mode(WindowMode p_mode, WindowID p_window) { } break; case WINDOW_MODE_EXCLUSIVE_FULLSCREEN: case WINDOW_MODE_FULLSCREEN: { - [wd.window_object setLevel:NSNormalWindowLevel]; + [(NSWindow *)wd.window_object setLevel:NSNormalWindowLevel]; _set_window_per_pixel_transparency_enabled(true, p_window); if (wd.resize_disabled) { // Restore resize disabled. [wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable]; @@ -2380,9 +2380,9 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo return; } if (p_enabled) { - [wd.window_object setLevel:NSFloatingWindowLevel]; + [(NSWindow *)wd.window_object setLevel:NSFloatingWindowLevel]; } else { - [wd.window_object setLevel:NSNormalWindowLevel]; + [(NSWindow *)wd.window_object setLevel:NSNormalWindowLevel]; } } break; case WINDOW_FLAG_TRANSPARENT: { @@ -2423,7 +2423,7 @@ bool DisplayServerOSX::window_get_flag(WindowFlags p_flag, WindowID p_window) co if (wd.fullscreen) { return wd.on_top; } else { - return [wd.window_object level] == NSFloatingWindowLevel; + return [(NSWindow *)wd.window_object level] == NSFloatingWindowLevel; } } break; case WINDOW_FLAG_TRANSPARENT: { @@ -2468,8 +2468,8 @@ bool DisplayServerOSX::window_can_draw(WindowID p_window) const { bool DisplayServerOSX::can_any_window_draw() const { _THREAD_SAFE_METHOD_ - for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { - if (window_get_mode(E->key()) != WINDOW_MODE_MINIMIZED) { + for (const KeyValue<WindowID, WindowData> &E : windows) { + if (window_get_mode(E.key) != WINDOW_MODE_MINIMIZED) { return true; } } @@ -2505,9 +2505,9 @@ DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Po position /= screen_get_max_scale(); NSInteger wnum = [NSWindow windowNumberAtPoint:NSMakePoint(position.x, position.y) belowWindowWithWindowNumber:0 /*topmost*/]; - for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { - if ([E->get().window_object windowNumber] == wnum) { - return E->key(); + for (const KeyValue<WindowID, WindowData> &E : windows) { + if ([E.value.window_object windowNumber] == wnum) { + return E.key; } } return INVALID_WINDOW_ID; @@ -2678,10 +2678,10 @@ void DisplayServerOSX::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu _THREAD_SAFE_METHOD_ if (p_cursor.is_valid()) { - Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); + HashMap<CursorShape, Vector<Variant>>::Iterator cursor_c = cursors_cache.find(p_shape); if (cursor_c) { - if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { + if (cursor_c->value[0] == p_cursor && cursor_c->value[1] == p_hotspot) { cursor_set_shape(p_shape); return; } @@ -2886,8 +2886,8 @@ void DisplayServerOSX::process_events() { Input::get_singleton()->flush_buffered_events(); } - for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { - WindowData &wd = E->get(); + for (KeyValue<WindowID, WindowData> &E : windows) { + WindowData &wd = E.value; if (wd.mpath.size() > 0) { update_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]); if (Geometry2D::is_point_in_polygon(wd.mouse_pos, wd.mpath)) { @@ -3266,11 +3266,11 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode DisplayServerOSX::~DisplayServerOSX() { // Destroy all windows. - for (Map<WindowID, WindowData>::Element *E = windows.front(); E;) { - Map<WindowID, WindowData>::Element *F = E; - E = E->next(); - [F->get().window_object setContentView:nil]; - [F->get().window_object close]; + for (HashMap<WindowID, WindowData>::Iterator E = windows.begin(); E;) { + HashMap<WindowID, WindowData>::Iterator F = E; + ++E; + [F->value.window_object setContentView:nil]; + [F->value.window_object close]; } // Destroy drivers. diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp index 94ef875072..9309b9f89b 100644 --- a/platform/osx/export/export_plugin.cpp +++ b/platform/osx/export/export_plugin.cpp @@ -51,7 +51,7 @@ void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset> r_features->push_back("64"); } -bool EditorExportPlatformOSX::get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool EditorExportPlatformOSX::get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { // These options are not supported by built-in codesign, used on non macOS host. if (!OS::get_singleton()->has_feature("macos")) { if (p_option == "codesign/identity" || p_option == "codesign/timestamp" || p_option == "codesign/hardened_runtime" || p_option == "codesign/custom_options" || p_option.begins_with("notarization/")) { @@ -722,7 +722,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p return ERR_FILE_BAD_PATH; } - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); if (ep.step(TTR("Creating app bundle"), 0)) { return ERR_SKIP; @@ -1327,7 +1328,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p OS::get_singleton()->move_to_trash(p_path); } - zlib_filefunc_def io_dst = zipio_create_io(); + Ref<FileAccess> io_fa_dst; + zlib_filefunc_def io_dst = zipio_create_io(&io_fa_dst); zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io_dst); _zip_folder_recursive(zip, tmp_base_path_name, "", pkg_name); diff --git a/platform/osx/export/export_plugin.h b/platform/osx/export/export_plugin.h index 013e5eaa71..c90c5c29b2 100644 --- a/platform/osx/export/export_plugin.h +++ b/platform/osx/export/export_plugin.h @@ -101,7 +101,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform { protected: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override; virtual void get_export_options(List<ExportOption> *r_options) override; - virtual bool get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const override; public: virtual String get_name() const override { return "macOS"; } @@ -127,7 +127,7 @@ public: r_features->push_back("macos"); } - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override { + virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, RBSet<String> &p_features) override { } EditorExportPlatformOSX(); diff --git a/platform/osx/export/plist.cpp b/platform/osx/export/plist.cpp index d089233b80..36de9dd34b 100644 --- a/platform/osx/export/plist.cpp +++ b/platform/osx/export/plist.cpp @@ -140,10 +140,11 @@ size_t PListNode::get_asn1_size(uint8_t p_len_octets) const { } break; case PList::PLNodeType::PL_NODE_TYPE_DICT: { size_t size = 0; - for (const Map<String, Ref<PListNode>>::Element *it = data_dict.front(); it; it = it->next()) { + + for (const KeyValue<String, Ref<PListNode>> &E : data_dict) { size += 1 + _asn1_size_len(p_len_octets); // Sequence. - size += 1 + _asn1_size_len(p_len_octets) + it->key().utf8().length(); //Key. - size += 1 + _asn1_size_len(p_len_octets) + it->value()->get_asn1_size(p_len_octets); // Value. + size += 1 + _asn1_size_len(p_len_octets) + E.key.utf8().length(); //Key. + size += 1 + _asn1_size_len(p_len_octets) + E.value->get_asn1_size(p_len_octets); // Value. } return size; } break; @@ -225,13 +226,13 @@ bool PListNode::store_asn1(PackedByteArray &p_stream, uint8_t p_len_octets) cons case PList::PLNodeType::PL_NODE_TYPE_DICT: { p_stream.push_back(0x31); // Set. store_asn1_size(p_stream, p_len_octets); - for (const Map<String, Ref<PListNode>>::Element *it = data_dict.front(); it; it = it->next()) { - CharString cs = it->key().utf8(); + for (const KeyValue<String, Ref<PListNode>> &E : data_dict) { + CharString cs = E.key.utf8(); uint32_t size = cs.length(); // Sequence. p_stream.push_back(0x30); - uint32_t seq_size = 2 * (1 + _asn1_size_len(p_len_octets)) + size + it->value()->get_asn1_size(p_len_octets); + uint32_t seq_size = 2 * (1 + _asn1_size_len(p_len_octets)) + size + E.value->get_asn1_size(p_len_octets); if (p_len_octets > 1) { p_stream.push_back(0x80 + p_len_octets); } @@ -252,7 +253,7 @@ bool PListNode::store_asn1(PackedByteArray &p_stream, uint8_t p_len_octets) cons p_stream.push_back(cs[i]); } // Value. - valid = valid && it->value()->store_asn1(p_stream, p_len_octets); + valid = valid && E.value->store_asn1(p_stream, p_len_octets); } } break; } @@ -317,12 +318,12 @@ void PListNode::store_text(String &p_stream, uint8_t p_indent) const { case PList::PLNodeType::PL_NODE_TYPE_DICT: { p_stream += String("\t").repeat(p_indent); p_stream += "<dict>\n"; - for (const Map<String, Ref<PListNode>>::Element *it = data_dict.front(); it; it = it->next()) { + for (const KeyValue<String, Ref<PListNode>> &E : data_dict) { p_stream += String("\t").repeat(p_indent + 1); p_stream += "<key>"; - p_stream += it->key(); + p_stream += E.key; p_stream += "</key>\n"; - it->value()->store_text(p_stream, p_indent + 1); + E.value->store_text(p_stream, p_indent + 1); } p_stream += String("\t").repeat(p_indent); p_stream += "</dict>\n"; diff --git a/platform/osx/export/plist.h b/platform/osx/export/plist.h index fb4aaaa935..ba9eaec196 100644 --- a/platform/osx/export/plist.h +++ b/platform/osx/export/plist.h @@ -83,7 +83,7 @@ public: CharString data_string; Vector<Ref<PListNode>> data_array; - Map<String, Ref<PListNode>> data_dict; + HashMap<String, Ref<PListNode>> data_dict; union { int32_t data_int; bool data_bool; diff --git a/platform/osx/gl_manager_osx_legacy.h b/platform/osx/gl_manager_osx_legacy.h index b5a1b9dd98..2d4913a7a6 100644 --- a/platform/osx/gl_manager_osx_legacy.h +++ b/platform/osx/gl_manager_osx_legacy.h @@ -38,9 +38,9 @@ #include "core/templates/local_vector.h" #include "servers/display_server.h" -#include <AppKit/AppKit.h> -#include <ApplicationServices/ApplicationServices.h> -#include <CoreVideo/CoreVideo.h> +#import <AppKit/AppKit.h> +#import <ApplicationServices/ApplicationServices.h> +#import <CoreVideo/CoreVideo.h> class GLManager_OSX { public: @@ -57,7 +57,7 @@ private: NSOpenGLContext *context = nullptr; }; - Map<DisplayServer::WindowID, GLWindow> windows; + RBMap<DisplayServer::WindowID, GLWindow> windows; NSOpenGLContext *shared_context = nullptr; DisplayServer::WindowID current_window = DisplayServer::INVALID_WINDOW_ID; diff --git a/platform/osx/gl_manager_osx_legacy.mm b/platform/osx/gl_manager_osx_legacy.mm index fbe64e32a3..c769d7f5c5 100644 --- a/platform/osx/gl_manager_osx_legacy.mm +++ b/platform/osx/gl_manager_osx_legacy.mm @@ -167,8 +167,8 @@ void GLManager_OSX::make_current() { } void GLManager_OSX::swap_buffers() { - for (Map<DisplayServer::WindowID, GLWindow>::Element *E = windows.front(); E; E = E->next()) { - [E->get().context flushBuffer]; + for (const KeyValue<DisplayServer::WindowID, GLWindow> &E : windows) { + [E.value.context flushBuffer]; } } diff --git a/platform/osx/joypad_osx.h b/platform/osx/joypad_osx.h index b09d5ce34a..3f89048ce6 100644 --- a/platform/osx/joypad_osx.h +++ b/platform/osx/joypad_osx.h @@ -32,13 +32,13 @@ #define JOYPADOSX_H #ifdef MACOS_10_0_4 -#include <IOKit/hidsystem/IOHIDUsageTables.h> +#import <IOKit/hidsystem/IOHIDUsageTables.h> #else -#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h> +#import <Kernel/IOKit/hidsystem/IOHIDUsageTables.h> #endif -#include <ForceFeedback/ForceFeedback.h> -#include <ForceFeedback/ForceFeedbackConstants.h> -#include <IOKit/hid/IOHIDLib.h> +#import <ForceFeedback/ForceFeedback.h> +#import <ForceFeedback/ForceFeedbackConstants.h> +#import <IOKit/hid/IOHIDLib.h> #include "core/input/input.h" diff --git a/platform/osx/key_mapping_osx.mm b/platform/osx/key_mapping_osx.mm index fde9206824..bfec45de58 100644 --- a/platform/osx/key_mapping_osx.mm +++ b/platform/osx/key_mapping_osx.mm @@ -30,8 +30,8 @@ #include "key_mapping_osx.h" -#include <Carbon/Carbon.h> -#include <Cocoa/Cocoa.h> +#import <Carbon/Carbon.h> +#import <Cocoa/Cocoa.h> bool KeyMappingOSX::is_numpad_key(unsigned int key) { static const unsigned int table[] = { diff --git a/platform/osx/tts_osx.h b/platform/osx/tts_osx.h index 2cf6d21c18..449418e48f 100644 --- a/platform/osx/tts_osx.h +++ b/platform/osx/tts_osx.h @@ -33,17 +33,22 @@ #include "core/string/ustring.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/variant/array.h" #include "servers/display_server.h" -#include <AVFAudio/AVSpeechSynthesis.h> -#include <AppKit/AppKit.h> +#import <AppKit/AppKit.h> + +#if __has_include(<AVFAudio/AVSpeechSynthesis.h>) +#import <AVFAudio/AVSpeechSynthesis.h> +#else +#import <AVFoundation/AVFoundation.h> +#endif @interface TTS_OSX : NSObject <AVSpeechSynthesizerDelegate> { // AVSpeechSynthesizer bool speaking; - Map<id, int> ids; + HashMap<id, int> ids; // NSSpeechSynthesizer bool paused; diff --git a/platform/osx/vulkan_context_osx.h b/platform/osx/vulkan_context_osx.h index b78b4eb141..ade0f4a4c9 100644 --- a/platform/osx/vulkan_context_osx.h +++ b/platform/osx/vulkan_context_osx.h @@ -32,7 +32,7 @@ #define VULKAN_DEVICE_OSX_H #include "drivers/vulkan/vulkan_context.h" -#include <AppKit/AppKit.h> +#import <AppKit/AppKit.h> class VulkanContextOSX : public VulkanContext { virtual const char *_get_platform_surface_extension() const; diff --git a/platform/uwp/export/app_packager.cpp b/platform/uwp/export/app_packager.cpp index 2f70c3e74c..09717b9d69 100644 --- a/platform/uwp/export/app_packager.cpp +++ b/platform/uwp/export/app_packager.cpp @@ -91,7 +91,7 @@ void AppxPackager::make_content_types(const String &p_path) { tmp_file->store_string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); tmp_file->store_string("<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">"); - Map<String, String> types; + HashMap<String, String> types; for (int i = 0; i < file_metadata.size(); i++) { String ext = file_metadata[i].name.get_extension().to_lower(); diff --git a/platform/uwp/export/app_packager.h b/platform/uwp/export/app_packager.h index ea42e9bdfe..430f42d85f 100644 --- a/platform/uwp/export/app_packager.h +++ b/platform/uwp/export/app_packager.h @@ -89,7 +89,7 @@ class AppxPackager { String progress_task; Ref<FileAccess> package; - Set<String> mime_types; + RBSet<String> mime_types; Vector<FileMeta> file_metadata; diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp index 7e06bf01e3..e2e84131a3 100644 --- a/platform/uwp/export/export_plugin.cpp +++ b/platform/uwp/export/export_plugin.cpp @@ -301,7 +301,8 @@ Error EditorExportPlatformUWP::export_project(const Ref<EditorExportPreset> &p_p AppxPackager packager; packager.init(fa_pack); - zlib_filefunc_def io = zipio_create_io(); + Ref<FileAccess> io_fa; + zlib_filefunc_def io = zipio_create_io(&io_fa); if (ep.step("Creating package...", 0)) { return ERR_SKIP; @@ -498,7 +499,7 @@ void EditorExportPlatformUWP::get_platform_features(List<String> *r_features) { r_features->push_back("uwp"); } -void EditorExportPlatformUWP::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) { +void EditorExportPlatformUWP::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, RBSet<String> &p_features) { } EditorExportPlatformUWP::EditorExportPlatformUWP() { diff --git a/platform/uwp/export/export_plugin.h b/platform/uwp/export/export_plugin.h index ceb6d613b3..4eff96a432 100644 --- a/platform/uwp/export/export_plugin.h +++ b/platform/uwp/export/export_plugin.h @@ -441,7 +441,7 @@ public: virtual void get_platform_features(List<String> *r_features) override; - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override; + virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, RBSet<String> &p_features) override; EditorExportPlatformUWP(); }; diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 0b18fb74fb..b82fe5e7ad 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -269,12 +269,14 @@ def configure_msvc(env, manual_msvc_config): "dwmapi", ] - env.AppendUnique(CPPDEFINES=["VULKAN_ENABLED"]) - if not env["use_volk"]: - LIBS += ["vulkan"] - - env.AppendUnique(CPPDEFINES=["GLES3_ENABLED"]) - LIBS += ["opengl32"] + if env["vulkan"]: + env.AppendUnique(CPPDEFINES=["VULKAN_ENABLED"]) + if not env["use_volk"]: + LIBS += ["vulkan"] + + if env["opengl3"]: + env.AppendUnique(CPPDEFINES=["GLES3_ENABLED"]) + LIBS += ["opengl32"] env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS]) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index b548277f95..e771057d2e 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -607,8 +607,11 @@ void DisplayServerWindows::show_window(WindowID p_id) { _update_window_style(p_id); } - ShowWindow(wd.hWnd, (wd.no_focus || wd.is_popup) ? SW_SHOWNOACTIVATE : SW_SHOW); // Show the window. - if (!wd.no_focus && !wd.is_popup) { + if (wd.no_focus || wd.is_popup) { + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow + ShowWindow(wd.hWnd, SW_SHOWNA); + } else { + ShowWindow(wd.hWnd, SW_SHOW); SetForegroundWindow(wd.hWnd); // Slightly higher priority. SetFocus(wd.hWnd); // Set keyboard focus. } @@ -1106,6 +1109,10 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain SetWindowLongPtr(wd.hWnd, GWL_STYLE, style); SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex); + if (icon.is_valid()) { + set_icon(icon); + } + SetWindowPos(wd.hWnd, wd.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | ((wd.no_focus || wd.is_popup) ? SWP_NOACTIVATE : 0)); if (p_repaint) { @@ -1494,7 +1501,7 @@ void DisplayServerWindows::cursor_set_custom_image(const Ref<Resource> &p_cursor _THREAD_SAFE_METHOD_ if (p_cursor.is_valid()) { - Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); + RBMap<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); if (cursor_c) { if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { @@ -1794,7 +1801,9 @@ void DisplayServerWindows::make_rendering_thread() { void DisplayServerWindows::swap_buffers() { #if defined(GLES3_ENABLED) - gl_manager->swap_buffers(); + if (gl_manager) { + gl_manager->swap_buffers(); + } #endif } @@ -1895,9 +1904,11 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!p_icon.is_valid()); - Ref<Image> icon = p_icon->duplicate(); - if (icon->get_format() != Image::FORMAT_RGBA8) { - icon->convert(Image::FORMAT_RGBA8); + if (icon != p_icon) { + icon = p_icon->duplicate(); + if (icon->get_format() != Image::FORMAT_RGBA8) { + icon->convert(Image::FORMAT_RGBA8); + } } int w = icon->get_width(); int h = icon->get_height(); @@ -1946,14 +1957,18 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) { void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { _THREAD_SAFE_METHOD_ #if defined(VULKAN_ENABLED) - context_vulkan->set_vsync_mode(p_window, p_vsync_mode); + if (context_vulkan) { + context_vulkan->set_vsync_mode(p_window, p_vsync_mode); + } #endif } DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_window) const { _THREAD_SAFE_METHOD_ #if defined(VULKAN_ENABLED) - return context_vulkan->get_vsync_mode(p_window); + if (context_vulkan) { + return context_vulkan->get_vsync_mode(p_window); + } #endif return DisplayServer::VSYNC_ENABLED; } @@ -1991,7 +2006,7 @@ void DisplayServerWindows::_touch_event(WindowID p_window, bool p_pressed, float } void DisplayServerWindows::_drag_event(WindowID p_window, float p_x, float p_y, int idx) { - Map<int, Vector2>::Element *curr = touch_state.find(idx); + RBMap<int, Vector2>::Element *curr = touch_state.find(idx); if (!curr) { return; } @@ -2143,7 +2158,10 @@ void DisplayServerWindows::popup_close(WindowID p_window) { WindowID win_id = E->get(); popup_list.erase(E); - _send_window_event(windows[win_id], DisplayServerWindows::WINDOW_EVENT_CLOSE_REQUEST); + if (win_id != p_window) { + // Only request close on related windows, not this window. We are already processing it. + _send_window_event(windows[win_id], DisplayServerWindows::WINDOW_EVENT_CLOSE_REQUEST); + } E = F; } } @@ -2158,6 +2176,7 @@ LRESULT DisplayServerWindows::MouseProc(int code, WPARAM wParam, LPARAM lParam) case WM_NCRBUTTONDOWN: case WM_NCMBUTTONDOWN: case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: { MOUSEHOOKSTRUCT *ms = (MOUSEHOOKSTRUCT *)lParam; Point2i pos = Point2i(ms->pt.x, ms->pt.y); @@ -2187,8 +2206,39 @@ LRESULT DisplayServerWindows::MouseProc(int code, WPARAM wParam, LPARAM lParam) return ::CallNextHookEx(mouse_monitor, code, wParam, lParam); } -// Our default window procedure to handle processing of window-related system messages/events. -// Also known as DefProc or DefWindowProc. +// Handle a single window message received while CreateWindowEx is still on the stack and our data +// structures are not fully initialized. +LRESULT DisplayServerWindows::_handle_early_window_message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch (uMsg) { + case WM_GETMINMAXINFO: { + // We receive this during CreateWindowEx and we haven't initialized the window + // struct, so let Windows figure out the maximized size. + // Silently forward to user/default. + } break; + case WM_NCCREATE: { + // We tunnel an unowned pointer to our window context (WindowData) through the + // first possible message (WM_NCCREATE) to fix up our window context collection. + CREATESTRUCTW *pCreate = (CREATESTRUCTW *)lParam; + WindowData *pWindowData = reinterpret_cast<WindowData *>(pCreate->lpCreateParams); + + // Fix this up so we can recognize the remaining messages. + pWindowData->hWnd = hWnd; + } break; + default: { + // Additional messages during window creation should happen after we fixed + // up the data structures on WM_NCCREATE, but this might change in the future, + // so report an error here and then we can implement them. + ERR_PRINT_ONCE(vformat("Unexpected window message 0x%x received for window we cannot recognize in our collection; sequence error.", uMsg)); + } break; + } + + if (user_proc) { + return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam); + } + return DefWindowProcW(hWnd, uMsg, wParam, lParam); +} + +// The window procedure for our window class "Engine", used to handle processing of window-related system messages/events. // See: https://docs.microsoft.com/en-us/windows/win32/winmsg/window-procedures LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (drop_events) { @@ -2202,7 +2252,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA WindowID window_id = INVALID_WINDOW_ID; bool window_created = false; - // Check whether window exists. + // Check whether window exists + // FIXME this is O(n), where n is the set of currently open windows and subwindows + // we should have a secondary map from HWND to WindowID or even WindowData* alias, if we want to eliminate all the map lookups below for (const KeyValue<WindowID, WindowData> &E : windows) { if (E.value.hWnd == hWnd) { window_id = E.key; @@ -2211,10 +2263,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } } - // Window doesn't exist or creation in progress, don't handle messages yet. + // WARNING: we get called with events before the window is registered in our collection + // specifically, even the call to CreateWindowEx already calls here while still on the stack, + // so there is no way to store the window handle in our collection before we get here if (!window_created) { - window_id = window_id_counter; - ERR_FAIL_COND_V(!windows.has(window_id), 0); + // don't let code below operate on incompletely initialized window objects or missing window_id + return _handle_early_window_message(hWnd, uMsg, wParam, lParam); } // Process window messages. @@ -3382,11 +3436,17 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, WindowRect.top, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, - nullptr, nullptr, hInstance, nullptr); + nullptr, + nullptr, + hInstance, + // tunnel the WindowData we need to handle creation message + // lifetime is ensured because we are still on the stack when this is + // processed in the window proc + reinterpret_cast<void *>(&wd)); if (!wd.hWnd) { MessageBoxW(nullptr, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); windows.erase(id); - return INVALID_WINDOW_ID; + ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create Windows OS window."); } if (p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) { wd.pre_fs_valid = true; @@ -3406,7 +3466,14 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, #ifdef GLES3_ENABLED if (gl_manager) { Error err = gl_manager->window_create(id, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top); - ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Failed to create an OpenGL window."); + + // shut down OpenGL, to mirror behavior of Vulkan code + if (err != OK) { + memdelete(gl_manager); + gl_manager = nullptr; + windows.erase(id); + ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create an OpenGL window."); + } } #endif @@ -3451,6 +3518,8 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, ImmReleaseContext(wd.hWnd, wd.im_himc); wd.im_position = Vector2(); + + // FIXME this is wrong in cases where the window coordinates were changed due to full screen mode; use WindowRect wd.last_pos = p_rect.position; wd.width = p_rect.size.width; wd.height = p_rect.size.height; @@ -3741,6 +3810,7 @@ DisplayServerWindows::~DisplayServerWindows() { #ifdef GLES3_ENABLED // destroy windows .. NYI? + // FIXME wglDeleteContext is never called #endif if (windows.has(MAIN_WINDOW_ID)) { diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index c039b29c54..90f7b27b0c 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -314,7 +314,7 @@ class DisplayServerWindows : public DisplayServer { RenderingDeviceVulkan *rendering_device_vulkan = nullptr; #endif - Map<int, Vector2> touch_state; + RBMap<int, Vector2> touch_state; int pressrc; HINSTANCE hInstance; // Holds The Instance Of The Application @@ -389,7 +389,7 @@ class DisplayServerWindows : public DisplayServer { Callable drop_files_callback; WindowID transient_parent = INVALID_WINDOW_ID; - Set<WindowID> transient_children; + RBSet<WindowID> transient_children; bool is_popup = false; Rect2i parent_safe_rect; @@ -399,10 +399,11 @@ class DisplayServerWindows : public DisplayServer { HHOOK mouse_monitor = nullptr; List<WindowID> popup_list; uint64_t time_since_popup = 0; + Ref<Image> icon; WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect); WindowID window_id_counter = MAIN_WINDOW_ID; - Map<WindowID, WindowData> windows; + RBMap<WindowID, WindowData> windows; WindowID last_focused_window = INVALID_WINDOW_ID; @@ -429,7 +430,7 @@ class DisplayServerWindows : public DisplayServer { HCURSOR cursors[CURSOR_MAX] = { nullptr }; CursorShape cursor_shape = CursorShape::CURSOR_ARROW; - Map<CursorShape, Vector<Variant>> cursors_cache; + RBMap<CursorShape, Vector<Variant>> cursors_cache; void _drag_event(WindowID p_window, float p_x, float p_y, int idx); void _touch_event(WindowID p_window, bool p_pressed, float p_x, float p_y, int idx); @@ -447,6 +448,8 @@ class DisplayServerWindows : public DisplayServer { static void _dispatch_input_events(const Ref<InputEvent> &p_event); void _dispatch_input_event(const Ref<InputEvent> &p_event); + LRESULT _handle_early_window_message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + public: LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT MouseProc(int code, WPARAM wParam, LPARAM lParam); diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 7627a3cba3..45281f037c 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -106,7 +106,7 @@ List<String> EditorExportPlatformWindows::get_binary_extensions(const Ref<Editor return list; } -bool EditorExportPlatformWindows::get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool EditorExportPlatformWindows::get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { // This option is not supported by "osslsigncode", used on non-Windows host. if (!OS::get_singleton()->has_feature("windows") && p_option == "codesign/identity_type") { return false; diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index b48ee7c985..61184a8987 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -48,7 +48,7 @@ public: virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) override; virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override; virtual void get_export_options(List<ExportOption> *r_options) override; - virtual bool get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const override; virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; virtual String get_template_file_name(const String &p_target, const String &p_arch) const override; virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) const override; diff --git a/platform/windows/gl_manager_windows.cpp b/platform/windows/gl_manager_windows.cpp index a97fa99d7f..d509ff8c51 100644 --- a/platform/windows/gl_manager_windows.cpp +++ b/platform/windows/gl_manager_windows.cpp @@ -54,6 +54,18 @@ typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int *); +static String format_error_message(DWORD id) { + LPWSTR messageBuffer = nullptr; + size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, nullptr); + + String msg = "Error " + itos(id) + ": " + String::utf16((const char16_t *)messageBuffer, size); + + LocalFree(messageBuffer); + + return msg; +} + int GLManager_Windows::_find_or_create_display(GLWindow &win) { // find display NYI, only 1 supported so far if (_displays.size()) { @@ -79,7 +91,7 @@ int GLManager_Windows::_find_or_create_display(GLWindow &win) { return new_display_id; } -Error GLManager_Windows::_create_context(GLWindow &win, GLDisplay &gl_display) { +static Error _configure_pixel_format(HDC hDC) { static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 1, @@ -101,9 +113,6 @@ Error GLManager_Windows::_create_context(GLWindow &win, GLDisplay &gl_display) { 0, 0, 0 // Layer Masks Ignored }; - // alias - HDC hDC = win.hDC; - int pixel_format = ChoosePixelFormat(hDC, &pfd); if (!pixel_format) // Did Windows Find A Matching Pixel Format? { @@ -116,13 +125,24 @@ Error GLManager_Windows::_create_context(GLWindow &win, GLDisplay &gl_display) { return ERR_CANT_CREATE; // Return FALSE } - gl_display.hRC = wglCreateContext(hDC); + return OK; +} + +Error GLManager_Windows::_create_context(GLWindow &win, GLDisplay &gl_display) { + Error err = _configure_pixel_format(win.hDC); + if (err != OK) { + return err; + } + + gl_display.hRC = wglCreateContext(win.hDC); if (!gl_display.hRC) // Are We Able To Get A Rendering Context? { return ERR_CANT_CREATE; // Return FALSE } - wglMakeCurrent(hDC, gl_display.hRC); + if (!wglMakeCurrent(win.hDC, gl_display.hRC)) { + ERR_PRINT("Could not attach OpenGL context to newly created window: " + format_error_message(GetLastError())); + } int attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, //we want a 3.3 context @@ -143,57 +163,61 @@ Error GLManager_Windows::_create_context(GLWindow &win, GLDisplay &gl_display) { return ERR_CANT_CREATE; } - HGLRC new_hRC = wglCreateContextAttribsARB(hDC, 0, attribs); + HGLRC new_hRC = wglCreateContextAttribsARB(win.hDC, 0, attribs); if (!new_hRC) { wglDeleteContext(gl_display.hRC); gl_display.hRC = 0; - return ERR_CANT_CREATE; // Return false + return ERR_CANT_CREATE; } - wglMakeCurrent(hDC, nullptr); + + if (!wglMakeCurrent(win.hDC, nullptr)) { + ERR_PRINT("Could not detach OpenGL context from newly created window: " + format_error_message(GetLastError())); + } + wglDeleteContext(gl_display.hRC); gl_display.hRC = new_hRC; - if (!wglMakeCurrent(hDC, gl_display.hRC)) // Try To Activate The Rendering Context + if (!wglMakeCurrent(win.hDC, gl_display.hRC)) // Try To Activate The Rendering Context { + ERR_PRINT("Could not attach OpenGL context to newly created window with replaced OpenGL context: " + format_error_message(GetLastError())); wglDeleteContext(gl_display.hRC); gl_display.hRC = 0; - return ERR_CANT_CREATE; // Return FALSE + return ERR_CANT_CREATE; } return OK; } Error GLManager_Windows::window_create(DisplayServer::WindowID p_window_id, HWND p_hwnd, HINSTANCE p_hinstance, int p_width, int p_height) { - HDC hdc = GetDC(p_hwnd); - if (!hdc) { - return ERR_CANT_CREATE; // Return FALSE + HDC hDC = GetDC(p_hwnd); + if (!hDC) { + return ERR_CANT_CREATE; } - // make sure vector is big enough... - // we can mirror the external vector, it is simpler - // to keep the IDs identical for fast lookup - if (p_window_id >= (int)_windows.size()) { - _windows.resize(p_window_id + 1); + // configure the HDC to use a compatible pixel format + Error result = _configure_pixel_format(hDC); + if (result != OK) { + return result; } - GLWindow &win = _windows[p_window_id]; - win.in_use = true; - win.window_id = p_window_id; + GLWindow win; win.width = p_width; win.height = p_height; win.hwnd = p_hwnd; - win.hDC = hdc; + win.hDC = hDC; win.gldisplay_id = _find_or_create_display(win); if (win.gldisplay_id == -1) { - // release DC? - _windows.remove_at(_windows.size() - 1); return FAILED; } + // WARNING: p_window_id is an eternally growing integer since popup windows keep coming and going + // and each of them has a higher id than the previous, so it must be used in a map not a vector + _windows[p_window_id] = win; + // make current - window_make_current(_windows.size() - 1); + window_make_current(p_window_id); return OK; } @@ -217,11 +241,10 @@ int GLManager_Windows::window_get_height(DisplayServer::WindowID p_window_id) { void GLManager_Windows::window_destroy(DisplayServer::WindowID p_window_id) { GLWindow &win = get_window(p_window_id); - win.in_use = false; - if (_current_window == &win) { _current_window = nullptr; } + _windows.erase(p_window_id); } void GLManager_Windows::release_current() { @@ -229,7 +252,9 @@ void GLManager_Windows::release_current() { return; } - wglMakeCurrent(_current_window->hDC, nullptr); + if (!wglMakeCurrent(_current_window->hDC, nullptr)) { + ERR_PRINT("Could not detach OpenGL context from window marked current: " + format_error_message(GetLastError())); + } } void GLManager_Windows::window_make_current(DisplayServer::WindowID p_window_id) { @@ -237,10 +262,8 @@ void GLManager_Windows::window_make_current(DisplayServer::WindowID p_window_id) return; } + // crash if our data structures are out of sync, i.e. not found GLWindow &win = _windows[p_window_id]; - if (!win.in_use) { - return; - } // noop if (&win == _current_window) { @@ -248,7 +271,9 @@ void GLManager_Windows::window_make_current(DisplayServer::WindowID p_window_id) } const GLDisplay &disp = get_display(win.gldisplay_id); - wglMakeCurrent(win.hDC, disp.hRC); + if (!wglMakeCurrent(win.hDC, disp.hRC)) { + ERR_PRINT("Could not switch OpenGL context to other window: " + format_error_message(GetLastError())); + } _internal_set_current_window(&win); } @@ -257,34 +282,19 @@ void GLManager_Windows::make_current() { if (!_current_window) { return; } - if (!_current_window->in_use) { - WARN_PRINT("current window not in use!"); - return; - } const GLDisplay &disp = get_current_display(); - wglMakeCurrent(_current_window->hDC, disp.hRC); + if (!wglMakeCurrent(_current_window->hDC, disp.hRC)) { + ERR_PRINT("Could not switch OpenGL context to window marked current: " + format_error_message(GetLastError())); + } } void GLManager_Windows::swap_buffers() { - // NO NEED TO CALL SWAP BUFFERS for each window... - // see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXSwapBuffers.xml - - if (!_current_window) { - return; + // on other platforms, OpenGL swaps buffers for all windows (on all displays, really?) + // Windows swaps buffers on a per-window basis + // REVISIT: this could be structurally bad, should we have "dirty" flags then? + for (KeyValue<DisplayServer::WindowID, GLWindow> &entry : _windows) { + SwapBuffers(entry.value.hDC); } - if (!_current_window->in_use) { - WARN_PRINT("current window not in use!"); - return; - } - - // print_line("\tswap_buffers"); - - // only for debugging without drawing anything - // glClearColor(Math::randf(), 0, 1, 1); - //glClear(GL_COLOR_BUFFER_BIT); - - // const GLDisplay &disp = get_current_display(); - SwapBuffers(_current_window->hDC); } Error GLManager_Windows::initialize() { diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows.h index dc411983e8..5e43a3de2a 100644 --- a/platform/windows/gl_manager_windows.h +++ b/platform/windows/gl_manager_windows.h @@ -52,10 +52,6 @@ public: private: // any data specific to the window struct GLWindow { - bool in_use = false; - - // the external ID .. should match the GL window number .. unused I think - DisplayServer::WindowID window_id = DisplayServer::INVALID_WINDOW_ID; int width = 0; int height = 0; @@ -71,7 +67,7 @@ private: HGLRC hRC; }; - LocalVector<GLWindow> _windows; + RBMap<DisplayServer::WindowID, GLWindow> _windows; LocalVector<GLDisplay> _displays; GLWindow *_current_window = nullptr; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index d43ab47004..6f414c094c 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -129,9 +129,34 @@ void OS_Windows::initialize_debugging() { SetConsoleCtrlHandler(HandlerRoutine, TRUE); } +#ifdef WINDOWS_DEBUG_OUTPUT_ENABLED +static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) { + String err_str; + if (p_errorexp && p_errorexp[0]) { + err_str = String::utf8(p_errorexp); + } else { + err_str = String::utf8(p_file) + ":" + itos(p_line) + " - " + String::utf8(p_error); + } + + if (p_editor_notify) { + err_str += " (User)\n"; + } else { + err_str += "\n"; + } + + OutputDebugStringW((LPCWSTR)err_str.utf16().ptr()); +} +#endif + void OS_Windows::initialize() { crash_handler.initialize(); +#ifdef WINDOWS_DEBUG_OUTPUT_ENABLED + error_handlers.errfunc = _error_handler; + error_handlers.userdata = this; + add_error_handler(&error_handlers); +#endif + #ifndef WINDOWS_SUBSYSTEM_CONSOLE RedirectIOToConsole(); #endif @@ -153,7 +178,7 @@ void OS_Windows::initialize() { // long as the windows scheduler resolution (~16-30ms) even for calls like Sleep(1) timeBeginPeriod(1); - process_map = memnew((Map<ProcessID, ProcessInfo>)); + process_map = memnew((HashMap<ProcessID, ProcessInfo>)); // Add current Godot PID to the list of known PIDs ProcessInfo current_pi = {}; @@ -194,6 +219,10 @@ void OS_Windows::finalize_core() { memdelete(process_map); NetSocketPosix::cleanup(); + +#ifdef WINDOWS_DEBUG_OUTPUT_ENABLED + remove_error_handler(&error_handlers); +#endif } Error OS_Windows::get_entropy(uint8_t *r_buffer, int p_bytes) { @@ -387,6 +416,31 @@ String OS_Windows::_quote_command_line_argument(const String &p_text) const { return p_text; } +static void _append_to_pipe(char *p_bytes, int p_size, String *r_pipe, Mutex *p_pipe_mutex) { + // Try to convert from default ANSI code page to Unicode. + LocalVector<wchar_t> wchars; + int total_wchars = MultiByteToWideChar(CP_ACP, 0, p_bytes, p_size, nullptr, 0); + if (total_wchars > 0) { + wchars.resize(total_wchars); + if (MultiByteToWideChar(CP_ACP, 0, p_bytes, p_size, wchars.ptr(), total_wchars) == 0) { + wchars.clear(); + } + } + + if (p_pipe_mutex) { + p_pipe_mutex->lock(); + } + if (wchars.is_empty()) { + // Let's hope it's compatible with UTF-8. + (*r_pipe) += String::utf8(p_bytes, p_size); + } else { + (*r_pipe) += String(wchars.ptr(), total_wchars); + } + if (p_pipe_mutex) { + p_pipe_mutex->unlock(); + } +} + Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) { String path = p_path.replace("/", "\\"); String command = _quote_command_line_argument(path); @@ -435,21 +489,44 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, if (r_pipe) { CloseHandle(pipe[1]); // Close pipe write handle (only child process is writing). - char buf[4096]; + + LocalVector<char> bytes; + int bytes_in_buffer = 0; + + const int CHUNK_SIZE = 4096; DWORD read = 0; for (;;) { // Read StdOut and StdErr from pipe. - bool success = ReadFile(pipe[0], buf, 4096, &read, NULL); + bytes.resize(bytes_in_buffer + CHUNK_SIZE); + const bool success = ReadFile(pipe[0], bytes.ptr() + bytes_in_buffer, CHUNK_SIZE, &read, NULL); if (!success || read == 0) { break; } - if (p_pipe_mutex) { - p_pipe_mutex->lock(); + + // Assume that all possible encodings are ASCII-compatible. + // Break at newline to allow receiving long output in portions. + int newline_index = -1; + for (int i = read - 1; i >= 0; i--) { + if (bytes[bytes_in_buffer + i] == '\n') { + newline_index = i; + break; + } } - (*r_pipe) += String::utf8(buf, read); - if (p_pipe_mutex) { - p_pipe_mutex->unlock(); + if (newline_index == -1) { + bytes_in_buffer += read; + continue; } + + const int bytes_to_convert = bytes_in_buffer + (newline_index + 1); + _append_to_pipe(bytes.ptr(), bytes_to_convert, r_pipe, p_pipe_mutex); + + bytes_in_buffer = read - (newline_index + 1); + memmove(bytes.ptr(), bytes.ptr() + bytes_to_convert, bytes_in_buffer); } + + if (bytes_in_buffer > 0) { + _append_to_pipe(bytes.ptr(), bytes_in_buffer, r_pipe, p_pipe_mutex); + } + CloseHandle(pipe[0]); // Close pipe read handle. } else { WaitForSingleObject(pi.pi.hProcess, INFINITE); diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 378438a075..dc702c66e1 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -57,6 +57,11 @@ #include <windows.h> #include <windowsx.h> +#ifdef DEBUG_ENABLED +// forward error messages to OutputDebugString +#define WINDOWS_DEBUG_OUTPUT_ENABLED +#endif + class JoypadWindows; class OS_Windows : public OS { #ifdef STDOUT_FILE @@ -81,6 +86,10 @@ class OS_Windows : public OS { CrashHandler crash_handler; +#ifdef WINDOWS_DEBUG_OUTPUT_ENABLED + ErrorHandlerList error_handlers; +#endif + bool force_quit; HWND main_window; @@ -101,7 +110,7 @@ protected: STARTUPINFO si; PROCESS_INFORMATION pi; }; - Map<ProcessID, ProcessInfo> *process_map; + HashMap<ProcessID, ProcessInfo> *process_map; public: virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override; diff --git a/platform/windows/tts_windows.h b/platform/windows/tts_windows.h index 5da404baf9..d84a3d273a 100644 --- a/platform/windows/tts_windows.h +++ b/platform/windows/tts_windows.h @@ -33,7 +33,7 @@ #include "core/string/ustring.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/variant/array.h" #include "servers/display_server.h" @@ -54,7 +54,7 @@ class TTS_Windows { int offset; int id; }; - Map<ULONG, UTData> ids; + RBMap<ULONG, UTData> ids; static void __stdcall speech_event_callback(WPARAM wParam, LPARAM lParam); void _update_tts(); diff --git a/platform/windows/vulkan_context_win.cpp b/platform/windows/vulkan_context_win.cpp index 07c41395fb..e62c6c1dc8 100644 --- a/platform/windows/vulkan_context_win.cpp +++ b/platform/windows/vulkan_context_win.cpp @@ -28,6 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#if defined(WINDOWS_ENABLED) && defined(VULKAN_ENABLED) + #include "vulkan_context_win.h" #ifdef USE_VOLK #include <volk.h> @@ -57,3 +59,5 @@ VulkanContextWindows::VulkanContextWindows() { VulkanContextWindows::~VulkanContextWindows() { } + +#endif diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index 4734f97e23..b33c2f43d4 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -388,6 +388,7 @@ void AnimatedSprite2D::play(const StringName &p_animation, const bool p_backward } } + is_over = false; set_playing(true); } diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 70b9b769cd..9699f784a2 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -137,14 +137,14 @@ void Area2D::_body_enter_tree(ObjectID p_id) { Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); - Map<ObjectID, BodyState>::Element *E = body_map.find(p_id); + HashMap<ObjectID, BodyState>::Iterator E = body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_tree); + ERR_FAIL_COND(E->value.in_tree); - E->get().in_tree = true; + E->value.in_tree = true; emit_signal(SceneStringNames::get_singleton()->body_entered, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape); } } @@ -152,13 +152,13 @@ void Area2D::_body_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); - Map<ObjectID, BodyState>::Element *E = body_map.find(p_id); + HashMap<ObjectID, BodyState>::Iterator E = body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_tree); - E->get().in_tree = false; + ERR_FAIL_COND(!E->value.in_tree); + E->value.in_tree = false; emit_signal(SceneStringNames::get_singleton()->body_exited, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape); } } @@ -169,7 +169,7 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i Object *obj = ObjectDB::get_instance(objid); Node *node = Object::cast_to<Node>(obj); - Map<ObjectID, BodyState>::Element *E = body_map.find(objid); + HashMap<ObjectID, BodyState>::Iterator E = body_map.find(objid); if (!body_in && !E) { return; //does not exist because it was likely removed from the tree @@ -180,36 +180,36 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i if (body_in) { if (!E) { E = body_map.insert(objid, BodyState()); - E->get().rid = p_body; - E->get().rc = 0; - E->get().in_tree = node && node->is_inside_tree(); + E->value.rid = p_body; + E->value.rc = 0; + E->value.in_tree = node && node->is_inside_tree(); if (node) { node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree), make_binds(objid)); node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree), make_binds(objid)); - if (E->get().in_tree) { + if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } } } - E->get().rc++; + E->value.rc++; if (node) { - E->get().shapes.insert(ShapePair(p_body_shape, p_area_shape)); + E->value.shapes.insert(ShapePair(p_body_shape, p_area_shape)); } - if (!node || E->get().in_tree) { + if (!node || E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape); } } else { - E->get().rc--; + E->value.rc--; if (node) { - E->get().shapes.erase(ShapePair(p_body_shape, p_area_shape)); + E->value.shapes.erase(ShapePair(p_body_shape, p_area_shape)); } - bool in_tree = E->get().in_tree; - if (E->get().rc == 0) { - body_map.erase(E); + bool in_tree = E->value.in_tree; + if (E->value.rc == 0) { + body_map.remove(E); if (node) { node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree)); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree)); @@ -231,14 +231,14 @@ void Area2D::_area_enter_tree(ObjectID p_id) { Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); - Map<ObjectID, AreaState>::Element *E = area_map.find(p_id); + HashMap<ObjectID, AreaState>::Iterator E = area_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_tree); + ERR_FAIL_COND(E->value.in_tree); - E->get().in_tree = true; + E->value.in_tree = true; emit_signal(SceneStringNames::get_singleton()->area_entered, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape); } } @@ -246,13 +246,13 @@ void Area2D::_area_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); - Map<ObjectID, AreaState>::Element *E = area_map.find(p_id); + HashMap<ObjectID, AreaState>::Iterator E = area_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_tree); - E->get().in_tree = false; + ERR_FAIL_COND(!E->value.in_tree); + E->value.in_tree = false; emit_signal(SceneStringNames::get_singleton()->area_exited, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape); } } @@ -263,7 +263,7 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i Object *obj = ObjectDB::get_instance(objid); Node *node = Object::cast_to<Node>(obj); - Map<ObjectID, AreaState>::Element *E = area_map.find(objid); + HashMap<ObjectID, AreaState>::Iterator E = area_map.find(objid); if (!area_in && !E) { return; //likely removed from the tree @@ -273,36 +273,36 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i if (area_in) { if (!E) { E = area_map.insert(objid, AreaState()); - E->get().rid = p_area; - E->get().rc = 0; - E->get().in_tree = node && node->is_inside_tree(); + E->value.rid = p_area; + E->value.rc = 0; + E->value.in_tree = node && node->is_inside_tree(); if (node) { node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree), make_binds(objid)); node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree), make_binds(objid)); - if (E->get().in_tree) { + if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->area_entered, node); } } } - E->get().rc++; + E->value.rc++; if (node) { - E->get().shapes.insert(AreaShapePair(p_area_shape, p_self_shape)); + E->value.shapes.insert(AreaShapePair(p_area_shape, p_self_shape)); } - if (!node || E->get().in_tree) { + if (!node || E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, node, p_area_shape, p_self_shape); } } else { - E->get().rc--; + E->value.rc--; if (node) { - E->get().shapes.erase(AreaShapePair(p_area_shape, p_self_shape)); + E->value.shapes.erase(AreaShapePair(p_area_shape, p_self_shape)); } - bool in_tree = E->get().in_tree; - if (E->get().rc == 0) { - area_map.erase(E); + bool in_tree = E->value.in_tree; + if (E->value.rc == 0) { + area_map.remove(E); if (node) { node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree)); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree)); @@ -323,7 +323,7 @@ void Area2D::_clear_monitoring() { ERR_FAIL_COND_MSG(locked, "This function can't be used during the in/out signal."); { - Map<ObjectID, BodyState> bmcopy = body_map; + HashMap<ObjectID, BodyState> bmcopy = body_map; body_map.clear(); //disconnect all monitored stuff @@ -351,7 +351,7 @@ void Area2D::_clear_monitoring() { } { - Map<ObjectID, AreaState> bmcopy = area_map; + HashMap<ObjectID, AreaState> bmcopy = area_map; area_map.clear(); //disconnect all monitored stuff @@ -461,20 +461,20 @@ TypedArray<Area2D> Area2D::get_overlapping_areas() const { bool Area2D::overlaps_area(Node *p_area) const { ERR_FAIL_NULL_V(p_area, false); - const Map<ObjectID, AreaState>::Element *E = area_map.find(p_area->get_instance_id()); + HashMap<ObjectID, AreaState>::ConstIterator E = area_map.find(p_area->get_instance_id()); if (!E) { return false; } - return E->get().in_tree; + return E->value.in_tree; } bool Area2D::overlaps_body(Node *p_body) const { ERR_FAIL_NULL_V(p_body, false); - const Map<ObjectID, BodyState>::Element *E = body_map.find(p_body->get_instance_id()); + HashMap<ObjectID, BodyState>::ConstIterator E = body_map.find(p_body->get_instance_id()); if (!E) { return false; } - return E->get().in_tree; + return E->value.in_tree; } void Area2D::set_audio_bus_override(bool p_override) { diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index a42e7722b0..a584420ced 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -94,7 +94,7 @@ private: VSet<ShapePair> shapes; }; - Map<ObjectID, BodyState> body_map; + HashMap<ObjectID, BodyState> body_map; void _area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape); @@ -126,7 +126,7 @@ private: VSet<AreaShapePair> shapes; }; - Map<ObjectID, AreaState> area_map; + HashMap<ObjectID, AreaState> area_map; void _clear_monitoring(); bool audio_bus_override = false; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index c1328badfb..624ef70468 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -148,7 +148,7 @@ void AudioStreamPlayer2D::_update_panning() { Vector2 global_pos = get_global_position(); - Set<Viewport *> viewports = world_2d->get_viewports(); + RBSet<Viewport *> viewports = world_2d->get_viewports(); viewports.insert(get_viewport()); // TODO: This is a mediocre workaround for #50958. Remove when that bug is fixed! volume_vector.resize(4); diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index efde8d8a2b..f61dbc071d 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -57,7 +57,7 @@ void Camera2D::_update_scroll() { Size2 screen_size = _get_camera_screen_size(); Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5) : Point2()); - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_camera_moved", xform, screen_offset); + get_tree()->call_group(group_name, "_camera_moved", xform, screen_offset); }; } @@ -421,7 +421,7 @@ bool Camera2D::is_current() const { void Camera2D::make_current() { if (is_inside_tree()) { - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_make_current", this); + get_tree()->call_group(group_name, "_make_current", this); } else { current = true; } @@ -430,7 +430,7 @@ void Camera2D::make_current() { void Camera2D::clear_current() { if (is_inside_tree()) { - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_make_current", (Object *)nullptr); + get_tree()->call_group(group_name, "_make_current", (Object *)nullptr); } else { current = false; } diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 50863f2c4d..a8c12f4893 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -606,7 +606,7 @@ void CollisionObject2D::_bind_methods() { ADD_SIGNAL(MethodInfo("mouse_shape_entered", PropertyInfo(Variant::INT, "shape_idx"))); ADD_SIGNAL(MethodInfo("mouse_shape_exited", PropertyInfo(Variant::INT, "shape_idx"))); - ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,MakeStatic,KeepActive"), "set_disable_mode", "get_disable_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,Make Static,Keep Active"), "set_disable_mode", "get_disable_mode"); ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h index f2b7eecc7b..997afee6c4 100644 --- a/scene/2d/collision_object_2d.h +++ b/scene/2d/collision_object_2d.h @@ -75,7 +75,7 @@ private: int total_subshapes = 0; - Map<uint32_t, ShapeData> shapes; + RBMap<uint32_t, ShapeData> shapes; bool only_update_transform_changes = false; // This is used for sync to physics. void _apply_disabled(); diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index c8986e3c94..20840f5aea 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -32,6 +32,7 @@ #include "collision_object_2d.h" #include "core/math/geometry_2d.h" +#include "scene/2d/area_2d.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" @@ -254,6 +255,9 @@ TypedArray<String> CollisionPolygon2D::get_configuration_warnings() const { warnings.push_back(RTR("Invalid polygon. At least 2 points are needed in 'Segments' build mode.")); } } + if (one_way_collision && Object::cast_to<Area2D>(get_parent())) { + warnings.push_back(RTR("The One Way Collision property will be ignored when the parent is an Area2D.")); + } return warnings; } @@ -276,6 +280,7 @@ void CollisionPolygon2D::set_one_way_collision(bool p_enable) { if (parent) { parent->shape_owner_set_one_way_collision(owner_id, p_enable); } + update_configuration_warnings(); } bool CollisionPolygon2D::is_one_way_collision_enabled() const { diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index dd47ae6cb5..5a25b1705a 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -31,6 +31,7 @@ #include "collision_shape_2d.h" #include "collision_object_2d.h" +#include "scene/2d/area_2d.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" @@ -176,6 +177,9 @@ TypedArray<String> CollisionShape2D::get_configuration_warnings() const { if (!shape.is_valid()) { warnings.push_back(RTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!")); } + if (one_way_collision && Object::cast_to<Area2D>(get_parent())) { + warnings.push_back(RTR("The One Way Collision property will be ignored when the parent is an Area2D.")); + } Ref<ConvexPolygonShape2D> convex = shape; Ref<ConcavePolygonShape2D> concave = shape; @@ -204,6 +208,7 @@ void CollisionShape2D::set_one_way_collision(bool p_enable) { if (parent) { parent->shape_owner_set_one_way_collision(owner_id, p_enable); } + update_configuration_warnings(); } bool CollisionShape2D::is_one_way_collision_enabled() const { diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index d1e5bc11bc..b594aa3bb2 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -31,10 +31,13 @@ #include "navigation_obstacle_2d.h" #include "scene/2d/collision_shape_2d.h" +#include "scene/2d/physics_body_2d.h" #include "scene/resources/world_2d.h" #include "servers/navigation_server_2d.h" void NavigationObstacle2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle2D::get_rid); + ClassDB::bind_method(D_METHOD("set_estimate_radius", "estimate_radius"), &NavigationObstacle2D::set_estimate_radius); ClassDB::bind_method(D_METHOD("is_radius_estimated"), &NavigationObstacle2D::is_radius_estimated); ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationObstacle2D::set_radius); @@ -79,7 +82,7 @@ void NavigationObstacle2D::_notification(int p_what) { } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - if (parent_node2d) { + if (parent_node2d && parent_node2d->is_inside_tree()) { NavigationServer2D::get_singleton()->agent_set_position(agent, parent_node2d->get_global_position()); } } break; @@ -103,6 +106,11 @@ TypedArray<String> NavigationObstacle2D::get_configuration_warnings() const { warnings.push_back(RTR("The NavigationObstacle2D only serves to provide collision avoidance to a Node2D object.")); } + if (Object::cast_to<StaticBody2D>(get_parent())) { + warnings.push_back(RTR("The NavigationObstacle2D is intended for constantly moving bodies like CharacterBody2D or RigidDynamicBody2D as it creates only an RVO avoidance radius and does not follow scene geometry exactly." + "\nNot constantly moving or complete static objects should be captured with a refreshed NavigationPolygon so agents can not only avoid them but also move along those objects outline at high detail")); + } + return warnings; } @@ -122,13 +130,13 @@ void NavigationObstacle2D::reevaluate_agent_radius() { } real_t NavigationObstacle2D::estimate_agent_radius() const { - if (parent_node2d) { + if (parent_node2d && parent_node2d->is_inside_tree()) { // Estimate the radius of this physics body real_t radius = 0.0; for (int i(0); i < parent_node2d->get_child_count(); i++) { // For each collision shape CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(parent_node2d->get_child(i)); - if (cs) { + if (cs && cs->is_inside_tree()) { // Take the distance between the Body center to the shape center real_t r = cs->get_transform().get_origin().length(); if (cs->get_shape().is_valid()) { @@ -139,6 +147,9 @@ real_t NavigationObstacle2D::estimate_agent_radius() const { r *= MAX(s.x, s.y); // Takes the biggest radius radius = MAX(radius, r); + } else if (cs && !cs->is_inside_tree()) { + WARN_PRINT("A CollisionShape2D of the NavigationObstacle2D parent node was not inside the SceneTree when estimating the obstacle radius." + "\nMove the NavigationObstacle2D to a child position below any CollisionShape2D node of the parent node so the CollisionShape2D is already inside the SceneTree."); } } Vector2 s = parent_node2d->get_global_scale(); diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index 3cc9f3f2c4..f46453283c 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -302,19 +302,19 @@ void NavigationPolygon::make_polygons_from_outlines() { polygons.clear(); vertices.clear(); - Map<Vector2, int> points; + HashMap<Vector2, int> points; for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) { TPPLPoly &tp = I->get(); struct Polygon p; for (int64_t i = 0; i < tp.GetNumPoints(); i++) { - Map<Vector2, int>::Element *E = points.find(tp[i]); + HashMap<Vector2, int>::Iterator E = points.find(tp[i]); if (!E) { E = points.insert(tp[i], vertices.size()); vertices.push_back(tp[i]); } - p.indices.push_back(E->get()); + p.indices.push_back(E->value); } polygons.push_back(p); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 88f68e4142..f345d8c3c9 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -339,17 +339,17 @@ void RigidDynamicBody2D::_body_enter_tree(ObjectID p_id) { ERR_FAIL_COND(!node); ERR_FAIL_COND(!contact_monitor); - Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(p_id); + HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_scene); + ERR_FAIL_COND(E->value.in_scene); contact_monitor->locked = true; - E->get().in_scene = true; + E->value.in_scene = true; emit_signal(SceneStringNames::get_singleton()->body_entered, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape); } contact_monitor->locked = false; @@ -360,17 +360,17 @@ void RigidDynamicBody2D::_body_exit_tree(ObjectID p_id) { Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); ERR_FAIL_COND(!contact_monitor); - Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(p_id); + HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_scene); - E->get().in_scene = false; + ERR_FAIL_COND(!E->value.in_scene); + E->value.in_scene = false; contact_monitor->locked = true; emit_signal(SceneStringNames::get_singleton()->body_exited, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape); } contact_monitor->locked = false; @@ -384,45 +384,45 @@ void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!contact_monitor); - Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(objid); + HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(objid); ERR_FAIL_COND(!body_in && !E); if (body_in) { if (!E) { E = contact_monitor->body_map.insert(objid, BodyState()); - E->get().rid = p_body; - //E->get().rc=0; - E->get().in_scene = node && node->is_inside_tree(); + E->value.rid = p_body; + //E->value.rc=0; + E->value.in_scene = node && node->is_inside_tree(); if (node) { node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree), make_binds(objid)); node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree), make_binds(objid)); - if (E->get().in_scene) { + if (E->value.in_scene) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } } - //E->get().rc++; + //E->value.rc++; } if (node) { - E->get().shapes.insert(ShapePair(p_body_shape, p_local_shape)); + E->value.shapes.insert(ShapePair(p_body_shape, p_local_shape)); } - if (E->get().in_scene) { + if (E->value.in_scene) { emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape); } } else { - //E->get().rc--; + //E->value.rc--; if (node) { - E->get().shapes.erase(ShapePair(p_body_shape, p_local_shape)); + E->value.shapes.erase(ShapePair(p_body_shape, p_local_shape)); } - bool in_scene = E->get().in_scene; + bool in_scene = E->value.in_scene; - if (E->get().shapes.is_empty()) { + if (E->value.shapes.is_empty()) { if (node) { node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree)); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree)); @@ -431,7 +431,7 @@ void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p } } - contact_monitor->body_map.erase(E); + contact_monitor->body_map.remove(E); } if (node && in_scene) { emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, node, p_body_shape, p_local_shape); @@ -494,7 +494,7 @@ void RigidDynamicBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) int local_shape = p_state->get_contact_local_shape(i); int shape = p_state->get_contact_collider_shape(i); - Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(obj); + HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(obj); if (!E) { toadd[toadd_count].rid = rid; toadd[toadd_count].local_shape = local_shape; @@ -505,7 +505,7 @@ void RigidDynamicBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) } ShapePair sp(shape, local_shape); - int idx = E->get().shapes.find(sp); + int idx = E->value.shapes.find(sp); if (idx == -1) { toadd[toadd_count].rid = rid; toadd[toadd_count].local_shape = local_shape; @@ -515,7 +515,7 @@ void RigidDynamicBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) continue; } - E->get().shapes[idx].tagged = true; + E->value.shapes[idx].tagged = true; } //put the ones to remove diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 1e4483b4d0..7401fc7578 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -200,7 +200,7 @@ private: struct ContactMonitor { bool locked = false; - Map<ObjectID, BodyState> body_map; + HashMap<ObjectID, BodyState> body_map; }; ContactMonitor *contact_monitor = nullptr; diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index 2c6f2d5c00..b809bc4b8e 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -44,7 +44,7 @@ class RayCast2D : public Node2D { int against_shape = 0; Vector2 collision_point; Vector2 collision_normal; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = 1; bool exclude_parent_body = true; diff --git a/scene/2d/shape_cast_2d.h b/scene/2d/shape_cast_2d.h index 15436d6e3d..78125b08bd 100644 --- a/scene/2d/shape_cast_2d.h +++ b/scene/2d/shape_cast_2d.h @@ -46,7 +46,7 @@ class ShapeCast2D : public Node2D { RID shape_rid; Vector2 target_position = Vector2(0, 50); - Set<RID> exclude; + RBSet<RID> exclude; real_t margin = 0.0; uint32_t collision_mask = 1; bool exclude_parent_body = true; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index cab57146b1..19c341c1e1 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -34,8 +34,8 @@ #include "scene/resources/world_2d.h" #include "servers/navigation_server_2d.h" -Map<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlapping_coords_and_peering_bits() const { - Map<Vector2i, TileSet::CellNeighbor> output; +HashMap<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlapping_coords_and_peering_bits() const { + HashMap<Vector2i, TileSet::CellNeighbor> output; Ref<TileSet> tile_set = tile_map->get_tileset(); ERR_FAIL_COND_V(!tile_set.is_valid(), output); @@ -742,7 +742,7 @@ Vector2i TileMap::_coords_to_quadrant_coords(int p_layer, const Vector2i &p_coor p_coords.y > 0 ? p_coords.y / quadrant_size : (p_coords.y - (quadrant_size - 1)) / quadrant_size); } -Map<Vector2i, TileMapQuadrant>::Element *TileMap::_create_quadrant(int p_layer, const Vector2i &p_qk) { +HashMap<Vector2i, TileMapQuadrant>::Iterator TileMap::_create_quadrant(int p_layer, const Vector2i &p_qk) { ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), nullptr); TileMapQuadrant q; @@ -765,9 +765,9 @@ Map<Vector2i, TileMapQuadrant>::Element *TileMap::_create_quadrant(int p_layer, return layers[p_layer].quadrant_map.insert(p_qk, q); } -void TileMap::_make_quadrant_dirty(Map<Vector2i, TileMapQuadrant>::Element *Q) { +void TileMap::_make_quadrant_dirty(HashMap<Vector2i, TileMapQuadrant>::Iterator Q) { // Make the given quadrant dirty, then trigger an update later. - TileMapQuadrant &q = Q->get(); + TileMapQuadrant &q = Q->value; if (!q.dirty_list_element.in_list()) { layers[q.layer].dirty_quadrant_list.add(&q.dirty_list_element); } @@ -810,7 +810,7 @@ void TileMap::_update_dirty_quadrants() { for (SelfList<TileMapQuadrant> *q = dirty_quadrant_list.first(); q; q = q->next()) { q->self()->map_to_world.clear(); q->self()->world_to_map.clear(); - for (Set<Vector2i>::Element *E = q->self()->cells.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = q->self()->cells.front(); E; E = E->next()) { Vector2i pk = E->get(); Vector2i pk_world_coords = map_to_world(pk); q->self()->map_to_world[pk] = pk_world_coords; @@ -871,18 +871,18 @@ void TileMap::_recreate_layer_internals(int p_layer) { _rendering_update_layer(p_layer); // Recreate the quadrants. - const Map<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; + const HashMap<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; for (const KeyValue<Vector2i, TileMapCell> &E : tile_map) { Vector2i qk = _coords_to_quadrant_coords(p_layer, Vector2i(E.key.x, E.key.y)); - Map<Vector2i, TileMapQuadrant>::Element *Q = layers[p_layer].quadrant_map.find(qk); + HashMap<Vector2i, TileMapQuadrant>::Iterator Q = layers[p_layer].quadrant_map.find(qk); if (!Q) { Q = _create_quadrant(p_layer, qk); - layers[p_layer].dirty_quadrant_list.add(&Q->get().dirty_list_element); + layers[p_layer].dirty_quadrant_list.add(&Q->value.dirty_list_element); } Vector2i pk = E.key; - Q->get().cells.insert(pk); + Q->value.cells.insert(pk); _make_quadrant_dirty(Q); } @@ -896,9 +896,9 @@ void TileMap::_recreate_internals() { } } -void TileMap::_erase_quadrant(Map<Vector2i, TileMapQuadrant>::Element *Q) { +void TileMap::_erase_quadrant(HashMap<Vector2i, TileMapQuadrant>::Iterator Q) { // Remove a quadrant. - TileMapQuadrant *q = &(Q->get()); + TileMapQuadrant *q = &(Q->value); // Call the cleanup_quadrant method on plugins. if (tile_set.is_valid()) { @@ -917,7 +917,7 @@ void TileMap::_erase_quadrant(Map<Vector2i, TileMapQuadrant>::Element *Q) { RenderingServer *rs = RenderingServer::get_singleton(); rs->free(q->debug_canvas_item); - layers[q->layer].quadrant_map.erase(Q); + layers[q->layer].quadrant_map.remove(Q); rect_cache_dirty = true; } @@ -926,7 +926,7 @@ void TileMap::_clear_layer_internals(int p_layer) { // Clear quadrants. while (layers[p_layer].quadrant_map.size()) { - _erase_quadrant(layers[p_layer].quadrant_map.front()); + _erase_quadrant(layers[p_layer].quadrant_map.begin()); } // Clear the layers internals. @@ -954,15 +954,17 @@ void TileMap::_recompute_rect_cache() { } Rect2 r_total; + bool first = true; for (unsigned int layer = 0; layer < layers.size(); layer++) { - for (const Map<Vector2i, TileMapQuadrant>::Element *E = layers[layer].quadrant_map.front(); E; E = E->next()) { + for (const KeyValue<Vector2i, TileMapQuadrant> &E : layers[layer].quadrant_map) { Rect2 r; - r.position = map_to_world(E->key() * get_effective_quadrant_size(layer)); - r.expand_to(map_to_world((E->key() + Vector2i(1, 0)) * get_effective_quadrant_size(layer))); - r.expand_to(map_to_world((E->key() + Vector2i(1, 1)) * get_effective_quadrant_size(layer))); - r.expand_to(map_to_world((E->key() + Vector2i(0, 1)) * get_effective_quadrant_size(layer))); - if (E == layers[layer].quadrant_map.front()) { + r.position = map_to_world(E.key * get_effective_quadrant_size(layer)); + r.expand_to(map_to_world((E.key + Vector2i(1, 0)) * get_effective_quadrant_size(layer))); + r.expand_to(map_to_world((E.key + Vector2i(1, 1)) * get_effective_quadrant_size(layer))); + r.expand_to(map_to_world((E.key + Vector2i(0, 1)) * get_effective_quadrant_size(layer))); + if (first) { r_total = r; + first = false; } else { r_total = r_total.merge(r); } @@ -1201,7 +1203,7 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List for (int layer = 0; layer < (int)layers.size(); layer++) { // Sort the quadrants coords per world coordinates - Map<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator> world_to_map; + RBMap<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator> world_to_map; for (const KeyValue<Vector2i, TileMapQuadrant> &E : layers[layer].quadrant_map) { world_to_map[map_to_world(E.key)] = E.key; } @@ -1248,7 +1250,7 @@ void TileMap::_rendering_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { // Draw a placeholder for scenes needing one. RenderingServer *rs = RenderingServer::get_singleton(); Vector2 quadrant_pos = map_to_world(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); - for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) { + for (RBSet<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) { const TileMapCell &c = get_cell(p_quadrant->layer, E_cell->get(), true); TileSetSource *source; @@ -1462,7 +1464,7 @@ void TileMap::_physics_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r q.bodies.clear(); // Recreate bodies and shapes. - for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) { + for (RBSet<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) { TileMapCell c = get_cell(q.layer, E_cell->get(), true); TileSetSource *source; @@ -1659,7 +1661,7 @@ void TileMap::_navigation_update_dirty_quadrants(SelfList<TileMapQuadrant>::List q.navigation_regions.clear(); // Get the navigation polygons and create regions. - for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) { + for (RBSet<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) { TileMapCell c = get_cell(q.layer, E_cell->get(), true); TileSetSource *source; @@ -1748,7 +1750,7 @@ void TileMap::_navigation_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { Vector2 quadrant_pos = map_to_world(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); - for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) { + for (RBSet<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) { TileMapCell c = get_cell(p_quadrant->layer, E_cell->get(), true); TileSetSource *source; @@ -1823,7 +1825,7 @@ void TileMap::_scenes_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r_ q.scenes.clear(); // Recreate the scenes. - for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) { + for (RBSet<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) { const TileMapCell &c = get_cell(q.layer, E_cell->get(), true); TileSetSource *source; @@ -1881,7 +1883,7 @@ void TileMap::_scenes_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { // Draw a placeholder for scenes needing one. RenderingServer *rs = RenderingServer::get_singleton(); Vector2 quadrant_pos = map_to_world(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); - for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) { + for (RBSet<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) { const TileMapCell &c = get_cell(p_quadrant->layer, E_cell->get(), true); TileSetSource *source; @@ -1923,9 +1925,9 @@ void TileMap::set_cell(int p_layer, const Vector2i &p_coords, int p_source_id, c ERR_FAIL_INDEX(p_layer, (int)layers.size()); // Set the current cell tile (using integer position). - Map<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; + HashMap<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; Vector2i pk(p_coords); - Map<Vector2i, TileMapCell>::Element *E = tile_map.find(pk); + HashMap<Vector2i, TileMapCell>::Iterator E = tile_map.find(pk); int source_id = p_source_id; Vector2i atlas_coords = p_atlas_coords; @@ -1946,7 +1948,7 @@ void TileMap::set_cell(int p_layer, const Vector2i &p_coords, int p_source_id, c // Get the quadrant Vector2i qk = _coords_to_quadrant_coords(p_layer, pk); - Map<Vector2i, TileMapQuadrant>::Element *Q = layers[p_layer].quadrant_map.find(qk); + HashMap<Vector2i, TileMapQuadrant>::Iterator Q = layers[p_layer].quadrant_map.find(qk); if (source_id == TileSet::INVALID_SOURCE) { // Erase existing cell in the tile map. @@ -1954,7 +1956,7 @@ void TileMap::set_cell(int p_layer, const Vector2i &p_coords, int p_source_id, c // Erase existing cell in the quadrant. ERR_FAIL_COND(!Q); - TileMapQuadrant &q = Q->get(); + TileMapQuadrant &q = Q->value; q.cells.erase(pk); @@ -1975,18 +1977,18 @@ void TileMap::set_cell(int p_layer, const Vector2i &p_coords, int p_source_id, c if (!Q) { Q = _create_quadrant(p_layer, qk); } - TileMapQuadrant &q = Q->get(); + TileMapQuadrant &q = Q->value; q.cells.insert(pk); } else { ERR_FAIL_COND(!Q); // TileMapQuadrant should exist... - if (E->get().source_id == source_id && E->get().get_atlas_coords() == atlas_coords && E->get().alternative_tile == alternative_tile) { + if (E->value.source_id == source_id && E->value.get_atlas_coords() == atlas_coords && E->value.alternative_tile == alternative_tile) { return; // Nothing changed. } } - TileMapCell &c = E->get(); + TileMapCell &c = E->value; c.source_id = source_id; c.set_atlas_coords(atlas_coords); @@ -2005,57 +2007,57 @@ int TileMap::get_cell_source_id(int p_layer, const Vector2i &p_coords, bool p_us ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), TileSet::INVALID_SOURCE); // Get a cell source id from position - const Map<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; - const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords); + const HashMap<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; + HashMap<Vector2i, TileMapCell>::ConstIterator E = tile_map.find(p_coords); if (!E) { return TileSet::INVALID_SOURCE; } if (p_use_proxies && tile_set.is_valid()) { - Array proxyed = tile_set->map_tile_proxy(E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + Array proxyed = tile_set->map_tile_proxy(E->value.source_id, E->value.get_atlas_coords(), E->value.alternative_tile); return proxyed[0]; } - return E->get().source_id; + return E->value.source_id; } Vector2i TileMap::get_cell_atlas_coords(int p_layer, const Vector2i &p_coords, bool p_use_proxies) const { ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), TileSetSource::INVALID_ATLAS_COORDS); // Get a cell source id from position - const Map<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; - const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords); + const HashMap<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; + HashMap<Vector2i, TileMapCell>::ConstIterator E = tile_map.find(p_coords); if (!E) { return TileSetSource::INVALID_ATLAS_COORDS; } if (p_use_proxies && tile_set.is_valid()) { - Array proxyed = tile_set->map_tile_proxy(E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + Array proxyed = tile_set->map_tile_proxy(E->value.source_id, E->value.get_atlas_coords(), E->value.alternative_tile); return proxyed[1]; } - return E->get().get_atlas_coords(); + return E->value.get_atlas_coords(); } int TileMap::get_cell_alternative_tile(int p_layer, const Vector2i &p_coords, bool p_use_proxies) const { ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), TileSetSource::INVALID_TILE_ALTERNATIVE); // Get a cell source id from position - const Map<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; - const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords); + const HashMap<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; + HashMap<Vector2i, TileMapCell>::ConstIterator E = tile_map.find(p_coords); if (!E) { return TileSetSource::INVALID_TILE_ALTERNATIVE; } if (p_use_proxies && tile_set.is_valid()) { - Array proxyed = tile_set->map_tile_proxy(E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + Array proxyed = tile_set->map_tile_proxy(E->value.source_id, E->value.get_atlas_coords(), E->value.alternative_tile); return proxyed[2]; } - return E->get().alternative_tile; + return E->value.alternative_tile; } Ref<TileMapPattern> TileMap::get_pattern(int p_layer, TypedArray<Vector2i> p_coords_array) { @@ -2147,13 +2149,13 @@ void TileMap::set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPat } } -Set<TileSet::TerrainsPattern> TileMap::_get_valid_terrains_patterns_for_constraints(int p_terrain_set, const Vector2i &p_position, Set<TerrainConstraint> p_constraints) { +RBSet<TileSet::TerrainsPattern> TileMap::_get_valid_terrains_patterns_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints) { if (!tile_set.is_valid()) { - return Set<TileSet::TerrainsPattern>(); + return RBSet<TileSet::TerrainsPattern>(); } // Returns all tiles compatible with the given constraints. - Set<TileSet::TerrainsPattern> compatible_terrain_tile_patterns; + RBSet<TileSet::TerrainsPattern> compatible_terrain_tile_patterns; for (TileSet::TerrainsPattern &terrain_pattern : tile_set->get_terrains_pattern_set(p_terrain_set)) { int valid = true; for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { @@ -2161,7 +2163,7 @@ Set<TileSet::TerrainsPattern> TileMap::_get_valid_terrains_patterns_for_constrai if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, bit)) { // Check if the bit is compatible with the constraints. TerrainConstraint terrain_bit_constraint = TerrainConstraint(this, p_position, bit, terrain_pattern.get_terrain(bit)); - Set<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_bit_constraint); + RBSet<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_bit_constraint); if (in_set_constraint_element && in_set_constraint_element->get().get_terrain() != terrain_bit_constraint.get_terrain()) { valid = false; break; @@ -2177,17 +2179,17 @@ Set<TileSet::TerrainsPattern> TileMap::_get_valid_terrains_patterns_for_constrai return compatible_terrain_tile_patterns; } -Set<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_removed_cells_list(int p_layer, const Set<Vector2i> &p_to_replace, int p_terrain_set, bool p_ignore_empty_terrains) const { +RBSet<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_removed_cells_list(int p_layer, const RBSet<Vector2i> &p_to_replace, int p_terrain_set, bool p_ignore_empty_terrains) const { if (!tile_set.is_valid()) { - return Set<TerrainConstraint>(); + return RBSet<TerrainConstraint>(); } - ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), Set<TerrainConstraint>()); - ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), Set<TerrainConstraint>()); + ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), RBSet<TerrainConstraint>()); + ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), RBSet<TerrainConstraint>()); // Build a set of dummy constraints get the constrained points. - Set<TerrainConstraint> dummy_constraints; - for (Set<Vector2i>::Element *E = p_to_replace.front(); E; E = E->next()) { + RBSet<TerrainConstraint> dummy_constraints; + for (RBSet<Vector2i>::Element *E = p_to_replace.front(); E; E = E->next()) { for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { // Iterates over sides. TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, bit)) { @@ -2197,14 +2199,14 @@ Set<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_removed_ce } // For each constrained point, we get all overlapping tiles, and select the most adequate terrain for it. - Set<TerrainConstraint> constraints; - for (Set<TerrainConstraint>::Element *E = dummy_constraints.front(); E; E = E->next()) { + RBSet<TerrainConstraint> constraints; + for (RBSet<TerrainConstraint>::Element *E = dummy_constraints.front(); E; E = E->next()) { TerrainConstraint c = E->get(); - Map<int, int> terrain_count; + HashMap<int, int> terrain_count; // Count the number of occurrences per terrain. - Map<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = c.get_overlapping_coords_and_peering_bits(); + HashMap<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = c.get_overlapping_coords_and_peering_bits(); for (const KeyValue<Vector2i, TileSet::CellNeighbor> &E_overlapping : overlapping_terrain_bits) { if (!p_to_replace.has(E_overlapping.key)) { TileData *neighbor_tile_data = nullptr; @@ -2250,13 +2252,13 @@ Set<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_removed_ce return constraints; } -Set<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_added_tile(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const { +RBSet<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_added_tile(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const { if (!tile_set.is_valid()) { - return Set<TerrainConstraint>(); + return RBSet<TerrainConstraint>(); } // Compute the constraints needed from the surrounding tiles. - Set<TerrainConstraint> output; + RBSet<TerrainConstraint> output; for (uint32_t i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor side = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, side)) { @@ -2268,35 +2270,35 @@ Set<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_added_tile return output; } -Map<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_wave_function_collapse(const Set<Vector2i> &p_to_replace, int p_terrain_set, const Set<TerrainConstraint> p_constraints) { +HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_wave_function_collapse(const RBSet<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints) { if (!tile_set.is_valid()) { - return Map<Vector2i, TileSet::TerrainsPattern>(); + return HashMap<Vector2i, TileSet::TerrainsPattern>(); } // Copy the constraints set. - Set<TerrainConstraint> constraints = p_constraints; + RBSet<TerrainConstraint> constraints = p_constraints; // Compute all acceptable patterns for each cell. - Map<Vector2i, Set<TileSet::TerrainsPattern>> per_cell_acceptable_tiles; + HashMap<Vector2i, RBSet<TileSet::TerrainsPattern>> per_cell_acceptable_tiles; for (Vector2i cell : p_to_replace) { per_cell_acceptable_tiles[cell] = _get_valid_terrains_patterns_for_constraints(p_terrain_set, cell, constraints); } // Output map. - Map<Vector2i, TileSet::TerrainsPattern> output; + HashMap<Vector2i, TileSet::TerrainsPattern> output; // Add all positions to a set. - Set<Vector2i> to_replace = Set<Vector2i>(p_to_replace); + RBSet<Vector2i> to_replace = RBSet<Vector2i>(p_to_replace); while (!to_replace.is_empty()) { // Compute the minimum number of tile possibilities for each cell. int min_nb_possibilities = 100000000; - for (const KeyValue<Vector2i, Set<TileSet::TerrainsPattern>> &E : per_cell_acceptable_tiles) { + for (const KeyValue<Vector2i, RBSet<TileSet::TerrainsPattern>> &E : per_cell_acceptable_tiles) { min_nb_possibilities = MIN(min_nb_possibilities, E.value.size()); } // Get the set of possible cells to fill, out of the most constrained ones. LocalVector<Vector2i> to_choose_from; - for (const KeyValue<Vector2i, Set<TileSet::TerrainsPattern>> &E : per_cell_acceptable_tiles) { + for (const KeyValue<Vector2i, RBSet<TileSet::TerrainsPattern>> &E : per_cell_acceptable_tiles) { if (E.value.size() == min_nb_possibilities) { to_choose_from.push_back(E.key); } @@ -2306,7 +2308,7 @@ Map<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_wave_function_collapse( Vector2i selected_cell_to_replace = to_choose_from[Math::random(0, to_choose_from.size() - 1)]; // Get the list of acceptable patterns for the given cell. - Set<TileSet::TerrainsPattern> valid_tiles = per_cell_acceptable_tiles[selected_cell_to_replace]; + RBSet<TileSet::TerrainsPattern> valid_tiles = per_cell_acceptable_tiles[selected_cell_to_replace]; if (valid_tiles.is_empty()) { break; // No possibilities :/ } @@ -2317,7 +2319,7 @@ Map<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_wave_function_collapse( LocalVector<int> terrains_counts; int pattern_index = 0; for (const TileSet::TerrainsPattern &pattern : valid_tiles) { - Set<int> terrains; + RBSet<int> terrains; for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor side = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, side)) { @@ -2345,8 +2347,8 @@ Map<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_wave_function_collapse( per_cell_acceptable_tiles.erase(selected_cell_to_replace); // Add the new constraints from the added tiles. - Set<TerrainConstraint> new_constraints = get_terrain_constraints_from_added_tile(selected_cell_to_replace, p_terrain_set, selected_terrain_tile_pattern); - for (Set<TerrainConstraint>::Element *E_constraint = new_constraints.front(); E_constraint; E_constraint = E_constraint->next()) { + RBSet<TerrainConstraint> new_constraints = get_terrain_constraints_from_added_tile(selected_cell_to_replace, p_terrain_set, selected_terrain_tile_pattern); + for (RBSet<TerrainConstraint>::Element *E_constraint = new_constraints.front(); E_constraint; E_constraint = E_constraint->next()) { constraints.insert(E_constraint->get()); } @@ -2369,14 +2371,14 @@ void TileMap::set_cells_from_surrounding_terrains(int p_layer, TypedArray<Vector ERR_FAIL_INDEX(p_layer, (int)layers.size()); ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count()); - Set<Vector2i> coords_set; + RBSet<Vector2i> coords_set; for (int i = 0; i < p_coords_array.size(); i++) { coords_set.insert(p_coords_array[i]); } - Set<TileMap::TerrainConstraint> constraints = get_terrain_constraints_from_removed_cells_list(p_layer, coords_set, p_terrain_set, p_ignore_empty_terrains); + RBSet<TileMap::TerrainConstraint> constraints = get_terrain_constraints_from_removed_cells_list(p_layer, coords_set, p_terrain_set, p_ignore_empty_terrains); - Map<Vector2i, TileSet::TerrainsPattern> wfc_output = terrain_wave_function_collapse(coords_set, p_terrain_set, constraints); + HashMap<Vector2i, TileSet::TerrainsPattern> wfc_output = terrain_wave_function_collapse(coords_set, p_terrain_set, constraints); for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &kv : wfc_output) { TileMapCell cell = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); set_cell(p_layer, kv.key, cell.source_id, cell.get_atlas_coords(), cell.alternative_tile); @@ -2385,11 +2387,11 @@ void TileMap::set_cells_from_surrounding_terrains(int p_layer, TypedArray<Vector TileMapCell TileMap::get_cell(int p_layer, const Vector2i &p_coords, bool p_use_proxies) const { ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), TileMapCell()); - const Map<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; + const HashMap<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; if (!tile_map.has(p_coords)) { return TileMapCell(); } else { - TileMapCell c = tile_map.find(p_coords)->get(); + TileMapCell c = tile_map.find(p_coords)->value; if (p_use_proxies && tile_set.is_valid()) { Array proxyed = tile_set->map_tile_proxy(c.source_id, c.get_atlas_coords(), c.alternative_tile); c.source_id = proxyed[0]; @@ -2400,7 +2402,7 @@ TileMapCell TileMap::get_cell(int p_layer, const Vector2i &p_coords, bool p_use_ } } -Map<Vector2i, TileMapQuadrant> *TileMap::get_quadrant_map(int p_layer) { +HashMap<Vector2i, TileMapQuadrant> *TileMap::get_quadrant_map(int p_layer) { ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), nullptr); return &layers[p_layer].quadrant_map; @@ -2415,15 +2417,15 @@ void TileMap::fix_invalid_tiles() { ERR_FAIL_COND_MSG(tile_set.is_null(), "Cannot fix invalid tiles if Tileset is not open."); for (unsigned int i = 0; i < layers.size(); i++) { - const Map<Vector2i, TileMapCell> &tile_map = layers[i].tile_map; - Set<Vector2i> coords; + const HashMap<Vector2i, TileMapCell> &tile_map = layers[i].tile_map; + RBSet<Vector2i> coords; for (const KeyValue<Vector2i, TileMapCell> &E : tile_map) { TileSetSource *source = *tile_set->get_source(E.value.source_id); if (!source || !source->has_tile(E.value.get_atlas_coords()) || !source->has_alternative_tile(E.value.get_atlas_coords(), E.value.alternative_tile)) { coords.insert(E.key); } } - for (Set<Vector2i>::Element *E = coords.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = coords.front(); E; E = E->next()) { set_cell(i, E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); } } @@ -2546,7 +2548,7 @@ Vector<int> TileMap::_get_tile_data(int p_layer) const { ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), Vector<int>()); // Export tile data to raw format - const Map<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; + const HashMap<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map; Vector<int> data; data.resize(tile_map.size() * 3); int *w = data.ptrw(); @@ -3375,10 +3377,10 @@ Rect2 TileMap::get_used_rect() { // Not const because of cache used_rect_cache = Rect2i(); for (unsigned int i = 0; i < layers.size(); i++) { - const Map<Vector2i, TileMapCell> &tile_map = layers[i].tile_map; + const HashMap<Vector2i, TileMapCell> &tile_map = layers[i].tile_map; if (tile_map.size() > 0) { if (first) { - used_rect_cache = Rect2i(tile_map.front()->key().x, tile_map.front()->key().y, 0, 0); + used_rect_cache = Rect2i(tile_map.begin()->key.x, tile_map.begin()->key.y, 0, 0); first = false; } @@ -3448,8 +3450,8 @@ void TileMap::set_texture_filter(TextureFilter p_texture_filter) { // Set a default texture filter for the whole tilemap CanvasItem::set_texture_filter(p_texture_filter); for (unsigned int layer = 0; layer < layers.size(); layer++) { - for (Map<Vector2i, TileMapQuadrant>::Element *F = layers[layer].quadrant_map.front(); F; F = F->next()) { - TileMapQuadrant &q = F->get(); + for (HashMap<Vector2i, TileMapQuadrant>::Iterator F = layers[layer].quadrant_map.begin(); F; ++F) { + TileMapQuadrant &q = F->value; for (const RID &ci : q.canvas_items) { RenderingServer::get_singleton()->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(p_texture_filter)); _make_quadrant_dirty(F); @@ -3463,8 +3465,8 @@ void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) { // Set a default texture repeat for the whole tilemap CanvasItem::set_texture_repeat(p_texture_repeat); for (unsigned int layer = 0; layer < layers.size(); layer++) { - for (Map<Vector2i, TileMapQuadrant>::Element *F = layers[layer].quadrant_map.front(); F; F = F->next()) { - TileMapQuadrant &q = F->get(); + for (HashMap<Vector2i, TileMapQuadrant>::Iterator F = layers[layer].quadrant_map.begin(); F; ++F) { + TileMapQuadrant &q = F->value; for (const RID &ci : q.canvas_items) { RenderingServer::get_singleton()->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(p_texture_repeat)); _make_quadrant_dirty(F); @@ -3512,7 +3514,7 @@ TypedArray<Vector2i> TileMap::get_surrounding_tiles(Vector2i coords) { return around; } -void TileMap::draw_cells_outline(Control *p_control, Set<Vector2i> p_cells, Color p_color, Transform2D p_transform) { +void TileMap::draw_cells_outline(Control *p_control, RBSet<Vector2i> p_cells, Color p_color, Transform2D p_transform) { if (!tile_set.is_valid()) { return; } @@ -3522,7 +3524,7 @@ void TileMap::draw_cells_outline(Control *p_control, Set<Vector2i> p_cells, Colo Vector<Vector2> polygon = tile_set->get_tile_shape_polygon(); TileSet::TileShape shape = tile_set->get_tile_shape(); - for (Set<Vector2i>::Element *E = p_cells.front(); E; E = E->next()) { + for (RBSet<Vector2i>::Element *E = p_cells.front(); E; E = E->next()) { Vector2 center = map_to_world(E->get()); #define DRAW_SIDE_IF_NEEDED(side, polygon_index_from, polygon_index_to) \ @@ -3576,7 +3578,7 @@ TypedArray<String> TileMap::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); // Retrieve the set of Z index values with a Y-sorted layer. - Set<int> y_sorted_z_index; + RBSet<int> y_sorted_z_index; for (int layer = 0; layer < (int)layers.size(); layer++) { if (layers[layer].y_sort_enabled) { y_sorted_z_index.insert(layers[layer].z_index); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index a0655dea2a..02a2b3a1c6 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -57,11 +57,11 @@ struct TileMapQuadrant { Vector2i coords; // TileMapCells - Set<Vector2i> cells; + RBSet<Vector2i> cells; // We need those two maps to sort by world position for rendering // This is kind of workaround, it would be better to sort the cells directly in the "cells" set instead. - Map<Vector2i, Vector2i> map_to_world; - Map<Vector2i, Vector2i, CoordsWorldComparator> world_to_map; + RBMap<Vector2i, Vector2i> map_to_world; + RBMap<Vector2i, Vector2i, CoordsWorldComparator> world_to_map; // Debug. RID debug_canvas_item; @@ -74,13 +74,13 @@ struct TileMapQuadrant { List<RID> bodies; // Navigation. - Map<Vector2i, Vector<RID>> navigation_regions; + HashMap<Vector2i, Vector<RID>> navigation_regions; // Scenes. - Map<Vector2i, String> scenes; + HashMap<Vector2i, String> scenes; // Runtime TileData cache. - Map<Vector2i, TileData *> runtime_tile_data_cache; + HashMap<Vector2i, TileData *> runtime_tile_data_cache; void operator=(const TileMapQuadrant &q) { layer = q.layer; @@ -135,7 +135,7 @@ public: return base_cell_coords; } - Map<Vector2i, TileSet::CellNeighbor> get_overlapping_coords_and_peering_bits() const; + HashMap<Vector2i, TileSet::CellNeighbor> get_overlapping_coords_and_peering_bits() const; void set_terrain(int p_terrain) { terrain = p_terrain; @@ -193,22 +193,22 @@ private: int y_sort_origin = 0; int z_index = 0; RID canvas_item; - Map<Vector2i, TileMapCell> tile_map; - Map<Vector2i, TileMapQuadrant> quadrant_map; + HashMap<Vector2i, TileMapCell> tile_map; + HashMap<Vector2i, TileMapQuadrant> quadrant_map; SelfList<TileMapQuadrant>::List dirty_quadrant_list; }; LocalVector<TileMapLayer> layers; int selected_layer = -1; // Mapping for RID to coords. - Map<RID, Vector2i> bodies_coords; + HashMap<RID, Vector2i> bodies_coords; // Quadrants and internals management. Vector2i _coords_to_quadrant_coords(int p_layer, const Vector2i &p_coords) const; - Map<Vector2i, TileMapQuadrant>::Element *_create_quadrant(int p_layer, const Vector2i &p_qk); + HashMap<Vector2i, TileMapQuadrant>::Iterator _create_quadrant(int p_layer, const Vector2i &p_qk); - void _make_quadrant_dirty(Map<Vector2i, TileMapQuadrant>::Element *Q); + void _make_quadrant_dirty(HashMap<Vector2i, TileMapQuadrant>::Iterator Q); void _make_all_quadrants_dirty(); void _queue_update_dirty_quadrants(); @@ -217,7 +217,7 @@ private: void _recreate_layer_internals(int p_layer); void _recreate_internals(); - void _erase_quadrant(Map<Vector2i, TileMapQuadrant>::Element *Q); + void _erase_quadrant(HashMap<Vector2i, TileMapQuadrant>::Iterator Q); void _clear_layer_internals(int p_layer); void _clear_internals(); @@ -251,7 +251,7 @@ private: void _scenes_draw_quadrant_debug(TileMapQuadrant *p_quadrant); // Terrains. - Set<TileSet::TerrainsPattern> _get_valid_terrains_patterns_for_constraints(int p_terrain_set, const Vector2i &p_position, Set<TerrainConstraint> p_constraints); + RBSet<TileSet::TerrainsPattern> _get_valid_terrains_patterns_for_constraints(int p_terrain_set, const Vector2i &p_position, RBSet<TerrainConstraint> p_constraints); // Set and get tiles from data arrays. void _set_tile_data(int p_layer, const Vector<int> &p_data); @@ -333,14 +333,14 @@ public: void set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPattern> p_pattern); // Terrains. - Set<TerrainConstraint> get_terrain_constraints_from_removed_cells_list(int p_layer, const Set<Vector2i> &p_to_replace, int p_terrain_set, bool p_ignore_empty_terrains = true) const; // Not exposed. - Set<TerrainConstraint> get_terrain_constraints_from_added_tile(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const; // Not exposed. - Map<Vector2i, TileSet::TerrainsPattern> terrain_wave_function_collapse(const Set<Vector2i> &p_to_replace, int p_terrain_set, const Set<TerrainConstraint> p_constraints); // Not exposed. + RBSet<TerrainConstraint> get_terrain_constraints_from_removed_cells_list(int p_layer, const RBSet<Vector2i> &p_to_replace, int p_terrain_set, bool p_ignore_empty_terrains = true) const; // Not exposed. + RBSet<TerrainConstraint> get_terrain_constraints_from_added_tile(Vector2i p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const; // Not exposed. + HashMap<Vector2i, TileSet::TerrainsPattern> terrain_wave_function_collapse(const RBSet<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> p_constraints); // Not exposed. void set_cells_from_surrounding_terrains(int p_layer, TypedArray<Vector2i> p_coords_array, int p_terrain_set, bool p_ignore_empty_terrains = true); // Not exposed to users TileMapCell get_cell(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const; - Map<Vector2i, TileMapQuadrant> *get_quadrant_map(int p_layer); + HashMap<Vector2i, TileMapQuadrant> *get_quadrant_map(int p_layer); int get_effective_quadrant_size(int p_layer) const; //--- @@ -377,7 +377,7 @@ public: // Helpers? TypedArray<Vector2i> get_surrounding_tiles(Vector2i coords); - void draw_cells_outline(Control *p_control, Set<Vector2i> p_cells, Color p_color, Transform2D p_transform = Transform2D()); + void draw_cells_outline(Control *p_control, RBSet<Vector2i> p_cells, Color p_color, Transform2D p_transform = Transform2D()); // Virtual function to modify the TileData at runtime GDVIRTUAL2R(bool, _use_tile_data_runtime_update, int, Vector2i); diff --git a/scene/2d/visible_on_screen_notifier_2d.cpp b/scene/2d/visible_on_screen_notifier_2d.cpp index 4bceaf71c6..2aae383cdf 100644 --- a/scene/2d/visible_on_screen_notifier_2d.cpp +++ b/scene/2d/visible_on_screen_notifier_2d.cpp @@ -198,7 +198,7 @@ void VisibleOnScreenEnabler2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_enable_node_path"), &VisibleOnScreenEnabler2D::get_enable_node_path); ADD_GROUP("Enabling", "enable_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "enable_mode", PROPERTY_HINT_ENUM, "Inherit,Always,WhenPaused"), "set_enable_mode", "get_enable_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "enable_mode", PROPERTY_HINT_ENUM, "Inherit,Always,When Paused"), "set_enable_mode", "get_enable_mode"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "enable_node_path"), "set_enable_node_path", "get_enable_node_path"); BIND_ENUM_CONSTANT(ENABLE_MODE_INHERIT); diff --git a/scene/2d/visible_on_screen_notifier_2d.h b/scene/2d/visible_on_screen_notifier_2d.h index e0d580f174..3165eb92df 100644 --- a/scene/2d/visible_on_screen_notifier_2d.h +++ b/scene/2d/visible_on_screen_notifier_2d.h @@ -37,7 +37,7 @@ class Viewport; class VisibleOnScreenNotifier2D : public Node2D { GDCLASS(VisibleOnScreenNotifier2D, Node2D); - Set<Viewport *> viewports; + RBSet<Viewport *> viewports; Rect2 rect; diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index fb37e64a1a..54737e13b3 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -192,14 +192,14 @@ void Area3D::_body_enter_tree(ObjectID p_id) { Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); - Map<ObjectID, BodyState>::Element *E = body_map.find(p_id); + HashMap<ObjectID, BodyState>::Iterator E = body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_tree); + ERR_FAIL_COND(E->value.in_tree); - E->get().in_tree = true; + E->value.in_tree = true; emit_signal(SceneStringNames::get_singleton()->body_entered, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape); } } @@ -207,13 +207,13 @@ void Area3D::_body_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); - Map<ObjectID, BodyState>::Element *E = body_map.find(p_id); + HashMap<ObjectID, BodyState>::Iterator E = body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_tree); - E->get().in_tree = false; + ERR_FAIL_COND(!E->value.in_tree); + E->value.in_tree = false; emit_signal(SceneStringNames::get_singleton()->body_exited, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape); } } @@ -224,7 +224,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i Object *obj = ObjectDB::get_instance(objid); Node *node = Object::cast_to<Node>(obj); - Map<ObjectID, BodyState>::Element *E = body_map.find(objid); + HashMap<ObjectID, BodyState>::Iterator E = body_map.find(objid); if (!body_in && !E) { return; //likely removed from the tree @@ -235,36 +235,36 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i if (body_in) { if (!E) { E = body_map.insert(objid, BodyState()); - E->get().rid = p_body; - E->get().rc = 0; - E->get().in_tree = node && node->is_inside_tree(); + E->value.rid = p_body; + E->value.rc = 0; + E->value.in_tree = node && node->is_inside_tree(); if (node) { node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree), make_binds(objid)); node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree), make_binds(objid)); - if (E->get().in_tree) { + if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } } } - E->get().rc++; + E->value.rc++; if (node) { - E->get().shapes.insert(ShapePair(p_body_shape, p_area_shape)); + E->value.shapes.insert(ShapePair(p_body_shape, p_area_shape)); } - if (E->get().in_tree) { + if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape); } } else { - E->get().rc--; + E->value.rc--; if (node) { - E->get().shapes.erase(ShapePair(p_body_shape, p_area_shape)); + E->value.shapes.erase(ShapePair(p_body_shape, p_area_shape)); } - bool in_tree = E->get().in_tree; - if (E->get().rc == 0) { - body_map.erase(E); + bool in_tree = E->value.in_tree; + if (E->value.rc == 0) { + body_map.remove(E); if (node) { node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree)); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree)); @@ -285,7 +285,7 @@ void Area3D::_clear_monitoring() { ERR_FAIL_COND_MSG(locked, "This function can't be used during the in/out signal."); { - Map<ObjectID, BodyState> bmcopy = body_map; + HashMap<ObjectID, BodyState> bmcopy = body_map; body_map.clear(); //disconnect all monitored stuff @@ -314,7 +314,7 @@ void Area3D::_clear_monitoring() { } { - Map<ObjectID, AreaState> bmcopy = area_map; + HashMap<ObjectID, AreaState> bmcopy = area_map; area_map.clear(); //disconnect all monitored stuff @@ -379,14 +379,14 @@ void Area3D::_area_enter_tree(ObjectID p_id) { Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); - Map<ObjectID, AreaState>::Element *E = area_map.find(p_id); + HashMap<ObjectID, AreaState>::Iterator E = area_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_tree); + ERR_FAIL_COND(E->value.in_tree); - E->get().in_tree = true; + E->value.in_tree = true; emit_signal(SceneStringNames::get_singleton()->area_entered, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape); } } @@ -394,13 +394,13 @@ void Area3D::_area_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); - Map<ObjectID, AreaState>::Element *E = area_map.find(p_id); + HashMap<ObjectID, AreaState>::Iterator E = area_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_tree); - E->get().in_tree = false; + ERR_FAIL_COND(!E->value.in_tree); + E->value.in_tree = false; emit_signal(SceneStringNames::get_singleton()->area_exited, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape); } } @@ -411,7 +411,7 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i Object *obj = ObjectDB::get_instance(objid); Node *node = Object::cast_to<Node>(obj); - Map<ObjectID, AreaState>::Element *E = area_map.find(objid); + HashMap<ObjectID, AreaState>::Iterator E = area_map.find(objid); if (!area_in && !E) { return; //likely removed from the tree @@ -422,36 +422,36 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i if (area_in) { if (!E) { E = area_map.insert(objid, AreaState()); - E->get().rid = p_area; - E->get().rc = 0; - E->get().in_tree = node && node->is_inside_tree(); + E->value.rid = p_area; + E->value.rc = 0; + E->value.in_tree = node && node->is_inside_tree(); if (node) { node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree), make_binds(objid)); node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree), make_binds(objid)); - if (E->get().in_tree) { + if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->area_entered, node); } } } - E->get().rc++; + E->value.rc++; if (node) { - E->get().shapes.insert(AreaShapePair(p_area_shape, p_self_shape)); + E->value.shapes.insert(AreaShapePair(p_area_shape, p_self_shape)); } - if (!node || E->get().in_tree) { + if (!node || E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, node, p_area_shape, p_self_shape); } } else { - E->get().rc--; + E->value.rc--; if (node) { - E->get().shapes.erase(AreaShapePair(p_area_shape, p_self_shape)); + E->value.shapes.erase(AreaShapePair(p_area_shape, p_self_shape)); } - bool in_tree = E->get().in_tree; - if (E->get().rc == 0) { - area_map.erase(E); + bool in_tree = E->value.in_tree; + if (E->value.rc == 0) { + area_map.remove(E); if (node) { node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree)); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree)); @@ -524,20 +524,20 @@ TypedArray<Area3D> Area3D::get_overlapping_areas() const { bool Area3D::overlaps_area(Node *p_area) const { ERR_FAIL_NULL_V(p_area, false); - const Map<ObjectID, AreaState>::Element *E = area_map.find(p_area->get_instance_id()); + HashMap<ObjectID, AreaState>::ConstIterator E = area_map.find(p_area->get_instance_id()); if (!E) { return false; } - return E->get().in_tree; + return E->value.in_tree; } bool Area3D::overlaps_body(Node *p_body) const { ERR_FAIL_NULL_V(p_body, false); - const Map<ObjectID, BodyState>::Element *E = body_map.find(p_body->get_instance_id()); + HashMap<ObjectID, BodyState>::ConstIterator E = body_map.find(p_body->get_instance_id()); if (!E) { return false; } - return E->get().in_tree; + return E->value.in_tree; } void Area3D::set_audio_bus_override(bool p_override) { diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h index 31ded00fb7..3b892baf57 100644 --- a/scene/3d/area_3d.h +++ b/scene/3d/area_3d.h @@ -98,7 +98,7 @@ private: VSet<ShapePair> shapes; }; - Map<ObjectID, BodyState> body_map; + HashMap<ObjectID, BodyState> body_map; void _area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape); @@ -130,7 +130,7 @@ private: VSet<AreaShapePair> shapes; }; - Map<ObjectID, AreaState> area_map; + HashMap<ObjectID, AreaState> area_map; void _clear_monitoring(); bool audio_bus_override = false; diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index f057c72012..4a20a88346 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -281,7 +281,7 @@ void AudioStreamPlayer3D::_notification(int p_what) { active.set(); Ref<AudioStreamPlayback> new_playback = stream->instance_playback(); ERR_FAIL_COND_MSG(new_playback.is_null(), "Failed to instantiate playback."); - Map<StringName, Vector<AudioFrame>> bus_map; + HashMap<StringName, Vector<AudioFrame>> bus_map; bus_map[_get_actual_bus()] = volume_vector; AudioServer::get_singleton()->start_playback_stream(new_playback, bus_map, setplay.get(), actual_pitch_scale, linear_attenuation, attenuation_filter_cutoff_hz); stream_playbacks.push_back(new_playback); @@ -387,7 +387,7 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() { Ref<World3D> world_3d = get_world_3d(); ERR_FAIL_COND_V(world_3d.is_null(), output_volume_vector); - Set<Camera3D *> cameras = world_3d->get_cameras(); + RBSet<Camera3D *> cameras = world_3d->get_cameras(); cameras.insert(get_viewport()->get_camera_3d()); PhysicsDirectSpaceState3D *space_state = PhysicsServer3D::get_singleton()->space_get_direct_state(world_3d->get_space()); @@ -466,7 +466,7 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() { output_volume_vector.write[k] = multiplier * output_volume_vector[k]; } - Map<StringName, Vector<AudioFrame>> bus_volumes; + HashMap<StringName, Vector<AudioFrame>> bus_volumes; if (area) { if (area->is_overriding_audio_bus()) { //override audio bus diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 4f05e80377..4c53776bba 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -217,8 +217,6 @@ void Camera3D::make_current() { } get_viewport()->_camera_3d_set(this); - - //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this); } void Camera3D::clear_current(bool p_enable_next) { diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 40c09593a4..70cab77eda 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -345,7 +345,7 @@ void CollisionObject3D::_update_debug_shapes() { return; } - for (Set<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) { + for (RBSet<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) { if (shapes.has(shapedata_idx->get())) { ShapeData &shapedata = shapes[shapedata_idx->get()]; ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw(); @@ -459,7 +459,7 @@ void CollisionObject3D::_bind_methods() { ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); - ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,MakeStatic,KeepActive"), "set_disable_mode", "get_disable_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,Make Static,Keep Active"), "set_disable_mode", "get_disable_mode"); ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index e92843d784..84b00de9c9 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -71,14 +71,14 @@ private: int total_subshapes = 0; - Map<uint32_t, ShapeData> shapes; + RBMap<uint32_t, ShapeData> shapes; bool only_update_transform_changes = false; // This is used for sync to physics. bool capture_input_on_drag = false; bool ray_pickable = true; - Set<uint32_t> debug_shapes_to_update; + RBSet<uint32_t> debug_shapes_to_update; int debug_shapes_count = 0; Transform3D debug_shape_old_transform; diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp index bedf0edf38..4552ed9537 100644 --- a/scene/3d/gpu_particles_collision_3d.cpp +++ b/scene/3d/gpu_particles_collision_3d.cpp @@ -640,18 +640,13 @@ void GPUParticlesCollisionHeightField3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_update_mode", "update_mode"), &GPUParticlesCollisionHeightField3D::set_update_mode); ClassDB::bind_method(D_METHOD("get_update_mode"), &GPUParticlesCollisionHeightField3D::get_update_mode); - ClassDB::bind_method(D_METHOD("set_follow_camera_mode", "enabled"), &GPUParticlesCollisionHeightField3D::set_follow_camera_mode); - ClassDB::bind_method(D_METHOD("is_follow_camera_mode_enabled"), &GPUParticlesCollisionHeightField3D::is_follow_camera_mode_enabled); - - ClassDB::bind_method(D_METHOD("set_follow_camera_push_ratio", "ratio"), &GPUParticlesCollisionHeightField3D::set_follow_camera_push_ratio); - ClassDB::bind_method(D_METHOD("get_follow_camera_push_ratio"), &GPUParticlesCollisionHeightField3D::get_follow_camera_push_ratio); + ClassDB::bind_method(D_METHOD("set_follow_camera_enabled", "enabled"), &GPUParticlesCollisionHeightField3D::set_follow_camera_enabled); + ClassDB::bind_method(D_METHOD("is_follow_camera_enabled"), &GPUParticlesCollisionHeightField3D::is_follow_camera_enabled); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096,8192"), "set_resolution", "get_resolution"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "WhenMoved,Always"), "set_update_mode", "get_update_mode"); - ADD_GROUP("Follow Camera", "follow_camera_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_camera_enabled"), "set_follow_camera_mode", "is_follow_camera_mode_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "follow_camera_push_ratio", PROPERTY_HINT_RANGE, "0.01,1,0.01"), "set_follow_camera_push_ratio", "get_follow_camera_push_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "256 (Fastest),512 (Fast),1024 (Average),2048 (Slow),4096 (Slower),8192 (Slowest)"), "set_resolution", "get_resolution"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "When Moved (Fast),Always (Slow)"), "set_update_mode", "get_update_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_camera_enabled"), "set_follow_camera_enabled", "is_follow_camera_enabled"); BIND_ENUM_CONSTANT(RESOLUTION_256); BIND_ENUM_CONSTANT(RESOLUTION_512); @@ -665,14 +660,6 @@ void GPUParticlesCollisionHeightField3D::_bind_methods() { BIND_ENUM_CONSTANT(UPDATE_MODE_ALWAYS); } -void GPUParticlesCollisionHeightField3D::set_follow_camera_push_ratio(float p_follow_camera_push_ratio) { - follow_camera_push_ratio = p_follow_camera_push_ratio; -} - -float GPUParticlesCollisionHeightField3D::get_follow_camera_push_ratio() const { - return follow_camera_push_ratio; -} - void GPUParticlesCollisionHeightField3D::set_extents(const Vector3 &p_extents) { extents = p_extents; RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); @@ -704,12 +691,12 @@ GPUParticlesCollisionHeightField3D::UpdateMode GPUParticlesCollisionHeightField3 return update_mode; } -void GPUParticlesCollisionHeightField3D::set_follow_camera_mode(bool p_enabled) { +void GPUParticlesCollisionHeightField3D::set_follow_camera_enabled(bool p_enabled) { follow_camera_mode = p_enabled; set_process_internal(follow_camera_mode || update_mode == UPDATE_MODE_ALWAYS); } -bool GPUParticlesCollisionHeightField3D::is_follow_camera_mode_enabled() const { +bool GPUParticlesCollisionHeightField3D::is_follow_camera_enabled() const { return follow_camera_mode; } diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h index fdd2fa4b18..4b2cb930fa 100644 --- a/scene/3d/gpu_particles_collision_3d.h +++ b/scene/3d/gpu_particles_collision_3d.h @@ -211,7 +211,6 @@ private: Vector3 extents = Vector3(1, 1, 1); Resolution resolution = RESOLUTION_1024; bool follow_camera_mode = false; - float follow_camera_push_ratio = 0.1; UpdateMode update_mode = UPDATE_MODE_WHEN_MOVED; @@ -229,11 +228,8 @@ public: void set_update_mode(UpdateMode p_update_mode); UpdateMode get_update_mode() const; - void set_follow_camera_mode(bool p_enabled); - bool is_follow_camera_mode_enabled() const; - - void set_follow_camera_push_ratio(float p_ratio); - float get_follow_camera_push_ratio() const; + void set_follow_camera_enabled(bool p_enabled); + bool is_follow_camera_enabled() const; virtual AABB get_aabb() const override; diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 9375190151..2d7da48ab1 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -469,8 +469,8 @@ void Label3D::_shape() { aabb = AABB(); // Clear materials. - for (Map<uint64_t, SurfaceData>::Element *E = surfaces.front(); E; E = E->next()) { - RenderingServer::get_singleton()->free(E->get().material); + for (const KeyValue<uint64_t, SurfaceData> &E : surfaces) { + RenderingServer::get_singleton()->free(E.value.material); } surfaces.clear(); @@ -599,20 +599,20 @@ void Label3D::_shape() { offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing + font->get_spacing(TextServer::SPACING_BOTTOM)) * pixel_size; } - for (Map<uint64_t, SurfaceData>::Element *E = surfaces.front(); E; E = E->next()) { + for (const KeyValue<uint64_t, SurfaceData> &E : surfaces) { Array mesh_array; mesh_array.resize(RS::ARRAY_MAX); - mesh_array[RS::ARRAY_VERTEX] = E->get().mesh_vertices; - mesh_array[RS::ARRAY_NORMAL] = E->get().mesh_normals; - mesh_array[RS::ARRAY_TANGENT] = E->get().mesh_tangents; - mesh_array[RS::ARRAY_COLOR] = E->get().mesh_colors; - mesh_array[RS::ARRAY_TEX_UV] = E->get().mesh_uvs; - mesh_array[RS::ARRAY_INDEX] = E->get().indices; + mesh_array[RS::ARRAY_VERTEX] = E.value.mesh_vertices; + mesh_array[RS::ARRAY_NORMAL] = E.value.mesh_normals; + mesh_array[RS::ARRAY_TANGENT] = E.value.mesh_tangents; + mesh_array[RS::ARRAY_COLOR] = E.value.mesh_colors; + mesh_array[RS::ARRAY_TEX_UV] = E.value.mesh_uvs; + mesh_array[RS::ARRAY_INDEX] = E.value.indices; RS::SurfaceData sd; RS::get_singleton()->mesh_create_surface_data_from_arrays(&sd, RS::PRIMITIVE_TRIANGLES, mesh_array); - sd.material = E->get().material; + sd.material = E.value.material; RS::get_singleton()->mesh_add_surface(mesh, sd); } @@ -1003,8 +1003,8 @@ Label3D::~Label3D() { TS->free_rid(text_rid); RenderingServer::get_singleton()->free(mesh); - for (Map<uint64_t, SurfaceData>::Element *E = surfaces.front(); E; E = E->next()) { - RenderingServer::get_singleton()->free(E->get().material); + for (KeyValue<uint64_t, SurfaceData> E : surfaces) { + RenderingServer::get_singleton()->free(E.value.material); } surfaces.clear(); } diff --git a/scene/3d/label_3d.h b/scene/3d/label_3d.h index 86b8faa617..f57797a247 100644 --- a/scene/3d/label_3d.h +++ b/scene/3d/label_3d.h @@ -83,7 +83,7 @@ private: RID material; }; - Map<uint64_t, SurfaceData> surfaces; + HashMap<uint64_t, SurfaceData> surfaces; HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER; VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER; diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 88d2c1ad69..5c63bdcf1d 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -318,12 +318,11 @@ void LightmapGI::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &m int LightmapGI::_bsp_get_simplex_side(const Vector<Vector3> &p_points, const LocalVector<BSPSimplex> &p_simplices, const Plane &p_plane, uint32_t p_simplex) const { int over = 0; int under = 0; - int coplanar = 0; const BSPSimplex &s = p_simplices[p_simplex]; for (int i = 0; i < 4; i++) { const Vector3 v = p_points[s.vertices[i]]; - if (p_plane.has_point(v)) { //coplanar - coplanar++; + if (p_plane.has_point(v)) { + // Coplanar. } else if (p_plane.is_point_over(v)) { over++; } else { diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h index f641c99ec1..55d9a52a28 100644 --- a/scene/3d/lightmapper.h +++ b/scene/3d/lightmapper.h @@ -88,7 +88,9 @@ public: instID(INVALID_GEOMETRY_ID) {} /*! Tests if we hit something. */ - _FORCE_INLINE_ explicit operator bool() const { return geomID != INVALID_GEOMETRY_ID; } + _FORCE_INLINE_ explicit operator bool() const { + return geomID != INVALID_GEOMETRY_ID; + } public: Vector3 org; //!< Ray origin + tnear @@ -116,7 +118,7 @@ public: virtual void set_mesh_alpha_texture(Ref<Image> p_alpha_texture, unsigned int p_id) = 0; virtual void commit() = 0; - virtual void set_mesh_filter(const Set<int> &p_mesh_ids) = 0; + virtual void set_mesh_filter(const RBSet<int> &p_mesh_ids) = 0; virtual void clear_mesh_filter() = 0; static Ref<LightmapRaycaster> create(); diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index 31c33a6b61..189ab7fc3b 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -42,9 +42,9 @@ bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) { return false; } - Map<StringName, int>::Element *E = blend_shape_properties.find(p_name); + HashMap<StringName, int>::Iterator E = blend_shape_properties.find(p_name); if (E) { - set_blend_shape_value(E->get(), p_value); + set_blend_shape_value(E->value, p_value); return true; } @@ -66,9 +66,9 @@ bool MeshInstance3D::_get(const StringName &p_name, Variant &r_ret) const { return false; } - const Map<StringName, int>::Element *E = blend_shape_properties.find(p_name); + HashMap<StringName, int>::ConstIterator E = blend_shape_properties.find(p_name); if (E) { - r_ret = get_blend_shape_value(E->get()); + r_ret = get_blend_shape_value(E->value); return true; } diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h index 0bf5c32410..dc9c64fa41 100644 --- a/scene/3d/mesh_instance_3d.h +++ b/scene/3d/mesh_instance_3d.h @@ -47,7 +47,7 @@ protected: NodePath skeleton_path = NodePath(".."); LocalVector<float> blend_shape_tracks; - Map<StringName, int> blend_shape_properties; + HashMap<StringName, int> blend_shape_properties; Vector<Ref<Material>> surface_override_materials; void _mesh_changed(); diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index 78dbecc0c5..fa6a633dee 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -35,6 +35,8 @@ #include "servers/navigation_server_3d.h" void NavigationObstacle3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle3D::get_rid); + ClassDB::bind_method(D_METHOD("set_estimate_radius", "estimate_radius"), &NavigationObstacle3D::set_estimate_radius); ClassDB::bind_method(D_METHOD("is_radius_estimated"), &NavigationObstacle3D::is_radius_estimated); ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationObstacle3D::set_radius); @@ -79,7 +81,7 @@ void NavigationObstacle3D::_notification(int p_what) { } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - if (parent_node3d) { + if (parent_node3d && parent_node3d->is_inside_tree()) { NavigationServer3D::get_singleton()->agent_set_position(agent, parent_node3d->get_global_transform().origin); PhysicsBody3D *rigid = Object::cast_to<PhysicsBody3D>(get_parent()); @@ -107,7 +109,12 @@ TypedArray<String> NavigationObstacle3D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (!Object::cast_to<Node3D>(get_parent())) { - warnings.push_back(RTR("The NavigationObstacle3D only serves to provide collision avoidance to a spatial object.")); + warnings.push_back(RTR("The NavigationObstacle3D only serves to provide collision avoidance to a Node3D inheriting parent object.")); + } + + if (Object::cast_to<StaticBody3D>(get_parent())) { + warnings.push_back(RTR("The NavigationObstacle3D is intended for constantly moving bodies like CharacterBody3D or RigidDynamicBody3D as it creates only an RVO avoidance radius and does not follow scene geometry exactly." + "\nNot constantly moving or complete static objects should be (re)baked to a NavigationMesh so agents can not only avoid them but also move along those objects outline at high detail")); } return warnings; @@ -129,13 +136,13 @@ void NavigationObstacle3D::reevaluate_agent_radius() { } real_t NavigationObstacle3D::estimate_agent_radius() const { - if (parent_node3d) { + if (parent_node3d && parent_node3d->is_inside_tree()) { // Estimate the radius of this physics body real_t radius = 0.0; for (int i(0); i < parent_node3d->get_child_count(); i++) { // For each collision shape CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(parent_node3d->get_child(i)); - if (cs) { + if (cs && cs->is_inside_tree()) { // Take the distance between the Body center to the shape center real_t r = cs->get_transform().origin.length(); if (cs->get_shape().is_valid()) { @@ -146,6 +153,9 @@ real_t NavigationObstacle3D::estimate_agent_radius() const { r *= MAX(s.x, MAX(s.y, s.z)); // Takes the biggest radius radius = MAX(radius, r); + } else if (cs && !cs->is_inside_tree()) { + WARN_PRINT("A CollisionShape3D of the NavigationObstacle3D parent node was not inside the SceneTree when estimating the obstacle radius." + "\nMove the NavigationObstacle3D to a child position below any CollisionShape3D node of the parent node so the CollisionShape3D is already inside the SceneTree."); } } diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 80be770dfc..6404432631 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -171,7 +171,12 @@ void NavigationRegion3D::bake_navigation_mesh(bool p_on_thread) { BakeThreadsArgs *args = memnew(BakeThreadsArgs); args->nav_region = this; - if (p_on_thread) { + if (p_on_thread && !OS::get_singleton()->can_use_threads()) { + WARN_PRINT("NavigationMesh bake 'on_thread' will be disabled as the current OS does not support multiple threads." + "\nAs a fallback the navigation mesh will bake on the main thread which can cause framerate issues."); + } + + if (p_on_thread && OS::get_singleton()->can_use_threads()) { bake_thread.start(_bake_navigation_mesh, args); } else { _bake_navigation_mesh(args); diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 5f9bca7c49..94cd5400db 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -390,18 +390,18 @@ void RigidDynamicBody3D::_body_enter_tree(ObjectID p_id) { ERR_FAIL_COND(!node); ERR_FAIL_COND(!contact_monitor); - Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(p_id); + HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_tree); + ERR_FAIL_COND(E->value.in_tree); - E->get().in_tree = true; + E->value.in_tree = true; contact_monitor->locked = true; emit_signal(SceneStringNames::get_singleton()->body_entered, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape); } contact_monitor->locked = false; @@ -412,17 +412,17 @@ void RigidDynamicBody3D::_body_exit_tree(ObjectID p_id) { Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); ERR_FAIL_COND(!contact_monitor); - Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(p_id); + HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_tree); - E->get().in_tree = false; + ERR_FAIL_COND(!E->value.in_tree); + E->value.in_tree = false; contact_monitor->locked = true; emit_signal(SceneStringNames::get_singleton()->body_exited, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + for (int i = 0; i < E->value.shapes.size(); i++) { + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape); } contact_monitor->locked = false; @@ -436,43 +436,43 @@ void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!contact_monitor); - Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(objid); + HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(objid); ERR_FAIL_COND(!body_in && !E); if (body_in) { if (!E) { E = contact_monitor->body_map.insert(objid, BodyState()); - E->get().rid = p_body; - //E->get().rc=0; - E->get().in_tree = node && node->is_inside_tree(); + E->value.rid = p_body; + //E->value.rc=0; + E->value.in_tree = node && node->is_inside_tree(); if (node) { node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree), make_binds(objid)); node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree), make_binds(objid)); - if (E->get().in_tree) { + if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } } } - //E->get().rc++; + //E->value.rc++; if (node) { - E->get().shapes.insert(ShapePair(p_body_shape, p_local_shape)); + E->value.shapes.insert(ShapePair(p_body_shape, p_local_shape)); } - if (E->get().in_tree) { + if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape); } } else { - //E->get().rc--; + //E->value.rc--; if (node) { - E->get().shapes.erase(ShapePair(p_body_shape, p_local_shape)); + E->value.shapes.erase(ShapePair(p_body_shape, p_local_shape)); } - bool in_tree = E->get().in_tree; + bool in_tree = E->value.in_tree; - if (E->get().shapes.is_empty()) { + if (E->value.shapes.is_empty()) { if (node) { node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree)); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree)); @@ -481,7 +481,7 @@ void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p } } - contact_monitor->body_map.erase(E); + contact_monitor->body_map.remove(E); } if (node && in_tree) { emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_local_shape); @@ -547,7 +547,7 @@ void RigidDynamicBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) //bool found=false; - Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(obj); + HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(obj); if (!E) { toadd[toadd_count].rid = rid; toadd[toadd_count].local_shape = local_shape; @@ -558,7 +558,7 @@ void RigidDynamicBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) } ShapePair sp(shape, local_shape); - int idx = E->get().shapes.find(sp); + int idx = E->value.shapes.find(sp); if (idx == -1) { toadd[toadd_count].rid = rid; toadd[toadd_count].local_shape = local_shape; @@ -568,7 +568,7 @@ void RigidDynamicBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) continue; } - E->get().shapes[idx].tagged = true; + E->value.shapes[idx].tagged = true; } //put the ones to remove diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index e64987b73e..22dcb218bc 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -212,7 +212,7 @@ private: struct ContactMonitor { bool locked = false; - Map<ObjectID, BodyState> body_map; + HashMap<ObjectID, BodyState> body_map; }; ContactMonitor *contact_monitor = nullptr; @@ -714,7 +714,9 @@ public: const JointData *get_joint_data() const; Skeleton3D *find_skeleton_parent(); - int get_bone_id() const { return bone_id; } + int get_bone_id() const { + return bone_id; + } void set_joint_type(JointType p_joint_type); JointType get_joint_type() const; diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h index ad85001591..d6062969d8 100644 --- a/scene/3d/ray_cast_3d.h +++ b/scene/3d/ray_cast_3d.h @@ -46,7 +46,7 @@ class RayCast3D : public Node3D { Vector3 collision_normal; Vector3 target_position = Vector3(0, -1, 0); - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = 1; bool exclude_parent_body = true; diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 9e403a6ecd..f4a7767c44 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -263,7 +263,7 @@ void Skeleton3D::_notification(int p_what) { force_update_all_bone_transforms(); // Update skins. - for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { + for (RBSet<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { const Skin *skin = E->get()->skin.operator->(); RID skeleton = E->get()->skeleton; uint32_t bind_count = skin->get_bind_count(); @@ -1000,7 +1000,7 @@ Ref<Skin> Skeleton3D::create_skin_from_rest_transforms() { Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { ERR_FAIL_COND_V(p_skin.is_null(), Ref<SkinReference>()); - for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { + for (RBSet<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { if (E->get()->skin == p_skin) { return Ref<SkinReference>(E->get()); } @@ -1303,7 +1303,7 @@ Skeleton3D::Skeleton3D() { Skeleton3D::~Skeleton3D() { // Some skins may remain bound. - for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { + for (RBSet<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { E->get()->skeleton_node = nullptr; } } diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index ca706bea98..c72792bd47 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -131,7 +131,7 @@ private: } }; - Set<SkinReference *> skin_bindings; + RBSet<SkinReference *> skin_bindings; void _skin_changed(); diff --git a/scene/3d/spring_arm_3d.h b/scene/3d/spring_arm_3d.h index b247ea1707..78d9db7259 100644 --- a/scene/3d/spring_arm_3d.h +++ b/scene/3d/spring_arm_3d.h @@ -37,7 +37,7 @@ class SpringArm3D : public Node3D { GDCLASS(SpringArm3D, Node3D); Ref<Shape3D> shape; - Set<RID> excluded_objects; + RBSet<RID> excluded_objects; real_t spring_length = 1.0; real_t current_spring_length = 0.0; bool keep_child_basis = false; diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h index d2371d819b..4ef70f7764 100644 --- a/scene/3d/vehicle_body_3d.h +++ b/scene/3d/vehicle_body_3d.h @@ -162,7 +162,7 @@ class VehicleBody3D : public RigidDynamicBody3D { real_t m_steeringValue = 0.0; real_t m_currentVehicleSpeedKmHour = 0.0; - Set<RID> exclude; + RBSet<RID> exclude; Vector<Vector3> m_forwardWS; Vector<Vector3> m_axle; diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index d6ac5ccf30..42a2a68e2d 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -592,7 +592,6 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) { bake_cells.write[p_idx].albedo[2] = 0; float alpha_average = 0; - int children_found = 0; for (int i = 0; i < 8; i++) { uint32_t child = bake_cells[p_idx].children[i]; @@ -603,8 +602,6 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) { _fixup_plot(child, p_level + 1); alpha_average += bake_cells[child].alpha; - - children_found++; } bake_cells.write[p_idx].alpha = alpha_average / 8.0; diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h index dc7569d17c..0179795ddc 100644 --- a/scene/3d/voxelizer.h +++ b/scene/3d/voxelizer.h @@ -86,7 +86,7 @@ private: Vector<Color> emission; }; - Map<Ref<Material>, MaterialCache> material_cache; + HashMap<Ref<Material>, MaterialCache> material_cache; AABB original_bounds; AABB po2_bounds; int axis_cell_size[3] = {}; diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index f638644628..fe9d9ae4dd 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -71,7 +71,7 @@ void WorldEnvironment::_update_current_environment() { } else { get_viewport()->find_world_3d()->set_environment(Ref<Environment>()); } - get_tree()->call_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); + get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); } void WorldEnvironment::_update_current_camera_effects() { @@ -82,7 +82,7 @@ void WorldEnvironment::_update_current_camera_effects() { get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>()); } - get_tree()->call_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); + get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); } void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) { diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 2acacd7396..73bde633cb 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -354,7 +354,7 @@ class AnimationNodeBlendTree : public AnimationRootNode { Vector<StringName> connections; }; - Map<StringName, Node> nodes; + HashMap<StringName, Node> nodes; Vector2 graph_offset; diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index b3cae4f5b5..81df12791c 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -188,7 +188,7 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta Vector2 current_pos = p_state_machine->states[current].position; Vector2 target_pos = p_state_machine->states[p_travel].position; - Map<StringName, AStarCost> cost_map; + HashMap<StringName, AStarCost> cost_map; List<int> open_list; diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h index 39a84358fb..07d0579533 100644 --- a/scene/animation/animation_node_state_machine.h +++ b/scene/animation/animation_node_state_machine.h @@ -152,7 +152,7 @@ private: Vector2 position; }; - Map<StringName, State> states; + HashMap<StringName, State> states; struct Transition { StringName from; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 081e6e809a..9ace6db505 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -163,7 +163,7 @@ bool AnimationPlayer::_get(const StringName &p_name, Variant &r_ret) const { for (int i = 0; i < keys.size(); i++) { array.push_back(keys[i].from); array.push_back(keys[i].to); - array.push_back(blend_times[keys[i]]); + array.push_back(blend_times.get(keys[i])); } r_ret = array; @@ -588,10 +588,10 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double //StringName property=a->track_get_path(i).get_property(); - Map<StringName, TrackNodeCache::PropertyAnim>::Element *E = nc->property_anim.find(a->track_get_path(i).get_concatenated_subnames()); + HashMap<StringName, TrackNodeCache::PropertyAnim>::Iterator E = nc->property_anim.find(a->track_get_path(i).get_concatenated_subnames()); ERR_CONTINUE(!E); //should it continue, or create a new one? - TrackNodeCache::PropertyAnim *pa = &E->get(); + TrackNodeCache::PropertyAnim *pa = &E->value; Animation::UpdateMode update_mode = a->value_track_get_update_mode(i); @@ -738,10 +738,10 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double continue; } - Map<StringName, TrackNodeCache::BezierAnim>::Element *E = nc->bezier_anim.find(a->track_get_path(i).get_concatenated_subnames()); + HashMap<StringName, TrackNodeCache::BezierAnim>::Iterator E = nc->bezier_anim.find(a->track_get_path(i).get_concatenated_subnames()); ERR_CONTINUE(!E); //should it continue, or create a new one? - TrackNodeCache::BezierAnim *ba = &E->get(); + TrackNodeCache::BezierAnim *ba = &E->value; real_t bezier = a->bezier_track_interpolate(i, p_time); if (ba->accum_pass != accum_pass) { @@ -1272,7 +1272,7 @@ void AnimationPlayer::_animation_removed(const StringName &p_name, const StringN void AnimationPlayer::_rename_animation(const StringName &p_from_name, const StringName &p_to_name) { // Rename autoplay or blends if needed. List<BlendKey> to_erase; - Map<BlendKey, float> to_insert; + HashMap<BlendKey, float, BlendKey> to_insert; for (const KeyValue<BlendKey, float> &E : blend_times) { BlendKey bk = E.key; BlendKey new_bk = bk; @@ -1298,8 +1298,8 @@ void AnimationPlayer::_rename_animation(const StringName &p_from_name, const Str } while (to_insert.size()) { - blend_times[to_insert.front()->key()] = to_insert.front()->get(); - to_insert.erase(to_insert.front()); + blend_times[to_insert.begin()->key] = to_insert.begin()->value; + to_insert.remove(to_insert.begin()); } if (autoplay == p_from_name) { @@ -1766,7 +1766,7 @@ void AnimationPlayer::_animation_changed() { } void AnimationPlayer::_stop_playing_caches() { - for (Set<TrackNodeCache *>::Element *E = playing_caches.front(); E; E = E->next()) { + for (RBSet<TrackNodeCache *>::Element *E = playing_caches.front(); E; E = E->next()) { if (E->get()->node && E->get()->audio_playing) { E->get()->node->call(SNAME("stop")); } diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 8c2f0e390b..3ef87dba28 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -132,7 +132,7 @@ private: Variant capture; }; - Map<StringName, PropertyAnim> property_anim; + HashMap<StringName, PropertyAnim> property_anim; struct BezierAnim { Vector<StringName> bezier_property; @@ -142,7 +142,7 @@ private: uint64_t accum_pass = 0; }; - Map<StringName, BezierAnim> bezier_anim; + HashMap<StringName, BezierAnim> bezier_anim; uint32_t last_setup_pass = 0; TrackNodeCache() {} @@ -153,6 +153,16 @@ private: int bone_idx = -1; int blend_shape_idx = -1; + static uint32_t hash(const TrackNodeCacheKey &p_key) { + uint32_t h = hash_one_uint64(p_key.id); + h = hash_djb2_one_32(p_key.bone_idx, h); + return hash_djb2_one_32(p_key.blend_shape_idx, h); + } + + inline bool operator==(const TrackNodeCacheKey &p_right) const { + return id == p_right.id && bone_idx == p_right.bone_idx && blend_shape_idx == p_right.blend_shape_idx; + } + inline bool operator<(const TrackNodeCacheKey &p_right) const { if (id == p_right.id) { if (blend_shape_idx == p_right.blend_shape_idx) { @@ -166,7 +176,7 @@ private: } }; - Map<TrackNodeCacheKey, TrackNodeCache> node_cache_map; + HashMap<TrackNodeCacheKey, TrackNodeCache, TrackNodeCacheKey> node_cache_map; TrackNodeCache *cache_update[NODE_CACHE_UPDATE_MAX]; int cache_update_size = 0; @@ -174,7 +184,7 @@ private: int cache_update_prop_size = 0; TrackNodeCache::BezierAnim *cache_update_bezier[NODE_CACHE_UPDATE_MAX]; int cache_update_bezier_size = 0; - Set<TrackNodeCache *> playing_caches; + RBSet<TrackNodeCache *> playing_caches; uint64_t accum_pass = 1; float speed_scale = 1.0; @@ -189,7 +199,7 @@ private: uint64_t last_update = 0; }; - Map<StringName, AnimationData> animation_set; + HashMap<StringName, AnimationData> animation_set; struct AnimationLibraryData { StringName name; @@ -202,10 +212,22 @@ private: struct BlendKey { StringName from; StringName to; - bool operator<(const BlendKey &bk) const { return from == bk.from ? String(to) < String(bk.to) : String(from) < String(bk.from); } + static uint32_t hash(const BlendKey &p_key) { + return hash_one_uint64((uint64_t(p_key.from.hash()) << 32) | uint32_t(p_key.to.hash())); + } + bool operator==(const BlendKey &bk) const { + return from == bk.from && to == bk.to; + } + bool operator<(const BlendKey &bk) const { + if (from == bk.from) { + return to < bk.to; + } else { + return from < bk.from; + } + } }; - Map<BlendKey, float> blend_times; + HashMap<BlendKey, float, BlendKey> blend_times; struct PlaybackData { AnimationData *from = nullptr; diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index b0590bc2bd..92af15d5d3 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -198,12 +198,11 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri blendw[i] = 0.0; //all to zero by default } - const NodePath *K = nullptr; - while ((K = filter.next(K))) { - if (!state->track_map.has(*K)) { + for (const KeyValue<NodePath, bool> &E : filter) { + if (!state->track_map.has(E.key)) { continue; } - int idx = state->track_map[*K]; + int idx = state->track_map[E.key]; blendw[idx] = 1.0; //filtered goes to one } @@ -374,9 +373,8 @@ bool AnimationNode::has_filter() const { Array AnimationNode::_get_filters() const { Array paths; - const NodePath *K = nullptr; - while ((K = filter.next(K))) { - paths.push_back(String(*K)); //use strings, so sorting is possible + for (const KeyValue<NodePath, bool> &E : filter) { + paths.push_back(String(E.key)); //use strings, so sorting is possible } paths.sort(); //done so every time the scene is saved, it does not change @@ -488,7 +486,7 @@ void AnimationTree::set_active(bool p_active) { } if (!active && is_inside_tree()) { - for (Set<TrackCache *>::Element *E = playing_caches.front(); E; E = E->next()) { + for (RBSet<TrackCache *>::Element *E = playing_caches.front(); E; E = E->next()) { if (ObjectDB::get_instance(E->get()->object_id)) { E->get()->object->call(SNAME("stop")); } @@ -803,11 +801,10 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { List<NodePath> to_delete; - const NodePath *K = nullptr; - while ((K = track_cache.next(K))) { - TrackCache *tc = track_cache[*K]; + for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { + TrackCache *tc = track_cache[K.key]; if (tc->setup_pass != setup_pass) { - to_delete.push_back(*K); + to_delete.push_back(K.key); } } @@ -820,10 +817,9 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { state.track_map.clear(); - K = nullptr; int idx = 0; - while ((K = track_cache.next(K))) { - state.track_map[*K] = idx; + for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { + state.track_map[K.key] = idx; idx++; } @@ -835,9 +831,8 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { } void AnimationTree::_clear_caches() { - const NodePath *K = nullptr; - while ((K = track_cache.next(K))) { - memdelete(track_cache[*K]); + for (KeyValue<NodePath, TrackCache *> &K : track_cache) { + memdelete(K.value); } playing_caches.clear(); @@ -1569,9 +1564,8 @@ void AnimationTree::_process_graph(double p_delta) { { // finally, set the tracks - const NodePath *K = nullptr; - while ((K = track_cache.next(K))) { - TrackCache *track = track_cache[*K]; + for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { + TrackCache *track = K.value; if (track->process_pass != process_pass) { continue; //not processed, ignore } diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 3f09bf7f4b..d40d4ccbbd 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -266,7 +266,7 @@ private: }; HashMap<NodePath, TrackCache *> track_cache; - Set<TrackCache *> playing_caches; + RBSet<TrackCache *> playing_caches; Ref<AnimationNode> root; diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index 17b573b776..b792b11dbc 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -68,7 +68,7 @@ bool SceneDebugger::RPCProfilerFrame::deserialize(const Array &p_arr) { } class SceneDebugger::RPCProfiler : public EngineProfiler { - Map<ObjectID, RPCNodeInfo> rpc_node_data; + HashMap<ObjectID, RPCNodeInfo> rpc_node_data; uint64_t last_profile_time = 0; void init_node(const ObjectID p_node) { @@ -345,22 +345,22 @@ void SceneDebugger::remove_from_cache(const String &p_filename, Node *p_node) { return; } - Map<String, Set<Node *>> &edit_cache = debugger->live_scene_edit_cache; - Map<String, Set<Node *>>::Element *E = edit_cache.find(p_filename); + HashMap<String, RBSet<Node *>> &edit_cache = debugger->live_scene_edit_cache; + HashMap<String, RBSet<Node *>>::Iterator E = edit_cache.find(p_filename); if (E) { - E->get().erase(p_node); - if (E->get().size() == 0) { - edit_cache.erase(E); + E->value.erase(p_node); + if (E->value.size() == 0) { + edit_cache.remove(E); } } - Map<Node *, Map<ObjectID, Node *>> &remove_list = debugger->live_edit_remove_list; - Map<Node *, Map<ObjectID, Node *>>::Element *F = remove_list.find(p_node); + HashMap<Node *, HashMap<ObjectID, Node *>> &remove_list = debugger->live_edit_remove_list; + HashMap<Node *, HashMap<ObjectID, Node *>>::Iterator F = remove_list.find(p_node); if (F) { - for (const KeyValue<ObjectID, Node *> &G : F->get()) { + for (const KeyValue<ObjectID, Node *> &G : F->value) { memdelete(G.value); } - remove_list.erase(F); + remove_list.remove(F); } } @@ -408,47 +408,47 @@ SceneDebuggerObject::SceneDebuggerObject(ObjectID p_id) { } void SceneDebuggerObject::_parse_script_properties(Script *p_script, ScriptInstance *p_instance) { - typedef Map<const Script *, Set<StringName>> ScriptMemberMap; - typedef Map<const Script *, Map<StringName, Variant>> ScriptConstantsMap; + typedef HashMap<const Script *, RBSet<StringName>> ScriptMemberMap; + typedef HashMap<const Script *, HashMap<StringName, Variant>> ScriptConstantsMap; ScriptMemberMap members; if (p_instance) { - members[p_script] = Set<StringName>(); + members[p_script] = RBSet<StringName>(); p_script->get_members(&(members[p_script])); } ScriptConstantsMap constants; - constants[p_script] = Map<StringName, Variant>(); + constants[p_script] = HashMap<StringName, Variant>(); p_script->get_constants(&(constants[p_script])); Ref<Script> base = p_script->get_base_script(); while (base.is_valid()) { if (p_instance) { - members[base.ptr()] = Set<StringName>(); + members[base.ptr()] = RBSet<StringName>(); base->get_members(&(members[base.ptr()])); } - constants[base.ptr()] = Map<StringName, Variant>(); + constants[base.ptr()] = HashMap<StringName, Variant>(); base->get_constants(&(constants[base.ptr()])); base = base->get_base_script(); } // Members - for (ScriptMemberMap::Element *sm = members.front(); sm; sm = sm->next()) { - for (Set<StringName>::Element *E = sm->get().front(); E; E = E->next()) { + for (KeyValue<const Script *, RBSet<StringName>> sm : members) { + for (RBSet<StringName>::Element *E = sm.value.front(); E; E = E->next()) { Variant m; if (p_instance->get(E->get(), m)) { - String script_path = sm->key() == p_script ? "" : sm->key()->get_path().get_file() + "/"; + String script_path = sm.key == p_script ? "" : sm.key->get_path().get_file() + "/"; PropertyInfo pi(m.get_type(), "Members/" + script_path + E->get()); properties.push_back(SceneDebuggerProperty(pi, m)); } } } // Constants - for (ScriptConstantsMap::Element *sc = constants.front(); sc; sc = sc->next()) { - for (const KeyValue<StringName, Variant> &E : sc->get()) { - String script_path = sc->key() == p_script ? "" : sc->key()->get_path().get_file() + "/"; + for (KeyValue<const Script *, HashMap<StringName, Variant>> &sc : constants) { + for (const KeyValue<StringName, Variant> &E : sc.value) { + String script_path = sc.key == p_script ? "" : sc.key->get_path().get_file() + "/"; if (E.value.get_type() == Variant::OBJECT) { Variant id = ((Object *)E.value)->get_instance_id(); PropertyInfo pi(id.get_type(), "Constants/" + E.key, PROPERTY_HINT_OBJECT_ID, "Object"); @@ -624,12 +624,12 @@ void LiveEditor::_node_set_func(int p_id, const StringName &p_prop, const Varian base = scene_tree->root->get_node(live_edit_root); } - Map<String, Set<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene); + HashMap<String, RBSet<Node *>>::Iterator E = live_scene_edit_cache.find(live_edit_scene); if (!E) { return; //scene not editable } - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { + for (RBSet<Node *>::Element *F = E->value.front(); F; F = F->next()) { Node *n = F->get(); if (base && !base->is_ancestor_of(n)) { @@ -668,12 +668,12 @@ void LiveEditor::_node_call_func(int p_id, const StringName &p_method, const Var base = scene_tree->root->get_node(live_edit_root); } - Map<String, Set<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene); + HashMap<String, RBSet<Node *>>::Iterator E = live_scene_edit_cache.find(live_edit_scene); if (!E) { return; //scene not editable } - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { + for (RBSet<Node *>::Element *F = E->value.front(); F; F = F->next()) { Node *n = F->get(); if (base && !base->is_ancestor_of(n)) { @@ -753,12 +753,12 @@ void LiveEditor::_create_node_func(const NodePath &p_parent, const String &p_typ base = scene_tree->root->get_node(live_edit_root); } - Map<String, Set<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene); + HashMap<String, RBSet<Node *>>::Iterator E = live_scene_edit_cache.find(live_edit_scene); if (!E) { return; //scene not editable } - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { + for (RBSet<Node *>::Element *F = E->value.front(); F; F = F->next()) { Node *n = F->get(); if (base && !base->is_ancestor_of(n)) { @@ -797,12 +797,12 @@ void LiveEditor::_instance_node_func(const NodePath &p_parent, const String &p_p base = scene_tree->root->get_node(live_edit_root); } - Map<String, Set<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene); + HashMap<String, RBSet<Node *>>::Iterator E = live_scene_edit_cache.find(live_edit_scene); if (!E) { return; //scene not editable } - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { + for (RBSet<Node *>::Element *F = E->value.front(); F; F = F->next()) { Node *n = F->get(); if (base && !base->is_ancestor_of(n)) { @@ -835,13 +835,13 @@ void LiveEditor::_remove_node_func(const NodePath &p_at) { base = scene_tree->root->get_node(live_edit_root); } - Map<String, Set<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene); + HashMap<String, RBSet<Node *>>::Iterator E = live_scene_edit_cache.find(live_edit_scene); if (!E) { return; //scene not editable } - for (Set<Node *>::Element *F = E->get().front(); F;) { - Set<Node *>::Element *N = F->next(); + for (RBSet<Node *>::Element *F = E->value.front(); F;) { + RBSet<Node *>::Element *N = F->next(); Node *n = F->get(); @@ -871,13 +871,13 @@ void LiveEditor::_remove_and_keep_node_func(const NodePath &p_at, ObjectID p_kee base = scene_tree->root->get_node(live_edit_root); } - Map<String, Set<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene); + HashMap<String, RBSet<Node *>>::Iterator E = live_scene_edit_cache.find(live_edit_scene); if (!E) { return; //scene not editable } - for (Set<Node *>::Element *F = E->get().front(); F;) { - Set<Node *>::Element *N = F->next(); + for (RBSet<Node *>::Element *F = E->value.front(); F;) { + RBSet<Node *>::Element *N = F->next(); Node *n = F->get(); @@ -910,13 +910,13 @@ void LiveEditor::_restore_node_func(ObjectID p_id, const NodePath &p_at, int p_a base = scene_tree->root->get_node(live_edit_root); } - Map<String, Set<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene); + HashMap<String, RBSet<Node *>>::Iterator E = live_scene_edit_cache.find(live_edit_scene); if (!E) { return; //scene not editable } - for (Set<Node *>::Element *F = E->get().front(); F;) { - Set<Node *>::Element *N = F->next(); + for (RBSet<Node *>::Element *F = E->value.front(); F;) { + RBSet<Node *>::Element *N = F->next(); Node *n = F->get(); @@ -929,23 +929,23 @@ void LiveEditor::_restore_node_func(ObjectID p_id, const NodePath &p_at, int p_a } Node *n2 = n->get_node(p_at); - Map<Node *, Map<ObjectID, Node *>>::Element *EN = live_edit_remove_list.find(n); + HashMap<Node *, HashMap<ObjectID, Node *>>::Iterator EN = live_edit_remove_list.find(n); if (!EN) { continue; } - Map<ObjectID, Node *>::Element *FN = EN->get().find(p_id); + HashMap<ObjectID, Node *>::Iterator FN = EN->value.find(p_id); if (!FN) { continue; } - n2->add_child(FN->get()); + n2->add_child(FN->value); - EN->get().erase(FN); + EN->value.remove(FN); - if (EN->get().size() == 0) { - live_edit_remove_list.erase(EN); + if (EN->value.size() == 0) { + live_edit_remove_list.remove(EN); } F = N; @@ -963,12 +963,12 @@ void LiveEditor::_duplicate_node_func(const NodePath &p_at, const String &p_new_ base = scene_tree->root->get_node(live_edit_root); } - Map<String, Set<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene); + HashMap<String, RBSet<Node *>>::Iterator E = live_scene_edit_cache.find(live_edit_scene); if (!E) { return; //scene not editable } - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { + for (RBSet<Node *>::Element *F = E->value.front(); F; F = F->next()) { Node *n = F->get(); if (base && !base->is_ancestor_of(n)) { @@ -1002,12 +1002,12 @@ void LiveEditor::_reparent_node_func(const NodePath &p_at, const NodePath &p_new base = scene_tree->root->get_node(live_edit_root); } - Map<String, Set<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene); + HashMap<String, RBSet<Node *>>::Iterator E = live_scene_edit_cache.find(live_edit_scene); if (!E) { return; //scene not editable } - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { + for (RBSet<Node *>::Element *F = E->value.front(); F; F = F->next()) { Node *n = F->get(); if (base && !base->is_ancestor_of(n)) { diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h index 29d7da7d11..0daefa9609 100644 --- a/scene/debugger/scene_debugger.h +++ b/scene/debugger/scene_debugger.h @@ -132,14 +132,14 @@ public: class LiveEditor { private: friend class SceneDebugger; - Map<int, NodePath> live_edit_node_path_cache; - Map<int, String> live_edit_resource_cache; + HashMap<int, NodePath> live_edit_node_path_cache; + HashMap<int, String> live_edit_resource_cache; NodePath live_edit_root; String live_edit_scene; - Map<String, Set<Node *>> live_scene_edit_cache; - Map<Node *, Map<ObjectID, Node *>> live_edit_remove_list; + HashMap<String, RBSet<Node *>> live_scene_edit_cache; + HashMap<Node *, HashMap<ObjectID, Node *>> live_edit_remove_list; void _send_tree(); diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 789c01adf3..595f0cbea7 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -43,7 +43,7 @@ void BaseButton::_unpress_group() { status.pressed = true; } - for (Set<BaseButton *>::Element *E = button_group->buttons.front(); E; E = E->next()) { + for (RBSet<BaseButton *>::Element *E = button_group->buttons.front(); E; E = E->next()) { if (E->get() == this) { continue; } @@ -485,14 +485,14 @@ BaseButton::~BaseButton() { } void ButtonGroup::get_buttons(List<BaseButton *> *r_buttons) { - for (Set<BaseButton *>::Element *E = buttons.front(); E; E = E->next()) { + for (RBSet<BaseButton *>::Element *E = buttons.front(); E; E = E->next()) { r_buttons->push_back(E->get()); } } Array ButtonGroup::_get_buttons() { Array btns; - for (Set<BaseButton *>::Element *E = buttons.front(); E; E = E->next()) { + for (RBSet<BaseButton *>::Element *E = buttons.front(); E; E = E->next()) { btns.push_back(E->get()); } @@ -500,7 +500,7 @@ Array ButtonGroup::_get_buttons() { } BaseButton *ButtonGroup::get_pressed_button() { - for (Set<BaseButton *>::Element *E = buttons.front(); E; E = E->next()) { + for (RBSet<BaseButton *>::Element *E = buttons.front(); E; E = E->next()) { if (E->get()->is_pressed()) { return E->get(); } diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index f4f9b88868..0b70d285ee 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -143,7 +143,7 @@ VARIANT_ENUM_CAST(BaseButton::ActionMode) class ButtonGroup : public Resource { GDCLASS(ButtonGroup, Resource); friend class BaseButton; - Set<BaseButton *> buttons; + RBSet<BaseButton *> buttons; protected: static void _bind_methods(); diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index 251648da69..df695feba8 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -52,7 +52,7 @@ void BoxContainer::_resort() { int stretch_min = 0; int stretch_avail = 0; float stretch_ratio_total = 0.0; - Map<Control *, _MinSizeCache> min_size_cache; + HashMap<Control *, _MinSizeCache> min_size_cache; for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index e294060bbd..c54897035a 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -258,7 +258,8 @@ void Button::_notification(int p_what) { if (expand_icon) { Size2 _size = get_size() - style->get_offset() * 2; - _size.width -= get_theme_constant(SNAME("h_separation")) + icon_ofs_region; + int icon_text_separation = text.is_empty() ? 0 : get_theme_constant(SNAME("h_separation")); + _size.width -= icon_text_separation + icon_ofs_region; if (!clip_text && icon_align_rtl_checked != HORIZONTAL_ALIGNMENT_CENTER) { _size.width -= text_buf->get_size().width; } diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 05bb30f7e0..197c9005c3 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -357,6 +357,11 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } Ref<InputEventKey> k = p_gui_input; + if (TextEdit::alt_input(p_gui_input)) { + accept_event(); + return; + } + bool update_code_completion = false; if (!k.is_valid()) { TextEdit::gui_input(p_gui_input); @@ -735,7 +740,7 @@ void CodeEdit::set_auto_indent_prefixes(const TypedArray<String> &p_prefixes) { TypedArray<String> CodeEdit::get_auto_indent_prefixes() const { TypedArray<String> prefixes; - for (const Set<char32_t>::Element *E = auto_indent_prefixes.front(); E; E = E->next()) { + for (const RBSet<char32_t>::Element *E = auto_indent_prefixes.front(); E; E = E->next()) { prefixes.push_back(String::chr(E->get())); } return prefixes; @@ -1623,7 +1628,7 @@ Point2 CodeEdit::get_delimiter_start_position(int p_line, int p_column) const { start_position.y = -1; start_position.x = -1; - bool in_region = ((p_line <= 0 || delimiter_cache[p_line - 1].size() < 1) ? -1 : delimiter_cache[p_line - 1].back()->value()) != -1; + bool in_region = ((p_line <= 0 || delimiter_cache[p_line - 1].size() < 1) ? -1 : delimiter_cache[p_line - 1].back()->get()) != -1; /* Check the keys for this line. */ for (const KeyValue<int, int> &E : delimiter_cache[p_line]) { @@ -1747,7 +1752,7 @@ void CodeEdit::set_code_completion_prefixes(const TypedArray<String> &p_prefixes TypedArray<String> CodeEdit::get_code_completion_prefixes() const { TypedArray<String> prefixes; - for (const Set<char32_t>::Element *E = code_completion_prefixes.front(); E; E = E->next()) { + for (const RBSet<char32_t>::Element *E = code_completion_prefixes.front(); E; E = E->next()) { prefixes.push_back(String::chr(E->get())); } return prefixes; @@ -2397,7 +2402,7 @@ void CodeEdit::_update_delimiter_cache(int p_from_line, int p_to_line) { } } else { for (int i = start_line; i < end_line; i++) { - delimiter_cache.insert(i, Map<int, int>()); + delimiter_cache.insert(i, RBMap<int, int>()); } } } @@ -2534,7 +2539,7 @@ int CodeEdit::_is_in_delimiter(int p_line, int p_column, DelimiterType p_type) c int region = (p_line <= 0 || delimiter_cache[p_line - 1].size() < 1) ? -1 : delimiter_cache[p_line - 1].back()->value(); bool in_region = region != -1 && delimiters[region].type == p_type; - for (Map<int, int>::Element *E = delimiter_cache[p_line].front(); E; E = E->next()) { + for (RBMap<int, int>::Element *E = delimiter_cache[p_line].front(); E; E = E->next()) { /* If column is specified, loop until the key is larger then the column. */ if (p_column != -1) { if (E->key() > p_column) { @@ -3036,7 +3041,9 @@ void CodeEdit::_text_changed() { lc = get_line_count(); List<int> breakpoints; - breakpointed_lines.get_key_list(&breakpoints); + for (const KeyValue<int, bool> &E : breakpointed_lines) { + breakpoints.push_back(E.key); + } for (const int &line : breakpoints) { if (line < lines_edited_from || (line < lc && is_line_breakpointed(line))) { continue; diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h index 135dd32780..0b00735f46 100644 --- a/scene/gui/code_edit.h +++ b/scene/gui/code_edit.h @@ -58,7 +58,7 @@ private: String indent_text = "\t"; bool auto_indent = false; - Set<char32_t> auto_indent_prefixes; + RBSet<char32_t> auto_indent_prefixes; bool indent_using_spaces = false; int _calculate_spaces_till_next_left_indent(int p_column) const; @@ -176,7 +176,7 @@ private: * ] * ] */ - Vector<Map<int, int>> delimiter_cache; + Vector<RBMap<int, int>> delimiter_cache; void _update_delimiter_cache(int p_from_line = 0, int p_to_line = -1); int _is_in_delimiter(int p_line, int p_column, DelimiterType p_type) const; @@ -214,7 +214,7 @@ private: int code_completion_longest_line = 0; Rect2i code_completion_rect; - Set<char32_t> code_completion_prefixes; + RBSet<char32_t> code_completion_prefixes; List<ScriptLanguage::CodeCompletionOption> code_completion_option_submitted; List<ScriptLanguage::CodeCompletionOption> code_completion_option_sources; String code_completion_base; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index dddeec5610..a0104387c9 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -712,35 +712,25 @@ void Control::_notification(int p_notification) { data.parent_window = Object::cast_to<Window>(get_parent()); data.is_rtl_dirty = true; - Node *parent = this; //meh + CanvasItem *node = this; Control *parent_control = nullptr; - bool subwindow = false; - - while (parent) { - parent = parent->get_parent(); + while (!node->is_set_as_top_level()) { + CanvasItem *parent = Object::cast_to<CanvasItem>(node->get_parent()); if (!parent) { break; } - CanvasItem *ci = Object::cast_to<CanvasItem>(parent); - if (ci && ci->is_set_as_top_level()) { - subwindow = true; - break; - } - parent_control = Object::cast_to<Control>(parent); - if (parent_control) { break; - } else if (ci) { - } else { - break; } + + node = parent; } - if (parent_control && !subwindow) { - //do nothing, has a parent control and not top_level + if (parent_control) { + // Do nothing, has a parent control. if (data.theme.is_null() && parent_control->data.theme_owner) { data.theme_owner = parent_control->data.theme_owner; notification(NOTIFICATION_THEME_CHANGED); @@ -1590,22 +1580,22 @@ void Control::set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos, void Control::_set_anchors_layout_preset(int p_preset) { bool list_changed = false; - if (has_meta("_edit_layout_mode") && (int)get_meta("_edit_layout_mode") != (int)LayoutMode::LAYOUT_MODE_ANCHORS) { + if (get_meta("_edit_layout_mode", LayoutMode::LAYOUT_MODE_ANCHORS).operator int() != LayoutMode::LAYOUT_MODE_ANCHORS) { list_changed = true; - set_meta("_edit_layout_mode", (int)LayoutMode::LAYOUT_MODE_ANCHORS); + set_meta("_edit_layout_mode", LayoutMode::LAYOUT_MODE_ANCHORS); } if (p_preset == -1) { - if (!has_meta("_edit_use_custom_anchors") || !(bool)get_meta("_edit_use_custom_anchors")) { + if (!get_meta("_edit_use_custom_anchors", false)) { set_meta("_edit_use_custom_anchors", true); notify_property_list_changed(); } return; // Keep settings as is. } - if (!has_meta("_edit_use_custom_anchors") || (bool)get_meta("_edit_use_custom_anchors")) { + if (get_meta("_edit_use_custom_anchors", true)) { list_changed = true; - set_meta("_edit_use_custom_anchors", false); + remove_meta("_edit_use_custom_anchors"); } LayoutPreset preset = (LayoutPreset)p_preset; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 6da5340ca4..1725816c31 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -915,7 +915,7 @@ void FileDialog::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title"); ADD_PROPERTY(PropertyInfo(Variant::INT, "file_mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_file_mode", "get_file_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User Data,File System"), "set_access", "get_access"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR, "", PROPERTY_USAGE_NONE), "set_current_dir", "get_current_dir"); diff --git a/scene/gui/flow_container.cpp b/scene/gui/flow_container.cpp index 1e5863b845..30b694da76 100644 --- a/scene/gui/flow_container.cpp +++ b/scene/gui/flow_container.cpp @@ -49,7 +49,7 @@ void FlowContainer::_resort() { bool rtl = is_layout_rtl(); - Map<Control *, Size2i> children_minsize_cache; + HashMap<Control *, Size2i> children_minsize_cache; Vector<_LineData> lines_data; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index f2b724fa39..0ed9a4e989 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -523,7 +523,7 @@ void GraphEdit::_update_comment_enclosed_nodes_list(GraphNode *p_node, HashMap<S } } - p_comment_enclosed_nodes.set(p_node->get_name(), enclosed_nodes); + p_comment_enclosed_nodes.insert(p_node->get_name(), enclosed_nodes); } void GraphEdit::_set_drag_comment_enclosed_nodes(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes, bool p_drag) { @@ -1343,7 +1343,19 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { emit_signal(SNAME("paste_nodes_request")); accept_event(); } else if (p_ev->is_action("ui_graph_delete")) { - emit_signal(SNAME("delete_nodes_request")); + TypedArray<StringName> nodes; + + for (int i = 0; i < get_child_count(); i++) { + GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); + if (!gn) { + continue; + } + if (gn->is_selected() && gn->is_close_button_visible()) { + nodes.push_back(gn->get_name()); + } + } + + emit_signal(SNAME("delete_nodes_request"), nodes); accept_event(); } } @@ -1684,10 +1696,10 @@ void GraphEdit::set_warped_panning(bool p_warped) { warped_panning = p_warped; } -int GraphEdit::_set_operations(SET_OPERATIONS p_operation, Set<StringName> &r_u, const Set<StringName> &r_v) { +int GraphEdit::_set_operations(SET_OPERATIONS p_operation, RBSet<StringName> &r_u, const RBSet<StringName> &r_v) { switch (p_operation) { case GraphEdit::IS_EQUAL: { - for (Set<StringName>::Element *E = r_u.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = r_u.front(); E; E = E->next()) { if (!r_v.has(E->get())) { return 0; } @@ -1698,7 +1710,7 @@ int GraphEdit::_set_operations(SET_OPERATIONS p_operation, Set<StringName> &r_u, if (r_u.size() == r_v.size() && !r_u.size()) { return 1; } - for (Set<StringName>::Element *E = r_u.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = r_u.front(); E; E = E->next()) { if (!r_v.has(E->get())) { return 0; } @@ -1706,7 +1718,7 @@ int GraphEdit::_set_operations(SET_OPERATIONS p_operation, Set<StringName> &r_u, return 1; } break; case GraphEdit::DIFFERENCE: { - for (Set<StringName>::Element *E = r_u.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = r_u.front(); E; E = E->next()) { if (r_v.has(E->get())) { r_u.erase(E->get()); } @@ -1714,7 +1726,7 @@ int GraphEdit::_set_operations(SET_OPERATIONS p_operation, Set<StringName> &r_u, return r_u.size(); } break; case GraphEdit::UNION: { - for (Set<StringName>::Element *E = r_v.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = r_v.front(); E; E = E->next()) { if (!r_u.has(E->get())) { r_u.insert(E->get()); } @@ -1727,27 +1739,27 @@ int GraphEdit::_set_operations(SET_OPERATIONS p_operation, Set<StringName> &r_u, return -1; } -HashMap<int, Vector<StringName>> GraphEdit::_layering(const Set<StringName> &r_selected_nodes, const HashMap<StringName, Set<StringName>> &r_upper_neighbours) { +HashMap<int, Vector<StringName>> GraphEdit::_layering(const RBSet<StringName> &r_selected_nodes, const HashMap<StringName, RBSet<StringName>> &r_upper_neighbours) { HashMap<int, Vector<StringName>> l; - Set<StringName> p = r_selected_nodes, q = r_selected_nodes, u, z; + RBSet<StringName> p = r_selected_nodes, q = r_selected_nodes, u, z; int current_layer = 0; bool selected = false; while (!_set_operations(GraphEdit::IS_EQUAL, q, u)) { _set_operations(GraphEdit::DIFFERENCE, p, u); - for (const Set<StringName>::Element *E = p.front(); E; E = E->next()) { - Set<StringName> n = r_upper_neighbours[E->get()]; + for (const RBSet<StringName>::Element *E = p.front(); E; E = E->next()) { + RBSet<StringName> n = r_upper_neighbours[E->get()]; if (_set_operations(GraphEdit::IS_SUBSET, n, z)) { Vector<StringName> t; t.push_back(E->get()); if (!l.has(current_layer)) { - l.set(current_layer, Vector<StringName>{}); + l.insert(current_layer, Vector<StringName>{}); } selected = true; t.append_array(l[current_layer]); - l.set(current_layer, t); - Set<StringName> V; + l.insert(current_layer, t); + RBSet<StringName> V; V.insert(E->get()); _set_operations(GraphEdit::UNION, u, V); } @@ -1789,8 +1801,8 @@ Vector<StringName> GraphEdit::_split(const Vector<StringName> &r_layer, const Ha return left; } -void GraphEdit::_horizontal_alignment(Dictionary &r_root, Dictionary &r_align, const HashMap<int, Vector<StringName>> &r_layers, const HashMap<StringName, Set<StringName>> &r_upper_neighbours, const Set<StringName> &r_selected_nodes) { - for (const Set<StringName>::Element *E = r_selected_nodes.front(); E; E = E->next()) { +void GraphEdit::_horizontal_alignment(Dictionary &r_root, Dictionary &r_align, const HashMap<int, Vector<StringName>> &r_layers, const HashMap<StringName, RBSet<StringName>> &r_upper_neighbours, const RBSet<StringName> &r_selected_nodes) { + for (const RBSet<StringName>::Element *E = r_selected_nodes.front(); E; E = E->next()) { r_root[E->get()] = E->get(); r_align[E->get()] = E->get(); } @@ -1829,7 +1841,7 @@ void GraphEdit::_horizontal_alignment(Dictionary &r_root, Dictionary &r_align, c } } -void GraphEdit::_crossing_minimisation(HashMap<int, Vector<StringName>> &r_layers, const HashMap<StringName, Set<StringName>> &r_upper_neighbours) { +void GraphEdit::_crossing_minimisation(HashMap<int, Vector<StringName>> &r_layers, const HashMap<StringName, RBSet<StringName>> &r_upper_neighbours) { if (r_layers.size() == 1) { return; } @@ -1860,15 +1872,15 @@ void GraphEdit::_crossing_minimisation(HashMap<int, Vector<StringName>> &r_layer } d[q] = crossings; } - c.set(p, d); + c.insert(p, d); } - r_layers.set(i, _split(lower_layer, c)); + r_layers.insert(i, _split(lower_layer, c)); } } -void GraphEdit::_calculate_inner_shifts(Dictionary &r_inner_shifts, const Dictionary &r_root, const Dictionary &r_node_names, const Dictionary &r_align, const Set<StringName> &r_block_heads, const HashMap<StringName, Pair<int, int>> &r_port_info) { - for (const Set<StringName>::Element *E = r_block_heads.front(); E; E = E->next()) { +void GraphEdit::_calculate_inner_shifts(Dictionary &r_inner_shifts, const Dictionary &r_root, const Dictionary &r_node_names, const Dictionary &r_align, const RBSet<StringName> &r_block_heads, const HashMap<StringName, Pair<int, int>> &r_port_info) { + for (const RBSet<StringName>::Element *E = r_block_heads.front(); E; E = E->next()) { real_t left = 0; StringName u = E->get(); StringName v = r_align[u]; @@ -2026,7 +2038,7 @@ void GraphEdit::_place_block(StringName p_v, float p_delta, const HashMap<int, V threshold = _calculate_threshold(p_v, w, r_node_name, r_layers, r_root, r_align, r_inner_shift, threshold, r_node_positions); w = r_align[w]; } while (w != p_v); - r_node_positions.set(p_v, pos); + r_node_positions.insert(p_v, pos); } #undef PRED @@ -2040,7 +2052,7 @@ void GraphEdit::arrange_nodes() { } Dictionary node_names; - Set<StringName> selected_nodes; + RBSet<StringName> selected_nodes; for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); @@ -2051,7 +2063,7 @@ void GraphEdit::arrange_nodes() { node_names[gn->get_name()] = gn; } - HashMap<StringName, Set<StringName>> upper_neighbours; + HashMap<StringName, RBSet<StringName>> upper_neighbours; HashMap<StringName, Pair<int, int>> port_info; Vector2 origin(FLT_MAX, FLT_MAX); @@ -2066,7 +2078,7 @@ void GraphEdit::arrange_nodes() { if (gn->is_selected()) { selected_nodes.insert(gn->get_name()); - Set<StringName> s; + RBSet<StringName> s; for (List<Connection>::Element *E = connections.front(); E; E = E->next()) { GraphNode *p_from = Object::cast_to<GraphNode>(node_names[E->get().from]); if (E->get().to == gn->get_name() && p_from->is_selected()) { @@ -2082,10 +2094,10 @@ void GraphEdit::arrange_nodes() { ports = p_ports; } } - port_info.set(_connection, ports); + port_info.insert(_connection, ports); } } - upper_neighbours.set(gn->get_name(), s); + upper_neighbours.insert(gn->get_name(), s); } } @@ -2103,13 +2115,13 @@ void GraphEdit::arrange_nodes() { HashMap<StringName, Vector2> new_positions; Vector2 default_position(FLT_MAX, FLT_MAX); Dictionary inner_shift; - Set<StringName> block_heads; + RBSet<StringName> block_heads; - for (const Set<StringName>::Element *E = selected_nodes.front(); E; E = E->next()) { + for (const RBSet<StringName>::Element *E = selected_nodes.front(); E; E = E->next()) { inner_shift[E->get()] = 0.0f; sink[E->get()] = E->get(); shift[E->get()] = FLT_MAX; - new_positions.set(E->get(), default_position); + new_positions.insert(E->get(), default_position); if ((StringName)root[E->get()] == E->get()) { block_heads.insert(E->get()); } @@ -2117,19 +2129,19 @@ void GraphEdit::arrange_nodes() { _calculate_inner_shifts(inner_shift, root, node_names, align, block_heads, port_info); - for (const Set<StringName>::Element *E = block_heads.front(); E; E = E->next()) { + for (const RBSet<StringName>::Element *E = block_heads.front(); E; E = E->next()) { _place_block(E->get(), gap_v, layers, root, align, node_names, inner_shift, sink, shift, new_positions); } origin.y = Object::cast_to<GraphNode>(node_names[layers[0][0]])->get_position_offset().y - (new_positions[layers[0][0]].y + (float)inner_shift[layers[0][0]]); origin.x = Object::cast_to<GraphNode>(node_names[layers[0][0]])->get_position_offset().x; - for (const Set<StringName>::Element *E = block_heads.front(); E; E = E->next()) { + for (const RBSet<StringName>::Element *E = block_heads.front(); E; E = E->next()) { StringName u = E->get(); float start_from = origin.y + new_positions[E->get()].y; do { Vector2 cal_pos; cal_pos.y = start_from + (real_t)inner_shift[u]; - new_positions.set(u, cal_pos); + new_positions.insert(u, cal_pos); u = align[u]; } while (u != E->get()); } @@ -2161,7 +2173,7 @@ void GraphEdit::arrange_nodes() { } cal_pos.x = current_node_start_pos; } - new_positions.set(layer[j], cal_pos); + new_positions.insert(layer[j], cal_pos); } start_from += largest_node_size + gap_h; @@ -2169,7 +2181,7 @@ void GraphEdit::arrange_nodes() { } emit_signal(SNAME("begin_node_move")); - for (const Set<StringName>::Element *E = selected_nodes.front(); E; E = E->next()) { + for (const RBSet<StringName>::Element *E = selected_nodes.front(); E; E = E->next()) { GraphNode *gn = Object::cast_to<GraphNode>(node_names[E->get()]); gn->set_drag(true); Vector2 pos = (new_positions[E->get()]); @@ -2290,7 +2302,7 @@ void GraphEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("node_deselected", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING_NAME, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::VECTOR2, "release_position"))); ADD_SIGNAL(MethodInfo("connection_from_empty", PropertyInfo(Variant::STRING_NAME, "to"), PropertyInfo(Variant::INT, "to_slot"), PropertyInfo(Variant::VECTOR2, "release_position"))); - ADD_SIGNAL(MethodInfo("delete_nodes_request")); + ADD_SIGNAL(MethodInfo("delete_nodes_request", PropertyInfo(Variant::ARRAY, "nodes", PROPERTY_HINT_ARRAY_TYPE, "StringName"))); ADD_SIGNAL(MethodInfo("begin_node_move")); ADD_SIGNAL(MethodInfo("end_node_move")); ADD_SIGNAL(MethodInfo("scroll_offset_changed", PropertyInfo(Variant::VECTOR2, "offset"))); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index f556fcdd23..9e34d5528f 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -228,9 +228,9 @@ private: } }; - Set<ConnType> valid_connection_types; - Set<int> valid_left_disconnect_types; - Set<int> valid_right_disconnect_types; + RBSet<ConnType> valid_connection_types; + RBSet<int> valid_left_disconnect_types; + RBSet<int> valid_right_disconnect_types; HashMap<StringName, Vector<GraphNode *>> comment_enclosed_nodes; void _update_comment_enclosed_nodes_list(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes); @@ -258,12 +258,12 @@ private: UNION, }; - int _set_operations(SET_OPERATIONS p_operation, Set<StringName> &r_u, const Set<StringName> &r_v); - HashMap<int, Vector<StringName>> _layering(const Set<StringName> &r_selected_nodes, const HashMap<StringName, Set<StringName>> &r_upper_neighbours); + int _set_operations(SET_OPERATIONS p_operation, RBSet<StringName> &r_u, const RBSet<StringName> &r_v); + HashMap<int, Vector<StringName>> _layering(const RBSet<StringName> &r_selected_nodes, const HashMap<StringName, RBSet<StringName>> &r_upper_neighbours); Vector<StringName> _split(const Vector<StringName> &r_layer, const HashMap<StringName, Dictionary> &r_crossings); - void _horizontal_alignment(Dictionary &r_root, Dictionary &r_align, const HashMap<int, Vector<StringName>> &r_layers, const HashMap<StringName, Set<StringName>> &r_upper_neighbours, const Set<StringName> &r_selected_nodes); - void _crossing_minimisation(HashMap<int, Vector<StringName>> &r_layers, const HashMap<StringName, Set<StringName>> &r_upper_neighbours); - void _calculate_inner_shifts(Dictionary &r_inner_shifts, const Dictionary &r_root, const Dictionary &r_node_names, const Dictionary &r_align, const Set<StringName> &r_block_heads, const HashMap<StringName, Pair<int, int>> &r_port_info); + void _horizontal_alignment(Dictionary &r_root, Dictionary &r_align, const HashMap<int, Vector<StringName>> &r_layers, const HashMap<StringName, RBSet<StringName>> &r_upper_neighbours, const RBSet<StringName> &r_selected_nodes); + void _crossing_minimisation(HashMap<int, Vector<StringName>> &r_layers, const HashMap<StringName, RBSet<StringName>> &r_upper_neighbours); + void _calculate_inner_shifts(Dictionary &r_inner_shifts, const Dictionary &r_root, const Dictionary &r_node_names, const Dictionary &r_align, const RBSet<StringName> &r_block_heads, const HashMap<StringName, Pair<int, int>> &r_port_info); float _calculate_threshold(StringName p_v, StringName p_w, const Dictionary &r_node_names, const HashMap<int, Vector<StringName>> &r_layers, const Dictionary &r_root, const Dictionary &r_align, const Dictionary &r_inner_shift, real_t p_current_threshold, const HashMap<StringName, Vector2> &r_node_positions); void _place_block(StringName p_v, float p_delta, const HashMap<int, Vector<StringName>> &r_layers, const Dictionary &r_root, const Dictionary &r_align, const Dictionary &r_node_name, const Dictionary &r_inner_shift, Dictionary &r_sink, Dictionary &r_shift, HashMap<StringName, Vector2> &r_node_positions); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index e3ecd17ed8..45f036d8fc 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -93,11 +93,13 @@ bool GraphNode::_set(const StringName &p_name, const Variant &p_value) { si.color_right = p_value; } else if (what == "right_icon") { si.custom_slot_right = p_value; + } else if (what == "draw_stylebox") { + si.draw_stylebox = p_value; } else { return false; } - set_slot(idx, si.enable_left, si.type_left, si.color_left, si.enable_right, si.type_right, si.color_right, si.custom_slot_left, si.custom_slot_right); + set_slot(idx, si.enable_left, si.type_left, si.color_left, si.enable_right, si.type_right, si.color_right, si.custom_slot_left, si.custom_slot_right, si.draw_stylebox); update(); return true; } @@ -144,6 +146,8 @@ bool GraphNode::_get(const StringName &p_name, Variant &r_ret) const { r_ret = si.color_right; } else if (what == "right_icon") { r_ret = si.custom_slot_right; + } else if (what == "draw_stylebox") { + r_ret = si.draw_stylebox; } else { return false; } @@ -175,7 +179,7 @@ void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::INT, base + "right_type")); p_list->push_back(PropertyInfo(Variant::COLOR, base + "right_color")); p_list->push_back(PropertyInfo(Variant::OBJECT, base + "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); - + p_list->push_back(PropertyInfo(Variant::BOOL, base + "draw_stylebox")); idx++; } } @@ -185,6 +189,7 @@ void GraphNode::_resort() { Size2i new_size = get_size(); Ref<StyleBox> sb = get_theme_stylebox(SNAME("frame")); + Ref<StyleBox> sb_slot = get_theme_stylebox(SNAME("slot")); int sep = get_theme_constant(SNAME("separation")); @@ -193,7 +198,7 @@ void GraphNode::_resort() { int stretch_min = 0; int stretch_avail = 0; float stretch_ratio_total = 0; - Map<Control *, _MinSizeCache> min_size_cache; + HashMap<Control *, _MinSizeCache> min_size_cache; for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); @@ -204,7 +209,7 @@ void GraphNode::_resort() { continue; } - Size2i size = c->get_combined_minimum_size(); + Size2i size = c->get_combined_minimum_size() + (slot_info[i].draw_stylebox ? sb_slot->get_minimum_size() : Size2()); _MinSizeCache msc; stretch_min += size.height; @@ -312,7 +317,9 @@ void GraphNode::_resort() { int size = to - from; - Rect2 rect(sb->get_margin(SIDE_LEFT), from, w, size); + float margin = sb->get_margin(SIDE_LEFT) + (slot_info[i].draw_stylebox ? sb_slot->get_margin(SIDE_LEFT) : 0); + float width = w - (slot_info[i].draw_stylebox ? sb_slot->get_minimum_size().x : 0); + Rect2 rect(margin, from, width, size); fit_child_in_rect(c, rect); cache_y.push_back(from - sb->get_margin(SIDE_TOP) + size * 0.5); @@ -351,14 +358,14 @@ void GraphNode::_notification(int p_what) { Ref<StyleBox> sb; if (comment) { - sb = get_theme_stylebox(selected ? "comment_focus" : "comment"); + sb = get_theme_stylebox(selected ? SNAME("comment_focus") : SNAME("comment")); } else { - sb = get_theme_stylebox(selected ? "selected_frame" : "frame"); + sb = get_theme_stylebox(selected ? SNAME("selected_frame") : SNAME("frame")); } - //sb=sb->duplicate(); - //sb->call("set_modulate",modulate); + Ref<StyleBox> sb_slot = get_theme_stylebox(SNAME("slot")); + Ref<Texture2D> port = get_theme_icon(SNAME("port")); Ref<Texture2D> close = get_theme_icon(SNAME("close")); Ref<Texture2D> resizer = get_theme_icon(SNAME("resizer")); @@ -389,13 +396,9 @@ void GraphNode::_notification(int p_what) { int w = get_size().width - sb->get_minimum_size().x; - if (show_close) { - w -= close->get_width(); - } - title_buf->draw(get_canvas_item(), Point2(sb->get_margin(SIDE_LEFT) + title_h_offset, -title_buf->get_size().y + title_offset), title_color); if (show_close) { - Vector2 cpos = Point2(w + sb->get_margin(SIDE_LEFT) + close_h_offset, -close->get_height() + close_offset); + Vector2 cpos = Point2(w + sb->get_margin(SIDE_LEFT) + close_h_offset - close->get_width(), -close->get_height() + close_offset); draw_texture(close, cpos, close_color); close_rect.position = cpos; close_rect.size = close->get_size(); @@ -411,7 +414,7 @@ void GraphNode::_notification(int p_what) { continue; } const Slot &s = slot_info[E.key]; - //left + // Left port. if (s.enable_left) { Ref<Texture2D> p = port; if (s.custom_slot_left.is_valid()) { @@ -419,6 +422,7 @@ void GraphNode::_notification(int p_what) { } p->draw(get_canvas_item(), icofs + Point2(edgeofs, cache_y[E.key]), s.color_left); } + // Right port. if (s.enable_right) { Ref<Texture2D> p = port; if (s.custom_slot_right.is_valid()) { @@ -426,6 +430,15 @@ void GraphNode::_notification(int p_what) { } p->draw(get_canvas_item(), icofs + Point2(get_size().x - edgeofs, cache_y[E.key]), s.color_right); } + + // Draw slot stylebox. + if (s.draw_stylebox) { + Control *c = Object::cast_to<Control>(get_child(E.key)); + Rect2 c_rect = c->get_rect(); + c_rect.position.x = sb->get_margin(SIDE_LEFT); + c_rect.size.width = w; + draw_style_box(sb_slot, c_rect); + } } if (resizable) { @@ -482,7 +495,7 @@ void GraphNode::_validate_property(PropertyInfo &property) const { } #endif -void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left, const Ref<Texture2D> &p_custom_right) { +void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left, const Ref<Texture2D> &p_custom_right, bool p_draw_stylebox) { ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set slot with p_idx (%d) lesser than zero.", p_idx)); if (!p_enable_left && p_type_left == 0 && p_color_left == Color(1, 1, 1, 1) && @@ -501,6 +514,7 @@ void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const C s.color_right = p_color_right; s.custom_slot_left = p_custom_left; s.custom_slot_right = p_custom_right; + s.draw_stylebox = p_draw_stylebox; slot_info[p_idx] = s; update(); connpos_dirty = true; @@ -622,16 +636,39 @@ Color GraphNode::get_slot_color_right(int p_idx) const { return slot_info[p_idx].color_right; } +bool GraphNode::is_slot_draw_stylebox(int p_idx) const { + if (!slot_info.has(p_idx)) { + return false; + } + return slot_info[p_idx].draw_stylebox; +} + +void GraphNode::set_slot_draw_stylebox(int p_idx, bool p_enable) { + ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set draw_stylebox for the slot with p_idx (%d) lesser than zero.", p_idx)); + + slot_info[p_idx].draw_stylebox = p_enable; + update(); + connpos_dirty = true; + + emit_signal(SNAME("slot_updated"), p_idx); +} + Size2 GraphNode::get_minimum_size() const { - int sep = get_theme_constant(SNAME("separation")); Ref<StyleBox> sb = get_theme_stylebox(SNAME("frame")); + Ref<StyleBox> sb_slot = get_theme_stylebox(SNAME("slot")); + + int sep = get_theme_constant(SNAME("separation")); + int title_h_offset = get_theme_constant(SNAME("title_h_offset")); + bool first = true; Size2 minsize; - minsize.x = title_buf->get_size().x; + minsize.x = title_buf->get_size().x + title_h_offset; if (show_close) { + int close_h_offset = get_theme_constant(SNAME("close_h_offset")); Ref<Texture2D> close = get_theme_icon(SNAME("close")); - minsize.x += sep + close->get_width(); + //TODO: Remove this magic number after GraphNode rework. + minsize.x += 12 + close->get_width() + close_h_offset; } for (int i = 0; i < get_child_count(); i++) { @@ -644,6 +681,9 @@ Size2 GraphNode::get_minimum_size() const { } Size2i size = c->get_combined_minimum_size(); + if (slot_info.has(i)) { + size += slot_info[i].draw_stylebox ? sb_slot->get_minimum_size() : Size2(); + } minsize.y += size.y; minsize.x = MAX(minsize.x, size.x); @@ -989,7 +1029,7 @@ void GraphNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_language", "language"), &GraphNode::set_language); ClassDB::bind_method(D_METHOD("get_language"), &GraphNode::get_language); - ClassDB::bind_method(D_METHOD("set_slot", "idx", "enable_left", "type_left", "color_left", "enable_right", "type_right", "color_right", "custom_left", "custom_right"), &GraphNode::set_slot, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>())); + ClassDB::bind_method(D_METHOD("set_slot", "idx", "enable_left", "type_left", "color_left", "enable_right", "type_right", "color_right", "custom_left", "custom_right", "enable"), &GraphNode::set_slot, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()), DEFVAL(true)); ClassDB::bind_method(D_METHOD("clear_slot", "idx"), &GraphNode::clear_slot); ClassDB::bind_method(D_METHOD("clear_all_slots"), &GraphNode::clear_all_slots); @@ -1011,6 +1051,9 @@ void GraphNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_slot_color_right", "idx", "color_right"), &GraphNode::set_slot_color_right); ClassDB::bind_method(D_METHOD("get_slot_color_right", "idx"), &GraphNode::get_slot_color_right); + ClassDB::bind_method(D_METHOD("is_slot_draw_stylebox", "idx"), &GraphNode::is_slot_draw_stylebox); + ClassDB::bind_method(D_METHOD("set_slot_draw_stylebox", "idx", "draw_stylebox"), &GraphNode::set_slot_draw_stylebox); + ClassDB::bind_method(D_METHOD("set_position_offset", "offset"), &GraphNode::set_position_offset); ClassDB::bind_method(D_METHOD("get_position_offset"), &GraphNode::get_position_offset); diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index 7eb5f27cff..9481a7452d 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -54,6 +54,7 @@ private: Color color_right = Color(1, 1, 1, 1); Ref<Texture2D> custom_slot_left; Ref<Texture2D> custom_slot_right; + bool draw_stylebox = true; }; String title; @@ -85,7 +86,7 @@ private: Vector<ConnCache> conn_input_cache; Vector<ConnCache> conn_output_cache; - Map<int, Slot> slot_info; + HashMap<int, Slot> slot_info; bool connpos_dirty = true; @@ -115,7 +116,7 @@ protected: public: bool has_point(const Point2 &p_point) const override; - void set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left = Ref<Texture2D>(), const Ref<Texture2D> &p_custom_right = Ref<Texture2D>()); + void set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left = Ref<Texture2D>(), const Ref<Texture2D> &p_custom_right = Ref<Texture2D>(), bool p_draw_stylebox = true); void clear_slot(int p_idx); void clear_all_slots(); @@ -137,6 +138,9 @@ public: void set_slot_color_right(int p_idx, const Color &p_color_right); Color get_slot_color_right(int p_idx) const; + bool is_slot_draw_stylebox(int p_idx) const; + void set_slot_draw_stylebox(int p_idx, bool p_enable); + void set_title(const String &p_title); String get_title() const; @@ -185,7 +189,9 @@ public: virtual Vector<int> get_allowed_size_flags_horizontal() const override; virtual Vector<int> get_allowed_size_flags_vertical() const override; - bool is_resizing() const { return resizing; } + bool is_resizing() const { + return resizing; + } GraphNode(); }; diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index b58bb4d74a..ec33018da0 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -33,10 +33,10 @@ void GridContainer::_notification(int p_what) { switch (p_what) { case NOTIFICATION_SORT_CHILDREN: { - Map<int, int> col_minw; // Max of min_width of all controls in each col (indexed by col). - Map<int, int> row_minh; // Max of min_height of all controls in each row (indexed by row). - Set<int> col_expanded; // Columns which have the SIZE_EXPAND flag set. - Set<int> row_expanded; // Rows which have the SIZE_EXPAND flag set. + HashMap<int, int> col_minw; // Max of min_width of all controls in each col (indexed by col). + HashMap<int, int> row_minh; // Max of min_height of all controls in each row (indexed by row). + RBSet<int> col_expanded; // Columns which have the SIZE_EXPAND flag set. + RBSet<int> row_expanded; // Rows which have the SIZE_EXPAND flag set. int hsep = get_theme_constant(SNAME("h_separation")); int vsep = get_theme_constant(SNAME("v_separation")); @@ -104,7 +104,7 @@ void GridContainer::_notification(int p_what) { // Check if all minwidth constraints are OK if we use the remaining space. can_fit = true; int max_index = col_expanded.front()->get(); - for (Set<int>::Element *E = col_expanded.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = col_expanded.front(); E; E = E->next()) { if (col_minw[E->get()] > col_minw[max_index]) { max_index = E->get(); } @@ -125,7 +125,7 @@ void GridContainer::_notification(int p_what) { // Check if all minheight constraints are OK if we use the remaining space. can_fit = true; int max_index = row_expanded.front()->get(); - for (Set<int>::Element *E = row_expanded.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = row_expanded.front(); E; E = E->next()) { if (row_minh[E->get()] > row_minh[max_index]) { max_index = E->get(); } @@ -142,13 +142,47 @@ void GridContainer::_notification(int p_what) { } // Finally, fit the nodes. - int col_expand = col_expanded.size() > 0 ? remaining_space.width / col_expanded.size() : 0; - int row_expand = row_expanded.size() > 0 ? remaining_space.height / row_expanded.size() : 0; + int col_remaining_pixel = 0; + int col_expand = 0; + if (col_expanded.size() > 0) { + col_expand = remaining_space.width / col_expanded.size(); + col_remaining_pixel = remaining_space.width - col_expanded.size() * col_expand; + } + + int row_remaining_pixel = 0; + int row_expand = 0; + if (row_expanded.size() > 0) { + row_expand = remaining_space.height / row_expanded.size(); + row_remaining_pixel = remaining_space.height - row_expanded.size() * row_expand; + } + bool rtl = is_layout_rtl(); int col_ofs = 0; int row_ofs = 0; + // Calculate the index of rows and columns that receive the remaining pixel. + int col_remaining_pixel_index = 0; + for (int i = 0; i < max_col; i++) { + if (col_remaining_pixel == 0) { + break; + } + if (col_expanded.has(i)) { + col_remaining_pixel_index = i + 1; + col_remaining_pixel--; + } + } + int row_remaining_pixel_index = 0; + for (int i = 0; i < max_row; i++) { + if (row_remaining_pixel == 0) { + break; + } + if (row_expanded.has(i)) { + row_remaining_pixel_index = i + 1; + row_remaining_pixel--; + } + } + valid_controls_index = 0; for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); @@ -167,17 +201,30 @@ void GridContainer::_notification(int p_what) { } if (row > 0) { row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + vsep; + + if (row_expanded.has(row - 1) && row - 1 < row_remaining_pixel_index) { + // Apply the remaining pixel of the previous row. + row_ofs++; + } } } + Size2 s(col_expanded.has(col) ? col_expand : col_minw[col], row_expanded.has(row) ? row_expand : row_minh[row]); + + // Add the remaining pixel to the expanding columns and rows, starting from left and top. + if (col_expanded.has(col) && col < col_remaining_pixel_index) { + s.x++; + } + if (row_expanded.has(row) && row < row_remaining_pixel_index) { + s.y++; + } + if (rtl) { - Size2 s(col_expanded.has(col) ? col_expand : col_minw[col], row_expanded.has(row) ? row_expand : row_minh[row]); Point2 p(col_ofs - s.width, row_ofs); fit_child_in_rect(c, Rect2(p, s)); col_ofs -= s.width + hsep; } else { Point2 p(col_ofs, row_ofs); - Size2 s(col_expanded.has(col) ? col_expand : col_minw[col], row_expanded.has(row) ? row_expand : row_minh[row]); fit_child_in_rect(c, Rect2(p, s)); col_ofs += s.width + hsep; } @@ -214,8 +261,8 @@ void GridContainer::_bind_methods() { } Size2 GridContainer::get_minimum_size() const { - Map<int, int> col_minw; - Map<int, int> row_minh; + HashMap<int, int> col_minw; + HashMap<int, int> row_minh; int hsep = get_theme_constant(SNAME("h_separation")); int vsep = get_theme_constant(SNAME("v_separation")); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index e5b58a7cc8..73188d6602 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -406,9 +406,45 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { if (k.is_valid()) { if (!k->is_pressed()) { + if (alt_start && k->get_keycode() == Key::ALT) { + alt_start = false; + if ((alt_code > 0x31 && alt_code < 0xd800) || (alt_code > 0xdfff && alt_code <= 0x10ffff)) { + char32_t ucodestr[2] = { (char32_t)alt_code, 0 }; + insert_text_at_caret(ucodestr); + } + accept_event(); + return; + } return; } + // Alt+ Unicode input: + if (k->is_alt_pressed()) { + if (!alt_start) { + if (k->get_keycode() == Key::KP_ADD) { + alt_start = true; + alt_code = 0; + accept_event(); + return; + } + } else { + if (k->get_keycode() >= Key::KEY_0 && k->get_keycode() <= Key::KEY_9) { + alt_code = alt_code << 4; + alt_code += (uint32_t)(k->get_keycode() - Key::KEY_0); + } + if (k->get_keycode() >= Key::KP_0 && k->get_keycode() <= Key::KP_9) { + alt_code = alt_code << 4; + alt_code += (uint32_t)(k->get_keycode() - Key::KP_0); + } + if (k->get_keycode() >= Key::A && k->get_keycode() <= Key::F) { + alt_code = alt_code << 4; + alt_code += (uint32_t)(k->get_keycode() - Key::A) + 10; + } + accept_event(); + return; + } + } + if (context_menu_enabled) { if (k->is_action("ui_menu", true)) { _ensure_menu(); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 50aa2f4460..0fb178fca4 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -77,6 +77,9 @@ private: bool pass = false; bool text_changed_dirty = false; + bool alt_start = false; + uint32_t alt_code = 0; + String undo_text; String text; String placeholder; diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 1feee017c2..316fee53fe 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -187,7 +187,7 @@ void MenuButton::_get_property_list(List<PropertyInfo> *p_list) const { pi.usage &= ~(popup->get_item_icon(i).is_null() ? PROPERTY_USAGE_STORAGE : 0); p_list->push_back(pi); - pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/checkable", i), PROPERTY_HINT_ENUM, "No,As checkbox,As radio button"); + pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/checkable", i), PROPERTY_HINT_ENUM, "No,As Checkbox,As Radio Button"); pi.usage &= ~(!popup->is_item_checkable(i) ? PROPERTY_USAGE_STORAGE : 0); p_list->push_back(pi); diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index b9e3e7814e..6532fc5934 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -108,11 +108,25 @@ void Popup::_close_pressed() { _deinitialize_visible_parents(); - call_deferred(SNAME("hide")); + // Hide after returning to process events, but only if we don't + // get popped up in the interim. + call_deferred(SNAME("_popup_conditional_hide")); +} + +void Popup::_post_popup() { + Window::_post_popup(); + popped_up = true; +} + +void Popup::_popup_conditional_hide() { + if (!popped_up) { + hide(); + } } void Popup::_bind_methods() { ADD_SIGNAL(MethodInfo("popup_hide")); + ClassDB::bind_method(D_METHOD("_popup_conditional_hide"), &Popup::_popup_conditional_hide); } Rect2i Popup::_popup_adjust_rect() const { diff --git a/scene/gui/popup.h b/scene/gui/popup.h index 6211af4d20..27f46d4a97 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -57,6 +57,10 @@ protected: void _notification(int p_what); static void _bind_methods(); + void _popup_conditional_hide(); + + virtual void _post_popup() override; + public: Popup(); ~Popup(); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 98d76875cb..12587b7e73 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -117,7 +117,7 @@ class PopupMenu : public Popup { bool hide_on_multistate_item_selection = false; Vector2 moved; - Map<Ref<Shortcut>, int> shortcut_refcount; + HashMap<Ref<Shortcut>, int> shortcut_refcount; void _ref_shortcut(Ref<Shortcut> p_sc); void _unref_shortcut(Ref<Shortcut> p_sc); diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index 50ffb3ca67..f36682942f 100644 --- a/scene/gui/progress_bar.cpp +++ b/scene/gui/progress_bar.cpp @@ -62,15 +62,42 @@ void ProgressBar::_notification(int p_what) { Color font_color = get_theme_color(SNAME("font_color")); draw_style_box(bg, Rect2(Point2(), get_size())); + float r = get_as_ratio(); - int mp = fg->get_minimum_size().width; - int p = r * (get_size().width - mp); - if (p > 0) { - if (is_layout_rtl()) { - draw_style_box(fg, Rect2(Point2(p, 0), Size2(fg->get_minimum_size().width, get_size().height))); - } else { - draw_style_box(fg, Rect2(Point2(0, 0), Size2(p + fg->get_minimum_size().width, get_size().height))); - } + + switch (mode) { + case FILL_BEGIN_TO_END: + case FILL_END_TO_BEGIN: { + int mp = fg->get_minimum_size().width; + int p = round(r * (get_size().width - mp)); + // We want FILL_BEGIN_TO_END to map to right to left when UI layout is RTL, + // and left to right otherwise. And likewise for FILL_END_TO_BEGIN. + bool right_to_left = is_layout_rtl() ? (mode == FILL_BEGIN_TO_END) : (mode == FILL_END_TO_BEGIN); + if (p > 0) { + if (right_to_left) { + int p_remaining = round((1.0 - r) * (get_size().width - mp)); + draw_style_box(fg, Rect2(Point2(p_remaining, 0), Size2(p + fg->get_minimum_size().width, get_size().height))); + } else { + draw_style_box(fg, Rect2(Point2(0, 0), Size2(p + fg->get_minimum_size().width, get_size().height))); + } + } + } break; + case FILL_TOP_TO_BOTTOM: + case FILL_BOTTOM_TO_TOP: { + int mp = fg->get_minimum_size().height; + int p = round(r * (get_size().height - mp)); + + if (p > 0) { + if (mode == FILL_TOP_TO_BOTTOM) { + draw_style_box(fg, Rect2(Point2(0, 0), Size2(get_size().width, p + fg->get_minimum_size().height))); + } else { + int p_remaining = round((1.0 - r) * (get_size().height - mp)); + draw_style_box(fg, Rect2(Point2(0, p_remaining), Size2(get_size().width, p + fg->get_minimum_size().height))); + } + } + } break; + case FILL_MODE_MAX: + break; } if (percent_visible) { @@ -88,6 +115,16 @@ void ProgressBar::_notification(int p_what) { } } +void ProgressBar::set_fill_mode(int p_fill) { + ERR_FAIL_INDEX(p_fill, FILL_MODE_MAX); + mode = (FillMode)p_fill; + update(); +} + +int ProgressBar::get_fill_mode() { + return mode; +} + void ProgressBar::set_percent_visible(bool p_visible) { percent_visible = p_visible; update(); @@ -98,10 +135,18 @@ bool ProgressBar::is_percent_visible() const { } void ProgressBar::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_fill_mode", "mode"), &ProgressBar::set_fill_mode); + ClassDB::bind_method(D_METHOD("get_fill_mode"), &ProgressBar::get_fill_mode); ClassDB::bind_method(D_METHOD("set_percent_visible", "visible"), &ProgressBar::set_percent_visible); ClassDB::bind_method(D_METHOD("is_percent_visible"), &ProgressBar::is_percent_visible); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fill_mode", PROPERTY_HINT_ENUM, "Begin to End,End to Begin,Top to Bottom,Bottom to Top"), "set_fill_mode", "get_fill_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "percent_visible"), "set_percent_visible", "is_percent_visible"); + + BIND_ENUM_CONSTANT(FILL_BEGIN_TO_END); + BIND_ENUM_CONSTANT(FILL_END_TO_BEGIN); + BIND_ENUM_CONSTANT(FILL_TOP_TO_BOTTOM); + BIND_ENUM_CONSTANT(FILL_BOTTOM_TO_TOP); } ProgressBar::ProgressBar() { diff --git a/scene/gui/progress_bar.h b/scene/gui/progress_bar.h index 2d89163f78..5ba21ad7d5 100644 --- a/scene/gui/progress_bar.h +++ b/scene/gui/progress_bar.h @@ -43,11 +43,27 @@ protected: static void _bind_methods(); public: + enum FillMode { + FILL_BEGIN_TO_END, + FILL_END_TO_BEGIN, + FILL_TOP_TO_BOTTOM, + FILL_BOTTOM_TO_TOP, + FILL_MODE_MAX + }; + + void set_fill_mode(int p_fill); + int get_fill_mode(); + void set_percent_visible(bool p_visible); bool is_percent_visible() const; Size2 get_minimum_size() const override; ProgressBar(); + +private: + FillMode mode = FILL_BEGIN_TO_END; }; +VARIANT_ENUM_CAST(ProgressBar::FillMode); + #endif // PROGRESS_BAR_H diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index 8e66826e9d..73f19a8eda 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -50,7 +50,7 @@ void Range::_value_changed_notify() { } void Range::Shared::emit_value_changed() { - for (Set<Range *>::Element *E = owners.front(); E; E = E->next()) { + for (RBSet<Range *>::Element *E = owners.front(); E; E = E->next()) { Range *r = E->get(); if (!r->is_inside_tree()) { continue; @@ -70,7 +70,7 @@ void Range::_validate_values() { } void Range::Shared::emit_changed(const char *p_what) { - for (Set<Range *>::Element *E = owners.front(); E; E = E->next()) { + for (RBSet<Range *>::Element *E = owners.front(); E; E = E->next()) { Range *r = E->get(); if (!r->is_inside_tree()) { continue; diff --git a/scene/gui/range.h b/scene/gui/range.h index 46b0d39202..a59bfa9677 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -45,7 +45,7 @@ class Range : public Control { bool exp_ratio = false; bool allow_greater = false; bool allow_lesser = false; - Set<Range *> owners; + RBSet<Range *> owners; void emit_value_changed(); void emit_changed(const char *p_what = ""); }; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 7ed28ac3c8..fa0c2ce12c 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -3177,7 +3177,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { // Find optional parameters. String bbcode_name; - typedef Map<String, String> OptionMap; + typedef HashMap<String, String> OptionMap; OptionMap bbcode_options; if (!split_tag_block.is_empty()) { bbcode_name = split_tag_block[0]; @@ -3620,9 +3620,9 @@ void RichTextLabel::append_text(const String &p_bbcode) { Ref<Texture2D> texture = ResourceLoader::load(image, "Texture2D"); if (texture.is_valid()) { Color color = Color(1.0, 1.0, 1.0); - OptionMap::Element *color_option = bbcode_options.find("color"); + OptionMap::Iterator color_option = bbcode_options.find("color"); if (color_option) { - color = Color::from_string(color_option->value(), color); + color = Color::from_string(color_option->value, color); } int width = 0; @@ -3636,14 +3636,14 @@ void RichTextLabel::append_text(const String &p_bbcode) { height = bbcode_value.substr(sep + 1).to_int(); } } else { - OptionMap::Element *width_option = bbcode_options.find("width"); + OptionMap::Iterator width_option = bbcode_options.find("width"); if (width_option) { - width = width_option->value().to_int(); + width = width_option->value.to_int(); } - OptionMap::Element *height_option = bbcode_options.find("height"); + OptionMap::Iterator height_option = bbcode_options.find("height"); if (height_option) { - height = height_option->value().to_int(); + height = height_option->value.to_int(); } } @@ -3729,15 +3729,15 @@ void RichTextLabel::append_text(const String &p_bbcode) { } else if (bbcode_name == "fade") { int start_index = 0; - OptionMap::Element *start_option = bbcode_options.find("start"); + OptionMap::Iterator start_option = bbcode_options.find("start"); if (start_option) { - start_index = start_option->value().to_int(); + start_index = start_option->value.to_int(); } int length = 10; - OptionMap::Element *length_option = bbcode_options.find("length"); + OptionMap::Iterator length_option = bbcode_options.find("length"); if (length_option) { - length = length_option->value().to_int(); + length = length_option->value.to_int(); } push_fade(start_index, length); @@ -3745,15 +3745,15 @@ void RichTextLabel::append_text(const String &p_bbcode) { tag_stack.push_front("fade"); } else if (bbcode_name == "shake") { int strength = 5; - OptionMap::Element *strength_option = bbcode_options.find("level"); + OptionMap::Iterator strength_option = bbcode_options.find("level"); if (strength_option) { - strength = strength_option->value().to_int(); + strength = strength_option->value.to_int(); } float rate = 20.0f; - OptionMap::Element *rate_option = bbcode_options.find("rate"); + OptionMap::Iterator rate_option = bbcode_options.find("rate"); if (rate_option) { - rate = rate_option->value().to_float(); + rate = rate_option->value.to_float(); } push_shake(strength, rate); @@ -3762,15 +3762,15 @@ void RichTextLabel::append_text(const String &p_bbcode) { set_process_internal(true); } else if (bbcode_name == "wave") { float amplitude = 20.0f; - OptionMap::Element *amplitude_option = bbcode_options.find("amp"); + OptionMap::Iterator amplitude_option = bbcode_options.find("amp"); if (amplitude_option) { - amplitude = amplitude_option->value().to_float(); + amplitude = amplitude_option->value.to_float(); } float period = 5.0f; - OptionMap::Element *period_option = bbcode_options.find("freq"); + OptionMap::Iterator period_option = bbcode_options.find("freq"); if (period_option) { - period = period_option->value().to_float(); + period = period_option->value.to_float(); } push_wave(period, amplitude); @@ -3779,15 +3779,15 @@ void RichTextLabel::append_text(const String &p_bbcode) { set_process_internal(true); } else if (bbcode_name == "tornado") { float radius = 10.0f; - OptionMap::Element *radius_option = bbcode_options.find("radius"); + OptionMap::Iterator radius_option = bbcode_options.find("radius"); if (radius_option) { - radius = radius_option->value().to_float(); + radius = radius_option->value.to_float(); } float frequency = 1.0f; - OptionMap::Element *frequency_option = bbcode_options.find("freq"); + OptionMap::Iterator frequency_option = bbcode_options.find("freq"); if (frequency_option) { - frequency = frequency_option->value().to_float(); + frequency = frequency_option->value.to_float(); } push_tornado(frequency, radius); @@ -3796,21 +3796,21 @@ void RichTextLabel::append_text(const String &p_bbcode) { set_process_internal(true); } else if (bbcode_name == "rainbow") { float saturation = 0.8f; - OptionMap::Element *saturation_option = bbcode_options.find("sat"); + OptionMap::Iterator saturation_option = bbcode_options.find("sat"); if (saturation_option) { - saturation = saturation_option->value().to_float(); + saturation = saturation_option->value.to_float(); } float value = 0.8f; - OptionMap::Element *value_option = bbcode_options.find("val"); + OptionMap::Iterator value_option = bbcode_options.find("val"); if (value_option) { - value = value_option->value().to_float(); + value = value_option->value.to_float(); } float frequency = 1.0f; - OptionMap::Element *frequency_option = bbcode_options.find("freq"); + OptionMap::Iterator frequency_option = bbcode_options.find("freq"); if (frequency_option) { - frequency = frequency_option->value().to_float(); + frequency = frequency_option->value.to_float(); } push_rainbow(saturation, value, frequency); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 1a439a5c1d..315ffbd419 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1557,6 +1557,47 @@ void TextEdit::unhandled_key_input(const Ref<InputEvent> &p_event) { } } +bool TextEdit::alt_input(const Ref<InputEvent> &p_gui_input) { + Ref<InputEventKey> k = p_gui_input; + if (k.is_valid()) { + if (!k->is_pressed()) { + if (alt_start && k->get_keycode() == Key::ALT) { + alt_start = false; + if ((alt_code > 0x31 && alt_code < 0xd800) || (alt_code > 0xdfff && alt_code <= 0x10ffff)) { + handle_unicode_input(alt_code); + } + return true; + } + return false; + } + + if (k->is_alt_pressed()) { + if (!alt_start) { + if (k->get_keycode() == Key::KP_ADD) { + alt_start = true; + alt_code = 0; + return true; + } + } else { + if (k->get_keycode() >= Key::KEY_0 && k->get_keycode() <= Key::KEY_9) { + alt_code = alt_code << 4; + alt_code += (uint32_t)(k->get_keycode() - Key::KEY_0); + } + if (k->get_keycode() >= Key::KP_0 && k->get_keycode() <= Key::KP_9) { + alt_code = alt_code << 4; + alt_code += (uint32_t)(k->get_keycode() - Key::KP_0); + } + if (k->get_keycode() >= Key::A && k->get_keycode() <= Key::F) { + alt_code = alt_code << 4; + alt_code += (uint32_t)(k->get_keycode() - Key::A) + 10; + } + return true; + } + } + } + return false; +} + void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { ERR_FAIL_COND(p_gui_input.is_null()); @@ -1865,6 +1906,10 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { Ref<InputEventKey> k = p_gui_input; if (k.is_valid()) { + if (alt_input(p_gui_input)) { + accept_event(); + return; + } if (!k->is_pressed()) { return; } @@ -2388,7 +2433,7 @@ void TextEdit::_move_caret_page_down(bool p_select) { } void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) { - if (!editable || (caret.column == 0 && caret.line == 0)) { + if (!editable || (caret.column == 0 && caret.line == 0 && !has_selection())) { return; } diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index a0ae9631f9..993203bee6 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -247,6 +247,9 @@ private: bool setting_text = false; + bool alt_start = false; + uint32_t alt_code = 0; + // Text properties. String ime_text = ""; Point2 ime_selection; @@ -353,7 +356,7 @@ private: Vector<int> last_visible_chars; }; - Map<int, LineDrawingCache> line_drawing_cache; + HashMap<int, LineDrawingCache> line_drawing_cache; int _get_char_pos_for_line(int p_px, int p_line, int p_wrap_index = 0) const; @@ -508,7 +511,6 @@ private: /* Syntax highlighting. */ Ref<SyntaxHighlighter> syntax_highlighter; - Map<int, Dictionary> syntax_highlighting_cache; Dictionary _get_line_syntax_highlighting(int p_line); @@ -625,6 +627,7 @@ public: /* General overrides. */ virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; virtual void gui_input(const Ref<InputEvent> &p_gui_input) override; + bool alt_input(const Ref<InputEvent> &p_gui_input); virtual Size2 get_minimum_size() const override; virtual bool is_text_field() const override; virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 89807dbe95..0ca9a66e08 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1754,19 +1754,16 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) { Ref<Texture2D> b = p_item->cells[i].buttons[j].texture; Size2 s = b->get_size() + cache.button_pressed->get_minimum_size(); - if (s.height < label_h) { - s.height = label_h; - } Point2i o = Point2i(ofs + w - s.width, p_pos.y) - cache.offset + p_draw_ofs; if (cache.click_type == Cache::CLICK_BUTTON && cache.click_item == p_item && cache.click_column == i && cache.click_index == j && !p_item->cells[i].buttons[j].disabled) { - //being pressed + // Being pressed. Point2 od = o; if (rtl) { od.x = get_size().width - od.x - s.x; } - cache.button_pressed->draw(get_canvas_item(), Rect2(od, s)); + cache.button_pressed->draw(get_canvas_item(), Rect2(od.x, od.y, s.width, MAX(s.height, label_h))); } o.y += (label_h - s.height) / 2; diff --git a/scene/main/missing_node.cpp b/scene/main/missing_node.cpp index 6daa9dec6b..395fdad9e4 100644 --- a/scene/main/missing_node.cpp +++ b/scene/main/missing_node.cpp @@ -53,8 +53,8 @@ bool MissingNode::_get(const StringName &p_name, Variant &r_ret) const { } void MissingNode::_get_property_list(List<PropertyInfo> *p_list) const { - for (OrderedHashMap<StringName, Variant>::ConstElement E = properties.front(); E; E = E.next()) { - p_list->push_back(PropertyInfo(E.value().get_type(), E.key())); + for (const KeyValue<StringName, Variant> &E : properties) { + p_list->push_back(PropertyInfo(E.value.get_type(), E.key)); } } diff --git a/scene/main/missing_node.h b/scene/main/missing_node.h index b0f9492456..d200fbb47f 100644 --- a/scene/main/missing_node.h +++ b/scene/main/missing_node.h @@ -36,7 +36,7 @@ class MissingNode : public Node { GDCLASS(MissingNode, Node) - OrderedHashMap<StringName, Variant> properties; + HashMap<StringName, Variant> properties; String original_class; bool recording_properties = false; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 8961b5ba54..0c1a62c667 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1637,7 +1637,7 @@ Node *Node::find_common_parent_with(const Node *p_node) const { return const_cast<Node *>(p_node); } - Set<const Node *> visited; + RBSet<const Node *> visited; const Node *n = this; @@ -1669,7 +1669,7 @@ NodePath Node::get_path_to(const Node *p_node) const { return NodePath("."); } - Set<const Node *> visited; + RBSet<const Node *> visited; const Node *n = this; @@ -1763,15 +1763,15 @@ void Node::add_to_group(const StringName &p_identifier, bool p_persistent) { void Node::remove_from_group(const StringName &p_identifier) { ERR_FAIL_COND(!data.grouped.has(p_identifier)); - Map<StringName, GroupData>::Element *E = data.grouped.find(p_identifier); + HashMap<StringName, GroupData>::Iterator E = data.grouped.find(p_identifier); ERR_FAIL_COND(!E); if (data.tree) { - data.tree->remove_from_group(E->key(), this); + data.tree->remove_from_group(E->key, this); } - data.grouped.erase(E); + data.grouped.remove(E); } Array Node::_get_groups() const { @@ -2042,7 +2042,7 @@ StringName Node::get_property_store_alias(const StringName &p_property) const { } #endif -void Node::get_storable_properties(Set<StringName> &r_storable_properties) const { +void Node::get_storable_properties(RBSet<StringName> &r_storable_properties) const { List<PropertyInfo> pi; get_property_list(&pi); for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) { @@ -2088,7 +2088,7 @@ bool Node::get_scene_instance_load_placeholder() const { return data.use_placeholder; } -Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const { +Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) const { Node *node = nullptr; bool instantiated = false; @@ -2280,11 +2280,11 @@ Node *Node::duplicate(int p_flags) const { } #ifdef TOOLS_ENABLED -Node *Node::duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const { - return duplicate_from_editor(r_duplimap, Map<Ref<Resource>, Ref<Resource>>()); +Node *Node::duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap) const { + return duplicate_from_editor(r_duplimap, HashMap<Ref<Resource>, Ref<Resource>>()); } -Node *Node::duplicate_from_editor(Map<const Node *, Node *> &r_duplimap, const Map<Ref<Resource>, Ref<Resource>> &p_resource_remap) const { +Node *Node::duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const { Node *dupe = _duplicate(DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANCING | DUPLICATE_FROM_EDITOR, &r_duplimap); // This is used by SceneTreeDock's paste functionality. When pasting to foreign scene, resources are duplicated. @@ -2300,7 +2300,7 @@ Node *Node::duplicate_from_editor(Map<const Node *, Node *> &r_duplimap, const M return dupe; } -void Node::remap_node_resources(Node *p_node, const Map<Ref<Resource>, Ref<Resource>> &p_resource_remap) const { +void Node::remap_node_resources(Node *p_node, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const { List<PropertyInfo> props; p_node->get_property_list(&props); @@ -2326,7 +2326,7 @@ void Node::remap_node_resources(Node *p_node, const Map<Ref<Resource>, Ref<Resou } } -void Node::remap_nested_resources(Ref<Resource> p_resource, const Map<Ref<Resource>, Ref<Resource>> &p_resource_remap) const { +void Node::remap_nested_resources(Ref<Resource> p_resource, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const { List<PropertyInfo> props; p_resource->get_property_list(&props); diff --git a/scene/main/node.h b/scene/main/node.h index 72f340bbc3..8505d2618f 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -32,7 +32,7 @@ #define NODE_H #include "core/string/node_path.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/variant/typed_array.h" #include "scene/main/scene_tree.h" @@ -119,7 +119,7 @@ private: Viewport *viewport = nullptr; - Map<StringName, GroupData> grouped; + HashMap<StringName, GroupData> grouped; List<Node *>::Element *OW = nullptr; // Owned element. List<Node *> owned; @@ -177,7 +177,7 @@ private: Array _get_node_and_resource(const NodePath &p_path); void _duplicate_signals(const Node *p_original, Node *p_copy) const; - Node *_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap = nullptr) const; + Node *_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap = nullptr) const; TypedArray<Node> _get_children(bool p_include_internal = true) const; Array _get_groups() const; @@ -378,7 +378,7 @@ public: bool is_property_pinned(const StringName &p_property) const; virtual StringName get_property_store_alias(const StringName &p_property) const; #endif - void get_storable_properties(Set<StringName> &r_storable_properties) const; + void get_storable_properties(RBSet<StringName> &r_storable_properties) const; virtual String to_string() override; @@ -420,10 +420,10 @@ public: Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const; #ifdef TOOLS_ENABLED - Node *duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const; - Node *duplicate_from_editor(Map<const Node *, Node *> &r_duplimap, const Map<Ref<Resource>, Ref<Resource>> &p_resource_remap) const; - void remap_node_resources(Node *p_node, const Map<Ref<Resource>, Ref<Resource>> &p_resource_remap) const; - void remap_nested_resources(Ref<Resource> p_resource, const Map<Ref<Resource>, Ref<Resource>> &p_resource_remap) const; + Node *duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap) const; + Node *duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const; + void remap_node_resources(Node *p_node, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const; + void remap_nested_resources(Ref<Resource> p_resource, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const; #endif // used by editors, to save what has changed only @@ -522,6 +522,6 @@ public: VARIANT_ENUM_CAST(Node::DuplicateFlags); -typedef Set<Node *, Node::Comparator> NodeSet; +typedef RBSet<Node *, Node::Comparator> NodeSet; #endif diff --git a/scene/main/resource_preloader.cpp b/scene/main/resource_preloader.cpp index 8fb7456335..b3595c6227 100644 --- a/scene/main/resource_preloader.cpp +++ b/scene/main/resource_preloader.cpp @@ -55,14 +55,14 @@ Array ResourcePreloader::_get_resources() const { arr.resize(resources.size()); names.resize(resources.size()); - Set<String> sorted_names; + RBSet<String> sorted_names; for (const KeyValue<StringName, Ref<Resource>> &E : resources) { sorted_names.insert(E.key); } int i = 0; - for (Set<String>::Element *E = sorted_names.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = sorted_names.front(); E; E = E->next()) { names.set(i, E->get()); arr[i] = resources[E->get()]; i++; @@ -123,8 +123,9 @@ Vector<String> ResourcePreloader::_get_resource_list() const { Vector<String> res; res.resize(resources.size()); int i = 0; - for (Map<StringName, Ref<Resource>>::Element *E = resources.front(); E; E = E->next(), i++) { - res.set(i, E->key()); + for (const KeyValue<StringName, Ref<Resource>> &E : resources) { + res.set(i, E.key); + i++; } return res; diff --git a/scene/main/resource_preloader.h b/scene/main/resource_preloader.h index 2df8b5cda7..fe59bc8ae3 100644 --- a/scene/main/resource_preloader.h +++ b/scene/main/resource_preloader.h @@ -36,7 +36,7 @@ class ResourcePreloader : public Node { GDCLASS(ResourcePreloader, Node); - Map<StringName, Ref<Resource>> resources; + HashMap<StringName, Ref<Resource>> resources; void _set_resources(const Array &p_data); Array _get_resources() const; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index a151d3cb33..231b672f63 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -129,32 +129,32 @@ void SceneTree::node_renamed(Node *p_node) { } SceneTree::Group *SceneTree::add_to_group(const StringName &p_group, Node *p_node) { - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); if (!E) { E = group_map.insert(p_group, Group()); } - ERR_FAIL_COND_V_MSG(E->get().nodes.has(p_node), &E->get(), "Already in group: " + p_group + "."); - E->get().nodes.push_back(p_node); - //E->get().last_tree_version=0; - E->get().changed = true; - return &E->get(); + ERR_FAIL_COND_V_MSG(E->value.nodes.has(p_node), &E->value, "Already in group: " + p_group + "."); + E->value.nodes.push_back(p_node); + //E->value.last_tree_version=0; + E->value.changed = true; + return &E->value; } void SceneTree::remove_from_group(const StringName &p_group, Node *p_node) { - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); ERR_FAIL_COND(!E); - E->get().nodes.erase(p_node); - if (E->get().nodes.is_empty()) { - group_map.erase(E); + E->value.nodes.erase(p_node); + if (E->value.nodes.is_empty()) { + group_map.remove(E); } } void SceneTree::make_group_changed(const StringName &p_group) { - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); if (E) { - E->get().changed = true; + E->value.changed = true; } } @@ -173,17 +173,17 @@ void SceneTree::_flush_ugc() { ugc_locked = true; while (unique_group_calls.size()) { - Map<UGCall, Vector<Variant>>::Element *E = unique_group_calls.front(); + HashMap<UGCall, Vector<Variant>, UGCall>::Iterator E = unique_group_calls.begin(); - const Variant **argptrs = (const Variant **)alloca(E->get().size() * sizeof(Variant *)); + const Variant **argptrs = (const Variant **)alloca(E->value.size() * sizeof(Variant *)); - for (int i = 0; i < E->get().size(); i++) { - argptrs[i] = &E->get()[i]; + for (int i = 0; i < E->value.size(); i++) { + argptrs[i] = &E->value[i]; } - call_group_flagsp(GROUP_CALL_REALTIME, E->key().group, E->key().call, argptrs, E->get().size()); + call_group_flagsp(GROUP_CALL_DEFAULT, E->key.group, E->key.call, argptrs, E->value.size()); - unique_group_calls.erase(E); + unique_group_calls.remove(E); } ugc_locked = false; @@ -211,16 +211,16 @@ void SceneTree::_update_group_order(Group &g, bool p_use_priority) { } void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, const Variant **p_args, int p_argcount) { - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); if (!E) { return; } - Group &g = E->get(); + Group &g = E->value; if (g.nodes.is_empty()) { return; } - if (p_call_flags & GROUP_CALL_UNIQUE && !(p_call_flags & GROUP_CALL_REALTIME)) { + if (p_call_flags & GROUP_CALL_UNIQUE && p_call_flags & GROUP_CALL_DEFERRED) { ERR_FAIL_COND(ugc_locked); UGCall ug; @@ -254,7 +254,7 @@ void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_gro continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { Callable::CallError ce; nodes[i]->callp(p_function, p_args, p_argcount, ce); } else { @@ -268,7 +268,7 @@ void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_gro continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { Callable::CallError ce; nodes[i]->callp(p_function, p_args, p_argcount, ce); } else { @@ -284,11 +284,11 @@ void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_gro } void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification) { - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); if (!E) { return; } - Group &g = E->get(); + Group &g = E->value; if (g.nodes.is_empty()) { return; } @@ -307,7 +307,7 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { nodes[i]->notification(p_notification); } else { MessageQueue::get_singleton()->push_notification(nodes[i], p_notification); @@ -320,7 +320,7 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { nodes[i]->notification(p_notification); } else { MessageQueue::get_singleton()->push_notification(nodes[i], p_notification); @@ -335,11 +335,11 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr } void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value) { - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); if (!E) { return; } - Group &g = E->get(); + Group &g = E->value; if (g.nodes.is_empty()) { return; } @@ -358,7 +358,7 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { nodes[i]->set(p_name, p_value); } else { MessageQueue::get_singleton()->push_set(nodes[i], p_name, p_value); @@ -371,7 +371,7 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group continue; } - if (p_call_flags & GROUP_CALL_REALTIME) { + if (!(p_call_flags & GROUP_CALL_DEFERRED)) { nodes[i]->set(p_name, p_value); } else { MessageQueue::get_singleton()->push_set(nodes[i], p_name, p_value); @@ -390,7 +390,7 @@ void SceneTree::notify_group(const StringName &p_group, int p_notification) { } void SceneTree::set_group(const StringName &p_group, const String &p_name, const Variant &p_value) { - set_group_flags(0, p_group, p_name, p_value); + set_group_flags(GROUP_CALL_DEFAULT, p_group, p_name, p_value); } void SceneTree::initialize() { @@ -413,7 +413,7 @@ bool SceneTree::physics_process(double p_time) { emit_signal(SNAME("physics_frame")); _notify_group_pause(SNAME("physics_process_internal"), Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS); - call_group_flags(GROUP_CALL_REALTIME, SNAME("_picking_viewports"), SNAME("_process_picking")); + call_group(SNAME("_picking_viewports"), SNAME("_process_picking")); _notify_group_pause(SNAME("physics_process"), Node::NOTIFICATION_PHYSICS_PROCESS); _flush_ugc(); MessageQueue::get_singleton()->flush(); //small little hack @@ -438,9 +438,8 @@ bool SceneTree::process(double p_time) { if (multiplayer_poll) { multiplayer->poll(); - const NodePath *rpath = nullptr; - while ((rpath = custom_multiplayers.next(rpath))) { - custom_multiplayers[*rpath]->poll(); + for (KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) { + E.value->poll(); } } @@ -819,11 +818,11 @@ bool SceneTree::is_paused() const { } void SceneTree::_notify_group_pause(const StringName &p_group, int p_notification) { - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); if (!E) { return; } - Group &g = E->get(); + Group &g = E->value; if (g.nodes.is_empty()) { return; } @@ -863,11 +862,11 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio } void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_call_type, const Ref<InputEvent> &p_input, Viewport *p_viewport) { - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); if (!E) { return; } - Group &g = E->get(); + Group &g = E->value; if (g.nodes.is_empty()) { return; } @@ -944,7 +943,7 @@ void SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable::Ca StringName group = *p_args[0]; StringName method = *p_args[1]; - call_group_flagsp(0, group, method, p_args + 2, p_argcount - 2); + call_group_flagsp(GROUP_CALL_DEFAULT, group, method, p_args + 2, p_argcount - 2); } int64_t SceneTree::get_frame() const { @@ -953,20 +952,20 @@ int64_t SceneTree::get_frame() const { Array SceneTree::_get_nodes_in_group(const StringName &p_group) { Array ret; - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); if (!E) { return ret; } - _update_group_order(E->get()); //update order just in case - int nc = E->get().nodes.size(); + _update_group_order(E->value); //update order just in case + int nc = E->value.nodes.size(); if (nc == 0) { return ret; } ret.resize(nc); - Node **ptr = E->get().nodes.ptrw(); + Node **ptr = E->value.nodes.ptrw(); for (int i = 0; i < nc; i++) { ret[i] = ptr[i]; } @@ -979,32 +978,32 @@ bool SceneTree::has_group(const StringName &p_identifier) const { } Node *SceneTree::get_first_node_in_group(const StringName &p_group) { - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); if (!E) { return nullptr; // No group. } - _update_group_order(E->get()); // Update order just in case. + _update_group_order(E->value); // Update order just in case. - if (E->get().nodes.is_empty()) { + if (E->value.nodes.is_empty()) { return nullptr; } - return E->get().nodes[0]; + return E->value.nodes[0]; } void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_list) { - Map<StringName, Group>::Element *E = group_map.find(p_group); + HashMap<StringName, Group>::Iterator E = group_map.find(p_group); if (!E) { return; } - _update_group_order(E->get()); //update order just in case - int nc = E->get().nodes.size(); + _update_group_order(E->value); //update order just in case + int nc = E->value.nodes.size(); if (nc == 0) { return; } - Node **ptr = E->get().nodes.ptrw(); + Node **ptr = E->value.nodes.ptrw(); for (int i = 0; i < nc; i++) { p_list->push_back(ptr[i]); } @@ -1137,9 +1136,8 @@ Array SceneTree::get_processed_tweens() { Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const { Ref<MultiplayerAPI> out = multiplayer; - const NodePath *spath = nullptr; - while ((spath = custom_multiplayers.next(spath))) { - const Vector<StringName> snames = (*spath).get_names(); + for (const KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) { + const Vector<StringName> snames = E.key.get_names(); const Vector<StringName> tnames = p_for_path.get_names(); if (tnames.size() < snames.size()) { continue; @@ -1154,7 +1152,7 @@ Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const } } if (valid) { - out = custom_multiplayers[*spath]; + out = E.value; break; } } @@ -1277,7 +1275,7 @@ void SceneTree::_bind_methods() { BIND_ENUM_CONSTANT(GROUP_CALL_DEFAULT); BIND_ENUM_CONSTANT(GROUP_CALL_REVERSE); - BIND_ENUM_CONSTANT(GROUP_CALL_REALTIME); + BIND_ENUM_CONSTANT(GROUP_CALL_DEFERRED); BIND_ENUM_CONSTANT(GROUP_CALL_UNIQUE); } diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 9d7757e0a3..bdcfd2d35a 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -102,7 +102,7 @@ private: bool paused = false; int root_lock = 0; - Map<StringName, Group> group_map; + HashMap<StringName, Group> group_map; bool _quit = false; bool initialized = false; @@ -121,16 +121,20 @@ private: StringName group; StringName call; + static uint32_t hash(const UGCall &p_val) { + return p_val.group.hash() ^ p_val.call.hash(); + } + bool operator==(const UGCall &p_with) const { return group == p_with.group && call == p_with.call; } bool operator<(const UGCall &p_with) const { return group == p_with.group ? call < p_with.call : group < p_with.group; } }; // Safety for when a node is deleted while a group is being called. int call_lock = 0; - Set<Node *> call_skip; // Skip erased nodes. + RBSet<Node *> call_skip; // Skip erased nodes. List<ObjectID> delete_queue; - Map<UGCall, Vector<Variant>> unique_group_calls; + HashMap<UGCall, Vector<Variant>, UGCall> unique_group_calls; bool ugc_locked = false; void _flush_ugc(); @@ -151,7 +155,6 @@ private: int collision_debug_contacts; void _change_scene(Node *p_to); - //void _call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,const Variant& p_arg1,const Variant& p_arg2); List<Ref<SceneTreeTimer>> timers; List<Ref<Tween>> tweens; @@ -225,7 +228,7 @@ public: enum GroupCallFlags { GROUP_CALL_DEFAULT = 0, GROUP_CALL_REVERSE = 1, - GROUP_CALL_REALTIME = 2, + GROUP_CALL_DEFERRED = 2, GROUP_CALL_UNIQUE = 4, }; @@ -235,17 +238,20 @@ public: void notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification); void set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value); + // `notify_group()` is immediate by default since Godot 4.0. void notify_group(const StringName &p_group, int p_notification); + // `set_group()` is immediate by default since Godot 4.0. void set_group(const StringName &p_group, const String &p_name, const Variant &p_value); template <typename... VarArgs> + // `call_group()` is immediate by default since Godot 4.0. void call_group(const StringName &p_group, const StringName &p_function, VarArgs... p_args) { Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. const Variant *argptrs[sizeof...(p_args) + 1]; for (uint32_t i = 0; i < sizeof...(p_args); i++) { argptrs[i] = &args[i]; } - call_group_flagsp(0, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); + call_group_flagsp(GROUP_CALL_DEFAULT, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); } template <typename... VarArgs> diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp index 7c689bd436..0049359cad 100644 --- a/scene/main/shader_globals_override.cpp +++ b/scene/main/shader_globals_override.cpp @@ -229,20 +229,19 @@ void ShaderGlobalsOverride::_activate() { active = true; add_to_group(SceneStringNames::get_singleton()->shader_overrides_group_active); - const StringName *K = nullptr; - while ((K = overrides.next(K))) { - Override *o = overrides.getptr(*K); + for (const KeyValue<StringName, Override> &E : overrides) { + const Override *o = &E.value; if (o->in_use && o->override.get_type() != Variant::NIL) { if (o->override.get_type() == Variant::OBJECT) { RID tex_rid = o->override; - RS::get_singleton()->global_variable_set_override(*K, tex_rid); + RS::get_singleton()->global_variable_set_override(E.key, tex_rid); } else { - RS::get_singleton()->global_variable_set_override(*K, o->override); + RS::get_singleton()->global_variable_set_override(E.key, o->override); } } - } - update_configuration_warnings(); //may have activated + update_configuration_warnings(); //may have activated + } } } @@ -256,18 +255,17 @@ void ShaderGlobalsOverride::_notification(int p_what) { case Node3D::NOTIFICATION_EXIT_TREE: { if (active) { //remove overrides - const StringName *K = nullptr; - while ((K = overrides.next(K))) { - Override *o = overrides.getptr(*K); + for (const KeyValue<StringName, Override> &E : overrides) { + const Override *o = &E.value; if (o->in_use) { - RS::get_singleton()->global_variable_set_override(*K, Variant()); + RS::get_singleton()->global_variable_set_override(E.key, Variant()); } } } remove_from_group(SceneStringNames::get_singleton()->shader_overrides_group_active); remove_from_group(SceneStringNames::get_singleton()->shader_overrides_group); - get_tree()->call_group(SceneStringNames::get_singleton()->shader_overrides_group, "_activate"); //another may want to activate when this is removed + get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->shader_overrides_group, "_activate"); //another may want to activate when this is removed active = false; } break; } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index d7e58ed707..a2399c8b5a 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -412,7 +412,7 @@ void Viewport::_notification(int p_what) { #ifndef _3D_DISABLED if (audio_listener_3d_set.size() && !audio_listener_3d) { AudioListener3D *first = nullptr; - for (Set<AudioListener3D *>::Element *E = audio_listener_3d_set.front(); E; E = E->next()) { + for (RBSet<AudioListener3D *>::Element *E = audio_listener_3d_set.front(); E; E = E->next()) { if (first == nullptr || first->is_greater_than(E->get())) { first = E->get(); } @@ -426,7 +426,7 @@ void Viewport::_notification(int p_what) { if (camera_3d_set.size() && !camera_3d) { // There are cameras but no current camera, pick first in tree and make it current. Camera3D *first = nullptr; - for (Set<Camera3D *>::Element *E = camera_3d_set.front(); E; E = E->next()) { + for (RBSet<Camera3D *>::Element *E = camera_3d_set.front(); E; E = E->next()) { if (first == nullptr || first->is_greater_than(E->get())) { first = E->get(); } @@ -647,7 +647,7 @@ void Viewport::_process_picking() { uint64_t frame = get_tree()->get_frame(); PhysicsDirectSpaceState2D::ShapeResult res[64]; - for (Set<CanvasLayer *>::Element *E = canvas_layers.front(); E; E = E->next()) { + for (RBSet<CanvasLayer *>::Element *E = canvas_layers.front(); E; E = E->next()) { Transform2D canvas_transform; ObjectID canvas_layer_id; if (E->get()) { @@ -675,23 +675,23 @@ void Viewport::_process_picking() { if (co && co->can_process()) { bool send_event = true; if (is_mouse) { - Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id); + HashMap<ObjectID, uint64_t>::Iterator F = physics_2d_mouseover.find(res[i].collider_id); if (!F) { physics_2d_mouseover.insert(res[i].collider_id, frame); co->_mouse_enter(); } else { - F->get() = frame; + F->value = frame; // It was already hovered, so don't send the event if it's faked. if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) { send_event = false; } } - Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *SF = physics_2d_shape_mouseover.find(Pair(res[i].collider_id, res[i].shape)); + HashMap<Pair<ObjectID, int>, uint64_t, PairHash<ObjectID, int>>::Iterator SF = physics_2d_shape_mouseover.find(Pair(res[i].collider_id, res[i].shape)); if (!SF) { physics_2d_shape_mouseover.insert(Pair(res[i].collider_id, res[i].shape), frame); co->_mouse_shape_enter(res[i].shape); } else { - SF->get() = frame; + SF->value = frame; } } @@ -2186,7 +2186,7 @@ void Viewport::_gui_control_grab_focus(Control *p_control) { // No need for change. return; } - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "_viewports", "_gui_remove_focus_for_window", (Node *)get_base_window()); + get_tree()->call_group("_viewports", "_gui_remove_focus_for_window", (Node *)get_base_window()); gui.key_focus = p_control; emit_signal(SNAME("gui_focus_changed"), p_control); p_control->notification(Control::NOTIFICATION_FOCUS_ENTER); @@ -2250,14 +2250,14 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) { } void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference) { - List<Map<ObjectID, uint64_t>::Element *> to_erase; + List<ObjectID> to_erase; - for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) { - if (!p_clean_all_frames && E->get() == p_frame_reference) { + for (const KeyValue<ObjectID, uint64_t> &E : physics_2d_mouseover) { + if (!p_clean_all_frames && E.value == p_frame_reference) { continue; } - Object *o = ObjectDB::get_instance(E->key()); + Object *o = ObjectDB::get_instance(E.key); if (o) { CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o); if (co && co->is_inside_tree()) { @@ -2267,7 +2267,7 @@ void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paus co->_mouse_exit(); } } - to_erase.push_back(E); + to_erase.push_back(E.key); } while (to_erase.size()) { @@ -2276,24 +2276,24 @@ void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paus } // Per-shape. - List<Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *> shapes_to_erase; + List<Pair<ObjectID, int>> shapes_to_erase; - for (Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *E = physics_2d_shape_mouseover.front(); E; E = E->next()) { - if (!p_clean_all_frames && E->get() == p_frame_reference) { + for (KeyValue<Pair<ObjectID, int>, uint64_t> &E : physics_2d_shape_mouseover) { + if (!p_clean_all_frames && E.value == p_frame_reference) { continue; } - Object *o = ObjectDB::get_instance(E->key().first); + Object *o = ObjectDB::get_instance(E.key.first); if (o) { CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o); if (co && co->is_inside_tree()) { if (p_clean_all_frames && p_paused_only && co->can_process()) { continue; } - co->_mouse_shape_exit(E->key().second); + co->_mouse_shape_exit(E.key.second); } } - shapes_to_erase.push_back(E); + shapes_to_erase.push_back(E.key); } while (shapes_to_erase.size()) { @@ -3179,7 +3179,7 @@ void Viewport::_audio_listener_3d_remove(AudioListener3D *p_listener) { void Viewport::_audio_listener_3d_make_next_current(AudioListener3D *p_exclude) { if (audio_listener_3d_set.size() > 0) { - for (Set<AudioListener3D *>::Element *E = audio_listener_3d_set.front(); E; E = E->next()) { + for (RBSet<AudioListener3D *>::Element *E = audio_listener_3d_set.front(); E; E = E->next()) { if (p_exclude == E->get()) { continue; } @@ -3267,7 +3267,7 @@ void Viewport::_camera_3d_remove(Camera3D *p_camera) { } void Viewport::_camera_3d_make_next_current(Camera3D *p_exclude) { - for (Set<Camera3D *>::Element *E = camera_3d_set.front(); E; E = E->next()) { + for (RBSet<Camera3D *>::Element *E = camera_3d_set.front(); E; E = E->next()) { if (p_exclude == E->get()) { continue; } @@ -3913,7 +3913,7 @@ Viewport::Viewport() { Viewport::~Viewport() { // Erase itself from viewport textures. - for (Set<ViewportTexture *>::Element *E = viewport_textures.front(); E; E = E->next()) { + for (RBSet<ViewportTexture *>::Element *E = viewport_textures.front(); E; E = E->next()) { E->get()->vp = nullptr; } RenderingServer::get_singleton()->free(viewport); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index c1e71c69a3..c1e4b30c20 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -203,7 +203,7 @@ private: AudioListener2D *audio_listener_2d = nullptr; Camera2D *camera_2d = nullptr; - Set<CanvasLayer *> canvas_layers; + RBSet<CanvasLayer *> canvas_layers; RID viewport; RID current_canvas; @@ -258,9 +258,9 @@ private: bool local_input_handled = false; // Collider to frame - Map<ObjectID, uint64_t> physics_2d_mouseover; + HashMap<ObjectID, uint64_t> physics_2d_mouseover; // Collider & shape to frame - Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>> physics_2d_shape_mouseover; + HashMap<Pair<ObjectID, int>, uint64_t, PairHash<ObjectID, int>> physics_2d_shape_mouseover; // Cleans up colliders corresponding to old frames or all of them. void _cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference = 0); @@ -301,7 +301,7 @@ private: bool use_occlusion_culling = false; Ref<ViewportTexture> default_texture; - Set<ViewportTexture *> viewport_textures; + RBSet<ViewportTexture *> viewport_textures; SDFOversize sdf_oversize = SDF_OVERSIZE_120_PERCENT; SDFScale sdf_scale = SDF_SCALE_50_PERCENT; @@ -615,7 +615,7 @@ public: bool use_xr = false; friend class AudioListener3D; AudioListener3D *audio_listener_3d = nullptr; - Set<AudioListener3D *> audio_listener_3d_set; + RBSet<AudioListener3D *> audio_listener_3d_set; bool is_audio_listener_3d_enabled = false; RID internal_audio_listener_3d; AudioListener3D *get_audio_listener_3d() const; @@ -650,7 +650,7 @@ public: friend class Camera3D; Camera3D *camera_3d = nullptr; - Set<Camera3D *> camera_3d_set; + RBSet<Camera3D *> camera_3d_set; Camera3D *get_camera_3d() const; void _camera_3d_transform_changed_notify(); void _camera_3d_set(Camera3D *p_camera); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 6feccb7eec..d8264e7d33 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -263,7 +263,7 @@ void Window::_make_window() { DisplayServer::get_singleton()->window_set_transient(window_id, transient_parent->window_id); } - for (Set<Window *>::Element *E = transient_children.front(); E; E = E->next()) { + for (RBSet<Window *>::Element *E = transient_children.front(); E; E = E->next()) { if (E->get()->window_id != DisplayServer::INVALID_WINDOW_ID) { DisplayServer::get_singleton()->window_set_transient(E->get()->window_id, transient_parent->window_id); } @@ -290,7 +290,7 @@ void Window::_clear_window() { DisplayServer::get_singleton()->window_set_transient(window_id, DisplayServer::INVALID_WINDOW_ID); } - for (Set<Window *>::Element *E = transient_children.front(); E; E = E->next()) { + for (RBSet<Window *>::Element *E = transient_children.front(); E; E = E->next()) { if (E->get()->window_id != DisplayServer::INVALID_WINDOW_ID) { DisplayServer::get_singleton()->window_set_transient(E->get()->window_id, DisplayServer::INVALID_WINDOW_ID); } diff --git a/scene/main/window.h b/scene/main/window.h index f674f6425a..80dd9a854c 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -131,7 +131,7 @@ private: void _make_transient(); Window *transient_parent = nullptr; Window *exclusive_child = nullptr; - Set<Window *> transient_children; + RBSet<Window *> transient_children; friend class Control; Ref<Theme> theme; diff --git a/scene/multiplayer/multiplayer_spawner.cpp b/scene/multiplayer/multiplayer_spawner.cpp index 25ab27f3e7..a9b9ffa989 100644 --- a/scene/multiplayer/multiplayer_spawner.cpp +++ b/scene/multiplayer/multiplayer_spawner.cpp @@ -91,9 +91,9 @@ void MultiplayerSpawner::_notification(int p_what) { case NOTIFICATION_EXIT_TREE: { _update_spawn_node(); - const ObjectID *oid = nullptr; - while ((oid = tracked_nodes.next(oid))) { - Node *node = Object::cast_to<Node>(ObjectDB::get_instance(*oid)); + + for (const KeyValue<ObjectID, SpawnInfo> &E : tracked_nodes) { + Node *node = Object::cast_to<Node>(ObjectDB::get_instance(E.key)); ERR_CONTINUE(!node); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit)); // This is unlikely, but might still crash the engine. diff --git a/scene/multiplayer/multiplayer_spawner.h b/scene/multiplayer/multiplayer_spawner.h index 63948e39a5..ac35df7ff3 100644 --- a/scene/multiplayer/multiplayer_spawner.h +++ b/scene/multiplayer/multiplayer_spawner.h @@ -47,7 +47,7 @@ public: private: TypedArray<PackedScene> spawnable_scenes; - Set<ResourceUID::ID> spawnable_ids; + RBSet<ResourceUID::ID> spawnable_ids; NodePath spawn_path; struct SpawnInfo { diff --git a/scene/multiplayer/scene_cache_interface.cpp b/scene/multiplayer/scene_cache_interface.cpp index f05dc5a2da..a7e84b6bca 100644 --- a/scene/multiplayer/scene_cache_interface.cpp +++ b/scene/multiplayer/scene_cache_interface.cpp @@ -50,10 +50,8 @@ void SceneCacheInterface::on_peer_change(int p_id, bool p_connected) { path_get_cache.erase(p_id); // Cleanup sent cache. // Some refactoring is needed to make this faster and do paths GC. - List<NodePath> keys; - path_send_cache.get_key_list(&keys); - for (const NodePath &E : keys) { - PathSentCache *psc = path_send_cache.getptr(E); + for (const KeyValue<NodePath, PathSentCache> &E : path_send_cache) { + PathSentCache *psc = path_send_cache.getptr(E.key); psc->confirmed_peers.erase(p_id); } } @@ -134,9 +132,9 @@ void SceneCacheInterface::process_confirm_path(int p_from, const uint8_t *p_pack PathSentCache *psc = path_send_cache.getptr(path); ERR_FAIL_COND_MSG(!psc, "Invalid packet received. Tries to confirm a path which was not found in cache."); - Map<int, bool>::Element *E = psc->confirmed_peers.find(p_from); + HashMap<int, bool>::Iterator E = psc->confirmed_peers.find(p_from); ERR_FAIL_COND_MSG(!E, "Invalid packet received. Source peer was not found in cache for the given path."); - E->get() = true; + E->value = true; } Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, const List<int> &p_peers) { @@ -184,9 +182,9 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat bool SceneCacheInterface::is_cache_confirmed(NodePath p_path, int p_peer) { const PathSentCache *psc = path_send_cache.getptr(p_path); ERR_FAIL_COND_V(!psc, false); - const Map<int, bool>::Element *F = psc->confirmed_peers.find(p_peer); + HashMap<int, bool>::ConstIterator F = psc->confirmed_peers.find(p_peer); ERR_FAIL_COND_V(!F, false); // Should never happen. - return F->get(); + return F->value; } bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int p_peer_id, int &r_id) { @@ -207,16 +205,16 @@ bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int if (p_peer_id > 0) { // Fast single peer check. - Map<int, bool>::Element *F = psc->confirmed_peers.find(p_peer_id); + HashMap<int, bool>::Iterator F = psc->confirmed_peers.find(p_peer_id); if (!F) { peers_to_add.push_back(p_peer_id); // Need to also be notified. has_all_peers = false; - } else if (!F->get()) { + } else if (!F->value) { has_all_peers = false; } } else { // Long and painful. - for (const Set<int>::Element *E = multiplayer->get_connected_peers().front(); E; E = E->next()) { + for (const RBSet<int>::Element *E = multiplayer->get_connected_peers().front(); E; E = E->next()) { if (p_peer_id < 0 && E->get() == -p_peer_id) { continue; // Continue, excluded. } @@ -224,11 +222,11 @@ bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int continue; // Continue, not for this peer. } - Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get()); + HashMap<int, bool>::Iterator F = psc->confirmed_peers.find(E->get()); if (!F) { peers_to_add.push_back(E->get()); // Need to also be notified. has_all_peers = false; - } else if (!F->get()) { + } else if (!F->value) { has_all_peers = false; } } @@ -244,13 +242,13 @@ bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int Object *SceneCacheInterface::get_cached_object(int p_from, uint32_t p_cache_id) { Node *root_node = SceneTree::get_singleton()->get_root()->get_node(multiplayer->get_root_path()); ERR_FAIL_COND_V(!root_node, nullptr); - Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from); + HashMap<int, PathGetCache>::Iterator E = path_get_cache.find(p_from); ERR_FAIL_COND_V_MSG(!E, nullptr, vformat("No cache found for peer %d.", p_from)); - Map<int, PathGetCache::NodeInfo>::Element *F = E->get().nodes.find(p_cache_id); + HashMap<int, PathGetCache::NodeInfo>::Iterator F = E->value.nodes.find(p_cache_id); ERR_FAIL_COND_V_MSG(!F, nullptr, vformat("ID %d not found in cache of peer %d.", p_cache_id, p_from)); - PathGetCache::NodeInfo *ni = &F->get(); + PathGetCache::NodeInfo *ni = &F->value; Node *node = root_node->get_node(ni->path); if (!node) { ERR_PRINT("Failed to get cached path: " + String(ni->path) + "."); diff --git a/scene/multiplayer/scene_cache_interface.h b/scene/multiplayer/scene_cache_interface.h index d53cf387fb..3116233b5b 100644 --- a/scene/multiplayer/scene_cache_interface.h +++ b/scene/multiplayer/scene_cache_interface.h @@ -41,7 +41,7 @@ private: //path sent caches struct PathSentCache { - Map<int, bool> confirmed_peers; + HashMap<int, bool> confirmed_peers; int id; }; @@ -52,11 +52,11 @@ private: ObjectID instance; }; - Map<int, NodeInfo> nodes; + HashMap<int, NodeInfo> nodes; }; HashMap<NodePath, PathSentCache> path_send_cache; - Map<int, PathGetCache> path_get_cache; + HashMap<int, PathGetCache> path_get_cache; int last_send_cache_id = 1; protected: diff --git a/scene/multiplayer/scene_replication_interface.cpp b/scene/multiplayer/scene_replication_interface.cpp index 2952512462..55266c53ad 100644 --- a/scene/multiplayer/scene_replication_interface.cpp +++ b/scene/multiplayer/scene_replication_interface.cpp @@ -49,9 +49,8 @@ void SceneReplicationInterface::make_default() { void SceneReplicationInterface::_free_remotes(int p_id) { const HashMap<uint32_t, ObjectID> remotes = rep_state->peer_get_remotes(p_id); - const uint32_t *k = nullptr; - while ((k = remotes.next(k))) { - Node *node = rep_state->get_node(remotes.get(*k)); + for (const KeyValue<uint32_t, ObjectID> &E : remotes) { + Node *node = rep_state->get_node(E.value); ERR_CONTINUE(!node); node->queue_delete(); } @@ -317,7 +316,7 @@ Error SceneReplicationInterface::on_despawn_receive(int p_from, const uint8_t *p } void SceneReplicationInterface::_send_sync(int p_peer, uint64_t p_msec) { - const Set<ObjectID> &known = rep_state->get_known_nodes(p_peer); + const RBSet<ObjectID> &known = rep_state->get_known_nodes(p_peer); if (known.is_empty()) { return; } diff --git a/scene/multiplayer/scene_replication_state.cpp b/scene/multiplayer/scene_replication_state.cpp index b8dadeff24..e5cc57ff31 100644 --- a/scene/multiplayer/scene_replication_state.cpp +++ b/scene/multiplayer/scene_replication_state.cpp @@ -55,9 +55,8 @@ void SceneReplicationState::_untrack(const ObjectID &p_id) { } // If we spawned or synced it, we need to remove it from any peer it was sent to. if (net_id || peer == 0) { - const int *k = nullptr; - while ((k = peers_info.next(k))) { - peers_info.get(*k).known_nodes.erase(p_id); + for (KeyValue<int, PeerInfo> &E : peers_info) { + E.value.known_nodes.erase(p_id); } } } @@ -94,8 +93,8 @@ bool SceneReplicationState::update_sync_time(const ObjectID &p_id, uint64_t p_ms return false; } -const Set<ObjectID> SceneReplicationState::get_known_nodes(int p_peer) { - ERR_FAIL_COND_V(!peers_info.has(p_peer), Set<ObjectID>()); +const RBSet<ObjectID> SceneReplicationState::get_known_nodes(int p_peer) { + ERR_FAIL_COND_V(!peers_info.has(p_peer), RBSet<ObjectID>()); return peers_info[p_peer].known_nodes; } @@ -134,9 +133,8 @@ void SceneReplicationState::reset() { peers_info.clear(); known_peers.clear(); // Tracked nodes are cleared on deletion, here we only reset the ids so they can be later re-assigned. - const ObjectID *oid = nullptr; - while ((oid = tracked_nodes.next(oid))) { - TrackedNode &tobj = tracked_nodes[*oid]; + for (KeyValue<ObjectID, TrackedNode> &E : tracked_nodes) { + TrackedNode &tobj = E.value; tobj.net_id = 0; tobj.remote_peer = 0; tobj.last_sync = 0; @@ -195,9 +193,8 @@ Error SceneReplicationState::peer_add_node(int p_peer, const ObjectID &p_id) { ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER); peers_info[p_peer].known_nodes.insert(p_id); } else { - const int *pid = nullptr; - while ((pid = peers_info.next(pid))) { - peers_info.get(*pid).known_nodes.insert(p_id); + for (KeyValue<int, PeerInfo> &E : peers_info) { + E.value.known_nodes.insert(p_id); } } return OK; @@ -208,9 +205,8 @@ Error SceneReplicationState::peer_del_node(int p_peer, const ObjectID &p_id) { ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER); peers_info[p_peer].known_nodes.erase(p_id); } else { - const int *pid = nullptr; - while ((pid = peers_info.next(pid))) { - peers_info.get(*pid).known_nodes.erase(p_id); + for (KeyValue<int, PeerInfo> &E : peers_info) { + E.value.known_nodes.erase(p_id); } } return OK; diff --git a/scene/multiplayer/scene_replication_state.h b/scene/multiplayer/scene_replication_state.h index 18e4d9fa39..33f72363ac 100644 --- a/scene/multiplayer/scene_replication_state.h +++ b/scene/multiplayer/scene_replication_state.h @@ -62,27 +62,27 @@ private: }; struct PeerInfo { - Set<ObjectID> known_nodes; + RBSet<ObjectID> known_nodes; HashMap<uint32_t, ObjectID> recv_nodes; uint16_t last_sent_sync = 0; uint16_t last_recv_sync = 0; }; - Set<int> known_peers; + RBSet<int> known_peers; uint32_t last_net_id = 0; HashMap<ObjectID, TrackedNode> tracked_nodes; HashMap<int, PeerInfo> peers_info; - Set<ObjectID> spawned_nodes; - Set<ObjectID> path_only_nodes; + RBSet<ObjectID> spawned_nodes; + RBSet<ObjectID> path_only_nodes; TrackedNode &_track(const ObjectID &p_id); void _untrack(const ObjectID &p_id); bool is_tracked(const ObjectID &p_id) const { return tracked_nodes.has(p_id); } public: - const Set<int> get_peers() const { return known_peers; } - const Set<ObjectID> get_spawned_nodes() const { return spawned_nodes; } - const Set<ObjectID> get_path_only_nodes() const { return path_only_nodes; } + const RBSet<int> get_peers() const { return known_peers; } + const RBSet<ObjectID> &get_spawned_nodes() const { return spawned_nodes; } + const RBSet<ObjectID> &get_path_only_nodes() const { return path_only_nodes; } MultiplayerSynchronizer *get_synchronizer(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_synchronizer() : nullptr; } MultiplayerSpawner *get_spawner(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_spawner() : nullptr; } @@ -90,7 +90,7 @@ public: bool update_last_node_sync(const ObjectID &p_id, uint16_t p_time); bool update_sync_time(const ObjectID &p_id, uint64_t p_msec); - const Set<ObjectID> get_known_nodes(int p_peer); + const RBSet<ObjectID> get_known_nodes(int p_peer); uint32_t get_net_id(const ObjectID &p_id) const; void set_net_id(const ObjectID &p_id, uint32_t p_net_id); uint32_t ensure_net_id(const ObjectID &p_id); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 632952c2cb..6bce957d80 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -769,6 +769,7 @@ void register_scene_types() { GDREGISTER_CLASS(PrismMesh); GDREGISTER_CLASS(QuadMesh); GDREGISTER_CLASS(SphereMesh); + GDREGISTER_CLASS(TextMesh); GDREGISTER_CLASS(TubeTrailMesh); GDREGISTER_CLASS(RibbonTrailMesh); GDREGISTER_CLASS(PointMesh); diff --git a/scene/resources/animation_library.h b/scene/resources/animation_library.h index 21f0162eb3..7a69cd140a 100644 --- a/scene/resources/animation_library.h +++ b/scene/resources/animation_library.h @@ -43,7 +43,7 @@ class AnimationLibrary : public Resource { TypedArray<StringName> _get_animation_list() const; friend class AnimationPlayer; //for faster access - Map<StringName, Ref<Animation>> animations; + HashMap<StringName, Ref<Animation>> animations; protected: static void _bind_methods(); diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index c2988c2e8c..634fb3ef2f 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -170,8 +170,8 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) int curx = startx; int cury = starty; unsigned int count = 0; - Set<Point2i> case9s; - Set<Point2i> case6s; + RBSet<Point2i> case9s; + RBSet<Point2i> case6s; Vector<Vector2> _points; do { int sv = 0; diff --git a/scene/resources/canvas_item_material.cpp b/scene/resources/canvas_item_material.cpp index 2d668cdf7f..aa6cc4aded 100644 --- a/scene/resources/canvas_item_material.cpp +++ b/scene/resources/canvas_item_material.cpp @@ -34,7 +34,7 @@ Mutex CanvasItemMaterial::material_mutex; SelfList<CanvasItemMaterial>::List *CanvasItemMaterial::dirty_materials = nullptr; -Map<CanvasItemMaterial::MaterialKey, CanvasItemMaterial::ShaderData> CanvasItemMaterial::shader_map; +HashMap<CanvasItemMaterial::MaterialKey, CanvasItemMaterial::ShaderData, CanvasItemMaterial::MaterialKey> CanvasItemMaterial::shader_map; CanvasItemMaterial::ShaderNames *CanvasItemMaterial::shader_names = nullptr; void CanvasItemMaterial::init_shaders() { diff --git a/scene/resources/canvas_item_material.h b/scene/resources/canvas_item_material.h index b097d174f0..7c44c125a8 100644 --- a/scene/resources/canvas_item_material.h +++ b/scene/resources/canvas_item_material.h @@ -63,8 +63,11 @@ private: uint32_t key = 0; - bool operator<(const MaterialKey &p_key) const { - return key < p_key.key; + static uint32_t hash(const MaterialKey &p_key) { + return hash_djb2_one_32(p_key.key); + } + bool operator==(const MaterialKey &p_key) const { + return key == p_key.key; } }; @@ -81,7 +84,7 @@ private: int users = 0; }; - static Map<MaterialKey, ShaderData> shader_map; + static HashMap<MaterialKey, ShaderData, MaterialKey> shader_map; MaterialKey current_key; diff --git a/scene/resources/concave_polygon_shape_3d.cpp b/scene/resources/concave_polygon_shape_3d.cpp index 3e178108c4..ab2c1da327 100644 --- a/scene/resources/concave_polygon_shape_3d.cpp +++ b/scene/resources/concave_polygon_shape_3d.cpp @@ -33,7 +33,7 @@ #include "servers/physics_server_3d.h" Vector<Vector3> ConcavePolygonShape3D::get_debug_mesh_lines() const { - Set<DrawEdge> edges; + RBSet<DrawEdge> edges; int index_count = faces.size(); ERR_FAIL_COND_V((index_count % 3) != 0, Vector<Vector3>()); @@ -50,7 +50,7 @@ Vector<Vector3> ConcavePolygonShape3D::get_debug_mesh_lines() const { Vector<Vector3> points; points.resize(edges.size() * 2); int idx = 0; - for (Set<DrawEdge>::Element *E = edges.front(); E; E = E->next()) { + for (RBSet<DrawEdge>::Element *E = edges.front(); E; E = E->next()) { points.write[idx + 0] = E->get().a; points.write[idx + 1] = E->get().b; idx += 2; diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 6485c1ac77..9ea7bb464a 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -632,7 +632,7 @@ Vector2 Curve2D::interpolatef(real_t p_findex) const { return interpolate((int)p_findex, Math::fmod(p_findex, (real_t)1.0)); } -void Curve2D::_bake_segment2d(Map<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_tol) const { +void Curve2D::_bake_segment2d(RBMap<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_tol) const { real_t mp = p_begin + (p_end - p_begin) * 0.5; Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b); Vector2 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b); @@ -681,7 +681,8 @@ void Curve2D::_bake() const { List<Vector2> pointlist; List<real_t> distlist; - pointlist.push_back(position); //start always from origin + // Start always from origin. + pointlist.push_back(position); distlist.push_back(0.0); for (int i = 0; i < points.size() - 1; i++) { @@ -728,15 +729,18 @@ void Curve2D::_bake() const { p = np; } } - } - Vector2 lastpos = points[points.size() - 1].position; + Vector2 npp = points[i + 1].position; + real_t d = position.distance_to(npp); + + position = npp; + dist += d; + + pointlist.push_back(position); + distlist.push_back(dist); + } - real_t rem = position.distance_to(lastpos); - dist += rem; baked_max_ofs = dist; - pointlist.push_back(lastpos); - distlist.push_back(dist); baked_point_cache.resize(pointlist.size()); baked_dist_cache.resize(distlist.size()); @@ -763,7 +767,7 @@ Vector2 Curve2D::interpolate_baked(real_t p_offset, bool p_cubic) const { _bake(); } - //validate// + // Validate: Curve may not have baked points. int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, Vector2(), "No points in Curve2D."); @@ -771,18 +775,19 @@ Vector2 Curve2D::interpolate_baked(real_t p_offset, bool p_cubic) const { return baked_point_cache.get(0); } - int bpc = baked_point_cache.size(); const Vector2 *r = baked_point_cache.ptr(); if (p_offset < 0) { return r[0]; } if (p_offset >= baked_max_ofs) { - return r[bpc - 1]; + return r[pc - 1]; } - int start = 0, end = bpc, idx = (end + start) / 2; - // binary search to find baked points + int start = 0; + int end = pc; + int idx = (end + start) / 2; + // Binary search to find baked points. while (start < idx) { real_t offset = baked_dist_cache[idx]; if (p_offset <= offset) { @@ -803,7 +808,7 @@ Vector2 Curve2D::interpolate_baked(real_t p_offset, bool p_cubic) const { if (p_cubic) { Vector2 pre = idx > 0 ? r[idx - 1] : r[idx]; - Vector2 post = (idx < (bpc - 2)) ? r[idx + 2] : r[idx + 1]; + Vector2 post = (idx < (pc - 2)) ? r[idx + 2] : r[idx + 1]; return r[idx].cubic_interpolate(r[idx + 1], pre, post, frac); } else { return r[idx].lerp(r[idx + 1], frac); @@ -829,13 +834,13 @@ real_t Curve2D::get_bake_interval() const { } Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const { - // Brute force method + // Brute force method. if (baked_cache_dirty) { _bake(); } - //validate// + // Validate: Curve may not have baked points. int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, Vector2(), "No points in Curve2D."); @@ -867,13 +872,13 @@ Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const { } real_t Curve2D::get_closest_offset(const Vector2 &p_to_point) const { - // Brute force method + // Brute force method. if (baked_cache_dirty) { _bake(); } - //validate// + // Validate: Curve may not have baked points. int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, 0.0f, "No points in Curve2D."); @@ -949,7 +954,9 @@ PackedVector2Array Curve2D::tessellate(int p_max_stages, real_t p_tolerance) con if (points.size() == 0) { return tess; } - Vector<Map<real_t, Vector2>> midpoints; + + // The current implementation requires a sorted map. + Vector<RBMap<real_t, Vector2>> midpoints; midpoints.resize(points.size() - 1); @@ -1009,11 +1016,7 @@ void Curve2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); } -Curve2D::Curve2D() { - /* add_point(Vector2(-1,0,0)); - add_point(Vector2(0,2,0)); - add_point(Vector2(0,3,5));*/ -} +Curve2D::Curve2D() {} /***********************************************************************************/ /***********************************************************************************/ @@ -1136,7 +1139,7 @@ Vector3 Curve3D::interpolatef(real_t p_findex) const { return interpolate((int)p_findex, Math::fmod(p_findex, (real_t)1.0)); } -void Curve3D::_bake_segment3d(Map<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_tol) const { +void Curve3D::_bake_segment3d(RBMap<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_tol) const { real_t mp = p_begin + (p_end - p_begin) * 0.5; Vector3 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b); Vector3 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b); @@ -1194,6 +1197,7 @@ void Curve3D::_bake() const { List<Plane> pointlist; List<real_t> distlist; + // Start always from origin. pointlist.push_back(Plane(position, points[0].tilt)); distlist.push_back(0.0); @@ -1244,16 +1248,22 @@ void Curve3D::_bake() const { p = np; } } - } - Vector3 lastpos = points[points.size() - 1].position; - real_t lastilt = points[points.size() - 1].tilt; + Vector3 npp = points[i + 1].position; + real_t d = position.distance_to(npp); + + position = npp; + Plane post; + post.normal = position; + post.d = points[i + 1].tilt; + + dist += d; + + pointlist.push_back(post); + distlist.push_back(dist); + } - real_t rem = position.distance_to(lastpos); - dist += rem; baked_max_ofs = dist; - pointlist.push_back(Plane(lastpos, lastilt)); - distlist.push_back(dist); baked_point_cache.resize(pointlist.size()); Vector3 *w = baked_point_cache.ptrw(); @@ -1328,7 +1338,7 @@ Vector3 Curve3D::interpolate_baked(real_t p_offset, bool p_cubic) const { _bake(); } - //validate// + // Validate: Curve may not have baked points. int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, Vector3(), "No points in Curve3D."); @@ -1336,18 +1346,19 @@ Vector3 Curve3D::interpolate_baked(real_t p_offset, bool p_cubic) const { return baked_point_cache.get(0); } - int bpc = baked_point_cache.size(); const Vector3 *r = baked_point_cache.ptr(); if (p_offset < 0) { return r[0]; } if (p_offset >= baked_max_ofs) { - return r[bpc - 1]; + return r[pc - 1]; } - int start = 0, end = bpc, idx = (end + start) / 2; - // binary search to find baked points + int start = 0; + int end = pc; + int idx = (end + start) / 2; + // Binary search to find baked points. while (start < idx) { real_t offset = baked_dist_cache[idx]; if (p_offset <= offset) { @@ -1368,7 +1379,7 @@ Vector3 Curve3D::interpolate_baked(real_t p_offset, bool p_cubic) const { if (p_cubic) { Vector3 pre = idx > 0 ? r[idx - 1] : r[idx]; - Vector3 post = (idx < (bpc - 2)) ? r[idx + 2] : r[idx + 1]; + Vector3 post = (idx < (pc - 2)) ? r[idx + 2] : r[idx + 1]; return r[idx].cubic_interpolate(r[idx + 1], pre, post, frac); } else { return r[idx].lerp(r[idx + 1], frac); @@ -1380,7 +1391,7 @@ real_t Curve3D::interpolate_baked_tilt(real_t p_offset) const { _bake(); } - //validate// + // Validate: Curve may not have baked tilts. int pc = baked_tilt_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, 0, "No tilts in Curve3D."); @@ -1388,29 +1399,37 @@ real_t Curve3D::interpolate_baked_tilt(real_t p_offset) const { return baked_tilt_cache.get(0); } - int bpc = baked_tilt_cache.size(); const real_t *r = baked_tilt_cache.ptr(); if (p_offset < 0) { return r[0]; } if (p_offset >= baked_max_ofs) { - return r[bpc - 1]; + return r[pc - 1]; } - int idx = Math::floor((double)p_offset / (double)bake_interval); - real_t frac = Math::fmod(p_offset, bake_interval); - - if (idx >= bpc - 1) { - return r[bpc - 1]; - } else if (idx == bpc - 2) { - if (frac > 0) { - frac /= Math::fmod(baked_max_ofs, bake_interval); + int start = 0; + int end = pc; + int idx = (end + start) / 2; + // Binary search to find baked points. + while (start < idx) { + real_t offset = baked_dist_cache[idx]; + if (p_offset <= offset) { + end = idx; + } else { + start = idx; } - } else { - frac /= bake_interval; + idx = (end + start) / 2; } + real_t offset_begin = baked_dist_cache[idx]; + real_t offset_end = baked_dist_cache[idx + 1]; + + real_t idx_interval = offset_end - offset_begin; + ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, 0, "failed to find baked segment"); + + real_t frac = (p_offset - offset_begin) / idx_interval; + return Math::lerp(r[idx], r[idx + 1], (real_t)frac); } @@ -1419,8 +1438,7 @@ Vector3 Curve3D::interpolate_baked_up_vector(real_t p_offset, bool p_apply_tilt) _bake(); } - //validate// - // curve may not have baked up vectors + // Validate: Curve may not have baked up vectors. int count = baked_up_vector_cache.size(); ERR_FAIL_COND_V_MSG(count == 0, Vector3(0, 1, 0), "No up vectors in Curve3D."); @@ -1432,10 +1450,27 @@ Vector3 Curve3D::interpolate_baked_up_vector(real_t p_offset, bool p_apply_tilt) const Vector3 *rp = baked_point_cache.ptr(); const real_t *rt = baked_tilt_cache.ptr(); - real_t offset = CLAMP(p_offset, 0.0f, baked_max_ofs); + int start = 0; + int end = count; + int idx = (end + start) / 2; + // Binary search to find baked points. + while (start < idx) { + real_t offset = baked_dist_cache[idx]; + if (p_offset <= offset) { + end = idx; + } else { + start = idx; + } + idx = (end + start) / 2; + } + + real_t offset_begin = baked_dist_cache[idx]; + real_t offset_end = baked_dist_cache[idx + 1]; - int idx = Math::floor((double)offset / (double)bake_interval); - real_t frac = Math::fmod(offset, bake_interval) / bake_interval; + real_t idx_interval = offset_end - offset_begin; + ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(0, 1, 0), "failed to find baked segment"); + + real_t frac = (p_offset - offset_begin) / idx_interval; if (idx == count - 1) { return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx]; @@ -1486,13 +1521,13 @@ PackedVector3Array Curve3D::get_baked_up_vectors() const { } Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const { - // Brute force method + // Brute force method. if (baked_cache_dirty) { _bake(); } - //validate// + // Validate: Curve may not have baked points. int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, Vector3(), "No points in Curve3D."); @@ -1524,13 +1559,13 @@ Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const { } real_t Curve3D::get_closest_offset(const Vector3 &p_to_point) const { - // Brute force method + // Brute force method. if (baked_cache_dirty) { _bake(); } - //validate// + // Validate: Curve may not have baked points. int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, 0.0f, "No points in Curve3D."); @@ -1635,7 +1670,7 @@ PackedVector3Array Curve3D::tessellate(int p_max_stages, real_t p_tolerance) con if (points.size() == 0) { return tess; } - Vector<Map<real_t, Vector3>> midpoints; + Vector<RBMap<real_t, Vector3>> midpoints; midpoints.resize(points.size() - 1); @@ -1705,8 +1740,4 @@ void Curve3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "up_vector_enabled"), "set_up_vector_enabled", "is_up_vector_enabled"); } -Curve3D::Curve3D() { - /* add_point(Vector3(-1,0,0)); - add_point(Vector3(0,2,0)); - add_point(Vector3(0,3,5));*/ -} +Curve3D::Curve3D() {} diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 767900b843..398f64cabe 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -168,7 +168,7 @@ class Curve2D : public Resource { real_t bake_interval = 5.0; - void _bake_segment2d(Map<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_tol) const; + void _bake_segment2d(RBMap<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_tol) const; Dictionary _get_data() const; void _set_data(const Dictionary &p_data); @@ -233,7 +233,7 @@ class Curve3D : public Resource { real_t bake_interval = 0.2; bool up_vector_enabled = true; - void _bake_segment3d(Map<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_tol) const; + void _bake_segment3d(RBMap<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_tol) const; Dictionary _get_data() const; void _set_data(const Dictionary &p_data); diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 271cf61171..4fb44446d9 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -686,6 +686,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const graphnode_breakpoint->set_border_color(Color(0.9, 0.29, 0.3)); Ref<StyleBoxFlat> graphnode_position = make_flat_stylebox(style_pressed_color, 18, 42, 18, 12, 6, true, 4); graphnode_position->set_border_color(Color(0.98, 0.89, 0.27)); + Ref<StyleBoxEmpty> graphnode_slot = make_empty_stylebox(0, 0, 0, 0); theme->set_stylebox("frame", "GraphNode", graphnode_normal); theme->set_stylebox("selected_frame", "GraphNode", graphnode_selected); @@ -693,6 +694,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("comment_focus", "GraphNode", graphnode_comment_selected); theme->set_stylebox("breakpoint", "GraphNode", graphnode_breakpoint); theme->set_stylebox("position", "GraphNode", graphnode_position); + theme->set_stylebox("slot", "GraphNode", graphnode_slot); theme->set_icon("port", "GraphNode", icons["graph_port"]); theme->set_icon("close", "GraphNode", icons["close"]); @@ -704,6 +706,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("separation", "GraphNode", 2 * scale); theme->set_constant("title_offset", "GraphNode", 26 * scale); theme->set_constant("close_offset", "GraphNode", 22 * scale); + theme->set_constant("close_h_offset", "GraphNode", 22 * scale); theme->set_constant("port_offset", "GraphNode", 0); // Tree diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index d92d34437e..5d1e07f6cd 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -1096,7 +1096,6 @@ void Environment::_validate_property(PropertyInfo &property) const { static const char *high_end_prefixes[] = { "auto_exposure_", - "tonemap_", "ssr_", "ssao_", nullptr diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index d6b2572628..d586abac14 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -33,6 +33,7 @@ #include "core/io/image_loader.h" #include "core/io/resource_loader.h" #include "core/string/translation.h" +#include "core/templates/hash_map.h" #include "core/templates/hashfuncs.h" #include "scene/resources/text_line.h" #include "scene/resources/text_paragraph.h" @@ -963,7 +964,7 @@ Error FontData::load_bitmap_font(const String &p_path) { int delimiter = line.find(" "); String type = line.substr(0, delimiter); int pos = delimiter + 1; - Map<String, String> keys; + HashMap<String, String> keys; while (pos < line.size() && line[pos] == ' ') { pos++; diff --git a/scene/resources/font.h b/scene/resources/font.h index 9a90032605..96bfe3678b 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -33,7 +33,7 @@ #include "core/io/resource.h" #include "core/templates/lru.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "scene/resources/texture.h" #include "servers/text_server.h" diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index cca875f708..0fbd29b1a6 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -306,7 +306,7 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli float normal_split_threshold = Math::cos(Math::deg2rad(p_normal_split_angle)); const Vector3 *normals_ptr = normals.ptr(); - Map<Vector3, LocalVector<Pair<int, int>>> unique_vertices; + HashMap<Vector3, LocalVector<Pair<int, int>>> unique_vertices; LocalVector<int> vertex_remap; LocalVector<int> vertex_inverse_remap; @@ -320,10 +320,10 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli const Vector3 &v = vertices_ptr[j]; const Vector3 &n = normals_ptr[j]; - Map<Vector3, LocalVector<Pair<int, int>>>::Element *E = unique_vertices.find(v); + HashMap<Vector3, LocalVector<Pair<int, int>>>::Iterator E = unique_vertices.find(v); if (E) { - const LocalVector<Pair<int, int>> &close_verts = E->get(); + const LocalVector<Pair<int, int>> &close_verts = E->value; bool found = false; for (unsigned int k = 0; k < close_verts.size(); k++) { @@ -706,15 +706,15 @@ void ImporterMesh::create_shadow_mesh() { Vector<Vector3> vertices = surfaces[i].arrays[RS::ARRAY_VERTEX]; int vertex_count = vertices.size(); { - Map<Vector3, int> unique_vertices; + HashMap<Vector3, int> unique_vertices; const Vector3 *vptr = vertices.ptr(); for (int j = 0; j < vertex_count; j++) { const Vector3 &v = vptr[j]; - Map<Vector3, int>::Element *E = unique_vertices.find(v); + HashMap<Vector3, int>::Iterator E = unique_vertices.find(v); if (E) { - vertex_remap.push_back(E->get()); + vertex_remap.push_back(E->value); } else { int vcount = unique_vertices.size(); unique_vertices[v] = vcount; @@ -898,16 +898,16 @@ Vector<Ref<Shape3D>> ImporterMesh::convex_decompose(const Mesh::ConvexDecomposit Vector<uint32_t> indices; indices.resize(face_count * 3); { - Map<Vector3, uint32_t> vertex_map; + HashMap<Vector3, uint32_t> vertex_map; Vector3 *vertex_w = vertices.ptrw(); uint32_t *index_w = indices.ptrw(); for (int i = 0; i < face_count; i++) { for (int j = 0; j < 3; j++) { const Vector3 &vertex = faces[i].vertex[j]; - Map<Vector3, uint32_t>::Element *found_vertex = vertex_map.find(vertex); + HashMap<Vector3, uint32_t>::Iterator found_vertex = vertex_map.find(vertex); uint32_t index; if (found_vertex) { - index = found_vertex->get(); + index = found_vertex->value; } else { index = ++vertex_count; vertex_map[vertex] = index; @@ -960,7 +960,7 @@ Ref<NavigationMesh> ImporterMesh::create_navigation_mesh() { return Ref<NavigationMesh>(); } - Map<Vector3, int> unique_vertices; + HashMap<Vector3, int> unique_vertices; LocalVector<int> face_indices; for (int i = 0; i < faces.size(); i++) { diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 16fce5e08a..b8171ca4bd 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -84,7 +84,7 @@ void Material::inspect_native_shader_code() { SceneTree *st = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop()); RID shader = get_shader_rid(); if (st && shader.is_valid()) { - st->call_group("_native_shader_source_visualizer", "_inspect_shader", shader); + st->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_native_shader_source_visualizer", "_inspect_shader", shader); } } @@ -187,9 +187,9 @@ bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { } if (pr) { - const Map<StringName, Variant>::Element *E = param_cache.find(pr); + HashMap<StringName, Variant>::ConstIterator E = param_cache.find(pr); if (E) { - r_ret = E->get(); + r_ret = E->value; } else { r_ret = Variant(); } @@ -348,7 +348,7 @@ ShaderMaterial::~ShaderMaterial() { Mutex BaseMaterial3D::material_mutex; SelfList<BaseMaterial3D>::List *BaseMaterial3D::dirty_materials = nullptr; -Map<BaseMaterial3D::MaterialKey, BaseMaterial3D::ShaderData> BaseMaterial3D::shader_map; +HashMap<BaseMaterial3D::MaterialKey, BaseMaterial3D::ShaderData, BaseMaterial3D::MaterialKey> BaseMaterial3D::shader_map; BaseMaterial3D::ShaderNames *BaseMaterial3D::shader_names = nullptr; void BaseMaterial3D::init_shaders() { @@ -1788,8 +1788,6 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { _validate_high_end("refraction", property); _validate_high_end("subsurf_scatter", property); - _validate_high_end("anisotropy", property); - _validate_high_end("clearcoat", property); _validate_high_end("heightmap", property); if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { diff --git a/scene/resources/material.h b/scene/resources/material.h index 7edb8b7317..b845fd68c8 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -82,7 +82,7 @@ class ShaderMaterial : public Material { GDCLASS(ShaderMaterial, Material); Ref<Shader> shader; - Map<StringName, Variant> param_cache; + HashMap<StringName, Variant> param_cache; protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -323,6 +323,9 @@ private: memset(this, 0, sizeof(MaterialKey)); } + static uint32_t hash(const MaterialKey &p_key) { + return hash_djb2_buffer((const uint8_t *)&p_key, sizeof(MaterialKey)); + } bool operator==(const MaterialKey &p_key) const { return memcmp(this, &p_key, sizeof(MaterialKey)) == 0; } @@ -337,7 +340,7 @@ private: int users = 0; }; - static Map<MaterialKey, ShaderData> shader_map; + static HashMap<MaterialKey, ShaderData, MaterialKey> shader_map; MaterialKey current_key; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 253ba53c35..ab1873ffe9 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -455,7 +455,7 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { has_indices = true; } - Map<Vector3, Vector3> normal_accum; + HashMap<Vector3, Vector3> normal_accum; //fill normals with triangle normals for (int i = 0; i < vc; i += 3) { @@ -474,13 +474,13 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { Vector3 n = Plane(t[0], t[1], t[2]).normal; for (int j = 0; j < 3; j++) { - Map<Vector3, Vector3>::Element *E = normal_accum.find(t[j]); + HashMap<Vector3, Vector3>::Iterator E = normal_accum.find(t[j]); if (!E) { normal_accum[t[j]] = n; } else { - float d = n.dot(E->get()); + float d = n.dot(E->value); if (d < 1.0) { - E->get() += n * (1.0 - d); + E->value += n * (1.0 - d); } //E->get()+=n; } @@ -499,10 +499,10 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { for (int i = 0; i < vc2; i++) { Vector3 t = r[i]; - Map<Vector3, Vector3>::Element *E = normal_accum.find(t); + HashMap<Vector3, Vector3>::Iterator E = normal_accum.find(t); ERR_CONTINUE(!E); - t += E->get() * p_margin; + t += E->value * p_margin; r[i] = t; } diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp index 594f723a1d..33d63adc71 100644 --- a/scene/resources/mesh_data_tool.cpp +++ b/scene/resources/mesh_data_tool.cpp @@ -150,7 +150,7 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf vertices.write[i] = v; } - Map<Point2i, int> edge_indices; + HashMap<Point2i, int> edge_indices; for (int i = 0; i < icount; i += 3) { Vertex *v[3] = { &vertices.write[r[i + 0]], &vertices.write[r[i + 1]], &vertices.write[r[i + 2]] }; diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h index e0f2ab2114..4105bd6960 100644 --- a/scene/resources/mesh_library.h +++ b/scene/resources/mesh_library.h @@ -32,7 +32,7 @@ #define MESH_LIBRARY_H #include "core/io/resource.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "mesh.h" #include "scene/3d/navigation_region_3d.h" #include "shape_3d.h" @@ -56,7 +56,7 @@ public: Ref<NavigationMesh> navmesh; }; - Map<int, Item> item_map; + RBMap<int, Item> item_map; void _set_item_shapes(int p_item, const Array &p_shapes); Array _get_item_shapes(int p_item) const; diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index 552fa84bad..7813de94ca 100644 --- a/scene/resources/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -229,7 +229,7 @@ float NavigationMesh::get_verts_per_poly() const { } void NavigationMesh::set_detail_sample_distance(float p_value) { - ERR_FAIL_COND(p_value < 0); + ERR_FAIL_COND(p_value < 0.1); detail_sample_distance = p_value; } @@ -338,7 +338,7 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() { } } - Map<_EdgeKey, bool> edge_map; + HashMap<_EdgeKey, bool, _EdgeKey> edge_map; Vector<Vector3> tmeshfaces; tmeshfaces.resize(faces.size() * 3); @@ -356,10 +356,10 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() { SWAP(ek.from, ek.to); } - Map<_EdgeKey, bool>::Element *F = edge_map.find(ek); + HashMap<_EdgeKey, bool, _EdgeKey>::Iterator F = edge_map.find(ek); if (F) { - F->get() = false; + F->value = false; } else { edge_map[ek] = true; @@ -501,7 +501,7 @@ void NavigationMesh::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge/max_length", PROPERTY_HINT_RANGE, "0.0,50.0,0.01,or_greater"), "set_edge_max_length", "get_edge_max_length"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge/max_error", PROPERTY_HINT_RANGE, "0.1,3.0,0.01,or_greater"), "set_edge_max_error", "get_edge_max_error"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "polygon/verts_per_poly", PROPERTY_HINT_RANGE, "3.0,12.0,1.0,or_greater"), "set_verts_per_poly", "get_verts_per_poly"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail/sample_distance", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater"), "set_detail_sample_distance", "get_detail_sample_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail/sample_distance", PROPERTY_HINT_RANGE, "0.1,16.0,0.01,or_greater"), "set_detail_sample_distance", "get_detail_sample_distance"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail/sample_max_error", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater"), "set_detail_sample_max_error", "get_detail_sample_max_error"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter/low_hanging_obstacles"), "set_filter_low_hanging_obstacles", "get_filter_low_hanging_obstacles"); diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h index e43e8627e4..4d8611c3c9 100644 --- a/scene/resources/navigation_mesh.h +++ b/scene/resources/navigation_mesh.h @@ -49,7 +49,13 @@ class NavigationMesh : public Resource { Vector3 from; Vector3 to; - bool operator<(const _EdgeKey &p_with) const { return from == p_with.from ? to < p_with.to : from < p_with.from; } + static uint32_t hash(const _EdgeKey &p_key) { + return HashMapHasherDefault::hash(p_key.from) ^ HashMapHasherDefault::hash(p_key.to); + } + + bool operator==(const _EdgeKey &p_with) const { + return HashMapComparatorDefault<Vector3>::compare(from, p_with.from) && HashMapComparatorDefault<Vector3>::compare(to, p_with.to); + } }; protected: diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index d649942188..c7b1981aed 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -53,7 +53,7 @@ static Array _sanitize_node_pinned_properties(Node *p_node) { if (pinned.is_empty()) { return Array(); } - Set<StringName> storable_properties; + RBSet<StringName> storable_properties; p_node->get_storable_properties(storable_properties); int i = 0; do { @@ -106,12 +106,13 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { bool gen_node_path_cache = p_edit_state != GEN_EDIT_STATE_DISABLED && node_path_cache.is_empty(); - Map<Ref<Resource>, Ref<Resource>> resources_local_to_scene; + HashMap<Ref<Resource>, Ref<Resource>> resources_local_to_scene; for (int i = 0; i < nc; i++) { const NodeData &n = nd[i]; Node *parent = nullptr; + String old_parent_path; if (i > 0) { ERR_FAIL_COND_V_MSG(n.parent == -1, nullptr, vformat("Invalid scene: node %s does not specify its parent node.", snames[n.name])); @@ -119,6 +120,8 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { #ifdef DEBUG_ENABLED if (!nparent && (n.parent & FLAG_ID_IS_PATH)) { WARN_PRINT(String("Parent path '" + String(node_paths[n.parent & FLAG_MASK]) + "' for node '" + String(snames[n.name]) + "' has vanished when instancing: '" + get_path() + "'.").ascii().get_data()); + old_parent_path = String(node_paths[n.parent & FLAG_MASK]).trim_prefix("./").replace("/", "@"); + nparent = ret_nodes[0]; } #endif parent = nparent; @@ -254,10 +257,10 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { Ref<Resource> res = value; if (res.is_valid()) { if (res->is_local_to_scene()) { - Map<Ref<Resource>, Ref<Resource>>::Element *E = resources_local_to_scene.find(res); + HashMap<Ref<Resource>, Ref<Resource>>::Iterator E = resources_local_to_scene.find(res); if (E) { - value = E->get(); + value = E->value; } else { Node *base = i == 0 ? node : ret_nodes[0]; @@ -332,6 +335,10 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { } } + if (!old_parent_path.is_empty()) { + node->_set_name_nocheck(old_parent_path + "@" + node->get_name()); + } + if (n.owner >= 0) { NODE_FROM_ID(owner, n.owner); if (owner) { @@ -423,7 +430,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { return ret_nodes[0]; } -static int _nm_get_string(const String &p_string, Map<StringName, int> &name_map) { +static int _nm_get_string(const String &p_string, HashMap<StringName, int> &name_map) { if (name_map.has(p_string)) { return name_map[p_string]; } @@ -443,7 +450,7 @@ static int _vm_get_variant(const Variant &p_variant, HashMap<Variant, int, Varia return idx; } -Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, Map<Node *, int> &node_map, Map<Node *, int> &nodepath_map) { +Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, HashMap<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, HashMap<Node *, int> &node_map, HashMap<Node *, int> &nodepath_map) { // this function handles all the work related to properly packing scenes, be it // instantiated or inherited. // given the complexity of this process, an attempt will be made to properly @@ -665,7 +672,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map return OK; } -Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, Map<Node *, int> &node_map, Map<Node *, int> &nodepath_map) { +Error SceneState::_parse_connections(Node *p_owner, Node *p_node, HashMap<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, HashMap<Node *, int> &node_map, HashMap<Node *, int> &nodepath_map) { if (p_node != p_owner && p_node->get_owner() && p_node->get_owner() != p_owner && !p_owner->is_editable_instance(p_node->get_owner())) { return OK; } @@ -872,10 +879,10 @@ Error SceneState::pack(Node *p_scene) { Node *scene = p_scene; - Map<StringName, int> name_map; + HashMap<StringName, int> name_map; HashMap<Variant, int, VariantHasher, VariantComparator> variant_map; - Map<Node *, int> node_map; - Map<Node *, int> nodepath_map; + HashMap<Node *, int> node_map; + HashMap<Node *, int> nodepath_map; // If using scene inheritance, pack the scene it inherits from. if (scene->get_scene_inherited_state().is_valid()) { @@ -906,10 +913,10 @@ Error SceneState::pack(Node *p_scene) { } variants.resize(variant_map.size()); - const Variant *K = nullptr; - while ((K = variant_map.next(K))) { - int idx = variant_map[*K]; - variants.write[idx] = *K; + + for (const KeyValue<Variant, int> &E : variant_map) { + int idx = E.value; + variants.write[idx] = E.key; } node_paths.resize(nodepath_map.size()); diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index 96222937d0..05abb23284 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -42,7 +42,7 @@ class SceneState : public RefCounted { Vector<NodePath> node_paths; Vector<NodePath> editable_instances; mutable HashMap<NodePath, int> node_path_cache; - mutable Map<int, int> base_scene_node_remap; + mutable HashMap<int, int> base_scene_node_remap; int base_scene_idx = -1; @@ -83,8 +83,8 @@ class SceneState : public RefCounted { Vector<ConnectionData> connections; - Error _parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, Map<Node *, int> &node_map, Map<Node *, int> &nodepath_map); - Error _parse_connections(Node *p_owner, Node *p_node, Map<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, Map<Node *, int> &node_map, Map<Node *, int> &nodepath_map); + Error _parse_node(Node *p_owner, Node *p_node, int p_parent_idx, HashMap<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, HashMap<Node *, int> &node_map, HashMap<Node *, int> &nodepath_map); + Error _parse_connections(Node *p_owner, Node *p_node, HashMap<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, HashMap<Node *, int> &node_map, HashMap<Node *, int> &nodepath_map); String path; @@ -225,7 +225,9 @@ public: virtual void set_path(const String &p_path, bool p_take_over = false) override; #ifdef TOOLS_ENABLED - virtual void set_last_modified_time(uint64_t p_time) override { state->set_last_modified_time(p_time); } + virtual void set_last_modified_time(uint64_t p_time) override { + state->set_last_modified_time(p_time); + } #endif Ref<SceneState> get_state() const; diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 597d070285..587b84a11d 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -34,7 +34,7 @@ Mutex ParticlesMaterial::material_mutex; SelfList<ParticlesMaterial>::List *ParticlesMaterial::dirty_materials = nullptr; -Map<ParticlesMaterial::MaterialKey, ParticlesMaterial::ShaderData> ParticlesMaterial::shader_map; +HashMap<ParticlesMaterial::MaterialKey, ParticlesMaterial::ShaderData, ParticlesMaterial::MaterialKey> ParticlesMaterial::shader_map; ParticlesMaterial::ShaderNames *ParticlesMaterial::shader_names = nullptr; void ParticlesMaterial::init_shaders() { diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index 4c3a3ba16c..24341d964d 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -109,6 +109,14 @@ private: uint32_t key = 0; + static uint32_t hash(const MaterialKey &p_key) { + return hash_djb2_one_32(p_key.key); + } + + bool operator==(const MaterialKey &p_key) const { + return key == p_key.key; + } + bool operator<(const MaterialKey &p_key) const { return key < p_key.key; } @@ -119,7 +127,7 @@ private: int users = 0; }; - static Map<MaterialKey, ShaderData> shader_map; + static HashMap<MaterialKey, ShaderData, MaterialKey> shader_map; MaterialKey current_key; diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index 882afdb43d..155a8522cf 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -34,7 +34,7 @@ bool PolygonPathFinder::_is_point_inside(const Vector2 &p_point) const { int crosses = 0; - for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { + for (RBSet<Edge>::Element *E = edges.front(); E; E = E->next()) { const Edge &e = E->get(); Vector2 a = points[e.points[0]].pos; @@ -105,7 +105,7 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> bool valid = true; - for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { + for (RBSet<Edge>::Element *E = edges.front(); E; E = E->next()) { const Edge &e = E->get(); if (e.points[0] == i || e.points[1] == i || e.points[0] == j || e.points[1] == j) { continue; @@ -137,10 +137,10 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector Edge ignore_to_edge(-1, -1); if (!_is_point_inside(from)) { - float closest_dist = 1e20; + float closest_dist = 1e20f; Vector2 closest_point; - for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { + for (RBSet<Edge>::Element *E = edges.front(); E; E = E->next()) { const Edge &e = E->get(); Vector2 seg[2] = { points[e.points[0]].pos, @@ -161,10 +161,10 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector }; if (!_is_point_inside(to)) { - float closest_dist = 1e20; + float closest_dist = 1e20f; Vector2 closest_point; - for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { + for (RBSet<Edge>::Element *E = edges.front(); E; E = E->next()) { const Edge &e = E->get(); Vector2 seg[2] = { points[e.points[0]].pos, @@ -188,7 +188,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector { bool can_see_eachother = true; - for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { + for (RBSet<Edge>::Element *E = edges.front(); E; E = E->next()) { const Edge &e = E->get(); if (e.points[0] == ignore_from_edge.points[0] && e.points[1] == ignore_from_edge.points[1]) { continue; @@ -240,7 +240,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector valid_b = false; } - for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { + for (RBSet<Edge>::Element *E = edges.front(); E; E = E->next()) { const Edge &e = E->get(); if (e.points[0] == i || e.points[1] == i) { @@ -289,11 +289,11 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector } //solve graph - Set<int> open_list; + RBSet<int> open_list; points.write[aidx].distance = 0; points.write[aidx].prev = aidx; - for (Set<int>::Element *E = points[aidx].connections.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = points[aidx].connections.front(); E; E = E->next()) { open_list.insert(E->get()); points.write[E->get()].distance = from.distance_to(points[E->get()].pos); points.write[E->get()].prev = aidx; @@ -312,7 +312,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector float least_cost = 1e30; //this could be faster (cache previous results) - for (Set<int>::Element *E = open_list.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = open_list.front(); E; E = E->next()) { const Point &p = points[E->get()]; float cost = p.distance; cost += p.pos.distance_to(to); @@ -327,7 +327,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector const Point &np = points[least_cost_point]; //open the neighbours for search - for (Set<int>::Element *E = np.connections.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = np.connections.front(); E; E = E->next()) { Point &p = points.write[E->get()]; float distance = np.pos.distance_to(p.pos) + np.distance; @@ -459,7 +459,7 @@ Dictionary PolygonPathFinder::_get_data() const { { int *cw = c.ptrw(); int idx = 0; - for (Set<int>::Element *E = points[i].connections.front(); E; E = E->next()) { + for (RBSet<int>::Element *E = points[i].connections.front(); E; E = E->next()) { cw[idx++] = E->get(); } } @@ -469,7 +469,7 @@ Dictionary PolygonPathFinder::_get_data() const { { int *iw = ind.ptrw(); int idx = 0; - for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { + for (RBSet<Edge>::Element *E = edges.front(); E; E = E->next()) { iw[idx++] = E->get().points[0]; iw[idx++] = E->get().points[1]; } @@ -489,10 +489,10 @@ bool PolygonPathFinder::is_point_inside(const Vector2 &p_point) const { } Vector2 PolygonPathFinder::get_closest_point(const Vector2 &p_point) const { - float closest_dist = 1e20; + float closest_dist = 1e20f; Vector2 closest_point; - for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { + for (RBSet<Edge>::Element *E = edges.front(); E; E = E->next()) { const Edge &e = E->get(); Vector2 seg[2] = { points[e.points[0]].pos, @@ -508,7 +508,7 @@ Vector2 PolygonPathFinder::get_closest_point(const Vector2 &p_point) const { } } - ERR_FAIL_COND_V(closest_dist == 1e20, Vector2()); + ERR_FAIL_COND_V(Math::is_equal_approx(closest_dist, 1e20f), Vector2()); return closest_point; } @@ -516,7 +516,7 @@ Vector2 PolygonPathFinder::get_closest_point(const Vector2 &p_point) const { Vector<Vector2> PolygonPathFinder::get_intersections(const Vector2 &p_from, const Vector2 &p_to) const { Vector<Vector2> inters; - for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { + for (RBSet<Edge>::Element *E = edges.front(); E; E = E->next()) { Vector2 a = points[E->get().points[0]].pos; Vector2 b = points[E->get().points[1]].pos; diff --git a/scene/resources/polygon_path_finder.h b/scene/resources/polygon_path_finder.h index db96192917..71ad77eb6e 100644 --- a/scene/resources/polygon_path_finder.h +++ b/scene/resources/polygon_path_finder.h @@ -38,7 +38,7 @@ class PolygonPathFinder : public Resource { struct Point { Vector2 pos; - Set<int> connections; + RBSet<int> connections; float distance = 0.0; float penalty = 0.0; int prev = 0; @@ -68,7 +68,7 @@ class PolygonPathFinder : public Resource { Rect2 bounds; Vector<Point> points; - Set<Edge> edges; + RBSet<Edge> edges; bool _is_point_inside(const Vector2 &p_point) const; diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index c9a890194d..3009bdb449 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -29,7 +29,12 @@ /*************************************************************************/ #include "primitive_meshes.h" + +#include "core/core_string_names.h" +#include "scene/resources/theme.h" #include "servers/rendering_server.h" +#include "thirdparty/misc/clipper.hpp" +#include "thirdparty/misc/polypartition.h" /** PrimitiveMesh @@ -2151,3 +2156,819 @@ void RibbonTrailMesh::_bind_methods() { RibbonTrailMesh::RibbonTrailMesh() { } + +/*************************************************************************/ +/* TextMesh */ +/*************************************************************************/ + +void TextMesh::_generate_glyph_mesh_data(uint32_t p_hash, const Glyph &p_gl) const { + if (cache.has(p_hash)) { + return; + } + + GlyphMeshData &gl_data = cache[p_hash]; + + Dictionary d = TS->font_get_glyph_contours(p_gl.font_rid, p_gl.font_size, p_gl.index); + Vector2 origin = Vector2(p_gl.x_off, p_gl.y_off) * pixel_size; + + PackedVector3Array points = d["points"]; + PackedInt32Array contours = d["contours"]; + bool orientation = d["orientation"]; + + if (points.size() < 3 || contours.size() < 1) { + return; // No full contours, only glyph control points (or nothing), ignore. + } + + // Approximate Bezier curves as polygons. + // See https://freetype.org/freetype2/docs/glyphs/glyphs-6.html, for more info. + for (int i = 0; i < contours.size(); i++) { + int32_t start = (i == 0) ? 0 : (contours[i - 1] + 1); + int32_t end = contours[i]; + Vector<ContourPoint> polygon; + + for (int32_t j = start; j <= end; j++) { + if (points[j].z == TextServer::CONTOUR_CURVE_TAG_ON) { + // Point on the curve. + Vector2 p = Vector2(points[j].x, points[j].y) * pixel_size + origin; + polygon.push_back(ContourPoint(p, true)); + } else if (points[j].z == TextServer::CONTOUR_CURVE_TAG_OFF_CONIC) { + // Conic Bezier arc. + int32_t next = (j == end) ? start : (j + 1); + int32_t prev = (j == start) ? end : (j - 1); + Vector2 p0; + Vector2 p1 = Vector2(points[j].x, points[j].y); + Vector2 p2; + + // For successive conic OFF points add a virtual ON point in the middle. + if (points[prev].z == TextServer::CONTOUR_CURVE_TAG_OFF_CONIC) { + p0 = (Vector2(points[prev].x, points[prev].y) + Vector2(points[j].x, points[j].y)) / 2.0; + } else if (points[prev].z == TextServer::CONTOUR_CURVE_TAG_ON) { + p0 = Vector2(points[prev].x, points[prev].y); + } else { + ERR_FAIL_MSG(vformat("Invalid conic arc point sequence at %d:%d", i, j)); + } + if (points[next].z == TextServer::CONTOUR_CURVE_TAG_OFF_CONIC) { + p2 = (Vector2(points[j].x, points[j].y) + Vector2(points[next].x, points[next].y)) / 2.0; + } else if (points[next].z == TextServer::CONTOUR_CURVE_TAG_ON) { + p2 = Vector2(points[next].x, points[next].y); + } else { + ERR_FAIL_MSG(vformat("Invalid conic arc point sequence at %d:%d", i, j)); + } + + real_t step = CLAMP(curve_step / (p0 - p2).length(), 0.01, 0.5); + real_t t = step; + while (t < 1.0) { + real_t omt = (1.0 - t); + real_t omt2 = omt * omt; + real_t t2 = t * t; + + Vector2 point = p1 + omt2 * (p0 - p1) + t2 * (p2 - p1); + Vector2 p = point * pixel_size + origin; + polygon.push_back(ContourPoint(p, false)); + t += step; + } + } else if (points[j].z == TextServer::CONTOUR_CURVE_TAG_OFF_CUBIC) { + // Cubic Bezier arc. + int32_t next1 = (j == end) ? start : (j + 1); + int32_t next2 = (next1 == end) ? start : (next1 + 1); + int32_t prev = (j == start) ? end : (j - 1); + + // There must be exactly two OFF points and two ON points for each cubic arc. + ERR_FAIL_COND_MSG(points[prev].z != TextServer::CONTOUR_CURVE_TAG_ON, vformat("Invalid cubic arc point sequence at %d:%d", i, prev)); + ERR_FAIL_COND_MSG(points[next1].z != TextServer::CONTOUR_CURVE_TAG_OFF_CUBIC, vformat("Invalid cubic arc point sequence at %d:%d", i, next1)); + ERR_FAIL_COND_MSG(points[next2].z != TextServer::CONTOUR_CURVE_TAG_ON, vformat("Invalid cubic arc point sequence at %d:%d", i, next2)); + + Vector2 p0 = Vector2(points[prev].x, points[prev].y); + Vector2 p1 = Vector2(points[j].x, points[j].y); + Vector2 p2 = Vector2(points[next1].x, points[next1].y); + Vector2 p3 = Vector2(points[next2].x, points[next2].y); + + real_t step = CLAMP(curve_step / (p0 - p3).length(), 0.01, 0.5); + real_t t = step; + while (t < 1.0) { + real_t omt = (1.0 - t); + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + real_t t3 = t2 * t; + + Vector2 point = p0 * omt3 + p1 * omt2 * t * 3.0 + p2 * omt * t2 * 3.0 + p3 * t3; + Vector2 p = point * pixel_size + origin; + polygon.push_back(ContourPoint(p, false)); + t += step; + } + i++; + } else { + ERR_FAIL_MSG(vformat("Unknown point tag at %d:%d", i, j)); + } + } + + if (polygon.size() < 3) { + continue; // Skip glyph control points. + } + + if (!orientation) { + polygon.reverse(); + } + + gl_data.contours.push_back(polygon); + } + + // Calculate bounds. + List<TPPLPoly> in_poly; + for (int i = 0; i < gl_data.contours.size(); i++) { + TPPLPoly inp; + inp.Init(gl_data.contours[i].size()); + real_t length = 0.0; + for (int j = 0; j < gl_data.contours[i].size(); j++) { + int next = (j + 1 == gl_data.contours[i].size()) ? 0 : (j + 1); + + gl_data.min_p.x = MIN(gl_data.min_p.x, gl_data.contours[i][j].point.x); + gl_data.min_p.y = MIN(gl_data.min_p.y, gl_data.contours[i][j].point.y); + gl_data.max_p.x = MAX(gl_data.max_p.x, gl_data.contours[i][j].point.x); + gl_data.max_p.y = MAX(gl_data.max_p.y, gl_data.contours[i][j].point.y); + length += (gl_data.contours[i][next].point - gl_data.contours[i][j].point).length(); + + inp.GetPoint(j) = gl_data.contours[i][j].point; + } + TPPLOrientation poly_orient = inp.GetOrientation(); + if (poly_orient == TPPL_ORIENTATION_CW) { + inp.SetHole(true); + } + in_poly.push_back(inp); + gl_data.contours_info.push_back(ContourInfo(length, poly_orient == TPPL_ORIENTATION_CCW)); + } + + TPPLPartition tpart; + + //Decompose and triangulate. + List<TPPLPoly> out_poly; + if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { + ERR_FAIL_MSG("Convex decomposing failed!"); + } + List<TPPLPoly> out_tris; + for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) { + if (tpart.Triangulate_OPT(&(I->get()), &out_tris) == 0) { + ERR_FAIL_MSG("Triangulation failed!"); + } + } + + for (List<TPPLPoly>::Element *I = out_tris.front(); I; I = I->next()) { + TPPLPoly &tp = I->get(); + ERR_FAIL_COND(tp.GetNumPoints() != 3); // Trianges only. + + for (int i = 0; i < 3; i++) { + gl_data.triangles.push_back(Vector2(tp.GetPoint(i).x, tp.GetPoint(i).y)); + } + } +} + +void TextMesh::_create_mesh_array(Array &p_arr) const { + Ref<Font> font = _get_font_or_default(); + ERR_FAIL_COND(font.is_null()); + + if (dirty_cache) { + cache.clear(); + dirty_cache = false; + } + + // Update text buffer. + if (dirty_text) { + TS->shaped_text_clear(text_rid); + TS->shaped_text_set_direction(text_rid, text_direction); + + String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text; + TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, language); + + Array stt; + if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) { + GDVIRTUAL_CALL(_structured_text_parser, st_args, text, stt); + } else { + stt = TS->parse_structured_text(st_parser, st_args, text); + } + TS->shaped_text_set_bidi_override(text_rid, stt); + + dirty_text = false; + dirty_font = false; + } else if (dirty_font) { + int spans = TS->shaped_get_span_count(text_rid); + for (int i = 0; i < spans; i++) { + TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, opentype_features); + } + + dirty_font = false; + } + if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { + TS->shaped_text_fit_to_width(text_rid, width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); + } else { + TS->shaped_text_fit_to_width(text_rid, -1, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); + } + + Vector2 offset; + const Glyph *glyphs = TS->shaped_text_get_glyphs(text_rid); + int gl_size = TS->shaped_text_get_glyph_count(text_rid); + float line_width = TS->shaped_text_get_width(text_rid) * pixel_size; + + switch (horizontal_alignment) { + case HORIZONTAL_ALIGNMENT_LEFT: + offset.x = 0.0; + break; + case HORIZONTAL_ALIGNMENT_FILL: + case HORIZONTAL_ALIGNMENT_CENTER: { + offset.x = -line_width / 2.0; + } break; + case HORIZONTAL_ALIGNMENT_RIGHT: { + offset.x = -line_width; + } break; + } + + bool has_depth = !Math::is_zero_approx(depth); + + // Generate glyph data, precalculate size of the arrays and mesh bounds for UV. + int64_t p_size = 0; + int64_t i_size = 0; + + Vector2 min_p = Vector2(INFINITY, INFINITY); + Vector2 max_p = Vector2(-INFINITY, -INFINITY); + + Vector2 offset_pre = offset; + for (int i = 0; i < gl_size; i++) { + if (glyphs[i].font_rid != RID()) { + uint32_t hash = hash_one_uint64(glyphs[i].font_rid.get_id()); + hash = hash_djb2_one_32(glyphs[i].index, hash); + + _generate_glyph_mesh_data(hash, glyphs[i]); + GlyphMeshData &gl_data = cache[hash]; + + p_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); + i_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); + + if (has_depth) { + for (int j = 0; j < gl_data.contours.size(); j++) { + p_size += glyphs[i].repeat * gl_data.contours[j].size() * 4; + i_size += glyphs[i].repeat * gl_data.contours[j].size() * 6; + } + } + + for (int j = 0; j < glyphs[i].repeat; j++) { + min_p.x = MIN(gl_data.min_p.x + offset_pre.x, min_p.x); + min_p.y = MIN(gl_data.min_p.y + offset_pre.y, min_p.y); + max_p.x = MAX(gl_data.max_p.x + offset_pre.x, max_p.x); + max_p.y = MAX(gl_data.max_p.y + offset_pre.y, max_p.y); + + offset_pre.x += glyphs[i].advance * pixel_size; + } + } else { + p_size += glyphs[i].repeat * 4; + i_size += glyphs[i].repeat * 6; + + offset_pre.x += glyphs[i].advance * pixel_size * glyphs[i].repeat; + } + } + + Vector<Vector3> vertices; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int32_t> indices; + + vertices.resize(p_size); + normals.resize(p_size); + uvs.resize(p_size); + tangents.resize(p_size * 4); + indices.resize(i_size); + + Vector3 *vertices_ptr = vertices.ptrw(); + Vector3 *normals_ptr = normals.ptrw(); + float *tangents_ptr = tangents.ptrw(); + Vector2 *uvs_ptr = uvs.ptrw(); + int32_t *indices_ptr = indices.ptrw(); + + // Generate mesh. + int32_t p_idx = 0; + int32_t i_idx = 0; + for (int i = 0; i < gl_size; i++) { + if (glyphs[i].font_rid != RID()) { + uint32_t hash = hash_one_uint64(glyphs[i].font_rid.get_id()); + hash = hash_djb2_one_32(glyphs[i].index, hash); + + const GlyphMeshData &gl_data = cache[hash]; + + int64_t ts = gl_data.triangles.size(); + const Vector2 *ts_ptr = gl_data.triangles.ptr(); + + for (int j = 0; j < glyphs[i].repeat; j++) { + for (int k = 0; k < ts; k += 3) { + // Add front face. + for (int l = 0; l < 3; l++) { + Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, depth / 2.0); + vertices_ptr[p_idx] = point; + normals_ptr[p_idx] = Vector3(0.0, 0.0, 1.0); + if (has_depth) { + uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.0), real_t(0.4))); + } else { + uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.0), real_t(1.0))); + } + tangents_ptr[p_idx * 4 + 0] = 1.0; + tangents_ptr[p_idx * 4 + 1] = 0.0; + tangents_ptr[p_idx * 4 + 2] = 0.0; + tangents_ptr[p_idx * 4 + 3] = 1.0; + indices_ptr[i_idx++] = p_idx; + p_idx++; + } + if (has_depth) { + // Add back face. + for (int l = 2; l >= 0; l--) { + Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, -depth / 2.0); + vertices_ptr[p_idx] = point; + normals_ptr[p_idx] = Vector3(0.0, 0.0, -1.0); + uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.4), real_t(0.8))); + tangents_ptr[p_idx * 4 + 0] = -1.0; + tangents_ptr[p_idx * 4 + 1] = 0.0; + tangents_ptr[p_idx * 4 + 2] = 0.0; + tangents_ptr[p_idx * 4 + 3] = 1.0; + indices_ptr[i_idx++] = p_idx; + p_idx++; + } + } + } + // Add sides. + if (has_depth) { + for (int k = 0; k < gl_data.contours.size(); k++) { + int64_t ps = gl_data.contours[k].size(); + const ContourPoint *ps_ptr = gl_data.contours[k].ptr(); + const ContourInfo &ps_info = gl_data.contours_info[k]; + real_t length = 0.0; + for (int l = 0; l < ps; l++) { + int prev = (l == 0) ? (ps - 1) : (l - 1); + int next = (l + 1 == ps) ? 0 : (l + 1); + Vector2 d1; + Vector2 d2 = (ps_ptr[next].point - ps_ptr[l].point).normalized(); + if (ps_ptr[l].sharp) { + d1 = d2; + } else { + d1 = (ps_ptr[l].point - ps_ptr[prev].point).normalized(); + } + real_t seg_len = (ps_ptr[next].point - ps_ptr[l].point).length(); + + Vector3 quad_faces[4] = { + Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, -depth / 2.0), + Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, -depth / 2.0), + Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, depth / 2.0), + Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, depth / 2.0), + }; + for (int m = 0; m < 4; m++) { + const Vector2 &d = ((m % 2) == 0) ? d1 : d2; + real_t u_pos = ((m % 2) == 0) ? length : length + seg_len; + vertices_ptr[p_idx + m] = quad_faces[m]; + normals_ptr[p_idx + m] = Vector3(d.y, d.x, 0.0); + if (m < 2) { + uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.8 : 0.9); + } else { + uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.9 : 1.0); + } + tangents_ptr[(p_idx + m) * 4 + 0] = d.x; + tangents_ptr[(p_idx + m) * 4 + 1] = -d.y; + tangents_ptr[(p_idx + m) * 4 + 2] = 0.0; + tangents_ptr[(p_idx + m) * 4 + 3] = 1.0; + } + + indices_ptr[i_idx++] = p_idx; + indices_ptr[i_idx++] = p_idx + 1; + indices_ptr[i_idx++] = p_idx + 2; + + indices_ptr[i_idx++] = p_idx + 1; + indices_ptr[i_idx++] = p_idx + 3; + indices_ptr[i_idx++] = p_idx + 2; + + length += seg_len; + p_idx += 4; + } + } + } + offset.x += glyphs[i].advance * pixel_size; + } + } else { + // Add fallback quad for missing glyphs. + for (int j = 0; j < glyphs[i].repeat; j++) { + Size2 sz = TS->get_hex_code_box_size(glyphs[i].font_size, glyphs[i].index) * pixel_size; + Vector3 quad_faces[4] = { + Vector3(offset.x, offset.y, 0.0), + Vector3(offset.x, sz.y + offset.y, 0.0), + Vector3(sz.x + offset.x, sz.y + offset.y, 0.0), + Vector3(sz.x + offset.x, offset.y, 0.0), + }; + for (int k = 0; k < 4; k++) { + vertices_ptr[p_idx + k] = quad_faces[k]; + normals_ptr[p_idx + k] = Vector3(0.0, 0.0, 1.0); + if (has_depth) { + uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -min_p.y, -max_p.y, real_t(0.0), real_t(0.4))); + } else { + uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -min_p.y, -max_p.y, real_t(0.0), real_t(1.0))); + } + tangents_ptr[(p_idx + k) * 4 + 0] = 1.0; + tangents_ptr[(p_idx + k) * 4 + 1] = 0.0; + tangents_ptr[(p_idx + k) * 4 + 2] = 0.0; + tangents_ptr[(p_idx + k) * 4 + 3] = 1.0; + } + + indices_ptr[i_idx++] = p_idx; + indices_ptr[i_idx++] = p_idx + 1; + indices_ptr[i_idx++] = p_idx + 2; + + indices_ptr[i_idx++] = p_idx + 0; + indices_ptr[i_idx++] = p_idx + 2; + indices_ptr[i_idx++] = p_idx + 3; + p_idx += 4; + + offset.x += glyphs[i].advance * pixel_size; + } + } + } + + if (p_size == 0) { + // If empty, add single trinagle to suppress errors. + vertices.push_back(Vector3()); + normals.push_back(Vector3()); + uvs.push_back(Vector2()); + tangents.push_back(1.0); + tangents.push_back(0.0); + tangents.push_back(0.0); + tangents.push_back(1.0); + indices.push_back(0); + indices.push_back(0); + indices.push_back(0); + } + + p_arr[RS::ARRAY_VERTEX] = vertices; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; +} + +void TextMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &TextMesh::set_horizontal_alignment); + ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &TextMesh::get_horizontal_alignment); + + ClassDB::bind_method(D_METHOD("set_text", "text"), &TextMesh::set_text); + ClassDB::bind_method(D_METHOD("get_text"), &TextMesh::get_text); + + ClassDB::bind_method(D_METHOD("set_font", "font"), &TextMesh::set_font); + ClassDB::bind_method(D_METHOD("get_font"), &TextMesh::get_font); + + ClassDB::bind_method(D_METHOD("set_font_size", "font_size"), &TextMesh::set_font_size); + ClassDB::bind_method(D_METHOD("get_font_size"), &TextMesh::get_font_size); + + ClassDB::bind_method(D_METHOD("set_depth", "depth"), &TextMesh::set_depth); + ClassDB::bind_method(D_METHOD("get_depth"), &TextMesh::get_depth); + + ClassDB::bind_method(D_METHOD("set_width", "width"), &TextMesh::set_width); + ClassDB::bind_method(D_METHOD("get_width"), &TextMesh::get_width); + + ClassDB::bind_method(D_METHOD("set_pixel_size", "pixel_size"), &TextMesh::set_pixel_size); + ClassDB::bind_method(D_METHOD("get_pixel_size"), &TextMesh::get_pixel_size); + + ClassDB::bind_method(D_METHOD("set_curve_step", "curve_step"), &TextMesh::set_curve_step); + ClassDB::bind_method(D_METHOD("get_curve_step"), &TextMesh::get_curve_step); + + ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &TextMesh::set_text_direction); + ClassDB::bind_method(D_METHOD("get_text_direction"), &TextMesh::get_text_direction); + + ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &TextMesh::set_opentype_feature); + ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &TextMesh::get_opentype_feature); + ClassDB::bind_method(D_METHOD("clear_opentype_features"), &TextMesh::clear_opentype_features); + + ClassDB::bind_method(D_METHOD("set_language", "language"), &TextMesh::set_language); + ClassDB::bind_method(D_METHOD("get_language"), &TextMesh::get_language); + + ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &TextMesh::set_structured_text_bidi_override); + ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override"), &TextMesh::get_structured_text_bidi_override); + + ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override_options", "args"), &TextMesh::set_structured_text_bidi_override_options); + ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override_options"), &TextMesh::get_structured_text_bidi_override_options); + + ClassDB::bind_method(D_METHOD("set_uppercase", "enable"), &TextMesh::set_uppercase); + ClassDB::bind_method(D_METHOD("is_uppercase"), &TextMesh::is_uppercase); + + ClassDB::bind_method(D_METHOD("_font_changed"), &TextMesh::_font_changed); + ClassDB::bind_method(D_METHOD("_request_update"), &TextMesh::_request_update); + + ADD_GROUP("Text", ""); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1"), "set_font_size", "get_font_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options"); + + ADD_GROUP("Mesh", ""); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "curve_step", PROPERTY_HINT_RANGE, "0.1,10,0.1"), "set_curve_step", "get_curve_step"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater"), "set_depth", "get_depth"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width"), "set_width", "get_width"); + + ADD_GROUP("Locale", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); +} + +void TextMesh::_notification(int p_what) { + switch (p_what) { + case MainLoop::NOTIFICATION_TRANSLATION_CHANGED: { + String new_text = tr(text); + if (new_text == xl_text) { + return; // Nothing new. + } + xl_text = new_text; + dirty_text = true; + _request_update(); + } break; + } +} + +bool TextMesh::_set(const StringName &p_name, const Variant &p_value) { + String str = p_name; + if (str.begins_with("opentype_features/")) { + String name = str.get_slicec('/', 1); + int32_t tag = TS->name_to_tag(name); + int value = p_value; + if (value == -1) { + if (opentype_features.has(tag)) { + opentype_features.erase(tag); + dirty_font = true; + _request_update(); + } + } else { + if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) { + opentype_features[tag] = value; + dirty_font = true; + _request_update(); + } + } + notify_property_list_changed(); + return true; + } + + return false; +} + +bool TextMesh::_get(const StringName &p_name, Variant &r_ret) const { + String str = p_name; + if (str.begins_with("opentype_features/")) { + String name = str.get_slicec('/', 1); + int32_t tag = TS->name_to_tag(name); + if (opentype_features.has(tag)) { + r_ret = opentype_features[tag]; + return true; + } else { + r_ret = -1; + return true; + } + } + return false; +} + +void TextMesh::_get_property_list(List<PropertyInfo> *p_list) const { + for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) { + String name = TS->tag_to_name(*ftr); + p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name)); + } + p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); +} + +TextMesh::TextMesh() { + primitive_type = PRIMITIVE_TRIANGLES; + text_rid = TS->create_shaped_text(); +} + +TextMesh::~TextMesh() { + TS->free_rid(text_rid); +} + +void TextMesh::set_horizontal_alignment(HorizontalAlignment p_alignment) { + ERR_FAIL_INDEX((int)p_alignment, 4); + if (horizontal_alignment != p_alignment) { + horizontal_alignment = p_alignment; + _request_update(); + } +} + +HorizontalAlignment TextMesh::get_horizontal_alignment() const { + return horizontal_alignment; +} + +void TextMesh::set_text(const String &p_string) { + if (text != p_string) { + text = p_string; + xl_text = tr(text); + dirty_text = true; + _request_update(); + } +} + +String TextMesh::get_text() const { + return text; +} + +void TextMesh::_font_changed() { + dirty_font = true; + dirty_cache = true; + call_deferred(SNAME("_request_update")); +} + +void TextMesh::set_font(const Ref<Font> &p_font) { + if (font_override != p_font) { + if (font_override.is_valid()) { + font_override->disconnect(CoreStringNames::get_singleton()->changed, Callable(this, "_font_changed")); + } + font_override = p_font; + dirty_font = true; + dirty_cache = true; + if (font_override.is_valid()) { + font_override->connect(CoreStringNames::get_singleton()->changed, Callable(this, "_font_changed")); + } + _request_update(); + } +} + +Ref<Font> TextMesh::get_font() const { + return font_override; +} + +Ref<Font> TextMesh::_get_font_or_default() const { + if (font_override.is_valid() && font_override->get_data_count() > 0) { + return font_override; + } + + // Check the project-defined Theme resource. + if (Theme::get_project_default().is_valid()) { + List<StringName> theme_types; + Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); + + for (const StringName &E : theme_types) { + if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { + return Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); + } + } + } + + // Lastly, fall back on the items defined in the default Theme, if they exist. + { + List<StringName> theme_types; + Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); + + for (const StringName &E : theme_types) { + if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { + return Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); + } + } + } + + // If they don't exist, use any type to return the default/empty value. + return Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName()); +} + +void TextMesh::set_font_size(int p_size) { + if (font_size != p_size) { + font_size = CLAMP(p_size, 1, 127); + dirty_font = true; + dirty_cache = true; + _request_update(); + } +} + +int TextMesh::get_font_size() const { + return font_size; +} + +void TextMesh::set_depth(real_t p_depth) { + if (depth != p_depth) { + depth = MAX(p_depth, 0.0); + _request_update(); + } +} + +real_t TextMesh::get_depth() const { + return depth; +} + +void TextMesh::set_width(real_t p_width) { + if (width != p_width) { + width = p_width; + _request_update(); + } +} + +real_t TextMesh::get_width() const { + return width; +} + +void TextMesh::set_pixel_size(real_t p_amount) { + if (pixel_size != p_amount) { + pixel_size = CLAMP(p_amount, 0.0001, 128.0); + dirty_cache = true; + _request_update(); + } +} + +real_t TextMesh::get_pixel_size() const { + return pixel_size; +} + +void TextMesh::set_curve_step(real_t p_step) { + if (curve_step != p_step) { + curve_step = CLAMP(p_step, 0.1, 10.0); + dirty_cache = true; + _request_update(); + } +} + +real_t TextMesh::get_curve_step() const { + return curve_step; +} + +void TextMesh::set_text_direction(TextServer::Direction p_text_direction) { + ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3); + if (text_direction != p_text_direction) { + text_direction = p_text_direction; + dirty_text = true; + _request_update(); + } +} + +TextServer::Direction TextMesh::get_text_direction() const { + return text_direction; +} + +void TextMesh::clear_opentype_features() { + opentype_features.clear(); + dirty_font = true; + _request_update(); +} + +void TextMesh::set_opentype_feature(const String &p_name, int p_value) { + int32_t tag = TS->name_to_tag(p_name); + if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) { + opentype_features[tag] = p_value; + dirty_font = true; + _request_update(); + } +} + +int TextMesh::get_opentype_feature(const String &p_name) const { + int32_t tag = TS->name_to_tag(p_name); + if (!opentype_features.has(tag)) { + return -1; + } + return opentype_features[tag]; +} + +void TextMesh::set_language(const String &p_language) { + if (language != p_language) { + language = p_language; + dirty_text = true; + _request_update(); + } +} + +String TextMesh::get_language() const { + return language; +} + +void TextMesh::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) { + if (st_parser != p_parser) { + st_parser = p_parser; + dirty_text = true; + _request_update(); + } +} + +TextServer::StructuredTextParser TextMesh::get_structured_text_bidi_override() const { + return st_parser; +} + +void TextMesh::set_structured_text_bidi_override_options(Array p_args) { + if (st_args != p_args) { + st_args = p_args; + dirty_text = true; + _request_update(); + } +} + +Array TextMesh::get_structured_text_bidi_override_options() const { + return st_args; +} + +void TextMesh::set_uppercase(bool p_uppercase) { + if (uppercase != p_uppercase) { + uppercase = p_uppercase; + dirty_text = true; + _request_update(); + } +} + +bool TextMesh::is_uppercase() const { + return uppercase; +} diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 6b0d5993a1..3849c92a7b 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -31,7 +31,9 @@ #ifndef PRIMITIVE_MESHES_H #define PRIMITIVE_MESHES_H +#include "scene/resources/font.h" #include "scene/resources/mesh.h" +#include "servers/text_server.h" ///@TODO probably should change a few integers to unsigned integers... @@ -447,5 +449,129 @@ public: RibbonTrailMesh(); }; +/** + Text... +*/ + +class TextMesh : public PrimitiveMesh { + GDCLASS(TextMesh, PrimitiveMesh); + +private: + struct ContourPoint { + Vector2 point; + bool sharp = false; + + ContourPoint(){}; + ContourPoint(const Vector2 &p_pt, bool p_sharp) { + point = p_pt; + sharp = p_sharp; + }; + }; + struct ContourInfo { + real_t length = 0.0; + bool ccw = true; + ContourInfo(){}; + ContourInfo(real_t p_len, bool p_ccw) { + length = p_len; + ccw = p_ccw; + } + }; + struct GlyphMeshData { + Vector<Vector2> triangles; + Vector<Vector<ContourPoint>> contours; + Vector<ContourInfo> contours_info; + Vector2 min_p = Vector2(INFINITY, INFINITY); + Vector2 max_p = Vector2(-INFINITY, -INFINITY); + }; + mutable HashMap<uint32_t, GlyphMeshData> cache; + + RID text_rid; + String text; + String xl_text; + + int font_size = 16; + Ref<Font> font_override; + float width = 500.0; + + HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER; + bool uppercase = false; + Dictionary opentype_features; + String language; + TextServer::Direction text_direction = TextServer::DIRECTION_AUTO; + TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; + Array st_args; + + real_t depth = 0.05; + real_t pixel_size = 0.01; + real_t curve_step = 0.5; + + mutable bool dirty_text = true; + mutable bool dirty_font = true; + mutable bool dirty_cache = true; + + void _generate_glyph_mesh_data(uint32_t p_hash, const Glyph &p_glyph) const; + void _font_changed(); + +protected: + static void _bind_methods(); + void _notification(int p_what); + + virtual void _create_mesh_array(Array &p_arr) const override; + + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + +public: + GDVIRTUAL2RC(Array, _structured_text_parser, Array, String) + + TextMesh(); + ~TextMesh(); + + void set_horizontal_alignment(HorizontalAlignment p_alignment); + HorizontalAlignment get_horizontal_alignment() const; + + void set_text(const String &p_string); + String get_text() const; + + void set_font(const Ref<Font> &p_font); + Ref<Font> get_font() const; + Ref<Font> _get_font_or_default() const; + + void set_font_size(int p_size); + int get_font_size() const; + + void set_text_direction(TextServer::Direction p_text_direction); + TextServer::Direction get_text_direction() const; + + void set_opentype_feature(const String &p_name, int p_value); + int get_opentype_feature(const String &p_name) const; + void clear_opentype_features(); + + void set_language(const String &p_language); + String get_language() const; + + void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser); + TextServer::StructuredTextParser get_structured_text_bidi_override() const; + + void set_structured_text_bidi_override_options(Array p_args); + Array get_structured_text_bidi_override_options() const; + + void set_uppercase(bool p_uppercase); + bool is_uppercase() const; + + void set_width(real_t p_width); + real_t get_width() const; + + void set_depth(real_t p_depth); + real_t get_depth() const; + + void set_curve_step(real_t p_step); + real_t get_curve_step() const; + + void set_pixel_size(real_t p_amount); + real_t get_pixel_size() const; +}; + VARIANT_ENUM_CAST(RibbonTrailMesh::Shape) #endif diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index ae321fd9a7..193bd0ac05 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -867,7 +867,7 @@ void ResourceLoaderText::get_dependencies(Ref<FileAccess> p_f, List<String> *p_d } } -Error ResourceLoaderText::rename_dependencies(Ref<FileAccess> p_f, const String &p_path, const Map<String, String> &p_map) { +Error ResourceLoaderText::rename_dependencies(Ref<FileAccess> p_f, const String &p_path, const HashMap<String, String> &p_map) { open(p_f, true); ERR_FAIL_COND_V(error != OK, error); ignore_resource_parsing = true; @@ -1232,7 +1232,7 @@ Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_pa } if (!assign.is_empty()) { - Map<StringName, int> empty_string_map; //unused + HashMap<StringName, int> empty_string_map; //unused bs_save_unicode_string(wf2, assign, true); ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map); prop_count++; @@ -1293,7 +1293,7 @@ Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_pa String name = E.name; Variant value = packed_scene->get(name); - Map<StringName, int> empty_string_map; //unused + HashMap<StringName, int> empty_string_map; //unused bs_save_unicode_string(wf2, name, true); ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map); prop_count++; @@ -1507,7 +1507,7 @@ void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<Strin loader.get_dependencies(f, p_dependencies, p_add_types); } -Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { +Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) { Error err = OK; { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); @@ -1737,7 +1737,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso #ifdef TOOLS_ENABLED // Keep order from cached ids. - Set<String> cached_ids_found; + RBSet<String> cached_ids_found; for (KeyValue<Ref<Resource>, String> &E : external_resources) { String cached_id = E.key->get_id_for_path(local_path); if (cached_id.is_empty() || cached_ids_found.has(cached_id)) { @@ -1809,7 +1809,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso f->store_line(String()); // Separate. } - Set<String> used_unique_ids; + RBSet<String> used_unique_ids; for (List<Ref<Resource>>::Element *E = saved_resources.front(); E; E = E->next()) { Ref<Resource> res = E->get(); diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h index e67df72d7e..adab503599 100644 --- a/scene/resources/resource_format_text.h +++ b/scene/resources/resource_format_text.h @@ -58,8 +58,8 @@ class ResourceLoaderText { bool ignore_resource_parsing = false; - Map<String, ExtResource> ext_resources; - Map<String, Ref<Resource>> int_resources; + HashMap<String, ExtResource> ext_resources; + HashMap<String, Ref<Resource>> int_resources; int resources_total = 0; int resource_current = 0; @@ -76,7 +76,7 @@ class ResourceLoaderText { ResourceUID::ID res_uid = ResourceUID::INVALID_ID; - Map<String, String> remaps; + HashMap<String, String> remaps; static Error _parse_sub_resources(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return reinterpret_cast<ResourceLoaderText *>(p_self)->_parse_sub_resource(p_stream, r_res, line, r_err_str); } static Error _parse_ext_resources(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return reinterpret_cast<ResourceLoaderText *>(p_self)->_parse_ext_resource(p_stream, r_res, line, r_err_str); } @@ -90,10 +90,10 @@ class ResourceLoaderText { }; struct DummyReadData { - Map<Ref<Resource>, int> external_resources; - Map<String, Ref<Resource>> rev_external_resources; - Map<Ref<Resource>, int> resource_index_map; - Map<String, Ref<Resource>> resource_map; + HashMap<Ref<Resource>, int> external_resources; + HashMap<String, Ref<Resource>> rev_external_resources; + HashMap<Ref<Resource>, int> resource_index_map; + HashMap<String, Ref<Resource>> resource_map; }; static Error _parse_sub_resource_dummys(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return _parse_sub_resource_dummy(static_cast<DummyReadData *>(p_self), p_stream, r_res, line, r_err_str); } @@ -124,7 +124,7 @@ public: String recognize(Ref<FileAccess> p_f); ResourceUID::ID get_uid(Ref<FileAccess> p_f); void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types); - Error rename_dependencies(Ref<FileAccess> p_f, const String &p_path, const Map<String, String> &p_map); + Error rename_dependencies(Ref<FileAccess> p_f, const String &p_path, const HashMap<String, String> &p_map); Error save_as_binary(Ref<FileAccess> p_f, const String &p_path); ResourceLoaderText(); @@ -140,7 +140,7 @@ public: virtual String get_resource_type(const String &p_path) const; virtual ResourceUID::ID get_resource_uid(const String &p_path) const; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); - virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map); + virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map); static Error convert_file_to_binary(const String &p_src_path, const String &p_dst_path); @@ -163,12 +163,12 @@ class ResourceFormatSaverTextInstance { bool operator<(const NonPersistentKey &p_key) const { return base == p_key.base ? property < p_key.property : base < p_key.base; } }; - Map<NonPersistentKey, Ref<Resource>> non_persistent_map; + RBMap<NonPersistentKey, Ref<Resource>> non_persistent_map; - Set<Ref<Resource>> resource_set; + RBSet<Ref<Resource>> resource_set; List<Ref<Resource>> saved_resources; - Map<Ref<Resource>, String> external_resources; - Map<Ref<Resource>, String> internal_resources; + HashMap<Ref<Resource>, String> external_resources; + HashMap<Ref<Resource>, String> internal_resources; struct ResourceSort { Ref<Resource> resource; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 6b1f89454f..d49157b1b8 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -100,7 +100,7 @@ RID Shader::get_rid() const { void Shader::set_default_texture_param(const StringName &p_param, const Ref<Texture2D> &p_texture, int p_index) { if (p_texture.is_valid()) { if (!default_textures.has(p_param)) { - default_textures[p_param] = Map<int, Ref<Texture2D>>(); + default_textures[p_param] = HashMap<int, Ref<Texture2D>>(); } default_textures[p_param][p_index] = p_texture; RS::get_singleton()->shader_set_default_texture_param(shader, p_param, p_texture->get_rid(), p_index); @@ -126,7 +126,7 @@ Ref<Texture2D> Shader::get_default_texture_param(const StringName &p_param, int } void Shader::get_default_texture_param_list(List<StringName> *r_textures) const { - for (const KeyValue<StringName, Map<int, Ref<Texture2D>>> &E : default_textures) { + for (const KeyValue<StringName, HashMap<int, Ref<Texture2D>>> &E : default_textures) { r_textures->push_back(E.key); } } diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 3212dcd287..11c9f60ce8 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -58,8 +58,8 @@ private: // shaders keep a list of ShaderMaterial -> RenderingServer name translations, to make // conversion fast and save memory. mutable bool params_cache_dirty = true; - mutable Map<StringName, StringName> params_cache; //map a shader param to a material param.. - Map<StringName, Map<int, Ref<Texture2D>>> default_textures; + mutable HashMap<StringName, StringName> params_cache; //map a shader param to a material param.. + HashMap<StringName, HashMap<int, Ref<Texture2D>>> default_textures; virtual void _update_shader() const; //used for visual shader protected: @@ -86,9 +86,9 @@ public: get_param_list(nullptr); } - const Map<StringName, StringName>::Element *E = params_cache.find(p_param); + const HashMap<StringName, StringName>::Iterator E = params_cache.find(p_param); if (E) { - return E->get(); + return E->value; } return StringName(); } diff --git a/scene/resources/skeleton_modification_stack_2d.cpp b/scene/resources/skeleton_modification_stack_2d.cpp index b944c244b6..38ec19828f 100644 --- a/scene/resources/skeleton_modification_stack_2d.cpp +++ b/scene/resources/skeleton_modification_stack_2d.cpp @@ -263,7 +263,7 @@ void SkeletonModificationStack2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "get_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "0, 1, 0.001"), "set_strength", "get_strength"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "modification_count", PROPERTY_HINT_RANGE, "0, 100, 1"), "set_modification_count", "get_modification_count"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "modification_count", PROPERTY_HINT_RANGE, "0, 100, 1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Modifications,modifications/"), "set_modification_count", "get_modification_count"); } SkeletonModificationStack2D::SkeletonModificationStack2D() { diff --git a/scene/resources/skeleton_modification_stack_3d.cpp b/scene/resources/skeleton_modification_stack_3d.cpp index 7ccba1228c..44fbfc934e 100644 --- a/scene/resources/skeleton_modification_stack_3d.cpp +++ b/scene/resources/skeleton_modification_stack_3d.cpp @@ -217,7 +217,7 @@ void SkeletonModificationStack3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "get_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "0, 1, 0.001"), "set_strength", "get_strength"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "modification_count", PROPERTY_HINT_RANGE, "0, 100, 1"), "set_modification_count", "get_modification_count"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "modification_count", PROPERTY_HINT_RANGE, "0, 100, 1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Modifications,modifications/"), "set_modification_count", "get_modification_count"); } SkeletonModificationStack3D::SkeletonModificationStack3D() { diff --git a/scene/resources/sky.cpp b/scene/resources/sky.cpp index 9cb6a16f5c..735134e27b 100644 --- a/scene/resources/sky.cpp +++ b/scene/resources/sky.cpp @@ -83,7 +83,7 @@ void Sky::_bind_methods() { ClassDB::bind_method(D_METHOD("get_material"), &Sky::get_material); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,PanoramaSkyMaterial,ProceduralSkyMaterial,PhysicalSkyMaterial"), "set_material", "get_material"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Automatic,HighQuality,HighQualityIncremental,RealTime"), "set_process_mode", "get_process_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Automatic,High-Quality,High-Quality Incremental,Real-Time"), "set_process_mode", "get_process_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "32,64,128,256,512,1024,2048"), "set_radiance_size", "get_radiance_size"); BIND_ENUM_CONSTANT(RADIANCE_SIZE_32); diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp index ff5a85392c..ba21b9fd17 100644 --- a/scene/resources/sprite_frames.cpp +++ b/scene/resources/sprite_frames.cpp @@ -33,38 +33,38 @@ #include "scene/scene_string_names.h" void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos) { - Map<StringName, Anim>::Element *E = animations.find(p_anim); + HashMap<StringName, Anim>::Iterator E = animations.find(p_anim); ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - if (p_at_pos >= 0 && p_at_pos < E->get().frames.size()) { - E->get().frames.insert(p_at_pos, p_frame); + if (p_at_pos >= 0 && p_at_pos < E->value.frames.size()) { + E->value.frames.insert(p_at_pos, p_frame); } else { - E->get().frames.push_back(p_frame); + E->value.frames.push_back(p_frame); } emit_changed(); } int SpriteFrames::get_frame_count(const StringName &p_anim) const { - const Map<StringName, Anim>::Element *E = animations.find(p_anim); + HashMap<StringName, Anim>::ConstIterator E = animations.find(p_anim); ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist."); - return E->get().frames.size(); + return E->value.frames.size(); } void SpriteFrames::remove_frame(const StringName &p_anim, int p_idx) { - Map<StringName, Anim>::Element *E = animations.find(p_anim); + HashMap<StringName, Anim>::Iterator E = animations.find(p_anim); ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - E->get().frames.remove_at(p_idx); + E->value.frames.remove_at(p_idx); emit_changed(); } void SpriteFrames::clear(const StringName &p_anim) { - Map<StringName, Anim>::Element *E = animations.find(p_anim); + HashMap<StringName, Anim>::Iterator E = animations.find(p_anim); ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - E->get().frames.clear(); + E->value.frames.clear(); emit_changed(); } @@ -124,37 +124,37 @@ Vector<String> SpriteFrames::get_animation_names() const { void SpriteFrames::set_animation_speed(const StringName &p_anim, double p_fps) { ERR_FAIL_COND_MSG(p_fps < 0, "Animation speed cannot be negative (" + itos(p_fps) + ")."); - Map<StringName, Anim>::Element *E = animations.find(p_anim); + HashMap<StringName, Anim>::Iterator E = animations.find(p_anim); ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - E->get().speed = p_fps; + E->value.speed = p_fps; } double SpriteFrames::get_animation_speed(const StringName &p_anim) const { - const Map<StringName, Anim>::Element *E = animations.find(p_anim); + HashMap<StringName, Anim>::ConstIterator E = animations.find(p_anim); ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist."); - return E->get().speed; + return E->value.speed; } void SpriteFrames::set_animation_loop(const StringName &p_anim, bool p_loop) { - Map<StringName, Anim>::Element *E = animations.find(p_anim); + HashMap<StringName, Anim>::Iterator E = animations.find(p_anim); ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - E->get().loop = p_loop; + E->value.loop = p_loop; } bool SpriteFrames::get_animation_loop(const StringName &p_anim) const { - const Map<StringName, Anim>::Element *E = animations.find(p_anim); + HashMap<StringName, Anim>::ConstIterator E = animations.find(p_anim); ERR_FAIL_COND_V_MSG(!E, false, "Animation '" + String(p_anim) + "' doesn't exist."); - return E->get().loop; + return E->value.loop; } void SpriteFrames::_set_frames(const Array &p_frames) { clear_all(); - Map<StringName, Anim>::Element *E = animations.find(SceneStringNames::get_singleton()->_default); + HashMap<StringName, Anim>::Iterator E = animations.find(SceneStringNames::get_singleton()->_default); ERR_FAIL_COND(!E); - E->get().frames.resize(p_frames.size()); - for (int i = 0; i < E->get().frames.size(); i++) { - E->get().frames.write[i] = p_frames[i]; + E->value.frames.resize(p_frames.size()); + for (int i = 0; i < E->value.frames.size(); i++) { + E->value.frames.write[i] = p_frames[i]; } } diff --git a/scene/resources/sprite_frames.h b/scene/resources/sprite_frames.h index 12b69afde1..e32ccc1336 100644 --- a/scene/resources/sprite_frames.h +++ b/scene/resources/sprite_frames.h @@ -42,7 +42,7 @@ class SpriteFrames : public Resource { Vector<Ref<Texture2D>> frames; }; - Map<StringName, Anim> animations; + HashMap<StringName, Anim> animations; Array _get_frames() const; void _set_frames(const Array &p_frames); @@ -73,24 +73,24 @@ public: void add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos = -1); int get_frame_count(const StringName &p_anim) const; _FORCE_INLINE_ Ref<Texture2D> get_frame(const StringName &p_anim, int p_idx) const { - const Map<StringName, Anim>::Element *E = animations.find(p_anim); + HashMap<StringName, Anim>::ConstIterator E = animations.find(p_anim); ERR_FAIL_COND_V_MSG(!E, Ref<Texture2D>(), "Animation '" + String(p_anim) + "' doesn't exist."); ERR_FAIL_COND_V(p_idx < 0, Ref<Texture2D>()); - if (p_idx >= E->get().frames.size()) { + if (p_idx >= E->value.frames.size()) { return Ref<Texture2D>(); } - return E->get().frames[p_idx]; + return E->value.frames[p_idx]; } void set_frame(const StringName &p_anim, int p_idx, const Ref<Texture2D> &p_frame) { - Map<StringName, Anim>::Element *E = animations.find(p_anim); + HashMap<StringName, Anim>::Iterator E = animations.find(p_anim); ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); ERR_FAIL_COND(p_idx < 0); - if (p_idx >= E->get().frames.size()) { + if (p_idx >= E->value.frames.size()) { return; } - E->get().frames.write[p_idx] = p_frame; + E->value.frames.write[p_idx] = p_frame; } void remove_frame(const StringName &p_anim, int p_idx); void clear(const StringName &p_anim); diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 8ff1fde2cf..0e41eed570 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -1165,7 +1165,7 @@ void SurfaceTool::generate_normals(bool p_flip) { for (int i = 0; i < 3; i++) { Vector3 *lv = vertex_hash.getptr(v[i]); if (!lv) { - vertex_hash.set(v[i], normal); + vertex_hash.insert(v[i], normal); } else { (*lv) += normal; } diff --git a/scene/resources/syntax_highlighter.h b/scene/resources/syntax_highlighter.h index 143f1679c6..1243a9dbf7 100644 --- a/scene/resources/syntax_highlighter.h +++ b/scene/resources/syntax_highlighter.h @@ -41,7 +41,7 @@ class SyntaxHighlighter : public Resource { GDCLASS(SyntaxHighlighter, Resource) private: - Map<int, Dictionary> highlighting_cache; + RBMap<int, Dictionary> highlighting_cache; void _lines_edited_from(int p_from_line, int p_to_line); protected: @@ -83,7 +83,7 @@ private: bool line_only = false; }; Vector<ColorRegion> color_regions; - Map<int, int> color_region_cache; + HashMap<int, int> color_region_cache; Dictionary keywords; Dictionary member_keywords; diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp index 337776fd47..f9390ca528 100644 --- a/scene/resources/text_line.cpp +++ b/scene/resources/text_line.cpp @@ -36,7 +36,7 @@ void TextLine::_bind_methods() { ClassDB::bind_method(D_METHOD("set_direction", "direction"), &TextLine::set_direction); ClassDB::bind_method(D_METHOD("get_direction"), &TextLine::get_direction); - ADD_PROPERTY(PropertyInfo(Variant::INT, "direction", PROPERTY_HINT_ENUM, "Auto,Light-to-right,Right-to-left"), "set_direction", "get_direction"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "direction", PROPERTY_HINT_ENUM, "Auto,Left-to-right,Right-to-left"), "set_direction", "get_direction"); ClassDB::bind_method(D_METHOD("set_orientation", "orientation"), &TextLine::set_orientation); ClassDB::bind_method(D_METHOD("get_orientation"), &TextLine::get_orientation); diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index be54c309c8..1e57933000 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -123,82 +123,64 @@ bool Theme::_get(const StringName &p_name, Variant &r_ret) const { void Theme::_get_property_list(List<PropertyInfo> *p_list) const { List<PropertyInfo> list; - const StringName *key = nullptr; - // Type variations. - while ((key = variation_map.next(key))) { - list.push_back(PropertyInfo(Variant::STRING_NAME, String() + *key + "/base_type")); + for (const KeyValue<StringName, StringName> &E : variation_map) { + list.push_back(PropertyInfo(Variant::STRING_NAME, String() + E.key + "/base_type")); } - key = nullptr; - // Icons. - while ((key = icon_map.next(key))) { - const StringName *key2 = nullptr; - - while ((key2 = icon_map[*key].next(key2))) { - list.push_back(PropertyInfo(Variant::OBJECT, String() + *key + "/icons/" + *key2, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); + for (const KeyValue<StringName, HashMap<StringName, Ref<Texture2D>>> &E : icon_map) { + for (const KeyValue<StringName, Ref<Texture2D>> &F : E.value) { + list.push_back(PropertyInfo(Variant::OBJECT, String() + E.key + "/icons/" + F.key, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); } } - key = nullptr; - // Styles. - while ((key = style_map.next(key))) { - const StringName *key2 = nullptr; - - while ((key2 = style_map[*key].next(key2))) { - list.push_back(PropertyInfo(Variant::OBJECT, String() + *key + "/styles/" + *key2, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); + for (const KeyValue<StringName, HashMap<StringName, Ref<StyleBox>>> &E : style_map) { + for (const KeyValue<StringName, Ref<StyleBox>> &F : E.value) { + list.push_back(PropertyInfo(Variant::OBJECT, String() + E.key + "/styles/" + F.key, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); } } - key = nullptr; - // Fonts. - while ((key = font_map.next(key))) { - const StringName *key2 = nullptr; - - while ((key2 = font_map[*key].next(key2))) { - list.push_back(PropertyInfo(Variant::OBJECT, String() + *key + "/fonts/" + *key2, PROPERTY_HINT_RESOURCE_TYPE, "Font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); + for (const KeyValue<StringName, HashMap<StringName, Ref<Font>>> &E : font_map) { + for (const KeyValue<StringName, Ref<Font>> &F : E.value) { + list.push_back(PropertyInfo(Variant::OBJECT, String() + E.key + "/fonts/" + F.key, PROPERTY_HINT_RESOURCE_TYPE, "Font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); } } - key = nullptr; - // Font sizes. - while ((key = font_size_map.next(key))) { - const StringName *key2 = nullptr; - - while ((key2 = font_size_map[*key].next(key2))) { - list.push_back(PropertyInfo(Variant::INT, String() + *key + "/font_sizes/" + *key2, PROPERTY_HINT_RANGE, "0,256,1,or_greater")); + for (const KeyValue<StringName, HashMap<StringName, int>> &E : font_size_map) { + for (const KeyValue<StringName, int> &F : E.value) { + list.push_back(PropertyInfo(Variant::INT, String() + E.key + "/font_sizes/" + F.key, PROPERTY_HINT_RANGE, "0,256,1,or_greater")); } } - key = nullptr; - // Colors. - while ((key = color_map.next(key))) { - const StringName *key2 = nullptr; - - while ((key2 = color_map[*key].next(key2))) { - list.push_back(PropertyInfo(Variant::COLOR, String() + *key + "/colors/" + *key2)); + for (const KeyValue<StringName, HashMap<StringName, Color>> &E : color_map) { + for (const KeyValue<StringName, Color> &F : E.value) { + list.push_back(PropertyInfo(Variant::INT, String() + E.key + "/colors/" + F.key)); } } - key = nullptr; - // Constants. - while ((key = constant_map.next(key))) { - const StringName *key2 = nullptr; - - while ((key2 = constant_map[*key].next(key2))) { - list.push_back(PropertyInfo(Variant::INT, String() + *key + "/constants/" + *key2)); + for (const KeyValue<StringName, HashMap<StringName, int>> &E : constant_map) { + for (const KeyValue<StringName, int> &F : E.value) { + list.push_back(PropertyInfo(Variant::INT, String() + E.key + "/constants/" + F.key)); } } // Sort and store properties. list.sort(); + String prev_type; for (const PropertyInfo &E : list) { + // Add groups for types so that their names are left unchanged in the inspector. + String current_type = E.name.get_slice("/", 0); + if (prev_type != current_type) { + p_list->push_back(PropertyInfo(Variant::NIL, current_type, PROPERTY_HINT_NONE, current_type + "/", PROPERTY_USAGE_GROUP)); + prev_type = current_type; + } + p_list->push_back(E); } } @@ -414,10 +396,8 @@ void Theme::get_icon_list(StringName p_theme_type, List<StringName> *p_list) con return; } - const StringName *key = nullptr; - - while ((key = icon_map[p_theme_type].next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, Ref<Texture2D>> &E : icon_map[p_theme_type]) { + p_list->push_back(E.key); } } @@ -437,9 +417,8 @@ void Theme::remove_icon_type(const StringName &p_theme_type) { _freeze_change_propagation(); - const StringName *L = nullptr; - while ((L = icon_map[p_theme_type].next(L))) { - Ref<Texture2D> icon = icon_map[p_theme_type][*L]; + for (const KeyValue<StringName, Ref<Texture2D>> &E : icon_map[p_theme_type]) { + Ref<Texture2D> icon = E.value; if (icon.is_valid()) { icon->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } @@ -453,9 +432,8 @@ void Theme::remove_icon_type(const StringName &p_theme_type) { void Theme::get_icon_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - const StringName *key = nullptr; - while ((key = icon_map.next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, HashMap<StringName, Ref<Texture2D>>> &E : icon_map) { + p_list->push_back(E.key); } } @@ -528,10 +506,8 @@ void Theme::get_stylebox_list(StringName p_theme_type, List<StringName> *p_list) return; } - const StringName *key = nullptr; - - while ((key = style_map[p_theme_type].next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, Ref<StyleBox>> &E : style_map[p_theme_type]) { + p_list->push_back(E.key); } } @@ -551,9 +527,8 @@ void Theme::remove_stylebox_type(const StringName &p_theme_type) { _freeze_change_propagation(); - const StringName *L = nullptr; - while ((L = style_map[p_theme_type].next(L))) { - Ref<StyleBox> style = style_map[p_theme_type][*L]; + for (const KeyValue<StringName, Ref<StyleBox>> &E : style_map[p_theme_type]) { + Ref<StyleBox> style = E.value; if (style.is_valid()) { style->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } @@ -567,9 +542,8 @@ void Theme::remove_stylebox_type(const StringName &p_theme_type) { void Theme::get_stylebox_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - const StringName *key = nullptr; - while ((key = style_map.next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, HashMap<StringName, Ref<StyleBox>>> &E : style_map) { + p_list->push_back(E.key); } } @@ -644,10 +618,8 @@ void Theme::get_font_list(StringName p_theme_type, List<StringName> *p_list) con return; } - const StringName *key = nullptr; - - while ((key = font_map[p_theme_type].next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, Ref<Font>> &E : font_map[p_theme_type]) { + p_list->push_back(E.key); } } @@ -667,9 +639,8 @@ void Theme::remove_font_type(const StringName &p_theme_type) { _freeze_change_propagation(); - const StringName *L = nullptr; - while ((L = font_map[p_theme_type].next(L))) { - Ref<Font> font = font_map[p_theme_type][*L]; + for (const KeyValue<StringName, Ref<Font>> &E : font_map[p_theme_type]) { + Ref<Font> font = E.value; if (font.is_valid()) { font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } @@ -683,9 +654,8 @@ void Theme::remove_font_type(const StringName &p_theme_type) { void Theme::get_font_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - const StringName *key = nullptr; - while ((key = font_map.next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, HashMap<StringName, Ref<Font>>> &E : font_map) { + p_list->push_back(E.key); } } @@ -747,10 +717,8 @@ void Theme::get_font_size_list(StringName p_theme_type, List<StringName> *p_list return; } - const StringName *key = nullptr; - - while ((key = font_size_map[p_theme_type].next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, int> &E : font_size_map[p_theme_type]) { + p_list->push_back(E.key); } } @@ -774,9 +742,8 @@ void Theme::remove_font_size_type(const StringName &p_theme_type) { void Theme::get_font_size_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - const StringName *key = nullptr; - while ((key = font_size_map.next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, HashMap<StringName, int>> &E : font_size_map) { + p_list->push_back(E.key); } } @@ -836,10 +803,8 @@ void Theme::get_color_list(StringName p_theme_type, List<StringName> *p_list) co return; } - const StringName *key = nullptr; - - while ((key = color_map[p_theme_type].next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, Color> &E : color_map[p_theme_type]) { + p_list->push_back(E.key); } } @@ -863,9 +828,8 @@ void Theme::remove_color_type(const StringName &p_theme_type) { void Theme::get_color_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - const StringName *key = nullptr; - while ((key = color_map.next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, HashMap<StringName, Color>> &E : color_map) { + p_list->push_back(E.key); } } @@ -925,10 +889,8 @@ void Theme::get_constant_list(StringName p_theme_type, List<StringName> *p_list) return; } - const StringName *key = nullptr; - - while ((key = constant_map[p_theme_type].next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, int> &E : constant_map[p_theme_type]) { + p_list->push_back(E.key); } } @@ -952,9 +914,8 @@ void Theme::remove_constant_type(const StringName &p_theme_type) { void Theme::get_constant_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - const StringName *key = nullptr; - while ((key = constant_map.next(key))) { - p_list->push_back(*key); + for (const KeyValue<StringName, HashMap<StringName, int>> &E : constant_map) { + p_list->push_back(E.key); } } @@ -1311,52 +1272,12 @@ void Theme::remove_type(const StringName &p_theme_type) { void Theme::get_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - Set<StringName> types; - const StringName *key = nullptr; - - // Icons. - while ((key = icon_map.next(key))) { - types.insert(*key); - } - - key = nullptr; - - // StyleBoxes. - while ((key = style_map.next(key))) { - types.insert(*key); - } - - key = nullptr; - - // Fonts. - while ((key = font_map.next(key))) { - types.insert(*key); - } - - key = nullptr; - - // Font sizes. - while ((key = font_size_map.next(key))) { - types.insert(*key); - } - - key = nullptr; - - // Colors. - while ((key = color_map.next(key))) { - types.insert(*key); - } - - key = nullptr; - - // Constants. - while ((key = constant_map.next(key))) { - types.insert(*key); - } - - for (Set<StringName>::Element *E = types.front(); E; E = E->next()) { - p_list->push_back(E->get()); - } + get_icon_type_list(p_list); + get_stylebox_type_list(p_list); + get_font_type_list(p_list); + get_font_size_type_list(p_list); + get_color_type_list(p_list); + get_constant_type_list(p_list); } void Theme::get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variation, List<StringName> *p_list) { @@ -1667,75 +1588,62 @@ void Theme::merge_with(const Ref<Theme> &p_other) { // Colors. { - const StringName *K = nullptr; - while ((K = p_other->color_map.next(K))) { - const StringName *L = nullptr; - while ((L = p_other->color_map[*K].next(L))) { - set_color(*L, *K, p_other->color_map[*K][*L]); + for (const KeyValue<StringName, HashMap<StringName, Color>> &E : p_other->color_map) { + for (const KeyValue<StringName, Color> &F : E.value) { + set_color(F.key, E.key, F.value); } } } // Constants. { - const StringName *K = nullptr; - while ((K = p_other->constant_map.next(K))) { - const StringName *L = nullptr; - while ((L = p_other->constant_map[*K].next(L))) { - set_constant(*L, *K, p_other->constant_map[*K][*L]); + for (const KeyValue<StringName, HashMap<StringName, int>> &E : p_other->constant_map) { + for (const KeyValue<StringName, int> &F : E.value) { + set_constant(F.key, E.key, F.value); } } } // Fonts. { - const StringName *K = nullptr; - while ((K = p_other->font_map.next(K))) { - const StringName *L = nullptr; - while ((L = p_other->font_map[*K].next(L))) { - set_font(*L, *K, p_other->font_map[*K][*L]); + for (const KeyValue<StringName, HashMap<StringName, Ref<Font>>> &E : p_other->font_map) { + for (const KeyValue<StringName, Ref<Font>> &F : E.value) { + set_font(F.key, E.key, F.value); } } } // Font sizes. { - const StringName *K = nullptr; - while ((K = p_other->font_size_map.next(K))) { - const StringName *L = nullptr; - while ((L = p_other->font_size_map[*K].next(L))) { - set_font_size(*L, *K, p_other->font_size_map[*K][*L]); + for (const KeyValue<StringName, HashMap<StringName, int>> &E : p_other->font_size_map) { + for (const KeyValue<StringName, int> &F : E.value) { + set_font_size(F.key, E.key, F.value); } } } // Icons. { - const StringName *K = nullptr; - while ((K = p_other->icon_map.next(K))) { - const StringName *L = nullptr; - while ((L = p_other->icon_map[*K].next(L))) { - set_icon(*L, *K, p_other->icon_map[*K][*L]); + for (const KeyValue<StringName, HashMap<StringName, Ref<Texture2D>>> &E : p_other->icon_map) { + for (const KeyValue<StringName, Ref<Texture2D>> &F : E.value) { + set_icon(F.key, E.key, F.value); } } } // Styleboxes. { - const StringName *K = nullptr; - while ((K = p_other->style_map.next(K))) { - const StringName *L = nullptr; - while ((L = p_other->style_map[*K].next(L))) { - set_stylebox(*L, *K, p_other->style_map[*K][*L]); + for (const KeyValue<StringName, HashMap<StringName, Ref<StyleBox>>> &E : p_other->style_map) { + for (const KeyValue<StringName, Ref<StyleBox>> &F : E.value) { + set_stylebox(F.key, E.key, F.value); } } } // Type variations. { - const StringName *K = nullptr; - while ((K = p_other->variation_map.next(K))) { - set_type_variation(*K, p_other->variation_map[*K]); + for (const KeyValue<StringName, StringName> &E : p_other->variation_map) { + set_type_variation(E.key, E.value); } } @@ -1745,12 +1653,10 @@ void Theme::merge_with(const Ref<Theme> &p_other) { void Theme::clear() { // These items need disconnecting. { - const StringName *K = nullptr; - while ((K = icon_map.next(K))) { - const StringName *L = nullptr; - while ((L = icon_map[*K].next(L))) { - Ref<Texture2D> icon = icon_map[*K][*L]; - if (icon.is_valid()) { + for (const KeyValue<StringName, HashMap<StringName, Ref<Texture2D>>> &E : icon_map) { + for (const KeyValue<StringName, Ref<Texture2D>> &F : E.value) { + if (F.value.is_valid()) { + Ref<Texture2D> icon = F.value; icon->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } } @@ -1758,12 +1664,10 @@ void Theme::clear() { } { - const StringName *K = nullptr; - while ((K = style_map.next(K))) { - const StringName *L = nullptr; - while ((L = style_map[*K].next(L))) { - Ref<StyleBox> style = style_map[*K][*L]; - if (style.is_valid()) { + for (const KeyValue<StringName, HashMap<StringName, Ref<StyleBox>>> &E : style_map) { + for (const KeyValue<StringName, Ref<StyleBox>> &F : E.value) { + if (F.value.is_valid()) { + Ref<StyleBox> style = F.value; style->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } } @@ -1771,12 +1675,10 @@ void Theme::clear() { } { - const StringName *K = nullptr; - while ((K = font_map.next(K))) { - const StringName *L = nullptr; - while ((L = font_map[*K].next(L))) { - Ref<Font> font = font_map[*K][*L]; - if (font.is_valid()) { + for (const KeyValue<StringName, HashMap<StringName, Ref<Font>>> &E : font_map) { + for (const KeyValue<StringName, Ref<Font>> &F : E.value) { + if (F.value.is_valid()) { + Ref<Font> font = F.value; font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } } diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index da9e1ef2f6..cee3f85c32 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -1345,19 +1345,19 @@ int TileSet::get_patterns_count() { return patterns.size(); } -Set<TileSet::TerrainsPattern> TileSet::get_terrains_pattern_set(int p_terrain_set) { - ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), Set<TileSet::TerrainsPattern>()); +RBSet<TileSet::TerrainsPattern> TileSet::get_terrains_pattern_set(int p_terrain_set) { + ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), RBSet<TileSet::TerrainsPattern>()); _update_terrains_cache(); - Set<TileSet::TerrainsPattern> output; - for (KeyValue<TileSet::TerrainsPattern, Set<TileMapCell>> kv : per_terrain_pattern_tiles[p_terrain_set]) { + RBSet<TileSet::TerrainsPattern> output; + for (KeyValue<TileSet::TerrainsPattern, RBSet<TileMapCell>> kv : per_terrain_pattern_tiles[p_terrain_set]) { output.insert(kv.key); } return output; } -Set<TileMapCell> TileSet::get_tiles_for_terrains_pattern(int p_terrain_set, TerrainsPattern p_terrain_tile_pattern) { - ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), Set<TileMapCell>()); +RBSet<TileMapCell> TileSet::get_tiles_for_terrains_pattern(int p_terrain_set, TerrainsPattern p_terrain_tile_pattern) { + ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), RBSet<TileMapCell>()); _update_terrains_cache(); return per_terrain_pattern_tiles[p_terrain_set][p_terrain_tile_pattern]; } @@ -1368,8 +1368,8 @@ TileMapCell TileSet::get_random_tile_from_terrains_pattern(int p_terrain_set, Ti // Count the sum of probabilities. double sum = 0.0; - Set<TileMapCell> set = per_terrain_pattern_tiles[p_terrain_set][p_terrain_tile_pattern]; - for (Set<TileMapCell>::Element *E = set.front(); E; E = E->next()) { + RBSet<TileMapCell> set = per_terrain_pattern_tiles[p_terrain_set][p_terrain_tile_pattern]; + for (RBSet<TileMapCell>::Element *E = set.front(); E; E = E->next()) { if (E->get().source_id >= 0) { Ref<TileSetSource> source = sources[E->get().source_id]; Ref<TileSetAtlasSource> atlas_source = source; @@ -1389,7 +1389,7 @@ TileMapCell TileSet::get_random_tile_from_terrains_pattern(int p_terrain_set, Ti double picked = Math::random(0.0, sum); // Pick the tile. - for (Set<TileMapCell>::Element *E = set.front(); E; E = E->next()) { + for (RBSet<TileMapCell>::Element *E = set.front(); E; E = E->next()) { if (E->get().source_id >= 0) { Ref<TileSetSource> source = sources[E->get().source_id]; @@ -2391,7 +2391,7 @@ void TileSet::_compatibility_conversion() { value_array.push_back(alternative_tile); if (!compatibility_tilemap_mapping.has(E.key)) { - compatibility_tilemap_mapping[E.key] = Map<Array, Array>(); + compatibility_tilemap_mapping[E.key] = RBMap<Array, Array>(); } compatibility_tilemap_mapping[E.key][key_array] = value_array; compatibility_tilemap_mapping_tile_modes[E.key] = COMPATIBILITY_TILE_MODE_SINGLE_TILE; @@ -2483,7 +2483,7 @@ void TileSet::_compatibility_conversion() { value_array.push_back(alternative_tile); if (!compatibility_tilemap_mapping.has(E.key)) { - compatibility_tilemap_mapping[E.key] = Map<Array, Array>(); + compatibility_tilemap_mapping[E.key] = RBMap<Array, Array>(); } compatibility_tilemap_mapping[E.key][key_array] = value_array; compatibility_tilemap_mapping_tile_modes[E.key] = COMPATIBILITY_TILE_MODE_ATLAS_TILE; @@ -2571,7 +2571,7 @@ void TileSet::_compatibility_conversion() { for (const KeyValue<int, CompatibilityTileData *> &E : compatibility_data) { memdelete(E.value); } - compatibility_data = Map<int, CompatibilityTileData *>(); + compatibility_data = HashMap<int, CompatibilityTileData *>(); } Array TileSet::compatibility_tilemap_map(int p_tile_id, Vector2i p_coords, bool p_flip_h, bool p_flip_v, bool p_transpose) { @@ -2622,12 +2622,12 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { // Get or create the compatibility object CompatibilityTileData *ctd; - Map<int, CompatibilityTileData *>::Element *E = compatibility_data.find(id); + HashMap<int, CompatibilityTileData *>::Iterator E = compatibility_data.find(id); if (!E) { ctd = memnew(CompatibilityTileData); compatibility_data.insert(id, ctd); } else { - ctd = E->get(); + ctd = E->value; } if (components.size() < 2) { @@ -3099,7 +3099,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { // Terrains. p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int terrain_set_index = 0; terrain_set_index < terrain_sets.size(); terrain_set_index++) { - p_list->push_back(PropertyInfo(Variant::INT, vformat("terrain_set_%d/mode", terrain_set_index), PROPERTY_HINT_ENUM, "Match corners and sides,Match corners,Match sides")); + p_list->push_back(PropertyInfo(Variant::INT, vformat("terrain_set_%d/mode", terrain_set_index), PROPERTY_HINT_ENUM, "Match Corners and Sides,Match Corners,Match Sides")); p_list->push_back(PropertyInfo(Variant::NIL, vformat("terrain_set_%d/terrains", terrain_set_index), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, vformat("terrain_set_%d/terrain_", terrain_set_index))); for (int terrain_index = 0; terrain_index < terrain_sets[terrain_set_index].terrains.size(); terrain_index++) { p_list->push_back(PropertyInfo(Variant::STRING, vformat("terrain_set_%d/terrain_%d/name", terrain_set_index, terrain_index))); @@ -3264,16 +3264,10 @@ void TileSet::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uv_clipping"), "set_uv_clipping", "is_uv_clipping"); ADD_ARRAY("occlusion_layers", "occlusion_layer_"); - ADD_GROUP("Physics", ""); + ADD_GROUP("", ""); ADD_ARRAY("physics_layers", "physics_layer_"); - - ADD_GROUP("Terrains", ""); ADD_ARRAY("terrain_sets", "terrain_set_"); - - ADD_GROUP("Navigation", ""); ADD_ARRAY("navigation_layers", "navigation_layer_"); - - ADD_GROUP("Custom Data", ""); ADD_ARRAY("custom_data_layers", "custom_data_layer_"); // -- Enum binding -- diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 95de46c9ab..633e1f4bed 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -69,6 +69,11 @@ union TileMapCell { }; uint64_t _u64t; + + static uint32_t hash(const TileMapCell &p_hash) { + return hash_one_uint64(p_hash._u64t); + } + TileMapCell(int p_source_id = -1, Vector2i p_atlas_coords = Vector2i(-1, -1), int p_alternative_tile = -1) { // default are INVALID_SOURCE, INVALID_ATLAS_COORDS, INVALID_TILE_ALTERNATIVE source_id = p_source_id; set_atlas_coords(p_atlas_coords); @@ -103,13 +108,16 @@ union TileMapCell { bool operator!=(const TileMapCell &p_other) const { return !(source_id == p_other.source_id && coord_x == p_other.coord_x && coord_y == p_other.coord_y && alternative_tile == p_other.alternative_tile); } + bool operator==(const TileMapCell &p_other) const { + return source_id == p_other.source_id && coord_x == p_other.coord_x && coord_y == p_other.coord_y && alternative_tile == p_other.alternative_tile; + } }; class TileMapPattern : public Resource { GDCLASS(TileMapPattern, Resource); Vector2i size; - Map<Vector2i, TileMapCell> pattern; + HashMap<Vector2i, TileMapCell> pattern; void _set_tile_data(const Vector<int> &p_data); Vector<int> _get_tile_data() const; @@ -166,11 +174,11 @@ private: Size2i autotile_tile_size = Size2i(16, 16); int autotile_spacing = 0; - Map<Vector2i, int> autotile_bitmask_flags; - Map<Vector2i, Ref<OccluderPolygon2D>> autotile_occluder_map; - Map<Vector2i, Ref<NavigationPolygon>> autotile_navpoly_map; - Map<Vector2i, int> autotile_priority_map; - Map<Vector2i, int> autotile_z_index_map; + HashMap<Vector2i, int> autotile_bitmask_flags; + HashMap<Vector2i, Ref<OccluderPolygon2D>> autotile_occluder_map; + HashMap<Vector2i, Ref<NavigationPolygon>> autotile_navpoly_map; + HashMap<Vector2i, int> autotile_priority_map; + HashMap<Vector2i, int> autotile_z_index_map; Vector<CompatibilityShapeData> shapes; Ref<OccluderPolygon2D> occluder; @@ -186,9 +194,9 @@ private: COMPATIBILITY_TILE_MODE_ATLAS_TILE, }; - Map<int, CompatibilityTileData *> compatibility_data; - Map<int, int> compatibility_tilemap_mapping_tile_modes; - Map<int, Map<Array, Array>> compatibility_tilemap_mapping; + HashMap<int, CompatibilityTileData *> compatibility_data; + HashMap<int, int> compatibility_tilemap_mapping_tile_modes; + HashMap<int, RBMap<Array, Array>> compatibility_tilemap_mapping; void _compatibility_conversion(); @@ -324,10 +332,10 @@ private: }; Vector<TerrainSet> terrain_sets; - Map<TerrainMode, Map<CellNeighbor, Ref<ArrayMesh>>> terrain_bits_meshes; + HashMap<TerrainMode, HashMap<CellNeighbor, Ref<ArrayMesh>>> terrain_bits_meshes; bool terrain_bits_meshes_dirty = true; - LocalVector<Map<TileSet::TerrainsPattern, Set<TileMapCell>>> per_terrain_pattern_tiles; // Cached data. + LocalVector<RBMap<TileSet::TerrainsPattern, RBSet<TileMapCell>>> per_terrain_pattern_tiles; // Cached data. bool terrains_cache_dirty = true; void _update_terrains_cache(); @@ -343,10 +351,10 @@ private: Variant::Type type = Variant::NIL; }; Vector<CustomDataLayer> custom_data_layers; - Map<String, int> custom_data_layers_by_name; + HashMap<String, int> custom_data_layers_by_name; // Per Atlas source data. - Map<int, Ref<TileSetSource>> sources; + HashMap<int, Ref<TileSetSource>> sources; Vector<int> source_ids; int next_source_id = 0; // --------------------- @@ -357,9 +365,9 @@ private: void _source_changed(); // Tile proxies - Map<int, int> source_level_proxies; - Map<Array, Array> coords_level_proxies; - Map<Array, Array> alternative_level_proxies; + RBMap<int, int> source_level_proxies; + RBMap<Array, Array> coords_level_proxies; + RBMap<Array, Array> alternative_level_proxies; // Helpers Vector<Point2> _get_square_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); @@ -499,8 +507,8 @@ public: int get_patterns_count(); // Terrains. - Set<TerrainsPattern> get_terrains_pattern_set(int p_terrain_set); - Set<TileMapCell> get_tiles_for_terrains_pattern(int p_terrain_set, TerrainsPattern p_terrain_tile_pattern); + RBSet<TerrainsPattern> get_terrains_pattern_set(int p_terrain_set); + RBSet<TileMapCell> get_tiles_for_terrains_pattern(int p_terrain_set, TerrainsPattern p_terrain_tile_pattern); TileMapCell get_random_tile_from_terrains_pattern(int p_terrain_set, TerrainsPattern p_terrain_tile_pattern); // Helpers @@ -579,7 +587,7 @@ private: LocalVector<real_t> animation_frames_durations; // Alternatives - Map<int, TileData *> alternatives; + HashMap<int, TileData *> alternatives; Vector<int> alternatives_ids; int next_alternative_id = 1; }; @@ -589,9 +597,9 @@ private: Vector2i separation; Size2i texture_region_size = Size2i(16, 16); - Map<Vector2i, TileAlternativesData> tiles; + HashMap<Vector2i, TileAlternativesData> tiles; Vector<Vector2i> tiles_ids; - Map<Vector2i, Vector2i> _coords_mapping_cache; // Maps any coordinate to the including tile + HashMap<Vector2i, Vector2i> _coords_mapping_cache; // Maps any coordinate to the including tile TileData *_get_atlas_tile_data(Vector2i p_atlas_coords, int p_alternative_tile); const TileData *_get_atlas_tile_data(Vector2i p_atlas_coords, int p_alternative_tile) const; @@ -716,7 +724,7 @@ private: bool display_placeholder = false; }; Vector<int> scenes_ids; - Map<int, SceneData> scenes; + HashMap<int, SceneData> scenes; int next_scene_id = 1; void _compute_next_alternative_id(); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 755962b96c..8e7824665f 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -345,8 +345,8 @@ Vector<StringName> VisualShaderNode::get_editable_properties() const { return Vector<StringName>(); } -Map<StringName, String> VisualShaderNode::get_editable_properties_names() const { - return Map<StringName, String>(); +HashMap<StringName, String> VisualShaderNode::get_editable_properties_names() const { + return HashMap<StringName, String>(); } Array VisualShaderNode::get_default_input_values() const { @@ -1178,16 +1178,16 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port StringBuilder global_code; StringBuilder global_code_per_node; - Map<Type, StringBuilder> global_code_per_func; + HashMap<Type, StringBuilder> global_code_per_func; StringBuilder code; - Set<StringName> classes; + RBSet<StringName> classes; global_code += String() + "shader_type canvas_item;\n"; String global_expressions; for (int i = 0, index = 0; i < TYPE_MAX; i++) { - for (Map<int, Node>::Element *E = graph[i].nodes.front(); E; E = E->next()) { - Ref<VisualShaderNodeGlobalExpression> global_expression = Object::cast_to<VisualShaderNodeGlobalExpression>(E->get().node.ptr()); + for (const KeyValue<int, Node> &E : graph[i].nodes) { + Ref<VisualShaderNodeGlobalExpression> global_expression = E.value.node; if (global_expression.is_valid()) { String expr = ""; expr += "// " + global_expression->get_caption() + ":" + itos(index++) + "\n"; @@ -1222,7 +1222,7 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port code += "\nvoid fragment() {\n"; - Set<int> processed; + RBSet<int> processed; Error err = _write_node(p_type, &global_code, &global_code_per_node, &global_code_per_func, code, default_tex_params, input_connections, output_connections, p_node, processed, true, classes); ERR_FAIL_COND_V(err != OK, String()); @@ -1550,8 +1550,8 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Node3D,CanvasItem,Particles,Sky,Fog")); //render modes - Map<String, String> blend_mode_enums; - Set<String> toggles; + HashMap<String, String> blend_mode_enums; + RBSet<String> toggles; const Vector<ShaderLanguage::ModeInfo> &rmodes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode)); @@ -1562,7 +1562,7 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { const String begin = String(info.name); for (int j = 0; j < info.options.size(); j++) { - const String option = String(info.options[j]); + const String option = String(info.options[j]).capitalize(); if (!blend_mode_enums.has(begin)) { blend_mode_enums[begin] = option; @@ -1579,7 +1579,7 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::INT, "modes/" + E.key, PROPERTY_HINT_ENUM, E.value)); } - for (Set<String>::Element *E = toggles.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = toggles.front(); E; E = E->next()) { p_list->push_back(PropertyInfo(Variant::BOOL, "flags/" + E->get())); } @@ -1611,7 +1611,7 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { } } -Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBuilder *global_code_per_node, Map<Type, StringBuilder> *global_code_per_func, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const { +Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBuilder *global_code_per_node, HashMap<Type, StringBuilder> *global_code_per_func, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, RBSet<int> &processed, bool for_preview, RBSet<StringName> &r_classes) const { const Ref<VisualShaderNode> vsnode = graph[type].nodes[node].node; if (vsnode->is_disabled()) { @@ -1903,7 +1903,7 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui int output_count = vsnode->get_output_port_count(); int initial_output_count = output_count; - Map<int, bool> expanded_output_ports; + HashMap<int, bool> expanded_output_ports; for (int i = 0; i < initial_output_count; i++) { bool expanded = false; @@ -2133,11 +2133,11 @@ void VisualShader::_update_shader() const { StringBuilder global_code; StringBuilder global_code_per_node; - Map<Type, StringBuilder> global_code_per_func; + HashMap<Type, StringBuilder> global_code_per_func; StringBuilder code; Vector<VisualShader::DefaultTextureParam> default_tex_params; - Set<StringName> classes; - Map<int, int> insertion_pos; + RBSet<StringName> classes; + HashMap<int, int> insertion_pos; static const char *shader_mode_str[Shader::MODE_MAX] = { "spatial", "canvas_item", "particles", "sky", "fog" }; global_code += String() + "shader_type " + shader_mode_str[shader_mode] + ";\n"; @@ -2181,18 +2181,18 @@ void VisualShader::_update_shader() const { static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" }; String global_expressions; - Set<String> used_uniform_names; + RBSet<String> used_uniform_names; List<VisualShaderNodeUniform *> uniforms; - Map<int, List<int>> emitters; - Map<int, List<int>> varying_setters; + HashMap<int, List<int>> emitters; + HashMap<int, List<int>> varying_setters; for (int i = 0, index = 0; i < TYPE_MAX; i++) { if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { continue; } - for (Map<int, Node>::Element *E = graph[i].nodes.front(); E; E = E->next()) { - Ref<VisualShaderNodeGlobalExpression> global_expression = Object::cast_to<VisualShaderNodeGlobalExpression>(E->get().node.ptr()); + for (const KeyValue<int, Node> &E : graph[i].nodes) { + Ref<VisualShaderNodeGlobalExpression> global_expression = E.value.node; if (global_expression.is_valid()) { String expr = ""; expr += "// " + global_expression->get_caption() + ":" + itos(index++) + "\n"; @@ -2201,27 +2201,27 @@ void VisualShader::_update_shader() const { expr += "\n"; global_expressions += expr; } - Ref<VisualShaderNodeUniformRef> uniform_ref = Object::cast_to<VisualShaderNodeUniformRef>(E->get().node.ptr()); + Ref<VisualShaderNodeUniformRef> uniform_ref = E.value.node; if (uniform_ref.is_valid()) { used_uniform_names.insert(uniform_ref->get_uniform_name()); } - Ref<VisualShaderNodeUniform> uniform = Object::cast_to<VisualShaderNodeUniform>(E->get().node.ptr()); + Ref<VisualShaderNodeUniform> uniform = E.value.node; if (uniform.is_valid()) { uniforms.push_back(uniform.ptr()); } - Ref<VisualShaderNodeVaryingSetter> varying_setter = Object::cast_to<VisualShaderNodeVaryingSetter>(E->get().node.ptr()); + Ref<VisualShaderNodeVaryingSetter> varying_setter = E.value.node; if (varying_setter.is_valid() && varying_setter->is_input_port_connected(0)) { if (!varying_setters.has(i)) { varying_setters.insert(i, List<int>()); } - varying_setters[i].push_back(E->key()); + varying_setters[i].push_back(E.key); } - Ref<VisualShaderNodeParticleEmit> emit_particle = Object::cast_to<VisualShaderNodeParticleEmit>(E->get().node.ptr()); + Ref<VisualShaderNodeParticleEmit> emit_particle = E.value.node; if (emit_particle.is_valid()) { if (!emitters.has(i)) { emitters.insert(i, List<int>()); } - emitters[i].push_back(E->key()); + emitters[i].push_back(E.key); } } } @@ -2269,8 +2269,8 @@ void VisualShader::_update_shader() const { global_code += "\n"; } - Map<int, String> code_map; - Set<int> empty_funcs; + HashMap<int, String> code_map; + RBSet<int> empty_funcs; for (int i = 0; i < TYPE_MAX; i++) { if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { @@ -2282,7 +2282,7 @@ void VisualShader::_update_shader() const { VMap<ConnectionKey, const List<Connection>::Element *> output_connections; StringBuilder func_code; - Set<int> processed; + RBSet<int> processed; bool is_empty_func = false; if (shader_mode != Shader::MODE_PARTICLES && shader_mode != Shader::MODE_SKY && shader_mode != Shader::MODE_FOG) { @@ -3479,89 +3479,89 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { //////////////////////////////////////////////////////////////////////// // Node3D, Vertex. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "vertex", "VERTEX" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "TANGENT" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "BINORMAL" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_view_matrix", "MODELVIEW_MATRIX" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Vertex", "VERTEX" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal", "NORMAL" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Tangent", "TANGENT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Binormal", "BINORMAL" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "UV", "UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "UV2", "UV2" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Color", "COLOR" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Roughness", "ROUGHNESS" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Point Size", "POINT_SIZE" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "Model View Matrix", "MODELVIEW_MATRIX" }, //////////////////////////////////////////////////////////////////////// // Node3D, Fragment. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "albedo", "ALBEDO" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "ALPHA" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "metallic", "METALLIC" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "specular", "SPECULAR" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "emission", "EMISSION" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao", "AO" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao_light_affect", "AO_LIGHT_AFFECT" }, - - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal_map", "NORMAL_MAP" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "normal_map_depth", "NORMAL_MAP_DEPTH" }, - - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "rim", "RIM" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "rim_tint", "RIM_TINT" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "clearcoat", "CLEARCOAT" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "clearcoat_roughness", "CLEARCOAT_ROUGHNESS" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "anisotropy", "ANISOTROPY" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "anisotropy_flow", "ANISOTROPY_FLOW" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "subsurf_scatter", "SSS_STRENGTH" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "backlight", "BACKLIGHT" }, - - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_scissor_threshold", "ALPHA_SCISSOR_THRESHOLD" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_hash_scale", "ALPHA_HASH_SCALE" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_aa_edge", "ALPHA_ANTIALIASING_EDGE" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "alpha_uv", "ALPHA_TEXTURE_COORDINATE" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Albedo", "ALBEDO" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "ALPHA" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Metallic", "METALLIC" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Roughness", "ROUGHNESS" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Specular", "SPECULAR" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Emission", "EMISSION" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "AO", "AO" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "AO Light Affect", "AO_LIGHT_AFFECT" }, + + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal", "NORMAL" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal Map", "NORMAL_MAP" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Normal Map Depth", "NORMAL_MAP_DEPTH" }, + + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Rim", "RIM" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Rim Tint", "RIM_TINT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Clearcoat", "CLEARCOAT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Clearcoat Roughness", "CLEARCOAT_ROUGHNESS" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Anisotropy", "ANISOTROPY" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "Anisotropy Flow", "ANISOTROPY_FLOW" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Subsurf Scatter", "SSS_STRENGTH" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Backlight", "BACKLIGHT" }, + + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha Scissor Threshold", "ALPHA_SCISSOR_THRESHOLD" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha Hash Scale", "ALPHA_HASH_SCALE" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha AA Edge", "ALPHA_ANTIALIASING_EDGE" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "Alpha UV", "ALPHA_TEXTURE_COORDINATE" }, //////////////////////////////////////////////////////////////////////// // Node3D, Light. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "diffuse", "DIFFUSE_LIGHT" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "specular", "SPECULAR_LIGHT" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "ALPHA" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Diffuse", "DIFFUSE_LIGHT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Specular", "SPECULAR_LIGHT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "ALPHA" }, //////////////////////////////////////////////////////////////////////// // Canvas Item. //////////////////////////////////////////////////////////////////////// // Canvas Item, Vertex. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "Vertex", "VERTEX" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "UV", "UV" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Color", "COLOR" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Point Size", "POINT_SIZE" }, //////////////////////////////////////////////////////////////////////// // Canvas Item, Fragment. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal_map", "NORMAL_MAP" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "normal_map_depth", "NORMAL_MAP_DEPTH" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_vertex", "LIGHT_VERTEX" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "shadow_vertex", "SHADOW_VERTEX" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Color", "COLOR" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal", "NORMAL" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal Map", "NORMAL_MAP" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Normal Map Depth", "NORMAL_MAP_DEPTH" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Light Vertex", "LIGHT_VERTEX" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "Shadow Vertex", "SHADOW_VERTEX" }, //////////////////////////////////////////////////////////////////////// // Canvas Item, Light. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light", "LIGHT" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Light", "LIGHT" }, //////////////////////////////////////////////////////////////////////// // Sky, Sky. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR" }, - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "ALPHA" }, - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fog", "FOG" }, + { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Color", "COLOR" }, + { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "ALPHA" }, + { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Fog", "FOG" }, //////////////////////////////////////////////////////////////////////// // Fog, Fog. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "density", "DENSITY" }, - { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "albedo", "ALBEDO" }, - { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "emission", "EMISSION" }, + { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "Density", "DENSITY" }, + { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Albedo", "ALBEDO" }, + { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Emission", "EMISSION" }, //////////////////////////////////////////////////////////////////////// { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr }, @@ -3605,7 +3605,7 @@ String VisualShaderNodeOutput::get_input_port_name(int p_port) const { while (ports[idx].mode != Shader::MODE_MAX) { if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) { if (count == p_port) { - return String(ports[idx].name).capitalize(); + return String(ports[idx].name); } count++; } @@ -3638,7 +3638,7 @@ bool VisualShaderNodeOutput::is_port_separator(int p_index) const { } if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_FRAGMENT) { String name = get_input_port_name(p_index); - return bool(name == "Ao" || name == "Normal" || name == "Rim" || name == "Clearcoat" || name == "Anisotropy" || name == "Subsurf Scatter" || name == "Alpha Scissor Threshold"); + return bool(name == "AO" || name == "Normal" || name == "Rim" || name == "Clearcoat" || name == "Anisotropy" || name == "Subsurf Scatter" || name == "Alpha Scissor Threshold"); } return false; } diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index aaf570d98c..aa5263943b 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -127,7 +127,7 @@ private: }; struct Graph { - Map<int, Node> nodes; + RBMap<int, Node> nodes; List<Connection> connections; } graph[TYPE_MAX]; @@ -139,9 +139,9 @@ private: Vector2 graph_offset; HashMap<String, int> modes; - Set<StringName> flags; + RBSet<StringName> flags; - Map<String, Varying> varyings; + HashMap<String, Varying> varyings; List<Varying> varyings_list; mutable SafeFlag dirty; @@ -158,7 +158,7 @@ private: } }; - Error _write_node(Type p_type, StringBuilder *global_code, StringBuilder *global_code_per_node, Map<Type, StringBuilder> *global_code_per_func, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const; + Error _write_node(Type p_type, StringBuilder *global_code, StringBuilder *global_code_per_node, HashMap<Type, StringBuilder> *global_code_per_func, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, RBSet<int> &processed, bool for_preview, RBSet<StringName> &r_classes) const; void _input_type_changed(Type p_type, int p_id); bool has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const; @@ -255,10 +255,10 @@ class VisualShaderNode : public Resource { int port_preview = -1; - Map<int, Variant> default_input_values; - Map<int, bool> connected_input_ports; - Map<int, int> connected_output_ports; - Map<int, bool> expanded_output_ports; + HashMap<int, Variant> default_input_values; + HashMap<int, bool> connected_input_ports; + HashMap<int, int> connected_output_ports; + HashMap<int, bool> expanded_output_ports; protected: bool simple_decl = true; @@ -328,7 +328,7 @@ public: void set_disabled(bool p_disabled = true); virtual Vector<StringName> get_editable_properties() const; - virtual Map<StringName, String> get_editable_properties_names() const; + virtual HashMap<StringName, String> get_editable_properties_names() const; virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; @@ -680,9 +680,9 @@ protected: String name; }; - Map<int, Port> input_ports; - Map<int, Port> output_ports; - Map<int, Control *> controls; + HashMap<int, Port> input_ports; + HashMap<int, Port> output_ports; + HashMap<int, Control *> controls; protected: static void _bind_methods(); diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 99d5d5c5d5..dbd45793f9 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -2608,8 +2608,6 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad "", // FUNC_SATURATE "-($)", "1.0 / ($)", - "", // FUNC_RGB2HSV - "", // FUNC_HSV2RGB "abs($)", "acos($)", "acosh($)", @@ -2667,43 +2665,7 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad return " " + p_output_vars[0] + " = " + code.replace("$", p_input_vars[0]) + ";\n"; } - String code; - - if (func == FUNC_RGB2HSV) { - if (op_type == OP_TYPE_VECTOR_2D) { // Not supported. - return " " + p_output_vars[0] + " = vec2(0.0);\n"; - } - if (op_type == OP_TYPE_VECTOR_4D) { // Not supported. - return " " + p_output_vars[0] + " = vec4(0.0);\n"; - } - code += " {\n"; - code += " vec3 c = " + p_input_vars[0] + ";\n"; - code += " vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"; - code += " vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n"; - code += " vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"; - code += " float d = q.x - min(q.w, q.y);\n"; - code += " float e = 1.0e-10;\n"; - code += " " + p_output_vars[0] + " = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"; - code += " }\n"; - } else if (func == FUNC_HSV2RGB) { - if (op_type == OP_TYPE_VECTOR_2D) { // Not supported. - return " " + p_output_vars[0] + " = vec2(0.0);\n"; - } - if (op_type == OP_TYPE_VECTOR_4D) { // Not supported. - return " " + p_output_vars[0] + " = vec4(0.0);\n"; - } - code += " {\n"; - code += " vec3 c = " + p_input_vars[0] + ";\n"; - code += " vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n"; - code += " vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n"; - code += " " + p_output_vars[0] + " = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n"; - code += " }\n"; - - } else { - code += " " + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; - } - - return code; + return " " + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; } void VisualShaderNodeVectorFunc::set_op_type(OpType p_op_type) { @@ -2733,13 +2695,6 @@ void VisualShaderNodeVectorFunc::set_function(Function p_func) { if (func == p_func) { return; } - if (p_func == FUNC_RGB2HSV) { - simple_decl = false; - } else if (p_func == FUNC_HSV2RGB) { - simple_decl = false; - } else { - simple_decl = true; - } func = p_func; emit_changed(); } @@ -2754,34 +2709,16 @@ Vector<StringName> VisualShaderNodeVectorFunc::get_editable_properties() const { return props; } -String VisualShaderNodeVectorFunc::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { - bool invalid_type = false; - - if (op_type == OP_TYPE_VECTOR_2D || op_type == OP_TYPE_VECTOR_4D) { - if (func == FUNC_RGB2HSV || func == FUNC_HSV2RGB) { - invalid_type = true; - } - } - - if (invalid_type) { - return RTR("Invalid function for that type."); - } - - return String(); -} - void VisualShaderNodeVectorFunc::_bind_methods() { ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeVectorFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeVectorFunc::get_function); - ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Normalize,Saturate,Negate,Reciprocal,RGB2HSV,HSV2RGB,Abs,ACos,ACosH,ASin,ASinH,ATan,ATanH,Ceil,Cos,CosH,Degrees,Exp,Exp2,Floor,Frac,InverseSqrt,Log,Log2,Radians,Round,RoundEven,Sign,Sin,SinH,Sqrt,Tan,TanH,Trunc,OneMinus"), "set_function", "get_function"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Normalize,Saturate,Negate,Reciprocal,Abs,ACos,ACosH,ASin,ASinH,ATan,ATanH,Ceil,Cos,CosH,Degrees,Exp,Exp2,Floor,Frac,InverseSqrt,Log,Log2,Radians,Round,RoundEven,Sign,Sin,SinH,Sqrt,Tan,TanH,Trunc,OneMinus"), "set_function", "get_function"); BIND_ENUM_CONSTANT(FUNC_NORMALIZE); BIND_ENUM_CONSTANT(FUNC_SATURATE); BIND_ENUM_CONSTANT(FUNC_NEGATE); BIND_ENUM_CONSTANT(FUNC_RECIPROCAL); - BIND_ENUM_CONSTANT(FUNC_RGB2HSV); - BIND_ENUM_CONSTANT(FUNC_HSV2RGB); BIND_ENUM_CONSTANT(FUNC_ABS); BIND_ENUM_CONSTANT(FUNC_ACOS); BIND_ENUM_CONSTANT(FUNC_ACOSH); @@ -2872,6 +2809,25 @@ String VisualShaderNodeColorFunc::generate_code(Shader::Mode p_mode, VisualShade code += " " + p_output_vars[0] + " = vec3(max2, max2, max2);\n"; code += " }\n"; break; + case FUNC_HSV2RGB: + code += " {\n"; + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n"; + code += " vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n"; + code += " " + p_output_vars[0] + " = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n"; + code += " }\n"; + break; + case FUNC_RGB2HSV: + code += " {\n"; + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"; + code += " vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n"; + code += " vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"; + code += " float d = q.x - min(q.w, q.y);\n"; + code += " float e = 1.0e-10;\n"; + code += " " + p_output_vars[0] + " = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"; + code += " }\n"; + break; case FUNC_SEPIA: code += " {\n"; code += " vec3 c = " + p_input_vars[0] + ";\n"; @@ -2911,9 +2867,11 @@ void VisualShaderNodeColorFunc::_bind_methods() { ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeColorFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeColorFunc::get_function); - ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Grayscale,Sepia"), "set_function", "get_function"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Grayscale,HSV2RGB,RGB2HSV,Sepia"), "set_function", "get_function"); BIND_ENUM_CONSTANT(FUNC_GRAYSCALE); + BIND_ENUM_CONSTANT(FUNC_HSV2RGB); + BIND_ENUM_CONSTANT(FUNC_RGB2HSV); BIND_ENUM_CONSTANT(FUNC_SEPIA); BIND_ENUM_CONSTANT(FUNC_MAX); } @@ -5104,7 +5062,7 @@ int VisualShaderNodeColorUniform::get_input_port_count() const { } VisualShaderNodeColorUniform::PortType VisualShaderNodeColorUniform::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR_3D; + return PORT_TYPE_SCALAR; } String VisualShaderNodeColorUniform::get_input_port_name(int p_port) const { @@ -5112,15 +5070,22 @@ String VisualShaderNodeColorUniform::get_input_port_name(int p_port) const { } int VisualShaderNodeColorUniform::get_output_port_count() const { - return 2; + return 1; } VisualShaderNodeColorUniform::PortType VisualShaderNodeColorUniform::get_output_port_type(int p_port) const { - return p_port == 0 ? PORT_TYPE_VECTOR_3D : PORT_TYPE_SCALAR; + return p_port == 0 ? PORT_TYPE_VECTOR_4D : PORT_TYPE_SCALAR; } String VisualShaderNodeColorUniform::get_output_port_name(int p_port) const { - return p_port == 0 ? "color" : "alpha"; //no output port means the editor will be used as port + return "color"; +} + +bool VisualShaderNodeColorUniform::is_output_port_expandable(int p_port) const { + if (p_port == 0) { + return true; + } + return false; } void VisualShaderNodeColorUniform::set_default_value_enabled(bool p_enabled) { @@ -5157,9 +5122,7 @@ String VisualShaderNodeColorUniform::generate_global(Shader::Mode p_mode, Visual } String VisualShaderNodeColorUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - String code = " " + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n"; - code += " " + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n"; - return code; + return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; } bool VisualShaderNodeColorUniform::is_show_prop_names() const { @@ -5819,8 +5782,8 @@ bool VisualShaderNodeTextureUniform::is_show_prop_names() const { return true; } -Map<StringName, String> VisualShaderNodeTextureUniform::get_editable_properties_names() const { - Map<StringName, String> names; +HashMap<StringName, String> VisualShaderNodeTextureUniform::get_editable_properties_names() const { + HashMap<StringName, String> names; names.insert("texture_type", RTR("Type")); names.insert("color_default", RTR("Default Color")); names.insert("texture_filter", RTR("Filter")); diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 26c98bd2ea..b159d25eba 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -1039,8 +1039,6 @@ public: FUNC_SATURATE, FUNC_NEGATE, FUNC_RECIPROCAL, - FUNC_RGB2HSV, - FUNC_HSV2RGB, FUNC_ABS, FUNC_ACOS, FUNC_ACOSH, @@ -1095,7 +1093,6 @@ public: Function get_function() const; virtual Vector<StringName> get_editable_properties() const override; - String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; VisualShaderNodeVectorFunc(); }; @@ -1112,6 +1109,8 @@ class VisualShaderNodeColorFunc : public VisualShaderNode { public: enum Function { FUNC_GRAYSCALE, + FUNC_HSV2RGB, + FUNC_RGB2HSV, FUNC_SEPIA, FUNC_MAX, }; @@ -1922,6 +1921,8 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + bool is_output_port_expandable(int p_port) const override; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; @@ -2174,7 +2175,7 @@ public: virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; - virtual Map<StringName, String> get_editable_properties_names() const override; + virtual HashMap<StringName, String> get_editable_properties_names() const override; virtual bool is_show_prop_names() const override; Vector<StringName> get_editable_properties() const override; diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp index 0879f2e735..54df935168 100644 --- a/scene/resources/visual_shader_particle_nodes.cpp +++ b/scene/resources/visual_shader_particle_nodes.cpp @@ -74,8 +74,8 @@ Vector<StringName> VisualShaderNodeParticleEmitter::get_editable_properties() co return props; } -Map<StringName, String> VisualShaderNodeParticleEmitter::get_editable_properties_names() const { - Map<StringName, String> names; +HashMap<StringName, String> VisualShaderNodeParticleEmitter::get_editable_properties_names() const { + HashMap<StringName, String> names; names.insert("mode_2d", RTR("2D Mode")); return names; } @@ -704,8 +704,8 @@ Vector<StringName> VisualShaderNodeParticleMeshEmitter::get_editable_properties( return props; } -Map<StringName, String> VisualShaderNodeParticleMeshEmitter::get_editable_properties_names() const { - Map<StringName, String> names = VisualShaderNodeParticleEmitter::get_editable_properties_names(); +HashMap<StringName, String> VisualShaderNodeParticleMeshEmitter::get_editable_properties_names() const { + HashMap<StringName, String> names = VisualShaderNodeParticleEmitter::get_editable_properties_names(); names.insert("mesh", RTR("Mesh")); names.insert("use_all_surfaces", RTR("Use All Surfaces")); diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h index 0b91cba5e0..05a059373b 100644 --- a/scene/resources/visual_shader_particle_nodes.h +++ b/scene/resources/visual_shader_particle_nodes.h @@ -52,7 +52,7 @@ public: bool is_mode_2d() const; Vector<StringName> get_editable_properties() const override; - virtual Map<StringName, String> get_editable_properties_names() const override; + virtual HashMap<StringName, String> get_editable_properties_names() const override; bool is_show_prop_names() const override; VisualShaderNodeParticleEmitter(); @@ -153,7 +153,7 @@ public: int get_surface_index() const; Vector<StringName> get_editable_properties() const override; - Map<StringName, String> get_editable_properties_names() const override; + HashMap<StringName, String> get_editable_properties_names() const override; Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; VisualShaderNodeParticleMeshEmitter(); diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index 4a277c3d84..71ae40ec82 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -46,7 +46,7 @@ class World2D : public Resource { RID space; RID navigation_map; - Set<Viewport *> viewports; + RBSet<Viewport *> viewports; protected: static void _bind_methods(); @@ -62,7 +62,7 @@ public: PhysicsDirectSpaceState2D *get_direct_space_state(); - _FORCE_INLINE_ const Set<Viewport *> &get_viewports() { return viewports; } + _FORCE_INLINE_ const RBSet<Viewport *> &get_viewports() { return viewports; } World2D(); ~World2D(); diff --git a/scene/resources/world_3d.h b/scene/resources/world_3d.h index b34b7a2bfb..18d28e812f 100644 --- a/scene/resources/world_3d.h +++ b/scene/resources/world_3d.h @@ -53,7 +53,7 @@ private: Ref<Environment> fallback_environment; Ref<CameraEffects> camera_effects; - Set<Camera3D *> cameras; + RBSet<Camera3D *> cameras; protected: static void _bind_methods(); @@ -77,7 +77,7 @@ public: void set_camera_effects(const Ref<CameraEffects> &p_camera_effects); Ref<CameraEffects> get_camera_effects() const; - _FORCE_INLINE_ const Set<Camera3D *> &get_cameras() const { return cameras; } + _FORCE_INLINE_ const RBSet<Camera3D *> &get_cameras() const { return cameras; } PhysicsDirectSpaceState3D *get_direct_space_state(); diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index 9800707849..8851e1419b 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -125,7 +125,7 @@ class AudioStreamMicrophone : public AudioStream { GDCLASS(AudioStreamMicrophone, AudioStream); friend class AudioStreamPlaybackMicrophone; - Set<AudioStreamPlaybackMicrophone *> playbacks; + RBSet<AudioStreamPlaybackMicrophone *> playbacks; protected: static void _bind_methods(); @@ -192,7 +192,7 @@ private: float weight; }; - Set<AudioStreamPlaybackRandomizer *> playbacks; + RBSet<AudioStreamPlaybackRandomizer *> playbacks; Vector<PoolEntry> audio_stream_pool; float random_pitch_scale = 1.1f; float random_volume_offset_db = 5.0f; diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp index cc317031d4..b7c373479a 100644 --- a/servers/audio/effects/audio_effect_eq.cpp +++ b/servers/audio/effects/audio_effect_eq.cpp @@ -90,9 +90,9 @@ int AudioEffectEQ::get_band_count() const { } bool AudioEffectEQ::_set(const StringName &p_name, const Variant &p_value) { - const Map<StringName, int>::Element *E = prop_band_map.find(p_name); + HashMap<StringName, int>::ConstIterator E = prop_band_map.find(p_name); if (E) { - set_band_gain_db(E->get(), p_value); + set_band_gain_db(E->value, p_value); return true; } @@ -100,9 +100,9 @@ bool AudioEffectEQ::_set(const StringName &p_name, const Variant &p_value) { } bool AudioEffectEQ::_get(const StringName &p_name, Variant &r_ret) const { - const Map<StringName, int>::Element *E = prop_band_map.find(p_name); + HashMap<StringName, int>::ConstIterator E = prop_band_map.find(p_name); if (E) { - r_ret = get_band_gain_db(E->get()); + r_ret = get_band_gain_db(E->value); return true; } diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h index 252f931e6c..9b0560223f 100644 --- a/servers/audio/effects/audio_effect_eq.h +++ b/servers/audio/effects/audio_effect_eq.h @@ -55,7 +55,7 @@ class AudioEffectEQ : public AudioEffect { EQ eq; Vector<float> gain; - Map<StringName, int> prop_band_map; + HashMap<StringName, int> prop_band_map; Vector<String> band_names; protected: diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index c8f48207e4..8ec3e469d3 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1106,13 +1106,13 @@ float AudioServer::get_playback_speed_scale() const { void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time, float p_pitch_scale) { ERR_FAIL_COND(p_playback.is_null()); - Map<StringName, Vector<AudioFrame>> map; + HashMap<StringName, Vector<AudioFrame>> map; map[p_bus] = p_volume_db_vector; start_playback_stream(p_playback, map, p_start_time, p_pitch_scale); } -void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) { +void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) { ERR_FAIL_COND(p_playback.is_null()); AudioStreamPlaybackListNode *playback_node = new AudioStreamPlaybackListNode(); @@ -1173,13 +1173,13 @@ void AudioServer::stop_playback_stream(Ref<AudioStreamPlayback> p_playback) { void AudioServer::set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes) { ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS); - Map<StringName, Vector<AudioFrame>> map; + HashMap<StringName, Vector<AudioFrame>> map; map[p_bus] = p_volumes; set_playback_bus_volumes_linear(p_playback, map); } -void AudioServer::set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes) { +void AudioServer::set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes) { ERR_FAIL_COND(p_bus_volumes.size() > MAX_BUSES_PER_PLAYBACK); AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback); @@ -1215,7 +1215,7 @@ void AudioServer::set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p ERR_FAIL_COND(p_playback.is_null()); ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS); - Map<StringName, Vector<AudioFrame>> map; + HashMap<StringName, Vector<AudioFrame>> map; AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback); if (!playback_node) { diff --git a/servers/audio_server.h b/servers/audio_server.h index 3d8755071a..18e173ff0b 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -263,7 +263,7 @@ private: Vector<Vector<AudioFrame>> temp_buffer; //temp_buffer for each level Vector<AudioFrame> mix_buffer; Vector<Bus *> buses; - Map<StringName, Bus *> bus_map; + HashMap<StringName, Bus *> bus_map; void _update_bus_effects(int p_bus); @@ -365,11 +365,11 @@ public: // Convenience method. void start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time = 0, float p_pitch_scale = 1); // Expose all parameters. - void start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0); + void start_playback_stream(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0); void stop_playback_stream(Ref<AudioStreamPlayback> p_playback); void set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes); - void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes); + void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes); void set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Vector<AudioFrame> p_volumes); void set_playback_pitch_scale(Ref<AudioStreamPlayback> p_playback, float p_pitch_scale); void set_playback_paused(Ref<AudioStreamPlayback> p_playback, bool p_paused); diff --git a/servers/debugger/servers_debugger.cpp b/servers/debugger/servers_debugger.cpp index 02703cacbf..222b475be8 100644 --- a/servers/debugger/servers_debugger.cpp +++ b/servers/debugger/servers_debugger.cpp @@ -199,7 +199,7 @@ class ServersDebugger::ScriptsProfiler : public EngineProfiler { }; Vector<ScriptLanguage::ProfilingInfo> info; Vector<ScriptLanguage::ProfilingInfo *> ptrs; - Map<StringName, int> sig_map; + HashMap<StringName, int> sig_map; int max_frame_functions = 16; public: @@ -277,7 +277,7 @@ class ServersDebugger::ServersProfiler : public EngineProfiler { typedef ServersDebugger::ServerInfo ServerInfo; typedef ServersDebugger::ServerFunctionInfo ServerFunctionInfo; - Map<StringName, ServerInfo> server_data; + HashMap<StringName, ServerInfo> server_data; ScriptsProfiler scripts_profiler; double frame_time = 0; @@ -292,13 +292,13 @@ class ServersDebugger::ServersProfiler : public EngineProfiler { frame.process_time = process_time; frame.physics_time = physics_time; frame.physics_frame_time = physics_frame_time; - Map<StringName, ServerInfo>::Element *E = server_data.front(); + HashMap<StringName, ServerInfo>::Iterator E = server_data.begin(); while (E) { if (!p_final) { - frame.servers.push_back(E->get()); + frame.servers.push_back(E->value); } - E->get().functions.clear(); - E = E->next(); + E->value.functions.clear(); + ++E; } uint64_t time = 0; scripts_profiler.write_frame_data(frame.script_functions, time, p_final); @@ -357,7 +357,7 @@ class ServersDebugger::VisualProfiler : public EngineProfiler { typedef ServersDebugger::ServerInfo ServerInfo; typedef ServersDebugger::ServerFunctionInfo ServerFunctionInfo; - Map<StringName, ServerInfo> server_data; + HashMap<StringName, ServerInfo> server_data; public: void toggle(bool p_enable, const Array &p_opts) { diff --git a/servers/extensions/physics_server_3d_extension.cpp b/servers/extensions/physics_server_3d_extension.cpp index b2a9273538..b073e837e2 100644 --- a/servers/extensions/physics_server_3d_extension.cpp +++ b/servers/extensions/physics_server_3d_extension.cpp @@ -34,7 +34,7 @@ bool PhysicsDirectSpaceState3DExtension::is_body_excluded_from_query(const RID & return exclude && exclude->has(p_body); } -thread_local const Set<RID> *PhysicsDirectSpaceState3DExtension::exclude = nullptr; +thread_local const RBSet<RID> *PhysicsDirectSpaceState3DExtension::exclude = nullptr; void PhysicsDirectSpaceState3DExtension::_bind_methods() { GDVIRTUAL_BIND(_intersect_ray, "from", "to", "collision_mask", "collide_with_bodies", "collide_with_areas", "hit_from_inside", "hit_back_faces", "result"); @@ -113,8 +113,8 @@ void PhysicsDirectBodyState3DExtension::_bind_methods() { PhysicsDirectBodyState3DExtension::PhysicsDirectBodyState3DExtension() { } -thread_local const Set<RID> *PhysicsServer3DExtension::exclude_bodies = nullptr; -thread_local const Set<ObjectID> *PhysicsServer3DExtension::exclude_objects = nullptr; +thread_local const RBSet<RID> *PhysicsServer3DExtension::exclude_bodies = nullptr; +thread_local const RBSet<ObjectID> *PhysicsServer3DExtension::exclude_objects = nullptr; bool PhysicsServer3DExtension::body_test_motion_is_excluding_body(RID p_body) const { return exclude_bodies && exclude_bodies->has(p_body); diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h index ce6bed41c9..8b49278306 100644 --- a/servers/extensions/physics_server_3d_extension.h +++ b/servers/extensions/physics_server_3d_extension.h @@ -122,7 +122,7 @@ GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionShapeRestInfo) class PhysicsDirectSpaceState3DExtension : public PhysicsDirectSpaceState3D { GDCLASS(PhysicsDirectSpaceState3DExtension, PhysicsDirectSpaceState3D); - thread_local static const Set<RID> *exclude; + thread_local static const RBSet<RID> *exclude; protected: static void _bind_methods(); @@ -388,8 +388,8 @@ public: GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform3D &, const Vector3 &, real_t, int, bool, GDNativePtr<PhysicsServer3DExtensionMotionResult>) - thread_local static const Set<RID> *exclude_bodies; - thread_local static const Set<ObjectID> *exclude_objects; + thread_local static const RBSet<RID> *exclude_bodies; + thread_local static const RBSet<ObjectID> *exclude_objects; bool body_test_motion_is_excluding_body(RID p_body) const; bool body_test_motion_is_excluding_object(ObjectID p_object) const; diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index a92fe8c79a..901d335017 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -170,8 +170,12 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point); ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner); + ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer2D::map_get_regions); + ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer2D::map_get_agents); + ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create); ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map); + ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer2D::region_get_map); ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer2D::region_set_layers); ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer2D::region_get_layers); ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform); @@ -182,6 +186,7 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map); + ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer2D::agent_get_map); ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer2D::agent_set_neighbor_dist); ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer2D::agent_set_max_neighbors); ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer2D::agent_set_time_horizon); @@ -208,6 +213,14 @@ NavigationServer2D::~NavigationServer2D() { singleton = nullptr; } +Array FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid); + +Array FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid); + +RID FORWARD_1_C(region_get_map, RID, p_region, rid_to_rid); + +RID FORWARD_1_C(agent_get_map, RID, p_agent, rid_to_rid); + RID FORWARD_0_C(map_create); void FORWARD_2_C(map_set_active, RID, p_map, bool, p_active, rid_to_rid, bool_to_bool); diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index 7350eeb5b1..dfdcf5fca8 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -80,11 +80,15 @@ public: virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const; virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const; + virtual Array map_get_regions(RID p_map) const; + virtual Array map_get_agents(RID p_map) const; + /// Creates a new region. virtual RID region_create() const; /// Set the map of this region. virtual void region_set_map(RID p_region, RID p_map) const; + virtual RID region_get_map(RID p_region) const; /// Set the region's layers virtual void region_set_layers(RID p_region, uint32_t p_layers) const; @@ -106,6 +110,7 @@ public: /// Put the agent in the map. virtual void agent_set_map(RID p_agent, RID p_map) const; + virtual RID agent_get_map(RID p_agent) const; /// The maximum distance (center point to /// center point) to other agents this agent diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 46192772f6..0ce869ad1a 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -48,8 +48,12 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal); ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer3D::map_get_closest_point_owner); + ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer3D::map_get_regions); + ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer3D::map_get_agents); + ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create); ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map); + ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer3D::region_get_map); ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer3D::region_set_layers); ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer3D::region_get_layers); ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform); @@ -61,6 +65,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map); + ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer3D::agent_get_map); ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer3D::agent_set_neighbor_dist); ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer3D::agent_set_max_neighbors); ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer3D::agent_set_time_horizon); diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 0a75b07931..c3d3a589a9 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -91,11 +91,15 @@ public: virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0; virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0; + virtual Array map_get_regions(RID p_map) const = 0; + virtual Array map_get_agents(RID p_map) const = 0; + /// Creates a new region. virtual RID region_create() const = 0; /// Set the map of this region. virtual void region_set_map(RID p_region, RID p_map) const = 0; + virtual RID region_get_map(RID p_region) const = 0; /// Set the region's layers virtual void region_set_layers(RID p_region, uint32_t p_layers) const = 0; @@ -120,6 +124,7 @@ public: /// Put the agent in the map. virtual void agent_set_map(RID p_agent, RID p_map) const = 0; + virtual RID agent_get_map(RID p_agent) const = 0; /// The maximum distance (center point to /// center point) to other agents this agent diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp index 9937178550..11208f2d5b 100644 --- a/servers/physics_2d/godot_area_2d.cpp +++ b/servers/physics_2d/godot_area_2d.cpp @@ -225,22 +225,24 @@ void GodotArea2D::call_queries() { resptr[i] = &res[i]; } - for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) { - if (E->get().state == 0) { // Nothing happened - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_bodies.erase(E); + for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_bodies.begin(); E;) { + if (E->value.state == 0) { // Nothing happened + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_bodies.remove(E); E = next; continue; } - res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; - res[1] = E->key().rid; - res[2] = E->key().instance_id; - res[3] = E->key().body_shape; - res[4] = E->key().area_shape; + res[0] = E->value.state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; + res[1] = E->key.rid; + res[2] = E->key.instance_id; + res[3] = E->key.body_shape; + res[4] = E->key.area_shape; - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_bodies.erase(E); + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_bodies.remove(E); E = next; Callable::CallError ce; @@ -261,22 +263,24 @@ void GodotArea2D::call_queries() { resptr[i] = &res[i]; } - for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) { - if (E->get().state == 0) { // Nothing happened - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_areas.erase(E); + for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_areas.begin(); E;) { + if (E->value.state == 0) { // Nothing happened + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_areas.remove(E); E = next; continue; } - res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; - res[1] = E->key().rid; - res[2] = E->key().instance_id; - res[3] = E->key().body_shape; - res[4] = E->key().area_shape; + res[0] = E->value.state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; + res[1] = E->key.rid; + res[2] = E->key.instance_id; + res[3] = E->key.body_shape; + res[4] = E->key.area_shape; - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_areas.erase(E); + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_areas.remove(E); E = next; Callable::CallError ce; diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h index dadd9747b1..b825ea5cdb 100644 --- a/servers/physics_2d/godot_area_2d.h +++ b/servers/physics_2d/godot_area_2d.h @@ -68,16 +68,15 @@ class GodotArea2D : public GodotCollisionObject2D { uint32_t body_shape = 0; uint32_t area_shape = 0; - _FORCE_INLINE_ bool operator<(const BodyKey &p_key) const { - if (rid == p_key.rid) { - if (body_shape == p_key.body_shape) { - return area_shape < p_key.area_shape; - } else { - return body_shape < p_key.body_shape; - } - } else { - return rid < p_key.rid; - } + static uint32_t hash(const BodyKey &p_key) { + uint32_t h = hash_one_uint64(p_key.rid.get_id()); + h = hash_djb2_one_64(p_key.instance_id, h); + h = hash_djb2_one_32(p_key.area_shape, h); + return hash_djb2_one_32(p_key.body_shape, h); + } + + _FORCE_INLINE_ bool operator==(const BodyKey &p_key) const { + return rid == p_key.rid && instance_id == p_key.instance_id && body_shape == p_key.body_shape && area_shape == p_key.area_shape; } _FORCE_INLINE_ BodyKey() {} @@ -91,10 +90,10 @@ class GodotArea2D : public GodotCollisionObject2D { _FORCE_INLINE_ void dec() { state--; } }; - Map<BodyKey, BodyState> monitored_bodies; - Map<BodyKey, BodyState> monitored_areas; + HashMap<BodyKey, BodyState, BodyKey> monitored_bodies; + HashMap<BodyKey, BodyState, BodyKey> monitored_areas; - Set<GodotConstraint2D *> constraints; + RBSet<GodotConstraint2D *> constraints; virtual void _shapes_changed() override; void _queue_monitor_update(); @@ -143,7 +142,7 @@ public: _FORCE_INLINE_ void add_constraint(GodotConstraint2D *p_constraint) { constraints.insert(p_constraint); } _FORCE_INLINE_ void remove_constraint(GodotConstraint2D *p_constraint) { constraints.erase(p_constraint); } - _FORCE_INLINE_ const Set<GodotConstraint2D *> &get_constraints() const { return constraints; } + _FORCE_INLINE_ const RBSet<GodotConstraint2D *> &get_constraints() const { return constraints; } _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } void set_monitorable(bool p_monitorable); diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp index 650a95c914..f82f2533f3 100644 --- a/servers/physics_2d/godot_physics_server_2d.cpp +++ b/servers/physics_2d/godot_physics_server_2d.cpp @@ -1179,7 +1179,7 @@ void GodotPhysicsServer2D::free(RID p_rid) { GodotShape2D *shape = shape_owner.get_or_null(p_rid); while (shape->get_owners().size()) { - GodotShapeOwner2D *so = shape->get_owners().front()->key(); + GodotShapeOwner2D *so = shape->get_owners().begin()->key; so->remove_shape(shape); } @@ -1250,7 +1250,7 @@ void GodotPhysicsServer2D::step(real_t p_step) { island_count = 0; active_objects = 0; collision_pairs = 0; - for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (RBSet<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { stepper->step(const_cast<GodotSpace2D *>(E->get()), p_step); island_count += E->get()->get_island_count(); active_objects += E->get()->get_active_objects(); @@ -1271,7 +1271,7 @@ void GodotPhysicsServer2D::flush_queries() { uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); - for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (RBSet<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { GodotSpace2D *space = const_cast<GodotSpace2D *>(E->get()); space->call_queries(); } @@ -1292,7 +1292,7 @@ void GodotPhysicsServer2D::flush_queries() { total_time[i] = 0; } - for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (RBSet<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) { total_time[i] += E->get()->get_elapsed_time(GodotSpace2D::ElapsedTime(i)); } diff --git a/servers/physics_2d/godot_physics_server_2d.h b/servers/physics_2d/godot_physics_server_2d.h index 0a84caadc5..55a7b39b9e 100644 --- a/servers/physics_2d/godot_physics_server_2d.h +++ b/servers/physics_2d/godot_physics_server_2d.h @@ -56,7 +56,7 @@ class GodotPhysicsServer2D : public PhysicsServer2D { bool flushing_queries = false; GodotStep2D *stepper = nullptr; - Set<const GodotSpace2D *> active_spaces; + RBSet<const GodotSpace2D *> active_spaces; mutable RID_PtrOwner<GodotShape2D, true> shape_owner; mutable RID_PtrOwner<GodotSpace2D, true> space_owner; diff --git a/servers/physics_2d/godot_shape_2d.cpp b/servers/physics_2d/godot_shape_2d.cpp index 6c020f9e72..72ade3757b 100644 --- a/servers/physics_2d/godot_shape_2d.cpp +++ b/servers/physics_2d/godot_shape_2d.cpp @@ -50,20 +50,20 @@ Vector2 GodotShape2D::get_support(const Vector2 &p_normal) const { } void GodotShape2D::add_owner(GodotShapeOwner2D *p_owner) { - Map<GodotShapeOwner2D *, int>::Element *E = owners.find(p_owner); + HashMap<GodotShapeOwner2D *, int>::Iterator E = owners.find(p_owner); if (E) { - E->get()++; + E->value++; } else { owners[p_owner] = 1; } } void GodotShape2D::remove_owner(GodotShapeOwner2D *p_owner) { - Map<GodotShapeOwner2D *, int>::Element *E = owners.find(p_owner); + HashMap<GodotShapeOwner2D *, int>::Iterator E = owners.find(p_owner); ERR_FAIL_COND(!E); - E->get()--; - if (E->get() == 0) { - owners.erase(E); + E->value--; + if (E->value == 0) { + owners.remove(E); } } @@ -71,7 +71,7 @@ bool GodotShape2D::is_owner(GodotShapeOwner2D *p_owner) const { return owners.has(p_owner); } -const Map<GodotShapeOwner2D *, int> &GodotShape2D::get_owners() const { +const HashMap<GodotShapeOwner2D *, int> &GodotShape2D::get_owners() const { return owners; } @@ -841,7 +841,7 @@ void GodotConcavePolygonShape2D::set_data(const Variant &p_data) { const Vector2 *arr = p2arr.ptr(); - Map<Point2, int> pointmap; + HashMap<Point2, int> pointmap; for (int i = 0; i < len; i += 2) { Point2 p1 = arr[i]; Point2 p2 = arr[i + 1]; @@ -868,7 +868,7 @@ void GodotConcavePolygonShape2D::set_data(const Variant &p_data) { } points.resize(pointmap.size()); - aabb.position = pointmap.front()->key(); + aabb.position = pointmap.begin()->key; for (const KeyValue<Point2, int> &E : pointmap) { aabb.expand_to(E.key); points.write[E.value] = E.key; diff --git a/servers/physics_2d/godot_shape_2d.h b/servers/physics_2d/godot_shape_2d.h index 9b3477cea8..cede01e18d 100644 --- a/servers/physics_2d/godot_shape_2d.h +++ b/servers/physics_2d/godot_shape_2d.h @@ -50,7 +50,7 @@ class GodotShape2D { bool configured = false; real_t custom_bias = 0.0; - Map<GodotShapeOwner2D *, int> owners; + HashMap<GodotShapeOwner2D *, int> owners; protected: void configure(const Rect2 &p_aabb); @@ -86,7 +86,7 @@ public: void add_owner(GodotShapeOwner2D *p_owner); void remove_owner(GodotShapeOwner2D *p_owner); bool is_owner(GodotShapeOwner2D *p_owner) const; - const Map<GodotShapeOwner2D *, int> &get_owners() const; + const HashMap<GodotShapeOwner2D *, int> &get_owners() const; _FORCE_INLINE_ void get_supports_transformed_cast(const Vector2 &p_cast, const Vector2 &p_normal, const Transform2D &p_xform, Vector2 *r_supports, int &r_amount) const { get_supports(p_xform.basis_xform_inv(p_normal).normalized(), r_supports, r_amount); diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 3ff7ab86bb..731eab2dfe 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -1073,7 +1073,7 @@ void GodotSpace2D::remove_object(GodotCollisionObject2D *p_object) { objects.erase(p_object); } -const Set<GodotCollisionObject2D *> &GodotSpace2D::get_objects() const { +const RBSet<GodotCollisionObject2D *> &GodotSpace2D::get_objects() const { return objects; } diff --git a/servers/physics_2d/godot_space_2d.h b/servers/physics_2d/godot_space_2d.h index 5d97721176..e8b05fa4f9 100644 --- a/servers/physics_2d/godot_space_2d.h +++ b/servers/physics_2d/godot_space_2d.h @@ -92,7 +92,7 @@ private: static void *_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_self); static void _broadphase_unpair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_data, void *p_self); - Set<GodotCollisionObject2D *> objects; + RBSet<GodotCollisionObject2D *> objects; GodotArea2D *area = nullptr; @@ -156,7 +156,7 @@ public: void add_object(GodotCollisionObject2D *p_object); void remove_object(GodotCollisionObject2D *p_object); - const Set<GodotCollisionObject2D *> &get_objects() const; + const RBSet<GodotCollisionObject2D *> &get_objects() const; _FORCE_INLINE_ int get_solver_iterations() const { return solver_iterations; } _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; } diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index fd72038be3..0df5c1aabc 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -168,7 +168,7 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) { const SelfList<GodotArea2D>::List &aml = p_space->get_moved_area_list(); while (aml.first()) { - for (const Set<GodotConstraint2D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { + for (const RBSet<GodotConstraint2D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { GodotConstraint2D *constraint = E->get(); if (constraint->get_island_step() == _step) { continue; diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp index e7df23d0d8..e2ad765d62 100644 --- a/servers/physics_3d/godot_area_3d.cpp +++ b/servers/physics_3d/godot_area_3d.cpp @@ -254,22 +254,24 @@ void GodotArea3D::call_queries() { resptr[i] = &res[i]; } - for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) { - if (E->get().state == 0) { // Nothing happened - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_bodies.erase(E); + for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_bodies.begin(); E;) { + if (E->value.state == 0) { // Nothing happened + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_bodies.remove(E); E = next; continue; } - res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; - res[1] = E->key().rid; - res[2] = E->key().instance_id; - res[3] = E->key().body_shape; - res[4] = E->key().area_shape; + res[0] = E->value.state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; + res[1] = E->key.rid; + res[2] = E->key.instance_id; + res[3] = E->key.body_shape; + res[4] = E->key.area_shape; - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_bodies.erase(E); + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_bodies.remove(E); E = next; Callable::CallError ce; @@ -290,22 +292,24 @@ void GodotArea3D::call_queries() { resptr[i] = &res[i]; } - for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) { - if (E->get().state == 0) { // Nothing happened - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_areas.erase(E); + for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_areas.begin(); E;) { + if (E->value.state == 0) { // Nothing happened + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_areas.remove(E); E = next; continue; } - res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; - res[1] = E->key().rid; - res[2] = E->key().instance_id; - res[3] = E->key().body_shape; - res[4] = E->key().area_shape; + res[0] = E->value.state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; + res[1] = E->key.rid; + res[2] = E->key.instance_id; + res[3] = E->key.body_shape; + res[4] = E->key.area_shape; - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_areas.erase(E); + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_areas.remove(E); E = next; Callable::CallError ce; diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h index d15f8ec0a6..2a5e5a537a 100644 --- a/servers/physics_3d/godot_area_3d.h +++ b/servers/physics_3d/godot_area_3d.h @@ -72,16 +72,15 @@ class GodotArea3D : public GodotCollisionObject3D { uint32_t body_shape = 0; uint32_t area_shape = 0; - _FORCE_INLINE_ bool operator<(const BodyKey &p_key) const { - if (rid == p_key.rid) { - if (body_shape == p_key.body_shape) { - return area_shape < p_key.area_shape; - } else { - return body_shape < p_key.body_shape; - } - } else { - return rid < p_key.rid; - } + static uint32_t hash(const BodyKey &p_key) { + uint32_t h = hash_one_uint64(p_key.rid.get_id()); + h = hash_djb2_one_64(p_key.instance_id, h); + h = hash_djb2_one_32(p_key.area_shape, h); + return hash_djb2_one_32(p_key.body_shape, h); + } + + _FORCE_INLINE_ bool operator==(const BodyKey &p_key) const { + return rid == p_key.rid && instance_id == p_key.instance_id && body_shape == p_key.body_shape && area_shape == p_key.area_shape; } _FORCE_INLINE_ BodyKey() {} @@ -96,11 +95,11 @@ class GodotArea3D : public GodotCollisionObject3D { _FORCE_INLINE_ void dec() { state--; } }; - Map<BodyKey, BodyState> monitored_soft_bodies; - Map<BodyKey, BodyState> monitored_bodies; - Map<BodyKey, BodyState> monitored_areas; + HashMap<BodyKey, BodyState, BodyKey> monitored_soft_bodies; + HashMap<BodyKey, BodyState, BodyKey> monitored_bodies; + HashMap<BodyKey, BodyState, BodyKey> monitored_areas; - Set<GodotConstraint3D *> constraints; + RBSet<GodotConstraint3D *> constraints; virtual void _shapes_changed() override; void _queue_monitor_update(); @@ -164,7 +163,7 @@ public: _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint) { constraints.insert(p_constraint); } _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraints.erase(p_constraint); } - _FORCE_INLINE_ const Set<GodotConstraint3D *> &get_constraints() const { return constraints; } + _FORCE_INLINE_ const RBSet<GodotConstraint3D *> &get_constraints() const { return constraints; } _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } void set_monitorable(bool p_monitorable); diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index c0c847d920..93bd5a0071 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -112,7 +112,7 @@ class GodotBody3D : public GodotCollisionObject3D { virtual void _shapes_changed() override; Transform3D new_transform; - Map<GodotConstraint3D *, int> constraint_map; + HashMap<GodotConstraint3D *, int> constraint_map; Vector<AreaCMP> areas; @@ -196,7 +196,7 @@ public: _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; } _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraint_map.erase(p_constraint); } - const Map<GodotConstraint3D *, int> &get_constraint_map() const { return constraint_map; } + const HashMap<GodotConstraint3D *, int> &get_constraint_map() const { return constraint_map; } _FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); } _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; } diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp index e5107be74b..cb4988757c 100644 --- a/servers/physics_3d/godot_physics_server_3d.cpp +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -1531,7 +1531,7 @@ void GodotPhysicsServer3D::free(RID p_rid) { GodotShape3D *shape = shape_owner.get_or_null(p_rid); while (shape->get_owners().size()) { - GodotShapeOwner3D *so = shape->get_owners().front()->key(); + GodotShapeOwner3D *so = shape->get_owners().begin()->key; so->remove_shape(shape); } @@ -1611,7 +1611,7 @@ void GodotPhysicsServer3D::step(real_t p_step) { island_count = 0; active_objects = 0; collision_pairs = 0; - for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (RBSet<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { stepper->step(const_cast<GodotSpace3D *>(E->get()), p_step); island_count += E->get()->get_island_count(); active_objects += E->get()->get_active_objects(); @@ -1635,7 +1635,7 @@ void GodotPhysicsServer3D::flush_queries() { uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); - for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (RBSet<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { GodotSpace3D *space = const_cast<GodotSpace3D *>(E->get()); space->call_queries(); } @@ -1656,7 +1656,7 @@ void GodotPhysicsServer3D::flush_queries() { total_time[i] = 0; } - for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (RBSet<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) { total_time[i] += E->get()->get_elapsed_time(GodotSpace3D::ElapsedTime(i)); } diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h index d2078a912c..65c53084ac 100644 --- a/servers/physics_3d/godot_physics_server_3d.h +++ b/servers/physics_3d/godot_physics_server_3d.h @@ -54,7 +54,7 @@ class GodotPhysicsServer3D : public PhysicsServer3D { bool flushing_queries = false; GodotStep3D *stepper = nullptr; - Set<const GodotSpace3D *> active_spaces; + RBSet<const GodotSpace3D *> active_spaces; mutable RID_PtrOwner<GodotShape3D, true> shape_owner; mutable RID_PtrOwner<GodotSpace3D, true> space_owner; diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 2efc11a4c0..5e310670a5 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -76,20 +76,20 @@ Vector3 GodotShape3D::get_support(const Vector3 &p_normal) const { } void GodotShape3D::add_owner(GodotShapeOwner3D *p_owner) { - Map<GodotShapeOwner3D *, int>::Element *E = owners.find(p_owner); + HashMap<GodotShapeOwner3D *, int>::Iterator E = owners.find(p_owner); if (E) { - E->get()++; + E->value++; } else { owners[p_owner] = 1; } } void GodotShape3D::remove_owner(GodotShapeOwner3D *p_owner) { - Map<GodotShapeOwner3D *, int>::Element *E = owners.find(p_owner); + HashMap<GodotShapeOwner3D *, int>::Iterator E = owners.find(p_owner); ERR_FAIL_COND(!E); - E->get()--; - if (E->get() == 0) { - owners.erase(E); + E->value--; + if (E->value == 0) { + owners.remove(E); } } @@ -97,7 +97,7 @@ bool GodotShape3D::is_owner(GodotShapeOwner3D *p_owner) const { return owners.has(p_owner); } -const Map<GodotShapeOwner3D *, int> &GodotShape3D::get_owners() const { +const HashMap<GodotShapeOwner3D *, int> &GodotShape3D::get_owners() const { return owners; } diff --git a/servers/physics_3d/godot_shape_3d.h b/servers/physics_3d/godot_shape_3d.h index 9d171c3928..1fc8f7c711 100644 --- a/servers/physics_3d/godot_shape_3d.h +++ b/servers/physics_3d/godot_shape_3d.h @@ -51,7 +51,7 @@ class GodotShape3D { bool configured = false; real_t custom_bias = 0.0; - Map<GodotShapeOwner3D *, int> owners; + HashMap<GodotShapeOwner3D *, int> owners; protected: void configure(const AABB &p_aabb); @@ -93,7 +93,7 @@ public: void add_owner(GodotShapeOwner3D *p_owner); void remove_owner(GodotShapeOwner3D *p_owner); bool is_owner(GodotShapeOwner3D *p_owner) const; - const Map<GodotShapeOwner3D *, int> &get_owners() const; + const HashMap<GodotShapeOwner3D *, int> &get_owners() const; GodotShape3D() {} virtual ~GodotShape3D(); diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp index be4b41292d..9cc7912a5a 100644 --- a/servers/physics_3d/godot_soft_body_3d.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -33,7 +33,7 @@ #include "godot_space_3d.h" #include "core/math/geometry_3d.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "servers/rendering_server.h" // Based on Bullet soft body. @@ -494,7 +494,7 @@ bool GodotSoftBody3D::create_from_trimesh(const Vector<int> &p_indices, const Ve // Process vertices. { uint32_t vertex_count = 0; - Map<Vector3, uint32_t> unique_vertices; + HashMap<Vector3, uint32_t> unique_vertices; vertices.resize(visual_vertex_count); map_visual_to_physics.resize(visual_vertex_count); @@ -502,11 +502,11 @@ bool GodotSoftBody3D::create_from_trimesh(const Vector<int> &p_indices, const Ve for (int visual_vertex_index = 0; visual_vertex_index < visual_vertex_count; ++visual_vertex_index) { const Vector3 &vertex = p_vertices[visual_vertex_index]; - Map<Vector3, uint32_t>::Element *e = unique_vertices.find(vertex); + HashMap<Vector3, uint32_t>::Iterator e = unique_vertices.find(vertex); uint32_t vertex_id; if (e) { // Already existing. - vertex_id = e->value(); + vertex_id = e->value; } else { // Create new one. vertex_id = vertex_count++; diff --git a/servers/physics_3d/godot_soft_body_3d.h b/servers/physics_3d/godot_soft_body_3d.h index 96f63e5819..094ab39c47 100644 --- a/servers/physics_3d/godot_soft_body_3d.h +++ b/servers/physics_3d/godot_soft_body_3d.h @@ -38,7 +38,7 @@ #include "core/math/dynamic_bvh.h" #include "core/math/vector3.h" #include "core/templates/local_vector.h" -#include "core/templates/set.h" +#include "core/templates/rb_set.h" #include "core/templates/vset.h" class GodotConstraint3D; @@ -103,7 +103,7 @@ class GodotSoftBody3D : public GodotCollisionObject3D { SelfList<GodotSoftBody3D> active_list; - Set<GodotConstraint3D *> constraints; + RBSet<GodotConstraint3D *> constraints; Vector<AreaCMP> areas; @@ -123,7 +123,7 @@ public: _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint) { constraints.insert(p_constraint); } _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraints.erase(p_constraint); } - _FORCE_INLINE_ const Set<GodotConstraint3D *> &get_constraints() const { return constraints; } + _FORCE_INLINE_ const RBSet<GodotConstraint3D *> &get_constraints() const { return constraints; } _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } _FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); } diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 0b84520c39..9c051b23f6 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -1096,7 +1096,7 @@ void GodotSpace3D::remove_object(GodotCollisionObject3D *p_object) { objects.erase(p_object); } -const Set<GodotCollisionObject3D *> &GodotSpace3D::get_objects() const { +const RBSet<GodotCollisionObject3D *> &GodotSpace3D::get_objects() const { return objects; } diff --git a/servers/physics_3d/godot_space_3d.h b/servers/physics_3d/godot_space_3d.h index 6308ede9a9..67dde30fb5 100644 --- a/servers/physics_3d/godot_space_3d.h +++ b/servers/physics_3d/godot_space_3d.h @@ -89,7 +89,7 @@ private: static void *_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_self); static void _broadphase_unpair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_data, void *p_self); - Set<GodotCollisionObject3D *> objects; + RBSet<GodotCollisionObject3D *> objects; GodotArea3D *area = nullptr; @@ -158,7 +158,7 @@ public: void add_object(GodotCollisionObject3D *p_object); void remove_object(GodotCollisionObject3D *p_object); - const Set<GodotCollisionObject3D *> &get_objects() const; + const RBSet<GodotCollisionObject3D *> &get_objects() const; _FORCE_INLINE_ int get_solver_iterations() const { return solver_iterations; } _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; } diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index 204adae450..b46436ba39 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -87,7 +87,7 @@ void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D void GodotStep3D::_populate_island_soft_body(GodotSoftBody3D *p_soft_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island) { p_soft_body->set_island_step(_step); - for (Set<GodotConstraint3D *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) { + for (RBSet<GodotConstraint3D *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) { GodotConstraint3D *constraint = const_cast<GodotConstraint3D *>(E->get()); if (constraint->get_island_step() == _step) { continue; // Already processed. @@ -236,7 +236,7 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) { const SelfList<GodotArea3D>::List &aml = p_space->get_moved_area_list(); while (aml.first()) { - for (const Set<GodotConstraint3D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { + for (const RBSet<GodotConstraint3D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { GodotConstraint3D *constraint = E->get(); if (constraint->get_island_step() == _step) { continue; diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index d6d23f8310..4aeaa7497f 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -158,7 +158,7 @@ Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; @@ -208,7 +208,7 @@ Vector<RID> PhysicsPointQueryParameters2D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; @@ -267,7 +267,7 @@ Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 2f70b88e30..bd53764932 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -127,7 +127,7 @@ public: struct RayParameters { Vector2 from; Vector2 to; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -157,7 +157,7 @@ public: struct PointParameters { Vector2 position; ObjectID canvas_instance_id; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -173,7 +173,7 @@ public: Transform2D transform; Vector2 motion; real_t margin = 0.0; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -483,8 +483,8 @@ public: Vector2 motion; real_t margin = 0.08; bool collide_separation_ray = false; - Set<RID> exclude_bodies; - Set<ObjectID> exclude_objects; + RBSet<RID> exclude_bodies; + RBSet<ObjectID> exclude_objects; MotionParameters() {} diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index bfe93f0dfb..d05f5128b2 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -177,7 +177,7 @@ Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; @@ -231,7 +231,7 @@ Vector<RID> PhysicsPointQueryParameters3D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; @@ -286,7 +286,7 @@ Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 47f3fc2027..c707f621b4 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -133,7 +133,7 @@ public: struct RayParameters { Vector3 from; Vector3 to; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -165,7 +165,7 @@ public: struct PointParameters { Vector3 position; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -179,7 +179,7 @@ public: Transform3D transform; Vector3 motion; real_t margin = 0.0; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -520,8 +520,8 @@ public: real_t margin = 0.001; int max_collisions = 1; bool collide_separation_ray = false; - Set<RID> exclude_bodies; - Set<ObjectID> exclude_objects; + RBSet<RID> exclude_bodies; + RBSet<ObjectID> exclude_objects; MotionParameters() {} diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h index 6cad45ea6d..5c6fcc8386 100644 --- a/servers/rendering/dummy/rasterizer_dummy.h +++ b/servers/rendering/dummy/rasterizer_dummy.h @@ -95,9 +95,9 @@ public: static void make_current() { _create_func = _create_current; + low_end = true; } - bool is_low_end() const override { return true; } uint64_t get_frame_number() const override { return frame; } double get_frame_delta_time() const override { return delta; } diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 84ab19880c..46bc22ad54 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -1831,7 +1831,7 @@ void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygo RSG::canvas_render->occluder_polygon_set_shape(occluder_poly->occluder, p_shape, p_closed); - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { E->get()->aabb_cache = occluder_poly->aabb; } } @@ -1841,7 +1841,7 @@ void RendererCanvasCull::canvas_occluder_polygon_set_cull_mode(RID p_occluder_po ERR_FAIL_COND(!occluder_poly); occluder_poly->cull_mode = p_mode; RSG::canvas_render->occluder_polygon_set_cull_mode(occluder_poly->occluder, p_mode); - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { E->get()->cull_cache = p_mode; } } @@ -1931,7 +1931,7 @@ bool RendererCanvasCull::free(RID p_rid) { RendererViewport::Viewport *vp = RSG::viewport->viewport_owner.get_or_null(canvas->viewports.front()->get()); ERR_FAIL_COND_V(!vp, true); - Map<RID, RendererViewport::Viewport::CanvasData>::Element *E = vp->canvas_map.find(p_rid); + HashMap<RID, RendererViewport::Viewport::CanvasData>::Iterator E = vp->canvas_map.find(p_rid); ERR_FAIL_COND_V(!E, true); vp->canvas_map.erase(p_rid); @@ -1942,11 +1942,11 @@ bool RendererCanvasCull::free(RID p_rid) { canvas->child_items[i].item->parent = RID(); } - for (Set<RendererCanvasRender::Light *>::Element *E = canvas->lights.front(); E; E = E->next()) { + for (RBSet<RendererCanvasRender::Light *>::Element *E = canvas->lights.front(); E; E = E->next()) { E->get()->canvas = RID(); } - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = canvas->occluders.front(); E; E = E->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *E = canvas->occluders.front(); E; E = E->next()) { E->get()->canvas = RID(); } diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 637245502d..6f3cd1d2c6 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -108,7 +108,7 @@ public: Rect2 aabb; RS::CanvasOccluderPolygonCullMode cull_mode; RID occluder; - Set<RendererCanvasRender::LightOccluderInstance *> owners; + RBSet<RendererCanvasRender::LightOccluderInstance *> owners; LightOccluderPolygon() { active = false; @@ -121,7 +121,7 @@ public: RID_Owner<RendererCanvasRender::LightOccluderInstance, true> canvas_light_occluder_owner; struct Canvas : public RendererViewport::CanvasBase { - Set<RID> viewports; + RBSet<RID> viewports; struct ChildItem { Point2 mirror; Item *item = nullptr; @@ -130,10 +130,10 @@ public: } }; - Set<RendererCanvasRender::Light *> lights; - Set<RendererCanvasRender::Light *> directional_lights; + RBSet<RendererCanvasRender::Light *> lights; + RBSet<RendererCanvasRender::Light *> directional_lights; - Set<RendererCanvasRender::LightOccluderInstance *> occluders; + RBSet<RendererCanvasRender::LightOccluderInstance *> occluders; bool children_order_dirty; Vector<ChildItem> child_items; diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp index fa4d9c8b31..b331ec2c1d 100644 --- a/servers/rendering/renderer_compositor.cpp +++ b/servers/rendering/renderer_compositor.cpp @@ -35,6 +35,7 @@ #include "core/string/print_string.h" RendererCompositor *(*RendererCompositor::_create_func)() = nullptr; +bool RendererCompositor::low_end = false; RendererCompositor *RendererCompositor::create() { return _create_func(); diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index 9466148a31..df3df1077a 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -71,6 +71,7 @@ private: protected: static RendererCompositor *(*_create_func)(); bool back_end = false; + static bool low_end; public: static RendererCompositor *create(); @@ -97,7 +98,7 @@ public: virtual uint64_t get_frame_number() const = 0; virtual double get_frame_delta_time() const = 0; - _FORCE_INLINE_ virtual bool is_low_end() const { return back_end; }; + static bool is_low_end() { return low_end; }; virtual bool is_xr_enabled() const; RendererCompositor(); diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp new file mode 100644 index 0000000000..cc7441776d --- /dev/null +++ b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp @@ -0,0 +1,475 @@ +/*************************************************************************/ +/* bokeh_dof.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 "bokeh_dof.h" +#include "copy_effects.h" +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" + +using namespace RendererRD; + +BokehDOF::BokehDOF(bool p_prefer_raster_effects) { + prefer_raster_effects = p_prefer_raster_effects; + + // Initialize bokeh + Vector<String> bokeh_modes; + bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n#define OUTPUT_WEIGHT\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n#define OUTPUT_WEIGHT\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n#define OUTPUT_WEIGHT\n"); + bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n"); + if (prefer_raster_effects) { + bokeh.raster_shader.initialize(bokeh_modes); + + bokeh.shader_version = bokeh.raster_shader.version_create(); + + const int att_count[BOKEH_MAX] = { 1, 2, 1, 2, 1, 2, 1 }; + for (int i = 0; i < BOKEH_MAX; i++) { + RD::PipelineColorBlendState blend_state = (i == BOKEH_COMPOSITE) ? RD::PipelineColorBlendState::create_blend(att_count[i]) : RD::PipelineColorBlendState::create_disabled(att_count[i]); + bokeh.raster_pipelines[i].setup(bokeh.raster_shader.version_get_shader(bokeh.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } + } else { + bokeh.compute_shader.initialize(bokeh_modes); + bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_BOX_NOWEIGHT, false); + bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, false); + bokeh.shader_version = bokeh.compute_shader.version_create(); + + for (int i = 0; i < BOKEH_MAX; i++) { + if (bokeh.compute_shader.is_variant_enabled(i)) { + bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i)); + } + } + + for (int i = 0; i < BOKEH_MAX; i++) { + bokeh.raster_pipelines[i].clear(); + } + } +} + +BokehDOF::~BokehDOF() { + if (prefer_raster_effects) { + bokeh.raster_shader.version_free(bokeh.shader_version); + } else { + bokeh.compute_shader.version_free(bokeh.shader_version); + } +} + +void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of bokeh depth of field with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // setup our push constant + memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant)); + bokeh.push_constant.blur_far_active = p_dof_far; + bokeh.push_constant.blur_far_begin = p_dof_far_begin; + bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; + + bokeh.push_constant.blur_near_active = p_dof_near; + bokeh.push_constant.blur_near_begin = p_dof_near_begin; + bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size); + bokeh.push_constant.use_jitter = p_use_jitter; + bokeh.push_constant.jitter_seed = Math::randf() * 1000.0; + + bokeh.push_constant.z_near = p_cam_znear; + bokeh.push_constant.z_far = p_cam_zfar; + bokeh.push_constant.orthogonal = p_cam_orthogonal; + bokeh.push_constant.blur_size = p_bokeh_size; + + bokeh.push_constant.second_pass = false; + bokeh.push_constant.half_size = false; + + bokeh.push_constant.blur_scale = 0.5; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_base_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.base_texture })); + RD::Uniform u_depth_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.depth_texture })); + RD::Uniform u_secondary_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.secondary_texture })); + RD::Uniform u_half_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[0] })); + RD::Uniform u_half_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[1] })); + + RD::Uniform u_base_image(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.base_texture); + RD::Uniform u_secondary_image(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.secondary_texture); + RD::Uniform u_half_image0(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.half_texture[0]); + RD::Uniform u_half_image1(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.half_texture[1]); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + /* FIRST PASS */ + // The alpha channel of the source color texture is filled with the expected circle size + // If used for DOF far, the size is positive, if used for near, its negative. + + RID shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BLUR_SIZE); + ERR_FAIL_COND(shader.is_null()); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_texture), 1); + + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) { + //second pass + BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL; + shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[mode]); + + static const int quality_samples[4] = { 6, 12, 12, 24 }; + + bokeh.push_constant.steps = quality_samples[p_quality]; + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes) + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1); + + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; + bokeh.push_constant.half_size = true; + bokeh.push_constant.blur_size *= 0.5; + + } else { + //medium and high quality use full size + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_secondary_image), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1); + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //third pass + bokeh.push_constant.second_pass = true; + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image1), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_secondary_texture), 1); + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + //forth pass, upscale for low quality + + shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE); + ERR_FAIL_COND(shader.is_null()); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture1), 1); + + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; + bokeh.push_constant.half_size = false; + bokeh.push_constant.second_pass = false; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); + } + } else { + //circle + + shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BOKEH_CIRCULAR); + ERR_FAIL_COND(shader.is_null()); + + //second pass + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]); + + static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 }; + + bokeh.push_constant.steps = 0; + bokeh.push_constant.blur_scale = quality_scale[p_quality]; + + //circle always runs in half size, otherwise too expensive + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1); + + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; + bokeh.push_constant.half_size = true; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //circle is just one pass, then upscale + + // upscale + + shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE); + ERR_FAIL_COND(shader.is_null()); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1); + + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; + bokeh.push_constant.half_size = false; + bokeh.push_constant.second_pass = false; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); + } + + RD::get_singleton()->compute_list_end(); +} + +void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't blur-based depth of field with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // setup our base push constant + memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant)); + + bokeh.push_constant.orthogonal = p_cam_orthogonal; + bokeh.push_constant.size[0] = p_buffers.base_texture_size.width; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.height; + bokeh.push_constant.z_far = p_cam_zfar; + bokeh.push_constant.z_near = p_cam_znear; + + bokeh.push_constant.second_pass = false; + bokeh.push_constant.half_size = false; + bokeh.push_constant.blur_size = p_dof_blur_amount; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_base_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.base_texture })); + RD::Uniform u_depth_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.depth_texture })); + RD::Uniform u_secondary_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.secondary_texture })); + RD::Uniform u_half_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[0] })); + RD::Uniform u_half_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[1] })); + RD::Uniform u_weight_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[0] })); + RD::Uniform u_weight_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[1] })); + RD::Uniform u_weight_texture2(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[2] })); + RD::Uniform u_weight_texture3(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[3] })); + + if (p_dof_far || p_dof_near) { + if (p_dof_far) { + bokeh.push_constant.blur_far_active = true; + bokeh.push_constant.blur_far_begin = p_dof_far_begin; + bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; + } + + if (p_dof_near) { + bokeh.push_constant.blur_near_active = true; + bokeh.push_constant.blur_near_begin = p_dof_near_begin; + bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size; + } + + { + // generate our depth data + RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BLUR_SIZE); + ERR_FAIL_COND(shader.is_null()); + + RID framebuffer = p_buffers.base_weight_fb; + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_depth_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + } + + if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) { + // double pass approach + BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL; + + RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes) + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; + bokeh.push_constant.half_size = true; + bokeh.push_constant.blur_size *= 0.5; + } + + static const int quality_samples[4] = { 6, 12, 12, 24 }; + bokeh.push_constant.blur_scale = 0.5; + bokeh.push_constant.steps = quality_samples[p_quality]; + + RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; + + // Pass 1 + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + // Pass 2 + if (!bokeh.push_constant.half_size) { + // do not output weight, we're writing back into our base buffer + mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT; + + shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + } + bokeh.push_constant.second_pass = true; + + framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[1] : p_buffers.base_fb; + RD::Uniform texture = bokeh.push_constant.half_size ? u_half_texture0 : u_secondary_texture; + RD::Uniform weight = bokeh.push_constant.half_size ? u_weight_texture2 : u_weight_texture1; + + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, texture), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, weight), 1); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + if (bokeh.push_constant.half_size) { + // Compose pass + mode = BOKEH_COMPOSITE; + shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + framebuffer = p_buffers.base_fb; + + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture1), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture3), 1); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_weight_texture0), 2); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + } + + } else { + // circular is a single pass approach + BokehMode mode = BOKEH_GEN_BOKEH_CIRCULAR; + + RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + { + // circle always runs in half size, otherwise too expensive (though the code below does support making this optional) + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; + bokeh.push_constant.half_size = true; + // bokeh.push_constant.blur_size *= 0.5; + } + + static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 }; + bokeh.push_constant.blur_scale = quality_scale[p_quality]; + bokeh.push_constant.steps = 0.0; + + RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + if (bokeh.push_constant.half_size) { + // Compose + mode = BOKEH_COMPOSITE; + shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + framebuffer = p_buffers.base_fb; + + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture0), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture2), 1); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_weight_texture0), 2); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + } else { + CopyEffects::get_singleton()->copy_raster(p_buffers.secondary_texture, p_buffers.base_fb); + } + } + } +} diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h new file mode 100644 index 0000000000..d7b736119c --- /dev/null +++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h @@ -0,0 +1,120 @@ +/*************************************************************************/ +/* bokeh_dof.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 BOKEH_DOF_RD_H +#define BOKEH_DOF_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +namespace RendererRD { + +class BokehDOF { +private: + bool prefer_raster_effects; + + struct BokehPushConstant { + uint32_t size[2]; + float z_far; + float z_near; + + uint32_t orthogonal; + float blur_size; + float blur_scale; + uint32_t steps; + + uint32_t blur_near_active; + float blur_near_begin; + float blur_near_end; + uint32_t blur_far_active; + + float blur_far_begin; + float blur_far_end; + uint32_t second_pass; + uint32_t half_size; + + uint32_t use_jitter; + float jitter_seed; + uint32_t pad[2]; + }; + + enum BokehMode { + BOKEH_GEN_BLUR_SIZE, + BOKEH_GEN_BOKEH_BOX, + BOKEH_GEN_BOKEH_BOX_NOWEIGHT, + BOKEH_GEN_BOKEH_HEXAGONAL, + BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, + BOKEH_GEN_BOKEH_CIRCULAR, + BOKEH_COMPOSITE, + BOKEH_MAX + }; + + struct Bokeh { + BokehPushConstant push_constant; + BokehDofShaderRD compute_shader; + BokehDofRasterShaderRD raster_shader; + RID shader_version; + RID compute_pipelines[BOKEH_MAX]; + PipelineCacheRD raster_pipelines[BOKEH_MAX]; + } bokeh; + +public: + struct BokehBuffers { + // bokeh buffers + + // textures + Size2i base_texture_size; + RID base_texture; + RID depth_texture; + RID secondary_texture; + RID half_texture[2]; + + // raster only + RID base_fb; + RID secondary_fb; // with weights + RID half_fb[2]; // with weights + RID base_weight_fb; + RID weight_texture[4]; + }; + + BokehDOF(bool p_prefer_raster_effects); + ~BokehDOF(); + + void bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal); + void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal); +}; + +} // namespace RendererRD + +#endif // !BOKEH_DOF_RD_H diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp new file mode 100644 index 0000000000..6b786fdf16 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -0,0 +1,683 @@ +/*************************************************************************/ +/* copy_effects.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 "copy_effects.h" +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" + +using namespace RendererRD; + +CopyEffects *CopyEffects::singleton = nullptr; + +CopyEffects *CopyEffects::get_singleton() { + return singleton; +} + +CopyEffects::CopyEffects(bool p_prefer_raster_effects) { + singleton = this; + prefer_raster_effects = p_prefer_raster_effects; + + if (prefer_raster_effects) { + // init blur shader (on compute use copy shader) + + Vector<String> blur_modes; + blur_modes.push_back("\n#define MODE_MIPMAP\n"); // BLUR_MIPMAP + blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR + blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW + blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE + blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY + + blur_raster.shader.initialize(blur_modes); + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + blur_raster.shader_version = blur_raster.shader.version_create(); + + for (int i = 0; i < BLUR_MODE_MAX; i++) { + blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } + + } else { + // not used in clustered + for (int i = 0; i < BLUR_MODE_MAX; i++) { + blur_raster.pipelines[i].clear(); + } + + Vector<String> copy_modes; + copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); + copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n"); + copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n"); + copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); + copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n"); + copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n"); + copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n"); + copy_modes.push_back("\n#define MODE_SET_COLOR\n"); + copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n"); + copy_modes.push_back("\n#define MODE_MIPMAP\n"); + copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n"); + copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n"); + copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n"); + + copy.shader.initialize(copy_modes); + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + copy.shader_version = copy.shader.version_create(); + + for (int i = 0; i < COPY_MODE_MAX; i++) { + if (copy.shader.is_variant_enabled(i)) { + copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i)); + } + } + } + + { + Vector<String> copy_modes; + copy_modes.push_back("\n"); + copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); + copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); + copy_modes.push_back("\n#define MULTIVIEW\n"); + copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); + + copy_to_fb.shader.initialize(copy_modes); + + if (!RendererCompositorRD::singleton->is_xr_enabled()) { + copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW, false); + copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW_WITH_DEPTH, false); + } + + copy_to_fb.shader_version = copy_to_fb.shader.version_create(); + + //use additive + + for (int i = 0; i < COPY_TO_FB_MAX; i++) { + if (copy_to_fb.shader.is_variant_enabled(i)) { + copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } else { + copy_to_fb.pipelines[i].clear(); + } + } + } +} + +CopyEffects::~CopyEffects() { + if (prefer_raster_effects) { + blur_raster.shader.version_free(blur_raster.shader_version); + } else { + copy.shader.version_free(copy.shader_version); + } + + copy_to_fb.shader.version_free(copy_to_fb.shader_version); + + singleton = nullptr; +} + +void CopyEffects::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_to_rect shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + if (p_flip_y) { + copy.push_constant.flags |= COPY_FLAG_FLIP_Y; + } + + if (p_force_luminance) { + copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE; + } + + if (p_all_source) { + copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE; + } + + if (p_alpha_to_one) { + copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE; + } + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_rect.size.width; + copy.push_constant.section[3] = p_rect.size.height; + copy.push_constant.target[0] = p_rect.position.x; + copy.push_constant.target[1] = p_rect.position.y; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture); + + CopyMode mode = p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_cubemap_to_panorama shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_panorama_size.width; + copy.push_constant.section[3] = p_panorama_size.height; + copy.push_constant.target[0] = 0; + copy.push_constant.target[1] = 0; + copy.push_constant.camera_z_far = p_lod; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_cube(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cube })); + RD::Uniform u_dest_panorama(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_panorama); + + CopyMode mode = p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cube), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_panorama), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_panorama_size.width, p_panorama_size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_depth_to_rect shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + if (p_flip_y) { + copy.push_constant.flags |= COPY_FLAG_FLIP_Y; + } + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_rect.size.width; + copy.push_constant.section[3] = p_rect.size.height; + copy.push_constant.target[0] = p_rect.position.x; + copy.push_constant.target[1] = p_rect.position.y; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture); + + CopyMode mode = COPY_MODE_SIMPLY_COPY_DEPTH; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_depth_to_rect_and_linearize shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + if (p_flip_y) { + copy.push_constant.flags |= COPY_FLAG_FLIP_Y; + } + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_rect.size.width; + copy.push_constant.section[3] = p_rect.size.height; + copy.push_constant.target[0] = p_rect.position.x; + copy.push_constant.target[1] = p_rect.position.y; + copy.push_constant.camera_z_far = p_z_far; + copy.push_constant.camera_z_near = p_z_near; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture); + + CopyMode mode = COPY_MODE_LINEARIZE_DEPTH; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); + + copy_to_fb.push_constant.use_section = true; + copy_to_fb.push_constant.section[0] = p_uv_rect.position.x; + copy_to_fb.push_constant.section[1] = p_uv_rect.position.y; + copy_to_fb.push_constant.section[2] = p_uv_rect.size.x; + copy_to_fb.push_constant.section[3] = p_uv_rect.size.y; + + if (p_flip_y) { + copy_to_fb.push_constant.flip_y = true; + } + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + CopyToFBMode mode = p_panorama ? COPY_TO_FB_COPY_PANORAMA_TO_DP : COPY_TO_FB_COPY; + RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = p_draw_list; + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); +} + +void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); + + if (p_flip_y) { + copy_to_fb.push_constant.flip_y = true; + } + if (p_force_luminance) { + copy_to_fb.push_constant.force_luminance = true; + } + if (p_alpha_to_zero) { + copy_to_fb.push_constant.alpha_to_zero = true; + } + if (p_srgb) { + copy_to_fb.push_constant.srgb = true; + } + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + CopyToFBMode mode; + if (p_multiview) { + mode = p_secondary.is_valid() ? COPY_TO_FB_MULTIVIEW_WITH_DEPTH : COPY_TO_FB_MULTIVIEW; + } else { + mode = p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY; + } + + RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + if (p_secondary.is_valid()) { + // TODO may need to do this differently when reading from depth buffer for multiview + RD::Uniform u_secondary(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_secondary })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_secondary), 1); + } + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the copy with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_texture })); + + RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, BLUR_MODE_COPY); + ERR_FAIL_COND(shader.is_null()); + + // Just copy it back (we use our blur raster shader here).. + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + copy.push_constant.section[0] = p_region.position.x; + copy.push_constant.section[1] = p_region.position.y; + copy.push_constant.section[2] = p_region.size.width; + copy.push_constant.section[3] = p_region.size.height; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_texture); + + CopyMode mode = p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + //HORIZONTAL + RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_texture), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1); + + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW; + uint32_t base_flags = 0; + + copy.push_constant.section[2] = p_size.x; + copy.push_constant.section[3] = p_size.y; + + copy.push_constant.glow_strength = p_strength; + copy.push_constant.glow_bloom = p_bloom; + copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold; + copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale; + copy.push_constant.glow_exposure = p_exposure; + copy.push_constant.glow_white = 0; //actually unused + copy.push_constant.glow_luminance_cap = p_luminance_cap; + + copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_back_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_back_texture); + + RID shader = copy.shader.version_get_shader(copy.shader_version, copy_mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_back_texture), 3); + if (p_auto_exposure.is_valid() && p_first_pass) { + RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1); + } + + copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + + BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW; + uint32_t base_flags = 0; + + blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x); + blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y); + + blur_raster.push_constant.glow_strength = p_strength; + blur_raster.push_constant.glow_bloom = p_bloom; + blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold; + blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale; + blur_raster.push_constant.glow_exposure = p_exposure; + blur_raster.push_constant.glow_white = 0; //actually unused + blur_raster.push_constant.glow_luminance_cap = p_luminance_cap; + + blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also + + blur_raster.push_constant.luminance_multiplier = p_luminance_multiplier; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_rd_texture_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_rd_texture_half })); + + RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode); + ERR_FAIL_COND(shader.is_null()); + + //HORIZONTAL + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + if (p_auto_exposure.is_valid() && p_first_pass) { + RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1); + } + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + blur_mode = BLUR_MODE_GAUSSIAN_GLOW; + + shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode); + ERR_FAIL_COND(shader.is_null()); + + //VERTICAL + draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_rd_texture_half), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + blur_raster.push_constant.flags = base_flags; + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the make_mipmap shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_size.width; + copy.push_constant.section[3] = p_size.height; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture); + + CopyMode mode = COPY_MODE_MIPMAP; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + + BlurRasterMode mode = BLUR_MIPMAP; + + blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x); + blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y); + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the set_color shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_region.size.width; + copy.push_constant.section[3] = p_region.size.height; + copy.push_constant.target[0] = p_region.position.x; + copy.push_constant.target[1] = p_region.position.y; + copy.push_constant.set_color[0] = p_color.r; + copy.push_constant.set_color[1] = p_color.g; + copy.push_constant.set_color[2] = p_color.b; + copy.push_constant.set_color[3] = p_color.a; + + // setup our uniforms + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture); + + CopyMode mode = p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1); + RD::get_singleton()->compute_list_end(); +} diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h new file mode 100644 index 0000000000..e522408d20 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -0,0 +1,220 @@ +/*************************************************************************/ +/* copy_effects.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 COPY_RD_H +#define COPY_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/copy.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +namespace RendererRD { + +class CopyEffects { +private: + bool prefer_raster_effects; + + // Blur raster shader + + enum BlurRasterMode { + BLUR_MIPMAP, + + BLUR_MODE_GAUSSIAN_BLUR, + BLUR_MODE_GAUSSIAN_GLOW, + BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, + BLUR_MODE_COPY, + + BLUR_MODE_MAX + }; + + enum { + BLUR_FLAG_HORIZONTAL = (1 << 0), + BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1), + BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2), + }; + + struct BlurRasterPushConstant { + float pixel_size[2]; + uint32_t flags; + uint32_t pad; + + //glow + float glow_strength; + float glow_bloom; + float glow_hdr_threshold; + float glow_hdr_scale; + + float glow_exposure; + float glow_white; + float glow_luminance_cap; + float glow_auto_exposure_grey; + + float luminance_multiplier; + float res1; + float res2; + float res3; + }; + + struct BlurRaster { + BlurRasterPushConstant push_constant; + BlurRasterShaderRD shader; + RID shader_version; + PipelineCacheRD pipelines[BLUR_MODE_MAX]; + } blur_raster; + + // Copy shader + + enum CopyMode { + COPY_MODE_GAUSSIAN_COPY, + COPY_MODE_GAUSSIAN_COPY_8BIT, + COPY_MODE_GAUSSIAN_GLOW, + COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, + COPY_MODE_SIMPLY_COPY, + COPY_MODE_SIMPLY_COPY_8BIT, + COPY_MODE_SIMPLY_COPY_DEPTH, + COPY_MODE_SET_COLOR, + COPY_MODE_SET_COLOR_8BIT, + COPY_MODE_MIPMAP, + COPY_MODE_LINEARIZE_DEPTH, + COPY_MODE_CUBE_TO_PANORAMA, + COPY_MODE_CUBE_ARRAY_TO_PANORAMA, + COPY_MODE_MAX, + + }; + + enum { + COPY_FLAG_HORIZONTAL = (1 << 0), + COPY_FLAG_USE_COPY_SECTION = (1 << 1), + COPY_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2), + COPY_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3), + COPY_FLAG_GLOW_FIRST_PASS = (1 << 4), + COPY_FLAG_FLIP_Y = (1 << 5), + COPY_FLAG_FORCE_LUMINANCE = (1 << 6), + COPY_FLAG_ALL_SOURCE = (1 << 7), + COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8), + COPY_FLAG_ALPHA_TO_ONE = (1 << 9), + }; + + struct CopyPushConstant { + int32_t section[4]; + int32_t target[2]; + uint32_t flags; + uint32_t pad; + // Glow. + float glow_strength; + float glow_bloom; + float glow_hdr_threshold; + float glow_hdr_scale; + + float glow_exposure; + float glow_white; + float glow_luminance_cap; + float glow_auto_exposure_grey; + // DOF. + float camera_z_far; + float camera_z_near; + uint32_t pad2[2]; + //SET color + float set_color[4]; + }; + + struct Copy { + CopyPushConstant push_constant; + CopyShaderRD shader; + RID shader_version; + RID pipelines[COPY_MODE_MAX]; + + } copy; + + // Copy to FB shader + + enum CopyToFBMode { + COPY_TO_FB_COPY, + COPY_TO_FB_COPY_PANORAMA_TO_DP, + COPY_TO_FB_COPY2, + + COPY_TO_FB_MULTIVIEW, + COPY_TO_FB_MULTIVIEW_WITH_DEPTH, + COPY_TO_FB_MAX, + }; + + struct CopyToFbPushConstant { + float section[4]; + float pixel_size[2]; + uint32_t flip_y; + uint32_t use_section; + + uint32_t force_luminance; + uint32_t alpha_to_zero; + uint32_t srgb; + uint32_t pad; + }; + + struct CopyToFb { + CopyToFbPushConstant push_constant; + CopyToFbShaderRD shader; + RID shader_version; + PipelineCacheRD pipelines[COPY_TO_FB_MAX]; + + } copy_to_fb; + + static CopyEffects *singleton; + +public: + static CopyEffects *get_singleton(); + + CopyEffects(bool p_prefer_raster_effects); + ~CopyEffects(); + + void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false); + void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); + void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); + void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far); + void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false); + void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false); + void copy_raster(RID p_source_texture, RID p_dest_framebuffer); + + void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false); + void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); + void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); + + void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); + void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size); + + void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false); +}; + +} // namespace RendererRD + +#endif // !COPY_RD_H diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp index e5642116bb..38a4a37b8a 100644 --- a/servers/rendering/renderer_rd/effects/tone_mapper.cpp +++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp @@ -75,28 +75,9 @@ ToneMapper::ToneMapper() { } } } - - // TODO maybe centralise this in mesh_storage? - { //create index array for copy shaders - Vector<uint8_t> pv; - pv.resize(6 * 4); - { - uint8_t *w = pv.ptrw(); - int *p32 = (int *)w; - p32[0] = 0; - p32[1] = 1; - p32[2] = 2; - p32[3] = 0; - p32[4] = 2; - p32[5] = 3; - } - index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); - index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6); - } } ToneMapper::~ToneMapper() { - RD::get_singleton()->free(index_buffer); //array gets freed as dependency tonemap.shader.version_free(tonemap.shader_version); } @@ -154,11 +135,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - RD::Uniform u_source_color; - u_source_color.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u_source_color.binding = 0; - u_source_color.append_id(default_sampler); - u_source_color.append_id(p_source_color); + RD::Uniform u_source_color(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_color })); RD::Uniform u_exposure_texture; u_exposure_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; @@ -193,7 +170,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); RD::get_singleton()->draw_list_set_push_constant(draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant)); RD::get_singleton()->draw_list_draw(draw_list, true); @@ -273,7 +250,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1); // should be set to a default texture, it's ignored RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2); // should be set to a default texture, it's ignored RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3); - RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, index_array); + RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, material_storage->get_quad_index_array()); RD::get_singleton()->draw_list_set_push_constant(p_subpass_draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant)); RD::get_singleton()->draw_list_draw(p_subpass_draw_list, true); diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h index 357e814845..a90849dbeb 100644 --- a/servers/rendering/renderer_rd/effects/tone_mapper.h +++ b/servers/rendering/renderer_rd/effects/tone_mapper.h @@ -96,9 +96,6 @@ private: PipelineCacheRD pipelines[TONEMAP_MODE_MAX]; } tonemap; - RID index_buffer; - RID index_array; - public: ToneMapper(); ~ToneMapper(); diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index f05027d569..774745abdc 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -86,7 +86,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) u.append_id(p_texture); uniforms.push_back(u); // anything with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, 0), 0); + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0), 0); texture_to_uniform_set_cache[p_texture] = uniform_set; @@ -252,295 +252,6 @@ void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RI RD::get_singleton()->compute_list_end(compute_list); } -void EffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) { - memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); - - copy_to_fb.push_constant.use_section = true; - copy_to_fb.push_constant.section[0] = p_uv_rect.position.x; - copy_to_fb.push_constant.section[1] = p_uv_rect.position.y; - copy_to_fb.push_constant.section[2] = p_uv_rect.size.x; - copy_to_fb.push_constant.section[3] = p_uv_rect.size.y; - - if (p_flip_y) { - copy_to_fb.push_constant.flip_y = true; - } - - RD::DrawListID draw_list = p_draw_list; - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[p_panorama ? COPY_TO_FB_COPY_PANORAMA_TO_DP : COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); -} - -void EffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) { - memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); - - if (p_flip_y) { - copy_to_fb.push_constant.flip_y = true; - } - if (p_force_luminance) { - copy_to_fb.push_constant.force_luminance = true; - } - if (p_alpha_to_zero) { - copy_to_fb.push_constant.alpha_to_zero = true; - } - if (p_srgb) { - copy_to_fb.push_constant.srgb = true; - } - - CopyToFBMode mode; - if (p_multiview) { - mode = p_secondary.is_valid() ? COPY_TO_FB_MULTIVIEW_WITH_DEPTH : COPY_TO_FB_MULTIVIEW; - } else { - mode = p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY; - } - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - if (p_secondary.is_valid()) { - // TODO may need to do this differently when reading from depth buffer for multiview - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_secondary), 1); - } - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - -void EffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - if (p_flip_y) { - copy.push_constant.flags |= COPY_FLAG_FLIP_Y; - } - - if (p_force_luminance) { - copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE; - } - - if (p_all_source) { - copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE; - } - - if (p_alpha_to_one) { - copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE; - } - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_rect.size.width; - copy.push_constant.section[3] = p_rect.size.height; - copy.push_constant.target[0] = p_rect.position.x; - copy.push_constant.target[1] = p_rect.position.y; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_panorama_size.width; - copy.push_constant.section[3] = p_panorama_size.height; - copy.push_constant.target[0] = 0; - copy.push_constant.target[1] = 0; - copy.push_constant.camera_z_far = p_lod; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cube), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_panorama), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_panorama_size.width, p_panorama_size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - if (p_flip_y) { - copy.push_constant.flags |= COPY_FLAG_FLIP_Y; - } - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_rect.size.width; - copy.push_constant.section[3] = p_rect.size.height; - copy.push_constant.target[0] = p_rect.position.x; - copy.push_constant.target[1] = p_rect.position.y; - copy.push_constant.camera_z_far = p_z_far; - copy.push_constant.camera_z_near = p_z_near; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_LINEARIZE_DEPTH]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - if (p_flip_y) { - copy.push_constant.flags |= COPY_FLAG_FLIP_Y; - } - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_rect.size.width; - copy.push_constant.section[3] = p_rect.size.height; - copy.push_constant.target[0] = p_rect.position.x; - copy.push_constant.target[1] = p_rect.position.y; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_SIMPLY_COPY_DEPTH]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_region.size.width; - copy.push_constant.section[3] = p_region.size.height; - copy.push_constant.target[0] = p_region.position.x; - copy.push_constant.target[1] = p_region.position.y; - copy.push_constant.set_color[0] = p_color.r; - copy.push_constant.set_color[1] = p_color.g; - copy.push_constant.set_color[2] = p_color.b; - copy.push_constant.set_color[3] = p_color.a; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) { - ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer."); - - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - copy.push_constant.section[0] = p_region.position.x; - copy.push_constant.section[1] = p_region.position.y; - copy.push_constant.section[2] = p_region.size.width; - copy.push_constant.section[3] = p_region.size.height; - - //HORIZONTAL - RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 3); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1); - - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { - ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer."); - - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW; - uint32_t base_flags = 0; - - copy.push_constant.section[2] = p_size.x; - copy.push_constant.section[3] = p_size.y; - - copy.push_constant.glow_strength = p_strength; - copy.push_constant.glow_bloom = p_bloom; - copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold; - copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale; - copy.push_constant.glow_exposure = p_exposure; - copy.push_constant.glow_white = 0; //actually unused - copy.push_constant.glow_luminance_cap = p_luminance_cap; - - copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3); - if (p_auto_exposure.is_valid() && p_first_pass) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_auto_exposure), 1); - } - - copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { - ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer."); - - memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); - - BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW; - uint32_t base_flags = 0; - - blur_raster.push_constant.pixel_size[0] = p_pixel_size.x; - blur_raster.push_constant.pixel_size[1] = p_pixel_size.y; - - blur_raster.push_constant.glow_strength = p_strength; - blur_raster.push_constant.glow_bloom = p_bloom; - blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold; - blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale; - blur_raster.push_constant.glow_exposure = p_exposure; - blur_raster.push_constant.glow_white = 0; //actually unused - blur_raster.push_constant.glow_luminance_cap = p_luminance_cap; - - blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also - - //HORIZONTAL - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - if (p_auto_exposure.is_valid() && p_first_pass) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1); - } - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - - blur_mode = BLUR_MODE_GAUSSIAN_GLOW; - - //VERTICAL - draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - blur_raster.push_constant.flags = base_flags; - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -733,43 +444,6 @@ void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_bas RD::get_singleton()->draw_list_end(); } -void EffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_size.width; - copy.push_constant.section[3] = p_size.height; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_MIPMAP]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) { - ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer."); - - memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); - - BlurRasterMode mode = BLUR_MIPMAP; - - blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x); - blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) { CopyToDPPushConstant push_constant; push_constant.screen_rect[0] = p_rect.position.x; @@ -865,332 +539,6 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_ } } -void EffectsRD::bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { - ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of BOKEH DOF with the mobile renderer."); - - bokeh.push_constant.blur_far_active = p_dof_far; - bokeh.push_constant.blur_far_begin = p_dof_far_begin; - bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; - - bokeh.push_constant.blur_near_active = p_dof_near; - bokeh.push_constant.blur_near_begin = p_dof_near_begin; - bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size); - bokeh.push_constant.use_jitter = p_use_jitter; - bokeh.push_constant.jitter_seed = Math::randf() * 1000.0; - - bokeh.push_constant.z_near = p_cam_znear; - bokeh.push_constant.z_far = p_cam_zfar; - bokeh.push_constant.orthogonal = p_cam_orthogonal; - bokeh.push_constant.blur_size = p_bokeh_size; - - bokeh.push_constant.second_pass = false; - bokeh.push_constant.half_size = false; - - bokeh.push_constant.blur_scale = 0.5; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - /* FIRST PASS */ - // The alpha channel of the source color texture is filled with the expected circle size - // If used for DOF far, the size is positive, if used for near, its negative. - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.depth_texture), 1); - - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) { - //second pass - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]); - - static const int quality_samples[4] = { 6, 12, 12, 24 }; - - bokeh.push_constant.steps = quality_samples[p_quality]; - - if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { - //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes) - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1); - - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; - bokeh.push_constant.half_size = true; - bokeh.push_constant.blur_size *= 0.5; - - } else { - //medium and high quality use full size - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.secondary_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1); - } - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - //third pass - bokeh.push_constant.second_pass = true; - - if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[1]), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.secondary_texture), 1); - } - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { - //forth pass, upscale for low quality - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[1]), 1); - - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; - bokeh.push_constant.half_size = false; - bokeh.push_constant.second_pass = false; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); - } - } else { - //circle - - //second pass - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]); - - static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 }; - - bokeh.push_constant.steps = 0; - bokeh.push_constant.blur_scale = quality_scale[p_quality]; - - //circle always runs in half size, otherwise too expensive - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1); - - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; - bokeh.push_constant.half_size = true; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - //circle is just one pass, then upscale - - // upscale - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1); - - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; - bokeh.push_constant.half_size = false; - bokeh.push_constant.second_pass = false; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); - } - - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { - ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use blur DOF with the clustered renderer."); - - memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant)); - - bokeh.push_constant.orthogonal = p_cam_orthogonal; - bokeh.push_constant.size[0] = p_buffers.base_texture_size.width; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.height; - bokeh.push_constant.z_far = p_cam_zfar; - bokeh.push_constant.z_near = p_cam_znear; - - bokeh.push_constant.second_pass = false; - bokeh.push_constant.half_size = false; - bokeh.push_constant.blur_size = p_dof_blur_amount; - - if (p_dof_far || p_dof_near) { - if (p_dof_far) { - bokeh.push_constant.blur_far_active = true; - bokeh.push_constant.blur_far_begin = p_dof_far_begin; - bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; - } - - if (p_dof_near) { - bokeh.push_constant.blur_near_active = true; - bokeh.push_constant.blur_near_begin = p_dof_near_begin; - bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size; - } - - { - // generate our depth data - RID framebuffer = p_buffers.base_weight_fb; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.depth_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - } - - if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) { - // double pass approach - BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL; - - if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { - //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes) - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; - bokeh.push_constant.half_size = true; - bokeh.push_constant.blur_size *= 0.5; - } - - static const int quality_samples[4] = { 6, 12, 12, 24 }; - bokeh.push_constant.blur_scale = 0.5; - bokeh.push_constant.steps = quality_samples[p_quality]; - - RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; - - // Pass 1 - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - - // Pass 2 - if (!bokeh.push_constant.half_size) { - // do not output weight, we're writing back into our base buffer - mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT; - } - bokeh.push_constant.second_pass = true; - - framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[1] : p_buffers.base_fb; - RID texture = bokeh.push_constant.half_size ? p_buffers.half_texture[0] : p_buffers.secondary_texture; - RID weight = bokeh.push_constant.half_size ? p_buffers.weight_texture[2] : p_buffers.weight_texture[1]; - - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(texture), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(weight), 1); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - - if (bokeh.push_constant.half_size) { - // Compose pass - mode = BOKEH_COMPOSITE; - framebuffer = p_buffers.base_fb; - - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[1]), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[3]), 1); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - } - - } else { - // circular is a single pass approach - BokehMode mode = BOKEH_GEN_BOKEH_CIRCULAR; - - { - // circle always runs in half size, otherwise too expensive (though the code below does support making this optional) - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; - bokeh.push_constant.half_size = true; - // bokeh.push_constant.blur_size *= 0.5; - } - - static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 }; - bokeh.push_constant.blur_scale = quality_scale[p_quality]; - bokeh.push_constant.steps = 0.0; - - RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - - if (bokeh.push_constant.half_size) { - // Compose - mode = BOKEH_COMPOSITE; - framebuffer = p_buffers.base_fb; - - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[0]), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[2]), 1); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - } else { - // Just copy it back (we use our blur raster shader here).. - draw_list = RD::get_singleton()->draw_list_begin(p_buffers.base_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_buffers.base_fb))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.secondary_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - } - } - } -} - void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection) { // Downsample and deinterleave the depth buffer for SSAO and SSIL RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -2152,94 +1500,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { prefer_raster_effects = p_prefer_raster_effects; - if (prefer_raster_effects) { - // init blur shader (on compute use copy shader) - - Vector<String> blur_modes; - blur_modes.push_back("\n#define MODE_MIPMAP\n"); // BLUR_MIPMAP - blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR - blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW - blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE - blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY - - blur_raster.shader.initialize(blur_modes); - memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); - blur_raster.shader_version = blur_raster.shader.version_create(); - - for (int i = 0; i < BLUR_MODE_MAX; i++) { - blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); - } - - } else { - // not used in clustered - for (int i = 0; i < BLUR_MODE_MAX; i++) { - blur_raster.pipelines[i].clear(); - } - } - - if (!prefer_raster_effects) { // Initialize copy - Vector<String> copy_modes; - copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); - copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n"); - copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n"); - copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); - copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n"); - copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n"); - copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n"); - copy_modes.push_back("\n#define MODE_SET_COLOR\n"); - copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n"); - copy_modes.push_back("\n#define MODE_MIPMAP\n"); - copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n"); - copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n"); - copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n"); - - copy.shader.initialize(copy_modes); - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - if (prefer_raster_effects) { - // disable shaders we can't use - copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY, false); - copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY_8BIT, false); - copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW, false); - copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, false); - } - - copy.shader_version = copy.shader.version_create(); - - for (int i = 0; i < COPY_MODE_MAX; i++) { - if (copy.shader.is_variant_enabled(i)) { - copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i)); - } - } - } - { - Vector<String> copy_modes; - copy_modes.push_back("\n"); - copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); - copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); - copy_modes.push_back("\n#define MULTIVIEW\n"); - copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); - - copy_to_fb.shader.initialize(copy_modes); - - if (!RendererCompositorRD::singleton->is_xr_enabled()) { - copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW, false); - copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW_WITH_DEPTH, false); - } - - copy_to_fb.shader_version = copy_to_fb.shader.version_create(); - - //use additive - - for (int i = 0; i < COPY_TO_FB_MAX; i++) { - if (copy_to_fb.shader.is_variant_enabled(i)) { - copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); - } else { - copy_to_fb.pipelines[i].clear(); - } - } - } - { // Initialize roughness Vector<String> cubemap_roughness_modes; @@ -2311,42 +1571,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0); } - // Initialize bokeh - Vector<String> bokeh_modes; - bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n#define OUTPUT_WEIGHT\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n#define OUTPUT_WEIGHT\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n#define OUTPUT_WEIGHT\n"); - bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n"); - if (prefer_raster_effects) { - bokeh.raster_shader.initialize(bokeh_modes); - - bokeh.shader_version = bokeh.raster_shader.version_create(); - - const int att_count[BOKEH_MAX] = { 1, 2, 1, 2, 1, 2, 1 }; - for (int i = 0; i < BOKEH_MAX; i++) { - RD::PipelineColorBlendState blend_state = (i == BOKEH_COMPOSITE) ? RD::PipelineColorBlendState::create_blend(att_count[i]) : RD::PipelineColorBlendState::create_disabled(att_count[i]); - bokeh.raster_pipelines[i].setup(bokeh.raster_shader.version_get_shader(bokeh.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); - } - } else { - bokeh.compute_shader.initialize(bokeh_modes); - bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_BOX_NOWEIGHT, false); - bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, false); - bokeh.shader_version = bokeh.compute_shader.version_create(); - - for (int i = 0; i < BOKEH_MAX; i++) { - if (bokeh.compute_shader.is_variant_enabled(i)) { - bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i)); - } - } - - for (int i = 0; i < BOKEH_MAX; i++) { - bokeh.raster_pipelines[i].clear(); - } - } - if (!prefer_raster_effects) { { // Initialize depth buffer for screen space effects @@ -2837,21 +2061,17 @@ EffectsRD::~EffectsRD() { FSR_upscale.shader.version_free(FSR_upscale.shader_version); if (prefer_raster_effects) { - blur_raster.shader.version_free(blur_raster.shader_version); - bokeh.raster_shader.version_free(blur_raster.shader_version); luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version); roughness.raster_shader.version_free(roughness.shader_version); cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version); filter.raster_shader.version_free(filter.shader_version); } else { - bokeh.compute_shader.version_free(bokeh.shader_version); luminance_reduce.shader.version_free(luminance_reduce.shader_version); roughness.compute_shader.version_free(roughness.shader_version); cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version); filter.compute_shader.version_free(filter.shader_version); } if (!prefer_raster_effects) { - copy.shader.version_free(copy.shader_version); resolve.shader.version_free(resolve.shader_version); specular_merge.shader.version_free(specular_merge.shader_version); ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version); @@ -2875,7 +2095,6 @@ EffectsRD::~EffectsRD() { RD::get_singleton()->free(ssil.importance_map_load_counter); RD::get_singleton()->free(ssil.projection_uniform_buffer); } - copy_to_fb.shader.version_free(copy_to_fb.shader_version); cube_to_dp.shader.version_free(cube_to_dp.shader_version); sort.shader.version_free(sort.shader_version); } diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index 8174e30238..1963935236 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -33,11 +33,6 @@ #include "core/math/camera_matrix.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" -#include "servers/rendering/renderer_rd/shaders/blur_raster.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/bokeh_dof.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/copy.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/copy_to_fb.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/cube_to_dp.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl.gen.h" @@ -95,140 +90,6 @@ private: RID pipeline; } FSR_upscale; - enum BlurRasterMode { - BLUR_MIPMAP, - - BLUR_MODE_GAUSSIAN_BLUR, - BLUR_MODE_GAUSSIAN_GLOW, - BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, - BLUR_MODE_COPY, - - BLUR_MODE_MAX - }; - - enum { - BLUR_FLAG_HORIZONTAL = (1 << 0), - BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1), - BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2), - }; - - struct BlurRasterPushConstant { - float pixel_size[2]; - uint32_t flags; - uint32_t pad; - - //glow - float glow_strength; - float glow_bloom; - float glow_hdr_threshold; - float glow_hdr_scale; - - float glow_exposure; - float glow_white; - float glow_luminance_cap; - float glow_auto_exposure_grey; - }; - - struct BlurRaster { - BlurRasterPushConstant push_constant; - BlurRasterShaderRD shader; - RID shader_version; - PipelineCacheRD pipelines[BLUR_MODE_MAX]; - } blur_raster; - - enum CopyMode { - COPY_MODE_GAUSSIAN_COPY, - COPY_MODE_GAUSSIAN_COPY_8BIT, - COPY_MODE_GAUSSIAN_GLOW, - COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, - COPY_MODE_SIMPLY_COPY, - COPY_MODE_SIMPLY_COPY_8BIT, - COPY_MODE_SIMPLY_COPY_DEPTH, - COPY_MODE_SET_COLOR, - COPY_MODE_SET_COLOR_8BIT, - COPY_MODE_MIPMAP, - COPY_MODE_LINEARIZE_DEPTH, - COPY_MODE_CUBE_TO_PANORAMA, - COPY_MODE_CUBE_ARRAY_TO_PANORAMA, - COPY_MODE_MAX, - - }; - - enum { - COPY_FLAG_HORIZONTAL = (1 << 0), - COPY_FLAG_USE_COPY_SECTION = (1 << 1), - COPY_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2), - COPY_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3), - COPY_FLAG_GLOW_FIRST_PASS = (1 << 4), - COPY_FLAG_FLIP_Y = (1 << 5), - COPY_FLAG_FORCE_LUMINANCE = (1 << 6), - COPY_FLAG_ALL_SOURCE = (1 << 7), - COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8), - COPY_FLAG_ALPHA_TO_ONE = (1 << 9), - }; - - struct CopyPushConstant { - int32_t section[4]; - int32_t target[2]; - uint32_t flags; - uint32_t pad; - // Glow. - float glow_strength; - float glow_bloom; - float glow_hdr_threshold; - float glow_hdr_scale; - - float glow_exposure; - float glow_white; - float glow_luminance_cap; - float glow_auto_exposure_grey; - // DOF. - float camera_z_far; - float camera_z_near; - uint32_t pad2[2]; - //SET color - float set_color[4]; - }; - - struct Copy { - CopyPushConstant push_constant; - CopyShaderRD shader; - RID shader_version; - RID pipelines[COPY_MODE_MAX]; - - } copy; - - enum CopyToFBMode { - COPY_TO_FB_COPY, - COPY_TO_FB_COPY_PANORAMA_TO_DP, - COPY_TO_FB_COPY2, - - COPY_TO_FB_MULTIVIEW, - COPY_TO_FB_MULTIVIEW_WITH_DEPTH, - COPY_TO_FB_MAX, - - }; - - struct CopyToFbPushConstant { - float section[4]; - float pixel_size[2]; - uint32_t flip_y; - uint32_t use_section; - - uint32_t force_luminance; - uint32_t alpha_to_zero; - uint32_t srgb; - uint32_t pad; - }; - - struct CopyToFb { - CopyToFbPushConstant push_constant; - CopyToFbShaderRD shader; - RID shader_version; - PipelineCacheRD pipelines[COPY_TO_FB_MAX]; - - } copy_to_fb; - struct CubemapRoughnessPushConstant { uint32_t face_id; uint32_t sample_count; @@ -305,51 +166,6 @@ private: PipelineCacheRD pipeline; } cube_to_dp; - struct BokehPushConstant { - uint32_t size[2]; - float z_far; - float z_near; - - uint32_t orthogonal; - float blur_size; - float blur_scale; - uint32_t steps; - - uint32_t blur_near_active; - float blur_near_begin; - float blur_near_end; - uint32_t blur_far_active; - - float blur_far_begin; - float blur_far_end; - uint32_t second_pass; - uint32_t half_size; - - uint32_t use_jitter; - float jitter_seed; - uint32_t pad[2]; - }; - - enum BokehMode { - BOKEH_GEN_BLUR_SIZE, - BOKEH_GEN_BOKEH_BOX, - BOKEH_GEN_BOKEH_BOX_NOWEIGHT, - BOKEH_GEN_BOKEH_HEXAGONAL, - BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, - BOKEH_GEN_BOKEH_CIRCULAR, - BOKEH_COMPOSITE, - BOKEH_MAX - }; - - struct Bokeh { - BokehPushConstant push_constant; - BokehDofShaderRD compute_shader; - BokehDofRasterShaderRD raster_shader; - RID shader_version; - RID compute_pipelines[BOKEH_MAX]; - PipelineCacheRD raster_pipelines[BOKEH_MAX]; - } bokeh; - struct SSEffectsDownsamplePushConstant { float pixel_size[2]; float z_far; @@ -792,10 +608,10 @@ private: RID index_buffer; RID index_array; - Map<RID, RID> texture_to_uniform_set_cache; - Map<RID, RID> input_to_uniform_set_cache; + HashMap<RID, RID> texture_to_uniform_set_cache; + HashMap<RID, RID> input_to_uniform_set_cache; - Map<RID, RID> image_to_uniform_set_cache; + HashMap<RID, RID> image_to_uniform_set_cache; struct TexturePair { RID texture1; @@ -821,11 +637,11 @@ private: } }; - Map<TexturePair, RID> texture_pair_to_uniform_set_cache; - Map<RID, RID> texture_to_compute_uniform_set_cache; - Map<TexturePair, RID> texture_pair_to_compute_uniform_set_cache; - Map<TexturePair, RID> image_pair_to_compute_uniform_set_cache; - Map<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache; + RBMap<TexturePair, RID> texture_pair_to_uniform_set_cache; + RBMap<RID, RID> texture_to_compute_uniform_set_cache; + RBMap<TexturePair, RID> texture_pair_to_compute_uniform_set_cache; + RBMap<TexturePair, RID> image_pair_to_compute_uniform_set_cache; + RBMap<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache; RID _get_uniform_set_from_image(RID p_texture); RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); @@ -838,46 +654,13 @@ public: bool get_prefer_raster_effects(); void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness); - void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false); - void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false); - void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); - void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); - void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far); - void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false); - void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false); - void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false); - void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); - void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); - void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); - void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size); void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip); void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); - struct BokehBuffers { - // bokeh buffers - - // textures - Size2i base_texture_size; - RID base_texture; - RID depth_texture; - RID secondary_texture; - RID half_texture[2]; - - // raster only - RID base_fb; - RID secondary_fb; // with weights - RID half_fb[2]; // with weights - RID base_weight_fb; - RID weight_texture[4]; - }; - - void bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal); - void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal); - struct SSAOSettings { float radius = 1.0; float intensity = 2.0; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 4bfaad9fe6..0eb981d51b 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -2006,14 +2006,14 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture); - Map<Size2i, RID>::Element *E = sdfgi_framebuffer_size_cache.find(fb_size); + HashMap<Size2i, RID>::Iterator E = sdfgi_framebuffer_size_cache.find(fb_size); if (!E) { RID fb = RD::get_singleton()->framebuffer_create_empty(fb_size); E = sdfgi_framebuffer_size_cache.insert(fb_size, fb); } RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false); - _render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); + _render_list_with_threads(&render_list_params, E->value, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); } RD::get_singleton()->draw_command_end_label(); @@ -3276,8 +3276,8 @@ RenderForwardClustered::~RenderForwardClustered() { memdelete_arr(scene_state.lightmap_captures); } - while (sdfgi_framebuffer_size_cache.front()) { - RD::get_singleton()->free(sdfgi_framebuffer_size_cache.front()->get()); - sdfgi_framebuffer_size_cache.erase(sdfgi_framebuffer_size_cache.front()); + while (sdfgi_framebuffer_size_cache.begin()) { + RD::get_singleton()->free(sdfgi_framebuffer_size_cache.begin()->value); + sdfgi_framebuffer_size_cache.remove(sdfgi_framebuffer_size_cache.begin()); } } diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 0e588aecb4..bec10f7f0e 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -106,7 +106,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID color_only_fb; RID specular_only_fb; int width, height; - Map<uint32_t, RID> color_framebuffers; + HashMap<uint32_t, RID> color_framebuffers; uint32_t view_count; RID render_sdfgi_uniform_set; @@ -396,7 +396,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true); void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_append = false); - Map<Size2i, RID> sdfgi_framebuffer_size_cache; + HashMap<Size2i, RID> sdfgi_framebuffer_size_cache; struct GeometryInstanceData; struct GeometryInstanceForwardClustered; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index e60651f092..bd39dd9c70 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -154,7 +154,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - Map<String, String>::Element *el = gen_code.code.front(); + RBMap<String, String>::Element *el = gen_code.code.front(); while (el) { print_line("\n**code " + el->key() + ":\n" + el->value()); @@ -376,14 +376,14 @@ void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const St } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { @@ -477,7 +477,7 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -bool SceneShaderForwardClustered::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool SceneShaderForwardClustered::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton; return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER); @@ -748,7 +748,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; actions.global_buffer_array_variable = "global_variables.data"; - actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs"; + actions.instance_uniform_index_variable = "instances.data[instance_index_interp].instance_uniforms_ofs"; compiler.initialize(actions); } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 0b2df983ff..c22b2f243d 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -138,14 +138,14 @@ public: String path; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -208,7 +208,7 @@ public: uint8_t priority; virtual void set_render_priority(int p_priority); virtual void set_next_pass(RID p_pass); - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~MaterialData(); }; @@ -239,7 +239,7 @@ public: ShaderData *overdraw_material_shader_ptr = nullptr; Vector<RD::PipelineSpecializationConstant> default_specialization_constants; - Set<uint32_t> valid_color_pass_pipelines; + RBSet<uint32_t> valid_color_pass_pipelines; SceneShaderForwardClustered(); ~SceneShaderForwardClustered(); diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index cdddc35579..a3cabb0693 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -154,7 +154,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - Map<String, String>::Element * el = gen_code.code.front(); + RBMap<String, String>::Element * el = gen_code.code.front(); while (el) { print_line("\n**code " + el->key() + ":\n" + el->value()); @@ -339,14 +339,14 @@ void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const Strin } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { @@ -440,7 +440,7 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -bool SceneShaderForwardMobile::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton; return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER); diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 50b5fb26ec..f325d5c0a5 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -104,14 +104,14 @@ public: String path; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -171,7 +171,7 @@ public: uint8_t priority; virtual void set_render_priority(int p_priority); virtual void set_next_pass(RID p_pass); - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~MaterialData(); }; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 386bc18fcd..3c2f3f8a42 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -2160,14 +2160,14 @@ void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const S } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { @@ -2246,7 +2246,7 @@ RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { return shader_data; } -bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 06970acca6..04881ce7e6 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -166,14 +166,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender { PipelineVariants pipeline_variants; String path; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_screen_texture = false; bool uses_sdf = false; @@ -205,7 +205,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~CanvasMaterialData(); }; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 26bd28286b..aefc189f68 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -90,7 +90,7 @@ protected: RID sampler; } blit; - Map<RID, RID> render_target_descriptors; + HashMap<RID, RID> render_target_descriptors; double time = 0.0; double delta = 0.0; @@ -131,6 +131,7 @@ public: static void make_current() { _create_func = _create_current; + low_end = false; } static RendererCompositorRD *singleton; diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 5cbacb0ef3..7aede6bb48 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -1115,6 +1115,7 @@ void RendererSceneGIRD::SDFGI::update_cascades() { void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) { Vector<RD::Uniform> uniforms; @@ -1251,7 +1252,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons RD::get_singleton()->compute_list_end(); Size2 rtsize = texture_storage->render_target_get_size(p_render_target); - storage->get_effects()->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true); + copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true); } void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index bf65dca56a..e3bf2e3dda 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1556,8 +1556,6 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH); - // TODO make sure texture_create_shared_from_slice works for multiview - RD::TextureFormat tf; tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = rb->internal_width; @@ -1583,55 +1581,63 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { tf.mipmaps--; rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - int base_width = rb->internal_width; - int base_height = rb->internal_height; + for (uint32_t l = 0; l < rb->view_count; l++) { + RenderBuffers::Blur::Layer ll[2]; + int base_width = rb->internal_width; + int base_height = rb->internal_height; - for (uint32_t i = 0; i < mipmaps_required; i++) { - RenderBuffers::Blur::Mipmap mm; - mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, 0, i); + for (uint32_t i = 0; i < mipmaps_required; i++) { + RenderBuffers::Blur::Mipmap mm; + mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, l, i); - mm.width = base_width; - mm.height = base_height; + mm.width = base_width; + mm.height = base_height; - if (!_render_buffers_can_be_storage()) { - Vector<RID> fb; - fb.push_back(mm.texture); - - mm.fb = RD::get_singleton()->framebuffer_create(fb); - } + if (!_render_buffers_can_be_storage()) { + Vector<RID> fb; + fb.push_back(mm.texture); - if (!_render_buffers_can_be_storage()) { - // and half texture, this is an intermediate result so just allocate a texture, is this good enough? - tf.width = MAX(1, base_width >> 1); - tf.height = base_height; - tf.mipmaps = 1; // 1 or 0? + mm.fb = RD::get_singleton()->framebuffer_create(fb); + } - mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + if (!_render_buffers_can_be_storage()) { + // and half texture, this is an intermediate result so just allocate a texture, is this good enough? + tf.width = MAX(1, base_width >> 1); + tf.height = base_height; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + tf.mipmaps = 1; + + mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector<RID> half_fb; + half_fb.push_back(mm.half_texture); + mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb); + } - Vector<RID> half_fb; - half_fb.push_back(mm.half_texture); - mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb); - } + ll[0].mipmaps.push_back(mm); - rb->blur[0].mipmaps.push_back(mm); + if (i > 0) { + mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, l, i - 1); - if (i > 0) { - mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1); + if (!_render_buffers_can_be_storage()) { + Vector<RID> fb; + fb.push_back(mm.texture); - if (!_render_buffers_can_be_storage()) { - Vector<RID> fb; - fb.push_back(mm.texture); + mm.fb = RD::get_singleton()->framebuffer_create(fb); - mm.fb = RD::get_singleton()->framebuffer_create(fb); + // We can re-use the half texture here as it is an intermediate result + } - // We can re-use the half texture here as it is an intermediate result + ll[1].mipmaps.push_back(mm); } - rb->blur[1].mipmaps.push_back(mm); + base_width = MAX(1, base_width >> 1); + base_height = MAX(1, base_height >> 1); } - base_width = MAX(1, base_width >> 1); - base_height = MAX(1, base_height >> 1); + rb->blur[0].layers.push_back(ll[0]); + rb->blur[1].layers.push_back(ll[1]); } if (!_render_buffers_can_be_storage()) { @@ -1640,21 +1646,19 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP tf.width = rb->internal_width; tf.height = rb->internal_height; - tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D; - tf.array_layers = rb->view_count; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; // Our DOF effect handles one eye per turn tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; tf.mipmaps = 1; for (uint32_t i = 0; i < 4; i++) { // associated blur texture RID texture; - if (i == 0) { - texture = rb->texture; - } else if (i == 1) { - texture = rb->blur[0].mipmaps[0].texture; + if (i == 1) { + texture = rb->blur[0].layers[0].mipmaps[0].texture; } else if (i == 2) { - texture = rb->blur[1].mipmaps[0].texture; + texture = rb->blur[1].layers[0].mipmaps[0].texture; } else if (i == 3) { - texture = rb->blur[0].mipmaps[1].texture; + texture = rb->blur[0].layers[0].mipmaps[1].texture; } // create weight texture @@ -1662,7 +1666,9 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { // create frame buffer Vector<RID> fb; - fb.push_back(texture); + if (i != 0) { + fb.push_back(texture); + } fb.push_back(rb->weight_buffers[i].weight); rb->weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb); @@ -1672,13 +1678,6 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { tf.height = MAX(1u, tf.height >> 1); } } - - { - // and finally an FB for just our base weights - Vector<RID> fb; - fb.push_back(rb->weight_buffers[0].weight); - rb->base_weight_fb = RD::get_singleton()->framebuffer_create(fb); - } } } @@ -1765,6 +1764,21 @@ void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) { } void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { + if (rb->views.size() > 1) { // if 1 these are copies ofs rb->internal_texture, rb->depth_texture and rb->texture_fb + for (int i = 0; i < rb->views.size(); i++) { + if (rb->views[i].view_fb.is_valid()) { + RD::get_singleton()->free(rb->views[i].view_fb); + } + if (rb->views[i].view_texture.is_valid()) { + RD::get_singleton()->free(rb->views[i].view_texture); + } + if (rb->views[i].view_depth.is_valid()) { + RD::get_singleton()->free(rb->views[i].view_depth); + } + } + } + rb->views.clear(); + if (rb->texture_fb.is_valid()) { RD::get_singleton()->free(rb->texture_fb); rb->texture_fb = RID(); @@ -1813,24 +1827,26 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { } for (int i = 0; i < 2; i++) { - for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) { - // do we free the texture slice here? or is it enough to free the main texture? + for (int l = 0; l < rb->blur[i].layers.size(); l++) { + for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) { + // do we free the texture slice here? or is it enough to free the main texture? - // do free the mobile extra stuff - if (rb->blur[i].mipmaps[m].fb.is_valid()) { - RD::get_singleton()->free(rb->blur[i].mipmaps[m].fb); - } - // texture and framebuffer in both blur mipmaps are shared, so only free from the first one - if (i == 0) { - if (rb->blur[i].mipmaps[m].half_fb.is_valid()) { - RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_fb); + // do free the mobile extra stuff + if (rb->blur[i].layers[l].mipmaps[m].fb.is_valid()) { + RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].fb); } - if (rb->blur[i].mipmaps[m].half_texture.is_valid()) { - RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_texture); + // texture and framebuffer in both blur mipmaps are shared, so only free from the first one + if (i == 0) { + if (rb->blur[i].layers[l].mipmaps[m].half_fb.is_valid()) { + RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_fb); + } + if (rb->blur[i].layers[l].mipmaps[m].half_texture.is_valid()) { + RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_texture); + } } } } - rb->blur[i].mipmaps.clear(); + rb->blur[i].layers.clear(); if (rb->blur[i].texture.is_valid()) { RD::get_singleton()->free(rb->blur[i].texture); @@ -1998,8 +2014,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb _allocate_blur_textures(rb); } - storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); - storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].mipmaps[1].texture); + storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); + storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture); } void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { @@ -2295,14 +2311,14 @@ void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) { ERR_FAIL_COND(!rb); if (rb->ss_effects.last_frame.is_valid()) { - storage->get_effects()->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height)); + copy_effects->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height)); int width = rb->width; int height = rb->height; for (int i = 0; i < rb->ss_effects.last_frame_slices.size() - 1; i++) { width = MAX(1, width >> 1); height = MAX(1, height >> 1); - storage->get_effects()->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height)); + copy_effects->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height)); } } } @@ -2317,19 +2333,19 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData _allocate_blur_textures(rb); } - // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye - bool can_use_storage = _render_buffers_can_be_storage(); - if (can_use_storage) { - storage->get_effects()->copy_to_rect(rb->texture, rb->blur[0].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height)); - for (int i = 1; i < rb->blur[0].mipmaps.size(); i++) { - storage->get_effects()->make_mipmap(rb->blur[0].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i].texture, Size2i(rb->blur[0].mipmaps[i].width, rb->blur[0].mipmaps[i].height)); - } - } else { - storage->get_effects()->copy_to_fb_rect(rb->texture, rb->blur[0].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height)); - for (int i = 1; i < rb->blur[0].mipmaps.size(); i++) { - storage->get_effects()->make_mipmap_raster(rb->blur[0].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i].fb, Size2i(rb->blur[0].mipmaps[i].width, rb->blur[0].mipmaps[i].height)); + for (uint32_t v = 0; v < rb->view_count; v++) { + if (can_use_storage) { + copy_effects->copy_to_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height)); + for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) { + copy_effects->make_mipmap(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].texture, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height)); + } + } else { + copy_effects->copy_to_fb_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height)); + for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) { + copy_effects->make_mipmap_raster(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].fb, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height)); + } } } @@ -2351,9 +2367,9 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR bool can_use_storage = _render_buffers_can_be_storage(); if (can_use_storage) { - storage->get_effects()->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height)); + copy_effects->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height)); } else { - storage->get_effects()->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height)); + copy_effects->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height)); } RD::get_singleton()->draw_command_end_label(); @@ -2371,30 +2387,33 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende bool can_use_effects = rb->width >= 8 && rb->height >= 8; bool can_use_storage = _render_buffers_can_be_storage(); - // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye - if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) { RD::get_singleton()->draw_command_begin_label("DOF"); if (rb->blur[0].texture.is_null()) { _allocate_blur_textures(rb); } - EffectsRD::BokehBuffers buffers; + RendererRD::BokehDOF::BokehBuffers buffers; // Textures we use buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height); - buffers.base_texture = rb->internal_texture; - buffers.depth_texture = rb->depth_texture; - buffers.secondary_texture = rb->blur[0].mipmaps[0].texture; - buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture; - buffers.half_texture[1] = rb->blur[0].mipmaps[1].texture; + buffers.secondary_texture = rb->blur[0].layers[0].mipmaps[0].texture; + buffers.half_texture[0] = rb->blur[1].layers[0].mipmaps[0].texture; + buffers.half_texture[1] = rb->blur[0].layers[0].mipmaps[1].texture; float bokeh_size = camfx->dof_blur_amount * 64.0; if (can_use_storage) { - storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_orthogonal); + for (uint32_t i = 0; i < rb->view_count; i++) { + buffers.base_texture = rb->views[i].view_texture; + buffers.depth_texture = rb->views[i].view_depth; + + // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum + float z_near = p_render_data->view_projection[i].get_z_near(); + float z_far = p_render_data->view_projection[i].get_z_far(); + bokeh_dof->bokeh_dof_compute(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, z_near, z_far, p_render_data->cam_orthogonal); + }; } else { // Set framebuffers. - buffers.base_fb = rb->texture_fb; buffers.secondary_fb = rb->weight_buffers[1].fb; buffers.half_fb[0] = rb->weight_buffers[2].fb; buffers.half_fb[1] = rb->weight_buffers[3].fb; @@ -2404,9 +2423,18 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende buffers.weight_texture[3] = rb->weight_buffers[3].weight; // Set weight buffers. - buffers.base_weight_fb = rb->base_weight_fb; + buffers.base_weight_fb = rb->weight_buffers[0].fb; + + for (uint32_t i = 0; i < rb->view_count; i++) { + buffers.base_texture = rb->views[i].view_texture; + buffers.depth_texture = rb->views[i].view_depth; + buffers.base_fb = rb->views[i].view_fb; - storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_orthogonal); + // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum + float z_near = p_render_data->view_projection[i].get_z_near(); + float z_far = p_render_data->view_projection[i].get_z_far(); + bokeh_dof->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, z_near, z_far, p_render_data->cam_orthogonal); + } } RD::get_singleton()->draw_command_end_label(); } @@ -2449,33 +2477,36 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { if (env->glow_levels[i] > 0.0) { - if (i >= rb->blur[1].mipmaps.size()) { - max_glow_level = rb->blur[1].mipmaps.size() - 1; + if (i >= rb->blur[1].layers[0].mipmaps.size()) { + max_glow_level = rb->blur[1].layers[0].mipmaps.size() - 1; } else { max_glow_level = i; } } } - for (int i = 0; i < (max_glow_level + 1); i++) { - int vp_w = rb->blur[1].mipmaps[i].width; - int vp_h = rb->blur[1].mipmaps[i].height; + float luminance_multiplier = _render_buffers_get_luminance_multiplier(); + for (uint32_t l = 0; l < rb->view_count; l++) { + for (int i = 0; i < (max_glow_level + 1); i++) { + int vp_w = rb->blur[1].layers[l].mipmaps[i].width; + int vp_h = rb->blur[1].layers[l].mipmaps[i].height; - if (i == 0) { - RID luminance_texture; - if (env->auto_exposure && rb->luminance.current.is_valid()) { - luminance_texture = rb->luminance.current; - } - if (can_use_storage) { - storage->get_effects()->gaussian_glow(rb->internal_texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); - } else { - storage->get_effects()->gaussian_glow_raster(rb->internal_texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); - } - } else { - if (can_use_storage) { - storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + if (i == 0) { + RID luminance_texture; + if (env->auto_exposure && rb->luminance.current.is_valid()) { + luminance_texture = rb->luminance.current; + } + if (can_use_storage) { + copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + } else { + copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + } } else { - storage->get_effects()->gaussian_glow_raster(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, glow_high_quality); + if (can_use_storage) { + copy_effects->gaussian_glow(rb->blur[1].layers[l].mipmaps[i - 1].texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + } else { + copy_effects->gaussian_glow_raster(rb->blur[1].layers[l].mipmaps[i - 1].texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + } } } } @@ -2503,8 +2534,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { tonemap.glow_levels[i] = env->glow_levels[i]; } - tonemap.glow_texture_size.x = rb->blur[1].mipmaps[0].width; - tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height; + tonemap.glow_texture_size.x = rb->blur[1].layers[0].mipmaps[0].width; + tonemap.glow_texture_size.y = rb->blur[1].layers[0].mipmaps[0].height; tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale; tonemap.glow_texture = rb->blur[1].texture; if (env->glow_map.is_valid()) { @@ -2562,7 +2593,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) { - RD::get_singleton()->draw_command_begin_label("FSR Upscale"); + RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale"); storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness); @@ -2652,7 +2683,6 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - EffectsRD *effects = storage->get_effects(); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -2666,7 +2696,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID } Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); + copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); } } @@ -2675,7 +2705,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID RID shadow_atlas_texture = directional_shadow_get_texture(); Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); + copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); } } @@ -2685,7 +2715,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID if (decal_atlas.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true); + copy_effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true); } } @@ -2693,36 +2723,36 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID if (rb->luminance.current.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true); + copy_effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true); } } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ss_effects.ssao.ao_final.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); + copy_effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb->ss_effects.ssil.ssil_final.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); + copy_effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); + copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->ambient_buffer.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); RID ambient_texture = rb->ambient_buffer; RID reflection_texture = rb->reflection_buffer; - effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture); + copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) { if (p_occlusion_buffer.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); + copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); } } } @@ -3035,12 +3065,38 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); } - if (!_render_buffers_can_be_storage()) { - // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS! - Vector<RID> fb; - fb.push_back(rb->internal_texture); + { + if (!_render_buffers_can_be_storage()) { + // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS! + Vector<RID> fb; + fb.push_back(rb->internal_texture); + + rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count); + } - rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count); + rb->views.clear(); // JIC + if (rb->view_count == 1) { + // copy as a convenience + RenderBuffers::View view; + view.view_texture = rb->internal_texture; + view.view_depth = rb->depth_texture; + view.view_fb = rb->texture_fb; + rb->views.push_back(view); + } else { + for (uint32_t i = 0; i < rb->view_count; i++) { + RenderBuffers::View view; + view.view_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->internal_texture, i, 0); + view.view_depth = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->depth_texture, i, 0); + + if (!_render_buffers_can_be_storage()) { + Vector<RID> fb; + fb.push_back(view.view_texture); + view.view_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, 1); + } + + rb->views.push_back(view); + } + } } RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target); @@ -3903,45 +3959,45 @@ void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const Strin } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + RBMap<int, StringName> order; - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { - if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - if (E->get().texture_order >= 0) { - order[E->get().texture_order + 100000] = E->key(); + if (E.value.texture_order >= 0) { + order[E.value.texture_order + 100000] = E.key; } else { - order[E->get().order] = E->key(); + order[E.value.order] = E.key; } } - for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) { - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); - pi.name = E->get(); + for (const KeyValue<int, StringName> &E : order) { + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); + pi.name = E.value; p_param_list->push_back(pi); } } void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { - if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E->get()); - p.info.name = E->key(); //supply name - p.index = E->get().instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().array_size, E->get().hint); + p.info = ShaderLanguage::uniform_to_property_info(E.value); + p.info.name = E.key; //supply name + p.index = E.value.instance_index; + p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); p_param_list->push_back(p); } } @@ -3989,7 +4045,7 @@ RendererSceneRenderRD::FogShaderData::~FogShaderData() { //////////////////////////////////////////////////////////////////////////////// // Fog material -bool RendererSceneRenderRD::FogMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool RendererSceneRenderRD::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -5408,7 +5464,7 @@ bool RendererSceneRenderRD::free(RID p_rid) { LightInstance *light_instance = light_instance_owner.get_or_null(p_rid); //remove from shadow atlases.. - for (Set<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E->get()); ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid)); uint32_t key = shadow_atlas->shadow_owners[p_rid]; @@ -5836,12 +5892,21 @@ void fog() { cull_argument.set_page_pool(&cull_argument_pool); + bool can_use_storage = _render_buffers_can_be_storage(); + bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage)); + copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage)); tone_mapper = memnew(RendererRD::ToneMapper); } RendererSceneRenderRD::~RendererSceneRenderRD() { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + if (bokeh_dof) { + memdelete(bokeh_dof); + } + if (copy_effects) { + memdelete(copy_effects); + } if (tone_mapper) { memdelete(tone_mapper); } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 6bf3a95dd0..4daee17525 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -35,6 +35,8 @@ #include "core/templates/rid_owner.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/cluster_builder_rd.h" +#include "servers/rendering/renderer_rd/effects/bokeh_dof.h" +#include "servers/rendering/renderer_rd/effects/copy_effects.h" #include "servers/rendering/renderer_rd/effects/tone_mapper.h" #include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_gi_rd.h" @@ -94,6 +96,8 @@ class RendererSceneRenderRD : public RendererSceneRender { protected: RendererStorageRD *storage = nullptr; + RendererRD::BokehDOF *bokeh_dof = nullptr; + RendererRD::CopyEffects *copy_effects = nullptr; RendererRD::ToneMapper *tone_mapper = nullptr; double time = 0.0; double time_step = 0.0; @@ -293,7 +297,7 @@ private: RID depth; RID fb; //for copying - Map<RID, uint32_t> shadow_owners; + HashMap<RID, uint32_t> shadow_owners; }; RID_Owner<ShadowAtlas> shadow_atlas_owner; @@ -341,7 +345,7 @@ private: RID side_fb[6]; }; - Map<int, ShadowCubemap> shadow_cubemaps; + HashMap<int, ShadowCubemap> shadow_cubemaps; ShadowCubemap *_get_shadow_cubemap(int p_size); void _create_shadow_cubemaps(); @@ -383,7 +387,7 @@ private: Rect2 directional_rect; - Set<RID> shadow_atlases; //shadow atlases where this light is registered + RBSet<RID> shadow_atlases; //shadow atlases where this light is registered ForwardID forward_id = -1; @@ -482,6 +486,14 @@ private: RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!! RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling) + // Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images) + struct View { + RID view_texture; // texture slice for this view/layer + RID view_depth; // depth slice for this view/layer + RID view_fb; // framebuffer for this view/layer, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!! + }; + Vector<View> views; + RendererSceneGIRD::SDFGI *sdfgi = nullptr; VolumetricFog *volumetric_fog = nullptr; RendererSceneGIRD::RenderBuffersGI gi; @@ -503,19 +515,22 @@ private: RID half_fb; }; - Vector<Mipmap> mipmaps; + struct Layer { + Vector<Mipmap> mipmaps; + }; + + Vector<Layer> layers; }; Blur blur[2]; //the second one starts from the first mipmap struct WeightBuffers { RID weight; - RID fb; // FB with both texture and weight + RID fb; // FB with both texture and weight writing into one level lower }; // 2 full size, 2 half size WeightBuffers weight_buffers[4]; // Only used in raster - RID base_weight_fb; // base buffer for weight RID depth_back_texture; RID depth_back_fb; // only used on mobile @@ -906,7 +921,7 @@ private: RID version; RID pipeline; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; @@ -914,7 +929,7 @@ private: String path; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_time = false; @@ -939,7 +954,7 @@ private: virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~FogMaterialData(); }; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 51cf0e952b..14a5f02eee 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/math/math_defs.h" #include "renderer_scene_render_rd.h" +#include "servers/rendering/renderer_rd/effects/copy_effects.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" @@ -150,14 +151,14 @@ void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringNa } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { @@ -236,7 +237,7 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { //////////////////////////////////////////////////////////////////////////////// // Sky material -bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -730,8 +731,10 @@ bool RendererSceneSkyRD::Sky::set_material(RID p_material) { return true; } -Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage, float p_energy, int p_roughness_layers, const Size2i &p_size) { +Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) { if (radiance.is_valid()) { + RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); + RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; tf.width = p_size.width; @@ -739,7 +742,7 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage, tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; RID rad_tex = RD::get_singleton()->texture_create(tf, RD::TextureView()); - p_storage->get_effects()->copy_cubemap_to_panorama(radiance, rad_tex, p_size, p_roughness_layers, reflection.layers.size() > 1); + copy_effects->copy_cubemap_to_panorama(radiance, rad_tex, p_size, p_roughness_layers, reflection.layers.size() > 1); Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0); RD::get_singleton()->free(rad_tex); @@ -1905,7 +1908,7 @@ Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool update_dirty_skys(); - return sky->bake_panorama(storage, p_energy, p_bake_irradiance ? roughness_layers : 0, p_size); + return sky->bake_panorama(p_energy, p_bake_irradiance ? roughness_layers : 0, p_size); } RID RendererSceneSkyRD::sky_get_radiance_texture_rd(RID p_sky) const { diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index 497d27ec26..83a8fe6e77 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -110,7 +110,7 @@ private: RID version; PipelineCacheRD pipelines[SKY_VERSION_MAX]; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; @@ -118,7 +118,7 @@ private: String path; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_time = false; bool uses_position = false; @@ -235,7 +235,7 @@ public: virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~SkyMaterialData(); }; @@ -273,7 +273,7 @@ public: bool set_radiance_size(int p_radiance_size); bool set_mode(RS::SkyMode p_mode); bool set_material(RID p_material); - Ref<Image> bake_panorama(RendererStorageRD *p_storage, float p_energy, int p_roughness_layers, const Size2i &p_size); + Ref<Image> bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size); }; uint32_t sky_ggx_samples_quality; diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index fdfecf2d2c..04e05380f1 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -522,7 +522,7 @@ void ShaderRD::_compile_version(Version *p_version) { p_version->valid = true; } -void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) { +void ShaderRD::version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) { ERR_FAIL_COND(is_compute); Version *version = version_owner.get_or_null(p_version); @@ -547,7 +547,7 @@ void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code } } -void ShaderRD::version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines) { +void ShaderRD::version_set_compute_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines) { ERR_FAIL_COND(!is_compute); Version *version = version_owner.get_or_null(p_version); diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index 8e57f0d9af..40b10808c2 100644 --- a/servers/rendering/renderer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -35,7 +35,7 @@ #include "core/string/string_builder.h" #include "core/templates/hash_map.h" #include "core/templates/local_vector.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/templates/rid_owner.h" #include "core/variant/variant.h" #include "servers/rendering_server.h" @@ -51,7 +51,7 @@ class ShaderRD { CharString vertex_globals; CharString compute_globals; CharString fragment_globals; - Map<StringName, CharString> code_sections; + HashMap<StringName, CharString> code_sections; Vector<CharString> custom_defines; Vector<uint8_t> *variant_data = nullptr; @@ -129,8 +129,8 @@ protected: public: RID version_create(); - void version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines); - void version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines); + void version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines); + void version_set_compute_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines); _FORCE_INLINE_ RID version_get_shader(RID p_version, int p_variant) { ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID()); diff --git a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl deleted file mode 100644 index e7a2e18323..0000000000 --- a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl +++ /dev/null @@ -1,21 +0,0 @@ -#define FLAG_HORIZONTAL (1 << 0) -#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1) -#define FLAG_GLOW_FIRST_PASS (1 << 2) - -layout(push_constant, std430) uniform Blur { - vec2 pixel_size; - uint flags; - uint pad; - - // Glow. - float glow_strength; - float glow_bloom; - float glow_hdr_threshold; - float glow_hdr_scale; - - float glow_exposure; - float glow_white; - float glow_luminance_cap; - float glow_auto_exposure_grey; -} -blur; diff --git a/servers/rendering/renderer_rd/shaders/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl index f8b4e3f610..96f5c3e9f2 100644 --- a/servers/rendering/renderer_rd/shaders/blur_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl @@ -53,7 +53,9 @@ void main() { #ifdef MODE_GAUSSIAN_BLUR - //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect + // Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect + + // note, for blur blur.luminance_multiplier is irrelavant, we would be multiplying and then dividing by this amount. if (bool(blur.flags & FLAG_HORIZONTAL)) { vec2 pix_size = blur.pixel_size; @@ -94,6 +96,7 @@ void main() { if (bool(blur.flags & FLAG_HORIZONTAL)) { vec2 pix_size = blur.pixel_size; pix_size *= 0.5; //reading from larger buffer, so use more samples + vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938; GLOW_ADD(vec2(1.0, 0.0), 0.165569); GLOW_ADD(vec2(2.0, 0.0), 0.140367); @@ -101,7 +104,10 @@ void main() { GLOW_ADD(vec2(-1.0, 0.0), 0.165569); GLOW_ADD(vec2(-2.0, 0.0), 0.140367); GLOW_ADD(vec2(-3.0, 0.0), 0.106595); + + // only do this in the horizontal pass, if we also do this in the vertical pass we're doubling up. color *= blur.glow_strength; + frag_color = color; } else { vec2 pix_size = blur.pixel_size; @@ -110,13 +116,17 @@ void main() { GLOW_ADD(vec2(0.0, 2.0), 0.122581); GLOW_ADD(vec2(0.0, -1.0), 0.233062); GLOW_ADD(vec2(0.0, -2.0), 0.122581); - color *= blur.glow_strength; + frag_color = color; } #undef GLOW_ADD if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) { + // In the first pass bring back to correct color range else we're applying the wrong threshold + // in subsequent passes we can use it as is as we'd just be undoing it right after. + frag_color *= blur.luminance_multiplier; + #ifdef GLOW_USE_AUTO_EXPOSURE frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey; @@ -126,10 +136,10 @@ void main() { float luminance = max(frag_color.r, max(frag_color.g, frag_color.b)); float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom); - frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap)); + frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap)) / blur.luminance_multiplier; } -#endif +#endif // MODE_GAUSSIAN_GLOW #ifdef MODE_COPY vec4 color = textureLod(source_color, uv_interp, 0.0); diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl new file mode 100644 index 0000000000..730504571a --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl @@ -0,0 +1,26 @@ +#define FLAG_HORIZONTAL (1 << 0) +#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1) +#define FLAG_GLOW_FIRST_PASS (1 << 2) + +layout(push_constant, std430) uniform Blur { + vec2 pixel_size; // 08 - 08 + uint flags; // 04 - 12 + uint pad; // 04 - 16 + + // Glow. + float glow_strength; // 04 - 20 + float glow_bloom; // 04 - 24 + float glow_hdr_threshold; // 04 - 28 + float glow_hdr_scale; // 04 - 32 + + float glow_exposure; // 04 - 36 + float glow_white; // 04 - 40 + float glow_luminance_cap; // 04 - 44 + float glow_auto_exposure_grey; // 04 - 48 + + float luminance_multiplier; // 04 - 52 + float res1; // 04 - 56 + float res2; // 04 - 60 + float res3; // 04 - 64 +} +blur; diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl index 0438671dd2..0438671dd2 100644 --- a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl index b90a527554..b90a527554 100644 --- a/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl index a3b3938ee9..a3b3938ee9 100644 --- a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl diff --git a/servers/rendering/renderer_rd/shaders/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl index 4563ac7af9..3a4ef86ef0 100644 --- a/servers/rendering/renderer_rd/shaders/copy.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl @@ -189,7 +189,7 @@ void main() { #endif color *= params.glow_exposure; - float luminance = dot(color.rgb, vec3(0.299, 0.587, 0.114)); + float luminance = max(color.r, max(color.g, color.b)); float feedback = max(smoothstep(params.glow_hdr_threshold, params.glow_hdr_threshold + params.glow_hdr_scale, luminance), params.glow_bloom); color = min(color * feedback, vec4(params.glow_luminance_cap)); diff --git a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl index 9787c9879d..9787c9879d 100644 --- a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl diff --git a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl index 19a9350137..5a238452c0 100644 --- a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl @@ -44,7 +44,11 @@ layout(set = 0, binding = 0) uniform sampler2D source_color; #endif layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; +#ifdef MULTIVIEW +layout(set = 2, binding = 0) uniform sampler2DArray source_glow; +#else layout(set = 2, binding = 0) uniform sampler2D source_glow; +#endif layout(set = 2, binding = 1) uniform sampler2D glow_map; #ifdef USE_1D_LUT @@ -118,6 +122,36 @@ float h1(float a) { return 1.0f + w3(a) / (w2(a) + w3(a)); } +#ifdef MULTIVIEW +vec4 texture2D_bicubic(sampler2DArray tex, vec2 uv, int p_lod) { + float lod = float(p_lod); + vec2 tex_size = vec2(params.glow_texture_size >> p_lod); + vec2 pixel_size = vec2(1.0f) / tex_size; + + uv = uv * tex_size + vec2(0.5f); + + vec2 iuv = floor(uv); + vec2 fuv = fract(uv); + + float g0x = g0(fuv.x); + float g1x = g1(fuv.x); + float h0x = h0(fuv.x); + float h1x = h1(fuv.x); + float h0y = h0(fuv.y); + float h1y = h1(fuv.y); + + vec3 p0 = vec3((vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5f)) * pixel_size, ViewIndex); + vec3 p1 = vec3((vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5f)) * pixel_size, ViewIndex); + vec3 p2 = vec3((vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5f)) * pixel_size, ViewIndex); + vec3 p3 = vec3((vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size, ViewIndex); + + return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) + + (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod))); +} + +#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod) +#else // MULTIVIEW + vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) { float lod = float(p_lod); vec2 tex_size = vec2(params.glow_texture_size >> p_lod); @@ -145,12 +179,17 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) { } #define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod) +#endif // !MULTIVIEW -#else +#else // USE_GLOW_FILTER_BICUBIC +#ifdef MULTIVIEW +#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, vec3(m_uv, ViewIndex), float(m_lod)) +#else // MULTIVIEW #define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod)) +#endif // !MULTIVIEW -#endif +#endif // !USE_GLOW_FILTER_BICUBIC vec3 tonemap_filmic(vec3 color, float white) { // exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers @@ -231,7 +270,11 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o } } +#ifdef MULTIVIEW +vec3 gather_glow(sampler2DArray tex, vec2 uv) { // sample all selected glow levels, view is added to uv later +#else vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels +#endif // defined(MULTIVIEW) vec3 glow = vec3(0.0f); if (params.glow_levels[0] > 0.0001) { diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 58b4ded9f4..4f49c186a6 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -679,7 +679,7 @@ void main() { float normal_map_depth = 1.0; - vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center + vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size; float sss_strength = 0.0; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index b6ba244665..fd0fefc5fd 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -650,7 +650,7 @@ void main() { float normal_map_depth = 1.0; - vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center + vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size; float sss_strength = 0.0; @@ -924,7 +924,7 @@ void main() { #endif // !USE_LIGHTMAP #if defined(CUSTOM_IRRADIANCE_USED) - ambient_light = mix(specular_light, custom_irradiance.rgb, custom_irradiance.a); + ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a); #endif // CUSTOM_IRRADIANCE_USED #ifdef LIGHT_CLEARCOAT_USED diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 9ca2973fd4..27f0c5f273 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -896,7 +896,7 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, /////////////////////////////////////////////////////////////////////////// // MaterialData -void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { +void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { MaterialStorage *material_storage = MaterialStorage::get_singleton(); bool uses_global_buffer = false; @@ -943,11 +943,11 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S ERR_CONTINUE(offset + size > p_buffer_size); #endif uint8_t *data = &p_buffer[offset]; - const Map<StringName, Variant>::Element *V = p_parameters.find(E.key); + HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(E.key); if (V) { //user provided - _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color); + _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->value, data, p_use_linear_color); } else if (E.value.default_value.size()) { //default value @@ -1001,7 +1001,7 @@ MaterialData::~MaterialData() { } } -void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { +void MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { TextureStorage *texture_storage = TextureStorage::get_singleton(); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -1029,12 +1029,12 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); } else { - Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name); + HashMap<StringName, uint64_t>::Iterator E = used_global_textures.find(uniform_name); if (!E) { E = used_global_textures.insert(uniform_name, global_textures_pass); v->texture_materials.insert(self); } else { - E->get() = global_textures_pass; + E->value = global_textures_pass; } textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value); @@ -1044,10 +1044,10 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly."); } } else { - const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name); + HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(uniform_name); if (V) { - if (V->get().is_array()) { - Array array = (Array)V->get(); + if (V->value.is_array()) { + Array array = (Array)V->value; if (uniform_array_size > 0) { for (int j = 0; j < array.size(); j++) { textures.push_back(array[j]); @@ -1058,25 +1058,25 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, } } } else { - textures.push_back(V->get()); + textures.push_back(V->value); } } if (uniform_array_size > 0) { if (textures.size() < uniform_array_size) { - const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); + HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name); for (int j = textures.size(); j < uniform_array_size; j++) { - if (W && W->get().has(j)) { - textures.push_back(W->get()[j]); + if (W && W->value.has(j)) { + textures.push_back(W->value[j]); } else { textures.push_back(RID()); } } } } else if (textures.is_empty()) { - const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); - if (W && W->get().has(0)) { - textures.push_back(W->get()[0]); + HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name); + if (W && W->value.has(0)) { + textures.push_back(W->value[0]); } } } @@ -1190,12 +1190,12 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, } { //for textures no longer used, unregister them - List<Map<StringName, uint64_t>::Element *> to_delete; - for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) { - if (E->get() != global_textures_pass) { - to_delete.push_back(E); + List<StringName> to_delete; + for (KeyValue<StringName, uint64_t> &E : used_global_textures) { + if (E.value != global_textures_pass) { + to_delete.push_back(E.key); - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E->key()); + GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); if (v) { v->texture_materials.erase(self); } @@ -1225,7 +1225,7 @@ void MaterialData::free_parameters_uniform_set(RID p_uniform_set) { } } -bool MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { +bool MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { if ((uint32_t)ubo_data.size() != p_ubo_size) { p_uniform_dirty = true; if (uniform_buffer.is_valid()) { @@ -1420,6 +1420,25 @@ MaterialStorage::MaterialStorage() { //custom sampler sampler_rd_configure_custom(0.0f); + // buffers + { //create index array for copy shaders + Vector<uint8_t> pv; + pv.resize(6 * 4); + { + uint8_t *w = pv.ptrw(); + int *p32 = (int *)w; + p32[0] = 0; + p32[1] = 1; + p32[2] = 2; + p32[3] = 0; + p32[4] = 2; + p32[5] = 3; + } + quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); + quad_index_array = RD::get_singleton()->index_array_create(quad_index_buffer, 0, 6); + } + + // Shaders for (int i = 0; i < SHADER_TYPE_MAX; i++) { shader_data_request_func[i] = nullptr; } @@ -1441,6 +1460,10 @@ MaterialStorage::~MaterialStorage() { memdelete_arr(global_variables.buffer_dirty_regions); RD::get_singleton()->free(global_variables.buffer); + // buffers + + RD::get_singleton()->free(quad_index_buffer); //array gets freed as dependency + //def samplers for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { @@ -1936,10 +1959,9 @@ Vector<StringName> MaterialStorage::global_variable_get_list() const { ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); } - const StringName *K = nullptr; Vector<StringName> names; - while ((K = global_variables.variables.next(K))) { - names.push_back(*K); + for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) { + names.push_back(E.key); } names.sort_custom<StringName::AlphCompare>(); return names; @@ -1957,7 +1979,7 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { Material *material = material_storage->get_material(E->get()); ERR_CONTINUE(!material); material_storage->_material_queue_update(material, false, true); @@ -1989,7 +2011,7 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { Material *material = material_storage->get_material(E->get()); ERR_CONTINUE(!material); material_storage->_material_queue_update(material, false, true); @@ -2283,7 +2305,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->data = nullptr; } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); material->shader_type = new_type; if (material->data) { @@ -2300,7 +2322,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->type = SHADER_TYPE_MAX; //invalid } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); if (shader->data) { material->data = material_get_data_request_function(new_type)(shader->data); @@ -2312,7 +2334,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { } if (shader->data) { - for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) { + for (const KeyValue<StringName, HashMap<int, RID>> &E : shader->default_texture_parameter) { for (const KeyValue<int, RID> &E2 : E.value) { shader->data->set_default_texture_param(E.key, E2.value, E2.key); } @@ -2324,7 +2346,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->data->set_code(p_code); } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); _material_queue_update(material, true, true); @@ -2351,7 +2373,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) { if (!shader->default_texture_parameter.has(p_name)) { - shader->default_texture_parameter[p_name] = Map<int, RID>(); + shader->default_texture_parameter[p_name] = HashMap<int, RID>(); } shader->default_texture_parameter[p_name][p_index] = p_texture; } else { @@ -2366,7 +2388,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin if (shader->data) { shader->data->set_default_texture_param(p_name, p_texture, p_index); } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); _material_queue_update(material, false, true); } diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index c8cc418c3a..7d4db49f78 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -76,23 +76,23 @@ struct Shader { ShaderData *data = nullptr; String code; ShaderType type; - Map<StringName, Map<int, RID>> default_texture_parameter; - Set<Material *> owners; + HashMap<StringName, HashMap<int, RID>> default_texture_parameter; + RBSet<Material *> owners; }; /* Material structs */ struct MaterialData { - void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); + void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); + void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); virtual void set_render_priority(int p_priority) = 0; virtual void set_next_pass(RID p_pass) = 0; - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; virtual ~MaterialData(); //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); void free_parameters_uniform_set(RID p_uniform_set); private: @@ -101,7 +101,7 @@ private: List<RID>::Element *global_buffer_E = nullptr; List<RID>::Element *global_texture_E = nullptr; uint64_t global_textures_pass = 0; - Map<StringName, uint64_t> used_global_textures; + HashMap<StringName, uint64_t> used_global_textures; //internally by update_parameters_uniform_set Vector<uint8_t> ubo_data; @@ -120,7 +120,7 @@ struct Material { uint32_t shader_id = 0; bool uniform_dirty = false; bool texture_dirty = false; - Map<StringName, Variant> params; + HashMap<StringName, Variant> params; int32_t priority = 0; RID next_pass; SelfList<Material> update_element; @@ -137,7 +137,7 @@ struct GlobalVariables { BUFFER_DIRTY_REGION_SIZE = 1024 }; struct Variable { - Set<RID> texture_materials; // materials using this + RBSet<RID> texture_materials; // materials using this RS::GlobalVariableType type; Variant value; @@ -200,6 +200,11 @@ private: RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + /* Buffers */ + + RID quad_index_buffer; + RID quad_index_array; + /* GLOBAL VARIABLE API */ GlobalVariables global_variables; @@ -240,6 +245,10 @@ public: // void sampler_rd_set_default(float p_mipmap_bias); + /* Buffers */ + + RID get_quad_index_array() { return quad_index_array; } + /* GLOBAL VARIABLE API */ void _update_global_variables(); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 9b7b0d2c25..fa051c92ed 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -215,7 +215,7 @@ void MeshStorage::mesh_free(RID p_rid) { ERR_PRINT("deleting mesh with active instances"); } if (mesh->shadow_owners.size()) { - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + for (RBSet<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { Mesh *shadow_owner = E->get(); shadow_owner->shadow_mesh = RID(); shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); @@ -431,7 +431,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + for (RBSet<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { Mesh *shadow_owner = E->get(); shadow_owner->shadow_mesh = RID(); shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); @@ -742,7 +742,7 @@ void MeshStorage::mesh_clear(RID p_mesh) { mesh->has_bone_weights = false; mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + for (RBSet<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { Mesh *shadow_owner = E->get(); shadow_owner->shadow_mesh = RID(); shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 7d3f603afd..d90bb2f128 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -141,7 +141,7 @@ struct Mesh { List<MeshInstance *> instances; RID shadow_mesh; - Set<Mesh *> shadow_owners; + RBSet<Mesh *> shadow_owners; RendererStorage::Dependency dependency; }; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 094120f908..1701b56b0b 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -838,7 +838,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta } uint32_t collision_3d_textures_used = 0; - for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) { + for (const RBSet<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) { ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E->get()); if (!pci || !pci->active) { continue; @@ -1592,14 +1592,14 @@ void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const Stri } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { @@ -1676,7 +1676,7 @@ ShaderData *ParticlesStorage::_create_particles_shader_func() { return shader_data; } -bool ParticlesStorage::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool ParticlesStorage::ParticlesMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index c6480794c1..eb55db19fb 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -224,7 +224,7 @@ struct Particles { ParticleEmissionBuffer *emission_buffer = nullptr; RID emission_storage_buffer; - Set<RID> collisions; + RBSet<RID> collisions; RendererStorage::Dependency dependency; @@ -345,7 +345,7 @@ private: RID version; bool uses_collision = false; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; @@ -353,7 +353,7 @@ private: String path; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; RID pipeline; @@ -387,7 +387,7 @@ private: virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~ParticlesMaterialData(); }; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 3b52a187f6..7d4808f936 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -29,8 +29,8 @@ /*************************************************************************/ #include "texture_storage.h" - -#include "../renderer_storage_rd.h" +#include "../effects/copy_effects.h" +#include "material_storage.h" using namespace RendererRD; @@ -1808,8 +1808,8 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const { } void TextureStorage::update_decal_atlas() { - EffectsRD *effects = RendererStorageRD::base_singleton->get_effects(); - ERR_FAIL_NULL(effects); + RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); + ERR_FAIL_NULL(copy_effects); if (!decal_atlas.dirty) { return; //nothing to do @@ -1831,13 +1831,13 @@ void TextureStorage::update_decal_atlas() { Vector<DecalAtlas::SortItem> itemsv; itemsv.resize(decal_atlas.textures.size()); int base_size = 8; - const RID *K = nullptr; int idx = 0; - while ((K = decal_atlas.textures.next(K))) { + + for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) { DecalAtlas::SortItem &si = itemsv.write[idx]; - Texture *src_tex = get_texture(*K); + Texture *src_tex = get_texture(E.key); si.size.width = (src_tex->width / border) + 1; si.size.height = (src_tex->height / border) + 1; @@ -1847,7 +1847,7 @@ void TextureStorage::update_decal_atlas() { base_size = nearest_power_of_2_templated(si.size.width); } - si.texture = *K; + si.texture = E.key; idx++; } @@ -1983,18 +1983,17 @@ void TextureStorage::update_decal_atlas() { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc); - const RID *K = nullptr; - while ((K = decal_atlas.textures.next(K))) { - DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K); - Texture *src_tex = get_texture(*K); - effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0); + for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) { + DecalAtlas::Texture *t = decal_atlas.textures.getptr(E.key); + Texture *src_tex = get_texture(E.key); + copy_effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0); } RD::get_singleton()->draw_list_end(); prev_texture = mm.texture; } else { - effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size)); + copy_effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size)); prev_texture = mm.texture; } } else { @@ -2623,8 +2622,8 @@ void TextureStorage::render_target_sdf_process(RID p_render_target) { } void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) { - EffectsRD *effects = RendererStorageRD::base_singleton->get_effects(); - ERR_FAIL_NULL(effects); + CopyEffects *copy_effects = CopyEffects::get_singleton(); + ERR_FAIL_NULL(copy_effects); RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); @@ -2642,9 +2641,11 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons } } + // TODO figure out stereo support here + //single texture copy for backbuffer //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true); - effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true); + copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true); if (!p_gen_mipmaps) { return; @@ -2660,7 +2661,7 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons region.size.y = MAX(1, region.size.y >> 1); RID mipmap = rt->backbuffer_mipmaps[i]; - effects->gaussian_blur(prev_texture, mipmap, region, true); + copy_effects->gaussian_blur(prev_texture, mipmap, region, true); prev_texture = mipmap; } RD::get_singleton()->draw_command_end_label(); @@ -2670,8 +2671,8 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); - EffectsRD *effects = RendererStorageRD::base_singleton->get_effects(); - ERR_FAIL_NULL(effects); + CopyEffects *copy_effects = CopyEffects::get_singleton(); + ERR_FAIL_NULL(copy_effects); if (!rt->backbuffer.is_valid()) { _create_render_target_backbuffer(rt); @@ -2688,15 +2689,15 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const } //single texture copy for backbuffer - effects->set_color(rt->backbuffer_mipmap0, p_color, region, true); + copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true); } void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); - EffectsRD *effects = RendererStorageRD::base_singleton->get_effects(); - ERR_FAIL_NULL(effects); + CopyEffects *copy_effects = CopyEffects::get_singleton(); + ERR_FAIL_NULL(copy_effects); if (!rt->backbuffer.is_valid()) { _create_render_target_backbuffer(rt); @@ -2722,7 +2723,7 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, region.size.y = MAX(1, region.size.y >> 1); RID mipmap = rt->backbuffer_mipmaps[i]; - effects->gaussian_blur(prev_texture, mipmap, region, true); + copy_effects->gaussian_blur(prev_texture, mipmap, region, true); prev_texture = mipmap; } RD::get_singleton()->draw_command_end_label(); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index a6f50803e4..029816cbda 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -124,7 +124,7 @@ public: RID proxy_to; Vector<RID> proxies; - Set<RID> lightmap_users; + RBSet<RID> lightmap_users; RS::TextureDetectCallback detect_3d_callback = nullptr; void *detect_3d_callback_ud = nullptr; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 6e1fa59a7a..37bbab86ff 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -609,13 +609,16 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { if (p_base.is_valid()) { instance->base_type = RSG::storage->get_base_type(p_base); + // fix up a specific malfunctioning case before the switch, so it can be handled if (instance->base_type == RS::INSTANCE_NONE && RendererSceneOcclusionCull::get_singleton()->is_occluder(p_base)) { instance->base_type = RS::INSTANCE_OCCLUDER; } - ERR_FAIL_COND(instance->base_type == RS::INSTANCE_NONE); - switch (instance->base_type) { + case RS::INSTANCE_NONE: { + ERR_PRINT_ONCE("unimplemented base type encountered in renderer scene cull"); + return; + } case RS::INSTANCE_LIGHT: { InstanceLightData *light = memnew(InstanceLightData); @@ -650,7 +653,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr()); } - for (Set<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) { Instance *dep_instance = E->get(); ERR_CONTINUE(dep_instance->array_index == -1); ERR_CONTINUE(dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index != -1); @@ -1289,14 +1292,14 @@ void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_par bool RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) { bool cycle_detected = false; - Set<Instance *> traversed_nodes; + RBSet<Instance *> traversed_nodes; { Instance *instance = p_instance; while (instance) { if (!instance->visibility_dependencies.is_empty()) { uint32_t depth = 0; - for (Set<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) { depth = MAX(depth, E->get()->visibility_dependencies_depth); } instance->visibility_dependencies_depth = depth + 1; @@ -1426,7 +1429,7 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); - Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter); + HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_parameters.find(p_parameter); if (!E) { Instance::InstanceShaderParameter isp; @@ -1435,10 +1438,10 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c isp.value = p_value; instance->instance_shader_parameters[p_parameter] = isp; } else { - E->get().value = p_value; - if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) { + E->value.value = p_value; + if (E->value.index >= 0 && instance->instance_allocated_shader_parameters) { //update directly - RSG::material_storage->global_variables_instance_update(p_instance, E->get().index, p_value); + RSG::material_storage->global_variables_instance_update(p_instance, E->value.index, p_value); } } } @@ -1556,7 +1559,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data); //erase dependencies, since no longer a lightmap - for (Set<Instance *>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) { Instance *geom = E->get(); _instance_queue_update(geom, true, false); } @@ -1571,7 +1574,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { //make sure lights are updated if it casts shadow if (geom->can_cast_shadows) { - for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); light->shadow_dirty = true; } @@ -1629,7 +1632,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { idata.parent_array_index = p_instance->visibility_parent ? p_instance->visibility_parent->array_index : -1; idata.visibility_index = p_instance->visibility_index; - for (Set<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) { Instance *dep_instance = E->get(); if (dep_instance->array_index != -1) { dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index; @@ -1797,7 +1800,7 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) { swapped_instance->scenario->instance_visibility[swapped_instance->visibility_index].array_index = swapped_instance->array_index; } - for (Set<Instance *>::Element *E = swapped_instance->visibility_dependencies.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = swapped_instance->visibility_dependencies.front(); E; E = E->next()) { Instance *dep_instance = E->get(); if (dep_instance != p_instance && dep_instance->array_index != -1) { dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index; @@ -1821,7 +1824,7 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) { scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0); } - for (Set<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) { Instance *dep_instance = E->get(); if (dep_instance->array_index != -1) { dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1; @@ -1920,7 +1923,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance) float accum_blend = 0.0; InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); - for (Set<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { Instance *lightmap = E->get(); bool interior = RSG::light_storage->lightmap_is_interior(lightmap->base); @@ -2741,7 +2744,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); uint32_t idx = 0; - for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); instance_pair_buffer[idx++] = light->instance; if (idx == MAX_INSTANCE_PAIRS) { @@ -2764,7 +2767,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); uint32_t idx = 0; - for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data); instance_pair_buffer[idx++] = reflection_probe->instance; @@ -2781,7 +2784,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); uint32_t idx = 0; - for (Set<Instance *>::Element *E = geom->decals.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->decals.front(); E; E = E->next()) { InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->get()->base_data); instance_pair_buffer[idx++] = decal->instance; @@ -2796,7 +2799,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul if (idata.flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); uint32_t idx = 0; - for (Set<Instance *>::Element *E = geom->voxel_gi_instances.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->voxel_gi_instances.front(); E; E = E->next()) { InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(E->get()->base_data); instance_pair_buffer[idx++] = voxel_gi->probe_instance; @@ -3417,7 +3420,7 @@ void RendererSceneCull::render_probes() { const RID *instance_caches = probe->light_instances.ptr(); int idx = 0; //must count visible lights - for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { Instance *instance = E->get(); InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; if (!instance->visible) { @@ -3499,7 +3502,7 @@ void RendererSceneCull::render_probes() { RID *instance_caches = probe->light_instances.ptrw(); int idx = 0; //must count visible lights - for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { Instance *instance = E->get(); InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; if (!instance->visible) { @@ -3554,7 +3557,7 @@ void RendererSceneCull::render_probes() { RID instance_pair_buffer[MAX_INSTANCE_PAIRS]; - for (Set<Instance *>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) { Instance *ins = E->get(); if (!ins->visible) { continue; @@ -3563,7 +3566,7 @@ void RendererSceneCull::render_probes() { if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY)) { uint32_t idx = 0; - for (Set<Instance *>::Element *F = geom->voxel_gi_instances.front(); F; F = F->next()) { + for (RBSet<Instance *>::Element *F = geom->voxel_gi_instances.front(); F; F = F->next()) { InstanceVoxelGIData *voxel_gi2 = static_cast<InstanceVoxelGIData *>(F->get()->base_data); instance_pair_buffer[idx++] = voxel_gi2->probe_instance; @@ -3626,7 +3629,7 @@ void RendererSceneCull::render_particle_colliders() { } } -void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) { +void RendererSceneCull::_update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) { List<RendererMaterialStorage::InstanceShaderParam> plist; RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist); for (const RendererMaterialStorage::InstanceShaderParam &E : plist) { @@ -3697,7 +3700,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { bool can_cast_shadows = true; bool is_animated = false; - Map<StringName, Instance::InstanceShaderParameter> isparams; + HashMap<StringName, Instance::InstanceShaderParameter> isparams; if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) { can_cast_shadows = false; @@ -3820,7 +3823,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { if (can_cast_shadows != geom->can_cast_shadows) { //ability to cast shadows change, let lights now - for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); light->shadow_dirty = true; } diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index b5e8cf702f..c5325ef30a 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -324,7 +324,7 @@ public: RID reflection_probe_shadow_atlas; RID reflection_atlas; uint64_t used_viewport_visibility_bits; - Map<RID, uint64_t> viewport_visibility_masks; + HashMap<RID, uint64_t> viewport_visibility_masks; SelfList<Instance>::List instances; @@ -426,7 +426,7 @@ public: PropertyInfo info; }; - Map<StringName, InstanceShaderParameter> instance_shader_parameters; + HashMap<StringName, InstanceShaderParameter> instance_shader_parameters; bool instance_allocated_shader_parameters = false; int32_t instance_allocated_shader_parameters_offset = -1; @@ -443,7 +443,7 @@ public: float visibility_range_end_margin = 0.0f; RS::VisibilityRangeFadeMode visibility_range_fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED; Instance *visibility_parent = nullptr; - Set<Instance *> visibility_dependencies; + RBSet<Instance *> visibility_dependencies; uint32_t visibility_dependencies_depth = 0; float transparency = 0.0f; Scenario *scenario = nullptr; @@ -579,16 +579,16 @@ public: struct InstanceGeometryData : public InstanceBaseData { RendererSceneRender::GeometryInstance *geometry_instance = nullptr; - Set<Instance *> lights; + RBSet<Instance *> lights; bool can_cast_shadows; bool material_is_animated; uint32_t projector_count = 0; uint32_t softshadow_count = 0; - Set<Instance *> decals; - Set<Instance *> reflection_probes; - Set<Instance *> voxel_gi_instances; - Set<Instance *> lightmap_captures; + RBSet<Instance *> decals; + RBSet<Instance *> reflection_probes; + RBSet<Instance *> voxel_gi_instances; + RBSet<Instance *> lightmap_captures; InstanceGeometryData() { can_cast_shadows = true; @@ -599,7 +599,7 @@ public: struct InstanceReflectionProbeData : public InstanceBaseData { Instance *owner = nullptr; - Set<Instance *> geometries; + RBSet<Instance *> geometries; RID instance; SelfList<InstanceReflectionProbeData> update_list; @@ -616,7 +616,7 @@ public: Instance *owner = nullptr; RID instance; - Set<Instance *> geometries; + RBSet<Instance *> geometries; InstanceDecalData() { } @@ -654,7 +654,7 @@ public: bool uses_projector = false; bool uses_softshadow = false; - Set<Instance *> geometries; + RBSet<Instance *> geometries; Instance *baked_light = nullptr; @@ -673,10 +673,10 @@ public: struct InstanceVoxelGIData : public InstanceBaseData { Instance *owner = nullptr; - Set<Instance *> geometries; - Set<Instance *> dynamic_geometries; + RBSet<Instance *> geometries; + RBSet<Instance *> dynamic_geometries; - Set<Instance *> lights; + RBSet<Instance *> lights; struct LightCache { RS::LightType type; @@ -713,8 +713,8 @@ public: struct InstanceLightmapData : public InstanceBaseData { RID instance; - Set<Instance *> geometries; - Set<Instance *> users; + RBSet<Instance *> geometries; + RBSet<Instance *> users; InstanceLightmapData() { } @@ -779,7 +779,7 @@ public: } }; - Set<Instance *> heightfield_particle_colliders_update_list; + RBSet<Instance *> heightfield_particle_colliders_update_list; PagedArrayPool<Instance *> instance_cull_page_pool; PagedArrayPool<RendererSceneRender::GeometryInstance *> geometry_instance_cull_page_pool; @@ -964,7 +964,7 @@ public: virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index); virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias); - void _update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material); + void _update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material); virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value); virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const; diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index 7cf4fd0aff..7f35d2ca99 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -62,7 +62,7 @@ public: private: friend struct DependencyTracker; - Map<DependencyTracker *, uint32_t> instances; + HashMap<DependencyTracker *, uint32_t> instances; }; struct DependencyTracker { @@ -83,15 +83,16 @@ public: } void update_end() { //call after updating dependencies - List<Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *>> to_clean_up; - for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) { + List<Pair<Dependency *, DependencyTracker *>> to_clean_up; + + for (RBSet<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) { Dependency *dep = E->get(); - Map<DependencyTracker *, uint32_t>::Element *F = dep->instances.find(this); + HashMap<DependencyTracker *, uint32_t>::Iterator F = dep->instances.find(this); ERR_CONTINUE(!F); - if (F->get() != instance_version) { - Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *> p; + if (F->value != instance_version) { + Pair<Dependency *, DependencyTracker *> p; p.first = dep; - p.second = F; + p.second = F->key; to_clean_up.push_back(p); } } @@ -104,7 +105,7 @@ public: } void clear() { // clear all dependencies - for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) { + for (RBSet<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) { Dependency *dep = E->get(); dep->instances.erase(this); } @@ -116,7 +117,7 @@ public: private: friend struct Dependency; uint32_t instance_version = 0; - Set<Dependency *> dependencies; + RBSet<Dependency *> dependencies; }; virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 7e18eac6ae..d612fb4aa7 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -226,9 +226,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { } if (!p_viewport->disable_2d) { - int i = 0; - - Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map; + RBMap<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map; Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y); RendererCanvasRender::Light *lights = nullptr; @@ -238,18 +236,18 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasRender::Light *directional_lights_with_shadow = nullptr; if (p_viewport->sdf_active) { - //process SDF + // Process SDF. Rect2 sdf_rect = RSG::texture_storage->render_target_get_sdf_rect(p_viewport->render_target); RendererCanvasRender::LightOccluderInstance *occluders = nullptr; - //make list of occluders + // Make list of occluders. for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) { RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas); Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size); - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) { continue; } @@ -265,14 +263,13 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RSG::canvas_render->render_sdf(p_viewport->render_target, occluders); RSG::texture_storage->render_target_mark_sdf_enabled(p_viewport->render_target, true); - p_viewport->sdf_active = false; // if used, gets set active again + p_viewport->sdf_active = false; // If used, gets set active again. } else { RSG::texture_storage->render_target_mark_sdf_enabled(p_viewport->render_target, false); } Rect2 shadow_rect; - int light_count = 0; int shadow_count = 0; int directional_light_count = 0; @@ -282,9 +279,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size); - //find lights in canvas + // Find lights in canvas. - for (Set<RendererCanvasRender::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) { + for (RBSet<RendererCanvasRender::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) { RendererCanvasRender::Light *cl = F->get(); if (cl->enabled && cl->texture.is_valid()) { //not super efficient.. @@ -298,12 +295,10 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) { cl->filter_next_ptr = lights; lights = cl; - // cl->texture_cache = nullptr; Transform2D scale; scale.scale(cl->rect_cache.size); scale.columns[2] = cl->rect_cache.position; cl->light_shader_xform = cl->xform * scale; - //cl->light_shader_pos = cl->xform_cache[2]; if (cl->use_shadow) { cl->shadows_next_ptr = lights_with_shadow; if (lights_with_shadow == nullptr) { @@ -314,15 +309,11 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { lights_with_shadow = cl; cl->radius_cache = cl->rect_cache.size.length(); } - - light_count++; } - - //guess this is not needed, but keeping because it may be } } - for (Set<RendererCanvasRender::Light *>::Element *F = canvas->directional_lights.front(); F; F = F->next()) { + for (RBSet<RendererCanvasRender::Light *>::Element *F = canvas->directional_lights.front(); F; F = F->next()) { RendererCanvasRender::Light *cl = F->get(); if (cl->enabled) { cl->filter_next_ptr = directional_lights; @@ -358,7 +349,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas); Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size); - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) { continue; } @@ -433,13 +424,12 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RENDER_TIMESTAMP("> Render DirectionalLight2D Shadows"); - //make list of occluders - int occ_cullded = 0; + // Make list of occluders. for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) { RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas); Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size); - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) { continue; } @@ -452,7 +442,6 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { if (F->get()->aabb_cache.intersects_filled_polygon(xf_points, point_count)) { F->get()->next = occluders; occluders = F->get(); - occ_cullded++; } } } @@ -465,7 +454,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RENDER_TIMESTAMP("< Render DirectionalLight2D Shadows"); } - if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) { + if (scenario_draw_canvas_bg && canvas_map.begin() && canvas_map.begin()->key.get_layer() > scenario_canvas_max_layer) { if (!can_draw_3d) { RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas); } else { @@ -504,7 +493,6 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { if (RSG::canvas->was_sdf_used()) { p_viewport->sdf_active = true; } - i++; if (scenario_draw_canvas_bg && E.key.get_layer() >= scenario_canvas_max_layer) { if (!can_draw_3d) { @@ -559,7 +547,7 @@ void RendererViewport::draw_viewports() { //sort viewports active_viewports.sort_custom<ViewportSort>(); - Map<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list; + HashMap<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list; //draw viewports RENDER_TIMESTAMP("> Render Viewports"); @@ -1188,8 +1176,8 @@ bool RendererViewport::free(RID p_rid) { RSG::scene->free(viewport->render_buffers); } - while (viewport->canvas_map.front()) { - viewport_remove_canvas(p_rid, viewport->canvas_map.front()->key()); + while (viewport->canvas_map.begin()) { + viewport_remove_canvas(p_rid, viewport->canvas_map.begin()->key); } viewport_set_scenario(p_rid, RID()); diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index b6e44e8436..da8cf5396c 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -137,7 +137,7 @@ public: Transform2D global_transform; - Map<RID, CanvasData> canvas_map; + HashMap<RID, CanvasData> canvas_map; RendererScene::RenderInfo render_info; diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp index e50ac42027..d03c4e0427 100644 --- a/servers/rendering/rendering_device_binds.cpp +++ b/servers/rendering/rendering_device_binds.cpp @@ -45,7 +45,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String }; String stage_code[RD::SHADER_STAGE_MAX]; int stages_found = 0; - Map<StringName, String> version_texts; + HashMap<StringName, String> version_texts; versions.clear(); base_error = ""; diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index ee5bf8b891..8bdd3deea1 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -329,7 +329,7 @@ protected: class RDShaderFile : public Resource { GDCLASS(RDShaderFile, Resource) - Map<StringName, Ref<RDShaderSPIRV>> versions; + HashMap<StringName, Ref<RDShaderSPIRV>> versions; String base_error; public: diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 000b253e8a..c4538e0776 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -179,10 +179,10 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { print_line("GPU PROFILE (total " + rtos(total_time) + "ms): "); float print_threshold = 0.01; - for (OrderedHashMap<String, float>::Element E = print_gpu_profile_task_time.front(); E; E = E.next()) { - double time = E.value() / double(print_frame_profile_frame_count); + for (const KeyValue<String, float> &E : print_gpu_profile_task_time) { + double time = E.value / double(print_frame_profile_frame_count); if (time > print_threshold) { - print_line("\t-" + E.key() + ": " + rtos(time) + "ms"); + print_line("\t-" + E.key + ": " + rtos(time) + "ms"); } } print_gpu_profile_task_time.clear(); @@ -321,11 +321,7 @@ void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) { } bool RenderingServerDefault::is_low_end() const { - // FIXME: Commented out when rebasing vulkan branch on master, - // causes a crash, it seems rasterizer is not initialized yet the - // first time it's called. - //return RSG::rasterizer->is_low_end(); - return false; + return RendererCompositor::is_low_end(); } void RenderingServerDefault::_thread_exit() { diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index de4f8d9194..9d4059b9df 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -33,7 +33,7 @@ #include "core/math/octree.h" #include "core/templates/command_queue_mt.h" -#include "core/templates/ordered_hash_map.h" +#include "core/templates/hash_map.h" #include "renderer_canvas_cull.h" #include "renderer_scene_cull.h" #include "renderer_viewport.h" @@ -69,7 +69,7 @@ class RenderingServerDefault : public RenderingServer { //for printing bool print_gpu_profile = false; - OrderedHashMap<String, float> print_gpu_profile_task_time; + HashMap<String, float> print_gpu_profile_task_time; uint64_t print_frame_profile_ticks_from = 0; uint32_t print_frame_profile_frame_count = 0; @@ -113,7 +113,9 @@ public: _changes_changed(); #else - _FORCE_INLINE_ static void redraw_request() { changes++; } + _FORCE_INLINE_ static void redraw_request() { + changes++; + } #endif #define WRITE_ACTION redraw_request(); diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 812d636a0b..c88d9e8222 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -48,8 +48,8 @@ static String _mktab(int p_level) { static String _typestr(SL::DataType p_type) { String type = ShaderLanguage::get_datatype_name(p_type); - if (ShaderLanguage::is_sampler_type(p_type)) { - type = type.replace("sampler", "texture"); //we use textures instead of samplers + if (!RS::get_singleton()->is_low_end() && ShaderLanguage::is_sampler_type(p_type)) { + type = type.replace("sampler", "texture"); //we use textures instead of samplers in Vulkan GLSL } return type; } @@ -289,7 +289,7 @@ String ShaderCompiler::_get_sampler_name(ShaderLanguage::TextureFilter p_filter, return actions.sampler_array_name + "[" + itos(p_filter + (p_repeat == ShaderLanguage::REPEAT_ENABLE ? ShaderLanguage::FILTER_DEFAULT : 0)) + "]"; } -void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added) { +void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const HashMap<StringName, String> &p_func_code, String &r_to_add, RBSet<StringName> &added) { int fidx = -1; for (int i = 0; i < p_node->functions.size(); i++) { @@ -303,7 +303,7 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str Vector<StringName> uses_functions; - for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) { uses_functions.push_back(E->get()); } uses_functions.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced @@ -538,7 +538,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene continue; // Instances are indexed directly, don't need index uniforms. } if (SL::is_sampler_type(uniform.type)) { - ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") uniform "; + // Texture layouts are different for OpenGL GLSL and Vulkan GLSL + if (!RS::get_singleton()->is_low_end()) { + ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") "; + } + ucode += "uniform "; } bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL; @@ -681,9 +685,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } vcode += ";\n"; - - r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode; - r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode; + // GLSL ES 3.0 does not allow layout qualifiers for varyings + if (!RS::get_singleton()->is_low_end()) { + r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") "; + r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") "; + } + r_gen_code.stage_globals[STAGE_VERTEX] += interp_mode + "out " + vcode; + r_gen_code.stage_globals[STAGE_FRAGMENT] += interp_mode + "in " + vcode; index += inc; } @@ -727,7 +735,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } } - Map<StringName, String> function_code; + HashMap<StringName, String> function_code; //code for functions for (int i = 0; i < pnode->functions.size(); i++) { @@ -740,7 +748,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene //place functions in actual code - Set<StringName> added_funcs_per_stage[STAGE_MAX]; + RBSet<StringName> added_funcs_per_stage[STAGE_MAX]; for (int i = 0; i < pnode->functions.size(); i++) { SL::FunctionNode *fnode = pnode->functions[i].function; @@ -1125,8 +1133,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene code += ", "; } String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - if (is_texture_func && i == 1) { - //need to map from texture to sampler in order to sample + if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) { + //need to map from texture to sampler in order to sample when using Vulkan GLSL StringName texture_uniform; bool correct_texture_uniform = false; diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h index 347ecf2988..85b93c4063 100644 --- a/servers/rendering/shader_compiler.h +++ b/servers/rendering/shader_compiler.h @@ -45,14 +45,14 @@ public: }; struct IdentifierActions { - Map<StringName, Stage> entry_point_stages; + HashMap<StringName, Stage> entry_point_stages; - Map<StringName, Pair<int *, int>> render_mode_values; - Map<StringName, bool *> render_mode_flags; - Map<StringName, bool *> usage_flag_pointers; - Map<StringName, bool *> write_flag_pointers; + HashMap<StringName, Pair<int *, int>> render_mode_values; + HashMap<StringName, bool *> render_mode_flags; + HashMap<StringName, bool *> usage_flag_pointers; + HashMap<StringName, bool *> write_flag_pointers; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms; }; struct GeneratedCode { @@ -74,7 +74,7 @@ public: String uniforms; String stage_globals[STAGE_MAX]; - Map<String, String> code; + HashMap<String, String> code; bool uses_global_textures; bool uses_fragment_time; @@ -82,10 +82,10 @@ public: }; struct DefaultIdentifierActions { - Map<StringName, String> renames; - Map<StringName, String> render_mode_defines; - Map<StringName, String> usage_defines; - Map<StringName, String> custom_samplers; + HashMap<StringName, String> renames; + HashMap<StringName, String> render_mode_defines; + HashMap<StringName, String> usage_defines; + HashMap<StringName, String> custom_samplers; ShaderLanguage::TextureFilter default_filter; ShaderLanguage::TextureRepeat default_repeat; String sampler_array_name; @@ -103,20 +103,20 @@ private: String _get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat); - void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added); + void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const HashMap<StringName, String> &p_func_code, String &r_to_add, RBSet<StringName> &added); String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_scope = true); const ShaderLanguage::ShaderNode *shader = nullptr; const ShaderLanguage::FunctionNode *function = nullptr; StringName current_func_name; StringName time_name; - Set<StringName> texture_functions; + RBSet<StringName> texture_functions; - Set<StringName> used_name_defines; - Set<StringName> used_flag_pointers; - Set<StringName> used_rmode_defines; - Set<StringName> internal_functions; - Set<StringName> fragment_varyings; + RBSet<StringName> used_name_defines; + RBSet<StringName> used_flag_pointers; + RBSet<StringName> used_rmode_defines; + RBSet<StringName> internal_functions; + RBSet<StringName> fragment_varyings; DefaultIdentifierActions actions; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 6f70a55948..8a3ab92714 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -4019,7 +4019,7 @@ uint32_t ShaderLanguage::get_datatype_size(ShaderLanguage::DataType p_type) { } void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { - Set<String> kws; + RBSet<String> kws; int idx = 0; @@ -4036,7 +4036,7 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { idx++; } - for (Set<String>::Element *E = kws.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = kws.front(); E; E = E->next()) { r_keywords->push_back(E->get()); } } @@ -4056,7 +4056,7 @@ bool ShaderLanguage::is_control_flow_keyword(String p_keyword) { } void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) { - Set<String> kws; + RBSet<String> kws; int idx = 0; @@ -4066,7 +4066,7 @@ void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) { idx++; } - for (Set<String>::Element *E = kws.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = kws.front(); E; E = E->next()) { r_keywords->push_back(E->get()); } } @@ -4340,8 +4340,8 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam arg->tex_argument_check = true; arg->tex_argument_filter = p_filter; arg->tex_argument_repeat = p_repeat; - for (KeyValue<StringName, Set<int>> &E : arg->tex_argument_connect) { - for (Set<int>::Element *F = E.value.front(); F; F = F->next()) { + for (KeyValue<StringName, RBSet<int>> &E : arg->tex_argument_connect) { + for (RBSet<int>::Element *F = E.value.front(); F; F = F->next()) { if (!_propagate_function_call_sampler_uniform_settings(E.key, F->get(), p_filter, p_repeat)) { return false; } @@ -4374,8 +4374,8 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa arg->tex_builtin_check = true; arg->tex_builtin = p_builtin; - for (KeyValue<StringName, Set<int>> &E : arg->tex_argument_connect) { - for (Set<int>::Element *F = E.value.front(); F; F = F->next()) { + for (KeyValue<StringName, RBSet<int>> &E : arg->tex_argument_connect) { + for (RBSet<int>::Element *F = E.value.front(); F; F = F->next()) { if (!_propagate_function_call_sampler_builtin_reference(E.key, F->get(), p_builtin)) { return false; } @@ -5096,7 +5096,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons for (int j = 0; j < base_function->arguments.size(); j++) { if (base_function->arguments[j].name == varname) { if (!base_function->arguments[j].tex_argument_connect.has(call_function->name)) { - base_function->arguments.write[j].tex_argument_connect[call_function->name] = Set<int>(); + base_function->arguments.write[j].tex_argument_connect[call_function->name] = RBSet<int>(); } base_function->arguments.write[j].tex_argument_connect[call_function->name].insert(i); found = true; @@ -5419,9 +5419,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons StringName member_struct_name = ""; int array_size = 0; - Set<char> position_symbols; - Set<char> color_symbols; - Set<char> texture_symbols; + RBSet<char> position_symbols; + RBSet<char> color_symbols; + RBSet<char> texture_symbols; bool mix_error = false; @@ -6648,7 +6648,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun StringName func_name = parent_function->name; if (!used_local_vars.has(func_name)) { - used_local_vars.insert(func_name, Map<StringName, Usage>()); + used_local_vars.insert(func_name, HashMap<StringName, Usage>()); } used_local_vars[func_name].insert(name, Usage(tk_line)); @@ -7062,7 +7062,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun _set_tkpos(pos); continue; } else { - Set<int> constants; + RBSet<int> constants; for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates. ControlFlowNode *flow = static_cast<ControlFlowNode *>(switch_block->statements[i]); if (flow) { @@ -7565,10 +7565,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return OK; } -String ShaderLanguage::_get_shader_type_list(const Set<String> &p_shader_types) const { +String ShaderLanguage::_get_shader_type_list(const RBSet<String> &p_shader_types) const { // Return a list of shader types as an human-readable string String valid_types; - for (const Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) { + for (const RBSet<String>::Element *E = p_shader_types.front(); E; E = E->next()) { if (!valid_types.is_empty()) { valid_types += ", "; } @@ -7639,7 +7639,7 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) { return OK; } -Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types) { +Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const RBSet<String> &p_shader_types) { Token tk = _get_token(); TkPos prev_pos; Token next; @@ -7699,7 +7699,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct stages = &p_functions; const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo(); - Map<String, String> defined_modes; + HashMap<String, String> defined_modes; while (tk.type != TK_EOF) { switch (tk.type) { @@ -7790,7 +7790,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct st.shader_struct = st_node; int member_count = 0; - Set<String> member_names; + RBSet<String> member_names; while (true) { // variables list #ifdef DEBUG_ENABLED @@ -9234,7 +9234,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return OK; } -bool ShaderLanguage::has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) { +bool ShaderLanguage::has_builtin(const HashMap<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) { for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : p_functions) { if (E.value.built_ins.has(p_name)) { return true; @@ -9376,19 +9376,19 @@ String ShaderLanguage::get_shader_type(const String &p_code) { #ifdef DEBUG_ENABLED void ShaderLanguage::_check_warning_accums() { - for (const KeyValue<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *> &E : warnings_check_map2) { - for (Map<StringName, Map<StringName, Usage>>::Element *T = (*E.value).front(); T; T = T->next()) { - for (const KeyValue<StringName, Usage> &U : T->get()) { + for (const KeyValue<ShaderWarning::Code, HashMap<StringName, HashMap<StringName, Usage>> *> &E : warnings_check_map2) { + for (const KeyValue<StringName, HashMap<StringName, Usage>> &T : *E.value) { + for (const KeyValue<StringName, Usage> &U : T.value) { if (!U.value.used) { _add_warning(E.key, U.value.decl_line, U.key); } } } } - for (const KeyValue<ShaderWarning::Code, Map<StringName, Usage> *> &E : warnings_check_map) { - for (const Map<StringName, Usage>::Element *U = (*E.value).front(); U; U = U->next()) { - if (!U->get().used) { - _add_warning(E.key, U->get().decl_line, U->key()); + for (const KeyValue<ShaderWarning::Code, HashMap<StringName, Usage> *> &E : warnings_check_map) { + for (const KeyValue<StringName, Usage> &U : (*E.value)) { + if (!U.value.used) { + _add_warning(E.key, U.value.decl_line, U.key); } } } @@ -9546,7 +9546,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ case COMPLETION_IDENTIFIER: case COMPLETION_FUNCTION_CALL: { bool comp_ident = completion_type == COMPLETION_IDENTIFIER; - Map<String, ScriptLanguage::CodeCompletionKind> matches; + HashMap<String, ScriptLanguage::CodeCompletionKind> matches; StringName skip_function; BlockNode *block = completion_block; @@ -9793,7 +9793,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } int idx2 = 0; - Set<int> out_args; + RBSet<int> out_args; while (builtin_func_out_args[idx2].name != nullptr) { if (builtin_func_out_args[idx2].name == builtin_func_defs[idx].name) { for (int i = 0; i < BuiltinFuncOutArgs::MAX_ARGS; i++) { diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 80230ed54c..d4a2e0b549 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -35,7 +35,7 @@ #include "core/string/string_name.h" #include "core/string/ustring.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/typedefs.h" #include "core/variant/variant.h" @@ -525,7 +525,7 @@ public: ConstantNode::Value value; }; - Map<StringName, Variable> variables; + HashMap<StringName, Variable> variables; List<Node *> statements; bool single_statement = false; bool use_comma_between_statements = false; @@ -589,7 +589,7 @@ public: bool is_const; int array_size; - Map<StringName, Set<int>> tex_argument_connect; + HashMap<StringName, RBSet<int>> tex_argument_connect; }; StringName name; @@ -622,7 +622,7 @@ public: struct Function { StringName name; FunctionNode *function = nullptr; - Set<StringName> uses_function; + RBSet<StringName> uses_function; bool callable; }; @@ -697,10 +697,10 @@ public: } }; - Map<StringName, Constant> constants; - Map<StringName, Varying> varyings; - Map<StringName, Uniform> uniforms; - Map<StringName, Struct> structs; + HashMap<StringName, Constant> constants; + HashMap<StringName, Varying> varyings; + HashMap<StringName, Uniform> uniforms; + HashMap<StringName, Struct> structs; Vector<StringName> render_modes; Vector<Function> functions; @@ -857,13 +857,13 @@ public: }; struct FunctionInfo { - Map<StringName, BuiltInInfo> built_ins; - Map<StringName, StageFunctionInfo> stage_functions; + HashMap<StringName, BuiltInInfo> built_ins; + HashMap<StringName, StageFunctionInfo> stage_functions; bool can_discard = false; bool main_function = false; }; - static bool has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name); + static bool has_builtin(const HashMap<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name); typedef DataType (*GlobalVariableGetTypeFunc)(const StringName &p_name); @@ -893,15 +893,15 @@ private: } }; - Map<StringName, Usage> used_constants; - Map<StringName, Usage> used_varyings; - Map<StringName, Usage> used_uniforms; - Map<StringName, Usage> used_functions; - Map<StringName, Usage> used_structs; - Map<ShaderWarning::Code, Map<StringName, Usage> *> warnings_check_map; + HashMap<StringName, Usage> used_constants; + HashMap<StringName, Usage> used_varyings; + HashMap<StringName, Usage> used_uniforms; + HashMap<StringName, Usage> used_functions; + HashMap<StringName, Usage> used_structs; + HashMap<ShaderWarning::Code, HashMap<StringName, Usage> *> warnings_check_map; - Map<StringName, Map<StringName, Usage>> used_local_vars; - Map<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *> warnings_check_map2; + HashMap<StringName, HashMap<StringName, Usage>> used_local_vars; + HashMap<ShaderWarning::Code, HashMap<StringName, HashMap<StringName, Usage>> *> warnings_check_map2; List<ShaderWarning> warnings; @@ -1039,7 +1039,7 @@ private: uint32_t keyword_completion_context; #endif // DEBUG_ENABLED - const Map<StringName, FunctionInfo> *stages = nullptr; + const HashMap<StringName, FunctionInfo> *stages = nullptr; bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier); static const BuiltinFuncDef builtin_func_defs[]; @@ -1068,10 +1068,10 @@ private: Node *_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info); Error _parse_block(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); - String _get_shader_type_list(const Set<String> &p_shader_types) const; + String _get_shader_type_list(const RBSet<String> &p_shader_types) const; String _get_qualifier_str(ArgumentQualifier p_qualifier) const; - Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types); + Error _parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const RBSet<String> &p_shader_types); Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op); Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op); @@ -1094,10 +1094,10 @@ public: static String get_shader_type(const String &p_code); struct ShaderCompileInfo { - Map<StringName, FunctionInfo> functions; + HashMap<StringName, FunctionInfo> functions; Vector<ModeInfo> render_modes; VaryingFunctionNames varying_function_names = VaryingFunctionNames(); - Set<String> shader_types; + RBSet<String> shader_types; GlobalVariableGetTypeFunc global_variable_type_func = nullptr; }; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 27a69fbc2e..98c7f0d7aa 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -31,7 +31,7 @@ #include "shader_types.h" #include "core/math/math_defs.h" -const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) const { +const HashMap<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) const { return shader_modes[p_mode].functions; } @@ -39,7 +39,7 @@ const Vector<ShaderLanguage::ModeInfo> &ShaderTypes::get_modes(RS::ShaderMode p_ return shader_modes[p_mode].modes; } -const Set<String> &ShaderTypes::get_types() const { +const RBSet<String> &ShaderTypes::get_types() const { return shader_types; } diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h index 385083b670..e0fee0a822 100644 --- a/servers/rendering/shader_types.h +++ b/servers/rendering/shader_types.h @@ -31,29 +31,29 @@ #ifndef SHADERTYPES_H #define SHADERTYPES_H -#include "core/templates/ordered_hash_map.h" +#include "core/templates/rb_map.h" #include "servers/rendering_server.h" #include "shader_language.h" class ShaderTypes { struct Type { - Map<StringName, ShaderLanguage::FunctionInfo> functions; + HashMap<StringName, ShaderLanguage::FunctionInfo> functions; Vector<ShaderLanguage::ModeInfo> modes; }; - Map<RS::ShaderMode, Type> shader_modes; + HashMap<RS::ShaderMode, Type> shader_modes; static ShaderTypes *singleton; - Set<String> shader_types; + RBSet<String> shader_types; List<String> shader_types_list; public: static ShaderTypes *get_singleton() { return singleton; } - const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const; + const HashMap<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const; const Vector<ShaderLanguage::ModeInfo> &get_modes(RS::ShaderMode p_mode) const; - const Set<String> &get_types() const; + const RBSet<String> &get_types() const; const List<String> &get_types_list() const; ShaderTypes(); diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp index 639b9bd165..855dc23d94 100644 --- a/servers/rendering/shader_warnings.cpp +++ b/servers/rendering/shader_warnings.cpp @@ -109,10 +109,10 @@ ShaderWarning::Code ShaderWarning::get_code_from_name(const String &p_name) { ERR_FAIL_V_MSG(WARNING_MAX, "Invalid shader warning name: " + p_name); } -static Map<int, uint32_t> *code_to_flags_map = nullptr; +static HashMap<int, uint32_t> *code_to_flags_map = nullptr; static void init_code_to_flags_map() { - code_to_flags_map = memnew((Map<int, uint32_t>)); + code_to_flags_map = memnew((HashMap<int, uint32_t>)); code_to_flags_map->insert(ShaderWarning::FLOAT_COMPARISON, ShaderWarning::FLOAT_COMPARISON_FLAG); code_to_flags_map->insert(ShaderWarning::UNUSED_CONSTANT, ShaderWarning::UNUSED_CONSTANT_FLAG); code_to_flags_map->insert(ShaderWarning::UNUSED_FUNCTION, ShaderWarning::UNUSED_FUNCTION_FLAG); @@ -124,7 +124,7 @@ static void init_code_to_flags_map() { code_to_flags_map->insert(ShaderWarning::DEVICE_LIMIT_EXCEEDED, ShaderWarning::DEVICE_LIMIT_EXCEEDED_FLAG); } -ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) { +ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const HashMap<Code, bool> &p_map) { uint32_t result = 0U; if (code_to_flags_map == nullptr) { diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h index e309907181..8edf85842f 100644 --- a/servers/rendering/shader_warnings.h +++ b/servers/rendering/shader_warnings.h @@ -34,8 +34,9 @@ #ifdef DEBUG_ENABLED #include "core/string/string_name.h" +#include "core/templates/hash_map.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/variant/variant.h" class ShaderWarning { @@ -82,7 +83,7 @@ public: static String get_name_from_code(Code p_code); static Code get_code_from_name(const String &p_name); - static CodeFlags get_flags_from_codemap(const Map<Code, bool> &p_map); + static CodeFlags get_flags_from_codemap(const HashMap<Code, bool> &p_map); ShaderWarning(Code p_code = WARNING_MAX, int p_line = -1, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()); }; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 136664e333..766ca88e34 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2885,6 +2885,7 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/shading/overrides/force_lambert_over_burley.mobile", true); GLOBAL_DEF("rendering/driver/depth_prepass/enable", true); + GLOBAL_DEF("rendering/driver/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple"); GLOBAL_DEF_RST("rendering/textures/default_filters/use_nearest_mipmap_filter", false); GLOBAL_DEF_RST("rendering/textures/default_filters/anisotropic_filtering_level", 2); @@ -2933,7 +2934,7 @@ RenderingServer::RenderingServer() { ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/mode", PropertyInfo(Variant::INT, "rendering/scaling_3d/mode", - PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR (Fast)")); + PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR 1.0 (Fast)")); ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/scale", PropertyInfo(Variant::FLOAT, @@ -3002,44 +3003,15 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/limits/cluster_builder/max_clustered_elements", 512); ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/cluster_builder/max_clustered_elements", PropertyInfo(Variant::FLOAT, "rendering/limits/cluster_builder/max_clustered_elements", PROPERTY_HINT_RANGE, "32,8192,1")); - GLOBAL_DEF_RST_BASIC("xr/shaders/enabled", false); + // OpenGL limits + GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_elements", 65536); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_elements", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_elements", PROPERTY_HINT_RANGE, "1024,65536,1")); + GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_lights", 32); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_lights", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_lights", PROPERTY_HINT_RANGE, "2,256,1")); + GLOBAL_DEF_RST("rendering/limits/opengl/max_lights_per_object", 8); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_lights_per_object", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_lights_per_object", PROPERTY_HINT_RANGE, "2,1024,1")); - GLOBAL_DEF_RST("rendering/2d/options/use_software_skinning", true); - GLOBAL_DEF_RST("rendering/2d/options/ninepatch_mode", 1); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/options/ninepatch_mode", PropertyInfo(Variant::INT, "rendering/2d/options/ninepatch_mode", PROPERTY_HINT_ENUM, "Fixed,Scaling")); - - GLOBAL_DEF_RST("rendering/2d/opengl/batching_send_null", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_send_null", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_send_null", PROPERTY_HINT_ENUM, "Default (On),Off,On")); - GLOBAL_DEF_RST("rendering/2d/opengl/batching_stream", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_stream", PROPERTY_HINT_ENUM, "Default (Off),Off,On")); - GLOBAL_DEF_RST("rendering/2d/opengl/legacy_orphan_buffers", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_orphan_buffers", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_orphan_buffers", PROPERTY_HINT_ENUM, "Default (On),Off,On")); - GLOBAL_DEF_RST("rendering/2d/opengl/legacy_stream", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_stream", PROPERTY_HINT_ENUM, "Default (On),Off,On")); - - GLOBAL_DEF("rendering/batching/options/use_batching", false); - GLOBAL_DEF_RST("rendering/batching/options/use_batching_in_editor", false); - GLOBAL_DEF("rendering/batching/options/single_rect_fallback", false); - GLOBAL_DEF("rendering/batching/parameters/max_join_item_commands", 16); - GLOBAL_DEF("rendering/batching/parameters/colored_vertex_format_threshold", 0.25f); - GLOBAL_DEF("rendering/batching/lights/scissor_area_threshold", 1.0f); - GLOBAL_DEF("rendering/batching/lights/max_join_items", 32); - GLOBAL_DEF("rendering/batching/parameters/batch_buffer_size", 16384); - GLOBAL_DEF("rendering/batching/parameters/item_reordering_lookahead", 4); - GLOBAL_DEF("rendering/batching/debug/flash_batching", false); - GLOBAL_DEF("rendering/batching/debug/diagnose_frame", false); - GLOBAL_DEF("rendering/gles2/compatibility/disable_half_float", false); - GLOBAL_DEF("rendering/gles2/compatibility/enable_high_float.Android", false); - GLOBAL_DEF("rendering/batching/precision/uv_contract", false); - GLOBAL_DEF("rendering/batching/precision/uv_contract_amount", 100); - - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/max_join_item_commands", PropertyInfo(Variant::INT, "rendering/batching/parameters/max_join_item_commands", PROPERTY_HINT_RANGE, "0,65535")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/colored_vertex_format_threshold", PropertyInfo(Variant::FLOAT, "rendering/batching/parameters/colored_vertex_format_threshold", PROPERTY_HINT_RANGE, "0.0,1.0,0.01")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/batch_buffer_size", PropertyInfo(Variant::INT, "rendering/batching/parameters/batch_buffer_size", PROPERTY_HINT_RANGE, "1024,65535,1024")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/lights/scissor_area_threshold", PropertyInfo(Variant::FLOAT, "rendering/batching/lights/scissor_area_threshold", PROPERTY_HINT_RANGE, "0.0,1.0")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/lights/max_join_items", PropertyInfo(Variant::INT, "rendering/batching/lights/max_join_items", PROPERTY_HINT_RANGE, "0,512")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/item_reordering_lookahead", PropertyInfo(Variant::INT, "rendering/batching/parameters/item_reordering_lookahead", PROPERTY_HINT_RANGE, "0,256")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/precision/uv_contract_amount", PropertyInfo(Variant::INT, "rendering/batching/precision/uv_contract_amount", PROPERTY_HINT_RANGE, "0,10000")); + GLOBAL_DEF_RST_BASIC("xr/shaders/enabled", false); } RenderingServer::~RenderingServer() { diff --git a/servers/text_server.h b/servers/text_server.h index b08aa26917..f96146a549 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -159,7 +159,7 @@ public: void _draw_hex_code_box_number(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const; protected: - Map<char32_t, char32_t> diacritics_map; + HashMap<char32_t, char32_t> diacritics_map; void _diacritics_map_add(const String &p_from, char32_t p_to); void _init_diacritics_map(); diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h index cd06d4a087..8371dfcbb5 100644 --- a/servers/xr/xr_positional_tracker.h +++ b/servers/xr/xr_positional_tracker.h @@ -60,8 +60,8 @@ private: String profile; // this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker TrackerHand hand; // if known, the hand this tracker is held in - Map<StringName, Ref<XRPose>> poses; - Map<StringName, Variant> inputs; + HashMap<StringName, Ref<XRPose>> poses; + HashMap<StringName, Variant> inputs; protected: static void _bind_methods(); diff --git a/tests/core/math/test_geometry_2d.h b/tests/core/math/test_geometry_2d.h index 3487e4d7e8..db4e6e2177 100644 --- a/tests/core/math/test_geometry_2d.h +++ b/tests/core/math/test_geometry_2d.h @@ -135,7 +135,7 @@ TEST_CASE("[Geometry2D] Line intersection") { "Parallel lines should not intersect."); } -TEST_CASE("[Geometry2D] Segment intersection.") { +TEST_CASE("[Geometry2D] Segment intersection") { Vector2 r; CHECK(Geometry2D::segment_intersects_segment(Vector2(-1, 1), Vector2(1, -1), Vector2(1, 1), Vector2(-1, -1), &r)); @@ -148,6 +148,10 @@ TEST_CASE("[Geometry2D] Segment intersection.") { Geometry2D::segment_intersects_segment(Vector2(-1, 1), Vector2(1, -1), Vector2(0, 1), Vector2(2, -1), &r), "Parallel segments should not intersect."); + CHECK_FALSE_MESSAGE( + Geometry2D::segment_intersects_segment(Vector2(1, 2), Vector2(3, 2), Vector2(0, 2), Vector2(-2, 2), &r), + "Non-overlapping collinear segments should not intersect."); + CHECK_MESSAGE( Geometry2D::segment_intersects_segment(Vector2(0, 0), Vector2(0, 1), Vector2(0, 0), Vector2(1, 0), &r), "Touching segments should intersect."); @@ -159,11 +163,114 @@ TEST_CASE("[Geometry2D] Segment intersection.") { CHECK(r.is_equal_approx(Vector2(0, 0))); } +TEST_CASE("[Geometry2D] Segment intersection with circle") { + real_t minus_one = -1.0; + real_t zero = 0.0; + real_t one_quarter = 0.25; + real_t three_quarters = 0.75; + real_t one = 1.0; + + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(0, 0), Vector2(4, 0), Vector2(0, 0), 1.0), one_quarter), + "Segment from inside to outside of circle should intersect it."); + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(4, 0), Vector2(0, 0), Vector2(0, 0), 1.0), three_quarters), + "Segment from outside to inside of circle should intersect it."); + + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(-2, 0), Vector2(2, 0), Vector2(0, 0), 1.0), one_quarter), + "Segment running through circle should intersect it."); + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(2, 0), Vector2(-2, 0), Vector2(0, 0), 1.0), one_quarter), + "Segment running through circle should intersect it."); + + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(0, 0), Vector2(1, 0), Vector2(0, 0), 1.0), one), + "Segment starting inside the circle and ending on the circle should intersect it"); + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(1, 0), Vector2(0, 0), Vector2(0, 0), 1.0), zero), + "Segment starting on the circle and going inwards should intersect it"); + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(1, 0), Vector2(2, 0), Vector2(0, 0), 1.0), zero), + "Segment starting on the circle and going outwards should intersect it"); + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(2, 0), Vector2(1, 0), Vector2(0, 0), 1.0), one), + "Segment starting outside the circle and ending on the circle intersect it"); + + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(-1, 0), Vector2(1, 0), Vector2(0, 0), 2.0), minus_one), + "Segment completely within the circle should not intersect it"); + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(1, 0), Vector2(-1, 0), Vector2(0, 0), 2.0), minus_one), + "Segment completely within the circle should not intersect it"); + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(2, 0), Vector2(3, 0), Vector2(0, 0), 1.0), minus_one), + "Segment completely outside the circle should not intersect it"); + CHECK_MESSAGE( + Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(3, 0), Vector2(2, 0), Vector2(0, 0), 1.0), minus_one), + "Segment completely outside the circle should not intersect it"); +} + +TEST_CASE("[Geometry2D] Segment intersection with polygon") { + Vector<Point2> a; + + a.push_back(Point2(-2, 2)); + a.push_back(Point2(3, 4)); + a.push_back(Point2(1, 1)); + a.push_back(Point2(2, -2)); + a.push_back(Point2(-1, -1)); + + CHECK_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(0, 2), Vector2(2, 2), a), + "Segment from inside to outside of polygon should intersect it."); + CHECK_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(2, 2), Vector2(0, 2), a), + "Segment from outside to inside of polygon should intersect it."); + + CHECK_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(2, 4), Vector2(3, 3), a), + "Segment running through polygon should intersect it."); + CHECK_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(3, 3), Vector2(2, 4), a), + "Segment running through polygon should intersect it."); + + CHECK_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(0, 0), Vector2(1, 1), a), + "Segment starting inside the polygon and ending on the polygon should intersect it"); + CHECK_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(1, 1), Vector2(0, 0), a), + "Segment starting on the polygon and going inwards should intersect it"); + CHECK_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(-2, 2), Vector2(-2, -1), a), + "Segment starting on the polygon and going outwards should intersect it"); + CHECK_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(-2, 1), Vector2(-2, 2), a), + "Segment starting outside the polygon and ending on the polygon intersect it"); + + CHECK_FALSE_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(-1, 2), Vector2(1, -1), a), + "Segment completely within the polygon should not intersect it"); + CHECK_FALSE_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(1, -1), Vector2(-1, 2), a), + "Segment completely within the polygon should not intersect it"); + CHECK_FALSE_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(2, 2), Vector2(2, -1), a), + "Segment completely outside the polygon should not intersect it"); + CHECK_FALSE_MESSAGE( + Geometry2D::is_segment_intersecting_polygon(Vector2(2, -1), Vector2(2, 2), a), + "Segment completely outside the polygon should not intersect it"); +} + TEST_CASE("[Geometry2D] Closest point to segment") { Vector2 s[] = { Vector2(-4, -4), Vector2(4, 4) }; CHECK(Geometry2D::get_closest_point_to_segment(Vector2(4.1, 4.1), s).is_equal_approx(Vector2(4, 4))); CHECK(Geometry2D::get_closest_point_to_segment(Vector2(-4.1, -4.1), s).is_equal_approx(Vector2(-4, -4))); CHECK(Geometry2D::get_closest_point_to_segment(Vector2(-1, 1), s).is_equal_approx(Vector2(0, 0))); + + Vector2 t[] = { Vector2(1, -2), Vector2(1, -2) }; + CHECK_MESSAGE( + Geometry2D::get_closest_point_to_segment(Vector2(-3, 4), t).is_equal_approx(Vector2(1, -2)), + "Line segment is only a single point. This point should be the closest."); } TEST_CASE("[Geometry2D] Closest point to uncapped segment") { @@ -186,6 +293,30 @@ TEST_CASE("[Geometry2D] Closest points between segments") { Geometry2D::get_closest_points_between_segments(Vector2(-1, 1), Vector2(1, -1), Vector2(1, 1), Vector2(-1, -1), c1, c2); CHECK(c1.is_equal_approx(Vector2(0, 0))); CHECK(c2.is_equal_approx(Vector2(0, 0))); + + Geometry2D::get_closest_points_between_segments(Vector2(-3, 4), Vector2(-3, 4), Vector2(-4, 3), Vector2(-2, 3), c1, c2); + CHECK_MESSAGE( + c1.is_equal_approx(Vector2(-3, 4)), + "1st line segment is only a point, this point should be the closest point to the 2nd line segment."); + CHECK_MESSAGE( + c2.is_equal_approx(Vector2(-3, 3)), + "1st line segment is only a point, this should not matter when determining the closest point on the 2nd line segment."); + + Geometry2D::get_closest_points_between_segments(Vector2(-4, 3), Vector2(-2, 3), Vector2(-3, 4), Vector2(-3, 4), c1, c2); + CHECK_MESSAGE( + c1.is_equal_approx(Vector2(-3, 3)), + "2nd line segment is only a point, this should not matter when determining the closest point on the 1st line segment."); + CHECK_MESSAGE( + c2.is_equal_approx(Vector2(-3, 4)), + "2nd line segment is only a point, this point should be the closest point to the 1st line segment."); + + Geometry2D::get_closest_points_between_segments(Vector2(5, -4), Vector2(5, -4), Vector2(-2, 1), Vector2(-2, 1), c1, c2); + CHECK_MESSAGE( + c1.is_equal_approx(Vector2(5, -4)), + "Both line segments are only a point. On the 1st line segment, that point should be the closest point to the 2nd line segment."); + CHECK_MESSAGE( + c2.is_equal_approx(Vector2(-2, 1)), + "Both line segments are only a point. On the 2nd line segment, that point should be the closest point to the 1st line segment."); } TEST_CASE("[Geometry2D] Make atlas") { @@ -562,6 +693,174 @@ TEST_CASE("[Geometry2D] Clip polyline with polygon") { CHECK(r[1][1].is_equal_approx(Vector2(55, 70))); } } + +TEST_CASE("[Geometry2D] Convex hull") { + Vector<Point2> a; + Vector<Point2> r; + + a.push_back(Point2(-4, -8)); + a.push_back(Point2(-10, -4)); + a.push_back(Point2(8, 2)); + a.push_back(Point2(-6, 10)); + a.push_back(Point2(-12, 4)); + a.push_back(Point2(10, -8)); + a.push_back(Point2(4, 8)); + + SUBCASE("[Geometry2D] No points") { + r = Geometry2D::convex_hull(Vector<Vector2>()); + + CHECK_MESSAGE(r.is_empty(), "The convex hull should be empty if there are no input points."); + } + + SUBCASE("[Geometry2D] Single point") { + Vector<Point2> b; + b.push_back(Point2(4, -3)); + + r = Geometry2D::convex_hull(b); + REQUIRE_MESSAGE(r.size() == 1, "Convex hull should contain 1 point."); + CHECK(r[0].is_equal_approx(b[0])); + } + + SUBCASE("[Geometry2D] All points form the convex hull") { + r = Geometry2D::convex_hull(a); + REQUIRE_MESSAGE(r.size() == 8, "Convex hull should contain 8 points."); + CHECK(r[0].is_equal_approx(Point2(-12, 4))); + CHECK(r[1].is_equal_approx(Point2(-10, -4))); + CHECK(r[2].is_equal_approx(Point2(-4, -8))); + CHECK(r[3].is_equal_approx(Point2(10, -8))); + CHECK(r[4].is_equal_approx(Point2(8, 2))); + CHECK(r[5].is_equal_approx(Point2(4, 8))); + CHECK(r[6].is_equal_approx(Point2(-6, 10))); + CHECK(r[7].is_equal_approx(Point2(-12, 4))); + } + + SUBCASE("[Geometry2D] Add extra points inside original convex hull") { + a.push_back(Point2(-4, -8)); + a.push_back(Point2(0, 0)); + a.push_back(Point2(0, 8)); + a.push_back(Point2(-10, -3)); + a.push_back(Point2(9, -4)); + a.push_back(Point2(6, 4)); + + r = Geometry2D::convex_hull(a); + REQUIRE_MESSAGE(r.size() == 8, "Convex hull should contain 8 points."); + CHECK(r[0].is_equal_approx(Point2(-12, 4))); + CHECK(r[1].is_equal_approx(Point2(-10, -4))); + CHECK(r[2].is_equal_approx(Point2(-4, -8))); + CHECK(r[3].is_equal_approx(Point2(10, -8))); + CHECK(r[4].is_equal_approx(Point2(8, 2))); + CHECK(r[5].is_equal_approx(Point2(4, 8))); + CHECK(r[6].is_equal_approx(Point2(-6, 10))); + CHECK(r[7].is_equal_approx(Point2(-12, 4))); + } + + SUBCASE("[Geometry2D] Add extra points on border of original convex hull") { + a.push_back(Point2(9, -3)); + a.push_back(Point2(-2, -8)); + + r = Geometry2D::convex_hull(a); + REQUIRE_MESSAGE(r.size() == 8, "Convex hull should contain 8 points."); + CHECK(r[0].is_equal_approx(Point2(-12, 4))); + CHECK(r[1].is_equal_approx(Point2(-10, -4))); + CHECK(r[2].is_equal_approx(Point2(-4, -8))); + CHECK(r[3].is_equal_approx(Point2(10, -8))); + CHECK(r[4].is_equal_approx(Point2(8, 2))); + CHECK(r[5].is_equal_approx(Point2(4, 8))); + CHECK(r[6].is_equal_approx(Point2(-6, 10))); + CHECK(r[7].is_equal_approx(Point2(-12, 4))); + } + + SUBCASE("[Geometry2D] Add extra points outside border of original convex hull") { + a.push_back(Point2(-11, -1)); + a.push_back(Point2(7, 6)); + + r = Geometry2D::convex_hull(a); + REQUIRE_MESSAGE(r.size() == 10, "Convex hull should contain 10 points."); + CHECK(r[0].is_equal_approx(Point2(-12, 4))); + CHECK(r[1].is_equal_approx(Point2(-11, -1))); + CHECK(r[2].is_equal_approx(Point2(-10, -4))); + CHECK(r[3].is_equal_approx(Point2(-4, -8))); + CHECK(r[4].is_equal_approx(Point2(10, -8))); + CHECK(r[5].is_equal_approx(Point2(8, 2))); + CHECK(r[6].is_equal_approx(Point2(7, 6))); + CHECK(r[7].is_equal_approx(Point2(4, 8))); + CHECK(r[8].is_equal_approx(Point2(-6, 10))); + CHECK(r[9].is_equal_approx(Point2(-12, 4))); + } +} + +TEST_CASE("[Geometry2D] Bresenham line") { + Vector<Vector2i> r; + + SUBCASE("[Geometry2D] Single point") { + r = Geometry2D::bresenham_line(Point2i(0, 0), Point2i(0, 0)); + + REQUIRE_MESSAGE(r.size() == 1, "The Bresenham line should contain exactly one point."); + CHECK(r[0] == Vector2i(0, 0)); + } + + SUBCASE("[Geometry2D] Line parallel to x-axis") { + r = Geometry2D::bresenham_line(Point2i(1, 2), Point2i(5, 2)); + + REQUIRE_MESSAGE(r.size() == 5, "The Bresenham line should contain exactly five points."); + CHECK(r[0] == Vector2i(1, 2)); + CHECK(r[1] == Vector2i(2, 2)); + CHECK(r[2] == Vector2i(3, 2)); + CHECK(r[3] == Vector2i(4, 2)); + CHECK(r[4] == Vector2i(5, 2)); + } + + SUBCASE("[Geometry2D] 45 degree line from the origin") { + r = Geometry2D::bresenham_line(Point2i(0, 0), Point2i(4, 4)); + + REQUIRE_MESSAGE(r.size() == 5, "The Bresenham line should contain exactly five points."); + CHECK(r[0] == Vector2i(0, 0)); + CHECK(r[1] == Vector2i(1, 1)); + CHECK(r[2] == Vector2i(2, 2)); + CHECK(r[3] == Vector2i(3, 3)); + CHECK(r[4] == Vector2i(4, 4)); + } + + SUBCASE("[Geometry2D] Sloped line going up one unit") { + r = Geometry2D::bresenham_line(Point2i(0, 0), Point2i(4, 1)); + + REQUIRE_MESSAGE(r.size() == 5, "The Bresenham line should contain exactly five points."); + CHECK(r[0] == Vector2i(0, 0)); + CHECK(r[1] == Vector2i(1, 0)); + CHECK(r[2] == Vector2i(2, 0)); + CHECK(r[3] == Vector2i(3, 1)); + CHECK(r[4] == Vector2i(4, 1)); + } + + SUBCASE("[Geometry2D] Sloped line going up two units") { + r = Geometry2D::bresenham_line(Point2i(0, 0), Point2i(4, 2)); + + REQUIRE_MESSAGE(r.size() == 5, "The Bresenham line should contain exactly five points."); + CHECK(r[0] == Vector2i(0, 0)); + CHECK(r[1] == Vector2i(1, 0)); + CHECK(r[2] == Vector2i(2, 1)); + CHECK(r[3] == Vector2i(3, 1)); + CHECK(r[4] == Vector2i(4, 2)); + } + + SUBCASE("[Geometry2D] Long sloped line") { + r = Geometry2D::bresenham_line(Point2i(0, 0), Point2i(11, 5)); + + REQUIRE_MESSAGE(r.size() == 12, "The Bresenham line should contain exactly twelve points."); + CHECK(r[0] == Vector2i(0, 0)); + CHECK(r[1] == Vector2i(1, 0)); + CHECK(r[2] == Vector2i(2, 1)); + CHECK(r[3] == Vector2i(3, 1)); + CHECK(r[4] == Vector2i(4, 2)); + CHECK(r[5] == Vector2i(5, 2)); + CHECK(r[6] == Vector2i(6, 3)); + CHECK(r[7] == Vector2i(7, 3)); + CHECK(r[8] == Vector2i(8, 4)); + CHECK(r[9] == Vector2i(9, 4)); + CHECK(r[10] == Vector2i(10, 5)); + CHECK(r[11] == Vector2i(11, 5)); + } +} } // namespace TestGeometry2D #endif // TEST_GEOMETRY_2D_H diff --git a/tests/core/object/test_class_db.h b/tests/core/object/test_class_db.h index 5cf5403a50..8aaca69d13 100644 --- a/tests/core/object/test_class_db.h +++ b/tests/core/object/test_class_db.h @@ -173,7 +173,7 @@ struct NamesCache { } }; -typedef OrderedHashMap<StringName, ExposedClass> ExposedClasses; +typedef HashMap<StringName, ExposedClass> ExposedClasses; struct Context { Vector<StringName> enum_types; @@ -183,13 +183,13 @@ struct Context { NamesCache names_cache; const ExposedClass *find_exposed_class(const StringName &p_name) const { - ExposedClasses::ConstElement elem = exposed_classes.find(p_name); - return elem ? &elem.value() : nullptr; + ExposedClasses::ConstIterator elem = exposed_classes.find(p_name); + return elem ? &elem->value : nullptr; } const ExposedClass *find_exposed_class(const TypeReference &p_type_ref) const { - ExposedClasses::ConstElement elem = exposed_classes.find(p_type_ref.name); - return elem ? &elem.value() : nullptr; + ExposedClasses::ConstIterator elem = exposed_classes.find(p_type_ref.name); + return elem ? &elem->value : nullptr; } bool has_type(const TypeReference &p_type_ref) const { @@ -519,7 +519,7 @@ void add_exposed_classes(Context &r_context) { List<PropertyInfo> property_list; ClassDB::get_property_list(class_name, &property_list, true); - Map<StringName, StringName> accessor_methods; + HashMap<StringName, StringName> accessor_methods; for (const PropertyInfo &property : property_list) { if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY || (property.type == Variant::NIL && property.usage & PROPERTY_USAGE_ARRAY)) { @@ -676,12 +676,11 @@ void add_exposed_classes(Context &r_context) { // Add signals const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map; - const StringName *k = nullptr; - while ((k = signal_map.next(k))) { + for (const KeyValue<StringName, MethodInfo> &K : signal_map) { SignalData signal; - const MethodInfo &method_info = signal_map.get(*k); + const MethodInfo &method_info = signal_map.get(K.key); signal.name = method_info.name; @@ -734,14 +733,12 @@ void add_exposed_classes(Context &r_context) { ClassDB::get_integer_constant_list(class_name, &constants, true); const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map; - k = nullptr; - while ((k = enum_map.next(k))) { + for (const KeyValue<StringName, List<StringName>> &K : enum_map) { EnumData enum_; - enum_.name = *k; + enum_.name = K.key; - const List<StringName> &enum_constants = enum_map.get(*k); - for (const StringName &E : enum_constants) { + for (const StringName &E : K.value) { const StringName &constant_name = E; TEST_FAIL_COND(String(constant_name).find("::") != -1, "Enum constant contains '::', check bindings to remove the scope: '", @@ -760,7 +757,7 @@ void add_exposed_classes(Context &r_context) { exposed_class.enums.push_back(enum_); - r_context.enum_types.push_back(String(class_name) + "." + String(*k)); + r_context.enum_types.push_back(String(class_name) + "." + String(K.key)); } for (const String &E : constants) { @@ -850,8 +847,8 @@ TEST_SUITE("[ClassDB]") { TEST_FAIL_COND(object_class->base != StringName(), "Object class derives from another class: '", object_class->base, "'."); - for (ExposedClasses::Element E = context.exposed_classes.front(); E; E = E.next()) { - validate_class(context, E.value()); + for (const KeyValue<StringName, ExposedClass> &E : context.exposed_classes) { + validate_class(context, E.value); } } } diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h index 58372a0ed6..0b191d2d94 100644 --- a/tests/core/string/test_string.h +++ b/tests/core/string/test_string.h @@ -1447,6 +1447,20 @@ TEST_CASE("[String] validate_node_name") { CHECK(name_with_invalid_chars.validate_node_name() == "Name with invalid characters removed!"); } +TEST_CASE("[String] validate_identifier") { + String empty_string; + CHECK(empty_string.validate_identifier() == "_"); + + String numeric_only = "12345"; + CHECK(numeric_only.validate_identifier() == "_2345"); + + String name_with_spaces = "Name with spaces"; + CHECK(name_with_spaces.validate_identifier() == "Name_with_spaces"); + + String name_with_invalid_chars = String::utf8("Invalid characters:@*#&世界"); + CHECK(name_with_invalid_chars.validate_identifier() == "Invalid_characters_______"); +} + TEST_CASE("[String] Variant indexed get") { Variant s = String("abcd"); bool valid = false; diff --git a/tests/core/string/test_translation.h b/tests/core/string/test_translation.h index 85ac639bec..0a1903ccbf 100644 --- a/tests/core/string/test_translation.h +++ b/tests/core/string/test_translation.h @@ -154,7 +154,7 @@ TEST_CASE("[OptimizedTranslation] Generate from Translation and read messages") TEST_CASE("[Translation] CSV import") { Ref<ResourceImporterCSVTranslation> import_csv_translation = memnew(ResourceImporterCSVTranslation); - Map<StringName, Variant> options; + HashMap<StringName, Variant> options; options["compress"] = false; options["delimiter"] = 0; diff --git a/tests/core/templates/test_ordered_hash_map.h b/tests/core/templates/test_hash_map.h index 08c5c9b72a..7a3d5f5d47 100644 --- a/tests/core/templates/test_ordered_hash_map.h +++ b/tests/core/templates/test_hash_map.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* test_ordered_hash_map.h */ +/* test_hash_map.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,56 +28,53 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef TEST_ORDERED_HASH_MAP_H -#define TEST_ORDERED_HASH_MAP_H +#ifndef TEST_HASH_MAP_H +#define TEST_HASH_MAP_H -#include "core/templates/ordered_hash_map.h" +#include "core/templates/hash_map.h" #include "tests/test_macros.h" -namespace TestOrderedHashMap { +namespace TestHashMap { -TEST_CASE("[OrderedHashMap] Insert element") { - OrderedHashMap<int, int> map; - OrderedHashMap<int, int>::Element e = map.insert(42, 84); +TEST_CASE("[HashMap] Insert element") { + HashMap<int, int> map; + HashMap<int, int>::Iterator e = map.insert(42, 84); CHECK(e); - CHECK(e.key() == 42); - CHECK(e.get() == 84); - CHECK(e.value() == 84); + CHECK(e->key == 42); + CHECK(e->value == 84); CHECK(map[42] == 84); CHECK(map.has(42)); CHECK(map.find(42)); } -TEST_CASE("[OrderedHashMap] Overwrite element") { - OrderedHashMap<int, int> map; +TEST_CASE("[HashMap] Overwrite element") { + HashMap<int, int> map; map.insert(42, 84); map.insert(42, 1234); CHECK(map[42] == 1234); } -TEST_CASE("[OrderedHashMap] Erase via element") { - OrderedHashMap<int, int> map; - OrderedHashMap<int, int>::Element e = map.insert(42, 84); - - map.erase(e); - CHECK(!e); +TEST_CASE("[HashMap] Erase via element") { + HashMap<int, int> map; + HashMap<int, int>::Iterator e = map.insert(42, 84); + map.remove(e); CHECK(!map.has(42)); CHECK(!map.find(42)); } -TEST_CASE("[OrderedHashMap] Erase via key") { - OrderedHashMap<int, int> map; +TEST_CASE("[HashMap] Erase via key") { + HashMap<int, int> map; map.insert(42, 84); map.erase(42); CHECK(!map.has(42)); CHECK(!map.find(42)); } -TEST_CASE("[OrderedHashMap] Size") { - OrderedHashMap<int, int> map; +TEST_CASE("[HashMap] Size") { + HashMap<int, int> map; map.insert(42, 84); map.insert(123, 84); map.insert(123, 84); @@ -87,8 +84,8 @@ TEST_CASE("[OrderedHashMap] Size") { CHECK(map.size() == 4); } -TEST_CASE("[OrderedHashMap] Iteration") { - OrderedHashMap<int, int> map; +TEST_CASE("[HashMap] Iteration") { + HashMap<int, int> map; map.insert(42, 84); map.insert(123, 12385); map.insert(0, 12934); @@ -102,34 +99,35 @@ TEST_CASE("[OrderedHashMap] Iteration") { expected.push_back(Pair<int, int>(123485, 1238888)); int idx = 0; - for (OrderedHashMap<int, int>::Element E = map.front(); E; E = E.next()) { - CHECK(expected[idx] == Pair<int, int>(E.key(), E.value())); + for (const KeyValue<int, int> &E : map) { + CHECK(expected[idx] == Pair<int, int>(E.key, E.value)); ++idx; } } -TEST_CASE("[OrderedHashMap] Const iteration") { - OrderedHashMap<int, int> map; +TEST_CASE("[HashMap] Const iteration") { + HashMap<int, int> map; map.insert(42, 84); map.insert(123, 12385); map.insert(0, 12934); map.insert(123485, 1238888); map.insert(123, 111111); - const OrderedHashMap<int, int> const_map = map; + const HashMap<int, int> const_map = map; Vector<Pair<int, int>> expected; expected.push_back(Pair<int, int>(42, 84)); expected.push_back(Pair<int, int>(123, 111111)); expected.push_back(Pair<int, int>(0, 12934)); expected.push_back(Pair<int, int>(123485, 1238888)); + expected.push_back(Pair<int, int>(123, 111111)); int idx = 0; - for (OrderedHashMap<int, int>::ConstElement E = const_map.front(); E; E = E.next()) { - CHECK(expected[idx] == Pair<int, int>(E.key(), E.value())); + for (const KeyValue<int, int> &E : const_map) { + CHECK(expected[idx] == Pair<int, int>(E.key, E.value)); ++idx; } } -} // namespace TestOrderedHashMap +} // namespace TestHashMap -#endif // TEST_ORDERED_HASH_MAP_H +#endif // TEST_HASH_MAP_H diff --git a/tests/scene/test_text_edit.h b/tests/scene/test_text_edit.h index 249b645fae..a9a1a5fa71 100644 --- a/tests/scene/test_text_edit.h +++ b/tests/scene/test_text_edit.h @@ -42,8 +42,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { SceneTree::get_singleton()->get_root()->add_child(text_edit); text_edit->grab_focus(); - Array empty_singal_args; - empty_singal_args.push_back(Array()); + Array empty_signal_args; + empty_signal_args.push_back(Array()); SUBCASE("[TextEdit] text entry") { SIGNAL_WATCH(text_edit, "text_set"); @@ -65,7 +65,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == ""); CHECK(text_edit->get_caret_column() == 0); CHECK(text_edit->get_line_count() == 1); - SIGNAL_CHECK("text_set", empty_singal_args); + SIGNAL_CHECK("text_set", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); SIGNAL_CHECK_FALSE("caret_changed"); SIGNAL_CHECK_FALSE("text_changed"); @@ -75,16 +75,16 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "test text"); CHECK(text_edit->get_caret_column() == 0); CHECK(text_edit->get_line_count() == 1); - SIGNAL_CHECK("text_set", empty_singal_args); + SIGNAL_CHECK("text_set", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); text_edit->clear(); MessageQueue::get_singleton()->flush(); CHECK(text_edit->get_text() == ""); CHECK(text_edit->get_caret_column() == 0); - SIGNAL_CHECK("text_set", empty_singal_args); + SIGNAL_CHECK("text_set", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); SIGNAL_CHECK_FALSE("caret_changed"); SIGNAL_CHECK_FALSE("text_changed"); @@ -95,8 +95,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "test text"); CHECK(text_edit->get_caret_column() == 9); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); text_edit->redo(); @@ -104,8 +104,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == ""); CHECK(text_edit->get_caret_column() == 0); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); // Cannot undo when not-editable but should still clear. @@ -114,8 +114,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "test text"); CHECK(text_edit->get_caret_column() == 9); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); // Clear. @@ -130,8 +130,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { MessageQueue::get_singleton()->flush(); CHECK(text_edit->get_text() == ""); CHECK(text_edit->get_caret_column() == 0); - SIGNAL_CHECK("text_set", empty_singal_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("text_set", empty_signal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_clear_args); SIGNAL_CHECK_FALSE("text_changed"); @@ -153,9 +153,9 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { MessageQueue::get_singleton()->flush(); CHECK(text_edit->get_text() == "test text"); CHECK(text_edit->get_caret_column() == 0); - SIGNAL_CHECK("text_set", empty_singal_args); + SIGNAL_CHECK("text_set", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); text_edit->set_editable(true); @@ -165,7 +165,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == ""); CHECK(text_edit->get_caret_column() == 0); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("caret_changed"); SIGNAL_CHECK_FALSE("text_set"); @@ -173,14 +173,14 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { text_edit->set_text("test text"); MessageQueue::get_singleton()->flush(); text_edit->select_all(); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); MessageQueue::get_singleton()->flush(); CHECK(text_edit->get_text() == "test text"); CHECK(text_edit->get_caret_column() == 9); CHECK(text_edit->has_selection()); - SIGNAL_CHECK("text_set", empty_singal_args); + SIGNAL_CHECK("text_set", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); text_edit->set_text("test"); @@ -188,14 +188,14 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "test"); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("text_set", empty_singal_args); + SIGNAL_CHECK("text_set", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); text_edit->select_all(); MessageQueue::get_singleton()->flush(); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); CHECK(text_edit->has_selection()); text_edit->clear(); @@ -203,9 +203,9 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == ""); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("text_set", empty_singal_args); + SIGNAL_CHECK("text_set", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); } @@ -225,7 +225,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_line(0) == "test"); CHECK(text_edit->get_line(1) == ""); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); SIGNAL_CHECK_FALSE("caret_changed"); @@ -233,7 +233,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { text_edit->select_all(); MessageQueue::get_singleton()->flush(); CHECK(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); text_edit->set_line(0, "test text"); MessageQueue::get_singleton()->flush(); @@ -241,7 +241,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->has_selection()); CHECK(text_edit->get_selected_text() == "test"); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("caret_changed"); SIGNAL_CHECK_FALSE("text_set"); @@ -253,8 +253,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->has_selection()); CHECK(text_edit->get_selected_text() == "te"); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); text_edit->set_editable(true); @@ -264,8 +264,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_line(0) == "test text"); CHECK(text_edit->has_selection()); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); text_edit->redo(); @@ -273,8 +273,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_line(0) == "te"); CHECK_FALSE(text_edit->has_selection()); // Currently not handled. SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); // Out of range. @@ -304,14 +304,14 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { text_edit->set_text("testing\nswap"); MessageQueue::get_singleton()->flush(); CHECK(text_edit->get_text() == "testing\nswap"); - SIGNAL_CHECK("text_set", empty_singal_args); + SIGNAL_CHECK("text_set", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); text_edit->set_caret_column(text_edit->get_line(0).length()); MessageQueue::get_singleton()->flush(); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); ((Array)lines_edited_args[1])[1] = 0; Array swap_args; @@ -326,8 +326,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { MessageQueue::get_singleton()->flush(); CHECK(text_edit->get_text() == "swap\ntesting"); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); text_edit->set_editable(true); @@ -338,8 +338,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { MessageQueue::get_singleton()->flush(); CHECK(text_edit->get_text() == "testing\nswap"); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); lines_edited_args.reverse(); @@ -348,8 +348,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { MessageQueue::get_singleton()->flush(); CHECK(text_edit->get_text() == "swap\ntesting"); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); // Out of range. @@ -390,9 +390,9 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { text_edit->set_text("testing\nswap"); MessageQueue::get_singleton()->flush(); CHECK(text_edit->get_text() == "testing\nswap"); - SIGNAL_CHECK("text_set", empty_singal_args); + SIGNAL_CHECK("text_set", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); text_edit->select_all(); @@ -400,7 +400,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->has_selection()); CHECK(text_edit->get_selection_from_line() == 0); CHECK(text_edit->get_selection_to_line() == 1); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); // insert before should move caret and selecion, and works when not editable. text_edit->set_editable(false); @@ -414,8 +414,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_selection_from_line() == 1); CHECK(text_edit->get_selection_to_line() == 2); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); text_edit->set_editable(true); @@ -427,8 +427,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "testing\nswap"); CHECK_FALSE(text_edit->has_selection()); // Not currently handled. SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); ((Array)lines_edited_args[0])[0] = 0; @@ -438,8 +438,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "new\ntesting\nswap"); CHECK_FALSE(text_edit->has_selection()); // Not currently handled. SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); // Adding inside selection extends selection. @@ -448,7 +448,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->has_selection()); CHECK(text_edit->get_selection_from_line() == 0); CHECK(text_edit->get_selection_to_line() == 2); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); ((Array)lines_edited_args[0])[0] = 2; ((Array)lines_edited_args[0])[1] = 3; @@ -461,8 +461,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_selection_from_line() == 0); CHECK(text_edit->get_selection_to_line() == 3); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); // Out of range. @@ -493,8 +493,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == text_edit->get_line(1).size() - 1); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("text_changed", empty_singal_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); text_edit->set_caret_line(0, false); @@ -508,8 +508,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 5); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("text_changed", empty_singal_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); text_edit->select(0, 0, 0, text_edit->get_line(0).length()); @@ -524,8 +524,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == text_edit->get_line(0).size() - 1); CHECK_FALSE(text_edit->has_selection()); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("text_changed", empty_singal_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); text_edit->set_editable(true); @@ -536,8 +536,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 10); CHECK(text_edit->has_selection()); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("text_changed", empty_singal_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); text_edit->redo(); @@ -547,8 +547,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 8); CHECK_FALSE(text_edit->has_selection()); SIGNAL_CHECK("lines_edited_from", lines_edited_args); - SIGNAL_CHECK("text_changed", empty_singal_args); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_set"); } @@ -615,7 +615,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_selection_mode() == TextEdit::SelectionMode::SELECTION_MODE_SHIFT); CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 9); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); text_edit->set_caret_line(0); text_edit->set_caret_column(0); @@ -660,7 +660,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_selection_to_column() == 4); CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 4); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); text_edit->set_selecting_enabled(false); text_edit->select_word_under_caret(); @@ -817,7 +817,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_selection_to_column() == 3); CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 3); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SEND_GUI_MOUSE_MOTION_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButton::MASK_LEFT, Key::NONE); CHECK(text_edit->has_selection()); @@ -829,7 +829,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_selection_to_column() == 13); CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 13); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); Point2i line_0 = text_edit->get_pos_at_line_column(0, 0); line_0.y /= 2; @@ -1098,8 +1098,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "this is\nsome"); CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 4); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); ((Array)lines_edited_args[0])[0] = 1; @@ -1109,8 +1109,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "this is\nsom"); CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 3); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->end_complex_operation(); @@ -1121,8 +1121,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "this is\n"); CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_editable(false); @@ -1142,8 +1142,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "this is\nsom"); CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 3); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); } @@ -1167,8 +1167,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "some\n"); CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 4); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); ((Array)lines_edited_args[0])[0] = 0; @@ -1178,8 +1178,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "this is\nsome\n"); CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); ((Array)lines_edited_args[0])[0] = 1; @@ -1190,7 +1190,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); SIGNAL_CHECK_FALSE("caret_changed"); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_text("this is\nsome\n"); @@ -1211,8 +1211,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_text() == "this \nsome\n"); CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 5); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_editable(false); @@ -1276,8 +1276,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_caret_line(1); @@ -1304,8 +1304,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); } @@ -1327,8 +1327,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_editable(false); @@ -1363,8 +1363,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_editable(false); @@ -1405,8 +1405,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); ((Array)lines_edited_args[0])[1] = 0; @@ -1418,8 +1418,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_caret_column(text_edit->get_line(0).length()); @@ -1450,8 +1450,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); InputMap::get_singleton()->action_erase_event("ui_text_backspace_all_to_left", tmpevent); @@ -1479,8 +1479,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->end_complex_operation(); @@ -1493,8 +1493,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_editable(false); @@ -1525,8 +1525,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 14); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); } @@ -1552,8 +1552,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); ((Array)lines_edited_args[0])[1] = 0; @@ -1565,8 +1565,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_caret_column(text_edit->get_line(0).length()); @@ -1597,8 +1597,29 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 18); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); + SIGNAL_CHECK("lines_edited_from", lines_edited_args); + + // Select the entire text, from right to left + text_edit->select(0, 18, 0, 0); + text_edit->set_caret_line(0); + text_edit->set_caret_column(0); + MessageQueue::get_singleton()->flush(); + + SIGNAL_DISCARD("text_set"); + SIGNAL_DISCARD("text_changed"); + SIGNAL_DISCARD("lines_edited_from"); + SIGNAL_DISCARD("caret_changed"); + + ((Array)lines_edited_args[0])[0] = 0; + + SEND_GUI_ACTION(text_edit, "ui_text_backspace"); + CHECK(text_edit->get_text() == ""); + CHECK(text_edit->get_caret_line() == 0); + CHECK(text_edit->get_caret_column() == 0); + SIGNAL_CHECK_FALSE("caret_changed"); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); } @@ -1624,8 +1645,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); // End of line should not do anything. @@ -1674,7 +1695,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); SIGNAL_CHECK_FALSE("caret_changed"); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); InputMap::get_singleton()->action_erase_event("ui_text_delete_all_to_right", tmpevent); @@ -1702,8 +1723,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); // With selection should be a normal delete. @@ -1723,7 +1744,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == text_edit->get_line(0).length()); CHECK_FALSE(text_edit->has_selection()); SIGNAL_CHECK_FALSE("caret_changed"); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); ((Array)lines_edited_args[0])[0] = 0; @@ -1754,7 +1775,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); SIGNAL_CHECK_FALSE("caret_changed"); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); } @@ -1780,8 +1801,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); // With selection should be a normal delete. @@ -1801,7 +1822,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == text_edit->get_line(0).length()); CHECK_FALSE(text_edit->has_selection()); SIGNAL_CHECK_FALSE("caret_changed"); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); ((Array)lines_edited_args[0])[0] = 0; @@ -1832,7 +1853,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); SIGNAL_CHECK_FALSE("caret_changed"); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); SEND_GUI_ACTION(text_edit, "ui_text_delete"); @@ -1842,7 +1863,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); SIGNAL_CHECK_FALSE("caret_changed"); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_caret_mid_grapheme_enabled(false); @@ -1866,7 +1887,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); SIGNAL_CHECK_FALSE("caret_changed"); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); } @@ -1892,7 +1913,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 5); CHECK(text_edit->get_selected_text() == "is"); CHECK(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -1902,7 +1923,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -1912,7 +1933,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); } @@ -1935,7 +1956,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 2); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -1946,7 +1967,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 1); CHECK(text_edit->get_selected_text() == "h"); CHECK(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -1966,7 +1987,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -1976,7 +1997,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); } @@ -2003,7 +2024,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 17); CHECK(text_edit->get_selected_text() == "test"); CHECK(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2013,7 +2034,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 22); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2023,7 +2044,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); } @@ -2046,7 +2067,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 20); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2057,7 +2078,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 21); CHECK(text_edit->get_selected_text() == "x"); CHECK(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2077,7 +2098,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 22); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2087,7 +2108,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); } @@ -2114,7 +2135,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 5); CHECK(text_edit->get_selected_text() == "\ngo here"); CHECK(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2124,7 +2145,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 1); CHECK(text_edit->get_caret_column() == 8); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2134,7 +2155,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 12); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); text_edit->set_caret_column(12, false); @@ -2145,7 +2166,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 7); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); } @@ -2172,7 +2193,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 5); CHECK(text_edit->get_selected_text() == "\nlines"); CHECK(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2182,7 +2203,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 2); CHECK(text_edit->get_caret_column() == 8); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2192,7 +2213,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 3); CHECK(text_edit->get_caret_column() == 7); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); text_edit->set_caret_column(7, false); @@ -2203,7 +2224,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 3); CHECK(text_edit->get_caret_column() == 12); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); } @@ -2234,7 +2255,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 0); CHECK(text_edit->get_selected_text() == "this is some\nother test\nlines\ngo here"); CHECK(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2275,7 +2296,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 12); CHECK(text_edit->get_selected_text() == "go here\nlines\nother test\nthis is some"); CHECK(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2315,7 +2336,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 10); CHECK(text_edit->has_selection()); CHECK(text_edit->get_selected_text() == "some"); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2324,7 +2345,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 2); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2333,7 +2354,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 0); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2342,7 +2363,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == 2); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); } @@ -2372,7 +2393,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_column() == 9); CHECK(text_edit->has_selection()); CHECK(text_edit->get_selected_text() == " this is"); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); @@ -2381,7 +2402,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_caret_line() == 0); CHECK(text_edit->get_caret_column() == text_edit->get_line(0).length()); CHECK_FALSE(text_edit->has_selection()); - SIGNAL_CHECK("caret_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); SIGNAL_CHECK_FALSE("text_changed"); SIGNAL_CHECK_FALSE("lines_edited_from"); } @@ -2399,8 +2420,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_viewport()->is_input_handled()); CHECK(text_edit->get_text() == "aA"); CHECK(text_edit->get_caret_column() == 2); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_editable(false); @@ -2420,8 +2441,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_viewport()->is_input_handled()); CHECK(text_edit->get_text() == "BA"); CHECK(text_edit->get_caret_column() == 1); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); SEND_GUI_ACTION(text_edit, "ui_text_toggle_insert_mode"); @@ -2431,8 +2452,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_viewport()->is_input_handled()); CHECK(text_edit->get_text() == "BB"); CHECK(text_edit->get_caret_column() == 2); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->select(0, 0, 0, 1); @@ -2440,8 +2461,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_viewport()->is_input_handled()); CHECK(text_edit->get_text() == "AB"); CHECK(text_edit->get_caret_column() == 1); - SIGNAL_CHECK("caret_changed", empty_singal_args); - SIGNAL_CHECK("text_changed", empty_singal_args); + SIGNAL_CHECK("caret_changed", empty_signal_args); + SIGNAL_CHECK("text_changed", empty_signal_args); SIGNAL_CHECK("lines_edited_from", lines_edited_args); text_edit->set_overtype_mode_enabled(false); CHECK_FALSE(text_edit->is_overtype_mode_enabled()); @@ -3357,8 +3378,8 @@ TEST_CASE("[SceneTree][TextEdit] gutters") { TextEdit *text_edit = memnew(TextEdit); SceneTree::get_singleton()->get_root()->add_child(text_edit); - Array empty_singal_args; - empty_singal_args.push_back(Array()); + Array empty_signal_args; + empty_signal_args.push_back(Array()); SIGNAL_WATCH(text_edit, "gutter_clicked"); SIGNAL_WATCH(text_edit, "gutter_added"); @@ -3367,7 +3388,7 @@ TEST_CASE("[SceneTree][TextEdit] gutters") { SUBCASE("[TextEdit] gutter add and remove") { text_edit->add_gutter(); CHECK(text_edit->get_gutter_count() == 1); - SIGNAL_CHECK("gutter_added", empty_singal_args); + SIGNAL_CHECK("gutter_added", empty_signal_args); text_edit->set_gutter_name(0, "test_gutter"); CHECK(text_edit->get_gutter_name(0) == "test_gutter"); @@ -3383,7 +3404,7 @@ TEST_CASE("[SceneTree][TextEdit] gutters") { CHECK(text_edit->get_total_gutter_width() < 30); CHECK(text_edit->get_gutter_count() == 2); CHECK(text_edit->get_gutter_name(0) == "test_gutter"); - SIGNAL_CHECK("gutter_added", empty_singal_args); + SIGNAL_CHECK("gutter_added", empty_signal_args); text_edit->set_gutter_draw(1, false); CHECK(text_edit->get_total_gutter_width() > 10); @@ -3392,22 +3413,22 @@ TEST_CASE("[SceneTree][TextEdit] gutters") { text_edit->add_gutter(100); CHECK(text_edit->get_gutter_count() == 3); CHECK(text_edit->get_gutter_name(0) == "test_gutter"); - SIGNAL_CHECK("gutter_added", empty_singal_args); + SIGNAL_CHECK("gutter_added", empty_signal_args); text_edit->add_gutter(0); CHECK(text_edit->get_gutter_count() == 4); CHECK(text_edit->get_gutter_name(1) == "test_gutter"); - SIGNAL_CHECK("gutter_added", empty_singal_args); + SIGNAL_CHECK("gutter_added", empty_signal_args); text_edit->remove_gutter(2); CHECK(text_edit->get_gutter_name(1) == "test_gutter"); CHECK(text_edit->get_gutter_count() == 3); - SIGNAL_CHECK("gutter_removed", empty_singal_args); + SIGNAL_CHECK("gutter_removed", empty_signal_args); text_edit->remove_gutter(0); CHECK(text_edit->get_gutter_name(0) == "test_gutter"); CHECK(text_edit->get_gutter_count() == 2); - SIGNAL_CHECK("gutter_removed", empty_singal_args); + SIGNAL_CHECK("gutter_removed", empty_signal_args); ERR_PRINT_OFF; text_edit->remove_gutter(-1); @@ -3424,7 +3445,7 @@ TEST_CASE("[SceneTree][TextEdit] gutters") { SUBCASE("[TextEdit] gutter data") { text_edit->add_gutter(); CHECK(text_edit->get_gutter_count() == 1); - SIGNAL_CHECK("gutter_added", empty_singal_args); + SIGNAL_CHECK("gutter_added", empty_signal_args); text_edit->set_gutter_name(0, "test_gutter"); CHECK(text_edit->get_gutter_name(0) == "test_gutter"); diff --git a/tests/test_macros.cpp b/tests/test_macros.cpp index aa07f8211a..8c510cb4a5 100644 --- a/tests/test_macros.cpp +++ b/tests/test_macros.cpp @@ -31,11 +31,11 @@ #define DOCTEST_CONFIG_IMPLEMENT #include "test_macros.h" -Map<String, TestFunc> *test_commands = nullptr; +HashMap<String, TestFunc> *test_commands = nullptr; int register_test_command(String p_command, TestFunc p_function) { if (!test_commands) { - test_commands = new Map<String, TestFunc>; + test_commands = new HashMap<String, TestFunc>; } test_commands->insert(p_command, p_function); return 0; diff --git a/tests/test_macros.h b/tests/test_macros.h index 9cb9624d52..189554bd1a 100644 --- a/tests/test_macros.h +++ b/tests/test_macros.h @@ -122,7 +122,7 @@ DOCTEST_STRINGIFY_VARIANT(PackedColorArray); // Example usage: `godot --test gdscript-parser`. typedef void (*TestFunc)(); -extern Map<String, TestFunc> *test_commands; +extern HashMap<String, TestFunc> *test_commands; int register_test_command(String p_command, TestFunc p_function); #define REGISTER_TEST_COMMAND(m_command, m_function) \ @@ -233,8 +233,8 @@ class SignalWatcher : public Object { private: inline static SignalWatcher *singleton; - /* Equal to: Map<String, Vector<Vector<Variant>>> */ - Map<String, Array> _signals; + /* Equal to: RBMap<String, Vector<Vector<Variant>>> */ + HashMap<String, Array> _signals; void _add_signal_entry(const Array &p_args, const String &p_name) { if (!_signals.has(p_name)) { _signals[p_name] = Array(); diff --git a/tests/test_main.cpp b/tests/test_main.cpp index be51afd83c..a5f6fb9b88 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -59,10 +59,10 @@ #include "tests/core/string/test_string.h" #include "tests/core/string/test_translation.h" #include "tests/core/templates/test_command_queue.h" +#include "tests/core/templates/test_hash_map.h" #include "tests/core/templates/test_list.h" #include "tests/core/templates/test_local_vector.h" #include "tests/core/templates/test_lru.h" -#include "tests/core/templates/test_ordered_hash_map.h" #include "tests/core/templates/test_paged_array.h" #include "tests/core/templates/test_vector.h" #include "tests/core/test_crypto.h" @@ -105,9 +105,9 @@ int test_main(int argc, char *argv[]) { // Run custom test tools. if (test_commands) { - for (Map<String, TestFunc>::Element *E = test_commands->front(); E; E = E->next()) { - if (args.find(E->key())) { - const TestFunc &test_func = E->get(); + for (const KeyValue<String, TestFunc> &E : (*test_commands)) { + if (args.find(E.key)) { + const TestFunc &test_func = E.value; test_func(); run_tests = false; break; diff --git a/thirdparty/README.md b/thirdparty/README.md index 41cd0230cc..b147f9754f 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -115,7 +115,7 @@ will limit its functionality to IPv4 only. ## etcpak - Upstream: https://github.com/wolfpld/etcpak -- Version: git (7c3cb6fe708d4ae330b0ab2af1ad472bae2a37a2, 2021) +- Version: git (f128369e64a5f4715de8125b325e4fe7debb5194, 2022) - License: BSD-3-Clause Files extracted from upstream source: @@ -154,7 +154,7 @@ Files extracted from upstream source: ## freetype - Upstream: https://www.freetype.org -- Version: 2.11.1 (3f83daeecb1a78d851b660eed025eeba362c0e4a, 2021) +- Version: 2.12.1 (e8ebfe988b5f57bfb9a3ecb13c70d9791bce9ecf, 2022) - License: FreeType License (BSD-like) Files extracted from upstream source: @@ -204,7 +204,7 @@ Files extracted from upstream source: ## harfbuzz - Upstream: https://github.com/harfbuzz/harfbuzz -- Version: 4.2.0 (9d5730b958974bc9db95e46e6bad52e9e9cd6e1c, 2022) +- Version: 4.2.1 (f7aee78e90bc53b3a95eb56d7550c9effe569ea2, 2022) - License: MIT Files extracted from upstream source: @@ -216,7 +216,7 @@ Files extracted from upstream source: ## icu4c - Upstream: https://github.com/unicode-org/icu -- Version: 70.1 (a56dde820dc35665a66f2e9ee8ba58e75049b668, 2021) +- Version: 71.1 (c205e7ee49a7086a28b9c275fcfdac9ca3dc815d, 2022) - License: Unicode Files extracted from upstream source: @@ -226,14 +226,14 @@ Files extracted from upstream source: Files generated from upstream source: -- the `icudt70l.dat` built with the provided `godot_data.json` config file (see +- the `icudt71l.dat` built with the provided `godot_data.json` config file (see https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md for instructions). - Step 1: Build ICU with default options - `./runConfigureICU {PLATFORM} && make`. - Step 2: Reconfigure ICU with custom data config - `ICU_DATA_FILTER_FILE={GODOT_SOURCE}/thirdparty/icu4c/godot_data.json ./runConfigureICU {PLATFORM} --with-data-packaging=common`. - Step 3: Delete `data/out` folder and rebuild data - `cd data && rm -rf ./out && make`. -- Step 4: Copy `source/data/out/icudt70l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt70l.dat`. +- Step 4: Copy `source/data/out/icudt71l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt71l.dat`. ## jpeg-compressor @@ -625,7 +625,7 @@ instead of `miniz.h` as an external dependency. ## thorvg - Upstream: https://github.com/Samsung/thorvg -- Version: 0.8.0 (41093c17b3cac440bdcc53f8b69abeb5734696b5, 2022) +- Version: 0.8.1 (c4ccb1078f4390ec749ab8e05ba7e9e35f81285f, 2022) - License: MIT Files extracted from upstream source: diff --git a/thirdparty/enet/godot.cpp b/thirdparty/enet/godot.cpp index 93d3b3bbff..d2fcc4642e 100644 --- a/thirdparty/enet/godot.cpp +++ b/thirdparty/enet/godot.cpp @@ -259,7 +259,7 @@ public: class ENetDTLSServer : public ENetGodotSocket { Ref<DTLSServer> server; Ref<UDPServer> udp_server; - Map<String, Ref<PacketPeerDTLS>> peers; + HashMap<String, Ref<PacketPeerDTLS>> peers; int last_service = 0; IPAddress local_address; @@ -331,15 +331,16 @@ public: List<String> remove; Error err = ERR_BUSY; // TODO this needs to be fair! - for (Map<String, Ref<PacketPeerDTLS>>::Element *E = peers.front(); E; E = E->next()) { - Ref<PacketPeerDTLS> peer = E->get(); + + for (KeyValue<String, Ref<PacketPeerDTLS>> & E : peers) { + Ref<PacketPeerDTLS> peer = E.value; peer->poll(); if (peer->get_status() == PacketPeerDTLS::STATUS_HANDSHAKING) { continue; } else if (peer->get_status() != PacketPeerDTLS::STATUS_CONNECTED) { // Peer disconnected, removing it. - remove.push_back(E->key()); + remove.push_back(E.key); continue; } @@ -348,12 +349,12 @@ public: err = peer->get_packet(&buffer, r_read); if (err != OK || p_len < r_read) { // Something wrong with this peer, removing it. - remove.push_back(E->key()); + remove.push_back(E.key); err = FAILED; continue; } - Vector<String> s = E->key().rsplit(":", false, 1); + Vector<String> s = E.key.rsplit(":", false, 1); ERR_CONTINUE(s.size() != 2); // BUG! memcpy(p_buffer, buffer, r_read); @@ -376,8 +377,8 @@ public: } void close() { - for (Map<String, Ref<PacketPeerDTLS>>::Element *E = peers.front(); E; E = E->next()) { - E->get()->disconnect_from_peer(); + for (KeyValue<String, Ref<PacketPeerDTLS>> &E : peers) { + E.value->disconnect_from_peer(); } peers.clear(); udp_server->stop(); diff --git a/thirdparty/etcpak/ProcessRGB.cpp b/thirdparty/etcpak/ProcessRGB.cpp index d60164bcc8..fdb0967ce7 100644 --- a/thirdparty/etcpak/ProcessRGB.cpp +++ b/thirdparty/etcpak/ProcessRGB.cpp @@ -28,6 +28,10 @@ # define _bswap64(x) __builtin_bswap64(x) #endif +static const uint32_t MaxError = 1065369600; // ((38+76+14) * 255)^2 +// common T-/H-mode table +static uint8_t tableTH[8] = { 3, 6, 11, 16, 23, 32, 41, 64 }; + // thresholds for the early compression-mode decision scheme // default: 0.03, 0.09, and 0.38 float ecmd_threshold[3] = { 0.03f, 0.09f, 0.38f }; @@ -36,13 +40,17 @@ static const uint8_t ModeUndecided = 0; static const uint8_t ModePlanar = 0x1; static const uint8_t ModeTH = 0x2; +const unsigned int R = 2; +const unsigned int G = 1; +const unsigned int B = 0; + struct Luma { #ifdef __AVX2__ float max, min; uint8_t minIdx = 255, maxIdx = 255; __m128i luma8; -#elif defined __ARM_NEON +#elif defined __ARM_NEON && defined __aarch64__ float max, min; uint8_t minIdx = 255, maxIdx = 255; uint8x16_t luma8; @@ -52,8 +60,206 @@ struct Luma #endif }; +#ifdef __AVX2__ +struct Plane +{ + uint64_t plane; + uint64_t error; + __m256i sum4; +}; +#endif + +#if defined __AVX2__ || (defined __ARM_NEON && defined __aarch64__) +struct Channels +{ +#ifdef __AVX2__ + __m128i r8, g8, b8; +#elif defined __ARM_NEON && defined __aarch64__ + uint8x16x2_t r, g, b; +#endif +}; +#endif + namespace { +static etcpak_force_inline uint8_t clamp( uint8_t min, int16_t val, uint8_t max ) +{ + return val < min ? min : ( val > max ? max : val ); +} + +static etcpak_force_inline uint8_t clampMin( uint8_t min, int16_t val ) +{ + return val < min ? min : val; +} + +static etcpak_force_inline uint8_t clampMax( int16_t val, uint8_t max ) +{ + return val > max ? max : val; +} + +// slightly faster than std::sort +static void insertionSort( uint8_t* arr1, uint8_t* arr2 ) +{ + for( uint8_t i = 1; i < 16; ++i ) + { + uint8_t value = arr1[i]; + uint8_t hole = i; + + for( ; hole > 0 && value < arr1[hole - 1]; --hole ) + { + arr1[hole] = arr1[hole - 1]; + arr2[hole] = arr2[hole - 1]; + } + arr1[hole] = value; + arr2[hole] = i; + } +} + +//converts indices from |a0|a1|e0|e1|i0|i1|m0|m1|b0|b1|f0|f1|j0|j1|n0|n1|c0|c1|g0|g1|k0|k1|o0|o1|d0|d1|h0|h1|l0|l1|p0|p1| previously used by T- and H-modes +// into |p0|o0|n0|m0|l0|k0|j0|i0|h0|g0|f0|e0|d0|c0|b0|a0|p1|o1|n1|m1|l1|k1|j1|i1|h1|g1|f1|e1|d1|c1|b1|a1| which should be used for all modes. +// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved. +static etcpak_force_inline int indexConversion( int pixelIndices ) +{ + int correctIndices = 0; + int LSB[4][4]; + int MSB[4][4]; + int shift = 0; + for( int y = 3; y >= 0; y-- ) + { + for( int x = 3; x >= 0; x-- ) + { + LSB[x][y] = ( pixelIndices >> shift ) & 1; + shift++; + MSB[x][y] = ( pixelIndices >> shift ) & 1; + shift++; + } + } + shift = 0; + for( int x = 0; x < 4; x++ ) + { + for( int y = 0; y < 4; y++ ) + { + correctIndices |= ( LSB[x][y] << shift ); + correctIndices |= ( MSB[x][y] << ( 16 + shift ) ); + shift++; + } + } + return correctIndices; +} + +// Swapping two RGB-colors +// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved. +static etcpak_force_inline void swapColors( uint8_t( colors )[2][3] ) +{ + uint8_t temp = colors[0][R]; + colors[0][R] = colors[1][R]; + colors[1][R] = temp; + + temp = colors[0][G]; + colors[0][G] = colors[1][G]; + colors[1][G] = temp; + + temp = colors[0][B]; + colors[0][B] = colors[1][B]; + colors[1][B] = temp; +} + + +// calculates quantized colors for T or H modes +void compressColor( uint8_t( currColor )[2][3], uint8_t( quantColor )[2][3], bool t_mode ) +{ + if( t_mode ) + { + quantColor[0][R] = clampMax( 15 * ( currColor[0][R] + 8 ) / 255, 15 ); + quantColor[0][G] = clampMax( 15 * ( currColor[0][G] + 8 ) / 255, 15 ); + quantColor[0][B] = clampMax( 15 * ( currColor[0][B] + 8 ) / 255, 15 ); + } + else // clamped to [1,14] to get a wider range + { + quantColor[0][R] = clamp( 1, 15 * ( currColor[0][R] + 8 ) / 255, 14 ); + quantColor[0][G] = clamp( 1, 15 * ( currColor[0][G] + 8 ) / 255, 14 ); + quantColor[0][B] = clamp( 1, 15 * ( currColor[0][B] + 8 ) / 255, 14 ); + } + + // clamped to [1,14] to get a wider range + quantColor[1][R] = clamp( 1, 15 * ( currColor[1][R] + 8 ) / 255, 14 ); + quantColor[1][G] = clamp( 1, 15 * ( currColor[1][G] + 8 ) / 255, 14 ); + quantColor[1][B] = clamp( 1, 15 * ( currColor[1][B] + 8 ) / 255, 14 ); +} + +// three decoding functions come from ETCPACK v2.74 and are slightly changed. +static etcpak_force_inline void decompressColor( uint8_t( colorsRGB444 )[2][3], uint8_t( colors )[2][3] ) +{ + // The color should be retrieved as: + // + // c = round(255/(r_bits^2-1))*comp_color + // + // This is similar to bit replication + // + // Note -- this code only work for bit replication from 4 bits and up --- 3 bits needs + // two copy operations. + colors[0][R] = ( colorsRGB444[0][R] << 4 ) | colorsRGB444[0][R]; + colors[0][G] = ( colorsRGB444[0][G] << 4 ) | colorsRGB444[0][G]; + colors[0][B] = ( colorsRGB444[0][B] << 4 ) | colorsRGB444[0][B]; + colors[1][R] = ( colorsRGB444[1][R] << 4 ) | colorsRGB444[1][R]; + colors[1][G] = ( colorsRGB444[1][G] << 4 ) | colorsRGB444[1][G]; + colors[1][B] = ( colorsRGB444[1][B] << 4 ) | colorsRGB444[1][B]; +} + +// calculates the paint colors from the block colors +// using a distance d and one of the H- or T-patterns. +static void calculatePaintColors59T( uint8_t d, uint8_t( colors )[2][3], uint8_t( pColors )[4][3] ) +{ + ////////////////////////////////////////////// + // + // C3 C1 C4----C1---C2 + // | | | + // | | | + // |-------| | + // | | | + // | | | + // C4 C2 C3 + // + ////////////////////////////////////////////// + + // C4 + pColors[3][R] = clampMin( 0, colors[1][R] - tableTH[d] ); + pColors[3][G] = clampMin( 0, colors[1][G] - tableTH[d] ); + pColors[3][B] = clampMin( 0, colors[1][B] - tableTH[d] ); + + // C3 + pColors[0][R] = colors[0][R]; + pColors[0][G] = colors[0][G]; + pColors[0][B] = colors[0][B]; + // C2 + pColors[1][R] = clampMax( colors[1][R] + tableTH[d], 255 ); + pColors[1][G] = clampMax( colors[1][G] + tableTH[d], 255 ); + pColors[1][B] = clampMax( colors[1][B] + tableTH[d], 255 ); + // C1 + pColors[2][R] = colors[1][R]; + pColors[2][G] = colors[1][G]; + pColors[2][B] = colors[1][B]; +} + +static void calculatePaintColors58H( uint8_t d, uint8_t( colors )[2][3], uint8_t( pColors )[4][3] ) +{ + pColors[3][R] = clampMin( 0, colors[1][R] - tableTH[d] ); + pColors[3][G] = clampMin( 0, colors[1][G] - tableTH[d] ); + pColors[3][B] = clampMin( 0, colors[1][B] - tableTH[d] ); + + // C1 + pColors[0][R] = clampMax( colors[0][R] + tableTH[d], 255 ); + pColors[0][G] = clampMax( colors[0][G] + tableTH[d], 255 ); + pColors[0][B] = clampMax( colors[0][B] + tableTH[d], 255 ); + // C2 + pColors[1][R] = clampMin( 0, colors[0][R] - tableTH[d] ); + pColors[1][G] = clampMin( 0, colors[0][G] - tableTH[d] ); + pColors[1][B] = clampMin( 0, colors[0][B] - tableTH[d] ); + // C3 + pColors[2][R] = clampMax( colors[1][R] + tableTH[d], 255 ); + pColors[2][G] = clampMax( colors[1][G] + tableTH[d], 255 ); + pColors[2][B] = clampMax( colors[1][B] + tableTH[d], 255 ); +} #if defined _MSC_VER && !defined __clang__ static etcpak_force_inline unsigned long _bit_scan_forward( unsigned long mask ) @@ -586,127 +792,107 @@ static etcpak_force_inline __m128i r6g7b6_AVX2(__m128 cof, __m128 chf, __m128 cv return _mm_shuffle_epi8(cohv5, _mm_setr_epi8(6, 5, 4, -1, 2, 1, 0, -1, 10, 9, 8, -1, -1, -1, -1, -1)); } -struct Plane +static etcpak_force_inline Plane Planar_AVX2( const Channels& ch, uint8_t& mode, bool useHeuristics ) { - uint64_t plane; - uint64_t error; - __m256i sum4; -}; - -static etcpak_force_inline Plane Planar_AVX2( const uint8_t* src, const uint8_t mode ) -{ - __m128i d0 = _mm_loadu_si128(((__m128i*)src) + 0); - __m128i d1 = _mm_loadu_si128(((__m128i*)src) + 1); - __m128i d2 = _mm_loadu_si128(((__m128i*)src) + 2); - __m128i d3 = _mm_loadu_si128(((__m128i*)src) + 3); - - __m128i rgb0 = _mm_shuffle_epi8(d0, _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, -1, -1, -1, -1)); - __m128i rgb1 = _mm_shuffle_epi8(d1, _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, -1, -1, -1, -1)); - __m128i rgb2 = _mm_shuffle_epi8(d2, _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, -1, -1, -1, -1)); - __m128i rgb3 = _mm_shuffle_epi8(d3, _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, -1, -1, -1, -1)); - - __m128i rg0 = _mm_unpacklo_epi32(rgb0, rgb1); - __m128i rg1 = _mm_unpacklo_epi32(rgb2, rgb3); - __m128i b0 = _mm_unpackhi_epi32(rgb0, rgb1); - __m128i b1 = _mm_unpackhi_epi32(rgb2, rgb3); - - // swap channels - __m128i b8 = _mm_unpacklo_epi64(rg0, rg1); - __m128i g8 = _mm_unpackhi_epi64(rg0, rg1); - __m128i r8 = _mm_unpacklo_epi64(b0, b1); + __m128i t0 = _mm_sad_epu8( ch.r8, _mm_setzero_si128() ); + __m128i t1 = _mm_sad_epu8( ch.g8, _mm_setzero_si128() ); + __m128i t2 = _mm_sad_epu8( ch.b8, _mm_setzero_si128() ); - __m128i t0 = _mm_sad_epu8(r8, _mm_setzero_si128()); - __m128i t1 = _mm_sad_epu8(g8, _mm_setzero_si128()); - __m128i t2 = _mm_sad_epu8(b8, _mm_setzero_si128()); + __m128i r8s = _mm_shuffle_epi8( ch.r8, _mm_set_epi8( 0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0 ) ); + __m128i g8s = _mm_shuffle_epi8( ch.g8, _mm_set_epi8( 0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0 ) ); + __m128i b8s = _mm_shuffle_epi8( ch.b8, _mm_set_epi8( 0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0 ) ); - __m128i r8s = _mm_shuffle_epi8(r8, _mm_set_epi8(0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0)); - __m128i g8s = _mm_shuffle_epi8(g8, _mm_set_epi8(0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0)); - __m128i b8s = _mm_shuffle_epi8(b8, _mm_set_epi8(0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0)); + __m128i s0 = _mm_sad_epu8( r8s, _mm_setzero_si128() ); + __m128i s1 = _mm_sad_epu8( g8s, _mm_setzero_si128() ); + __m128i s2 = _mm_sad_epu8( b8s, _mm_setzero_si128() ); - __m128i s0 = _mm_sad_epu8(r8s, _mm_setzero_si128()); - __m128i s1 = _mm_sad_epu8(g8s, _mm_setzero_si128()); - __m128i s2 = _mm_sad_epu8(b8s, _mm_setzero_si128()); + __m256i sr0 = _mm256_insertf128_si256( _mm256_castsi128_si256( t0 ), s0, 1 ); + __m256i sg0 = _mm256_insertf128_si256( _mm256_castsi128_si256( t1 ), s1, 1 ); + __m256i sb0 = _mm256_insertf128_si256( _mm256_castsi128_si256( t2 ), s2, 1 ); - __m256i sr0 = _mm256_insertf128_si256(_mm256_castsi128_si256(t0), s0, 1); - __m256i sg0 = _mm256_insertf128_si256(_mm256_castsi128_si256(t1), s1, 1); - __m256i sb0 = _mm256_insertf128_si256(_mm256_castsi128_si256(t2), s2, 1); + __m256i sr1 = _mm256_slli_epi64( sr0, 32 ); + __m256i sg1 = _mm256_slli_epi64( sg0, 16 ); - __m256i sr1 = _mm256_slli_epi64(sr0, 32); - __m256i sg1 = _mm256_slli_epi64(sg0, 16); + __m256i srb = _mm256_or_si256( sr1, sb0 ); + __m256i srgb = _mm256_or_si256( srb, sg1 ); - __m256i srb = _mm256_or_si256(sr1, sb0); - __m256i srgb = _mm256_or_si256(srb, sg1); + if( mode != ModePlanar && useHeuristics ) + { + Plane plane; + plane.sum4 = _mm256_permute4x64_epi64( srgb, _MM_SHUFFLE( 2, 3, 0, 1 ) ); + return plane; + } - __m128i t3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(t0), _mm_castsi128_ps(t1), _MM_SHUFFLE(2, 0, 2, 0))); - __m128i t4 = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3, 1, 2, 0)); - __m128i t5 = _mm_hadd_epi32(t3, t4); - __m128i t6 = _mm_shuffle_epi32(t5, _MM_SHUFFLE(1, 1, 1, 1)); - __m128i t7 = _mm_shuffle_epi32(t5, _MM_SHUFFLE(2, 2, 2, 2)); + __m128i t3 = _mm_castps_si128( _mm_shuffle_ps( _mm_castsi128_ps( t0 ), _mm_castsi128_ps( t1 ), _MM_SHUFFLE( 2, 0, 2, 0 ) ) ); + __m128i t4 = _mm_shuffle_epi32( t2, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + __m128i t5 = _mm_hadd_epi32( t3, t4 ); + __m128i t6 = _mm_shuffle_epi32( t5, _MM_SHUFFLE( 1, 1, 1, 1 ) ); + __m128i t7 = _mm_shuffle_epi32( t5, _MM_SHUFFLE( 2, 2, 2, 2 ) ); - __m256i sr = _mm256_broadcastw_epi16(t5); - __m256i sg = _mm256_broadcastw_epi16(t6); - __m256i sb = _mm256_broadcastw_epi16(t7); + __m256i sr = _mm256_broadcastw_epi16( t5 ); + __m256i sg = _mm256_broadcastw_epi16( t6 ); + __m256i sb = _mm256_broadcastw_epi16( t7 ); - __m256i r08 = _mm256_cvtepu8_epi16(r8); - __m256i g08 = _mm256_cvtepu8_epi16(g8); - __m256i b08 = _mm256_cvtepu8_epi16(b8); + __m256i r08 = _mm256_cvtepu8_epi16( ch.r8 ); + __m256i g08 = _mm256_cvtepu8_epi16( ch.g8 ); + __m256i b08 = _mm256_cvtepu8_epi16( ch.b8 ); - __m256i r16 = _mm256_slli_epi16(r08, 4); - __m256i g16 = _mm256_slli_epi16(g08, 4); - __m256i b16 = _mm256_slli_epi16(b08, 4); + __m256i r16 = _mm256_slli_epi16( r08, 4 ); + __m256i g16 = _mm256_slli_epi16( g08, 4 ); + __m256i b16 = _mm256_slli_epi16( b08, 4 ); - __m256i difR0 = _mm256_sub_epi16(r16, sr); - __m256i difG0 = _mm256_sub_epi16(g16, sg); - __m256i difB0 = _mm256_sub_epi16(b16, sb); + __m256i difR0 = _mm256_sub_epi16( r16, sr ); + __m256i difG0 = _mm256_sub_epi16( g16, sg ); + __m256i difB0 = _mm256_sub_epi16( b16, sb ); - __m256i difRyz = _mm256_madd_epi16(difR0, _mm256_set_epi16(255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255)); - __m256i difGyz = _mm256_madd_epi16(difG0, _mm256_set_epi16(255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255)); - __m256i difByz = _mm256_madd_epi16(difB0, _mm256_set_epi16(255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255)); + __m256i difRyz = _mm256_madd_epi16( difR0, _mm256_set_epi16( 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255 ) ); + __m256i difGyz = _mm256_madd_epi16( difG0, _mm256_set_epi16( 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255 ) ); + __m256i difByz = _mm256_madd_epi16( difB0, _mm256_set_epi16( 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255 ) ); - __m256i difRxz = _mm256_madd_epi16(difR0, _mm256_set_epi16(255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255)); - __m256i difGxz = _mm256_madd_epi16(difG0, _mm256_set_epi16(255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255)); - __m256i difBxz = _mm256_madd_epi16(difB0, _mm256_set_epi16(255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255)); + __m256i difRxz = _mm256_madd_epi16( difR0, _mm256_set_epi16( 255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255 ) ); + __m256i difGxz = _mm256_madd_epi16( difG0, _mm256_set_epi16( 255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255 ) ); + __m256i difBxz = _mm256_madd_epi16( difB0, _mm256_set_epi16( 255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255 ) ); - __m256i difRGyz = _mm256_hadd_epi32(difRyz, difGyz); - __m256i difByzxz = _mm256_hadd_epi32(difByz, difBxz); + __m256i difRGyz = _mm256_hadd_epi32( difRyz, difGyz ); + __m256i difByzxz = _mm256_hadd_epi32( difByz, difBxz ); - __m256i difRGxz = _mm256_hadd_epi32(difRxz, difGxz); + __m256i difRGxz = _mm256_hadd_epi32( difRxz, difGxz ); - __m128i sumRGyz = _mm_add_epi32(_mm256_castsi256_si128(difRGyz), _mm256_extracti128_si256(difRGyz, 1)); - __m128i sumByzxz = _mm_add_epi32(_mm256_castsi256_si128(difByzxz), _mm256_extracti128_si256(difByzxz, 1)); - __m128i sumRGxz = _mm_add_epi32(_mm256_castsi256_si128(difRGxz), _mm256_extracti128_si256(difRGxz, 1)); + __m128i sumRGyz = _mm_add_epi32( _mm256_castsi256_si128( difRGyz ), _mm256_extracti128_si256( difRGyz, 1 ) ); + __m128i sumByzxz = _mm_add_epi32( _mm256_castsi256_si128( difByzxz ), _mm256_extracti128_si256( difByzxz, 1 ) ); + __m128i sumRGxz = _mm_add_epi32( _mm256_castsi256_si128( difRGxz ), _mm256_extracti128_si256( difRGxz, 1 ) ); - __m128i sumRGByz = _mm_hadd_epi32(sumRGyz, sumByzxz); - __m128i sumRGByzxz = _mm_hadd_epi32(sumRGxz, sumByzxz); + __m128i sumRGByz = _mm_hadd_epi32( sumRGyz, sumByzxz ); + __m128i sumRGByzxz = _mm_hadd_epi32( sumRGxz, sumByzxz ); - __m128i sumRGBxz = _mm_shuffle_epi32(sumRGByzxz, _MM_SHUFFLE(2, 3, 1, 0)); + __m128i sumRGBxz = _mm_shuffle_epi32( sumRGByzxz, _MM_SHUFFLE( 2, 3, 1, 0 ) ); - __m128 sumRGByzf = _mm_cvtepi32_ps(sumRGByz); - __m128 sumRGBxzf = _mm_cvtepi32_ps(sumRGBxz); + __m128 sumRGByzf = _mm_cvtepi32_ps( sumRGByz ); + __m128 sumRGBxzf = _mm_cvtepi32_ps( sumRGBxz ); - const float value = (255 * 255 * 8.0f + 85 * 85 * 8.0f) * 16.0f; + const float value = ( 255 * 255 * 8.0f + 85 * 85 * 8.0f ) * 16.0f; - __m128 scale = _mm_set1_ps(-4.0f / value); + __m128 scale = _mm_set1_ps( -4.0f / value ); - __m128 af = _mm_mul_ps(sumRGBxzf, scale); - __m128 bf = _mm_mul_ps(sumRGByzf, scale); + __m128 af = _mm_mul_ps( sumRGBxzf, scale ); + __m128 bf = _mm_mul_ps( sumRGByzf, scale ); - __m128 df = _mm_mul_ps(_mm_cvtepi32_ps(t5), _mm_set1_ps(4.0f / 16.0f)); + __m128 df = _mm_mul_ps( _mm_cvtepi32_ps( t5 ), _mm_set1_ps( 4.0f / 16.0f ) ); // calculating the three colors RGBO, RGBH, and RGBV. RGB = df - af * x - bf * y; - __m128 cof0 = _mm_fnmadd_ps(af, _mm_set1_ps(-255.0f), _mm_fnmadd_ps(bf, _mm_set1_ps(-255.0f), df)); - __m128 chf0 = _mm_fnmadd_ps(af, _mm_set1_ps( 425.0f), _mm_fnmadd_ps(bf, _mm_set1_ps(-255.0f), df)); - __m128 cvf0 = _mm_fnmadd_ps(af, _mm_set1_ps(-255.0f), _mm_fnmadd_ps(bf, _mm_set1_ps( 425.0f), df)); + __m128 cof0 = _mm_fnmadd_ps( af, _mm_set1_ps( -255.0f ), _mm_fnmadd_ps( bf, _mm_set1_ps( -255.0f ), df ) ); + __m128 chf0 = _mm_fnmadd_ps( af, _mm_set1_ps( 425.0f ), _mm_fnmadd_ps( bf, _mm_set1_ps( -255.0f ), df ) ); + __m128 cvf0 = _mm_fnmadd_ps( af, _mm_set1_ps( -255.0f ), _mm_fnmadd_ps( bf, _mm_set1_ps( 425.0f ), df ) ); // convert to r6g7b6 - __m128i cohv = r6g7b6_AVX2(cof0, chf0, cvf0); + __m128i cohv = r6g7b6_AVX2( cof0, chf0, cvf0 ); - uint64_t rgbho = _mm_extract_epi64(cohv, 0); - uint32_t rgbv0 = _mm_extract_epi32(cohv, 2); + uint64_t rgbho = _mm_extract_epi64( cohv, 0 ); + uint32_t rgbv0 = _mm_extract_epi32( cohv, 2 ); // Error calculation uint64_t error = 0; - if( mode != ModePlanar ) + if( !useHeuristics ) { auto ro0 = ( rgbho >> 48 ) & 0x3F; auto go0 = ( rgbho >> 40 ) & 0x7F; @@ -820,7 +1006,15 @@ static etcpak_force_inline Plane Planar_AVX2( const uint8_t* src, const uint8_t Plane plane; plane.plane = result; - plane.error = error; + if( useHeuristics ) + { + plane.error = 0; + mode = ModePlanar; + } + else + { + plane.error = error; + } plane.sum4 = _mm256_permute4x64_epi64(srgb, _MM_SHUFFLE(2, 3, 0, 1)); return plane; @@ -1570,7 +1764,7 @@ static etcpak_force_inline uint8_t convert7(float f) return (i + 9 - ((i + 9) >> 8) - ((i + 6) >> 8)) >> 2; } -static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar( const uint8_t* src, const uint8_t mode ) +static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar( const uint8_t* src, const uint8_t mode, bool useHeuristics ) { int32_t r = 0; int32_t g = 0; @@ -1645,7 +1839,7 @@ static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar( const uint8_t* // Error calculation uint64_t error = 0; - if( ModePlanar != mode ) + if( ModePlanar != mode && useHeuristics ) { auto ro0 = coR; auto go0 = coG; @@ -1756,7 +1950,7 @@ static etcpak_force_inline int16x8_t Planar_NEON_SumWide( uint8x16_t src ) uint16x4_t accu2 = vpadd_u16( accu4, accu4 ); uint16x4_t accu1 = vpadd_u16( accu2, accu2 ); return vreinterpretq_s16_u16( vcombine_u16( accu1, accu1 ) ); -#else +#else return vdupq_n_s16( vaddvq_u16( accu8 ) ); #endif } @@ -1783,7 +1977,7 @@ static etcpak_force_inline int16x4_t convert7_NEON( int32x4_t x ) return vshr_n_s16( vsub_s16( vsub_s16( p9, vshr_n_s16( p9, 8 ) ), vshr_n_s16( p6, 8 ) ), 2 ); } -static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar_NEON( const uint8_t* src, const uint8_t mode ) +static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar_NEON( const uint8_t* src, const uint8_t mode, bool useHeuristics ) { uint8x16x4_t srcBlock = vld4q_u8( src ); @@ -1828,7 +2022,7 @@ static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar_NEON( const uint int16x4_t c_hvox_g_8 = vorr_s16( vshr_n_s16( c_hvox_g_7, 6 ), vshl_n_s16( c_hvox_g_7, 1 ) ); uint64_t error = 0; - if( mode != ModePlanar ) + if( mode != ModePlanar && useHeuristics ) { int16x4_t rec_gxbr_o = vext_s16( c_hvox_g_8, vget_high_s16( c_hvoo_br_8 ), 3 ); @@ -1924,6 +2118,376 @@ static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar_NEON( const uint #endif +#ifdef __AVX2__ +uint32_t calculateErrorTH( bool tMode, uint8_t( colorsRGB444 )[2][3], uint8_t& dist, uint32_t& pixIndices, uint8_t startDist, __m128i r8, __m128i g8, __m128i b8 ) +#else +uint32_t calculateErrorTH( bool tMode, uint8_t* src, uint8_t( colorsRGB444 )[2][3], uint8_t& dist, uint32_t& pixIndices, uint8_t startDist ) +#endif +{ + uint32_t blockErr = 0, bestBlockErr = MaxError; + + uint32_t pixColors; + uint8_t possibleColors[4][3]; + uint8_t colors[2][3]; + + decompressColor( colorsRGB444, colors ); + +#ifdef __AVX2__ + __m128i reverseMask = _mm_set_epi8( 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 ); +#endif + + // test distances + for( uint8_t d = startDist; d < 8; ++d ) + { + if( d >= 2 && dist == d - 2 ) break; + + blockErr = 0; + pixColors = 0; + + if( tMode ) + { + calculatePaintColors59T( d, colors, possibleColors ); + } + else + { + calculatePaintColors58H( d, colors, possibleColors ); + } + +#ifdef __AVX2__ + // RGB ordering + __m128i b8Rev = _mm_shuffle_epi8( b8, reverseMask ); + __m128i g8Rev = _mm_shuffle_epi8( g8, reverseMask ); + __m128i r8Rev = _mm_shuffle_epi8( r8, reverseMask ); + + // extends 3x128 bits RGB into 3x256 bits RGB for error comparisions + static const __m128i zero = _mm_setzero_si128(); + __m128i b8Lo = _mm_unpacklo_epi8( b8Rev, zero ); + __m128i g8Lo = _mm_unpacklo_epi8( g8Rev, zero ); + __m128i r8Lo = _mm_unpacklo_epi8( r8Rev, zero ); + __m128i b8Hi = _mm_unpackhi_epi8( b8Rev, zero ); + __m128i g8Hi = _mm_unpackhi_epi8( g8Rev, zero ); + __m128i r8Hi = _mm_unpackhi_epi8( r8Rev, zero ); + + __m256i b8 = _mm256_set_m128i( b8Hi, b8Lo ); + __m256i g8 = _mm256_set_m128i( g8Hi, g8Lo ); + __m256i r8 = _mm256_set_m128i( r8Hi, r8Lo ); + + // caculates differences between the pixel colrs and the palette colors + __m256i diffb = _mm256_abs_epi16( _mm256_sub_epi16( b8, _mm256_set1_epi16( possibleColors[0][B] ) ) ); + __m256i diffg = _mm256_abs_epi16( _mm256_sub_epi16( g8, _mm256_set1_epi16( possibleColors[0][G] ) ) ); + __m256i diffr = _mm256_abs_epi16( _mm256_sub_epi16( r8, _mm256_set1_epi16( possibleColors[0][R] ) ) ); + + // luma-based error calculations + static const __m256i bWeight = _mm256_set1_epi16( 14 ); + static const __m256i gWeight = _mm256_set1_epi16( 76 ); + static const __m256i rWeight = _mm256_set1_epi16( 38 ); + + diffb = _mm256_mullo_epi16( diffb, bWeight ); + diffg = _mm256_mullo_epi16( diffg, gWeight ); + diffr = _mm256_mullo_epi16( diffr, rWeight ); + + // obtains the error with the current palette color + __m256i lowestPixErr = _mm256_add_epi16( _mm256_add_epi16( diffb, diffg ), diffr ); + + // error calucations with the remaining three palette colors + static const uint32_t masks[4] = { 0, 0x55555555, 0xAAAAAAAA, 0xFFFFFFFF }; + for( uint8_t c = 1; c < 4; c++ ) + { + __m256i diffb = _mm256_abs_epi16( _mm256_sub_epi16( b8, _mm256_set1_epi16( possibleColors[c][B] ) ) ); + __m256i diffg = _mm256_abs_epi16( _mm256_sub_epi16( g8, _mm256_set1_epi16( possibleColors[c][G] ) ) ); + __m256i diffr = _mm256_abs_epi16( _mm256_sub_epi16( r8, _mm256_set1_epi16( possibleColors[c][R] ) ) ); + + diffb = _mm256_mullo_epi16( diffb, bWeight ); + diffg = _mm256_mullo_epi16( diffg, gWeight ); + diffr = _mm256_mullo_epi16( diffr, rWeight ); + + // error comparison with the previous best color + __m256i pixErrors = _mm256_add_epi16( _mm256_add_epi16( diffb, diffg ), diffr ); + __m256i minErr = _mm256_min_epu16( lowestPixErr, pixErrors ); + __m256i cmpRes = _mm256_cmpeq_epi16( pixErrors, minErr ); + lowestPixErr = minErr; + + // update pixel colors + uint32_t updPixColors = _mm256_movemask_epi8( cmpRes ); + uint32_t prevPixColors = pixColors & ~updPixColors; + uint32_t mskPixColors = masks[c] & updPixColors; + pixColors = prevPixColors | mskPixColors; + } + + // accumulate the block error + alignas( 32 ) uint16_t pixErr16[16] = { 0, }; + _mm256_storeu_si256( (__m256i*)pixErr16, lowestPixErr ); + for( uint8_t p = 0; p < 16; p++ ) + { + blockErr += (int)( pixErr16[p] ) * pixErr16[p]; + } +#else + for( size_t y = 0; y < 4; ++y ) + { + for( size_t x = 0; x < 4; ++x ) + { + uint32_t bestPixErr = MaxError; + pixColors <<= 2; // Make room for next value + + // Loop possible block colors + for( uint8_t c = 0; c < 4; ++c ) + { + int diff[3]; + diff[R] = src[4 * ( x * 4 + y ) + R] - possibleColors[c][R]; + diff[G] = src[4 * ( x * 4 + y ) + G] - possibleColors[c][G]; + diff[B] = src[4 * ( x * 4 + y ) + B] - possibleColors[c][B]; + + const uint32_t err = 38 * abs( diff[R] ) + 76 * abs( diff[G] ) + 14 * abs( diff[B] ); + uint32_t pixErr = err * err; + + // Choose best error + if( pixErr < bestPixErr ) + { + bestPixErr = pixErr; + pixColors ^= ( pixColors & 3 ); // Reset the two first bits + pixColors |= c; + } + } + blockErr += bestPixErr; + } + } +#endif + + if( blockErr < bestBlockErr ) + { + bestBlockErr = blockErr; + dist = d; + pixIndices = pixColors; + } + } + + return bestBlockErr; +} + + +// main T-/H-mode compression function +#ifdef __AVX2__ +uint32_t compressBlockTH( uint8_t* src, Luma& l, uint32_t& compressed1, uint32_t& compressed2, bool& tMode, __m128i r8, __m128i g8, __m128i b8 ) +#else +uint32_t compressBlockTH( uint8_t *src, Luma& l, uint32_t& compressed1, uint32_t& compressed2, bool &tMode ) +#endif +{ +#ifdef __AVX2__ + alignas( 8 ) uint8_t luma[16] = { 0, }; + _mm_storeu_si128 ( (__m128i* )luma, l.luma8 ); +#elif defined __ARM_NEON && defined __aarch64__ + alignas( 8 ) uint8_t luma[16] = { 0 }; + vst1q_u8( luma, l.luma8 ); +#else + uint8_t* luma = l.val; +#endif + + uint8_t pixIdx[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + + // 1) sorts the pairs of (luma, pix_idx) + insertionSort( luma, pixIdx ); + + // 2) finds the min (left+right) + uint8_t minSumRangeIdx = 0; + uint16_t minSumRangeValue; + uint16_t sum; + static const uint8_t diffBonus[15] = {8, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 8}; + const int16_t temp = luma[15] - luma[0]; + + minSumRangeValue = luma[15] - luma[1] + diffBonus[0]; + for( uint8_t i = 1; i < 14; i++ ) + { + sum = temp - luma[i+1] + luma[i] + diffBonus[i]; + if( minSumRangeValue > sum ) + { + minSumRangeValue = sum; + minSumRangeIdx = i; + } + } + + sum = luma[14] - luma[0] + diffBonus[14]; + if( minSumRangeValue > sum ) + { + minSumRangeValue = sum; + minSumRangeIdx = 14; + } + uint8_t lRange, rRange; + + lRange = luma[minSumRangeIdx] - luma[0]; + rRange = luma[15] - luma[minSumRangeIdx + 1]; + + // 3) sets a proper mode + bool swap = false; + if( lRange >= rRange ) + { + if( lRange >= rRange * 2 ) + { + swap = true; + tMode = true; + } + } + else + { + if( lRange * 2 <= rRange ) tMode = true; + } + // 4) calculates the two base colors + uint8_t rangeIdx[4] = { pixIdx[0], pixIdx[minSumRangeIdx], pixIdx[minSumRangeIdx + 1], pixIdx[15] }; + + uint16_t r[4], g[4], b[4]; + for( uint8_t i = 0; i < 4; ++i ) + { + uint8_t idx = rangeIdx[i] * 4; + b[i] = src[idx]; + g[i] = src[idx + 1]; + r[i] = src[idx + 2]; + } + + uint8_t mid_rgb[2][3]; + if( swap ) + { + mid_rgb[1][B] = ( b[0] + b[1] ) / 2; + mid_rgb[1][G] = ( g[0] + g[1] ) / 2; + mid_rgb[1][R] = ( r[0] + r[1] ) / 2; + + uint16_t sum_rgb[3] = { 0, 0, 0 }; + for( uint8_t i = minSumRangeIdx + 1; i < 16; i++ ) + { + uint8_t idx = pixIdx[i] * 4; + sum_rgb[B] += src[idx]; + sum_rgb[G] += src[idx + 1]; + sum_rgb[R] += src[idx + 2]; + } + const uint8_t temp = 15 - minSumRangeIdx; + mid_rgb[0][B] = sum_rgb[B] / temp; + mid_rgb[0][G] = sum_rgb[G] / temp; + mid_rgb[0][R] = sum_rgb[R] / temp; + } + else + { + mid_rgb[0][B] = (b[0] + b[1]) / 2; + mid_rgb[0][G] = (g[0] + g[1]) / 2; + mid_rgb[0][R] = (r[0] + r[1]) / 2; + if( tMode ) + { + uint16_t sum_rgb[3] = { 0, 0, 0 }; + for( uint8_t i = minSumRangeIdx + 1; i < 16; i++ ) + { + uint8_t idx = pixIdx[i] * 4; + sum_rgb[B] += src[idx]; + sum_rgb[G] += src[idx + 1]; + sum_rgb[R] += src[idx + 2]; + } + const uint8_t temp = 15 - minSumRangeIdx; + mid_rgb[1][B] = sum_rgb[B] / temp; + mid_rgb[1][G] = sum_rgb[G] / temp; + mid_rgb[1][R] = sum_rgb[R] / temp; + } + else + { + mid_rgb[1][B] = (b[2] + b[3]) / 2; + mid_rgb[1][G] = (g[2] + g[3]) / 2; + mid_rgb[1][R] = (r[2] + r[3]) / 2; + } + } + + // 5) sets the start distance index + uint32_t startDistCandidate; + uint32_t avgDist; + if( tMode ) + { + if( swap ) + { + avgDist = ( b[1] - b[0] + g[1] - g[0] + r[1] - r[0] ) / 6; + } + else + { + avgDist = ( b[3] - b[2] + g[3] - g[2] + r[3] - r[2] ) / 6; + } + } + else + { + avgDist = ( b[1] - b[0] + g[1] - g[0] + r[1] - r[0] + b[3] - b[2] + g[3] - g[2] + r[3] - r[2] ) / 12; + } + + if( avgDist <= 16) + { + startDistCandidate = 0; + } + else if( avgDist <= 23 ) + { + startDistCandidate = 1; + } + else if( avgDist <= 32 ) + { + startDistCandidate = 2; + } + else if( avgDist <= 41 ) + { + startDistCandidate = 3; + } + else + { + startDistCandidate = 4; + } + + uint32_t bestErr = MaxError; + uint32_t bestPixIndices; + uint8_t bestDist = 10; + uint8_t colorsRGB444[2][3]; + compressColor( mid_rgb, colorsRGB444, tMode ); + compressed1 = 0; + + // 6) finds the best candidate with the lowest error +#ifdef __AVX2__ + // Vectorized ver + bestErr = calculateErrorTH( tMode, colorsRGB444, bestDist, bestPixIndices, startDistCandidate, r8, g8, b8 ); +#else + // Scalar ver + bestErr = calculateErrorTH( tMode, src, colorsRGB444, bestDist, bestPixIndices, startDistCandidate ); +#endif + + // 7) outputs the final T or H block + if( tMode ) + { + // Put the compress params into the compression block + compressed1 |= ( colorsRGB444[0][R] & 0xf ) << 23; + compressed1 |= ( colorsRGB444[0][G] & 0xf ) << 19; + compressed1 |= ( colorsRGB444[0][B] ) << 15; + compressed1 |= ( colorsRGB444[1][R] ) << 11; + compressed1 |= ( colorsRGB444[1][G] ) << 7; + compressed1 |= ( colorsRGB444[1][B] ) << 3; + compressed1 |= bestDist & 0x7; + } + else + { + int bestRGB444ColPacked[2]; + bestRGB444ColPacked[0] = (colorsRGB444[0][R] << 8) + (colorsRGB444[0][G] << 4) + colorsRGB444[0][B]; + bestRGB444ColPacked[1] = (colorsRGB444[1][R] << 8) + (colorsRGB444[1][G] << 4) + colorsRGB444[1][B]; + if( ( bestRGB444ColPacked[0] >= bestRGB444ColPacked[1] ) ^ ( ( bestDist & 1 ) == 1 ) ) + { + swapColors( colorsRGB444 ); + // Reshuffle pixel indices to to exchange C1 with C3, and C2 with C4 + bestPixIndices = ( 0x55555555 & bestPixIndices ) | ( 0xaaaaaaaa & ( ~bestPixIndices ) ); + } + + // Put the compress params into the compression block + compressed1 |= ( colorsRGB444[0][R] & 0xf ) << 22; + compressed1 |= ( colorsRGB444[0][G] & 0xf ) << 18; + compressed1 |= ( colorsRGB444[0][B] & 0xf ) << 14; + compressed1 |= ( colorsRGB444[1][R] & 0xf ) << 10; + compressed1 |= ( colorsRGB444[1][G] & 0xf ) << 6; + compressed1 |= ( colorsRGB444[1][B] & 0xf ) << 2; + compressed1 |= ( bestDist >> 1 ) & 0x3; + } + + bestPixIndices = indexConversion( bestPixIndices ); + compressed2 = 0; + compressed2 = ( compressed2 & ~( ( 0x2 << 31 ) - 1 ) ) | ( bestPixIndices & ( ( 2 << 31 ) - 1 ) ); + + return bestErr; +} +//#endif + template<class T, class S> static etcpak_force_inline uint64_t EncodeSelectors( uint64_t d, const T terr[2][8], const S tsel[16][8], const uint32_t* id, const uint64_t value, const uint64_t error) { @@ -2025,7 +2589,7 @@ static inline int16_t hMax( __m128i buffer, uint8_t& idx ) return result; } -#elif defined __ARM_NEON +#elif defined __ARM_NEON && defined __aarch64__ static inline int16_t hMax( uint8x16_t buffer, uint8_t& idx ) { const uint8_t max = vmaxvq_u8( buffer ); @@ -2072,7 +2636,7 @@ static inline int16_t hMin( __m128i buffer, uint8_t& idx ) idx = _tzcnt_u32( _mm_movemask_epi8( mask ) ); return result; } -#elif defined __ARM_NEON +#elif defined __ARM_NEON && defined __aarch64__ static inline int16_t hMin( uint8x16_t buffer, uint8_t& idx ) { const uint8_t min = vminvq_u8( buffer ); @@ -2109,8 +2673,153 @@ static inline int16_t hMin( uint8x16_t buffer, uint8_t& idx ) } #endif -static etcpak_force_inline void CalculateLuma( const uint8_t* src, Luma& luma ) +// During search it is not convenient to store the bits the way they are stored in the +// file format. Hence, after search, it is converted to this format. +// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved. +static inline void stuff59bits( unsigned int thumbT59W1, unsigned int thumbT59W2, unsigned int& thumbTW1, unsigned int& thumbTW2 ) { + // Put bits in twotimer configuration for 59 (red overflows) + // + // Go from this bit layout: + // + // |63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32| + // |----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--| + // + // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00| + // |----------------------------------------index bits---------------------------------------------| + // + // + // To this: + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // ----------------------------------------------------------------------------------------------- + // |// // //|R0a |//|R0b |G0 |B0 |R1 |G1 |B1 |da |df|db| + // ----------------------------------------------------------------------------------------------- + // + // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00| + // |----------------------------------------index bits---------------------------------------------| + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // ----------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |df|fp| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bt|bt| + // ------------------------------------------------------------------------------------------------ + + uint8_t R0a; + uint8_t bit, a, b, c, d, bits; + + R0a = ( thumbT59W1 >> 25 ) & 0x3; + + // Fix middle part + thumbTW1 = thumbT59W1 << 1; + // Fix R0a (top two bits of R0) + thumbTW1 = ( thumbTW1 & ~( 0x3 << 27 ) ) | ( ( R0a & 0x3 ) << 27 ); + // Fix db (lowest bit of d) + thumbTW1 = ( thumbTW1 & ~0x1 ) | ( thumbT59W1 & 0x1 ); + + // Make sure that red overflows: + a = ( thumbTW1 >> 28 ) & 0x1; + b = ( thumbTW1 >> 27 ) & 0x1; + c = ( thumbTW1 >> 25 ) & 0x1; + d = ( thumbTW1 >> 24 ) & 0x1; + + // The following bit abcd bit sequences should be padded with ones: 0111, 1010, 1011, 1101, 1110, 1111 + // The following logical expression checks for the presence of any of those: + bit = ( a & c ) | ( !a & b & c & d ) | ( a & b & !c & d ); + bits = 0xf * bit; + thumbTW1 = ( thumbTW1 & ~( 0x7 << 29 ) ) | ( bits & 0x7 ) << 29; + thumbTW1 = ( thumbTW1 & ~( 0x1 << 26 ) ) | ( !bit & 0x1 ) << 26; + + // Set diffbit + thumbTW1 = ( thumbTW1 & ~0x2 ) | 0x2; + thumbTW2 = thumbT59W2; +} + +// During search it is not convenient to store the bits the way they are stored in the +// file format. Hence, after search, it is converted to this format. +// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved. +static inline void stuff58bits( unsigned int thumbH58W1, unsigned int thumbH58W2, unsigned int& thumbHW1, unsigned int& thumbHW2 ) +{ + // Put bits in twotimer configuration for 58 (red doesn't overflow, green does) + // + // Go from this bit layout: + // + // + // |63 62 61 60 59 58|57 56 55 54|53 52 51 50|49 48 47 46|45 44 43 42|41 40 39 38|37 36 35 34|33 32| + // |-------empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|d2 d1| + // + // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00| + // |---------------------------------------index bits----------------------------------------------| + // + // To this: + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // ----------------------------------------------------------------------------------------------- + // |//|R0 |G0 |// // //|G0|B0|//|B0b |R1 |G1 |B0 |d2|df|d1| + // ----------------------------------------------------------------------------------------------- + // + // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00| + // |---------------------------------------index bits----------------------------------------------| + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // ----------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |df|fp| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bt|bt| + // ----------------------------------------------------------------------------------------------- + // + // + // Thus, what we are really doing is going from this bit layout: + // + // + // |63 62 61 60 59 58|57 56 55 54 53 52 51|50 49|48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33|32 | + // |-------empty-----|part0---------------|part1|part2------------------------------------------|part3| + // + // To this: + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------| + // |//|part0 |// // //|part1|//|part2 |df|part3| + // --------------------------------------------------------------------------------------------------| + + unsigned int part0, part1, part2, part3; + uint8_t bit, a, b, c, d, bits; + + // move parts + part0 = ( thumbH58W1 >> 19 ) & 0x7f; + part1 = ( thumbH58W1 >> 17 ) & 0x3; + part2 = ( thumbH58W1 >> 1 ) & 0xffff; + part3 = thumbH58W1 & 0x1; + thumbHW1 = 0; + thumbHW1 = ( thumbHW1 & ~( 0x7f << 24 ) ) | ( ( part0 & 0x7f ) << 24 ); + thumbHW1 = ( thumbHW1 & ~( 0x3 << 19 ) ) | ( ( part1 & 0x3 ) << 19 ); + thumbHW1 = ( thumbHW1 & ~( 0xffff << 2 ) ) | ( ( part2 & 0xffff ) << 2 ); + thumbHW1 = ( thumbHW1 & ~0x1 ) | ( part3 & 0x1 ); + + // Make sure that red does not overflow: + bit = ( thumbHW1 >> 30 ) & 0x1; + thumbHW1 = ( thumbHW1 & ~( 0x1 << 31 ) ) | ( ( !bit & 0x1 ) << 31 ); + + // Make sure that green overflows: + a = ( thumbHW1 >> 20 ) & 0x1; + b = ( thumbHW1 >> 19 ) & 0x1; + c = ( thumbHW1 >> 17 ) & 0x1; + d = ( thumbHW1 >> 16 ) & 0x1; + // The following bit abcd bit sequences should be padded with ones: 0111, 1010, 1011, 1101, 1110, 1111 + // The following logical expression checks for the presence of any of those: + bit = ( a & c ) | ( !a & b & c & d ) | ( a & b & !c & d ); + bits = 0xf * bit; + thumbHW1 = ( thumbHW1 & ~( 0x7 << 21 ) ) | ( ( bits & 0x7 ) << 21 ); + thumbHW1 = ( thumbHW1 & ~( 0x1 << 18 ) ) | ( ( !bit & 0x1 ) << 18 ); + + // Set diffbit + thumbHW1 = ( thumbHW1 & ~0x2 ) | 0x2; + thumbHW2 = thumbH58W2; +} + +#if defined __AVX2__ || (defined __ARM_NEON && defined __aarch64__) +static etcpak_force_inline Channels GetChannels( const uint8_t* src ) +{ + Channels ch; #ifdef __AVX2__ __m128i d0 = _mm_loadu_si128( ( (__m128i*)src ) + 0 ); __m128i d1 = _mm_loadu_si128( ( (__m128i*)src ) + 1 ); @@ -2128,30 +2837,10 @@ static etcpak_force_inline void CalculateLuma( const uint8_t* src, Luma& luma ) __m128i b1 = _mm_unpackhi_epi32( rgb2, rgb3 ); // swap channels - __m128i b8 = _mm_unpacklo_epi64( rg0, rg1 ); - __m128i g8 = _mm_unpackhi_epi64( rg0, rg1 ); - __m128i r8 = _mm_unpacklo_epi64( b0, b1 ); - - __m256i b16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( b8 ), _mm256_set1_epi16( 14 ) ); - __m256i g16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( g8 ), _mm256_set1_epi16( 76 ) ); - __m256i r16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( r8 ), _mm256_set1_epi16( 38 ) ); - - __m256i luma_16bit = _mm256_add_epi16( _mm256_add_epi16( g16_luma, r16_luma ), b16_luma ); - __m256i luma_8bit_m256i = _mm256_srli_epi16( luma_16bit, 7 ); - __m128i luma_8bit_lo = _mm256_extractf128_si256( luma_8bit_m256i, 0 ); - __m128i luma_8bit_hi = _mm256_extractf128_si256( luma_8bit_m256i, 1 ); - - static const __m128i interleaving_mask_lo = _mm_set_epi8( 15, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 0 ); - static const __m128i interleaving_mask_hi = _mm_set_epi8( 14, 12, 10, 8, 6, 4, 2, 0, 15, 13, 11, 9, 7, 5, 3, 1 ); - __m128i luma_8bit_lo_moved = _mm_shuffle_epi8( luma_8bit_lo, interleaving_mask_lo ); - __m128i luma_8bit_hi_moved = _mm_shuffle_epi8( luma_8bit_hi, interleaving_mask_hi ); - __m128i luma_8bit = _mm_or_si128( luma_8bit_hi_moved, luma_8bit_lo_moved ); - luma.luma8 = luma_8bit; - - // min/max calculation - luma.min = hMin( luma_8bit, luma.minIdx ) * 0.00392156f; - luma.max = hMax( luma_8bit, luma.maxIdx ) * 0.00392156f; -#elif defined __ARM_NEON + ch.b8 = _mm_unpacklo_epi64( rg0, rg1 ); + ch.g8 = _mm_unpackhi_epi64( rg0, rg1 ); + ch.r8 = _mm_unpacklo_epi64( b0, b1 ); +#elif defined __ARM_NEON && defined __aarch64__ //load pixel data into 4 rows uint8x16_t px0 = vld1q_u8( src + 0 ); uint8x16_t px1 = vld1q_u8( src + 16 ); @@ -2172,12 +2861,48 @@ static etcpak_force_inline void CalculateLuma( const uint8_t* src, Luma& luma ) uint8x16x2_t red = vzipq_u8( rr, uint8x16_t() ); uint8x16x2_t grn = vzipq_u8( gg, uint8x16_t() ); uint8x16x2_t blu = vzipq_u8( bb, uint8x16_t() ); - uint16x8_t red0 = vmulq_n_u16( vreinterpretq_u16_u8( red.val[0] ), 14 ); - uint16x8_t red1 = vmulq_n_u16( vreinterpretq_u16_u8( red.val[1] ), 14 ); - uint16x8_t grn0 = vmulq_n_u16( vreinterpretq_u16_u8( grn.val[0] ), 76 ); - uint16x8_t grn1 = vmulq_n_u16( vreinterpretq_u16_u8( grn.val[1] ), 76 ); - uint16x8_t blu0 = vmulq_n_u16( vreinterpretq_u16_u8( blu.val[0] ), 38 ); - uint16x8_t blu1 = vmulq_n_u16( vreinterpretq_u16_u8( blu.val[1] ), 38 ); + ch.r = red; + ch.b = blu; + ch.g = grn; +#endif + return ch; +} +#endif + +#if defined __AVX2__ || (defined __ARM_NEON && defined __aarch64__) +static etcpak_force_inline void CalculateLuma( Channels& ch, Luma& luma ) +#else +static etcpak_force_inline void CalculateLuma( const uint8_t* src, Luma& luma ) +#endif +{ +#ifdef __AVX2__ + __m256i b16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( ch.b8 ), _mm256_set1_epi16( 14 ) ); + __m256i g16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( ch.g8 ), _mm256_set1_epi16( 76 ) ); + __m256i r16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( ch.r8 ), _mm256_set1_epi16( 38 ) ); + + __m256i luma_16bit = _mm256_add_epi16( _mm256_add_epi16( g16_luma, r16_luma ), b16_luma ); + __m256i luma_8bit_m256i = _mm256_srli_epi16( luma_16bit, 7 ); + __m128i luma_8bit_lo = _mm256_extractf128_si256( luma_8bit_m256i, 0 ); + __m128i luma_8bit_hi = _mm256_extractf128_si256( luma_8bit_m256i, 1 ); + + static const __m128i interleaving_mask_lo = _mm_set_epi8( 15, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 0 ); + static const __m128i interleaving_mask_hi = _mm_set_epi8( 14, 12, 10, 8, 6, 4, 2, 0, 15, 13, 11, 9, 7, 5, 3, 1 ); + __m128i luma_8bit_lo_moved = _mm_shuffle_epi8( luma_8bit_lo, interleaving_mask_lo ); + __m128i luma_8bit_hi_moved = _mm_shuffle_epi8( luma_8bit_hi, interleaving_mask_hi ); + __m128i luma_8bit = _mm_or_si128( luma_8bit_hi_moved, luma_8bit_lo_moved ); + luma.luma8 = luma_8bit; + + // min/max calculation + luma.min = hMin( luma_8bit, luma.minIdx ) * 0.00392156f; + luma.max = hMax( luma_8bit, luma.maxIdx ) * 0.00392156f; +#elif defined __ARM_NEON && defined __aarch64__ + //load pixel data into 4 rows + uint16x8_t red0 = vmulq_n_u16( vreinterpretq_u16_u8( ch.r.val[0] ), 14 ); + uint16x8_t red1 = vmulq_n_u16( vreinterpretq_u16_u8( ch.r.val[1] ), 14 ); + uint16x8_t grn0 = vmulq_n_u16( vreinterpretq_u16_u8( ch.g.val[0] ), 76 ); + uint16x8_t grn1 = vmulq_n_u16( vreinterpretq_u16_u8( ch.g.val[1] ), 76 ); + uint16x8_t blu0 = vmulq_n_u16( vreinterpretq_u16_u8( ch.b.val[0] ), 38 ); + uint16x8_t blu1 = vmulq_n_u16( vreinterpretq_u16_u8( ch.b.val[1] ), 38 ); //calculate luma for rows 0,1 and 2,3 uint16x8_t lum_r01 = vaddq_u16( vaddq_u16( red0, grn0 ), blu0 ); @@ -2253,7 +2978,7 @@ static etcpak_force_inline uint8_t SelectModeETC2( const Luma& luma ) { return ModeTH; } - return 0; + return ModeUndecided; } static etcpak_force_inline uint64_t ProcessRGB_ETC2( const uint8_t* src, bool useHeuristics ) @@ -2267,33 +2992,33 @@ static etcpak_force_inline uint64_t ProcessRGB_ETC2( const uint8_t* src, bool us #endif uint8_t mode = ModeUndecided; + Luma luma; +#ifdef __AVX2__ + Channels ch = GetChannels( src ); if( useHeuristics ) { - Luma luma; - CalculateLuma( src, luma ); + CalculateLuma( ch, luma ); mode = SelectModeETC2( luma ); } -#ifdef __AVX2__ - auto plane = Planar_AVX2( src, mode ); + auto plane = Planar_AVX2( ch, mode, useHeuristics ); if( useHeuristics && mode == ModePlanar ) return plane.plane; - alignas(32) v4i a[8]; - + alignas( 32 ) v4i a[8]; __m128i err0 = PrepareAverages_AVX2( a, plane.sum4 ); // Get index of minimum error (err0) - __m128i err1 = _mm_shuffle_epi32(err0, _MM_SHUFFLE(2, 3, 0, 1)); + __m128i err1 = _mm_shuffle_epi32( err0, _MM_SHUFFLE( 2, 3, 0, 1 ) ); __m128i errMin0 = _mm_min_epu32(err0, err1); - __m128i errMin1 = _mm_shuffle_epi32(errMin0, _MM_SHUFFLE(1, 0, 3, 2)); - __m128i errMin2 = _mm_min_epu32(errMin1, errMin0); + __m128i errMin1 = _mm_shuffle_epi32( errMin0, _MM_SHUFFLE( 1, 0, 3, 2 ) ); + __m128i errMin2 = _mm_min_epu32( errMin1, errMin0 ); - __m128i errMask = _mm_cmpeq_epi32(errMin2, err0); + __m128i errMask = _mm_cmpeq_epi32( errMin2, err0 ); - uint32_t mask = _mm_movemask_epi8(errMask); + uint32_t mask = _mm_movemask_epi8( errMask ); - size_t idx = _bit_scan_forward(mask) >> 2; + size_t idx = _bit_scan_forward( mask ) >> 2; d = EncodeAverages_AVX2( a, idx ); @@ -2309,12 +3034,54 @@ static etcpak_force_inline uint64_t ProcessRGB_ETC2( const uint8_t* src, bool us FindBestFit_2x4_AVX2( terr, tsel, a, idx * 2, src ); } - return EncodeSelectors_AVX2( d, terr, tsel, (idx % 2) == 1, plane.plane, plane.error ); + if( useHeuristics ) + { + if( mode == ModeTH ) + { + uint64_t result = 0; + uint64_t error = 0; + uint32_t compressed[4] = { 0, 0, 0, 0 }; + bool tMode = false; + + error = compressBlockTH( (uint8_t*)src, luma, compressed[0], compressed[1], tMode, ch.r8, ch.g8, ch.b8 ); + if( tMode ) + { + stuff59bits( compressed[0], compressed[1], compressed[2], compressed[3] ); + } + else + { + stuff58bits( compressed[0], compressed[1], compressed[2], compressed[3] ); + } + + result = (uint32_t)_bswap( compressed[2] ); + result |= static_cast<uint64_t>( _bswap( compressed[3] ) ) << 32; + + plane.plane = result; + plane.error = error; + } + else + { + plane.plane = 0; + plane.error = MaxError; + } + } + + return EncodeSelectors_AVX2( d, terr, tsel, ( idx % 2 ) == 1, plane.plane, plane.error ); #else + if( useHeuristics ) + { +#if defined __ARM_NEON && defined __aarch64__ + Channels ch = GetChannels( src ); + CalculateLuma( ch, luma ); +#else + CalculateLuma( src, luma ); +#endif + mode = SelectModeETC2( luma ); + } #ifdef __ARM_NEON - auto result = Planar_NEON( src, mode ); + auto result = Planar_NEON( src, mode, useHeuristics ); #else - auto result = Planar( src, mode ); + auto result = Planar( src, mode, useHeuristics ); #endif if( result.second == 0 ) return result.first; @@ -2333,6 +3100,33 @@ static etcpak_force_inline uint64_t ProcessRGB_ETC2( const uint8_t* src, bool us auto id = g_id[idx]; FindBestFit( terr, tsel, a, id, src ); + if( useHeuristics ) + { + if( mode == ModeTH ) + { + uint32_t compressed[4] = { 0, 0, 0, 0 }; + bool tMode = false; + + result.second = compressBlockTH( (uint8_t*)src, luma, compressed[0], compressed[1], tMode ); + if( tMode ) + { + stuff59bits( compressed[0], compressed[1], compressed[2], compressed[3] ); + } + else + { + stuff58bits( compressed[0], compressed[1], compressed[2], compressed[3] ); + } + + result.first = (uint32_t)_bswap( compressed[2] ); + result.first |= static_cast<uint64_t>( _bswap( compressed[3] ) ) << 32; + } + else + { + result.first = 0; + result.second = MaxError; + } + } + return EncodeSelectors( d, terr, tsel, id, result.first, result.second ); #endif } diff --git a/thirdparty/freetype/include/freetype/config/ftconfig.h b/thirdparty/freetype/include/freetype/config/ftconfig.h index 65effcbe63..c696e900a6 100644 --- a/thirdparty/freetype/include/freetype/config/ftconfig.h +++ b/thirdparty/freetype/include/freetype/config/ftconfig.h @@ -4,7 +4,7 @@ * * ANSI-specific configuration file (specification only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/config/ftheader.h b/thirdparty/freetype/include/freetype/config/ftheader.h index e46d314e33..a8c6833df7 100644 --- a/thirdparty/freetype/include/freetype/config/ftheader.h +++ b/thirdparty/freetype/include/freetype/config/ftheader.h @@ -4,7 +4,7 @@ * * Build macros of the FreeType 2 library. * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -777,6 +777,18 @@ #define FT_COLOR_H <freetype/ftcolor.h> + /************************************************************************** + * + * @macro: + * FT_OTSVG_H + * + * @description: + * A macro used in `#include` statements to name the file containing the + * FreeType~2 API which handles the OpenType 'SVG~' glyphs. + */ +#define FT_OTSVG_H <freetype/otsvg.h> + + /* */ /* These header files don't need to be included by the user. */ diff --git a/thirdparty/freetype/include/freetype/config/ftmodule.h b/thirdparty/freetype/include/freetype/config/ftmodule.h index d4ba3f784d..b315baba8a 100644 --- a/thirdparty/freetype/include/freetype/config/ftmodule.h +++ b/thirdparty/freetype/include/freetype/config/ftmodule.h @@ -28,5 +28,6 @@ FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) FT_USE_MODULE( FT_Renderer_Class, ft_sdf_renderer_class ) FT_USE_MODULE( FT_Renderer_Class, ft_bitmap_sdf_renderer_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_svg_renderer_class ) /* EOF */ diff --git a/thirdparty/freetype/include/freetype/config/ftoption.h b/thirdparty/freetype/include/freetype/config/ftoption.h index 4227fd376e..c5bde243b1 100644 --- a/thirdparty/freetype/include/freetype/config/ftoption.h +++ b/thirdparty/freetype/include/freetype/config/ftoption.h @@ -4,7 +4,7 @@ * * User-selectable configuration macros (specification only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -219,6 +219,10 @@ FT_BEGIN_HEADER * If you use a build system like cmake or the `configure` script, * options set by those programs have precedence, overwriting the value * here with the configured one. + * + * If you use the GNU make build system directly (that is, without the + * `configure` script) and you define this macro, you also have to pass + * `SYSTEM_ZLIB=yes` as an argument to make. */ /* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */ @@ -525,6 +529,20 @@ FT_BEGIN_HEADER /************************************************************************** * + * OpenType SVG Glyph Support + * + * Setting this macro enables support for OpenType SVG glyphs. By + * default, FreeType can only fetch SVG documents. However, it can also + * render them if external rendering hook functions are plugged in at + * runtime. + * + * More details on the hooks can be found in file `otsvg.h`. + */ +#define FT_CONFIG_OPTION_SVG + + + /************************************************************************** + * * Error Strings * * If this macro is set, `FT_Error_String` will return meaningful @@ -1002,8 +1020,8 @@ FT_BEGIN_HEADER #error "Invalid CFF darkening parameters!" #endif -FT_END_HEADER +FT_END_HEADER #endif /* FTOPTION_H_ */ diff --git a/thirdparty/freetype/include/freetype/config/ftstdlib.h b/thirdparty/freetype/include/freetype/config/ftstdlib.h index 6ee412a074..7958c2a5f7 100644 --- a/thirdparty/freetype/include/freetype/config/ftstdlib.h +++ b/thirdparty/freetype/include/freetype/config/ftstdlib.h @@ -5,7 +5,7 @@ * ANSI-specific library and header configuration file (specification * only). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/config/integer-types.h b/thirdparty/freetype/include/freetype/config/integer-types.h index 5ef09f1978..d9d2638d1e 100644 --- a/thirdparty/freetype/include/freetype/config/integer-types.h +++ b/thirdparty/freetype/include/freetype/config/integer-types.h @@ -4,7 +4,7 @@ * * FreeType integer types definitions. * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -221,9 +221,10 @@ #define FT_INT64 __int64 #define FT_UINT64 unsigned __int64 -#elif defined( __WATCOMC__ ) /* Watcom C++ */ +#elif defined( __WATCOMC__ ) && __WATCOMC__ >= 1100 /* Watcom C++ */ - /* Watcom doesn't provide 64-bit data types */ +#define FT_INT64 long long int +#define FT_UINT64 unsigned long long int #elif defined( __MWERKS__ ) /* Metrowerks CodeWarrior */ diff --git a/thirdparty/freetype/include/freetype/config/mac-support.h b/thirdparty/freetype/include/freetype/config/mac-support.h index ef58d8b3f0..e42c9fe410 100644 --- a/thirdparty/freetype/include/freetype/config/mac-support.h +++ b/thirdparty/freetype/include/freetype/config/mac-support.h @@ -4,7 +4,7 @@ * * Mac/OS X support configuration header. * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/config/public-macros.h b/thirdparty/freetype/include/freetype/config/public-macros.h index 9fbb3274a0..0074134f1d 100644 --- a/thirdparty/freetype/include/freetype/config/public-macros.h +++ b/thirdparty/freetype/include/freetype/config/public-macros.h @@ -4,7 +4,7 @@ * * Define a set of compiler macros used in public FreeType headers. * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/freetype.h b/thirdparty/freetype/include/freetype/freetype.h index f6c66b94ae..aa1a4fe389 100644 --- a/thirdparty/freetype/include/freetype/freetype.h +++ b/thirdparty/freetype/include/freetype/freetype.h @@ -4,7 +4,7 @@ * * FreeType high-level API and common types (specification only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -153,6 +153,9 @@ FT_BEGIN_HEADER * FT_FACE_FLAG_GLYPH_NAMES * FT_FACE_FLAG_EXTERNAL_STREAM * FT_FACE_FLAG_HINTER + * FT_FACE_FLAG_SVG + * FT_FACE_FLAG_SBIX + * FT_FACE_FLAG_SBIX_OVERLAY * * FT_HAS_HORIZONTAL * FT_HAS_VERTICAL @@ -161,6 +164,9 @@ FT_BEGIN_HEADER * FT_HAS_GLYPH_NAMES * FT_HAS_COLOR * FT_HAS_MULTIPLE_MASTERS + * FT_HAS_SVG + * FT_HAS_SBIX + * FT_HAS_SBIX_OVERLAY * * FT_IS_SFNT * FT_IS_SCALABLE @@ -225,6 +231,7 @@ FT_BEGIN_HEADER * FT_LOAD_NO_SCALE * FT_LOAD_NO_HINTING * FT_LOAD_NO_BITMAP + * FT_LOAD_SBITS_ONLY * FT_LOAD_NO_AUTOHINT * FT_LOAD_COLOR * @@ -522,13 +529,15 @@ FT_BEGIN_HEADER * size. * * @note: - * An @FT_Face has one _active_ @FT_Size object that is used by functions - * like @FT_Load_Glyph to determine the scaling transformation that in - * turn is used to load and hint glyphs and metrics. + * An @FT_Face has one _active_ `FT_Size` object that is used by + * functions like @FT_Load_Glyph to determine the scaling transformation + * that in turn is used to load and hint glyphs and metrics. * - * You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, @FT_Request_Size + * A newly created `FT_Size` object contains only meaningless zero values. + * You must use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, @FT_Request_Size * or even @FT_Select_Size to change the content (i.e., the scaling - * values) of the active @FT_Size. + * values) of the active `FT_Size`. Otherwise, the scaling and hinting + * will not be performed. * * You can use @FT_New_Size to create additional size objects for a given * @FT_Face, but they won't be used by other functions until you activate @@ -1228,6 +1237,19 @@ FT_BEGIN_HEADER * altered with @FT_Set_MM_Design_Coordinates, * @FT_Set_Var_Design_Coordinates, or @FT_Set_Var_Blend_Coordinates. * This flag is unset by a call to @FT_Set_Named_Instance. + * + * FT_FACE_FLAG_SVG :: + * [Since 2.12] The face has an 'SVG~' OpenType table. + * + * FT_FACE_FLAG_SBIX :: + * [Since 2.12] The face has an 'sbix' OpenType table *and* outlines. + * For such fonts, @FT_FACE_FLAG_SCALABLE is not set by default to + * retain backward compatibility. + * + * FT_FACE_FLAG_SBIX_OVERLAY :: + * [Since 2.12] The face has an 'sbix' OpenType table where outlines + * should be drawn on top of bitmap strikes. + * */ #define FT_FACE_FLAG_SCALABLE ( 1L << 0 ) #define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 ) @@ -1245,6 +1267,9 @@ FT_BEGIN_HEADER #define FT_FACE_FLAG_TRICKY ( 1L << 13 ) #define FT_FACE_FLAG_COLOR ( 1L << 14 ) #define FT_FACE_FLAG_VARIATION ( 1L << 15 ) +#define FT_FACE_FLAG_SVG ( 1L << 16 ) +#define FT_FACE_FLAG_SBIX ( 1L << 17 ) +#define FT_FACE_FLAG_SBIX_OVERLAY ( 1L << 18 ) /************************************************************************** @@ -1487,6 +1512,124 @@ FT_BEGIN_HEADER /************************************************************************** * + * @macro: + * FT_HAS_SVG + * + * @description: + * A macro that returns true whenever a face object contains an 'SVG~' + * OpenType table. + * + * @since: + * 2.12 + */ +#define FT_HAS_SVG( face ) \ + ( !!( (face)->face_flags & FT_FACE_FLAG_SVG ) ) + + + /************************************************************************** + * + * @macro: + * FT_HAS_SBIX + * + * @description: + * A macro that returns true whenever a face object contains an 'sbix' + * OpenType table *and* outline glyphs. + * + * Currently, FreeType only supports bitmap glyphs in PNG format for this + * table (i.e., JPEG and TIFF formats are unsupported, as are + * Apple-specific formats not part of the OpenType specification). + * + * @note: + * For backward compatibility, a font with an 'sbix' table is treated as + * a bitmap-only face. Using @FT_Open_Face with + * @FT_PARAM_TAG_IGNORE_SBIX, an application can switch off 'sbix' + * handling so that the face is treated as an ordinary outline font with + * scalable outlines. + * + * Here is some pseudo code that roughly illustrates how to implement + * 'sbix' handling according to the OpenType specification. + * + * ``` + * if ( FT_HAS_SBIX( face ) ) + * { + * // open font as a scalable one without sbix handling + * FT_Face face2; + * FT_Parameter param = { FT_PARAM_TAG_IGNORE_SBIX, NULL }; + * FT_Open_Args args = { FT_OPEN_PARAMS | ..., + * ..., + * 1, ¶m }; + * + * + * FT_Open_Face( library, &args, 0, &face2 ); + * + * <sort `face->available_size` as necessary into + * `preferred_sizes`[*]> + * + * for ( i = 0; i < face->num_fixed_sizes; i++ ) + * { + * size = preferred_sizes[i].size; + * + * error = FT_Set_Pixel_Sizes( face, size, size ); + * <error handling omitted> + * + * // check whether we have a glyph in a bitmap strike + * error = FT_Load_Glyph( face, + * glyph_index, + * FT_LOAD_SBITS_ONLY | + * FT_LOAD_BITMAP_METRICS_ONLY ); + * if ( error == FT_Err_Invalid_Argument ) + * continue; + * else if ( error ) + * <other error handling omitted> + * else + * break; + * } + * + * if ( i != face->num_fixed_sizes ) + * <load embedded bitmap with `FT_Load_Glyph`, + * scale it, display it, etc.> + * + * if ( i == face->num_fixed_sizes || + * FT_HAS_SBIX_OVERLAY( face ) ) + * <use `face2` to load outline glyph with `FT_Load_Glyph`, + * scale it, display it on top of the bitmap, etc.> + * } + * ``` + * + * [*] Assuming a target value of 400dpi and available strike sizes 100, + * 200, 300, and 400dpi, a possible order might be [400, 200, 300, 100]: + * scaling 200dpi to 400dpi usually gives better results than scaling + * 300dpi to 400dpi; it is also much faster. However, scaling 100dpi to + * 400dpi can yield a too pixelated result, thus the preference might be + * 300dpi over 100dpi. + * + * @since: + * 2.12 + */ +#define FT_HAS_SBIX( face ) \ + ( !!( (face)->face_flags & FT_FACE_FLAG_SBIX ) ) + + + /************************************************************************** + * + * @macro: + * FT_HAS_SBIX_OVERLAY + * + * @description: + * A macro that returns true whenever a face object contains an 'sbix' + * OpenType table with bit~1 in its `flags` field set, instructing the + * application to overlay the bitmap strike with the corresponding + * outline glyph. See @FT_HAS_SBIX for pseudo code how to use it. + * + * @since: + * 2.12 + */ +#define FT_HAS_SBIX_OVERLAY( face ) \ + ( !!( (face)->face_flags & FT_FACE_FLAG_SBIX_OVERLAY ) ) + + + /************************************************************************** + * * @enum: * FT_STYLE_FLAG_XXX * @@ -2702,8 +2845,8 @@ FT_BEGIN_HEADER * 'https://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html'. * * Contrary to @FT_Set_Char_Size, this function doesn't have special code - * to normalize zero-valued widths, heights, or resolutions (which lead - * to errors in most cases). + * to normalize zero-valued widths, heights, or resolutions, which are + * treated as @FT_LOAD_NO_SCALE. * * Don't use this function if you are using the FreeType cache API. */ @@ -2819,7 +2962,7 @@ FT_BEGIN_HEADER * * load_flags :: * A flag indicating what to load for this glyph. The @FT_LOAD_XXX - * constants can be used to control the glyph loading process (e.g., + * flags can be used to control the glyph loading process (e.g., * whether the outline should be scaled, whether to load bitmaps or * not, whether to hint the outline, etc). * @@ -2827,8 +2970,10 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: - * The loaded glyph may be transformed. See @FT_Set_Transform for the - * details. + * For proper scaling and hinting, the active @FT_Size object owned by + * the face has to be meaningfully initialized by calling + * @FT_Set_Char_Size before this function, for example. The loaded + * glyph may be transformed. See @FT_Set_Transform for the details. * * For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument` is returned * for invalid CID values (this is, for CID values that don't have a @@ -2918,6 +3063,8 @@ FT_BEGIN_HEADER * * FT_LOAD_NO_SCALE :: * Don't scale the loaded outline glyph but keep it in font units. + * This flag is also assumed if @FT_Size owned by the face was not + * properly initialized. * * This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and * unsets @FT_LOAD_RENDER. @@ -2948,6 +3095,15 @@ FT_BEGIN_HEADER * * @FT_LOAD_NO_SCALE always sets this flag. * + * FT_LOAD_SBITS_ONLY :: + * [Since 2.12] This is the opposite of @FT_LOAD_NO_BITMAP, more or + * less: @FT_Load_Glyph returns `FT_Err_Invalid_Argument` if the face + * contains a bitmap strike for the given size (or the strike selected + * by @FT_Select_Size) but there is no glyph in the strike. + * + * Note that this load flag was part of FreeType since version 2.0.6 + * but previously tagged as internal. + * * FT_LOAD_VERTICAL_LAYOUT :: * Load the glyph for vertical text layout. In particular, the * `advance` value in the @FT_GlyphSlotRec structure is set to the @@ -3004,21 +3160,31 @@ FT_BEGIN_HEADER * Disable the auto-hinter. See also the note below. * * FT_LOAD_COLOR :: - * Load colored glyphs. There are slight differences depending on the - * font format. - * - * [Since 2.5] Load embedded color bitmap images. The resulting color - * bitmaps, if available, will have the @FT_PIXEL_MODE_BGRA format, - * with pre-multiplied color channels. If the flag is not set and - * color bitmaps are found, they are converted to 256-level gray - * bitmaps, using the @FT_PIXEL_MODE_GRAY format. - * - * [Since 2.10, experimental] If the glyph index contains an entry in + * Load colored glyphs. FreeType searches in the following order; + * there are slight differences depending on the font format. + * + * [Since 2.5] Load embedded color bitmap images (provided + * @FT_LOAD_NO_BITMAP is not set). The resulting color bitmaps, if + * available, have the @FT_PIXEL_MODE_BGRA format, with pre-multiplied + * color channels. If the flag is not set and color bitmaps are found, + * they are converted to 256-level gray bitmaps, using the + * @FT_PIXEL_MODE_GRAY format. + * + * [Since 2.12] If the glyph index maps to an entry in the face's + * 'SVG~' table, load the associated SVG document from this table and + * set the `format` field of @FT_GlyphSlotRec to @FT_GLYPH_FORMAT_SVG. + * Note that FreeType itself can't render SVG documents; however, the + * library provides hooks to seamlessly integrate an external renderer. + * See sections @ot_svg_driver and @svg_fonts for more. + * + * [Since 2.10, experimental] If the glyph index maps to an entry in * the face's 'COLR' table with a 'CPAL' palette table (as defined in * the OpenType specification), make @FT_Render_Glyph provide a default * blending of the color glyph layers associated with the glyph index, * using the same bitmap format as embedded color bitmap images. This - * is mainly for convenience; for full control of color layers use + * is mainly for convenience and works only for glyphs in 'COLR' v0 + * tables (or glyphs in 'COLR' v1 tables that exclusively use v0 + * features). For full control of color layers use * @FT_Get_Color_Glyph_Layer and FreeType's color functions like * @FT_Palette_Select instead of setting @FT_LOAD_COLOR for rendering * so that the client application can handle blending by itself. @@ -3069,19 +3235,20 @@ FT_BEGIN_HEADER * */ #define FT_LOAD_DEFAULT 0x0 -#define FT_LOAD_NO_SCALE ( 1L << 0 ) -#define FT_LOAD_NO_HINTING ( 1L << 1 ) -#define FT_LOAD_RENDER ( 1L << 2 ) -#define FT_LOAD_NO_BITMAP ( 1L << 3 ) -#define FT_LOAD_VERTICAL_LAYOUT ( 1L << 4 ) -#define FT_LOAD_FORCE_AUTOHINT ( 1L << 5 ) -#define FT_LOAD_CROP_BITMAP ( 1L << 6 ) -#define FT_LOAD_PEDANTIC ( 1L << 7 ) -#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ( 1L << 9 ) +#define FT_LOAD_NO_SCALE ( 1L << 0 ) +#define FT_LOAD_NO_HINTING ( 1L << 1 ) +#define FT_LOAD_RENDER ( 1L << 2 ) +#define FT_LOAD_NO_BITMAP ( 1L << 3 ) +#define FT_LOAD_VERTICAL_LAYOUT ( 1L << 4 ) +#define FT_LOAD_FORCE_AUTOHINT ( 1L << 5 ) +#define FT_LOAD_CROP_BITMAP ( 1L << 6 ) +#define FT_LOAD_PEDANTIC ( 1L << 7 ) +#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ( 1L << 9 ) #define FT_LOAD_NO_RECURSE ( 1L << 10 ) #define FT_LOAD_IGNORE_TRANSFORM ( 1L << 11 ) #define FT_LOAD_MONOCHROME ( 1L << 12 ) #define FT_LOAD_LINEAR_DESIGN ( 1L << 13 ) +#define FT_LOAD_SBITS_ONLY ( 1L << 14 ) #define FT_LOAD_NO_AUTOHINT ( 1L << 15 ) /* Bits 16-19 are used by `FT_LOAD_TARGET_` */ #define FT_LOAD_COLOR ( 1L << 20 ) @@ -3091,8 +3258,8 @@ FT_BEGIN_HEADER /* */ /* used internally only by certain font drivers */ -#define FT_LOAD_ADVANCE_ONLY ( 1L << 8 ) -#define FT_LOAD_SBITS_ONLY ( 1L << 14 ) +#define FT_LOAD_ADVANCE_ONLY ( 1L << 8 ) +#define FT_LOAD_SVG_ONLY ( 1L << 23 ) /************************************************************************** @@ -3370,6 +3537,44 @@ FT_BEGIN_HEADER * } * * ``` + * + * FreeType has two rasterizers for generating SDF, namely: + * + * 1. `sdf` for generating SDF directly from glyph's outline, and + * + * 2. `bsdf` for generating SDF from rasterized bitmaps. + * + * Depending on the glyph type (i.e., outline or bitmap), one of the two + * rasterizers is chosen at runtime and used for generating SDFs. To + * force the use of `bsdf` you should render the glyph with any of the + * FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and + * then re-render with `FT_RENDER_MODE_SDF`. + * + * There are some issues with stability and possible failures of the SDF + * renderers (specifically `sdf`). + * + * 1. The `sdf` rasterizer is sensitive to really small features (e.g., + * sharp turns that are less than 1~pixel) and imperfections in the + * glyph's outline, causing artifacts in the final output. + * + * 2. The `sdf` rasterizer has limited support for handling intersecting + * contours and *cannot* handle self-intersecting contours whatsoever. + * Self-intersection happens when a single connected contour intersect + * itself at some point; having these in your font definitely pose a + * problem to the rasterizer and cause artifacts, too. + * + * 3. Generating SDF for really small glyphs may result in undesirable + * output; the pixel grid (which stores distance information) becomes + * too coarse. + * + * 4. Since the output buffer is normalized, precision at smaller spreads + * is greater than precision at larger spread values because the + * output range of [0..255] gets mapped to a smaller SDF range. A + * spread of~2 should be sufficient in most cases. + * + * Points (1) and (2) can be avoided by using the `bsdf` rasterizer, + * which is more stable than the `sdf` rasterizer in general. + * */ typedef enum FT_Render_Mode_ { @@ -3410,7 +3615,7 @@ FT_BEGIN_HEADER * @FT_Render_Mode for a list of possible values. * * If @FT_RENDER_MODE_NORMAL is used, a previous call of @FT_Load_Glyph - * with flag @FT_LOAD_COLOR makes FT_Render_Glyph provide a default + * with flag @FT_LOAD_COLOR makes `FT_Render_Glyph` provide a default * blending of colored glyph layers associated with the current glyph * slot (provided the font contains such layers) instead of rendering * the glyph slot's outline. This is an experimental feature; see @@ -3420,9 +3625,6 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: - * To get meaningful results, font scaling values must be set with - * functions like @FT_Set_Char_Size before calling `FT_Render_Glyph`. - * * When FreeType outputs a bitmap of a glyph, it really outputs an alpha * coverage map. If a pixel is completely covered by a filled-in * outline, the bitmap contains 0xFF at that pixel, meaning that @@ -4739,7 +4941,7 @@ FT_BEGIN_HEADER * */ #define FREETYPE_MAJOR 2 -#define FREETYPE_MINOR 11 +#define FREETYPE_MINOR 12 #define FREETYPE_PATCH 1 diff --git a/thirdparty/freetype/include/freetype/ftadvanc.h b/thirdparty/freetype/include/freetype/ftadvanc.h index 3a13bd3de4..8ce4846668 100644 --- a/thirdparty/freetype/include/freetype/ftadvanc.h +++ b/thirdparty/freetype/include/freetype/ftadvanc.h @@ -4,7 +4,7 @@ * * Quick computation of advance widths (specification only). * - * Copyright (C) 2008-2021 by + * Copyright (C) 2008-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftbbox.h b/thirdparty/freetype/include/freetype/ftbbox.h index 713aedb15f..768478f399 100644 --- a/thirdparty/freetype/include/freetype/ftbbox.h +++ b/thirdparty/freetype/include/freetype/ftbbox.h @@ -4,7 +4,7 @@ * * FreeType exact bbox computation (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftbdf.h b/thirdparty/freetype/include/freetype/ftbdf.h index c428506405..04d6094f75 100644 --- a/thirdparty/freetype/include/freetype/ftbdf.h +++ b/thirdparty/freetype/include/freetype/ftbdf.h @@ -4,7 +4,7 @@ * * FreeType API for accessing BDF-specific strings (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftbitmap.h b/thirdparty/freetype/include/freetype/ftbitmap.h index 11c45b0ed2..c3462dadc5 100644 --- a/thirdparty/freetype/include/freetype/ftbitmap.h +++ b/thirdparty/freetype/include/freetype/ftbitmap.h @@ -4,7 +4,7 @@ * * FreeType utility functions for bitmaps (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftbzip2.h b/thirdparty/freetype/include/freetype/ftbzip2.h index afd2a82afb..c85305806f 100644 --- a/thirdparty/freetype/include/freetype/ftbzip2.h +++ b/thirdparty/freetype/include/freetype/ftbzip2.h @@ -4,7 +4,7 @@ * * Bzip2-compressed stream support. * - * Copyright (C) 2010-2021 by + * Copyright (C) 2010-2022 by * Joel Klinghed. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftcache.h b/thirdparty/freetype/include/freetype/ftcache.h index 70399a328a..ecbbd7b8fb 100644 --- a/thirdparty/freetype/include/freetype/ftcache.h +++ b/thirdparty/freetype/include/freetype/ftcache.h @@ -4,7 +4,7 @@ * * FreeType Cache subsystem (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftchapters.h b/thirdparty/freetype/include/freetype/ftchapters.h index 4f32cc88c8..6a9733ad7c 100644 --- a/thirdparty/freetype/include/freetype/ftchapters.h +++ b/thirdparty/freetype/include/freetype/ftchapters.h @@ -62,6 +62,7 @@ * cid_fonts * pfr_fonts * winfnt_fonts + * svg_fonts * font_formats * gasp_table * @@ -82,6 +83,7 @@ * t1_cid_driver * tt_driver * pcf_driver + * ot_svg_driver * properties * parameter_tags * lcd_rendering diff --git a/thirdparty/freetype/include/freetype/ftcid.h b/thirdparty/freetype/include/freetype/ftcid.h index 9a415bd98b..d80108387a 100644 --- a/thirdparty/freetype/include/freetype/ftcid.h +++ b/thirdparty/freetype/include/freetype/ftcid.h @@ -4,7 +4,7 @@ * * FreeType API for accessing CID font information (specification). * - * Copyright (C) 2007-2021 by + * Copyright (C) 2007-2022 by * Dereg Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftcolor.h b/thirdparty/freetype/include/freetype/ftcolor.h index 08dbac0ccc..3edaee4ec1 100644 --- a/thirdparty/freetype/include/freetype/ftcolor.h +++ b/thirdparty/freetype/include/freetype/ftcolor.h @@ -4,7 +4,7 @@ * * FreeType's glyph color management (specification). * - * Copyright (C) 2018-2021 by + * Copyright (C) 2018-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -528,14 +528,14 @@ FT_BEGIN_HEADER * @fields: * num_color_stops :: * The number of color stops for the requested glyph index. Set by - * @FT_Get_Colorline_Stops. + * @FT_Get_Paint. * * current_color_stop :: * The current color stop. Set by @FT_Get_Colorline_Stops. * * p :: - * An opaque pointer into 'COLR' table data. The caller must set this - * to `NULL` before the first call of @FT_Get_Colorline_Stops. + * An opaque pointer into 'COLR' table data. Set by @FT_Get_Paint. + * Updated by @FT_Get_Colorline_Stops. * * @since: * 2.11 -- **currently experimental only!** There might be changes diff --git a/thirdparty/freetype/include/freetype/ftdriver.h b/thirdparty/freetype/include/freetype/ftdriver.h index 4936639056..0dc91e8b40 100644 --- a/thirdparty/freetype/include/freetype/ftdriver.h +++ b/thirdparty/freetype/include/freetype/ftdriver.h @@ -4,7 +4,7 @@ * * FreeType API for controlling driver modules (specification only). * - * Copyright (C) 2017-2021 by + * Copyright (C) 2017-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -212,16 +212,14 @@ FT_BEGIN_HEADER * @description: * While FreeType's TrueType driver doesn't expose API functions by * itself, it is possible to control its behaviour with @FT_Property_Set - * and @FT_Property_Get. The following lists the available properties - * together with the necessary macros and structures. - * - * The TrueType driver's module name is 'truetype'. + * and @FT_Property_Get. * - * A single property @interpreter-version is available, as documented in - * the @properties section. + * The TrueType driver's module name is 'truetype'; a single property + * @interpreter-version is available, as documented in the @properties + * section. * - * We start with a list of definitions, kindly provided by Greg - * Hitchcock. + * To help understand the differences between interpreter versions, we + * introduce a list of definitions, kindly provided by Greg Hitchcock. * * _Bi-Level Rendering_ * @@ -303,6 +301,31 @@ FT_BEGIN_HEADER /************************************************************************** * * @section: + * ot_svg_driver + * + * @title: + * The SVG driver + * + * @abstract: + * Controlling the external rendering of OT-SVG glyphs. + * + * @description: + * By default, FreeType can only load the 'SVG~' table of OpenType fonts + * if configuration macro `FT_CONFIG_OPTION_SVG` is defined. To make it + * render SVG glyphs, an external SVG rendering library is needed. All + * details on the interface between FreeType and the external library + * via function hooks can be found in section @svg_fonts. + * + * The OT-SVG driver's module name is 'ot-svg'; it supports a single + * property called @svg-hooks, documented below in the @properties + * section. + * + */ + + + /************************************************************************** + * + * @section: * properties * * @title: @@ -801,6 +824,40 @@ FT_BEGIN_HEADER /************************************************************************** * * @property: + * svg-hooks + * + * @description: + * Set up the interface between FreeType and an extern SVG rendering + * library like 'librsvg'. All details on the function hooks can be + * found in section @svg_fonts. + * + * @example: + * The following example code expects that the four hook functions + * `svg_*` are defined elsewhere. Error handling is omitted, too. + * + * ``` + * FT_Library library; + * SVG_RendererHooks hooks = { + * (SVG_Lib_Init_Func)svg_init, + * (SVG_Lib_Free_Func)svg_free, + * (SVG_Lib_Render_Func)svg_render, + * (SVG_Lib_Preset_Slot_Func)svg_preset_slot }; + * + * + * FT_Init_FreeType( &library ); + * + * FT_Property_Set( library, "ot-svg", + * "svg-hooks", &hooks ); + * ``` + * + * @since: + * 2.12 + */ + + + /************************************************************************** + * + * @property: * glyph-to-script-map * * @description: diff --git a/thirdparty/freetype/include/freetype/fterrdef.h b/thirdparty/freetype/include/freetype/fterrdef.h index 6e9c4ccb97..a3acfce430 100644 --- a/thirdparty/freetype/include/freetype/fterrdef.h +++ b/thirdparty/freetype/include/freetype/fterrdef.h @@ -4,7 +4,7 @@ * * FreeType error codes (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -101,6 +101,8 @@ "too many hints" ) FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, "invalid pixel size" ) + FT_ERRORDEF_( Invalid_SVG_Document, 0x18, + "invalid SVG document" ) /* handle errors */ @@ -234,6 +236,8 @@ "found FDEF or IDEF opcode in glyf bytecode" ) FT_ERRORDEF_( Missing_Bitmap, 0x9D, "missing bitmap in strike" ) + FT_ERRORDEF_( Missing_SVG_Hooks, 0x9E, + "SVG hooks have not been set" ) /* CFF, CID, and Type 1 errors */ diff --git a/thirdparty/freetype/include/freetype/fterrors.h b/thirdparty/freetype/include/freetype/fterrors.h index 151941dde0..ff1b375d7d 100644 --- a/thirdparty/freetype/include/freetype/fterrors.h +++ b/thirdparty/freetype/include/freetype/fterrors.h @@ -4,7 +4,7 @@ * * FreeType error code handling (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftfntfmt.h b/thirdparty/freetype/include/freetype/ftfntfmt.h index 8e68a4a3ac..77d553578b 100644 --- a/thirdparty/freetype/include/freetype/ftfntfmt.h +++ b/thirdparty/freetype/include/freetype/ftfntfmt.h @@ -4,7 +4,7 @@ * * Support functions for font formats. * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftgasp.h b/thirdparty/freetype/include/freetype/ftgasp.h index 76c45eb3b1..d4ab9b32db 100644 --- a/thirdparty/freetype/include/freetype/ftgasp.h +++ b/thirdparty/freetype/include/freetype/ftgasp.h @@ -4,7 +4,7 @@ * * Access of TrueType's 'gasp' table (specification). * - * Copyright (C) 2007-2021 by + * Copyright (C) 2007-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftglyph.h b/thirdparty/freetype/include/freetype/ftglyph.h index 26b32ed6be..6b77bd3d2a 100644 --- a/thirdparty/freetype/include/freetype/ftglyph.h +++ b/thirdparty/freetype/include/freetype/ftglyph.h @@ -4,7 +4,7 @@ * * FreeType convenience functions to handle glyphs (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -126,7 +126,7 @@ FT_BEGIN_HEADER * * @description: * A handle to an object used to model a bitmap glyph image. This is a - * sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. + * 'sub-class' of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. */ typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph; @@ -142,7 +142,7 @@ FT_BEGIN_HEADER * * @fields: * root :: - * The root @FT_Glyph fields. + * The root fields of @FT_Glyph. * * left :: * The left-side bearing, i.e., the horizontal distance from the @@ -181,7 +181,7 @@ FT_BEGIN_HEADER * * @description: * A handle to an object used to model an outline glyph image. This is a - * sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. + * 'sub-class' of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. */ typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph; @@ -224,6 +224,92 @@ FT_BEGIN_HEADER /************************************************************************** * + * @type: + * FT_SvgGlyph + * + * @description: + * A handle to an object used to model an SVG glyph. This is a + * 'sub-class' of @FT_Glyph, and a pointer to @FT_SvgGlyphRec. + * + * @since: + * 2.12 + */ + typedef struct FT_SvgGlyphRec_* FT_SvgGlyph; + + + /************************************************************************** + * + * @struct: + * FT_SvgGlyphRec + * + * @description: + * A structure used for OT-SVG glyphs. This is a 'sub-class' of + * @FT_GlyphRec. + * + * @fields: + * root :: + * The root @FT_GlyphRec fields. + * + * svg_document :: + * A pointer to the SVG document. + * + * svg_document_length :: + * The length of `svg_document`. + * + * glyph_index :: + * The index of the glyph to be rendered. + * + * metrics :: + * A metrics object storing the size information. + * + * units_per_EM :: + * The size of the EM square. + * + * start_glyph_id :: + * The first glyph ID in the glyph range covered by this document. + * + * end_glyph_id :: + * The last glyph ID in the glyph range covered by this document. + * + * transform :: + * A 2x2 transformation matrix to apply to the glyph while rendering + * it. + * + * delta :: + * Translation to apply to the glyph while rendering. + * + * @note: + * The Glyph Management API requires @FT_Glyph or its 'sub-class' to have + * all the information needed to completely define the glyph's rendering. + * Outline-based glyphs can directly apply transformations to the outline + * but this is not possible for an SVG document that hasn't been parsed. + * Therefore, the transformation is stored along with the document. In + * the absence of a 'ViewBox' or 'Width'/'Height' attribute, the size of + * the ViewPort should be assumed to be 'units_per_EM'. + */ + typedef struct FT_SvgGlyphRec_ + { + FT_GlyphRec root; + + FT_Byte* svg_document; + FT_ULong svg_document_length; + + FT_UInt glyph_index; + + FT_Size_Metrics metrics; + FT_UShort units_per_EM; + + FT_UShort start_glyph_id; + FT_UShort end_glyph_id; + + FT_Matrix transform; + FT_Vector delta; + + } FT_SvgGlyphRec; + + + /************************************************************************** + * * @function: * FT_New_Glyph * @@ -498,9 +584,9 @@ FT_BEGIN_HEADER * The glyph image is translated with the `origin` vector before * rendering. * - * The first parameter is a pointer to an @FT_Glyph handle, that will be + * The first parameter is a pointer to an @FT_Glyph handle that will be * _replaced_ by this function (with newly allocated data). Typically, - * you would use (omitting error handling): + * you would do something like the following (omitting error handling). * * ``` * FT_Glyph glyph; @@ -517,7 +603,7 @@ FT_BEGIN_HEADER * if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) * { * error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, - * 0, 1 ); + * 0, 1 ); * if ( error ) // `glyph' unchanged * ... * } @@ -532,7 +618,7 @@ FT_BEGIN_HEADER * FT_Done_Glyph( glyph ); * ``` * - * Here is another example, again without error handling: + * Here is another example, again without error handling. * * ``` * FT_Glyph glyphs[MAX_GLYPHS] diff --git a/thirdparty/freetype/include/freetype/ftgxval.h b/thirdparty/freetype/include/freetype/ftgxval.h index 21bbbde2ae..2d3f382acf 100644 --- a/thirdparty/freetype/include/freetype/ftgxval.h +++ b/thirdparty/freetype/include/freetype/ftgxval.h @@ -4,7 +4,7 @@ * * FreeType API for validating TrueTypeGX/AAT tables (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * Masatake YAMATO, Redhat K.K, * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/include/freetype/ftgzip.h b/thirdparty/freetype/include/freetype/ftgzip.h index ba82baba64..0880290f9e 100644 --- a/thirdparty/freetype/include/freetype/ftgzip.h +++ b/thirdparty/freetype/include/freetype/ftgzip.h @@ -4,7 +4,7 @@ * * Gzip-compressed stream support. * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftimage.h b/thirdparty/freetype/include/freetype/ftimage.h index 88533b8409..7f2d721cdc 100644 --- a/thirdparty/freetype/include/freetype/ftimage.h +++ b/thirdparty/freetype/include/freetype/ftimage.h @@ -5,7 +5,7 @@ * FreeType glyph image formats and default raster interface * (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -401,11 +401,11 @@ FT_BEGIN_HEADER * information. * * FT_OUTLINE_OVERLAP :: - * This flag indicates that this outline contains overlapping contrours - * and the anti-aliased renderer should perform oversampling to - * mitigate possible artifacts. This flag should _not_ be set for - * well designed glyphs without overlaps because it quadruples the - * rendering time. + * [Since 2.10.3] This flag indicates that this outline contains + * overlapping contours and the anti-aliased renderer should perform + * oversampling to mitigate possible artifacts. This flag should _not_ + * be set for well designed glyphs without overlaps because it quadruples + * the rendering time. * * FT_OUTLINE_HIGH_PRECISION :: * This flag indicates that the scan-line converter should try to @@ -741,6 +741,10 @@ FT_BEGIN_HEADER * contours. Some Type~1 fonts, like those in the Hershey family, * contain glyphs in this format. These are described as @FT_Outline, * but FreeType isn't currently capable of rendering them correctly. + * + * FT_GLYPH_FORMAT_SVG :: + * [Since 2.12] The glyph is represented by an SVG document in the + * 'SVG~' table. */ typedef enum FT_Glyph_Format_ { @@ -749,7 +753,8 @@ FT_BEGIN_HEADER FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ), FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ), FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ), - FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' ) + FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' ), + FT_IMAGE_TAG( FT_GLYPH_FORMAT_SVG, 'S', 'V', 'G', ' ' ) } FT_Glyph_Format; diff --git a/thirdparty/freetype/include/freetype/ftincrem.h b/thirdparty/freetype/include/freetype/ftincrem.h index 229b947bd8..3b3d93c2d3 100644 --- a/thirdparty/freetype/include/freetype/ftincrem.h +++ b/thirdparty/freetype/include/freetype/ftincrem.h @@ -4,7 +4,7 @@ * * FreeType incremental loading (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftlcdfil.h b/thirdparty/freetype/include/freetype/ftlcdfil.h index 18e2544175..c767c6cb48 100644 --- a/thirdparty/freetype/include/freetype/ftlcdfil.h +++ b/thirdparty/freetype/include/freetype/ftlcdfil.h @@ -5,7 +5,7 @@ * FreeType API for color filtering of subpixel bitmap glyphs * (specification). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftlist.h b/thirdparty/freetype/include/freetype/ftlist.h index 55f015977a..4dca2bf163 100644 --- a/thirdparty/freetype/include/freetype/ftlist.h +++ b/thirdparty/freetype/include/freetype/ftlist.h @@ -4,7 +4,7 @@ * * Generic list support for FreeType (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftlogging.h b/thirdparty/freetype/include/freetype/ftlogging.h index a558b85faf..7213dc30a8 100644 --- a/thirdparty/freetype/include/freetype/ftlogging.h +++ b/thirdparty/freetype/include/freetype/ftlogging.h @@ -4,7 +4,7 @@ * * Additional debugging APIs. * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftlzw.h b/thirdparty/freetype/include/freetype/ftlzw.h index fce1c9c4bb..3d7cfd52f7 100644 --- a/thirdparty/freetype/include/freetype/ftlzw.h +++ b/thirdparty/freetype/include/freetype/ftlzw.h @@ -4,7 +4,7 @@ * * LZW-compressed stream support. * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftmac.h b/thirdparty/freetype/include/freetype/ftmac.h index 607af9b589..3dd61d0fe1 100644 --- a/thirdparty/freetype/include/freetype/ftmac.h +++ b/thirdparty/freetype/include/freetype/ftmac.h @@ -4,7 +4,7 @@ * * Additional Mac-specific API. * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftmm.h b/thirdparty/freetype/include/freetype/ftmm.h index 32579e997f..c74ce618cb 100644 --- a/thirdparty/freetype/include/freetype/ftmm.h +++ b/thirdparty/freetype/include/freetype/ftmm.h @@ -4,7 +4,7 @@ * * FreeType Multiple Master font interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -47,6 +47,9 @@ FT_BEGIN_HEADER * MM fonts, others will work with all three types. They are similar * enough that a consistent interface makes sense. * + * For Adobe MM fonts, macro @FT_IS_SFNT returns false. For GX and + * OpenType variation fonts, it returns true. + * */ diff --git a/thirdparty/freetype/include/freetype/ftmodapi.h b/thirdparty/freetype/include/freetype/ftmodapi.h index b77d356de9..b78db724c7 100644 --- a/thirdparty/freetype/include/freetype/ftmodapi.h +++ b/thirdparty/freetype/include/freetype/ftmodapi.h @@ -4,7 +4,7 @@ * * FreeType modules public interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftmoderr.h b/thirdparty/freetype/include/freetype/ftmoderr.h index b417cd5ab7..88d2917771 100644 --- a/thirdparty/freetype/include/freetype/ftmoderr.h +++ b/thirdparty/freetype/include/freetype/ftmoderr.h @@ -4,7 +4,7 @@ * * FreeType module error offsets (specification). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftotval.h b/thirdparty/freetype/include/freetype/ftotval.h index 00f9727859..172fcf2402 100644 --- a/thirdparty/freetype/include/freetype/ftotval.h +++ b/thirdparty/freetype/include/freetype/ftotval.h @@ -4,7 +4,7 @@ * * FreeType API for validating OpenType tables (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftoutln.h b/thirdparty/freetype/include/freetype/ftoutln.h index 6bb5f809a9..46ebf9371b 100644 --- a/thirdparty/freetype/include/freetype/ftoutln.h +++ b/thirdparty/freetype/include/freetype/ftoutln.h @@ -5,7 +5,7 @@ * Support for the FT_Outline type used to store glyph shapes of * most scalable font formats (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -109,11 +109,13 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: - * A contour that contains a single point only is represented by a 'move - * to' operation followed by 'line to' to the same point. In most cases, - * it is best to filter this out before using the outline for stroking - * purposes (otherwise it would result in a visible dot when round caps - * are used). + * Degenerate contours, segments, and Bezier arcs may be reported. In + * most cases, it is best to filter these out before using the outline + * for stroking or other path modification purposes (which may cause + * degenerate segments to become non-degenrate and visible, like when + * stroke caps are used or the path is otherwise outset). Some glyph + * outlines may contain deliberate degenerate single points for mark + * attachement. * * Similarly, the function returns success for an empty outline also * (doing nothing, this is, not calling any emitter); if necessary, you diff --git a/thirdparty/freetype/include/freetype/ftparams.h b/thirdparty/freetype/include/freetype/ftparams.h index 04a3f44126..72080f396a 100644 --- a/thirdparty/freetype/include/freetype/ftparams.h +++ b/thirdparty/freetype/include/freetype/ftparams.h @@ -4,7 +4,7 @@ * * FreeType API for possible FT_Parameter tags (specification only). * - * Copyright (C) 2017-2021 by + * Copyright (C) 2017-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -115,6 +115,21 @@ FT_BEGIN_HEADER /************************************************************************** * * @enum: + * FT_PARAM_TAG_IGNORE_SBIX + * + * @description: + * A tag for @FT_Parameter to make @FT_Open_Face ignore an 'sbix' table + * while loading a font. Use this if @FT_FACE_FLAG_SBIX is set and you + * want to access the outline glyphs in the font. + * + */ +#define FT_PARAM_TAG_IGNORE_SBIX \ + FT_MAKE_TAG( 'i', 's', 'b', 'x' ) + + + /************************************************************************** + * + * @enum: * FT_PARAM_TAG_LCD_FILTER_WEIGHTS * * @description: diff --git a/thirdparty/freetype/include/freetype/ftpfr.h b/thirdparty/freetype/include/freetype/ftpfr.h index fbdb14c202..428e327061 100644 --- a/thirdparty/freetype/include/freetype/ftpfr.h +++ b/thirdparty/freetype/include/freetype/ftpfr.h @@ -4,7 +4,7 @@ * * FreeType API for accessing PFR-specific data (specification only). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftrender.h b/thirdparty/freetype/include/freetype/ftrender.h index 48d489d496..0fab3f8c2a 100644 --- a/thirdparty/freetype/include/freetype/ftrender.h +++ b/thirdparty/freetype/include/freetype/ftrender.h @@ -4,7 +4,7 @@ * * FreeType renderer modules public interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftsizes.h b/thirdparty/freetype/include/freetype/ftsizes.h index 22366393b8..e30938d862 100644 --- a/thirdparty/freetype/include/freetype/ftsizes.h +++ b/thirdparty/freetype/include/freetype/ftsizes.h @@ -4,7 +4,7 @@ * * FreeType size objects management (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftsnames.h b/thirdparty/freetype/include/freetype/ftsnames.h index c7f6581cb3..384096a585 100644 --- a/thirdparty/freetype/include/freetype/ftsnames.h +++ b/thirdparty/freetype/include/freetype/ftsnames.h @@ -7,7 +7,7 @@ * * This is _not_ used to retrieve glyph names! * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftstroke.h b/thirdparty/freetype/include/freetype/ftstroke.h index 88b2a8a4ed..12c006d3fb 100644 --- a/thirdparty/freetype/include/freetype/ftstroke.h +++ b/thirdparty/freetype/include/freetype/ftstroke.h @@ -4,7 +4,7 @@ * * FreeType path stroker (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftsynth.h b/thirdparty/freetype/include/freetype/ftsynth.h index 861dcb5ac5..afc40b1d84 100644 --- a/thirdparty/freetype/include/freetype/ftsynth.h +++ b/thirdparty/freetype/include/freetype/ftsynth.h @@ -5,7 +5,7 @@ * FreeType synthesizing code for emboldening and slanting * (specification). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftsystem.h b/thirdparty/freetype/include/freetype/ftsystem.h index e5abb85a85..5f8aec7b7c 100644 --- a/thirdparty/freetype/include/freetype/ftsystem.h +++ b/thirdparty/freetype/include/freetype/ftsystem.h @@ -4,7 +4,7 @@ * * FreeType low-level system interface definition (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/fttrigon.h b/thirdparty/freetype/include/freetype/fttrigon.h index dbe7b0d388..4e8d871dec 100644 --- a/thirdparty/freetype/include/freetype/fttrigon.h +++ b/thirdparty/freetype/include/freetype/fttrigon.h @@ -4,7 +4,7 @@ * * FreeType trigonometric functions (specification). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/fttypes.h b/thirdparty/freetype/include/freetype/fttypes.h index 699bd003c0..29f32fbb26 100644 --- a/thirdparty/freetype/include/freetype/fttypes.h +++ b/thirdparty/freetype/include/freetype/fttypes.h @@ -4,7 +4,7 @@ * * FreeType simple types definitions (specification only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/ftwinfnt.h b/thirdparty/freetype/include/freetype/ftwinfnt.h index f30f447d84..294f85ae0d 100644 --- a/thirdparty/freetype/include/freetype/ftwinfnt.h +++ b/thirdparty/freetype/include/freetype/ftwinfnt.h @@ -4,7 +4,7 @@ * * FreeType API for accessing Windows fnt-specific data. * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/autohint.h b/thirdparty/freetype/include/freetype/internal/autohint.h index 01585f5edf..aedf48984d 100644 --- a/thirdparty/freetype/include/freetype/internal/autohint.h +++ b/thirdparty/freetype/include/freetype/internal/autohint.h @@ -4,7 +4,7 @@ * * High-level 'autohint' module-specific interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/cffotypes.h b/thirdparty/freetype/include/freetype/internal/cffotypes.h index a91dd556ca..700f586c41 100644 --- a/thirdparty/freetype/include/freetype/internal/cffotypes.h +++ b/thirdparty/freetype/include/freetype/internal/cffotypes.h @@ -4,7 +4,7 @@ * * Basic OpenType/CFF object type definitions (specification). * - * Copyright (C) 2017-2021 by + * Copyright (C) 2017-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/cfftypes.h b/thirdparty/freetype/include/freetype/internal/cfftypes.h index 99e8d41368..23d26c1b34 100644 --- a/thirdparty/freetype/include/freetype/internal/cfftypes.h +++ b/thirdparty/freetype/include/freetype/internal/cfftypes.h @@ -5,7 +5,7 @@ * Basic OpenType/CFF type definitions and interface (specification * only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/compiler-macros.h b/thirdparty/freetype/include/freetype/internal/compiler-macros.h index d8b61b3dc9..66fa13c3c5 100644 --- a/thirdparty/freetype/include/freetype/internal/compiler-macros.h +++ b/thirdparty/freetype/include/freetype/internal/compiler-macros.h @@ -4,7 +4,7 @@ * * Compiler-specific macro definitions used internally by FreeType. * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -299,10 +299,12 @@ FT_BEGIN_HEADER #define FT_CALLBACK_DEF( x ) static x #endif -#if defined( __i386__ ) +#if defined( __GNUC__ ) && defined( __i386__ ) #define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __attribute__(( cdecl )) -#elif defined( _M_IX86 ) +#elif defined( _MSC_VER ) && defined( _M_IX86 ) #define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __cdecl +#elif defined( __WATCOMC__ ) && __WATCOMC__ >= 1240 +#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __watcall #else #define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) #endif diff --git a/thirdparty/freetype/include/freetype/internal/ftcalc.h b/thirdparty/freetype/include/freetype/internal/ftcalc.h index f88e055318..e6a87db94e 100644 --- a/thirdparty/freetype/include/freetype/internal/ftcalc.h +++ b/thirdparty/freetype/include/freetype/internal/ftcalc.h @@ -4,7 +4,7 @@ * * Arithmetic computations (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -408,6 +408,19 @@ FT_BEGIN_HEADER #endif +#elif defined( __WATCOMC__ ) && defined( __386__ ) + + extern __inline FT_Int32 + FT_MSB_i386( FT_UInt32 x ); + +#pragma aux FT_MSB_i386 = \ + "bsr eax, eax" \ + parm [eax] nomemory \ + value [eax] \ + modify exact [eax] nomemory; + +#define FT_MSB( x ) FT_MSB_i386( x ) + #elif defined( __DECC ) || defined( __DECCXX ) #include <builtins.h> diff --git a/thirdparty/freetype/include/freetype/internal/ftdebug.h b/thirdparty/freetype/include/freetype/internal/ftdebug.h index 5e8d9294a2..f05b1395cb 100644 --- a/thirdparty/freetype/include/freetype/internal/ftdebug.h +++ b/thirdparty/freetype/include/freetype/internal/ftdebug.h @@ -4,7 +4,7 @@ * * Debugging and logging component (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/ftdrv.h b/thirdparty/freetype/include/freetype/internal/ftdrv.h index 0db323d5ab..9459a9a190 100644 --- a/thirdparty/freetype/include/freetype/internal/ftdrv.h +++ b/thirdparty/freetype/include/freetype/internal/ftdrv.h @@ -4,7 +4,7 @@ * * FreeType internal font driver interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/ftgloadr.h b/thirdparty/freetype/include/freetype/internal/ftgloadr.h index fea931c3aa..f73b6631c8 100644 --- a/thirdparty/freetype/include/freetype/internal/ftgloadr.h +++ b/thirdparty/freetype/include/freetype/internal/ftgloadr.h @@ -4,7 +4,7 @@ * * The FreeType glyph loader (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/ftmemory.h b/thirdparty/freetype/include/freetype/internal/ftmemory.h index e20d949696..10d753aa5e 100644 --- a/thirdparty/freetype/include/freetype/internal/ftmemory.h +++ b/thirdparty/freetype/include/freetype/internal/ftmemory.h @@ -4,7 +4,7 @@ * * The FreeType memory management macros (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/ftobjs.h b/thirdparty/freetype/include/freetype/internal/ftobjs.h index e52a26aa06..1c779ceaeb 100644 --- a/thirdparty/freetype/include/freetype/internal/ftobjs.h +++ b/thirdparty/freetype/include/freetype/internal/ftobjs.h @@ -4,7 +4,7 @@ * * The FreeType private base classes (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -418,7 +418,8 @@ FT_BEGIN_HEADER * initializing the glyph slot. */ -#define FT_GLYPH_OWN_BITMAP 0x1U +#define FT_GLYPH_OWN_BITMAP 0x1U +#define FT_GLYPH_OWN_GZIP_SVG 0x2U typedef struct FT_Slot_InternalRec_ { diff --git a/thirdparty/freetype/include/freetype/internal/ftpsprop.h b/thirdparty/freetype/include/freetype/internal/ftpsprop.h index d94d0d7e4b..47373211cb 100644 --- a/thirdparty/freetype/include/freetype/internal/ftpsprop.h +++ b/thirdparty/freetype/include/freetype/internal/ftpsprop.h @@ -4,7 +4,7 @@ * * Get and set properties of PostScript drivers (specification). * - * Copyright (C) 2017-2021 by + * Copyright (C) 2017-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/ftrfork.h b/thirdparty/freetype/include/freetype/internal/ftrfork.h index 1c56d6ceb7..165e67f245 100644 --- a/thirdparty/freetype/include/freetype/internal/ftrfork.h +++ b/thirdparty/freetype/include/freetype/internal/ftrfork.h @@ -4,7 +4,7 @@ * * Embedded resource forks accessor (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * Masatake YAMATO and Redhat K.K. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/ftserv.h b/thirdparty/freetype/include/freetype/internal/ftserv.h index fa82c31fcd..78996d9c85 100644 --- a/thirdparty/freetype/include/freetype/internal/ftserv.h +++ b/thirdparty/freetype/include/freetype/internal/ftserv.h @@ -4,7 +4,7 @@ * * The FreeType services (specification only). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/ftstream.h b/thirdparty/freetype/include/freetype/internal/ftstream.h index 7f3af120c2..aa51fe5a87 100644 --- a/thirdparty/freetype/include/freetype/internal/ftstream.h +++ b/thirdparty/freetype/include/freetype/internal/ftstream.h @@ -4,7 +4,7 @@ * * Stream handling (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/fttrace.h b/thirdparty/freetype/include/freetype/internal/fttrace.h index 3307556bff..43c6a8713b 100644 --- a/thirdparty/freetype/include/freetype/internal/fttrace.h +++ b/thirdparty/freetype/include/freetype/internal/fttrace.h @@ -4,7 +4,7 @@ * * Tracing handling (specification only). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -49,6 +49,9 @@ FT_TRACE_DEF( synth ) /* bold/slant synthesizer (ftsynth.c) */ FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */ FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */ + /* ot-svg module */ +FT_TRACE_DEF( otsvg ) /* OT-SVG renderer (ftsvg.c) */ + /* cache sub-system */ FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */ @@ -61,6 +64,7 @@ FT_TRACE_DEF( ttbdf ) /* TrueType embedded BDF (ttbdf.c) */ FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */ FT_TRACE_DEF( ttcolr ) /* glyph layer table (ttcolr.c) */ FT_TRACE_DEF( ttcpal ) /* color palette table (ttcpal.c) */ +FT_TRACE_DEF( ttsvg ) /* OpenType SVG table (ttsvg.c) */ FT_TRACE_DEF( ttkern ) /* kerning handler (ttkern.c) */ FT_TRACE_DEF( ttload ) /* basic TrueType tables (ttload.c) */ FT_TRACE_DEF( ttmtx ) /* metrics-related tables (ttmtx.c) */ diff --git a/thirdparty/freetype/include/freetype/internal/ftvalid.h b/thirdparty/freetype/include/freetype/internal/ftvalid.h index 7bdfa62f32..171c2cb6f5 100644 --- a/thirdparty/freetype/include/freetype/internal/ftvalid.h +++ b/thirdparty/freetype/include/freetype/internal/ftvalid.h @@ -4,7 +4,7 @@ * * FreeType validation support (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/psaux.h b/thirdparty/freetype/include/freetype/internal/psaux.h index 6c6399aa16..48ec1df963 100644 --- a/thirdparty/freetype/include/freetype/internal/psaux.h +++ b/thirdparty/freetype/include/freetype/internal/psaux.h @@ -5,7 +5,7 @@ * Auxiliary functions and data structures related to PostScript fonts * (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/pshints.h b/thirdparty/freetype/include/freetype/internal/pshints.h index 9dbb0776b0..5de83e4565 100644 --- a/thirdparty/freetype/include/freetype/internal/pshints.h +++ b/thirdparty/freetype/include/freetype/internal/pshints.h @@ -6,7 +6,7 @@ * recorders (specification only). These are used to support native * T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers. * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svbdf.h b/thirdparty/freetype/include/freetype/internal/services/svbdf.h index 879aa61383..06e3b531c8 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svbdf.h +++ b/thirdparty/freetype/include/freetype/internal/services/svbdf.h @@ -4,7 +4,7 @@ * * The FreeType BDF services (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svcfftl.h b/thirdparty/freetype/include/freetype/internal/services/svcfftl.h index f6424e424d..1dea6bcda9 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svcfftl.h +++ b/thirdparty/freetype/include/freetype/internal/services/svcfftl.h @@ -4,7 +4,7 @@ * * The FreeType CFF tables loader service (specification). * - * Copyright (C) 2017-2021 by + * Copyright (C) 2017-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svcid.h b/thirdparty/freetype/include/freetype/internal/services/svcid.h index 7ef5afd0b7..acf9178d0a 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svcid.h +++ b/thirdparty/freetype/include/freetype/internal/services/svcid.h @@ -4,7 +4,7 @@ * * The FreeType CID font services (specification). * - * Copyright (C) 2007-2021 by + * Copyright (C) 2007-2022 by * Derek Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h index cc87fc122d..a7280319c5 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h +++ b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h @@ -4,7 +4,7 @@ * * The FreeType font format service (specification only). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svgldict.h b/thirdparty/freetype/include/freetype/internal/services/svgldict.h index 4256f14a04..489021d897 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svgldict.h +++ b/thirdparty/freetype/include/freetype/internal/services/svgldict.h @@ -4,7 +4,7 @@ * * The FreeType glyph dictionary services (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svgxval.h b/thirdparty/freetype/include/freetype/internal/services/svgxval.h index f36d55602a..59ae411b55 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svgxval.h +++ b/thirdparty/freetype/include/freetype/internal/services/svgxval.h @@ -4,7 +4,7 @@ * * FreeType API for validating TrueTypeGX/AAT tables (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/include/freetype/internal/services/svkern.h b/thirdparty/freetype/include/freetype/internal/services/svkern.h index 99dc2d97a3..c567acad46 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svkern.h +++ b/thirdparty/freetype/include/freetype/internal/services/svkern.h @@ -4,7 +4,7 @@ * * The FreeType Kerning service (specification). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svmetric.h b/thirdparty/freetype/include/freetype/internal/services/svmetric.h index b9c95a7c9c..7accdc46ff 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svmetric.h +++ b/thirdparty/freetype/include/freetype/internal/services/svmetric.h @@ -4,7 +4,7 @@ * * The FreeType services for metrics variations (specification). * - * Copyright (C) 2016-2021 by + * Copyright (C) 2016-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svmm.h b/thirdparty/freetype/include/freetype/internal/services/svmm.h index 8eac3a3fe3..c6394890ac 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svmm.h +++ b/thirdparty/freetype/include/freetype/internal/services/svmm.h @@ -4,7 +4,7 @@ * * The FreeType Multiple Masters and GX var services (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svotval.h b/thirdparty/freetype/include/freetype/internal/services/svotval.h index 7afb49e824..3c72d1f855 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svotval.h +++ b/thirdparty/freetype/include/freetype/internal/services/svotval.h @@ -4,7 +4,7 @@ * * The FreeType OpenType validation service (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svpfr.h b/thirdparty/freetype/include/freetype/internal/services/svpfr.h index 98442bf83d..bde0ed3545 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svpfr.h +++ b/thirdparty/freetype/include/freetype/internal/services/svpfr.h @@ -4,7 +4,7 @@ * * Internal PFR service functions (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svpostnm.h b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h index 5a25c5a58a..05f6291e13 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svpostnm.h +++ b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h @@ -4,7 +4,7 @@ * * The FreeType PostScript name services (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svprop.h b/thirdparty/freetype/include/freetype/internal/services/svprop.h index 9b71000c52..29c568640b 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svprop.h +++ b/thirdparty/freetype/include/freetype/internal/services/svprop.h @@ -4,7 +4,7 @@ * * The FreeType property service (specification). * - * Copyright (C) 2012-2021 by + * Copyright (C) 2012-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svpscmap.h b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h index 346f5e2a7c..7d586587a5 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svpscmap.h +++ b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h @@ -4,7 +4,7 @@ * * The FreeType PostScript charmap service (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h index 49aa4d565d..6e45f3272d 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h +++ b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h @@ -4,7 +4,7 @@ * * The FreeType PostScript info service (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svsfnt.h b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h index 4306cbc1b7..03938a562b 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svsfnt.h +++ b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h @@ -4,7 +4,7 @@ * * The FreeType SFNT table loading service (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svttcmap.h b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h index 775b6bcf20..a0b1bbd2f3 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svttcmap.h +++ b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h @@ -4,7 +4,7 @@ * * The FreeType TrueType/sfnt cmap extra information service. * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * Masatake YAMATO, Redhat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/include/freetype/internal/services/svtteng.h b/thirdparty/freetype/include/freetype/internal/services/svtteng.h index 964934284d..f8396eb08c 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svtteng.h +++ b/thirdparty/freetype/include/freetype/internal/services/svtteng.h @@ -4,7 +4,7 @@ * * The FreeType TrueType engine query service (specification). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svttglyf.h b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h index 4268467b75..982630c0aa 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svttglyf.h +++ b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h @@ -4,7 +4,7 @@ * * The FreeType TrueType glyph service. * - * Copyright (C) 2007-2021 by + * Copyright (C) 2007-2022 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h index aa70aa44db..950f4a8824 100644 --- a/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h +++ b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h @@ -4,7 +4,7 @@ * * The FreeType Windows FNT/FONT service (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/sfnt.h b/thirdparty/freetype/include/freetype/internal/sfnt.h index bf4c7e09fe..c67b47e860 100644 --- a/thirdparty/freetype/include/freetype/internal/sfnt.h +++ b/thirdparty/freetype/include/freetype/internal/sfnt.h @@ -4,7 +4,7 @@ * * High-level 'sfnt' driver interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -314,6 +314,33 @@ FT_BEGIN_HEADER /************************************************************************** * * @functype: + * TT_Load_Svg_Doc_Func + * + * @description: + * Scan the SVG document list to find the document containing the glyph + * that has the ID 'glyph*XXX*', where *XXX* is the value of + * `glyph_index` as a decimal integer. + * + * @inout: + * glyph :: + * The glyph slot from which pointers to the SVG document list is to be + * grabbed. The results are stored back in the slot. + * + * @input: + * glyph_index :: + * The index of the glyph that is to be looked up. + * + * @return: + * FreeType error code. 0 means success. + */ + typedef FT_Error + (*TT_Load_Svg_Doc_Func)( FT_GlyphSlot glyph, + FT_UInt glyph_index ); + + + /************************************************************************** + * + * @functype: * TT_Set_SBit_Strike_Func * * @description: @@ -946,6 +973,11 @@ FT_BEGIN_HEADER TT_Get_Name_Func get_name; TT_Get_Name_ID_Func get_name_id; + /* OpenType SVG Support */ + TT_Load_Table_Func load_svg; + TT_Free_Table_Func free_svg; + TT_Load_Svg_Doc_Func load_svg_doc; + } SFNT_Interface; @@ -997,7 +1029,10 @@ FT_BEGIN_HEADER colr_blend_, \ get_metrics_, \ get_name_, \ - get_name_id_ ) \ + get_name_id_, \ + load_svg_, \ + free_svg_, \ + load_svg_doc_ ) \ static const SFNT_Interface class_ = \ { \ goto_table_, \ @@ -1042,7 +1077,10 @@ FT_BEGIN_HEADER colr_blend_, \ get_metrics_, \ get_name_, \ - get_name_id_ \ + get_name_id_, \ + load_svg_, \ + free_svg_, \ + load_svg_doc_ \ }; diff --git a/thirdparty/freetype/include/freetype/internal/svginterface.h b/thirdparty/freetype/include/freetype/internal/svginterface.h new file mode 100644 index 0000000000..1b325e5e9d --- /dev/null +++ b/thirdparty/freetype/include/freetype/internal/svginterface.h @@ -0,0 +1,46 @@ +/**************************************************************************** + * + * svginterface.h + * + * Interface of ot-svg module (specification only). + * + * Copyright (C) 2022 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef SVGINTERFACE_H_ +#define SVGINTERFACE_H_ + +#include <ft2build.h> +#include <freetype/otsvg.h> + + +FT_BEGIN_HEADER + + typedef FT_Error + (*Preset_Bitmap_Func)( FT_Module module, + FT_GlyphSlot slot, + FT_Bool cache ); + + typedef struct SVG_Interface_ + { + Preset_Bitmap_Func preset_slot; + + } SVG_Interface; + + typedef SVG_Interface* SVG_Service; + +FT_END_HEADER + +#endif /* SVGINTERFACE_H_ */ + + +/* END */ diff --git a/thirdparty/freetype/include/freetype/internal/t1types.h b/thirdparty/freetype/include/freetype/internal/t1types.h index 023c5d08a2..b6a3de14d0 100644 --- a/thirdparty/freetype/include/freetype/internal/t1types.h +++ b/thirdparty/freetype/include/freetype/internal/t1types.h @@ -5,7 +5,7 @@ * Basic Type1/Type2 type definitions and interface (specification * only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/internal/tttypes.h b/thirdparty/freetype/include/freetype/internal/tttypes.h index 651131c8d3..df719387b5 100644 --- a/thirdparty/freetype/include/freetype/internal/tttypes.h +++ b/thirdparty/freetype/include/freetype/internal/tttypes.h @@ -5,7 +5,7 @@ * Basic SFNT/TrueType type definitions and interface (specification * only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -1390,8 +1390,8 @@ FT_BEGIN_HEADER * hdmx_record_size :: * The size of a single hdmx record. * - * hdmx_record_sizes :: - * An array holding the ppem sizes available in the 'hdmx' table. + * hdmx_records :: + * A array of pointers to the 'hdmx' table records sorted by ppem. * * sbit_table :: * A pointer to the font's embedded bitmap location table. @@ -1605,7 +1605,7 @@ FT_BEGIN_HEADER FT_ULong hdmx_table_size; FT_UInt hdmx_record_count; FT_ULong hdmx_record_size; - FT_Byte* hdmx_record_sizes; + FT_Byte** hdmx_records; FT_Byte* sbit_table; FT_ULong sbit_table_size; @@ -1644,6 +1644,9 @@ FT_BEGIN_HEADER void* cpal; void* colr; + /* since 2.12 */ + void* svg; + } TT_FaceRec; @@ -1769,6 +1772,9 @@ FT_BEGIN_HEADER /* since version 2.6.2 */ FT_ListRec composites; + /* since version 2.11.2 */ + FT_Byte* widthp; + } TT_LoaderRec; diff --git a/thirdparty/freetype/include/freetype/internal/wofftypes.h b/thirdparty/freetype/include/freetype/internal/wofftypes.h index c460107c4d..94804fa72f 100644 --- a/thirdparty/freetype/include/freetype/internal/wofftypes.h +++ b/thirdparty/freetype/include/freetype/internal/wofftypes.h @@ -5,7 +5,7 @@ * Basic WOFF/WOFF2 type definitions and interface (specification * only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/otsvg.h b/thirdparty/freetype/include/freetype/otsvg.h new file mode 100644 index 0000000000..2caadfdeeb --- /dev/null +++ b/thirdparty/freetype/include/freetype/otsvg.h @@ -0,0 +1,336 @@ +/**************************************************************************** + * + * otsvg.h + * + * Interface for OT-SVG support related things (specification). + * + * Copyright (C) 2022 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef OTSVG_H_ +#define OTSVG_H_ + +#include <freetype/freetype.h> + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /************************************************************************** + * + * @section: + * svg_fonts + * + * @title: + * OpenType SVG Fonts + * + * @abstract: + * OT-SVG API between FreeType and an external SVG rendering library. + * + * @description: + * This section describes the four hooks necessary to render SVG + * 'documents' that are contained in an OpenType font's 'SVG~' table. + * + * For more information on the implementation, see our standard hooks + * based on 'librsvg' in the [FreeType Demo + * Programs](https://gitlab.freedesktop.org/freetype/freetype-demos) + * repository. + * + */ + + + /************************************************************************** + * + * @functype: + * SVG_Lib_Init_Func + * + * @description: + * A callback that is called when the first OT-SVG glyph is rendered in + * the lifetime of an @FT_Library object. In a typical implementation, + * one would want to allocate a structure and point the `data_pointer` + * to it and perform any library initializations that might be needed. + * + * @inout: + * data_pointer :: + * The SVG rendering module stores a pointer variable that can be used + * by clients to store any data that needs to be shared across + * different hooks. `data_pointer` is essentially a pointer to that + * pointer such that it can be written to as well as read from. + * + * @return: + * FreeType error code. 0 means success. + * + * @since: + * 2.12 + */ + typedef FT_Error + (*SVG_Lib_Init_Func)( FT_Pointer *data_pointer ); + + + /************************************************************************** + * + * @functype: + * SVG_Lib_Free_Func + * + * @description: + * A callback that is called when the `ot-svg` module is being freed. + * It is only called if the init hook was called earlier. This means + * that neither the init nor the free hook is called if no OT-SVG glyph + * is rendered. + * + * In a typical implementation, one would want to free any state + * structure that was allocated in the init hook and perform any + * library-related closure that might be needed. + * + * @inout: + * data_pointer :: + * The SVG rendering module stores a pointer variable that can be used + * by clients to store any data that needs to be shared across + * different hooks. `data_pointer` is essentially a pointer to that + * pointer such that it can be written to as well as read from. + * + * @since: + * 2.12 + */ + typedef void + (*SVG_Lib_Free_Func)( FT_Pointer *data_pointer ); + + + /************************************************************************** + * + * @functype: + * SVG_Lib_Render_Func + * + * @description: + * A callback that is called to render an OT-SVG glyph. This callback + * hook is called right after the preset hook @SVG_Lib_Preset_Slot_Func + * has been called with `cache` set to `TRUE`. The data necessary to + * render is available through the handle @FT_SVG_Document, which is set + * in the `other` field of @FT_GlyphSlotRec. + * + * The render hook is expected to render the SVG glyph to the bitmap + * buffer that is allocated already at `slot->bitmap.buffer`. It also + * sets the `num_grays` value as well as `slot->format`. + * + * @input: + * slot :: + * The slot to render. + * + * @inout: + * data_pointer :: + * The SVG rendering module stores a pointer variable that can be used + * by clients to store any data that needs to be shared across + * different hooks. `data_pointer` is essentially a pointer to that + * pointer such that it can be written to as well as read from. + * + * @return: + * FreeType error code. 0 means success. + * + * @since: + * 2.12 + */ + typedef FT_Error + (*SVG_Lib_Render_Func)( FT_GlyphSlot slot, + FT_Pointer *data_pointer ); + + + /************************************************************************** + * + * @functype: + * SVG_Lib_Preset_Slot_Func + * + * @description: + * A callback that is called to preset the glyph slot. It is called from + * two places. + * + * 1. When `FT_Load_Glyph` needs to preset the glyph slot. + * + * 2. Right before the `svg` module calls the render callback hook. + * + * When it is the former, the argument `cache` is set to `FALSE`. When + * it is the latter, the argument `cache` is set to `TRUE`. This + * distinction has been made because many calculations that are necessary + * for presetting a glyph slot are the same needed later for the render + * callback hook. Thus, if `cache` is `TRUE`, the hook can _cache_ those + * calculations in a memory block referenced by the state pointer. + * + * This hook is expected to preset the slot by setting parameters such as + * `bitmap_left`, `bitmap_top`, `width`, `rows`, `pitch`, and + * `pixel_mode`. It is also expected to set all the metrics for the slot + * including the vertical advance if it is not already set. Typically, + * fonts have horizontal advances but not vertical ones. If those are + * available, they had already been set, otherwise they have to be + * estimated and set manually. The hook must take into account the + * transformations that have been set, and translate the transformation + * matrices into the SVG coordinate system, as the original matrix is + * intended for the TTF/CFF coordinate system. + * + * @input: + * slot :: + * The glyph slot that has the SVG document loaded. + * + * cache :: + * See description. + * + * @inout: + * data_pointer :: + * The SVG rendering module stores a pointer variable that can be used + * by clients to store any data that needs to be shared across + * different hooks. `data_pointer` is essentially a pointer to that + * pointer such that it can be written to as well as read from. + * + * @return: + * FreeType error code. 0 means success. + * + * @since: + * 2.12 + */ + typedef FT_Error + (*SVG_Lib_Preset_Slot_Func)( FT_GlyphSlot slot, + FT_Bool cache, + FT_Pointer *state ); + + + /************************************************************************** + * + * @struct: + * SVG_RendererHooks + * + * @description: + * A structure that stores the four hooks needed to render OT-SVG glyphs + * properly. The structure is publicly used to set the hooks via the + * @svg-hooks driver property. + * + * The behavior of each hook is described in its documentation. One + * thing to note is that the preset hook and the render hook often need + * to do the same operations; therefore, it's better to cache the + * intermediate data in a state structure to avoid calculating it twice. + * For example, in the preset hook one can draw the glyph on a recorder + * surface and later create a bitmap surface from it in the render hook. + * + * All four hooks must be non-NULL. + * + * @fields: + * init_svg :: + * The initialization hook. + * + * free_svg :: + * The cleanup hook. + * + * render_hook :: + * The render hook. + * + * preset_slot :: + * The preset hook. + * + * @since: + * 2.12 + */ + typedef struct SVG_RendererHooks_ + { + SVG_Lib_Init_Func init_svg; + SVG_Lib_Free_Func free_svg; + SVG_Lib_Render_Func render_svg; + + SVG_Lib_Preset_Slot_Func preset_slot; + + } SVG_RendererHooks; + + + /************************************************************************** + * + * @struct: + * FT_SVG_DocumentRec + * + * @description: + * A structure that models one SVG document. + * + * @fields: + * svg_document :: + * A pointer to the SVG document. + * + * svg_document_length :: + * The length of `svg_document`. + * + * metrics :: + * A metrics object storing the size information. + * + * units_per_EM :: + * The size of the EM square. + * + * start_glyph_id :: + * The first glyph ID in the glyph range covered by this document. + * + * end_glyph_id :: + * The last glyph ID in the glyph range covered by this document. + * + * transform :: + * A 2x2 transformation matrix to apply to the glyph while rendering + * it. + * + * delta :: + * The translation to apply to the glyph while rendering. + * + * @note: + * When an @FT_GlyphSlot object `slot` is passed down to a renderer, the + * renderer can only access the `metrics` and `units_per_EM` fields via + * `slot->face`. However, when @FT_Glyph_To_Bitmap sets up a dummy + * object, it has no way to set a `face` object. Thus, metrics + * information and `units_per_EM` (which is necessary for OT-SVG) has to + * be stored separately. + * + * @since: + * 2.12 + */ + typedef struct FT_SVG_DocumentRec_ + { + FT_Byte* svg_document; + FT_ULong svg_document_length; + + FT_Size_Metrics metrics; + FT_UShort units_per_EM; + + FT_UShort start_glyph_id; + FT_UShort end_glyph_id; + + FT_Matrix transform; + FT_Vector delta; + + } FT_SVG_DocumentRec; + + + /************************************************************************** + * + * @type: + * FT_SVG_Document + * + * @description: + * A handle to an @FT_SVG_DocumentRec object. + * + * @since: + * 2.12 + */ + typedef struct FT_SVG_DocumentRec_* FT_SVG_Document; + + +FT_END_HEADER + +#endif /* OTSVG_H_ */ + + +/* END */ diff --git a/thirdparty/freetype/include/freetype/t1tables.h b/thirdparty/freetype/include/freetype/t1tables.h index a5f6ae7210..4068b204a9 100644 --- a/thirdparty/freetype/include/freetype/t1tables.h +++ b/thirdparty/freetype/include/freetype/t1tables.h @@ -5,7 +5,7 @@ * Basic Type 1/Type 2 tables definitions and interface (specification * only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -453,22 +453,22 @@ FT_BEGIN_HEADER /************************************************************************** * * @function: - * FT_Has_PS_Glyph_Names + * FT_Has_PS_Glyph_Names * * @description: - * Return true if a given face provides reliable PostScript glyph names. - * This is similar to using the @FT_HAS_GLYPH_NAMES macro, except that - * certain fonts (mostly TrueType) contain incorrect glyph name tables. + * Return true if a given face provides reliable PostScript glyph names. + * This is similar to using the @FT_HAS_GLYPH_NAMES macro, except that + * certain fonts (mostly TrueType) contain incorrect glyph name tables. * - * When this function returns true, the caller is sure that the glyph - * names returned by @FT_Get_Glyph_Name are reliable. + * When this function returns true, the caller is sure that the glyph + * names returned by @FT_Get_Glyph_Name are reliable. * * @input: - * face :: - * face handle + * face :: + * face handle * * @return: - * Boolean. True if glyph names are reliable. + * Boolean. True if glyph names are reliable. * */ FT_EXPORT( FT_Int ) @@ -478,30 +478,40 @@ FT_BEGIN_HEADER /************************************************************************** * * @function: - * FT_Get_PS_Font_Info + * FT_Get_PS_Font_Info * * @description: - * Retrieve the @PS_FontInfoRec structure corresponding to a given - * PostScript font. + * Retrieve the @PS_FontInfoRec structure corresponding to a given + * PostScript font. * * @input: - * face :: - * PostScript face handle. + * face :: + * PostScript face handle. * * @output: - * afont_info :: - * Output font info structure pointer. + * afont_info :: + * A pointer to a @PS_FontInfoRec object. * * @return: - * FreeType error code. 0~means success. + * FreeType error code. 0~means success. * * @note: - * String pointers within the @PS_FontInfoRec structure are owned by the - * face and don't need to be freed by the caller. Missing entries in - * the font's FontInfo dictionary are represented by `NULL` pointers. + * String pointers within the @PS_FontInfoRec structure are owned by the + * face and don't need to be freed by the caller. Missing entries in the + * font's FontInfo dictionary are represented by `NULL` pointers. + * + * The following font formats support this feature: 'Type~1', 'Type~42', + * 'CFF', 'CID~Type~1'. For other font formats this function returns the + * `FT_Err_Invalid_Argument` error code. * - * If the font's format is not PostScript-based, this function will - * return the `FT_Err_Invalid_Argument` error code. + * @example: + * ``` + * PS_FontInfoRec font_info; + * + * + * error = FT_Get_PS_Font_Info( face, &font_info ); + * ... + * ``` * */ FT_EXPORT( FT_Error ) @@ -512,29 +522,39 @@ FT_BEGIN_HEADER /************************************************************************** * * @function: - * FT_Get_PS_Font_Private + * FT_Get_PS_Font_Private * * @description: - * Retrieve the @PS_PrivateRec structure corresponding to a given - * PostScript font. + * Retrieve the @PS_PrivateRec structure corresponding to a given + * PostScript font. * * @input: - * face :: - * PostScript face handle. + * face :: + * PostScript face handle. * * @output: - * afont_private :: - * Output private dictionary structure pointer. + * afont_private :: + * A pointer to a @PS_PrivateRec object. * * @return: - * FreeType error code. 0~means success. + * FreeType error code. 0~means success. * * @note: - * The string pointers within the @PS_PrivateRec structure are owned by - * the face and don't need to be freed by the caller. + * The string pointers within the @PS_PrivateRec structure are owned by + * the face and don't need to be freed by the caller. * - * If the font's format is not PostScript-based, this function returns - * the `FT_Err_Invalid_Argument` error code. + * Only the 'Type~1' font format supports this feature. For other font + * formats this function returns the `FT_Err_Invalid_Argument` error + * code. + * + * @example: + * ``` + * PS_PrivateRec font_private; + * + * + * error = FT_Get_PS_Font_Private( face, &font_private ); + * ... + * ``` * */ FT_EXPORT( FT_Error ) @@ -693,67 +713,67 @@ FT_BEGIN_HEADER /************************************************************************** * * @function: - * FT_Get_PS_Font_Value + * FT_Get_PS_Font_Value * * @description: - * Retrieve the value for the supplied key from a PostScript font. + * Retrieve the value for the supplied key from a PostScript font. * * @input: - * face :: - * PostScript face handle. + * face :: + * PostScript face handle. * - * key :: - * An enumeration value representing the dictionary key to retrieve. + * key :: + * An enumeration value representing the dictionary key to retrieve. * - * idx :: - * For array values, this specifies the index to be returned. + * idx :: + * For array values, this specifies the index to be returned. * - * value :: - * A pointer to memory into which to write the value. + * value :: + * A pointer to memory into which to write the value. * - * valen_len :: - * The size, in bytes, of the memory supplied for the value. + * valen_len :: + * The size, in bytes, of the memory supplied for the value. * * @output: - * value :: - * The value matching the above key, if it exists. + * value :: + * The value matching the above key, if it exists. * * @return: - * The amount of memory (in bytes) required to hold the requested value - * (if it exists, -1 otherwise). + * The amount of memory (in bytes) required to hold the requested value + * (if it exists, -1 otherwise). * * @note: - * The values returned are not pointers into the internal structures of - * the face, but are 'fresh' copies, so that the memory containing them - * belongs to the calling application. This also enforces the - * 'read-only' nature of these values, i.e., this function cannot be - * used to manipulate the face. + * The values returned are not pointers into the internal structures of + * the face, but are 'fresh' copies, so that the memory containing them + * belongs to the calling application. This also enforces the + * 'read-only' nature of these values, i.e., this function cannot be + * used to manipulate the face. * - * `value` is a void pointer because the values returned can be of - * various types. + * `value` is a void pointer because the values returned can be of + * various types. * - * If either `value` is `NULL` or `value_len` is too small, just the - * required memory size for the requested entry is returned. + * If either `value` is `NULL` or `value_len` is too small, just the + * required memory size for the requested entry is returned. * - * The `idx` parameter is used, not only to retrieve elements of, for - * example, the FontMatrix or FontBBox, but also to retrieve name keys - * from the CharStrings dictionary, and the charstrings themselves. It - * is ignored for atomic values. + * The `idx` parameter is used, not only to retrieve elements of, for + * example, the FontMatrix or FontBBox, but also to retrieve name keys + * from the CharStrings dictionary, and the charstrings themselves. It + * is ignored for atomic values. * - * `PS_DICT_BLUE_SCALE` returns a value that is scaled up by 1000. To - * get the value as in the font stream, you need to divide by 65536000.0 - * (to remove the FT_Fixed scale, and the x1000 scale). + * `PS_DICT_BLUE_SCALE` returns a value that is scaled up by 1000. To + * get the value as in the font stream, you need to divide by 65536000.0 + * (to remove the FT_Fixed scale, and the x1000 scale). * - * IMPORTANT: Only key/value pairs read by the FreeType interpreter can - * be retrieved. So, for example, PostScript procedures such as NP, ND, - * and RD are not available. Arbitrary keys are, obviously, not be - * available either. + * IMPORTANT: Only key/value pairs read by the FreeType interpreter can + * be retrieved. So, for example, PostScript procedures such as NP, ND, + * and RD are not available. Arbitrary keys are, obviously, not be + * available either. * - * If the font's format is not PostScript-based, this function returns - * the `FT_Err_Invalid_Argument` error code. + * If the font's format is not PostScript-based, this function returns + * the `FT_Err_Invalid_Argument` error code. * * @since: - * 2.4.8 + * 2.4.8 * */ FT_EXPORT( FT_Long ) diff --git a/thirdparty/freetype/include/freetype/ttnameid.h b/thirdparty/freetype/include/freetype/ttnameid.h index a09950f542..37b505a05b 100644 --- a/thirdparty/freetype/include/freetype/ttnameid.h +++ b/thirdparty/freetype/include/freetype/ttnameid.h @@ -4,7 +4,7 @@ * * TrueType name ID definitions (specification only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/tttables.h b/thirdparty/freetype/include/freetype/tttables.h index c33d99059d..21664df7b3 100644 --- a/thirdparty/freetype/include/freetype/tttables.h +++ b/thirdparty/freetype/include/freetype/tttables.h @@ -5,7 +5,7 @@ * Basic SFNT/TrueType tables definitions and interface * (specification only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/include/freetype/tttags.h b/thirdparty/freetype/include/freetype/tttags.h index 47ccc6ddf4..8b807641b8 100644 --- a/thirdparty/freetype/include/freetype/tttags.h +++ b/thirdparty/freetype/include/freetype/tttags.h @@ -4,7 +4,7 @@ * * Tags for TrueType and OpenType tables (specification only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -95,6 +95,7 @@ FT_BEGIN_HEADER #define TTAG_sbix FT_MAKE_TAG( 's', 'b', 'i', 'x' ) #define TTAG_sfnt FT_MAKE_TAG( 's', 'f', 'n', 't' ) #define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' ) +#define TTAG_SVG FT_MAKE_TAG( 'S', 'V', 'G', ' ' ) #define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' ) #define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' ) #define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' ) diff --git a/thirdparty/freetype/include/ft2build.h b/thirdparty/freetype/include/ft2build.h index 62686b1b20..2543ac435a 100644 --- a/thirdparty/freetype/include/ft2build.h +++ b/thirdparty/freetype/include/ft2build.h @@ -4,7 +4,7 @@ * * FreeType 2 build and setup macros. * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afblue.c b/thirdparty/freetype/src/autofit/afblue.c index c9e8045c18..b986eb4a13 100644 --- a/thirdparty/freetype/src/autofit/afblue.c +++ b/thirdparty/freetype/src/autofit/afblue.c @@ -7,7 +7,7 @@ * * Auto-fitter data for blue strings (body). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afblue.cin b/thirdparty/freetype/src/autofit/afblue.cin index 071e80b031..f7e27ad8e5 100644 --- a/thirdparty/freetype/src/autofit/afblue.cin +++ b/thirdparty/freetype/src/autofit/afblue.cin @@ -4,7 +4,7 @@ * * Auto-fitter data for blue strings (body). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afblue.dat b/thirdparty/freetype/src/autofit/afblue.dat index 1aa9b26de9..201acc4f6f 100644 --- a/thirdparty/freetype/src/autofit/afblue.dat +++ b/thirdparty/freetype/src/autofit/afblue.dat @@ -2,7 +2,7 @@ // // Auto-fitter data for blue strings. // -// Copyright (C) 2013-2021 by +// Copyright (C) 2013-2022 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afblue.h b/thirdparty/freetype/src/autofit/afblue.h index 311c9e3afd..0e56abb94d 100644 --- a/thirdparty/freetype/src/autofit/afblue.h +++ b/thirdparty/freetype/src/autofit/afblue.h @@ -7,7 +7,7 @@ * * Auto-fitter data for blue strings (specification). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afblue.hin b/thirdparty/freetype/src/autofit/afblue.hin index 5186914937..f9fd5aa3b4 100644 --- a/thirdparty/freetype/src/autofit/afblue.hin +++ b/thirdparty/freetype/src/autofit/afblue.hin @@ -4,7 +4,7 @@ * * Auto-fitter data for blue strings (specification). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afcjk.c b/thirdparty/freetype/src/autofit/afcjk.c index 7e46b6b1ef..1853a17f5c 100644 --- a/thirdparty/freetype/src/autofit/afcjk.c +++ b/thirdparty/freetype/src/autofit/afcjk.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for CJK writing system (body). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -843,7 +843,7 @@ { AF_AxisHints axis = &hints->axis[dim]; AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); AF_Direction major_dir = axis->major_dir; AF_Segment seg1, seg2; FT_Pos len_threshold; @@ -1005,7 +1005,7 @@ AF_CJKAxis laxis = &((AF_CJKMetrics)hints->metrics)->axis[dim]; AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); AF_Segment seg; FT_Fixed scale; @@ -1153,7 +1153,7 @@ */ { AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); AF_Edge edge; @@ -1291,7 +1291,7 @@ { AF_AxisHints axis = &hints->axis[dim]; AF_Edge edge = axis->edges; - AF_Edge edge_limit = edge + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edge, axis->num_edges ); AF_CJKAxis cjk = &metrics->axis[dim]; FT_Fixed scale = cjk->scale; FT_Pos best_dist0; /* initial threshold */ @@ -1798,7 +1798,7 @@ { AF_AxisHints axis = &hints->axis[dim]; AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); FT_PtrDist n_edges; AF_Edge edge; AF_Edge anchor = NULL; @@ -2177,7 +2177,7 @@ { AF_AxisHints axis = & hints->axis[dim]; AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); AF_Edge edge; FT_Bool snapping; diff --git a/thirdparty/freetype/src/autofit/afcjk.h b/thirdparty/freetype/src/autofit/afcjk.h index 58aa298dad..bf948bcec0 100644 --- a/thirdparty/freetype/src/autofit/afcjk.h +++ b/thirdparty/freetype/src/autofit/afcjk.h @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for CJK writing system (specification). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afcover.h b/thirdparty/freetype/src/autofit/afcover.h index c7ae1e9a8a..be71fe39de 100644 --- a/thirdparty/freetype/src/autofit/afcover.h +++ b/thirdparty/freetype/src/autofit/afcover.h @@ -4,7 +4,7 @@ * * Auto-fitter coverages (specification only). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afdummy.c b/thirdparty/freetype/src/autofit/afdummy.c index a36b56f784..5fdbfcfd42 100644 --- a/thirdparty/freetype/src/autofit/afdummy.c +++ b/thirdparty/freetype/src/autofit/afdummy.c @@ -5,7 +5,7 @@ * Auto-fitter dummy routines to be used if no hinting should be * performed (body). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afdummy.h b/thirdparty/freetype/src/autofit/afdummy.h index b58849fe50..4dddbd5215 100644 --- a/thirdparty/freetype/src/autofit/afdummy.h +++ b/thirdparty/freetype/src/autofit/afdummy.h @@ -5,7 +5,7 @@ * Auto-fitter dummy routines to be used if no hinting should be * performed (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/aferrors.h b/thirdparty/freetype/src/autofit/aferrors.h index 09bed66395..d31b1a9c88 100644 --- a/thirdparty/freetype/src/autofit/aferrors.h +++ b/thirdparty/freetype/src/autofit/aferrors.h @@ -4,7 +4,7 @@ * * Autofitter error codes (specification only). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afglobal.c b/thirdparty/freetype/src/autofit/afglobal.c index b805b3b0e5..87a3fbfb0f 100644 --- a/thirdparty/freetype/src/autofit/afglobal.c +++ b/thirdparty/freetype/src/autofit/afglobal.c @@ -4,7 +4,7 @@ * * Auto-fitter routines to compute global hinting values (body). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -337,11 +337,13 @@ /* we allocate an AF_FaceGlobals structure together */ /* with the glyph_styles array */ - if ( FT_ALLOC( globals, - sizeof ( *globals ) + - (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) ) + if ( FT_QALLOC( globals, + sizeof ( *globals ) + + (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) ) goto Exit; + FT_ZERO( &globals->metrics ); + globals->face = face; globals->glyph_count = face->num_glyphs; /* right after the globals structure come the glyph styles */ diff --git a/thirdparty/freetype/src/autofit/afglobal.h b/thirdparty/freetype/src/autofit/afglobal.h index cd97e716c4..f7ebf8d57a 100644 --- a/thirdparty/freetype/src/autofit/afglobal.h +++ b/thirdparty/freetype/src/autofit/afglobal.h @@ -5,7 +5,7 @@ * Auto-fitter routines to compute global hinting values * (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afhints.c b/thirdparty/freetype/src/autofit/afhints.c index 5506afda22..ae7d10528d 100644 --- a/thirdparty/freetype/src/autofit/afhints.c +++ b/thirdparty/freetype/src/autofit/afhints.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines (body). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -1316,7 +1316,7 @@ { AF_AxisHints axis = & hints->axis[dim]; AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); AF_Segment seg; @@ -1393,7 +1393,7 @@ AF_Point point_limit = points + hints->num_points; AF_AxisHints axis = &hints->axis[dim]; AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); FT_UInt touch_flag; diff --git a/thirdparty/freetype/src/autofit/afhints.h b/thirdparty/freetype/src/autofit/afhints.h index 38d2847d71..96001cd80d 100644 --- a/thirdparty/freetype/src/autofit/afhints.h +++ b/thirdparty/freetype/src/autofit/afhints.h @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afindic.c b/thirdparty/freetype/src/autofit/afindic.c index 064c300ed7..5bf0b5f945 100644 --- a/thirdparty/freetype/src/autofit/afindic.c +++ b/thirdparty/freetype/src/autofit/afindic.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for Indic writing system (body). * - * Copyright (C) 2007-2021 by + * Copyright (C) 2007-2022 by * Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afindic.h b/thirdparty/freetype/src/autofit/afindic.h index 3e46724112..59ae11a677 100644 --- a/thirdparty/freetype/src/autofit/afindic.h +++ b/thirdparty/freetype/src/autofit/afindic.h @@ -5,7 +5,7 @@ * Auto-fitter hinting routines for Indic writing system * (specification). * - * Copyright (C) 2007-2021 by + * Copyright (C) 2007-2022 by * Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/aflatin.c b/thirdparty/freetype/src/autofit/aflatin.c index 5e81d771a4..bed0ccee08 100644 --- a/thirdparty/freetype/src/autofit/aflatin.c +++ b/thirdparty/freetype/src/autofit/aflatin.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for latin writing system (body). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -200,7 +200,7 @@ (AF_Dimension)dim ); seg = axhints->segments; - limit = seg + axhints->num_segments; + limit = FT_OFFSET( seg, axhints->num_segments ); for ( ; seg < limit; seg++ ) { @@ -1989,7 +1989,7 @@ { AF_AxisHints axis = &hints->axis[dim]; AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); FT_Pos len_threshold, len_score, dist_score, max_width; AF_Segment seg1, seg2; @@ -2134,7 +2134,7 @@ FT_Bool top_to_bottom_hinting = 0; AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); AF_Segment seg; #if 0 @@ -2500,7 +2500,7 @@ { AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT]; AF_Edge edge = axis->edges; - AF_Edge edge_limit = edge + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edge, axis->num_edges ); AF_LatinAxis latin = &metrics->axis[AF_DIMENSION_VERT]; FT_Fixed scale = latin->scale; @@ -2993,7 +2993,7 @@ { AF_AxisHints axis = &hints->axis[dim]; AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); FT_PtrDist n_edges; AF_Edge edge; AF_Edge anchor = NULL; diff --git a/thirdparty/freetype/src/autofit/aflatin.h b/thirdparty/freetype/src/autofit/aflatin.h index d6b919ef84..facc663450 100644 --- a/thirdparty/freetype/src/autofit/aflatin.h +++ b/thirdparty/freetype/src/autofit/aflatin.h @@ -5,7 +5,7 @@ * Auto-fitter hinting routines for latin writing system * (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afloader.c b/thirdparty/freetype/src/autofit/afloader.c index a06d49ad7e..e55183a509 100644 --- a/thirdparty/freetype/src/autofit/afloader.c +++ b/thirdparty/freetype/src/autofit/afloader.c @@ -4,7 +4,7 @@ * * Auto-fitter glyph loading routines (body). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afloader.h b/thirdparty/freetype/src/autofit/afloader.h index b4936a8722..b345e46395 100644 --- a/thirdparty/freetype/src/autofit/afloader.h +++ b/thirdparty/freetype/src/autofit/afloader.h @@ -4,7 +4,7 @@ * * Auto-fitter glyph loading routines (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afmodule.c b/thirdparty/freetype/src/autofit/afmodule.c index 76f9b3733b..1b14ae682e 100644 --- a/thirdparty/freetype/src/autofit/afmodule.c +++ b/thirdparty/freetype/src/autofit/afmodule.c @@ -4,7 +4,7 @@ * * Auto-fitter module implementation (body). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afmodule.h b/thirdparty/freetype/src/autofit/afmodule.h index c5bd468201..1d1bfaf544 100644 --- a/thirdparty/freetype/src/autofit/afmodule.h +++ b/thirdparty/freetype/src/autofit/afmodule.h @@ -4,7 +4,7 @@ * * Auto-fitter module implementation (specification). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afranges.c b/thirdparty/freetype/src/autofit/afranges.c index e06f182dd0..2de1991a57 100644 --- a/thirdparty/freetype/src/autofit/afranges.c +++ b/thirdparty/freetype/src/autofit/afranges.c @@ -4,7 +4,7 @@ * * Auto-fitter Unicode script ranges (body). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afranges.h b/thirdparty/freetype/src/autofit/afranges.h index 841d630aab..acd01faf68 100644 --- a/thirdparty/freetype/src/autofit/afranges.h +++ b/thirdparty/freetype/src/autofit/afranges.h @@ -4,7 +4,7 @@ * * Auto-fitter Unicode script ranges (specification). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afscript.h b/thirdparty/freetype/src/autofit/afscript.h index af78d573e1..172b598069 100644 --- a/thirdparty/freetype/src/autofit/afscript.h +++ b/thirdparty/freetype/src/autofit/afscript.h @@ -4,7 +4,7 @@ * * Auto-fitter scripts (specification only). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afshaper.c b/thirdparty/freetype/src/autofit/afshaper.c index 5d078937e1..298480d864 100644 --- a/thirdparty/freetype/src/autofit/afshaper.c +++ b/thirdparty/freetype/src/autofit/afshaper.c @@ -4,7 +4,7 @@ * * HarfBuzz interface for accessing OpenType features (body). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afshaper.h b/thirdparty/freetype/src/autofit/afshaper.h index cf3f81342f..558f03bdef 100644 --- a/thirdparty/freetype/src/autofit/afshaper.h +++ b/thirdparty/freetype/src/autofit/afshaper.h @@ -4,7 +4,7 @@ * * HarfBuzz interface for accessing OpenType features (specification). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afstyles.h b/thirdparty/freetype/src/autofit/afstyles.h index 64c808c581..9080b9fb65 100644 --- a/thirdparty/freetype/src/autofit/afstyles.h +++ b/thirdparty/freetype/src/autofit/afstyles.h @@ -4,7 +4,7 @@ * * Auto-fitter styles (specification only). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/aftypes.h b/thirdparty/freetype/src/autofit/aftypes.h index 1d792b9476..754aad7ba4 100644 --- a/thirdparty/freetype/src/autofit/aftypes.h +++ b/thirdparty/freetype/src/autofit/aftypes.h @@ -4,7 +4,7 @@ * * Auto-fitter types (specification only). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afws-decl.h b/thirdparty/freetype/src/autofit/afws-decl.h index c10dd57e7b..c93845ef95 100644 --- a/thirdparty/freetype/src/autofit/afws-decl.h +++ b/thirdparty/freetype/src/autofit/afws-decl.h @@ -4,7 +4,7 @@ * * Auto-fitter writing system declarations (specification only). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/afws-iter.h b/thirdparty/freetype/src/autofit/afws-iter.h index 55714203e3..9cda3509bc 100644 --- a/thirdparty/freetype/src/autofit/afws-iter.h +++ b/thirdparty/freetype/src/autofit/afws-iter.h @@ -4,7 +4,7 @@ * * Auto-fitter writing systems iterator (specification only). * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/autofit/autofit.c b/thirdparty/freetype/src/autofit/autofit.c index 7e692b4de9..3d78a9b335 100644 --- a/thirdparty/freetype/src/autofit/autofit.c +++ b/thirdparty/freetype/src/autofit/autofit.c @@ -4,7 +4,7 @@ * * Auto-fitter module (body). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftadvanc.c b/thirdparty/freetype/src/base/ftadvanc.c index f20b9928aa..fc6b428817 100644 --- a/thirdparty/freetype/src/base/ftadvanc.c +++ b/thirdparty/freetype/src/base/ftadvanc.c @@ -4,7 +4,7 @@ * * Quick computation of advance widths (body). * - * Copyright (C) 2008-2021 by + * Copyright (C) 2008-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftbase.c b/thirdparty/freetype/src/base/ftbase.c index 7366bc46db..cd1056890f 100644 --- a/thirdparty/freetype/src/base/ftbase.c +++ b/thirdparty/freetype/src/base/ftbase.c @@ -4,7 +4,7 @@ * * Single object library component (body only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftbase.h b/thirdparty/freetype/src/base/ftbase.h index 963ff93d68..f873566f22 100644 --- a/thirdparty/freetype/src/base/ftbase.h +++ b/thirdparty/freetype/src/base/ftbase.h @@ -4,7 +4,7 @@ * * Private functions used in the `base' module (specification). * - * Copyright (C) 2008-2021 by + * Copyright (C) 2008-2022 by * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. * * This file is part of the FreeType project, and may only be used, @@ -28,6 +28,7 @@ FT_BEGIN_HEADER FT_DECLARE_GLYPH( ft_bitmap_glyph_class ) FT_DECLARE_GLYPH( ft_outline_glyph_class ) + FT_DECLARE_GLYPH( ft_svg_glyph_class ) #ifdef FT_CONFIG_OPTION_MAC_FONTS diff --git a/thirdparty/freetype/src/base/ftbbox.c b/thirdparty/freetype/src/base/ftbbox.c index 4db29cbf83..30aedf780c 100644 --- a/thirdparty/freetype/src/base/ftbbox.c +++ b/thirdparty/freetype/src/base/ftbbox.c @@ -4,7 +4,7 @@ * * FreeType bbox computation (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used diff --git a/thirdparty/freetype/src/base/ftbdf.c b/thirdparty/freetype/src/base/ftbdf.c index f93ca8eb75..4f22113d7e 100644 --- a/thirdparty/freetype/src/base/ftbdf.c +++ b/thirdparty/freetype/src/base/ftbdf.c @@ -4,7 +4,7 @@ * * FreeType API for accessing BDF-specific strings (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftbitmap.c b/thirdparty/freetype/src/base/ftbitmap.c index 2146d3e364..7825895ad6 100644 --- a/thirdparty/freetype/src/base/ftbitmap.c +++ b/thirdparty/freetype/src/base/ftbitmap.c @@ -4,7 +4,7 @@ * * FreeType utility functions for bitmaps (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -480,7 +480,7 @@ * A gamma of 2.2 is fair to assume. And then, we need to * undo the premultiplication too. * - * https://accessibility.kde.org/hsl-adjusted.php + * http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html#SideNotes * * We do the computation with integers only, applying a gamma of 2.0. * We guarantee 32-bit arithmetic to avoid overflow but the resulting @@ -488,9 +488,9 @@ * */ - l = ( 4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] + - 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] + - 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16; + l = ( 4731UL /* 0.072186 * 65536 */ * bgra[0] * bgra[0] + + 46868UL /* 0.715158 * 65536 */ * bgra[1] * bgra[1] + + 13937UL /* 0.212656 * 65536 */ * bgra[2] * bgra[2] ) >> 16; /* * Final transparency can be determined as follows. diff --git a/thirdparty/freetype/src/base/ftcalc.c b/thirdparty/freetype/src/base/ftcalc.c index 9df8e4010d..6c1e7fbd45 100644 --- a/thirdparty/freetype/src/base/ftcalc.c +++ b/thirdparty/freetype/src/base/ftcalc.c @@ -4,7 +4,7 @@ * * Arithmetic computations (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftcid.c b/thirdparty/freetype/src/base/ftcid.c index 216ee2b3e4..b882ca3de0 100644 --- a/thirdparty/freetype/src/base/ftcid.c +++ b/thirdparty/freetype/src/base/ftcid.c @@ -4,7 +4,7 @@ * * FreeType API for accessing CID font information. * - * Copyright (C) 2007-2021 by + * Copyright (C) 2007-2022 by * Derek Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftcolor.c b/thirdparty/freetype/src/base/ftcolor.c index 3ef3256b20..0edf379b43 100644 --- a/thirdparty/freetype/src/base/ftcolor.c +++ b/thirdparty/freetype/src/base/ftcolor.c @@ -4,7 +4,7 @@ * * FreeType's glyph color management (body). * - * Copyright (C) 2018-2021 by + * Copyright (C) 2018-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftdbgmem.c b/thirdparty/freetype/src/base/ftdbgmem.c index 4f5c1e7697..1df83c404d 100644 --- a/thirdparty/freetype/src/base/ftdbgmem.c +++ b/thirdparty/freetype/src/base/ftdbgmem.c @@ -4,7 +4,7 @@ * * Memory debugger (body). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftdebug.c b/thirdparty/freetype/src/base/ftdebug.c index 3485791306..648fff44ed 100644 --- a/thirdparty/freetype/src/base/ftdebug.c +++ b/thirdparty/freetype/src/base/ftdebug.c @@ -4,7 +4,7 @@ * * Debugging and logging component (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/fterrors.c b/thirdparty/freetype/src/base/fterrors.c index 14649268f8..5846fefc91 100644 --- a/thirdparty/freetype/src/base/fterrors.c +++ b/thirdparty/freetype/src/base/fterrors.c @@ -4,7 +4,7 @@ * * FreeType API for error code handling. * - * Copyright (C) 2018-2021 by + * Copyright (C) 2018-2022 by * Armin Hasitzka, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftfntfmt.c b/thirdparty/freetype/src/base/ftfntfmt.c index 4e1b830190..e69c1e0684 100644 --- a/thirdparty/freetype/src/base/ftfntfmt.c +++ b/thirdparty/freetype/src/base/ftfntfmt.c @@ -4,7 +4,7 @@ * * FreeType utility file for font formats (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftfstype.c b/thirdparty/freetype/src/base/ftfstype.c index 57e904d6f4..009d58c57d 100644 --- a/thirdparty/freetype/src/base/ftfstype.c +++ b/thirdparty/freetype/src/base/ftfstype.c @@ -4,7 +4,7 @@ * * FreeType utility file to access FSType data (body). * - * Copyright (C) 2008-2021 by + * Copyright (C) 2008-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftgasp.c b/thirdparty/freetype/src/base/ftgasp.c index b744f0a465..7567e3077a 100644 --- a/thirdparty/freetype/src/base/ftgasp.c +++ b/thirdparty/freetype/src/base/ftgasp.c @@ -4,7 +4,7 @@ * * Access of TrueType's `gasp' table (body). * - * Copyright (C) 2007-2021 by + * Copyright (C) 2007-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftgloadr.c b/thirdparty/freetype/src/base/ftgloadr.c index 83ce0660ae..f05abdee81 100644 --- a/thirdparty/freetype/src/base/ftgloadr.c +++ b/thirdparty/freetype/src/base/ftgloadr.c @@ -4,7 +4,7 @@ * * The FreeType glyph loader (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftglyph.c b/thirdparty/freetype/src/base/ftglyph.c index e2c6f73f80..571dca1a96 100644 --- a/thirdparty/freetype/src/base/ftglyph.c +++ b/thirdparty/freetype/src/base/ftglyph.c @@ -4,7 +4,7 @@ * * FreeType convenience functions to handle glyphs (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -34,6 +34,7 @@ #include <freetype/ftoutln.h> #include <freetype/ftbitmap.h> #include <freetype/internal/ftobjs.h> +#include <freetype/otsvg.h> #include "ftbase.h" @@ -277,6 +278,240 @@ ) +#ifdef FT_CONFIG_OPTION_SVG + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** FT_SvgGlyph support ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_CALLBACK_DEF( FT_Error ) + ft_svg_glyph_init( FT_Glyph svg_glyph, + FT_GlyphSlot slot ) + { + FT_ULong doc_length; + FT_SVG_Document document; + FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; + + FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_GLYPH( glyph )->library->memory; + + + if ( slot->format != FT_GLYPH_FORMAT_SVG ) + { + error = FT_THROW( Invalid_Glyph_Format ); + goto Exit; + } + + if ( slot->other == NULL ) + { + error = FT_THROW( Invalid_Slot_Handle ); + goto Exit; + } + + document = (FT_SVG_Document)slot->other; + + if ( document->svg_document_length == 0 ) + { + error = FT_THROW( Invalid_Slot_Handle ); + goto Exit; + } + + /* allocate a new document */ + doc_length = document->svg_document_length; + if ( FT_QALLOC( glyph->svg_document, doc_length ) ) + goto Exit; + glyph->svg_document_length = doc_length; + + glyph->glyph_index = slot->glyph_index; + + glyph->metrics = document->metrics; + glyph->units_per_EM = document->units_per_EM; + + glyph->start_glyph_id = document->start_glyph_id; + glyph->end_glyph_id = document->end_glyph_id; + + glyph->transform = document->transform; + glyph->delta = document->delta; + + /* copy the document into glyph */ + FT_MEM_COPY( glyph->svg_document, document->svg_document, doc_length ); + + Exit: + return error; + } + + + FT_CALLBACK_DEF( void ) + ft_svg_glyph_done( FT_Glyph svg_glyph ) + { + FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; + FT_Memory memory = svg_glyph->library->memory; + + + /* just free the memory */ + FT_FREE( glyph->svg_document ); + } + + + FT_CALLBACK_DEF( FT_Error ) + ft_svg_glyph_copy( FT_Glyph svg_source, + FT_Glyph svg_target ) + { + FT_SvgGlyph source = (FT_SvgGlyph)svg_source; + FT_SvgGlyph target = (FT_SvgGlyph)svg_target; + + FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_GLYPH( source )->library->memory; + + + if ( svg_source->format != FT_GLYPH_FORMAT_SVG ) + { + error = FT_THROW( Invalid_Glyph_Format ); + goto Exit; + } + + if ( source->svg_document_length == 0 ) + { + error = FT_THROW( Invalid_Slot_Handle ); + goto Exit; + } + + target->glyph_index = source->glyph_index; + + target->svg_document_length = source->svg_document_length; + + target->metrics = source->metrics; + target->units_per_EM = source->units_per_EM; + + target->start_glyph_id = source->start_glyph_id; + target->end_glyph_id = source->end_glyph_id; + + target->transform = source->transform; + target->delta = source->delta; + + /* allocate space for the SVG document */ + if ( FT_QALLOC( target->svg_document, target->svg_document_length ) ) + goto Exit; + + /* copy the document */ + FT_MEM_COPY( target->svg_document, + source->svg_document, + target->svg_document_length ); + + Exit: + return error; + } + + + FT_CALLBACK_DEF( void ) + ft_svg_glyph_transform( FT_Glyph svg_glyph, + const FT_Matrix* _matrix, + const FT_Vector* _delta ) + { + FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; + FT_Matrix* matrix = (FT_Matrix*)_matrix; + FT_Vector* delta = (FT_Vector*)_delta; + + FT_Matrix tmp_matrix; + FT_Vector tmp_delta; + + FT_Matrix a, b; + FT_Pos x, y; + + + if ( !matrix ) + { + tmp_matrix.xx = 0x10000; + tmp_matrix.xy = 0; + tmp_matrix.yx = 0; + tmp_matrix.yy = 0x10000; + + matrix = &tmp_matrix; + } + + if ( !delta ) + { + tmp_delta.x = 0; + tmp_delta.y = 0; + + delta = &tmp_delta; + } + + a = glyph->transform; + b = *matrix; + FT_Matrix_Multiply( &b, &a ); + + x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, glyph->delta.x ), + FT_MulFix( matrix->xy, glyph->delta.y ) ), + delta->x ); + y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, glyph->delta.x ), + FT_MulFix( matrix->yy, glyph->delta.y ) ), + delta->y ); + + glyph->delta.x = x; + glyph->delta.y = y; + + glyph->transform = a; + } + + + FT_CALLBACK_DEF( FT_Error ) + ft_svg_glyph_prepare( FT_Glyph svg_glyph, + FT_GlyphSlot slot ) + { + FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; + + FT_Error error = FT_Err_Ok; + FT_Memory memory = svg_glyph->library->memory; + + FT_SVG_Document document = NULL; + + + if ( FT_NEW( document ) ) + return error; + + document->svg_document = glyph->svg_document; + document->svg_document_length = glyph->svg_document_length; + + document->metrics = glyph->metrics; + document->units_per_EM = glyph->units_per_EM; + + document->start_glyph_id = glyph->start_glyph_id; + document->end_glyph_id = glyph->end_glyph_id; + + document->transform = glyph->transform; + document->delta = glyph->delta; + + slot->format = FT_GLYPH_FORMAT_SVG; + slot->glyph_index = glyph->glyph_index; + slot->other = document; + + return error; + } + + + FT_DEFINE_GLYPH( + ft_svg_glyph_class, + + sizeof ( FT_SvgGlyphRec ), + FT_GLYPH_FORMAT_SVG, + + ft_svg_glyph_init, /* FT_Glyph_InitFunc glyph_init */ + ft_svg_glyph_done, /* FT_Glyph_DoneFunc glyph_done */ + ft_svg_glyph_copy, /* FT_Glyph_CopyFunc glyph_copy */ + ft_svg_glyph_transform, /* FT_Glyph_TransformFunc glyph_transform */ + NULL, /* FT_Glyph_GetBBoxFunc glyph_bbox */ + ft_svg_glyph_prepare /* FT_Glyph_PrepareFunc glyph_prepare */ + ) + +#endif /* FT_CONFIG_OPTION_SVG */ + + /*************************************************************************/ /*************************************************************************/ /**** ****/ @@ -377,6 +612,12 @@ else if ( format == FT_GLYPH_FORMAT_OUTLINE ) clazz = &ft_outline_glyph_class; +#ifdef FT_CONFIG_OPTION_SVG + /* if it is an SVG glyph */ + else if ( format == FT_GLYPH_FORMAT_SVG ) + clazz = &ft_svg_glyph_class; +#endif + else { /* try to find a renderer that supports the glyph image format */ @@ -595,6 +836,16 @@ if ( !error ) error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); +#ifdef FT_CONFIG_OPTION_SVG + if ( clazz == &ft_svg_glyph_class ) + { + FT_Memory memory = library->memory; + + + FT_FREE( dummy.other ); + } +#endif + #if 1 if ( !destroy && origin ) { diff --git a/thirdparty/freetype/src/base/ftgxval.c b/thirdparty/freetype/src/base/ftgxval.c index e9567f77f3..5598a11c6d 100644 --- a/thirdparty/freetype/src/base/ftgxval.c +++ b/thirdparty/freetype/src/base/ftgxval.c @@ -4,7 +4,7 @@ * * FreeType API for validating TrueTypeGX/AAT tables (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * Masatake YAMATO, Redhat K.K, * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/base/fthash.c b/thirdparty/freetype/src/base/fthash.c index 449b03a5c1..313bbbb4b2 100644 --- a/thirdparty/freetype/src/base/fthash.c +++ b/thirdparty/freetype/src/base/fthash.c @@ -243,7 +243,7 @@ nn = *bp; if ( !nn ) { - if ( FT_NEW( nn ) ) + if ( FT_QNEW( nn ) ) goto Exit; *bp = nn; diff --git a/thirdparty/freetype/src/base/ftinit.c b/thirdparty/freetype/src/base/ftinit.c index a2d2b933c0..0f29a6017e 100644 --- a/thirdparty/freetype/src/base/ftinit.c +++ b/thirdparty/freetype/src/base/ftinit.c @@ -4,7 +4,7 @@ * * FreeType initialization layer (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftlcdfil.c b/thirdparty/freetype/src/base/ftlcdfil.c index 488b913e63..e72f6d668d 100644 --- a/thirdparty/freetype/src/base/ftlcdfil.c +++ b/thirdparty/freetype/src/base/ftlcdfil.c @@ -4,7 +4,7 @@ * * FreeType API for color filtering of subpixel bitmap glyphs (body). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftmac.c b/thirdparty/freetype/src/base/ftmac.c index 36a860979e..21f1894ad3 100644 --- a/thirdparty/freetype/src/base/ftmac.c +++ b/thirdparty/freetype/src/base/ftmac.c @@ -8,7 +8,7 @@ * This file is for Mac OS X only; see builds/mac/ftoldmac.c for * classic platforms built by MPW. * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -105,7 +105,7 @@ /* Don't want warnings about our own use of deprecated functions. */ #define FT_DEPRECATED_ATTRIBUTE -#include FT_MAC_H +#include <freetype/ftmac.h> #ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */ #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault @@ -314,7 +314,7 @@ NULL, NULL, NULL ) ) return ( OSType ) 0; - return ((FInfo *)(info.finderInfo))->fdType; + return ( (FInfo *)( info.finderInfo ) )->fdType; } @@ -462,7 +462,7 @@ if ( ps_name_len != 0 ) { - ft_memcpy(ps_name, names[0] + 1, ps_name_len); + ft_memcpy( ps_name, names[0] + 1, ps_name_len ); ps_name[ps_name_len] = 0; } if ( style->indexes[face_index] > 1 && diff --git a/thirdparty/freetype/src/base/ftmm.c b/thirdparty/freetype/src/base/ftmm.c index fc5d4ecc8d..dbbd87c9b9 100644 --- a/thirdparty/freetype/src/base/ftmm.c +++ b/thirdparty/freetype/src/base/ftmm.c @@ -4,7 +4,7 @@ * * Multiple Master font support (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftobjs.c b/thirdparty/freetype/src/base/ftobjs.c index 883f1a8970..eeda69c3ed 100644 --- a/thirdparty/freetype/src/base/ftobjs.c +++ b/thirdparty/freetype/src/base/ftobjs.c @@ -4,7 +4,7 @@ * * The FreeType private base classes (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -19,6 +19,7 @@ #include <freetype/ftlist.h> #include <freetype/ftoutln.h> #include <freetype/ftfntfmt.h> +#include <freetype/otsvg.h> #include <freetype/internal/ftvalid.h> #include <freetype/internal/ftobjs.h> @@ -27,6 +28,7 @@ #include <freetype/internal/ftstream.h> #include <freetype/internal/sfnt.h> /* for SFNT_Load_Table_Func */ #include <freetype/internal/psaux.h> /* for PS_Driver */ +#include <freetype/internal/svginterface.h> #include <freetype/tttables.h> #include <freetype/tttags.h> @@ -328,6 +330,19 @@ if ( !error && clazz->init_slot ) error = clazz->init_slot( slot ); +#ifdef FT_CONFIG_OPTION_SVG + /* if SVG table exists, allocate the space in `slot->other` */ + if ( slot->face->face_flags & FT_FACE_FLAG_SVG ) + { + FT_SVG_Document document = NULL; + + + if ( FT_NEW( document ) ) + goto Exit; + slot->other = document; + } +#endif + Exit: return error; } @@ -372,7 +387,18 @@ FT_Pos width, height, pitch; - if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) + if ( slot->format == FT_GLYPH_FORMAT_SVG ) + { + FT_Module module; + SVG_Service svg_service; + + + module = FT_Get_Module( slot->library, "ot-svg" ); + svg_service = (SVG_Service)module->clazz->module_interface; + + return (FT_Bool)svg_service->preset_slot( module, slot, FALSE ); + } + else if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) return 1; if ( origin ) @@ -564,8 +590,27 @@ slot->subglyphs = NULL; slot->control_data = NULL; slot->control_len = 0; - slot->other = NULL; - slot->format = FT_GLYPH_FORMAT_NONE; + +#ifndef FT_CONFIG_OPTION_SVG + slot->other = NULL; +#else + if ( !( slot->face->face_flags & FT_FACE_FLAG_SVG ) ) + slot->other = NULL; + else + { + if ( slot->internal->flags & FT_GLYPH_OWN_GZIP_SVG ) + { + FT_Memory memory = slot->face->memory; + FT_SVG_Document doc = (FT_SVG_Document)slot->other; + + + FT_FREE( doc->svg_document ); + slot->internal->load_flags &= ~FT_GLYPH_OWN_GZIP_SVG; + } + } +#endif + + slot->format = FT_GLYPH_FORMAT_NONE; slot->linearHoriAdvance = 0; slot->linearVertAdvance = 0; @@ -583,6 +628,23 @@ FT_Driver_Class clazz = driver->clazz; FT_Memory memory = driver->root.memory; +#ifdef FT_CONFIG_OPTION_SVG + if ( slot->face->face_flags & FT_FACE_FLAG_SVG ) + { + /* free memory in case SVG was there */ + if ( slot->internal->flags & FT_GLYPH_OWN_GZIP_SVG ) + { + FT_SVG_Document doc = (FT_SVG_Document)slot->other; + + + FT_FREE( doc->svg_document ); + + slot->internal->flags &= ~FT_GLYPH_OWN_GZIP_SVG; + } + + FT_FREE( slot->other ); + } +#endif if ( clazz->done_slot ) clazz->done_slot( slot ); @@ -858,6 +920,11 @@ library = driver->root.library; hinter = library->auto_hinter; + /* undefined scale means no scale */ + if ( face->size->metrics.x_ppem == 0 || + face->size->metrics.y_ppem == 0 ) + load_flags |= FT_LOAD_NO_SCALE; + /* resolve load flags dependencies */ if ( load_flags & FT_LOAD_NO_RECURSE ) @@ -947,11 +1014,21 @@ FT_AutoHinter_Interface hinting; - /* try to load embedded bitmaps first if available */ - /* */ - /* XXX: This is really a temporary hack that should disappear */ - /* promptly with FreeType 2.1! */ - /* */ + /* XXX: The use of the `FT_LOAD_XXX_ONLY` flags is not very */ + /* elegant. */ + + /* try to load SVG documents if available */ + if ( FT_HAS_SVG( face ) ) + { + error = driver->clazz->load_glyph( slot, face->size, + glyph_index, + load_flags | FT_LOAD_SVG_ONLY ); + + if ( !error && slot->format == FT_GLYPH_FORMAT_SVG ) + goto Load_Ok; + } + + /* try to load embedded bitmaps if available */ if ( FT_HAS_FIXED_SIZES( face ) && ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) { @@ -1597,7 +1674,6 @@ FT_FREE( stream->base ); stream->size = 0; - stream->base = NULL; stream->close = NULL; } @@ -2451,6 +2527,16 @@ #endif + /* only use lower 31 bits together with sign bit */ + if ( face_index > 0 ) + face_index &= 0x7FFFFFFFL; + else + { + face_index = -face_index; + face_index &= 0x7FFFFFFFL; + face_index = -face_index; + } + #ifdef FT_DEBUG_LEVEL_TRACE FT_TRACE3(( "FT_Open_Face: " )); if ( face_index < 0 ) @@ -3323,6 +3409,9 @@ if ( !face ) return FT_THROW( Invalid_Face_Handle ); + if ( !face->size ) + return FT_THROW( Invalid_Size_Handle ); + if ( !req || req->width < 0 || req->height < 0 || req->type >= FT_SIZE_REQUEST_TYPE_MAX ) return FT_THROW( Invalid_Argument ); @@ -4474,7 +4563,7 @@ render->glyph_format = clazz->glyph_format; /* allocate raster object if needed */ - if ( clazz->raster_class->raster_new ) + if ( clazz->raster_class && clazz->raster_class->raster_new ) { error = clazz->raster_class->raster_new( memory, &render->raster ); if ( error ) @@ -4484,6 +4573,11 @@ render->render = clazz->render_glyph; } +#ifdef FT_CONFIG_OPTION_SVG + if ( clazz->glyph_format == FT_GLYPH_FORMAT_SVG ) + render->render = clazz->render_glyph; +#endif + /* add to list */ node->data = module; FT_List_Add( &library->renderers, node ); @@ -5729,7 +5823,7 @@ SFNT_Service sfnt; - if ( !face || !paint || !paint ) + if ( !face || !paint ) return 0; if ( !FT_IS_SFNT( face ) ) diff --git a/thirdparty/freetype/src/base/ftotval.c b/thirdparty/freetype/src/base/ftotval.c index 0f748d006c..f336e96227 100644 --- a/thirdparty/freetype/src/base/ftotval.c +++ b/thirdparty/freetype/src/base/ftotval.c @@ -4,7 +4,7 @@ * * FreeType API for validating OpenType tables (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftoutln.c b/thirdparty/freetype/src/base/ftoutln.c index 98c6ca16e6..624df03ad8 100644 --- a/thirdparty/freetype/src/base/ftoutln.c +++ b/thirdparty/freetype/src/base/ftoutln.c @@ -4,7 +4,7 @@ * * FreeType outline management (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftpatent.c b/thirdparty/freetype/src/base/ftpatent.c index cd192d33bd..353ed2b531 100644 --- a/thirdparty/freetype/src/base/ftpatent.c +++ b/thirdparty/freetype/src/base/ftpatent.c @@ -5,7 +5,7 @@ * FreeType API for checking patented TrueType bytecode instructions * (body). Obsolete, retained for backward compatibility. * - * Copyright (C) 2007-2021 by + * Copyright (C) 2007-2022 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftpfr.c b/thirdparty/freetype/src/base/ftpfr.c index 5afd5a183f..9e748f06e6 100644 --- a/thirdparty/freetype/src/base/ftpfr.c +++ b/thirdparty/freetype/src/base/ftpfr.c @@ -4,7 +4,7 @@ * * FreeType API for accessing PFR-specific data (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftpsprop.c b/thirdparty/freetype/src/base/ftpsprop.c index 3655ae97ec..81fcee08f6 100644 --- a/thirdparty/freetype/src/base/ftpsprop.c +++ b/thirdparty/freetype/src/base/ftpsprop.c @@ -5,7 +5,7 @@ * Get and set properties of PostScript drivers (body). * See `ftdriver.h' for available properties. * - * Copyright (C) 2017-2021 by + * Copyright (C) 2017-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftrfork.c b/thirdparty/freetype/src/base/ftrfork.c index cb7e94ddb0..356998d3fa 100644 --- a/thirdparty/freetype/src/base/ftrfork.c +++ b/thirdparty/freetype/src/base/ftrfork.c @@ -4,7 +4,7 @@ * * Embedded resource forks accessor (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * Masatake YAMATO and Redhat K.K. * * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are @@ -402,17 +402,17 @@ FT_Long *result_offset ); - CONST_FT_RFORK_RULE_ARRAY_BEGIN(ft_raccess_guess_table, - ft_raccess_guess_rec) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_double, apple_double) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_single, apple_single) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_ufs_export, darwin_ufs_export) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_newvfs, darwin_newvfs) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_hfsplus, darwin_hfsplus) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(vfat, vfat) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_cap, linux_cap) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_double, linux_double) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_netatalk, linux_netatalk) + CONST_FT_RFORK_RULE_ARRAY_BEGIN( ft_raccess_guess_table, + ft_raccess_guess_rec ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_double, apple_double ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_single, apple_single ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_ufs_export, darwin_ufs_export ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_newvfs, darwin_newvfs ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_hfsplus, darwin_hfsplus ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( vfat, vfat ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_cap, linux_cap ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_double, linux_double ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_netatalk, linux_netatalk ) CONST_FT_RFORK_RULE_ARRAY_END @@ -868,9 +868,7 @@ const char* tmp; const char* slash; size_t new_length; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); + FT_Error error; new_length = ft_strlen( original_name ) + ft_strlen( insertion ); diff --git a/thirdparty/freetype/src/base/ftsnames.c b/thirdparty/freetype/src/base/ftsnames.c index 44dba66638..3bf20c389b 100644 --- a/thirdparty/freetype/src/base/ftsnames.c +++ b/thirdparty/freetype/src/base/ftsnames.c @@ -7,7 +7,7 @@ * * This is _not_ used to retrieve glyph names! * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftstream.c b/thirdparty/freetype/src/base/ftstream.c index 5992998ba3..cc926565c3 100644 --- a/thirdparty/freetype/src/base/ftstream.c +++ b/thirdparty/freetype/src/base/ftstream.c @@ -4,7 +4,7 @@ * * I/O stream support (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftstroke.c b/thirdparty/freetype/src/base/ftstroke.c index 37e9649411..aa983f940f 100644 --- a/thirdparty/freetype/src/base/ftstroke.c +++ b/thirdparty/freetype/src/base/ftstroke.c @@ -4,7 +4,7 @@ * * FreeType path stroker (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftsynth.c b/thirdparty/freetype/src/base/ftsynth.c index 73565b1307..10bbe0dfda 100644 --- a/thirdparty/freetype/src/base/ftsynth.c +++ b/thirdparty/freetype/src/base/ftsynth.c @@ -4,7 +4,7 @@ * * FreeType synthesizing code for emboldening and slanting (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftsystem.c b/thirdparty/freetype/src/base/ftsystem.c index 9beb7e245d..d8826b2367 100644 --- a/thirdparty/freetype/src/base/ftsystem.c +++ b/thirdparty/freetype/src/base/ftsystem.c @@ -4,7 +4,7 @@ * * ANSI-specific FreeType low-level system interface (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/fttrigon.c b/thirdparty/freetype/src/base/fttrigon.c index 0ca6d7810a..6964edb0f5 100644 --- a/thirdparty/freetype/src/base/fttrigon.c +++ b/thirdparty/freetype/src/base/fttrigon.c @@ -4,7 +4,7 @@ * * FreeType trigonometric functions (body). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/fttype1.c b/thirdparty/freetype/src/base/fttype1.c index 0d0afbcef0..de3d5a48bd 100644 --- a/thirdparty/freetype/src/base/fttype1.c +++ b/thirdparty/freetype/src/base/fttype1.c @@ -4,7 +4,7 @@ * * FreeType utility file for PS names support (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftutil.c b/thirdparty/freetype/src/base/ftutil.c index 3142faee98..5a91382580 100644 --- a/thirdparty/freetype/src/base/ftutil.c +++ b/thirdparty/freetype/src/base/ftutil.c @@ -4,7 +4,7 @@ * * FreeType utility file for memory and list management (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/base/ftver.rc b/thirdparty/freetype/src/base/ftver.rc index a3d05b3780..eb6090ecc2 100644 --- a/thirdparty/freetype/src/base/ftver.rc +++ b/thirdparty/freetype/src/base/ftver.rc @@ -4,7 +4,7 @@ /* */ /* FreeType VERSIONINFO resource for Windows DLLs. */ /* */ -/* Copyright (C) 2018-2021 by */ +/* Copyright (C) 2018-2022 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,8 +18,8 @@ #include<windows.h> -#define FT_VERSION 2,11,1,0 -#define FT_VERSION_STR "2.11.1" +#define FT_VERSION 2,12,1,0 +#define FT_VERSION_STR "2.12.1" VS_VERSION_INFO VERSIONINFO FILEVERSION FT_VERSION @@ -45,7 +45,7 @@ BEGIN VALUE "FileVersion", FT_VERSION_STR VALUE "ProductName", "FreeType" VALUE "ProductVersion", FT_VERSION_STR - VALUE "LegalCopyright", "\251 2000-2021 The FreeType Project www.freetype.org. All rights reserved." + VALUE "LegalCopyright", "\251 2000-2022 The FreeType Project www.freetype.org. All rights reserved." VALUE "InternalName", "freetype" VALUE "OriginalFilename", FT_FILENAME END diff --git a/thirdparty/freetype/src/base/ftwinfnt.c b/thirdparty/freetype/src/base/ftwinfnt.c index 98f197afdc..193f7fa048 100644 --- a/thirdparty/freetype/src/base/ftwinfnt.c +++ b/thirdparty/freetype/src/base/ftwinfnt.c @@ -4,7 +4,7 @@ * * FreeType API for accessing Windows FNT specific info (body). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/bdf/README b/thirdparty/freetype/src/bdf/README index 996ac2d2aa..d7cb8c14ef 100644 --- a/thirdparty/freetype/src/bdf/README +++ b/thirdparty/freetype/src/bdf/README @@ -13,7 +13,7 @@ This code implements a BDF driver for the FreeType library, following the Adobe Specification V 2.2. The specification of the BDF font format is available from Adobe's web site: - https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5005.BDF_Spec.pdf + https://adobe-type-tools.github.io/font-tech-notes/pdfs/5005.BDF_Spec.pdf Many good bitmap fonts in bdf format come with XFree86 (www.XFree86.org). They do not define vertical metrics, because the X Consortium BDF @@ -23,6 +23,10 @@ specification has removed them. Encodings ********* +[This section is out of date, retained for historical reasons. BDF + properties can be retrieved with `FT_Get_BDF_Property`, character set ID + values with `FT_Get_BDF_Charset_ID`.] + The variety of encodings that accompanies bdf fonts appears to encompass the small set defined in freetype.h. On the other hand, two properties that specify encoding and registry are usually defined in bdf fonts. diff --git a/thirdparty/freetype/src/bdf/bdflib.c b/thirdparty/freetype/src/bdf/bdflib.c index b65c8a2f3e..6603148a02 100644 --- a/thirdparty/freetype/src/bdf/bdflib.c +++ b/thirdparty/freetype/src/bdf/bdflib.c @@ -613,7 +613,7 @@ if ( FT_QREALLOC( buf, buf_size, new_size ) ) goto Exit; - cursor = (ptrdiff_t)buf_size; + cursor = avail; buf_size = new_size; } else @@ -623,7 +623,6 @@ FT_MEM_MOVE( buf, buf + start, bytes ); cursor = bytes; - avail -= bytes; start = 0; } refill = 1; @@ -1175,7 +1174,6 @@ font->props_size + 1 ) ) goto Exit; - fp = font->props + font->props_size; font->props_size++; } @@ -1537,8 +1535,6 @@ /* kept. */ FT_FREE( p->glyph_name ); } - - p->glyph_name = NULL; } /* Clear the flags that might be added when width and height are */ @@ -1953,7 +1949,7 @@ } } - if ( FT_ALLOC( p->font->internal, sizeof ( FT_HashRec ) ) ) + if ( FT_QALLOC( p->font->internal, sizeof ( FT_HashRec ) ) ) goto Exit; error = ft_hash_str_init( (FT_Hash)p->font->internal, memory ); if ( error ) diff --git a/thirdparty/freetype/src/bzip2/ftbzip2.c b/thirdparty/freetype/src/bzip2/ftbzip2.c index 296cea088b..ab2da7e62b 100644 --- a/thirdparty/freetype/src/bzip2/ftbzip2.c +++ b/thirdparty/freetype/src/bzip2/ftbzip2.c @@ -8,7 +8,7 @@ * parse compressed PCF fonts, as found with many X11 server * distributions. * - * Copyright (C) 2010-2021 by + * Copyright (C) 2010-2022 by * Joel Klinghed. * * based on `src/gzip/ftgzip.c' @@ -57,8 +57,9 @@ /* it is better to use FreeType memory routines instead of raw 'malloc/free' */ - typedef void *(* alloc_func)(void*, int, int); - typedef void (* free_func)(void*, void*); + typedef void* (*alloc_func)( void*, int, int ); + typedef void (*free_func) ( void*, void* ); + static void* ft_bzip2_alloc( FT_Memory memory, @@ -102,10 +103,11 @@ FT_Byte input[FT_BZIP2_BUFFER_SIZE]; /* input read buffer */ - FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */ - FT_ULong pos; /* position in output */ + FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */ + FT_ULong pos; /* position in output */ FT_Byte* cursor; FT_Byte* limit; + FT_Bool reset; /* reset before next read */ } FT_BZip2FileRec, *FT_BZip2File; @@ -153,6 +155,7 @@ zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE; zip->cursor = zip->limit; zip->pos = 0; + zip->reset = 0; /* check .bz2 header */ { @@ -228,6 +231,7 @@ zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE; zip->cursor = zip->limit; zip->pos = 0; + zip->reset = 0; BZ2_bzDecompressInit( bzstream, 0, 0 ); } @@ -302,18 +306,23 @@ err = BZ2_bzDecompress( bzstream ); - if ( err == BZ_STREAM_END ) + if ( err != BZ_OK ) { - zip->limit = (FT_Byte*)bzstream->next_out; - if ( zip->limit == zip->cursor ) - error = FT_THROW( Invalid_Stream_Operation ); - break; - } - else if ( err != BZ_OK ) - { - zip->limit = zip->cursor; - error = FT_THROW( Invalid_Stream_Operation ); - break; + zip->reset = 1; + + if ( err == BZ_STREAM_END ) + { + zip->limit = (FT_Byte*)bzstream->next_out; + if ( zip->limit == zip->cursor ) + error = FT_THROW( Invalid_Stream_Operation ); + break; + } + else + { + zip->limit = zip->cursor; + error = FT_THROW( Invalid_Stream_Operation ); + break; + } } } @@ -363,9 +372,9 @@ FT_Error error; - /* Reset inflate stream if we're seeking backwards. */ - /* Yes, that is not too efficient, but it saves memory :-) */ - if ( pos < zip->pos ) + /* Reset inflate stream if seeking backwards or bzip reported an error. */ + /* Yes, that is not too efficient, but it saves memory :-) */ + if ( pos < zip->pos || zip->reset ) { error = ft_bzip2_file_reset( zip ); if ( error ) diff --git a/thirdparty/freetype/src/cache/ftcache.c b/thirdparty/freetype/src/cache/ftcache.c index ddd3e43c02..e26b44a700 100644 --- a/thirdparty/freetype/src/cache/ftcache.c +++ b/thirdparty/freetype/src/cache/ftcache.c @@ -4,7 +4,7 @@ * * The FreeType Caching sub-system (body only). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cache/ftcbasic.c b/thirdparty/freetype/src/cache/ftcbasic.c index 1760c5fbd4..635b17d074 100644 --- a/thirdparty/freetype/src/cache/ftcbasic.c +++ b/thirdparty/freetype/src/cache/ftcbasic.c @@ -4,7 +4,7 @@ * * The FreeType basic cache interface (body). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -26,6 +26,7 @@ #include "ftccback.h" #include "ftcerror.h" +#undef FT_COMPONENT #define FT_COMPONENT cache @@ -182,7 +183,8 @@ if ( !error ) { if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP || - face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) + face->glyph->format == FT_GLYPH_FORMAT_OUTLINE || + face->glyph->format == FT_GLYPH_FORMAT_SVG ) { /* ok, copy it */ FT_Glyph glyph; diff --git a/thirdparty/freetype/src/cache/ftccache.c b/thirdparty/freetype/src/cache/ftccache.c index 5bbf329298..ab4ad2faa2 100644 --- a/thirdparty/freetype/src/cache/ftccache.c +++ b/thirdparty/freetype/src/cache/ftccache.c @@ -4,7 +4,7 @@ * * The FreeType internal cache interface (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cache/ftccache.h b/thirdparty/freetype/src/cache/ftccache.h index 4849b92352..ae0ae8b172 100644 --- a/thirdparty/freetype/src/cache/ftccache.h +++ b/thirdparty/freetype/src/cache/ftccache.h @@ -4,7 +4,7 @@ * * FreeType internal cache interface (specification). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -210,7 +210,7 @@ FT_BEGIN_HEADER #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \ FT_BEGIN_STMNT \ FTC_Node *_bucket, *_pnode, _node; \ - FTC_Cache _cache = FTC_CACHE(cache); \ + FTC_Cache _cache = FTC_CACHE( cache ); \ FT_Offset _hash = (FT_Offset)(hash); \ FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \ FT_Bool _list_changed = FALSE; \ diff --git a/thirdparty/freetype/src/cache/ftccback.h b/thirdparty/freetype/src/cache/ftccback.h index 8185fe3738..ba01af2e78 100644 --- a/thirdparty/freetype/src/cache/ftccback.h +++ b/thirdparty/freetype/src/cache/ftccback.h @@ -4,7 +4,7 @@ * * Callback functions of the caching sub-system (specification only). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cache/ftccmap.c b/thirdparty/freetype/src/cache/ftccmap.c index 40b449b9cc..0ee1834e27 100644 --- a/thirdparty/freetype/src/cache/ftccmap.c +++ b/thirdparty/freetype/src/cache/ftccmap.c @@ -4,7 +4,7 @@ * * FreeType CharMap cache (body) * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -116,7 +116,7 @@ FT_UInt nn; - if ( !FT_NEW( node ) ) + if ( !FT_QNEW( node ) ) { node->face_id = query->face_id; node->cmap_index = query->cmap_index; diff --git a/thirdparty/freetype/src/cache/ftcerror.h b/thirdparty/freetype/src/cache/ftcerror.h index 2c6faf65e2..44e74d36b4 100644 --- a/thirdparty/freetype/src/cache/ftcerror.h +++ b/thirdparty/freetype/src/cache/ftcerror.h @@ -4,7 +4,7 @@ * * Caching sub-system error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cache/ftcglyph.c b/thirdparty/freetype/src/cache/ftcglyph.c index 52771c7a8a..f826c8dd8e 100644 --- a/thirdparty/freetype/src/cache/ftcglyph.c +++ b/thirdparty/freetype/src/cache/ftcglyph.c @@ -4,7 +4,7 @@ * * FreeType Glyph Image (FT_Glyph) cache (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cache/ftcglyph.h b/thirdparty/freetype/src/cache/ftcglyph.h index cf00cdc7b8..cbb8077739 100644 --- a/thirdparty/freetype/src/cache/ftcglyph.h +++ b/thirdparty/freetype/src/cache/ftcglyph.h @@ -4,7 +4,7 @@ * * FreeType abstract glyph cache (specification). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -140,8 +140,8 @@ FT_BEGIN_HEADER } FTC_FamilyRec, *FTC_Family; -#define FTC_FAMILY(x) ( (FTC_Family)(x) ) -#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) ) +#define FTC_FAMILY( x ) ( (FTC_Family)(x) ) +#define FTC_FAMILY_P( x ) ( (FTC_Family*)(x) ) typedef struct FTC_GNodeRec_ @@ -245,7 +245,7 @@ FT_BEGIN_HEADER #define FTC_GCACHE_CLASS( x ) ((FTC_GCacheClass)(x)) #define FTC_CACHE_GCACHE_CLASS( x ) \ - FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class ) + FTC_GCACHE_CLASS( FTC_CACHE( x )->org_class ) #define FTC_CACHE_FAMILY_CLASS( x ) \ ( (FTC_MruListClass)FTC_CACHE_GCACHE_CLASS( x )->family_class ) diff --git a/thirdparty/freetype/src/cache/ftcimage.c b/thirdparty/freetype/src/cache/ftcimage.c index 3f12a654b2..39ce61a511 100644 --- a/thirdparty/freetype/src/cache/ftcimage.c +++ b/thirdparty/freetype/src/cache/ftcimage.c @@ -4,7 +4,7 @@ * * FreeType Image cache (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -64,7 +64,7 @@ FTC_INode inode = NULL; - if ( !FT_NEW( inode ) ) + if ( !FT_QNEW( inode ) ) { FTC_GNode gnode = FTC_GNODE( inode ); FTC_Family family = gquery->family; @@ -74,6 +74,7 @@ /* initialize its inner fields */ FTC_GNode_Init( gnode, gindex, family ); + inode->glyph = NULL; /* we will now load the glyph image */ error = clazz->family_load_glyph( family, gindex, cache, diff --git a/thirdparty/freetype/src/cache/ftcimage.h b/thirdparty/freetype/src/cache/ftcimage.h index 8b28d6f00b..55270a436c 100644 --- a/thirdparty/freetype/src/cache/ftcimage.h +++ b/thirdparty/freetype/src/cache/ftcimage.h @@ -4,7 +4,7 @@ * * FreeType Generic Image cache (specification) * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -51,8 +51,8 @@ FT_BEGIN_HEADER } FTC_INodeRec, *FTC_INode; #define FTC_INODE( x ) ( (FTC_INode)( x ) ) -#define FTC_INODE_GINDEX( x ) FTC_GNODE(x)->gindex -#define FTC_INODE_FAMILY( x ) FTC_GNODE(x)->family +#define FTC_INODE_GINDEX( x ) FTC_GNODE( x )->gindex +#define FTC_INODE_FAMILY( x ) FTC_GNODE( x )->family typedef FT_Error (*FTC_IFamily_LoadGlyphFunc)( FTC_Family family, @@ -72,7 +72,7 @@ FT_BEGIN_HEADER #define FTC_IFAMILY_CLASS( x ) ((FTC_IFamilyClass)(x)) #define FTC_CACHE_IFAMILY_CLASS( x ) \ - FTC_IFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS(x)->family_class ) + FTC_IFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS( x )->family_class ) /* can be used as a @FTC_Node_FreeFunc */ diff --git a/thirdparty/freetype/src/cache/ftcmanag.c b/thirdparty/freetype/src/cache/ftcmanag.c index 512de8a3fc..49f037aa73 100644 --- a/thirdparty/freetype/src/cache/ftcmanag.c +++ b/thirdparty/freetype/src/cache/ftcmanag.c @@ -4,7 +4,7 @@ * * FreeType Cache Manager (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cache/ftcmanag.h b/thirdparty/freetype/src/cache/ftcmanag.h index 99aa926369..5c67af30bc 100644 --- a/thirdparty/freetype/src/cache/ftcmanag.h +++ b/thirdparty/freetype/src/cache/ftcmanag.h @@ -4,7 +4,7 @@ * * FreeType Cache Manager (specification). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cache/ftcmru.c b/thirdparty/freetype/src/cache/ftcmru.c index 2cac6f9d3a..6a14ae36e9 100644 --- a/thirdparty/freetype/src/cache/ftcmru.c +++ b/thirdparty/freetype/src/cache/ftcmru.c @@ -4,7 +4,7 @@ * * FreeType MRU support (body). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -262,7 +262,9 @@ if ( list->clazz.node_done ) list->clazz.node_done( node, list->data ); } - else if ( FT_QALLOC( node, list->clazz.node_size ) ) + + /* zero new node in case of node_init failure */ + else if ( FT_ALLOC( node, list->clazz.node_size ) ) goto Exit; error = list->clazz.node_init( node, key, list->data ); diff --git a/thirdparty/freetype/src/cache/ftcmru.h b/thirdparty/freetype/src/cache/ftcmru.h index 6befde307f..4fcadef477 100644 --- a/thirdparty/freetype/src/cache/ftcmru.h +++ b/thirdparty/freetype/src/cache/ftcmru.h @@ -4,7 +4,7 @@ * * Simple MRU list-cache (specification). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cache/ftcsbits.c b/thirdparty/freetype/src/cache/ftcsbits.c index 362999fce0..4a8b1963eb 100644 --- a/thirdparty/freetype/src/cache/ftcsbits.c +++ b/thirdparty/freetype/src/cache/ftcsbits.c @@ -4,7 +4,7 @@ * * FreeType sbits manager (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -171,7 +171,7 @@ sbit->xadvance = (FT_Char)xadvance; sbit->yadvance = (FT_Char)yadvance; sbit->format = (FT_Byte)bitmap->pixel_mode; - sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1); + sbit->max_grays = (FT_Byte)( bitmap->num_grays - 1 ); if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) { @@ -233,7 +233,7 @@ goto Exit; } - if ( !FT_NEW( snode ) ) + if ( !FT_QNEW( snode ) ) { FT_UInt count, start; @@ -248,7 +248,9 @@ snode->count = count; for ( node_count = 0; node_count < count; node_count++ ) { - snode->sbits[node_count].width = 255; + snode->sbits[node_count].width = 255; + snode->sbits[node_count].height = 0; + snode->sbits[node_count].buffer = NULL; } error = ftc_snode_load( snode, diff --git a/thirdparty/freetype/src/cache/ftcsbits.h b/thirdparty/freetype/src/cache/ftcsbits.h index 9f2d5fb33c..8f10070457 100644 --- a/thirdparty/freetype/src/cache/ftcsbits.h +++ b/thirdparty/freetype/src/cache/ftcsbits.h @@ -4,7 +4,7 @@ * * A small-bitmap cache (specification). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -61,7 +61,7 @@ FT_BEGIN_HEADER typedef const FTC_SFamilyClassRec* FTC_SFamilyClass; -#define FTC_SFAMILY_CLASS( x ) ((FTC_SFamilyClass)(x)) +#define FTC_SFAMILY_CLASS( x ) ( (FTC_SFamilyClass)(x) ) #define FTC_CACHE_SFAMILY_CLASS( x ) \ FTC_SFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS( x )->family_class ) diff --git a/thirdparty/freetype/src/cff/cff.c b/thirdparty/freetype/src/cff/cff.c index c2ffea3d0d..1ac0beb06a 100644 --- a/thirdparty/freetype/src/cff/cff.c +++ b/thirdparty/freetype/src/cff/cff.c @@ -4,7 +4,7 @@ * * FreeType OpenType driver component (body only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cffcmap.c b/thirdparty/freetype/src/cff/cffcmap.c index ff1aae69ef..2d667a7248 100644 --- a/thirdparty/freetype/src/cff/cffcmap.c +++ b/thirdparty/freetype/src/cff/cffcmap.c @@ -4,7 +4,7 @@ * * CFF character mapping table (cmap) support (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -81,7 +81,7 @@ if ( char_code < 255 ) { - FT_UInt code = (FT_UInt)(char_code + 1); + FT_UInt code = (FT_UInt)( char_code + 1 ); for (;;) diff --git a/thirdparty/freetype/src/cff/cffcmap.h b/thirdparty/freetype/src/cff/cffcmap.h index 221e255afb..2818d3c6fe 100644 --- a/thirdparty/freetype/src/cff/cffcmap.h +++ b/thirdparty/freetype/src/cff/cffcmap.h @@ -4,7 +4,7 @@ * * CFF character mapping table (cmap) support (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cffdrivr.c b/thirdparty/freetype/src/cff/cffdrivr.c index 59210f37c5..d945afdfe8 100644 --- a/thirdparty/freetype/src/cff/cffdrivr.c +++ b/thirdparty/freetype/src/cff/cffdrivr.c @@ -4,7 +4,7 @@ * * OpenType font driver implementation (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cffdrivr.h b/thirdparty/freetype/src/cff/cffdrivr.h index fce92bbb00..a312003be7 100644 --- a/thirdparty/freetype/src/cff/cffdrivr.h +++ b/thirdparty/freetype/src/cff/cffdrivr.h @@ -4,7 +4,7 @@ * * High-level OpenType driver interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cfferrs.h b/thirdparty/freetype/src/cff/cfferrs.h index b507ec8bb7..90d32897c7 100644 --- a/thirdparty/freetype/src/cff/cfferrs.h +++ b/thirdparty/freetype/src/cff/cfferrs.h @@ -4,7 +4,7 @@ * * CFF error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cffgload.c b/thirdparty/freetype/src/cff/cffgload.c index 97e8f9c1c6..7586b886f1 100644 --- a/thirdparty/freetype/src/cff/cffgload.c +++ b/thirdparty/freetype/src/cff/cffgload.c @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -29,6 +29,14 @@ #include "cfferrs.h" +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#define IS_DEFAULT_INSTANCE( _face ) \ + ( !( FT_IS_NAMED_INSTANCE( _face ) || \ + FT_IS_VARIATION( _face ) ) ) +#else +#define IS_DEFAULT_INSTANCE( _face ) 1 +#endif + /************************************************************************** * @@ -67,7 +75,7 @@ #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { - CFF_Font cff = (CFF_Font)(face->extra.data); + CFF_Font cff = (CFF_Font)( face->extra.data ); return cff_index_access_element( &cff->charstrings_index, glyph_index, @@ -103,7 +111,7 @@ #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { - CFF_Font cff = (CFF_Font)(face->extra.data); + CFF_Font cff = (CFF_Font)( face->extra.data ); cff_index_forget_element( &cff->charstrings_index, pointer ); @@ -255,8 +263,8 @@ if ( size->strike_index != 0xFFFFFFFFUL && - sfnt->load_eblc && - ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) + ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && + IS_DEFAULT_INSTANCE( size->root.face ) ) { TT_SBit_MetricsRec metrics; @@ -346,6 +354,76 @@ if ( load_flags & FT_LOAD_SBITS_ONLY ) return FT_THROW( Invalid_Argument ); +#ifdef FT_CONFIG_OPTION_SVG + /* check for OT-SVG */ + if ( ( load_flags & FT_LOAD_COLOR ) && + ( (TT_Face)glyph->root.face )->svg ) + { + /* + * We load the SVG document and try to grab the advances from the + * table. For the bearings we rely on the presetting hook to do that. + */ + + FT_Short dummy; + FT_UShort advanceX; + FT_UShort advanceY; + SFNT_Service sfnt; + + + if ( size && (size->root.metrics.x_ppem < 1 || + size->root.metrics.y_ppem < 1 ) ) + { + error = FT_THROW( Invalid_Size_Handle ); + return error; + } + + FT_TRACE3(( "Trying to load SVG glyph\n" )); + + sfnt = (SFNT_Service)((TT_Face)glyph->root.face)->sfnt; + error = sfnt->load_svg_doc( (FT_GlyphSlot)glyph, glyph_index ); + if ( !error ) + { + FT_TRACE3(( "Successfully loaded SVG glyph\n" )); + + glyph->root.format = FT_GLYPH_FORMAT_SVG; + + /* + * If horizontal or vertical advances are not present in the table, + * this is a problem with the font since the standard requires them. + * However, we are graceful and calculate the values by ourselves + * for the vertical case. + */ + sfnt->get_metrics( face, + FALSE, + glyph_index, + &dummy, + &advanceX ); + sfnt->get_metrics( face, + TRUE, + glyph_index, + &dummy, + &advanceY ); + + advanceX = + (FT_UShort)FT_MulDiv( advanceX, + glyph->root.face->size->metrics.x_ppem, + glyph->root.face->units_per_EM ); + advanceY = + (FT_UShort)FT_MulDiv( advanceY, + glyph->root.face->size->metrics.y_ppem, + glyph->root.face->units_per_EM ); + + glyph->root.metrics.horiAdvance = advanceX << 6; + glyph->root.metrics.vertAdvance = advanceY << 6; + + return error; + } + + FT_TRACE3(( "Failed to load SVG glyph\n" )); + } + +#endif /* FT_CONFIG_OPTION_SVG */ + /* if we have a CID subfont, use its matrix (which has already */ /* been multiplied with the root matrix) */ diff --git a/thirdparty/freetype/src/cff/cffgload.h b/thirdparty/freetype/src/cff/cffgload.h index d0d6a6fa08..33616b9684 100644 --- a/thirdparty/freetype/src/cff/cffgload.h +++ b/thirdparty/freetype/src/cff/cffgload.h @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cffload.c b/thirdparty/freetype/src/cff/cffload.c index 3c3f6fe502..d6f8a1013d 100644 --- a/thirdparty/freetype/src/cff/cffload.c +++ b/thirdparty/freetype/src/cff/cffload.c @@ -4,7 +4,7 @@ * * OpenType and CFF data/program tables loader (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cffload.h b/thirdparty/freetype/src/cff/cffload.h index 20f9296c4f..a3cc642b77 100644 --- a/thirdparty/freetype/src/cff/cffload.h +++ b/thirdparty/freetype/src/cff/cffload.h @@ -4,7 +4,7 @@ * * OpenType & CFF data/program tables loader (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cffobjs.c b/thirdparty/freetype/src/cff/cffobjs.c index 3a4d47dbdd..fa42accb65 100644 --- a/thirdparty/freetype/src/cff/cffobjs.c +++ b/thirdparty/freetype/src/cff/cffobjs.c @@ -4,7 +4,7 @@ * * OpenType objects manager (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -411,9 +411,7 @@ FT_String* result; - (void)FT_STRDUP( result, source ); - - FT_UNUSED( error ); + FT_MEM_STRDUP( result, source ); return result; } diff --git a/thirdparty/freetype/src/cff/cffobjs.h b/thirdparty/freetype/src/cff/cffobjs.h index 149a8a2f0a..d48c1cded9 100644 --- a/thirdparty/freetype/src/cff/cffobjs.h +++ b/thirdparty/freetype/src/cff/cffobjs.h @@ -4,7 +4,7 @@ * * OpenType objects manager (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cffparse.c b/thirdparty/freetype/src/cff/cffparse.c index dde55e95c2..2536a21866 100644 --- a/thirdparty/freetype/src/cff/cffparse.c +++ b/thirdparty/freetype/src/cff/cffparse.c @@ -4,7 +4,7 @@ * * CFF token stream parser (body) * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cffparse.h b/thirdparty/freetype/src/cff/cffparse.h index a28ab52200..55b6fe6e7c 100644 --- a/thirdparty/freetype/src/cff/cffparse.h +++ b/thirdparty/freetype/src/cff/cffparse.h @@ -4,7 +4,7 @@ * * CFF token stream parser (specification) * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cff/cfftoken.h b/thirdparty/freetype/src/cff/cfftoken.h index eef30690c4..15237de9e5 100644 --- a/thirdparty/freetype/src/cff/cfftoken.h +++ b/thirdparty/freetype/src/cff/cfftoken.h @@ -4,7 +4,7 @@ * * CFF token definitions (specification only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/ciderrs.h b/thirdparty/freetype/src/cid/ciderrs.h index 2d762d9e1d..d07da5a01d 100644 --- a/thirdparty/freetype/src/cid/ciderrs.h +++ b/thirdparty/freetype/src/cid/ciderrs.h @@ -4,7 +4,7 @@ * * CID error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidgload.c b/thirdparty/freetype/src/cid/cidgload.c index a46d063dfe..24d37d3295 100644 --- a/thirdparty/freetype/src/cid/cidgload.c +++ b/thirdparty/freetype/src/cid/cidgload.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 Glyph Loader (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidgload.h b/thirdparty/freetype/src/cid/cidgload.h index 8b515efa01..c06bb29d3d 100644 --- a/thirdparty/freetype/src/cid/cidgload.h +++ b/thirdparty/freetype/src/cid/cidgload.h @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidload.c b/thirdparty/freetype/src/cid/cidload.c index 496219de80..fe8fa1abff 100644 --- a/thirdparty/freetype/src/cid/cidload.c +++ b/thirdparty/freetype/src/cid/cidload.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 font loader (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidload.h b/thirdparty/freetype/src/cid/cidload.h index ee1d486505..90ced9280b 100644 --- a/thirdparty/freetype/src/cid/cidload.h +++ b/thirdparty/freetype/src/cid/cidload.h @@ -4,7 +4,7 @@ * * CID-keyed Type1 font loader (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidobjs.c b/thirdparty/freetype/src/cid/cidobjs.c index e3c29c22f6..c39de6369c 100644 --- a/thirdparty/freetype/src/cid/cidobjs.c +++ b/thirdparty/freetype/src/cid/cidobjs.c @@ -4,7 +4,7 @@ * * CID objects manager (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidobjs.h b/thirdparty/freetype/src/cid/cidobjs.h index 32f59cbcce..fd76a1cba5 100644 --- a/thirdparty/freetype/src/cid/cidobjs.h +++ b/thirdparty/freetype/src/cid/cidobjs.h @@ -4,7 +4,7 @@ * * CID objects manager (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidparse.c b/thirdparty/freetype/src/cid/cidparse.c index 852c9b6b96..cfc820561f 100644 --- a/thirdparty/freetype/src/cid/cidparse.c +++ b/thirdparty/freetype/src/cid/cidparse.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 parser (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidparse.h b/thirdparty/freetype/src/cid/cidparse.h index fbc437bc38..ba363f7803 100644 --- a/thirdparty/freetype/src/cid/cidparse.h +++ b/thirdparty/freetype/src/cid/cidparse.h @@ -4,7 +4,7 @@ * * CID-keyed Type1 parser (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidriver.c b/thirdparty/freetype/src/cid/cidriver.c index a0898dfa2f..a63c01064a 100644 --- a/thirdparty/freetype/src/cid/cidriver.c +++ b/thirdparty/freetype/src/cid/cidriver.c @@ -4,7 +4,7 @@ * * CID driver interface (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidriver.h b/thirdparty/freetype/src/cid/cidriver.h index 3ff5f78e11..5073b7a8eb 100644 --- a/thirdparty/freetype/src/cid/cidriver.h +++ b/thirdparty/freetype/src/cid/cidriver.h @@ -4,7 +4,7 @@ * * High-level CID driver interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/cidtoken.h b/thirdparty/freetype/src/cid/cidtoken.h index 84c8258014..7640137eac 100644 --- a/thirdparty/freetype/src/cid/cidtoken.h +++ b/thirdparty/freetype/src/cid/cidtoken.h @@ -4,7 +4,7 @@ * * CID token definitions (specification only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/cid/type1cid.c b/thirdparty/freetype/src/cid/type1cid.c index 5405ecffc8..b32c261376 100644 --- a/thirdparty/freetype/src/cid/type1cid.c +++ b/thirdparty/freetype/src/cid/type1cid.c @@ -4,7 +4,7 @@ * * FreeType OpenType driver component (body only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/gxvalid/README b/thirdparty/freetype/src/gxvalid/README index 7fb0296282..921b3ac92e 100644 --- a/thirdparty/freetype/src/gxvalid/README +++ b/thirdparty/freetype/src/gxvalid/README @@ -518,7 +518,7 @@ gxvalid: TrueType GX validator ------------------------------------------------------------------------ -Copyright (C) 2004-2021 by +Copyright (C) 2004-2022 by suzuki toshiya, Masatake YAMATO, Red hat K.K., David Turner, Robert Wilhelm, and Werner Lemberg. diff --git a/thirdparty/freetype/src/gxvalid/gxvalid.c b/thirdparty/freetype/src/gxvalid/gxvalid.c index 309d517443..9f380337c9 100644 --- a/thirdparty/freetype/src/gxvalid/gxvalid.c +++ b/thirdparty/freetype/src/gxvalid/gxvalid.c @@ -4,7 +4,7 @@ * * FreeType validator for TrueTypeGX/AAT tables (body only). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvalid.h b/thirdparty/freetype/src/gxvalid/gxvalid.h index 2c41c28668..170fde3406 100644 --- a/thirdparty/freetype/src/gxvalid/gxvalid.h +++ b/thirdparty/freetype/src/gxvalid/gxvalid.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT table validation (specification only). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvbsln.c b/thirdparty/freetype/src/gxvalid/gxvbsln.c index af69cb51df..9784d18c5d 100644 --- a/thirdparty/freetype/src/gxvalid/gxvbsln.c +++ b/thirdparty/freetype/src/gxvalid/gxvbsln.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT bsln table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvcommn.c b/thirdparty/freetype/src/gxvalid/gxvcommn.c index 18e42b0cd8..999cba4e4c 100644 --- a/thirdparty/freetype/src/gxvalid/gxvcommn.c +++ b/thirdparty/freetype/src/gxvalid/gxvcommn.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT common tables validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -1033,7 +1033,7 @@ GXV_NAME_ENTER( "StateArray" ); GXV_TRACE(( "parse %d bytes by stateSize=%d maxClassID=%d\n", - (int)(*length_p), stateSize, (int)(maxClassID) )); + (int)( *length_p ), stateSize, (int)maxClassID )); /* * 2 states are predefined and must be described in StateArray: @@ -1418,7 +1418,7 @@ GXV_NAME_ENTER( "XStateArray" ); GXV_TRACE(( "parse % 3d bytes by stateSize=% 3d maxClassID=% 3d\n", - (int)(*length_p), (int)stateSize, (int)(maxClassID) )); + (int)( *length_p ), (int)stateSize, (int)maxClassID )); /* * 2 states are predefined and must be described: diff --git a/thirdparty/freetype/src/gxvalid/gxvcommn.h b/thirdparty/freetype/src/gxvalid/gxvcommn.h index b79b641142..794cf0a447 100644 --- a/thirdparty/freetype/src/gxvalid/gxvcommn.h +++ b/thirdparty/freetype/src/gxvalid/gxvcommn.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT common tables validation (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxverror.h b/thirdparty/freetype/src/gxvalid/gxverror.h index d20d395680..8d2faac808 100644 --- a/thirdparty/freetype/src/gxvalid/gxverror.h +++ b/thirdparty/freetype/src/gxvalid/gxverror.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT validation module error codes (specification only). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvfeat.c b/thirdparty/freetype/src/gxvalid/gxvfeat.c index 0a8e2f201a..77200564ee 100644 --- a/thirdparty/freetype/src/gxvalid/gxvfeat.c +++ b/thirdparty/freetype/src/gxvalid/gxvfeat.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT feat table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvfeat.h b/thirdparty/freetype/src/gxvalid/gxvfeat.h index f6d28fa71c..3deeb521dd 100644 --- a/thirdparty/freetype/src/gxvalid/gxvfeat.h +++ b/thirdparty/freetype/src/gxvalid/gxvfeat.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT feat table validation (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvfgen.c b/thirdparty/freetype/src/gxvalid/gxvfgen.c index b47cd0f7ba..57f11a8412 100644 --- a/thirdparty/freetype/src/gxvalid/gxvfgen.c +++ b/thirdparty/freetype/src/gxvalid/gxvfgen.c @@ -5,7 +5,7 @@ * Generate feature registry data for gxv `feat' validator. * This program is derived from gxfeatreg.c in gxlayout. * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * Masatake YAMATO and Redhat K.K. * * This file may only be used, diff --git a/thirdparty/freetype/src/gxvalid/gxvjust.c b/thirdparty/freetype/src/gxvalid/gxvjust.c index ec289b8ebf..6af2c79c84 100644 --- a/thirdparty/freetype/src/gxvalid/gxvjust.c +++ b/thirdparty/freetype/src/gxvalid/gxvjust.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT just table validation (body). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvkern.c b/thirdparty/freetype/src/gxvalid/gxvkern.c index 542e8bc095..f0804e37b9 100644 --- a/thirdparty/freetype/src/gxvalid/gxvkern.c +++ b/thirdparty/freetype/src/gxvalid/gxvkern.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT kern table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvlcar.c b/thirdparty/freetype/src/gxvalid/gxvlcar.c index 9db839ba8a..be6e491f9f 100644 --- a/thirdparty/freetype/src/gxvalid/gxvlcar.c +++ b/thirdparty/freetype/src/gxvalid/gxvlcar.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT lcar table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmod.c b/thirdparty/freetype/src/gxvalid/gxvmod.c index 1a11426ccb..8c505dd23f 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmod.c +++ b/thirdparty/freetype/src/gxvalid/gxvmod.c @@ -4,7 +4,7 @@ * * FreeType's TrueTypeGX/AAT validation module implementation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmod.h b/thirdparty/freetype/src/gxvalid/gxvmod.h index 90e0c10a28..1758d4c86e 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmod.h +++ b/thirdparty/freetype/src/gxvalid/gxvmod.h @@ -5,7 +5,7 @@ * FreeType's TrueTypeGX/AAT validation module implementation * (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmort.c b/thirdparty/freetype/src/gxvalid/gxvmort.c index d0db7f4d2d..01a77d6a5d 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmort.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT mort table validation (body). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmort.h b/thirdparty/freetype/src/gxvalid/gxvmort.h index de5ab4ef02..1a1d8961b5 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmort.h +++ b/thirdparty/freetype/src/gxvalid/gxvmort.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT common definition for mort table (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmort0.c b/thirdparty/freetype/src/gxvalid/gxvmort0.c index 0c695aa4c7..fa6c7368f7 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmort0.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort0.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT mort table validation * body for type0 (Indic Script Rearrangement) subtable. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmort1.c b/thirdparty/freetype/src/gxvalid/gxvmort1.c index 0af22362f1..170acee2c7 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmort1.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort1.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT mort table validation * body for type1 (Contextual Substitution) subtable. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmort2.c b/thirdparty/freetype/src/gxvalid/gxvmort2.c index 73f418ea1e..faf446741b 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmort2.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort2.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT mort table validation * body for type2 (Ligature Substitution) subtable. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmort4.c b/thirdparty/freetype/src/gxvalid/gxvmort4.c index 1b0dd3edab..12555da82a 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmort4.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort4.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT mort table validation * body for type4 (Non-Contextual Glyph Substitution) subtable. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmort5.c b/thirdparty/freetype/src/gxvalid/gxvmort5.c index cfbf31208c..48caac4347 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmort5.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort5.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT mort table validation * body for type5 (Contextual Glyph Insertion) subtable. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx.c b/thirdparty/freetype/src/gxvalid/gxvmorx.c index babff51866..4b848b1e10 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmorx.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT morx table validation (body). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx.h b/thirdparty/freetype/src/gxvalid/gxvmorx.h index f155f18460..a849d573b3 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmorx.h +++ b/thirdparty/freetype/src/gxvalid/gxvmorx.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT common definition for morx table (specification). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx0.c b/thirdparty/freetype/src/gxvalid/gxvmorx0.c index e93cea9cca..7eb27d143e 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmorx0.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx0.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT morx table validation * body for type0 (Indic Script Rearrangement) subtable. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx1.c b/thirdparty/freetype/src/gxvalid/gxvmorx1.c index d380f8d1ad..6ffbf151bb 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmorx1.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx1.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT morx table validation * body for type1 (Contextual Substitution) subtable. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx2.c b/thirdparty/freetype/src/gxvalid/gxvmorx2.c index e7e008f069..eb79e9b408 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmorx2.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx2.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT morx table validation * body for type2 (Ligature Substitution) subtable. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx4.c b/thirdparty/freetype/src/gxvalid/gxvmorx4.c index e632e8d42a..30c602cb8a 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmorx4.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx4.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT morx table validation * body for "morx" type4 (Non-Contextual Glyph Substitution) subtable. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx5.c b/thirdparty/freetype/src/gxvalid/gxvmorx5.c index 5ad33976d7..afdef05a89 100644 --- a/thirdparty/freetype/src/gxvalid/gxvmorx5.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx5.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT morx table validation * body for type5 (Contextual Glyph Insertion) subtable. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvopbd.c b/thirdparty/freetype/src/gxvalid/gxvopbd.c index 7a2feab468..a6b04a4b17 100644 --- a/thirdparty/freetype/src/gxvalid/gxvopbd.c +++ b/thirdparty/freetype/src/gxvalid/gxvopbd.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT opbd table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvprop.c b/thirdparty/freetype/src/gxvalid/gxvprop.c index 98cd368845..bf1ed112fd 100644 --- a/thirdparty/freetype/src/gxvalid/gxvprop.c +++ b/thirdparty/freetype/src/gxvalid/gxvprop.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT prop table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gxvalid/gxvtrak.c b/thirdparty/freetype/src/gxvalid/gxvtrak.c index c1ed92872d..93ac3e76a9 100644 --- a/thirdparty/freetype/src/gxvalid/gxvtrak.c +++ b/thirdparty/freetype/src/gxvalid/gxvtrak.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT trak table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/thirdparty/freetype/src/gzip/README.freetype b/thirdparty/freetype/src/gzip/README.freetype new file mode 100644 index 0000000000..493b807198 --- /dev/null +++ b/thirdparty/freetype/src/gzip/README.freetype @@ -0,0 +1,22 @@ +Name: zlib +Short Name: zlib +URL: http://zlib.net/ +Version: 1.2.12 +License: see `zlib.h` + +Description: +"A massively spiffy yet delicately unobtrusive compression library." + +'zlib' is a free, general-purpose, legally unencumbered lossless +data-compression library. 'zlib' implements the "deflate" compression +algorithm described by RFC 1951, which combines the LZ77 (Lempel-Ziv) +algorithm with Huffman coding. zlib also implements the zlib (RFC 1950) and +gzip (RFC 1952) wrapper formats. + +Local Modifications: +The files in this directory have been prepared as follows. + + - Take the unmodified source code files from the zlib distribution that are + included by `ftgzip.c`. + - Run zlib's `zlib2ansi` script on all `.c` files. + - Apply the diff file(s) in the `patches` folder. diff --git a/thirdparty/freetype/src/gzip/adler32.c b/thirdparty/freetype/src/gzip/adler32.c index c53f9dd125..aa032e1ddf 100644 --- a/thirdparty/freetype/src/gzip/adler32.c +++ b/thirdparty/freetype/src/gzip/adler32.c @@ -1,48 +1,192 @@ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2002 Mark Adler + * Copyright (C) 1995-2011, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ -#include "zlib.h" +#include "zutil.h" -#define BASE 65521L /* largest prime smaller than 65536 */ +#ifndef Z_FREETYPE +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); +#endif + +#define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ -#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ +#ifdef NO_DIVIDE +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD(a) \ + do { \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE +#endif + /* ========================================================================= */ -ZEXPORT(uLong) adler32( /* adler, buf, len) */ +uLong ZEXPORT adler32_z( uLong adler, const Bytef *buf, - uInt len ) + z_size_t len) { - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } - if (buf == Z_NULL) return 1L; + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD28(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; DO16(buf); buf += 16; - k -= 16; } - if (k != 0) do { - s1 += *buf++; - s2 += s1; - } while (--k); - s1 %= BASE; - s2 %= BASE; + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); } - return (s2 << 16) | s1; + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32( + uLong adler, + const Bytef *buf, + uInt len) +{ + return adler32_z(adler, buf, len); +} + +#ifndef Z_FREETYPE + +/* ========================================================================= */ +local uLong adler32_combine_( + uLong adler1, + uLong adler2, + z_off64_t len2) +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + + /* the derivation of this formula is left as an exercise for the reader */ + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); } + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine( + uLong adler1, + uLong adler2, + z_off_t len2) +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64( + uLong adler1, + uLong adler2, + z_off64_t len2) +{ + return adler32_combine_(adler1, adler2, len2); +} + +#endif /* !Z_FREETYPE */ diff --git a/thirdparty/freetype/src/gzip/crc32.c b/thirdparty/freetype/src/gzip/crc32.c new file mode 100644 index 0000000000..2ddc32d1fb --- /dev/null +++ b/thirdparty/freetype/src/gzip/crc32.c @@ -0,0 +1,1116 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2022 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * This interleaved implementation of a CRC makes use of pipelined multiple + * arithmetic-logic units, commonly found in modern CPU cores. It is due to + * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + + MAKECRCH can be #defined to write out crc32.h. A main() routine is also + produced, so that this one source file can be compiled to an executable. + */ + +#ifdef MAKECRCH +# include <stdio.h> +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */ + + /* + A CRC of a message is computed on N braids of words in the message, where + each word consists of W bytes (4 or 8). If N is 3, for example, then three + running sparse CRCs are calculated respectively on each braid, at these + indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ... + This is done starting at a word boundary, and continues until as many blocks + of N * W bytes as are available have been processed. The results are combined + into a single CRC at the end. For this code, N must be in the range 1..6 and + W must be 4 or 8. The upper limit on N can be increased if desired by adding + more #if blocks, extending the patterns apparent in the code. In addition, + crc32.h would need to be regenerated, if the maximum N value is increased. + + N and W are chosen empirically by benchmarking the execution time on a given + processor. The choices for N and W below were based on testing on Intel Kaby + Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64 + Octeon II processors. The Intel, AMD, and ARM processors were all fastest + with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4. + They were all tested with either gcc or clang, all using the -O3 optimization + level. Your mileage may vary. + */ + +/* Define N */ +#ifdef Z_TESTN +# define N Z_TESTN +#else +# define N 5 +#endif +#if N < 1 || N > 6 +# error N must be in 1..6 +#endif + +/* + z_crc_t must be at least 32 bits. z_word_t must be at least as long as + z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and + that bytes are eight bits. + */ + +/* + Define W and the associated z_word_t type. If W is not defined, then a + braided calculation is not used, and the associated tables and code are not + compiled. + */ +#ifdef Z_TESTW +# if Z_TESTW-1 != -1 +# define W Z_TESTW +# endif +#else +# ifdef MAKECRCH +# define W 8 /* required for MAKECRCH */ +# else +# if defined(__x86_64__) || defined(__aarch64__) +# define W 8 +# else +# define W 4 +# endif +# endif +#endif +#ifdef W +# if W == 8 && defined(Z_U8) + typedef Z_U8 z_word_t; +# elif defined(Z_U4) +# undef W +# define W 4 + typedef Z_U4 z_word_t; +# else +# undef W +# endif +#endif + +/* Local functions. */ +local z_crc_t multmodp OF((z_crc_t a, z_crc_t b)); +local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); + +/* If available, use the ARM processor CRC32 instruction. */ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8 +# define ARMCRC32 +#endif + +#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) +/* + Swap the bytes in a z_word_t to convert between little and big endian. Any + self-respecting compiler will optimize this to a single machine byte-swap + instruction, if one is available. This assumes that word_t is either 32 bits + or 64 bits. + */ +local z_word_t byte_swap( + z_word_t word) +{ +# if W == 8 + return + (word & 0xff00000000000000) >> 56 | + (word & 0xff000000000000) >> 40 | + (word & 0xff0000000000) >> 24 | + (word & 0xff00000000) >> 8 | + (word & 0xff000000) << 8 | + (word & 0xff0000) << 24 | + (word & 0xff00) << 40 | + (word & 0xff) << 56; +# else /* W == 4 */ + return + (word & 0xff000000) >> 24 | + (word & 0xff0000) >> 8 | + (word & 0xff00) << 8 | + (word & 0xff) << 24; +# endif +} +#endif + +/* CRC polynomial. */ +#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ + +#ifdef DYNAMIC_CRC_TABLE + +local z_crc_t FAR crc_table[256]; +local z_crc_t FAR x2n_table[32]; +local void make_crc_table OF((void)); +#ifdef W + local z_word_t FAR crc_big_table[256]; + local z_crc_t FAR crc_braid_table[W][256]; + local z_word_t FAR crc_braid_big_table[W][256]; + local void braid OF((z_crc_t [][256], z_word_t [][256], int, int)); +#endif +#ifdef MAKECRCH + local void write_table OF((FILE *, const z_crc_t FAR *, int)); + local void write_table32hi OF((FILE *, const z_word_t FAR *, int)); + local void write_table64 OF((FILE *, const z_word_t FAR *, int)); +#endif /* MAKECRCH */ + +/* + Define a once() function depending on the availability of atomics. If this is + compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in + multiple threads, and if atomics are not available, then get_crc_table() must + be called to initialize the tables and must return before any threads are + allowed to compute or combine CRCs. + */ + +/* Definition of once functionality. */ +typedef struct once_s once_t; +local void once OF((once_t *, void (*)(void))); + +/* Check for the availability of atomics. */ +#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ + !defined(__STDC_NO_ATOMICS__) + +#include <stdatomic.h> + +/* Structure for once(), which must be initialized with ONCE_INIT. */ +struct once_s { + atomic_flag begun; + atomic_int done; +}; +#define ONCE_INIT {ATOMIC_FLAG_INIT, 0} + +/* + Run the provided init() function exactly once, even if multiple threads + invoke once() at the same time. The state must be a once_t initialized with + ONCE_INIT. + */ +local void once(state, init) + once_t *state; + void (*init)(void); +{ + if (!atomic_load(&state->done)) { + if (atomic_flag_test_and_set(&state->begun)) + while (!atomic_load(&state->done)) + ; + else { + init(); + atomic_store(&state->done, 1); + } + } +} + +#else /* no atomics */ + +/* Structure for once(), which must be initialized with ONCE_INIT. */ +struct once_s { + volatile int begun; + volatile int done; +}; +#define ONCE_INIT {0, 0} + +/* Test and set. Alas, not atomic, but tries to minimize the period of + vulnerability. */ +local int test_and_set OF((int volatile *)); +local int test_and_set( + int volatile *flag) +{ + int was; + + was = *flag; + *flag = 1; + return was; +} + +/* Run the provided init() function once. This is not thread-safe. */ +local void once(state, init) + once_t *state; + void (*init)(void); +{ + if (!state->done) { + if (test_and_set(&state->begun)) + while (!state->done) + ; + else { + init(); + state->done = 1; + } + } +} + +#endif + +/* State for once(). */ +local once_t made = ONCE_INIT; + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x + (which is shifting right by one and adding x^32 mod p if the bit shifted out + is a one). We start with the highest power (least significant bit) of q and + repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all the + information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. + */ + +local void make_crc_table() +{ + unsigned i, j, n; + z_crc_t p; + + /* initialize the CRC of bytes tables */ + for (i = 0; i < 256; i++) { + p = i; + for (j = 0; j < 8; j++) + p = p & 1 ? (p >> 1) ^ POLY : p >> 1; + crc_table[i] = p; +#ifdef W + crc_big_table[i] = byte_swap(p); +#endif + } + + /* initialize the x^2^n mod p(x) table */ + p = (z_crc_t)1 << 30; /* x^1 */ + x2n_table[0] = p; + for (n = 1; n < 32; n++) + x2n_table[n] = p = multmodp(p, p); + +#ifdef W + /* initialize the braiding tables -- needs x2n_table[] */ + braid(crc_braid_table, crc_braid_big_table, N, W); +#endif + +#ifdef MAKECRCH + { + /* + The crc32.h header file contains tables for both 32-bit and 64-bit + z_word_t's, and so requires a 64-bit type be available. In that case, + z_word_t must be defined to be 64-bits. This code then also generates + and writes out the tables for the case that z_word_t is 32 bits. + */ +#if !defined(W) || W != 8 +# error Need a 64-bit integer type in order to generate crc32.h. +#endif + FILE *out; + int k, n; + z_crc_t ltl[8][256]; + z_word_t big[8][256]; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + + /* write out little-endian CRC table to crc32.h */ + fprintf(out, + "/* crc32.h -- tables for rapid CRC calculation\n" + " * Generated automatically by crc32.c\n */\n" + "\n" + "local const z_crc_t FAR crc_table[] = {\n" + " "); + write_table(out, crc_table, 256); + fprintf(out, + "};\n"); + + /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#ifdef W\n" + "\n" + "#if W == 8\n" + "\n" + "local const z_word_t FAR crc_big_table[] = {\n" + " "); + write_table64(out, crc_big_table, 256); + fprintf(out, + "};\n"); + + /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#else /* W == 4 */\n" + "\n" + "local const z_word_t FAR crc_big_table[] = {\n" + " "); + write_table32hi(out, crc_big_table, 256); + fprintf(out, + "};\n" + "\n" + "#endif\n"); + + /* write out braid tables for each value of N */ + for (n = 1; n <= 6; n++) { + fprintf(out, + "\n" + "#if N == %d\n", n); + + /* compute braid tables for this N and 64-bit word_t */ + braid(ltl, big, n, 8); + + /* write out braid tables for 64-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#if W == 8\n" + "\n" + "local const z_crc_t FAR crc_braid_table[][256] = {\n"); + for (k = 0; k < 8; k++) { + fprintf(out, " {"); + write_table(out, ltl[k], 256); + fprintf(out, "}%s", k < 7 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); + for (k = 0; k < 8; k++) { + fprintf(out, " {"); + write_table64(out, big[k], 256); + fprintf(out, "}%s", k < 7 ? ",\n" : ""); + } + fprintf(out, + "};\n"); + + /* compute braid tables for this N and 32-bit word_t */ + braid(ltl, big, n, 4); + + /* write out braid tables for 32-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#else /* W == 4 */\n" + "\n" + "local const z_crc_t FAR crc_braid_table[][256] = {\n"); + for (k = 0; k < 4; k++) { + fprintf(out, " {"); + write_table(out, ltl[k], 256); + fprintf(out, "}%s", k < 3 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); + for (k = 0; k < 4; k++) { + fprintf(out, " {"); + write_table32hi(out, big[k], 256); + fprintf(out, "}%s", k < 3 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "#endif\n" + "\n" + "#endif\n"); + } + fprintf(out, + "\n" + "#endif\n"); + + /* write out zeros operator table to crc32.h */ + fprintf(out, + "\n" + "local const z_crc_t FAR x2n_table[] = {\n" + " "); + write_table(out, x2n_table, 32); + fprintf(out, + "};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH + +/* + Write the 32-bit values in table[0..k-1] to out, five per line in + hexadecimal separated by commas. + */ +local void write_table( + FILE *out, + const z_crc_t FAR *table, + int k) +{ + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", + (unsigned long)(table[n]), + n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); +} + +/* + Write the high 32-bits of each value in table[0..k-1] to out, five per line + in hexadecimal separated by commas. + */ +local void write_table32hi( + FILE *out, + const z_word_t FAR *table, + int k) +{ + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", + (unsigned long)(table[n] >> 32), + n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); +} + +/* + Write the 64-bit values in table[0..k-1] to out, three per line in + hexadecimal separated by commas. This assumes that if there is a 64-bit + type, then there is also a long long integer type, and it is at least 64 + bits. If not, then the type cast and format string can be adjusted + accordingly. + */ +local void write_table64( + FILE *out, + const z_word_t FAR *table, + int k) +{ + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ", + (unsigned long long)(table[n]), + n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", ")); +} + +/* Actually do the deed. */ +int main() +{ + make_crc_table(); + return 0; +} + +#endif /* MAKECRCH */ + +#ifdef W +/* + Generate the little and big-endian braid tables for the given n and z_word_t + size w. Each array must have room for w blocks of 256 elements. + */ +local void braid(ltl, big, n, w) + z_crc_t ltl[][256]; + z_word_t big[][256]; + int n; + int w; +{ + int k; + z_crc_t i, p, q; + for (k = 0; k < w; k++) { + p = x2nmodp((n * w + 3 - k) << 3, 0); + ltl[k][0] = 0; + big[w - 1 - k][0] = 0; + for (i = 1; i < 256; i++) { + ltl[k][i] = q = multmodp(i << 24, p); + big[w - 1 - k][i] = byte_swap(q); + } + } +} +#endif + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables for byte-wise and braided CRC-32 calculations, and a table of powers + * of x for combining CRC-32s, all made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ======================================================================== + * Routines used for CRC calculation. Some are also required for the table + * generation above. + */ + +/* + Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, + reflected. For speed, this requires that a not be zero. + */ +local z_crc_t multmodp( + z_crc_t a, + z_crc_t b) +{ + z_crc_t m, p; + + m = (z_crc_t)1 << 31; + p = 0; + for (;;) { + if (a & m) { + p ^= b; + if ((a & (m - 1)) == 0) + break; + } + m >>= 1; + b = b & 1 ? (b >> 1) ^ POLY : b >> 1; + } + return p; +} + +/* + Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been + initialized. + */ +local z_crc_t x2nmodp( + z_off64_t n, + unsigned k) +{ + z_crc_t p; + + p = (z_crc_t)1 << 31; /* x^0 == 1 */ + while (n) { + if (n & 1) + p = multmodp(x2n_table[k & 31], p); + n >>= 1; + k++; + } + return p; +} + +/* ========================================================================= + * This function can be used by asm versions of crc32(), and to force the + * generation of the CRC tables in a threaded application. + */ +const z_crc_t FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + return (const z_crc_t FAR *)crc_table; +} + +/* ========================================================================= + * Use ARM machine instructions if available. This will compute the CRC about + * ten times faster than the braided calculation. This code does not check for + * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will + * only be defined if the compilation specifies an ARM processor architecture + * that has the instructions. For example, compiling with -march=armv8.1-a or + * -march=armv8-a+crc, or -march=native if the compile machine has the crc32 + * instructions. + */ +#ifdef ARMCRC32 + +/* + Constants empirically determined to maximize speed. These values are from + measurements on a Cortex-A57. Your mileage may vary. + */ +#define Z_BATCH 3990 /* number of words in a batch */ +#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */ +#define Z_BATCH_MIN 800 /* fewest words in a final batch */ + +unsigned long ZEXPORT crc32_z( + unsigned long crc, + const unsigned char FAR *buf, + z_size_t len) +{ + z_crc_t val; + z_word_t crc1, crc2; + const z_word_t *word; + z_word_t val0, val1, val2; + z_size_t last, last2, i; + z_size_t num; + + /* Return initial CRC, if requested. */ + if (buf == Z_NULL) return 0; + +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + + /* Pre-condition the CRC */ + crc ^= 0xffffffff; + + /* Compute the CRC up to a word boundary. */ + while (len && ((z_size_t)buf & 7) != 0) { + len--; + val = *buf++; + __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); + } + + /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */ + word = (z_word_t const *)buf; + num = len >> 3; + len &= 7; + + /* Do three interleaved CRCs to realize the throughput of one crc32x + instruction per cycle. Each CRC is calcuated on Z_BATCH words. The three + CRCs are combined into a single CRC after each set of batches. */ + while (num >= 3 * Z_BATCH) { + crc1 = 0; + crc2 = 0; + for (i = 0; i < Z_BATCH; i++) { + val0 = word[i]; + val1 = word[i + Z_BATCH]; + val2 = word[i + 2 * Z_BATCH]; + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); + } + word += 3 * Z_BATCH; + num -= 3 * Z_BATCH; + crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1; + crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2; + } + + /* Do one last smaller batch with the remaining words, if there are enough + to pay for the combination of CRCs. */ + last = num / 3; + if (last >= Z_BATCH_MIN) { + last2 = last << 1; + crc1 = 0; + crc2 = 0; + for (i = 0; i < last; i++) { + val0 = word[i]; + val1 = word[i + last]; + val2 = word[i + last2]; + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); + } + word += 3 * last; + num -= 3 * last; + val = x2nmodp(last, 6); + crc = multmodp(val, crc) ^ crc1; + crc = multmodp(val, crc) ^ crc2; + } + + /* Compute the CRC on any remaining words. */ + for (i = 0; i < num; i++) { + val0 = word[i]; + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); + } + word += num; + + /* Complete the CRC on any remaining bytes. */ + buf = (const unsigned char FAR *)word; + while (len) { + len--; + val = *buf++; + __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); + } + + /* Return the CRC, post-conditioned. */ + return crc ^ 0xffffffff; +} + +#else + +#ifdef W + +/* + Return the CRC of the W bytes in the word_t data, taking the + least-significant byte of the word as the first byte of data, without any pre + or post conditioning. This is used to combine the CRCs of each braid. + */ +local z_crc_t crc_word( + z_word_t data) +{ + int k; + for (k = 0; k < W; k++) + data = (data >> 8) ^ crc_table[data & 0xff]; + return (z_crc_t)data; +} + +local z_word_t crc_word_big( + z_word_t data) +{ + int k; + for (k = 0; k < W; k++) + data = (data << 8) ^ + crc_big_table[(data >> ((W - 1) << 3)) & 0xff]; + return data; +} + +#endif + +/* ========================================================================= */ +unsigned long ZEXPORT crc32_z( + unsigned long crc, + const unsigned char FAR *buf, + z_size_t len) +{ + /* Return initial CRC, if requested. */ + if (buf == Z_NULL) return 0; + +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + + /* Pre-condition the CRC */ + crc ^= 0xffffffff; + +#ifdef W + + /* If provided enough bytes, do a braided CRC calculation. */ + if (len >= N * W + W - 1) { + z_size_t blks; + z_word_t const *words; + unsigned endian; + int k; + + /* Compute the CRC up to a z_word_t boundary. */ + while (len && ((z_size_t)buf & (W - 1)) != 0) { + len--; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + } + + /* Compute the CRC on as many N z_word_t blocks as are available. */ + blks = len / (N * W); + len -= blks * N * W; + words = (z_word_t const *)buf; + + /* Do endian check at execution time instead of compile time, since ARM + processors can change the endianess at execution time. If the + compiler knows what the endianess will be, it can optimize out the + check and the unused branch. */ + endian = 1; + if (*(unsigned char *)&endian) { + /* Little endian. */ + + z_crc_t crc0; + z_word_t word0; +#if N > 1 + z_crc_t crc1; + z_word_t word1; +#if N > 2 + z_crc_t crc2; + z_word_t word2; +#if N > 3 + z_crc_t crc3; + z_word_t word3; +#if N > 4 + z_crc_t crc4; + z_word_t word4; +#if N > 5 + z_crc_t crc5; + z_word_t word5; +#endif +#endif +#endif +#endif +#endif + + /* Initialize the CRC for each braid. */ + crc0 = crc; +#if N > 1 + crc1 = 0; +#if N > 2 + crc2 = 0; +#if N > 3 + crc3 = 0; +#if N > 4 + crc4 = 0; +#if N > 5 + crc5 = 0; +#endif +#endif +#endif +#endif +#endif + + /* + Process the first blks-1 blocks, computing the CRCs on each braid + independently. + */ + while (--blks) { + /* Load the word for each braid into registers. */ + word0 = crc0 ^ words[0]; +#if N > 1 + word1 = crc1 ^ words[1]; +#if N > 2 + word2 = crc2 ^ words[2]; +#if N > 3 + word3 = crc3 ^ words[3]; +#if N > 4 + word4 = crc4 ^ words[4]; +#if N > 5 + word5 = crc5 ^ words[5]; +#endif +#endif +#endif +#endif +#endif + words += N; + + /* Compute and update the CRC for each word. The loop should + get unrolled. */ + crc0 = crc_braid_table[0][word0 & 0xff]; +#if N > 1 + crc1 = crc_braid_table[0][word1 & 0xff]; +#if N > 2 + crc2 = crc_braid_table[0][word2 & 0xff]; +#if N > 3 + crc3 = crc_braid_table[0][word3 & 0xff]; +#if N > 4 + crc4 = crc_braid_table[0][word4 & 0xff]; +#if N > 5 + crc5 = crc_braid_table[0][word5 & 0xff]; +#endif +#endif +#endif +#endif +#endif + for (k = 1; k < W; k++) { + crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff]; +#if N > 1 + crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff]; +#if N > 2 + crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff]; +#if N > 3 + crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff]; +#if N > 4 + crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff]; +#if N > 5 + crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff]; +#endif +#endif +#endif +#endif +#endif + } + } + + /* + Process the last block, combining the CRCs of the N braids at the + same time. + */ + crc = crc_word(crc0 ^ words[0]); +#if N > 1 + crc = crc_word(crc1 ^ words[1] ^ crc); +#if N > 2 + crc = crc_word(crc2 ^ words[2] ^ crc); +#if N > 3 + crc = crc_word(crc3 ^ words[3] ^ crc); +#if N > 4 + crc = crc_word(crc4 ^ words[4] ^ crc); +#if N > 5 + crc = crc_word(crc5 ^ words[5] ^ crc); +#endif +#endif +#endif +#endif +#endif + words += N; + } + else { + /* Big endian. */ + + z_word_t crc0, word0, comb; +#if N > 1 + z_word_t crc1, word1; +#if N > 2 + z_word_t crc2, word2; +#if N > 3 + z_word_t crc3, word3; +#if N > 4 + z_word_t crc4, word4; +#if N > 5 + z_word_t crc5, word5; +#endif +#endif +#endif +#endif +#endif + + /* Initialize the CRC for each braid. */ + crc0 = byte_swap(crc); +#if N > 1 + crc1 = 0; +#if N > 2 + crc2 = 0; +#if N > 3 + crc3 = 0; +#if N > 4 + crc4 = 0; +#if N > 5 + crc5 = 0; +#endif +#endif +#endif +#endif +#endif + + /* + Process the first blks-1 blocks, computing the CRCs on each braid + independently. + */ + while (--blks) { + /* Load the word for each braid into registers. */ + word0 = crc0 ^ words[0]; +#if N > 1 + word1 = crc1 ^ words[1]; +#if N > 2 + word2 = crc2 ^ words[2]; +#if N > 3 + word3 = crc3 ^ words[3]; +#if N > 4 + word4 = crc4 ^ words[4]; +#if N > 5 + word5 = crc5 ^ words[5]; +#endif +#endif +#endif +#endif +#endif + words += N; + + /* Compute and update the CRC for each word. The loop should + get unrolled. */ + crc0 = crc_braid_big_table[0][word0 & 0xff]; +#if N > 1 + crc1 = crc_braid_big_table[0][word1 & 0xff]; +#if N > 2 + crc2 = crc_braid_big_table[0][word2 & 0xff]; +#if N > 3 + crc3 = crc_braid_big_table[0][word3 & 0xff]; +#if N > 4 + crc4 = crc_braid_big_table[0][word4 & 0xff]; +#if N > 5 + crc5 = crc_braid_big_table[0][word5 & 0xff]; +#endif +#endif +#endif +#endif +#endif + for (k = 1; k < W; k++) { + crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff]; +#if N > 1 + crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff]; +#if N > 2 + crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff]; +#if N > 3 + crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff]; +#if N > 4 + crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff]; +#if N > 5 + crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff]; +#endif +#endif +#endif +#endif +#endif + } + } + + /* + Process the last block, combining the CRCs of the N braids at the + same time. + */ + comb = crc_word_big(crc0 ^ words[0]); +#if N > 1 + comb = crc_word_big(crc1 ^ words[1] ^ comb); +#if N > 2 + comb = crc_word_big(crc2 ^ words[2] ^ comb); +#if N > 3 + comb = crc_word_big(crc3 ^ words[3] ^ comb); +#if N > 4 + comb = crc_word_big(crc4 ^ words[4] ^ comb); +#if N > 5 + comb = crc_word_big(crc5 ^ words[5] ^ comb); +#endif +#endif +#endif +#endif +#endif + words += N; + crc = byte_swap(comb); + } + + /* + Update the pointer to the remaining bytes to process. + */ + buf = (unsigned char const *)words; + } + +#endif /* W */ + + /* Complete the computation of the CRC on any remaining bytes. */ + while (len >= 8) { + len -= 8; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + } + while (len) { + len--; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + } + + /* Return the CRC, post-conditioned. */ + return crc ^ 0xffffffff; +} + +#endif + +/* ========================================================================= */ +unsigned long ZEXPORT crc32( + unsigned long crc, + const unsigned char FAR *buf, + uInt len) +{ + return crc32_z(crc, buf, len); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine64( + uLong crc1, + uLong crc2, + z_off64_t len2) +{ +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + return multmodp(x2nmodp(len2, 3), crc1) ^ crc2; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine( + uLong crc1, + uLong crc2, + z_off_t len2) +{ + return crc32_combine64(crc1, crc2, len2); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine_gen64( + z_off64_t len2) +{ +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + return x2nmodp(len2, 3); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine_gen( + z_off_t len2) +{ + return crc32_combine_gen64(len2); +} + +/* ========================================================================= */ +uLong crc32_combine_op( + uLong crc1, + uLong crc2, + uLong op) +{ + return multmodp(op, crc1) ^ crc2; +} diff --git a/thirdparty/freetype/src/gzip/crc32.h b/thirdparty/freetype/src/gzip/crc32.h new file mode 100644 index 0000000000..137df68d61 --- /dev/null +++ b/thirdparty/freetype/src/gzip/crc32.h @@ -0,0 +1,9446 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const z_crc_t FAR crc_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}; + +#ifdef W + +#if W == 8 + +local const z_word_t FAR crc_big_table[] = { + 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, + 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, + 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, + 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, + 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, + 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, + 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, + 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, + 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, + 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, + 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, + 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, + 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, + 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, + 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, + 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, + 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, + 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, + 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, + 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, + 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, + 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, + 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, + 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, + 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, + 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, + 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, + 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, + 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, + 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, + 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, + 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, + 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, + 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, + 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, + 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, + 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, + 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, + 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, + 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, + 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, + 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, + 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, + 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, + 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, + 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, + 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, + 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, + 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, + 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, + 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, + 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, + 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, + 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, + 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, + 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, + 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, + 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, + 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, + 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, + 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, + 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, + 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, + 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, + 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, + 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, + 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, + 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, + 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, + 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, + 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, + 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, + 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, + 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, + 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, + 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, + 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, + 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, + 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, + 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, + 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, + 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, + 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, + 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, + 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, + 0x8def022d00000000}; + +#else /* W == 4 */ + +local const z_word_t FAR crc_big_table[] = { + 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, + 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, + 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, + 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, + 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, + 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, + 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, + 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, + 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, + 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, + 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, + 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, + 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, + 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, + 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, + 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, + 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, + 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, + 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, + 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, + 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, + 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, + 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, + 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, + 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, + 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, + 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, + 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, + 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, + 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, + 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, + 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, + 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, + 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, + 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, + 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, + 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, + 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, + 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, + 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, + 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, + 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, + 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, + 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, + 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, + 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, + 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, + 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, + 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, + 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, + 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, + 0x8def022d}; + +#endif + +#if N == 1 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, + 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, + 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, + 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, + 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, + 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, + 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, + 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, + 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, + 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, + 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, + 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, + 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, + 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, + 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, + 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, + 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, + 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, + 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, + 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, + 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, + 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, + 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, + 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, + 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, + 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, + 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, + 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, + 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, + 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, + 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, + 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, + 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, + 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, + 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, + 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, + 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, + 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, + 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, + 0x264b06e6}, + {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, + 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, + 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, + 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, + 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, + 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, + 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, + 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, + 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, + 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, + 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, + 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, + 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, + 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, + 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, + 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, + 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, + 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, + 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, + 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, + 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, + 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, + 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, + 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, + 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, + 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, + 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, + 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, + 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, + 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, + 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, + 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, + 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, + 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, + 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, + 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, + 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, + 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, + 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, + 0x92364a30}, + {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, + 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, + 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, + 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, + 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, + 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, + 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, + 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, + 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, + 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, + 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, + 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, + 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, + 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, + 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, + 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, + 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, + 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, + 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, + 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, + 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, + 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, + 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, + 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, + 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, + 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, + 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, + 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, + 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, + 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, + 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, + 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, + 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, + 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, + 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, + 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, + 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, + 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, + 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, + 0xe4c4abcc}, + {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, + 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, + 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, + 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, + 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, + 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, + 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, + 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, + 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, + 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, + 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, + 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, + 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, + 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, + 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, + 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, + 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, + 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, + 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, + 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, + 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, + 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, + 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, + 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, + 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, + 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, + 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, + 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, + 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, + 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, + 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, + 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, + 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, + 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, + 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, + 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, + 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, + 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, + 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, + 0xca64c78c}, + {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, + 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, + 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, + 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, + 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, + 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, + 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, + 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, + 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, + 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, + 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, + 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, + 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, + 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, + 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, + 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, + 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, + 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, + 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, + 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, + 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, + 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, + 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, + 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, + 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, + 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, + 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, + 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, + 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, + 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, + 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, + 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, + 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, + 0xde0506f1}, + {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, + 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, + 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, + 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, + 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, + 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, + 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, + 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, + 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, + 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, + 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, + 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, + 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, + 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, + 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, + 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, + 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, + 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, + 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, + 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, + 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, + 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, + 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, + 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, + 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, + 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, + 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, + 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, + 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, + 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, + 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, + 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, + 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, + 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, + 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed}, + {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, + 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, + 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, + 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, + 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, + 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, + 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, + 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, + 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, + 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, + 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, + 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, + 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, + 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, + 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, + 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, + 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, + 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, + 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, + 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, + 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, + 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, + 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, + 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, + 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, + 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, + 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, + 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, + 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, + 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, + 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, + 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, + 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, + 0x9324fd72}, + {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, + 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, + 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, + 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, + 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, + 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, + 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, + 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, + 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, + 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, + 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, + 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, + 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, + 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, + 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, + 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, + 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, + 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, + 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, + 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, + 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, + 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, + 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, + 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, + 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, + 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, + 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, + 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, + 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, + 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, + 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, + 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, + 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, + 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, + 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, + 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, + 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, + 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, + 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, + 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, + 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, + 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, + 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, + 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, + 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, + 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, + 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, + 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, + 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, + 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, + 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, + 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, + 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, + 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, + 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, + 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, + 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, + 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, + 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, + 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, + 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, + 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, + 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, + 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, + 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, + 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, + 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, + 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, + 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, + 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, + 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, + 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, + 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, + 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, + 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, + 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, + 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, + 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, + 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, + 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, + 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, + 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, + 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, + 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, + 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, + 0x8def022d00000000}, + {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000, + 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000, + 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000, + 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000, + 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000, + 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000, + 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000, + 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000, + 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000, + 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000, + 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000, + 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000, + 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000, + 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000, + 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000, + 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000, + 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000, + 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000, + 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000, + 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000, + 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000, + 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000, + 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000, + 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000, + 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000, + 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000, + 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000, + 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000, + 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000, + 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000, + 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000, + 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000, + 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000, + 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000, + 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000, + 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000, + 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000, + 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000, + 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000, + 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000, + 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000, + 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000, + 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000, + 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000, + 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000, + 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000, + 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000, + 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000, + 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000, + 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000, + 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000, + 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000, + 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000, + 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000, + 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000, + 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000, + 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000, + 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000, + 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000, + 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000, + 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000, + 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000, + 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000, + 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000, + 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000, + 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000, + 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000, + 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000, + 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000, + 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000, + 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000, + 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000, + 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000, + 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000, + 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000, + 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000, + 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000, + 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000, + 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000, + 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000, + 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000, + 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000, + 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000, + 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000, + 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000, + 0x72fd249300000000}, + {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000, + 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000, + 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000, + 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000, + 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000, + 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000, + 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000, + 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000, + 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000, + 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000, + 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000, + 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000, + 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000, + 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000, + 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000, + 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000, + 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000, + 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000, + 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000, + 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000, + 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000, + 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000, + 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000, + 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000, + 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000, + 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000, + 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000, + 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000, + 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000, + 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000, + 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000, + 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000, + 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000, + 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000, + 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000, + 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000, + 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000, + 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000, + 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000, + 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000, + 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000, + 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000, + 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000, + 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000, + 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000, + 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000, + 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000, + 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000, + 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000, + 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000, + 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000, + 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000, + 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000, + 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000, + 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000, + 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000, + 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000, + 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000, + 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000, + 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000, + 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000, + 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000, + 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000, + 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000, + 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000, + 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000, + 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000, + 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000, + 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000, + 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000, + 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000, + 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000, + 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000, + 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000, + 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000, + 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000, + 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000, + 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000, + 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000, + 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000, + 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000, + 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000, + 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000, + 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000, + 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000, + 0xed3498be00000000}, + {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000, + 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000, + 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000, + 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000, + 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000, + 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000, + 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000, + 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000, + 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000, + 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000, + 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000, + 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000, + 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000, + 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000, + 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000, + 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000, + 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000, + 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000, + 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000, + 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000, + 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000, + 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000, + 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000, + 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000, + 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000, + 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000, + 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000, + 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000, + 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000, + 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000, + 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000, + 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000, + 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000, + 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000, + 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000, + 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000, + 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000, + 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000, + 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000, + 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000, + 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000, + 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000, + 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000, + 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000, + 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000, + 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000, + 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000, + 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000, + 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000, + 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000, + 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000, + 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000, + 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000, + 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000, + 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000, + 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000, + 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000, + 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000, + 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000, + 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000, + 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000, + 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000, + 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000, + 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000, + 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000, + 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000, + 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000, + 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000, + 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000, + 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000, + 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000, + 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000, + 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000, + 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000, + 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000, + 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000, + 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000, + 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000, + 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000, + 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000, + 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000, + 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000, + 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000, + 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000, + 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000, + 0xf10605de00000000}, + {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000, + 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000, + 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000, + 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000, + 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000, + 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000, + 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000, + 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000, + 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000, + 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000, + 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000, + 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000, + 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000, + 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000, + 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000, + 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000, + 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000, + 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000, + 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000, + 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000, + 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000, + 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000, + 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000, + 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000, + 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000, + 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000, + 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000, + 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000, + 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000, + 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000, + 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000, + 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000, + 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000, + 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000, + 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000, + 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000, + 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000, + 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000, + 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000, + 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000, + 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000, + 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000, + 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000, + 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000, + 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000, + 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000, + 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000, + 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000, + 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000, + 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000, + 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000, + 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000, + 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000, + 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000, + 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000, + 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000, + 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000, + 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000, + 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000, + 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000, + 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000, + 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000, + 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000, + 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000, + 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000, + 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000, + 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000, + 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000, + 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000, + 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000, + 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000, + 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000, + 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000, + 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000, + 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000, + 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000, + 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000, + 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000, + 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000, + 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000, + 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000, + 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000, + 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000, + 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000, + 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000, + 0x8cc764ca00000000}, + {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000, + 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000, + 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000, + 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000, + 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000, + 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000, + 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000, + 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000, + 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000, + 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000, + 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000, + 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000, + 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000, + 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000, + 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000, + 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000, + 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000, + 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000, + 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000, + 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000, + 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000, + 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000, + 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000, + 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000, + 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000, + 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000, + 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000, + 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000, + 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000, + 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000, + 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000, + 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000, + 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000, + 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000, + 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000, + 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000, + 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000, + 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000, + 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000, + 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000, + 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000, + 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000, + 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000, + 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000, + 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000, + 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000, + 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000, + 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000, + 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000, + 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000, + 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000, + 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000, + 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000, + 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000, + 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000, + 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000, + 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000, + 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000, + 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000, + 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000, + 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000, + 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000, + 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000, + 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000, + 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000, + 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000, + 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000, + 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000, + 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000, + 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000, + 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000, + 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000, + 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000, + 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000, + 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000, + 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000, + 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000, + 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000, + 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000, + 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000, + 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000, + 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000, + 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000, + 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000, + 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000, + 0xccabc4e400000000}, + {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000, + 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000, + 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000, + 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000, + 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000, + 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000, + 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000, + 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000, + 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000, + 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000, + 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000, + 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000, + 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000, + 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000, + 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000, + 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000, + 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000, + 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000, + 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000, + 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000, + 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000, + 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000, + 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000, + 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000, + 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000, + 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000, + 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000, + 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000, + 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000, + 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000, + 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000, + 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000, + 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000, + 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000, + 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000, + 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000, + 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000, + 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000, + 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000, + 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000, + 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000, + 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000, + 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000, + 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000, + 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000, + 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000, + 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000, + 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000, + 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000, + 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000, + 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000, + 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000, + 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000, + 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000, + 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000, + 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000, + 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000, + 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000, + 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000, + 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000, + 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000, + 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000, + 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000, + 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000, + 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000, + 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000, + 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000, + 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000, + 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000, + 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000, + 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000, + 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000, + 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000, + 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000, + 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000, + 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000, + 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000, + 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000, + 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000, + 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000, + 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000, + 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000, + 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000, + 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000, + 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000, + 0x304a369200000000}, + {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000, + 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000, + 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000, + 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000, + 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000, + 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000, + 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000, + 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000, + 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000, + 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000, + 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000, + 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000, + 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000, + 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000, + 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000, + 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000, + 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000, + 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000, + 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000, + 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000, + 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000, + 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000, + 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000, + 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000, + 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000, + 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000, + 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000, + 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000, + 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000, + 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000, + 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000, + 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000, + 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000, + 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000, + 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000, + 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000, + 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000, + 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000, + 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000, + 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000, + 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000, + 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000, + 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000, + 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000, + 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000, + 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000, + 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000, + 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000, + 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000, + 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000, + 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000, + 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000, + 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000, + 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000, + 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000, + 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000, + 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000, + 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000, + 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000, + 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000, + 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000, + 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000, + 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000, + 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000, + 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000, + 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000, + 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000, + 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000, + 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000, + 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000, + 0x6171384400000000, 0xff71928800000000, 0xe678578200000000, + 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000, + 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000, + 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000, + 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000, + 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000, + 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000, + 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000, + 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000, + 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000, + 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000, + 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000, + 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000, + 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000, + 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000, + 0xe6064b2600000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, + 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, + 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, + 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, + 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, + 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, + 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, + 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, + 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, + 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, + 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, + 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, + 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, + 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, + 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, + 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, + 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, + 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, + 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, + 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, + 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, + 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, + 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, + 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, + 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, + 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, + 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, + 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, + 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, + 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, + 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, + 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, + 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, + 0xde0506f1}, + {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, + 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, + 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, + 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, + 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, + 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, + 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, + 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, + 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, + 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, + 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, + 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, + 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, + 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, + 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, + 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, + 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, + 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, + 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, + 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, + 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, + 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, + 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, + 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, + 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, + 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, + 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, + 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, + 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, + 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, + 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, + 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, + 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, + 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, + 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed}, + {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, + 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, + 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, + 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, + 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, + 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, + 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, + 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, + 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, + 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, + 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, + 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, + 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, + 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, + 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, + 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, + 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, + 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, + 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, + 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, + 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, + 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, + 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, + 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, + 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, + 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, + 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, + 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, + 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, + 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, + 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, + 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, + 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, + 0x9324fd72}, + {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, + 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, + 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, + 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, + 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, + 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, + 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, + 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, + 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, + 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, + 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, + 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, + 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, + 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, + 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, + 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, + 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, + 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, + 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, + 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, + 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, + 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, + 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, + 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, + 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, + 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, + 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, + 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, + 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, + 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, + 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, + 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, + 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, + 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, + 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, + 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, + 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, + 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, + 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, + 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, + 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, + 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, + 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, + 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, + 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, + 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, + 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, + 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, + 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, + 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, + 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, + 0x8def022d}, + {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64, + 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1, + 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e, + 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61, + 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82, + 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff, + 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7, + 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da, + 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139, + 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6, + 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89, + 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c, + 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0, + 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d, + 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a, + 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177, + 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de, + 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b, + 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824, + 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e, + 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad, + 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0, + 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d, + 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60, + 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83, + 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822, + 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d, + 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8, + 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171, + 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c, + 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b, + 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6, + 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca, + 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f, + 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430, + 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf, + 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c, + 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51, + 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9, + 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84, + 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67, + 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398, + 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7, + 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62, + 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e, + 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923, + 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4, + 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9, + 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070, + 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5, + 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a, + 0x72fd2493}, + {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907, + 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f, + 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a, + 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e, + 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512, + 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14, + 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b, + 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d, + 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731, + 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925, + 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620, + 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28, + 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70, + 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176, + 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d, + 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b, + 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b, + 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63, + 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266, + 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a, + 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446, + 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40, + 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557, + 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51, + 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d, + 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0, + 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5, + 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed, + 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd, + 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb, + 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0, + 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6, + 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de, + 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6, + 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3, + 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7, + 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb, + 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd, + 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92, + 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094, + 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598, + 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c, + 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489, + 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81, + 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9, + 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af, + 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4, + 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2, + 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2, + 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba, + 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf, + 0xed3498be}, + {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f, + 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d, + 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0, + 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42, + 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95, + 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2, + 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a, + 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d, + 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea, + 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748, + 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5, + 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27, + 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b, + 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac, + 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4, + 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3, + 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44, + 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6, + 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b, + 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329, + 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe, + 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9, + 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1, + 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6, + 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921, + 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555, + 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8, + 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a, + 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd, + 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a, + 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2, + 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5, + 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2, + 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330, + 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad, + 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f, + 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8, + 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef, + 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc, + 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb, + 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c, + 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e, + 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03, + 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1, + 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6, + 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1, + 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9, + 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e, + 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409, + 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb, + 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966, + 0xf10605de}}; + +#endif + +#endif + +#if N == 2 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, + 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, + 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, + 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, + 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, + 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, + 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, + 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, + 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, + 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, + 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, + 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, + 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, + 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, + 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, + 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, + 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, + 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, + 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, + 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, + 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, + 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, + 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, + 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, + 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, + 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, + 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, + 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, + 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, + 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, + 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, + 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, + 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, + 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, + 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, + 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, + 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, + 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, + 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, + 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, + 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, + 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, + 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, + 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, + 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, + 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, + 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, + 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, + 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, + 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, + 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, + 0x0d7139d7}, + {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, + 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, + 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, + 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, + 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, + 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, + 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, + 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, + 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, + 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, + 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, + 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, + 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, + 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, + 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, + 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, + 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, + 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, + 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, + 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, + 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, + 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, + 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, + 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, + 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, + 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, + 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, + 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, + 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, + 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, + 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, + 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, + 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, + 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, + 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, + 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, + 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, + 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, + 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, + 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, + 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, + 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, + 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, + 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, + 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, + 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, + 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, + 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, + 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, + 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, + 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, + 0x1c53e98a}, + {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, + 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, + 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, + 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, + 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, + 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, + 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, + 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, + 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, + 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, + 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, + 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, + 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, + 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, + 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, + 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, + 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, + 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, + 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, + 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, + 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, + 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, + 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, + 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, + 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, + 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, + 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, + 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, + 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, + 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, + 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, + 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, + 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, + 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, + 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, + 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, + 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, + 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, + 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, + 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, + 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, + 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, + 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, + 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, + 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, + 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, + 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, + 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, + 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, + 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, + 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, + 0x3f88e851}, + {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, + 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, + 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, + 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, + 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, + 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, + 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, + 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, + 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, + 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, + 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, + 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, + 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, + 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, + 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, + 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, + 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, + 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, + 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, + 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, + 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, + 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, + 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, + 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, + 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, + 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, + 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, + 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, + 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, + 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, + 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, + 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, + 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, + 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, + 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, + 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, + 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, + 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, + 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, + 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, + 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, + 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, + 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, + 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, + 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, + 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, + 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, + 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, + 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, + 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, + 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, + 0x3dee8ca6}, + {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, + 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, + 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, + 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, + 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, + 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, + 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, + 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, + 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, + 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, + 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, + 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, + 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, + 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, + 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, + 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, + 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, + 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, + 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, + 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, + 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, + 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, + 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, + 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, + 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, + 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, + 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, + 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, + 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, + 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, + 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, + 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, + 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, + 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, + 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, + 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, + 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, + 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, + 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, + 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, + 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, + 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, + 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, + 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, + 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, + 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, + 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, + 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, + 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, + 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, + 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, + 0x36197165}, + {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, + 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, + 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, + 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, + 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, + 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, + 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, + 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, + 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, + 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, + 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, + 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, + 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, + 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, + 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, + 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, + 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, + 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, + 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, + 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, + 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, + 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, + 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, + 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, + 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, + 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, + 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, + 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, + 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, + 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, + 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, + 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, + 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, + 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, + 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, + 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, + 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, + 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, + 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, + 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, + 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, + 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, + 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, + 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, + 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, + 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, + 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, + 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, + 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, + 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, + 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, + 0x1a3b93aa}, + {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, + 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, + 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, + 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, + 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, + 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, + 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, + 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, + 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, + 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, + 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, + 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, + 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, + 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, + 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, + 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, + 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, + 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, + 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, + 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, + 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, + 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, + 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, + 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, + 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, + 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, + 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, + 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, + 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, + 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, + 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, + 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, + 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, + 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, + 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, + 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, + 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, + 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, + 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, + 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, + 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, + 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, + 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, + 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, + 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, + 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, + 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, + 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, + 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, + 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, + 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, + 0xe147d714}, + {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, + 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, + 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, + 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, + 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, + 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, + 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, + 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, + 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, + 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, + 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, + 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, + 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, + 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, + 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, + 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, + 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, + 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, + 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, + 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, + 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, + 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, + 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, + 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, + 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, + 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, + 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, + 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, + 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, + 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, + 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, + 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, + 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, + 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, + 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, + 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, + 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, + 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, + 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, + 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, + 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, + 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, + 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, + 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, + 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, + 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, + 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, + 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, + 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, + 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, + 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, + 0x494f0c4b}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000, + 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000, + 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000, + 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000, + 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000, + 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000, + 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000, + 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000, + 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000, + 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000, + 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000, + 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000, + 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000, + 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000, + 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000, + 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000, + 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000, + 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000, + 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000, + 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000, + 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000, + 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000, + 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000, + 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000, + 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000, + 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000, + 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000, + 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000, + 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000, + 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000, + 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000, + 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000, + 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000, + 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000, + 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000, + 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000, + 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000, + 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000, + 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000, + 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000, + 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000, + 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000, + 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000, + 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000, + 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000, + 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000, + 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000, + 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000, + 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000, + 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000, + 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000, + 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000, + 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000, + 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000, + 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000, + 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000, + 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000, + 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000, + 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000, + 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000, + 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000, + 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000, + 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000, + 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000, + 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000, + 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000, + 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000, + 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000, + 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000, + 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000, + 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000, + 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000, + 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000, + 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000, + 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000, + 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000, + 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000, + 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000, + 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000, + 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000, + 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000, + 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000, + 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000, + 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000, + 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000, + 0x4b0c4f4900000000}, + {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000, + 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000, + 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000, + 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000, + 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000, + 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000, + 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000, + 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000, + 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000, + 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000, + 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000, + 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000, + 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000, + 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000, + 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000, + 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000, + 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000, + 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000, + 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000, + 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000, + 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000, + 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000, + 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000, + 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000, + 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000, + 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000, + 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000, + 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000, + 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000, + 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000, + 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000, + 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000, + 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000, + 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000, + 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000, + 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000, + 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000, + 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000, + 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000, + 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000, + 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000, + 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000, + 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000, + 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000, + 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000, + 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000, + 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000, + 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000, + 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000, + 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000, + 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000, + 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000, + 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000, + 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000, + 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000, + 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000, + 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000, + 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000, + 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000, + 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000, + 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000, + 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000, + 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000, + 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000, + 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000, + 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000, + 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000, + 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000, + 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000, + 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000, + 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000, + 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000, + 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000, + 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000, + 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000, + 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000, + 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000, + 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000, + 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000, + 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000, + 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000, + 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000, + 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000, + 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000, + 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000, + 0x14d747e100000000}, + {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000, + 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000, + 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000, + 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000, + 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000, + 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000, + 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000, + 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000, + 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000, + 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000, + 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000, + 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000, + 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000, + 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000, + 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000, + 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000, + 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000, + 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000, + 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000, + 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000, + 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000, + 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000, + 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000, + 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000, + 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000, + 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000, + 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000, + 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000, + 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000, + 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000, + 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000, + 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000, + 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000, + 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000, + 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000, + 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000, + 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000, + 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000, + 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000, + 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000, + 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000, + 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000, + 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000, + 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000, + 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000, + 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000, + 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000, + 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000, + 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000, + 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000, + 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000, + 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000, + 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000, + 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000, + 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000, + 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000, + 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000, + 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000, + 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000, + 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000, + 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000, + 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000, + 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000, + 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000, + 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000, + 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000, + 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000, + 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000, + 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000, + 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000, + 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000, + 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000, + 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000, + 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000, + 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000, + 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000, + 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000, + 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000, + 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000, + 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000, + 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000, + 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000, + 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000, + 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000, + 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000, + 0xaa933b1a00000000}, + {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000, + 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000, + 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000, + 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000, + 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000, + 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000, + 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000, + 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000, + 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000, + 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000, + 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000, + 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000, + 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000, + 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000, + 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000, + 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000, + 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000, + 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000, + 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000, + 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000, + 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000, + 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000, + 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000, + 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000, + 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000, + 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000, + 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000, + 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000, + 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000, + 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000, + 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000, + 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000, + 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000, + 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000, + 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000, + 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000, + 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000, + 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000, + 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000, + 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000, + 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000, + 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000, + 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000, + 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000, + 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000, + 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000, + 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000, + 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000, + 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000, + 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000, + 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000, + 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000, + 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000, + 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000, + 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000, + 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000, + 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000, + 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000, + 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000, + 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000, + 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000, + 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000, + 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000, + 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000, + 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000, + 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000, + 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000, + 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000, + 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000, + 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000, + 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000, + 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000, + 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000, + 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000, + 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000, + 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000, + 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000, + 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000, + 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000, + 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000, + 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000, + 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000, + 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000, + 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000, + 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000, + 0x6571193600000000}, + {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000, + 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000, + 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000, + 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000, + 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000, + 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000, + 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000, + 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000, + 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000, + 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000, + 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000, + 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000, + 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000, + 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000, + 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000, + 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000, + 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000, + 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000, + 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000, + 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000, + 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000, + 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000, + 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000, + 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000, + 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000, + 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000, + 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000, + 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000, + 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000, + 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000, + 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000, + 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000, + 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000, + 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000, + 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000, + 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000, + 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000, + 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000, + 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000, + 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000, + 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000, + 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000, + 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000, + 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000, + 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000, + 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000, + 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000, + 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000, + 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000, + 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000, + 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000, + 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000, + 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000, + 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000, + 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000, + 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000, + 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000, + 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000, + 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000, + 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000, + 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000, + 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000, + 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000, + 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000, + 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000, + 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000, + 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000, + 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000, + 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000, + 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000, + 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000, + 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000, + 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000, + 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000, + 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000, + 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000, + 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000, + 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000, + 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000, + 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000, + 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000, + 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000, + 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000, + 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000, + 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000, + 0xa68cee3d00000000}, + {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000, + 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000, + 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000, + 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000, + 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000, + 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000, + 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000, + 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000, + 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000, + 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000, + 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000, + 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000, + 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000, + 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000, + 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000, + 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000, + 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000, + 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000, + 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000, + 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000, + 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000, + 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000, + 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000, + 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000, + 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000, + 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000, + 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000, + 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000, + 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000, + 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000, + 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000, + 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000, + 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000, + 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000, + 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000, + 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000, + 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000, + 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000, + 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000, + 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000, + 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000, + 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000, + 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000, + 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000, + 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000, + 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000, + 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000, + 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000, + 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000, + 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000, + 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000, + 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000, + 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000, + 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000, + 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000, + 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000, + 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000, + 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000, + 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000, + 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000, + 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000, + 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000, + 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000, + 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000, + 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000, + 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000, + 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000, + 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000, + 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000, + 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000, + 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000, + 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000, + 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000, + 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000, + 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000, + 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000, + 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000, + 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000, + 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000, + 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000, + 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000, + 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000, + 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000, + 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000, + 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000, + 0x51e8883f00000000}, + {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000, + 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000, + 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000, + 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000, + 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000, + 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000, + 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000, + 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000, + 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000, + 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000, + 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000, + 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000, + 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000, + 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000, + 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000, + 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000, + 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000, + 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000, + 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000, + 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000, + 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000, + 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000, + 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000, + 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000, + 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000, + 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000, + 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000, + 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000, + 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000, + 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000, + 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000, + 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000, + 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000, + 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000, + 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000, + 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000, + 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000, + 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000, + 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000, + 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000, + 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000, + 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000, + 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000, + 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000, + 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000, + 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000, + 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000, + 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000, + 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000, + 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000, + 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000, + 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000, + 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000, + 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000, + 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000, + 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000, + 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000, + 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000, + 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000, + 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000, + 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000, + 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000, + 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000, + 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000, + 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000, + 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000, + 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000, + 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000, + 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000, + 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000, + 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000, + 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000, + 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000, + 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000, + 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000, + 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000, + 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000, + 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000, + 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000, + 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000, + 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000, + 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000, + 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000, + 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000, + 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000, + 0x8ae9531c00000000}, + {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000, + 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000, + 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000, + 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000, + 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000, + 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000, + 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000, + 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000, + 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000, + 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000, + 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000, + 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000, + 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000, + 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000, + 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000, + 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000, + 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000, + 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000, + 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000, + 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000, + 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000, + 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000, + 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000, + 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000, + 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000, + 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000, + 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000, + 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000, + 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000, + 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000, + 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000, + 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000, + 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000, + 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000, + 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000, + 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000, + 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000, + 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000, + 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000, + 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000, + 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000, + 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000, + 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000, + 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000, + 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000, + 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000, + 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000, + 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000, + 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000, + 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000, + 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000, + 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000, + 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000, + 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000, + 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000, + 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000, + 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000, + 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000, + 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000, + 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000, + 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000, + 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000, + 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000, + 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000, + 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000, + 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000, + 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000, + 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000, + 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000, + 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000, + 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000, + 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000, + 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000, + 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000, + 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000, + 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000, + 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000, + 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000, + 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000, + 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000, + 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000, + 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000, + 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000, + 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000, + 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000, + 0xd739710d00000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, + 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, + 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, + 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, + 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, + 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, + 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, + 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, + 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, + 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, + 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, + 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, + 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, + 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, + 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, + 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, + 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, + 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, + 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, + 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, + 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, + 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, + 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, + 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, + 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, + 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, + 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, + 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, + 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, + 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, + 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, + 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, + 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, + 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, + 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, + 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, + 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, + 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, + 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, + 0x264b06e6}, + {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, + 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, + 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, + 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, + 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, + 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, + 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, + 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, + 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, + 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, + 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, + 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, + 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, + 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, + 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, + 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, + 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, + 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, + 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, + 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, + 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, + 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, + 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, + 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, + 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, + 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, + 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, + 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, + 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, + 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, + 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, + 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, + 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, + 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, + 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, + 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, + 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, + 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, + 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, + 0x92364a30}, + {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, + 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, + 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, + 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, + 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, + 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, + 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, + 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, + 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, + 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, + 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, + 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, + 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, + 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, + 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, + 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, + 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, + 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, + 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, + 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, + 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, + 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, + 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, + 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, + 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, + 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, + 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, + 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, + 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, + 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, + 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, + 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, + 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, + 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, + 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, + 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, + 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, + 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, + 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, + 0xe4c4abcc}, + {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, + 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, + 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, + 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, + 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, + 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, + 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, + 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, + 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, + 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, + 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, + 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, + 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, + 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, + 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, + 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, + 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, + 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, + 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, + 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, + 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, + 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, + 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, + 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, + 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, + 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, + 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, + 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, + 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, + 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, + 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, + 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, + 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, + 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, + 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, + 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, + 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, + 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, + 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, + 0xca64c78c}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5, + 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d, + 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf, + 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027, + 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050, + 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098, + 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb, + 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173, + 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104, + 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c, + 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e, + 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6, + 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358, + 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390, + 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312, + 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da, + 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd, + 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335, + 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387, + 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de, + 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9, + 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261, + 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283, + 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b, + 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c, + 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c, + 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e, + 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6, + 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1, + 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619, + 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b, + 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653, + 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785, + 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d, + 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf, + 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757, + 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720, + 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8, + 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593, + 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b, + 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c, + 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4, + 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506, + 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe, + 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428, + 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0, + 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462, + 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa, + 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd, + 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445, + 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7, + 0x8cc764ca}, + {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b, + 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27, + 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a, + 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285, + 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef, + 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf, + 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a, + 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a, + 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70, + 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf, + 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2, + 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e, + 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f, + 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f, + 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae, + 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe, + 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97, + 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b, + 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436, + 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e, + 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4, + 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4, + 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46, + 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716, + 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c, + 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5, + 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8, + 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774, + 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d, + 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d, + 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc, + 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec, + 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82, + 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e, + 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623, + 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c, + 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6, + 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6, + 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c, + 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c, + 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66, + 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9, + 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4, + 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978, + 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416, + 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946, + 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7, + 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7, + 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e, + 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32, + 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f, + 0xccabc4e4}, + {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4, + 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895, + 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50, + 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656, + 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154, + 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906, + 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258, + 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a, + 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08, + 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e, + 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb, + 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa, + 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44, + 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316, + 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0, + 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2, + 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7, + 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6, + 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73, + 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba, + 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8, + 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea, + 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b, + 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29, + 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b, + 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e, + 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb, + 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a, + 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef, + 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd, + 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b, + 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019, + 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3, + 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2, + 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417, + 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11, + 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13, + 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241, + 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b, + 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09, + 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b, + 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d, + 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8, + 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9, + 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003, + 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851, + 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7, + 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5, + 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190, + 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1, + 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134, + 0x304a3692}, + {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84, + 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f, + 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15, + 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2, + 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf, + 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7, + 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb, + 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3, + 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae, + 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749, + 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243, + 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8, + 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29, + 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61, + 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8, + 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0, + 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1, + 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a, + 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40, + 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e, + 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03, + 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b, + 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee, + 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6, + 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb, + 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f, + 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495, + 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e, + 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f, + 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067, + 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be, + 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6, + 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e, + 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5, + 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf, + 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958, + 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305, + 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d, + 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338, + 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370, + 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d, + 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca, + 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0, + 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b, + 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083, + 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb, + 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012, + 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a, + 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b, + 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0, + 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea, + 0xe6064b26}}; + +#endif + +#endif + +#if N == 3 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, + 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, + 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, + 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, + 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, + 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, + 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, + 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, + 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, + 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, + 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, + 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, + 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, + 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, + 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, + 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, + 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, + 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, + 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, + 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, + 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, + 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, + 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, + 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, + 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, + 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, + 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, + 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, + 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, + 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, + 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, + 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, + 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, + 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, + 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, + 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, + 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, + 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, + 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, + 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, + 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, + 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, + 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, + 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, + 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, + 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, + 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, + 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, + 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, + 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, + 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, + 0x09cd8551}, + {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, + 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, + 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, + 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, + 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, + 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, + 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, + 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, + 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, + 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, + 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, + 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, + 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, + 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, + 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, + 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, + 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, + 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, + 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, + 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, + 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, + 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, + 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, + 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, + 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, + 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, + 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, + 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, + 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, + 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, + 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, + 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, + 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, + 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, + 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, + 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, + 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, + 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, + 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, + 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, + 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, + 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, + 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, + 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, + 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, + 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, + 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, + 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, + 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, + 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, + 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, + 0x7bc97a0c}, + {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, + 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, + 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, + 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, + 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, + 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, + 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, + 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, + 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, + 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, + 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, + 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, + 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, + 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, + 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, + 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, + 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, + 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, + 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, + 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, + 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, + 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, + 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, + 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, + 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, + 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, + 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, + 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, + 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, + 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, + 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, + 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, + 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, + 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, + 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, + 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, + 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, + 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, + 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, + 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, + 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, + 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, + 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, + 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, + 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, + 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, + 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, + 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, + 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, + 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, + 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, + 0x7851a2ca}, + {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, + 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, + 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, + 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, + 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, + 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, + 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, + 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, + 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, + 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, + 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, + 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, + 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, + 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, + 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, + 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, + 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, + 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, + 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, + 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, + 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, + 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, + 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, + 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, + 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, + 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, + 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, + 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, + 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, + 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, + 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, + 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, + 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, + 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, + 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, + 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, + 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, + 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, + 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, + 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, + 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, + 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, + 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, + 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, + 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, + 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, + 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, + 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, + 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, + 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, + 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, + 0x566b6848}, + {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, + 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, + 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, + 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, + 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, + 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, + 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, + 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, + 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, + 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, + 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, + 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, + 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, + 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, + 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, + 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, + 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, + 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, + 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, + 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, + 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, + 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, + 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, + 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, + 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, + 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, + 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, + 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, + 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, + 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, + 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, + 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, + 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, + 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, + 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, + 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, + 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, + 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, + 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, + 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, + 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, + 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, + 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, + 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, + 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, + 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, + 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, + 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, + 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, + 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, + 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, + 0xd8ac6b35}, + {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, + 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, + 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, + 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, + 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, + 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, + 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, + 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, + 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, + 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, + 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, + 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, + 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, + 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, + 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, + 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, + 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, + 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, + 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, + 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, + 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, + 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, + 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, + 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, + 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, + 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, + 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, + 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, + 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, + 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, + 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, + 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, + 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, + 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, + 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, + 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, + 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, + 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, + 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, + 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, + 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, + 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, + 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, + 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, + 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, + 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, + 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, + 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, + 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, + 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, + 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, + 0xa140efa8}, + {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, + 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, + 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, + 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, + 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, + 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, + 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, + 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, + 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, + 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, + 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, + 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, + 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, + 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, + 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, + 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, + 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, + 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, + 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, + 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, + 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, + 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, + 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, + 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, + 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, + 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, + 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, + 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, + 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, + 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, + 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, + 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, + 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, + 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, + 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, + 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, + 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, + 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, + 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, + 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, + 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, + 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, + 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, + 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, + 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, + 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, + 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, + 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, + 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, + 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, + 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, + 0x917cd6a1}, + {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, + 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, + 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, + 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, + 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, + 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, + 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, + 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, + 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, + 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, + 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, + 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, + 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, + 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, + 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, + 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, + 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, + 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, + 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, + 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, + 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, + 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, + 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, + 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, + 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, + 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, + 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, + 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, + 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, + 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, + 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, + 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, + 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, + 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, + 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, + 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, + 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, + 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, + 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, + 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, + 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, + 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, + 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, + 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, + 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, + 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, + 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, + 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, + 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, + 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, + 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, + 0x18ba364e}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000, + 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000, + 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000, + 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000, + 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000, + 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000, + 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000, + 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000, + 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000, + 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000, + 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000, + 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000, + 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000, + 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000, + 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000, + 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000, + 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000, + 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000, + 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000, + 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000, + 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000, + 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000, + 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000, + 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000, + 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000, + 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000, + 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000, + 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000, + 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000, + 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000, + 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000, + 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000, + 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000, + 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000, + 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000, + 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000, + 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000, + 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000, + 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000, + 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000, + 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000, + 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000, + 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000, + 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000, + 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000, + 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000, + 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000, + 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000, + 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000, + 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000, + 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000, + 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000, + 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000, + 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000, + 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000, + 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000, + 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000, + 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000, + 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000, + 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000, + 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000, + 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000, + 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000, + 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000, + 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000, + 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000, + 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000, + 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000, + 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000, + 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000, + 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000, + 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000, + 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000, + 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000, + 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000, + 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000, + 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000, + 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000, + 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000, + 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000, + 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000, + 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000, + 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000, + 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000, + 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000, + 0x4e36ba1800000000}, + {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000, + 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000, + 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000, + 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000, + 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000, + 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000, + 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000, + 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000, + 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000, + 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000, + 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000, + 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000, + 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000, + 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000, + 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000, + 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000, + 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000, + 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000, + 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000, + 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000, + 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000, + 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000, + 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000, + 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000, + 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000, + 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000, + 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000, + 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000, + 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000, + 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000, + 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000, + 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000, + 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000, + 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000, + 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000, + 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000, + 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000, + 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000, + 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000, + 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000, + 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000, + 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000, + 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000, + 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000, + 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000, + 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000, + 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000, + 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000, + 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000, + 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000, + 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000, + 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000, + 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000, + 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000, + 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000, + 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000, + 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000, + 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000, + 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000, + 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000, + 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000, + 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000, + 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000, + 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000, + 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000, + 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000, + 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000, + 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000, + 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000, + 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000, + 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000, + 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000, + 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000, + 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000, + 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000, + 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000, + 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000, + 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000, + 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000, + 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000, + 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000, + 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000, + 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000, + 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000, + 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000, + 0xa1d67c9100000000}, + {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000, + 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000, + 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000, + 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000, + 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000, + 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000, + 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000, + 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000, + 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000, + 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000, + 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000, + 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000, + 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000, + 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000, + 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000, + 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000, + 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000, + 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000, + 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000, + 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000, + 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000, + 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000, + 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000, + 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000, + 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000, + 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000, + 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000, + 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000, + 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000, + 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000, + 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000, + 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000, + 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000, + 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000, + 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000, + 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000, + 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000, + 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000, + 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000, + 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000, + 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000, + 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000, + 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000, + 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000, + 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000, + 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000, + 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000, + 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000, + 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000, + 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000, + 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000, + 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000, + 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000, + 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000, + 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000, + 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000, + 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000, + 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000, + 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000, + 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000, + 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000, + 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000, + 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000, + 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000, + 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000, + 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000, + 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000, + 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000, + 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000, + 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000, + 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000, + 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000, + 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000, + 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000, + 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000, + 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000, + 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000, + 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000, + 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000, + 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000, + 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000, + 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000, + 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000, + 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000, + 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000, + 0xa8ef40a100000000}, + {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000, + 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000, + 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000, + 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000, + 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000, + 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000, + 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000, + 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000, + 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000, + 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000, + 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000, + 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000, + 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000, + 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000, + 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000, + 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000, + 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000, + 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000, + 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000, + 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000, + 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000, + 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000, + 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000, + 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000, + 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000, + 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000, + 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000, + 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000, + 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000, + 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000, + 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000, + 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000, + 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000, + 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000, + 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000, + 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000, + 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000, + 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000, + 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000, + 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000, + 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000, + 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000, + 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000, + 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000, + 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000, + 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000, + 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000, + 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000, + 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000, + 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000, + 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000, + 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000, + 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000, + 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000, + 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000, + 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000, + 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000, + 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000, + 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000, + 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000, + 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000, + 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000, + 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000, + 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000, + 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000, + 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000, + 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000, + 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000, + 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000, + 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000, + 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000, + 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000, + 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000, + 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000, + 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000, + 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000, + 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000, + 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000, + 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000, + 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000, + 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000, + 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000, + 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000, + 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000, + 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000, + 0x356bacd800000000}, + {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000, + 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000, + 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000, + 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000, + 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000, + 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000, + 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000, + 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000, + 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000, + 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000, + 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000, + 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000, + 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000, + 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000, + 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000, + 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000, + 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000, + 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000, + 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000, + 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000, + 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000, + 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000, + 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000, + 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000, + 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000, + 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000, + 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000, + 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000, + 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000, + 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000, + 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000, + 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000, + 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000, + 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000, + 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000, + 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000, + 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000, + 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000, + 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000, + 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000, + 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000, + 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000, + 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000, + 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000, + 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000, + 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000, + 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000, + 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000, + 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000, + 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000, + 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000, + 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000, + 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000, + 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000, + 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000, + 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000, + 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000, + 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000, + 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000, + 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000, + 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000, + 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000, + 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000, + 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000, + 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000, + 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000, + 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000, + 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000, + 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000, + 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000, + 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000, + 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000, + 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000, + 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000, + 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000, + 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000, + 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000, + 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000, + 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000, + 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000, + 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000, + 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000, + 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000, + 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000, + 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000, + 0x48686b5600000000}, + {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000, + 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000, + 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000, + 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000, + 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000, + 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000, + 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000, + 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000, + 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000, + 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000, + 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000, + 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000, + 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000, + 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000, + 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000, + 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000, + 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000, + 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000, + 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000, + 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000, + 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000, + 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000, + 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000, + 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000, + 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000, + 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000, + 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000, + 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000, + 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000, + 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000, + 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000, + 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000, + 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000, + 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000, + 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000, + 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000, + 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000, + 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000, + 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000, + 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000, + 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000, + 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000, + 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000, + 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000, + 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000, + 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000, + 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000, + 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000, + 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000, + 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000, + 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000, + 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000, + 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000, + 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000, + 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000, + 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000, + 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000, + 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000, + 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000, + 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000, + 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000, + 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000, + 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000, + 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000, + 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000, + 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000, + 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000, + 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000, + 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000, + 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000, + 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000, + 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000, + 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000, + 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000, + 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000, + 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000, + 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000, + 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000, + 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000, + 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000, + 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000, + 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000, + 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000, + 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000, + 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000, + 0xcaa2517800000000}, + {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000, + 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000, + 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000, + 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000, + 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000, + 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000, + 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000, + 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000, + 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000, + 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000, + 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000, + 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000, + 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000, + 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000, + 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000, + 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000, + 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000, + 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000, + 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000, + 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000, + 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000, + 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000, + 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000, + 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000, + 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000, + 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000, + 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000, + 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000, + 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000, + 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000, + 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000, + 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000, + 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000, + 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000, + 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000, + 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000, + 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000, + 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000, + 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000, + 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000, + 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000, + 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000, + 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000, + 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000, + 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000, + 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000, + 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000, + 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000, + 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000, + 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000, + 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000, + 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000, + 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000, + 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000, + 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000, + 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000, + 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000, + 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000, + 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000, + 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000, + 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000, + 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000, + 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000, + 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000, + 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000, + 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000, + 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000, + 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000, + 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000, + 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000, + 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000, + 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000, + 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000, + 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000, + 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000, + 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000, + 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000, + 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000, + 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000, + 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000, + 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000, + 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000, + 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000, + 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000, + 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000, + 0x0c7ac97b00000000}, + {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000, + 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000, + 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000, + 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000, + 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000, + 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000, + 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000, + 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000, + 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000, + 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000, + 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000, + 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000, + 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000, + 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000, + 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000, + 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000, + 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000, + 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000, + 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000, + 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000, + 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000, + 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000, + 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000, + 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000, + 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000, + 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000, + 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000, + 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000, + 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000, + 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000, + 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000, + 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000, + 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000, + 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000, + 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000, + 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000, + 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000, + 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000, + 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000, + 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000, + 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000, + 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000, + 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000, + 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000, + 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000, + 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000, + 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000, + 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000, + 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000, + 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000, + 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000, + 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000, + 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000, + 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000, + 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000, + 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000, + 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000, + 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000, + 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000, + 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000, + 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000, + 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000, + 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000, + 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000, + 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000, + 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000, + 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000, + 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000, + 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000, + 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000, + 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000, + 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000, + 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000, + 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000, + 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000, + 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000, + 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000, + 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000, + 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000, + 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000, + 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000, + 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000, + 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000, + 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000, + 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000, + 0x5185cd0900000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, + 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, + 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, + 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, + 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, + 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, + 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, + 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, + 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, + 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, + 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, + 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, + 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, + 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, + 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, + 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, + 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, + 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, + 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, + 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, + 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, + 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, + 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, + 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, + 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, + 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, + 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, + 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, + 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, + 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, + 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, + 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, + 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, + 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, + 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, + 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, + 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, + 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, + 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, + 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, + 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, + 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, + 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, + 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, + 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, + 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, + 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, + 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, + 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, + 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, + 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, + 0x36197165}, + {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, + 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, + 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, + 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, + 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, + 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, + 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, + 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, + 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, + 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, + 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, + 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, + 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, + 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, + 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, + 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, + 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, + 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, + 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, + 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, + 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, + 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, + 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, + 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, + 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, + 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, + 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, + 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, + 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, + 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, + 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, + 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, + 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, + 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, + 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, + 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, + 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, + 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, + 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, + 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, + 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, + 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, + 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, + 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, + 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, + 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, + 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, + 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, + 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, + 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, + 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, + 0x1a3b93aa}, + {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, + 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, + 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, + 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, + 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, + 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, + 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, + 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, + 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, + 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, + 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, + 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, + 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, + 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, + 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, + 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, + 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, + 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, + 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, + 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, + 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, + 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, + 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, + 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, + 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, + 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, + 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, + 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, + 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, + 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, + 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, + 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, + 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, + 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, + 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, + 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, + 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, + 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, + 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, + 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, + 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, + 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, + 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, + 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, + 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, + 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, + 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, + 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, + 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, + 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, + 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, + 0xe147d714}, + {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, + 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, + 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, + 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, + 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, + 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, + 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, + 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, + 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, + 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, + 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, + 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, + 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, + 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, + 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, + 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, + 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, + 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, + 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, + 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, + 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, + 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, + 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, + 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, + 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, + 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, + 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, + 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, + 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, + 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, + 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, + 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, + 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, + 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, + 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, + 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, + 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, + 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, + 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, + 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, + 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, + 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, + 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, + 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, + 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, + 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, + 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, + 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, + 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, + 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, + 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, + 0x494f0c4b}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d, + 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac, + 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8, + 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95, + 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817, + 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d, + 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac, + 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6, + 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564, + 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39, + 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d, + 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac, + 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de, + 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594, + 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b, + 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01, + 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f, + 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de, + 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba, + 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65, + 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7, + 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad, + 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de, + 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294, + 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716, + 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71, + 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15, + 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4, + 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca, + 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280, + 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f, + 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15, + 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9, + 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748, + 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c, + 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971, + 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3, + 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9, + 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196, + 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc, + 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e, + 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03, + 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67, + 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296, + 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a, + 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170, + 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af, + 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5, + 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb, + 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a, + 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e, + 0x4b0c4f49}, + {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09, + 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc, + 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e, + 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc, + 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934, + 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2, + 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b, + 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad, + 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155, + 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187, + 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65, + 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390, + 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e, + 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378, + 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889, + 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f, + 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0, + 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145, + 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7, + 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a, + 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2, + 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924, + 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2, + 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514, + 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec, + 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709, + 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb, + 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e, + 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1, + 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227, + 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6, + 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030, + 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0, + 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55, + 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7, + 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165, + 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d, + 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b, + 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c, + 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a, + 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362, + 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0, + 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52, + 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7, + 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237, + 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1, + 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020, + 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6, + 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719, + 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec, + 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e, + 0x14d747e1}, + {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0, + 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b, + 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652, + 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437, + 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514, + 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265, + 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de, + 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af, + 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c, + 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9, + 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0, + 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b, + 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6, + 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7, + 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734, + 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045, + 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8, + 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303, + 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a, + 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9, + 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea, + 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b, + 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6, + 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7, + 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4, + 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6, + 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f, + 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054, + 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9, + 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8, + 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b, + 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a, + 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441, + 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a, + 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3, + 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6, + 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5, + 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94, + 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9, + 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288, + 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab, + 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce, + 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7, + 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c, + 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527, + 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256, + 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5, + 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4, + 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39, + 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2, + 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db, + 0xaa933b1a}, + {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603, + 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d, + 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9, + 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b, + 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a, + 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792, + 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4, + 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c, + 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d, + 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f, + 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb, + 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65, + 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330, + 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8, + 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da, + 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742, + 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f, + 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1, + 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5, + 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f, + 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e, + 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6, + 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8, + 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250, + 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021, + 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb, + 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f, + 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511, + 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c, + 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4, + 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886, + 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e, + 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b, + 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5, + 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791, + 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003, + 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272, + 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea, + 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc, + 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24, + 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55, + 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7, + 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3, + 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d, + 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548, + 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0, + 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2, + 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a, + 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47, + 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9, + 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad, + 0x65711936}}; + +#endif + +#endif + +#if N == 4 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a, + 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe, + 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b, + 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656, + 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd, + 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d, + 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7, + 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47, + 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac, + 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691, + 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404, + 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0, + 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4, + 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424, + 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5, + 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65, + 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67, + 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3, + 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626, + 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9, + 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222, + 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2, + 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a, + 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a, + 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1, + 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2, + 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077, + 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3, + 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1, + 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621, + 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0, + 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60, + 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0, + 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64, + 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1, + 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc, + 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027, + 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7, + 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9, + 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79, + 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292, + 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af, + 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a, + 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee, + 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e, + 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe, + 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f, + 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff, + 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd, + 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29, + 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc, + 0xe3c45916}, + {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344, + 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59, + 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e, + 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463, + 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98, + 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d, + 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3, + 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656, + 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad, + 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0, + 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397, + 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a, + 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2, + 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357, + 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8, + 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d, + 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696, + 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b, + 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc, + 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0, + 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b, + 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be, + 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811, + 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384, + 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f, + 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955, + 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362, + 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f, + 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94, + 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701, + 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe, + 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b, + 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1, + 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc, + 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b, + 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986, + 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d, + 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8, + 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4, + 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371, + 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a, + 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87, + 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0, + 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad, + 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527, + 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2, + 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d, + 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998, + 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73, + 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e, + 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59, + 0xa7520488}, + {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20, + 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09, + 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431, + 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a, + 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203, + 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b, + 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14, + 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c, + 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25, + 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e, + 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36, + 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f, + 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649, + 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961, + 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58, + 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170, + 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b, + 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742, + 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a, + 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55, + 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c, + 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64, + 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f, + 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77, + 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e, + 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a, + 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2, + 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b, + 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090, + 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8, + 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881, + 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9, + 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6, + 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f, + 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7, + 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c, + 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695, + 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd, + 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb, + 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3, + 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa, + 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1, + 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9, + 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0, + 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df, + 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7, + 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace, + 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6, + 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd, + 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4, + 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec, + 0x3522e9e4}, + {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1, + 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86, + 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b, + 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669, + 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7, + 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352, + 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03, + 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6, + 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38, + 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a, + 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7, + 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80, + 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7, + 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522, + 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d, + 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8, + 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103, + 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54, + 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9, + 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0, + 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e, + 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb, + 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1, + 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624, + 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea, + 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a, + 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37, + 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360, + 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab, + 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e, + 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741, + 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4, + 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334, + 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63, + 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de, + 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c, + 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942, + 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7, + 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131, + 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4, + 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a, + 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758, + 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5, + 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2, + 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32, + 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7, + 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8, + 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d, + 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6, + 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1, + 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c, + 0x97411e28}, + {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474, + 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5, + 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6, + 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7, + 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938, + 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051, + 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a, + 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3, + 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c, + 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d, + 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e, + 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf, + 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740, + 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29, + 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592, + 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb, + 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4, + 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365, + 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036, + 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7, + 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08, + 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561, + 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a, + 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663, + 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac, + 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d, + 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce, + 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f, + 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50, + 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639, + 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82, + 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb, + 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954, + 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5, + 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86, + 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7, + 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418, + 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71, + 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa, + 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93, + 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c, + 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d, + 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e, + 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df, + 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60, + 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309, + 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2, + 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db, + 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4, + 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45, + 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16, + 0x93c7a00b}, + {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45, + 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb, + 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d, + 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696, + 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf, + 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb, + 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028, + 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c, + 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65, + 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be, + 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038, + 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6, + 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15, + 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11, + 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d, + 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19, + 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05, + 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b, + 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d, + 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c, + 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35, + 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31, + 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068, + 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c, + 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25, + 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a, + 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac, + 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22, + 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e, + 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a, + 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36, + 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32, + 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84, + 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a, + 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c, + 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057, + 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e, + 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a, + 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc, + 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8, + 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1, + 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a, + 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec, + 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62, + 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4, + 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0, + 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc, + 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8, + 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4, + 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a, + 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc, + 0xce5f968d}, + {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de, + 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b, + 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d, + 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680, + 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4, + 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d, + 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde, + 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97, + 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3, + 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e, + 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678, + 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d, + 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723, + 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a, + 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0, + 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9, + 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85, + 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770, + 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56, + 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a, + 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e, + 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67, + 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785, + 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc, + 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788, + 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90, + 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6, + 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843, + 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f, + 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336, + 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac, + 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5, + 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68, + 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d, + 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb, + 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36, + 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72, + 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b, + 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b, + 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402, + 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446, + 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb, + 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed, + 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418, + 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95, + 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc, + 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946, + 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f, + 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233, + 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6, + 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0, + 0x3e721277}, + {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb, + 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9, + 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11, + 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d, + 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9, + 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c, + 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881, + 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274, + 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790, + 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc, + 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514, + 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56, + 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9, + 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c, + 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13, + 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6, + 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c, + 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e, + 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386, + 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376, + 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692, + 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67, + 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416, + 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3, + 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07, + 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd, + 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15, + 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457, + 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd, + 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28, + 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337, + 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2, + 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594, + 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6, + 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e, + 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52, + 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6, + 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143, + 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17, + 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2, + 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306, + 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a, + 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182, + 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0, + 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496, + 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63, + 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c, + 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89, + 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903, + 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041, + 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9, + 0x1c65ace7}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000, + 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000, + 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000, + 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000, + 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000, + 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000, + 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000, + 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000, + 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000, + 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000, + 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000, + 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000, + 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000, + 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000, + 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000, + 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000, + 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000, + 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000, + 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000, + 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000, + 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000, + 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000, + 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000, + 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000, + 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000, + 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000, + 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000, + 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000, + 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000, + 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000, + 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000, + 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000, + 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000, + 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000, + 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000, + 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000, + 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000, + 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000, + 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000, + 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000, + 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000, + 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000, + 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000, + 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000, + 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000, + 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000, + 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000, + 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000, + 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000, + 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000, + 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000, + 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000, + 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000, + 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000, + 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000, + 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000, + 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000, + 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000, + 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000, + 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000, + 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000, + 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000, + 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000, + 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000, + 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000, + 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000, + 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000, + 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000, + 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000, + 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000, + 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000, + 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000, + 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000, + 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000, + 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000, + 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000, + 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000, + 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000, + 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000, + 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000, + 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000, + 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000, + 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000, + 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000, + 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000, + 0xe7ac651c00000000}, + {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000, + 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000, + 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000, + 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000, + 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000, + 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000, + 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000, + 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000, + 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000, + 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000, + 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000, + 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000, + 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000, + 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000, + 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000, + 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000, + 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000, + 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000, + 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000, + 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000, + 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000, + 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000, + 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000, + 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000, + 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000, + 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000, + 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000, + 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000, + 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000, + 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000, + 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000, + 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000, + 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000, + 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000, + 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000, + 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000, + 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000, + 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000, + 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000, + 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000, + 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000, + 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000, + 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000, + 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000, + 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000, + 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000, + 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000, + 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000, + 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000, + 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000, + 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000, + 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000, + 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000, + 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000, + 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000, + 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000, + 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000, + 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000, + 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000, + 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000, + 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000, + 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000, + 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000, + 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000, + 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000, + 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000, + 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000, + 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000, + 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000, + 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000, + 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000, + 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000, + 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000, + 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000, + 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000, + 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000, + 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000, + 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000, + 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000, + 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000, + 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000, + 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000, + 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000, + 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000, + 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000, + 0x7712723e00000000}, + {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000, + 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000, + 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000, + 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000, + 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000, + 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000, + 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000, + 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000, + 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000, + 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000, + 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000, + 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000, + 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000, + 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000, + 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000, + 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000, + 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000, + 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000, + 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000, + 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000, + 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000, + 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000, + 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000, + 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000, + 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000, + 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000, + 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000, + 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000, + 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000, + 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000, + 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000, + 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000, + 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000, + 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000, + 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000, + 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000, + 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000, + 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000, + 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000, + 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000, + 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000, + 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000, + 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000, + 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000, + 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000, + 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000, + 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000, + 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000, + 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000, + 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000, + 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000, + 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000, + 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000, + 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000, + 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000, + 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000, + 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000, + 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000, + 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000, + 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000, + 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000, + 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000, + 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000, + 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000, + 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000, + 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000, + 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000, + 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000, + 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000, + 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000, + 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000, + 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000, + 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000, + 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000, + 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000, + 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000, + 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000, + 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000, + 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000, + 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000, + 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000, + 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000, + 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000, + 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000, + 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000, + 0x8d965fce00000000}, + {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000, + 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000, + 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000, + 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000, + 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000, + 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000, + 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000, + 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000, + 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000, + 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000, + 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000, + 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000, + 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000, + 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000, + 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000, + 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000, + 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000, + 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000, + 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000, + 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000, + 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000, + 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000, + 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000, + 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000, + 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000, + 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000, + 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000, + 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000, + 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000, + 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000, + 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000, + 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000, + 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000, + 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000, + 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000, + 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000, + 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000, + 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000, + 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000, + 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000, + 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000, + 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000, + 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000, + 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000, + 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000, + 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000, + 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000, + 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000, + 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000, + 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000, + 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000, + 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000, + 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000, + 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000, + 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000, + 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000, + 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000, + 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000, + 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000, + 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000, + 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000, + 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000, + 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000, + 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000, + 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000, + 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000, + 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000, + 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000, + 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000, + 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000, + 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000, + 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000, + 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000, + 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000, + 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000, + 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000, + 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000, + 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000, + 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000, + 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000, + 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000, + 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000, + 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000, + 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000, + 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000, + 0x0ba0c79300000000}, + {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000, + 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000, + 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000, + 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000, + 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000, + 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000, + 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000, + 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000, + 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000, + 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000, + 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000, + 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000, + 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000, + 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000, + 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000, + 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000, + 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000, + 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000, + 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000, + 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000, + 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000, + 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000, + 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000, + 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000, + 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000, + 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000, + 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000, + 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000, + 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000, + 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000, + 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000, + 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000, + 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000, + 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000, + 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000, + 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000, + 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000, + 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000, + 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000, + 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000, + 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000, + 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000, + 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000, + 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000, + 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000, + 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000, + 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000, + 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000, + 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000, + 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000, + 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000, + 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000, + 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000, + 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000, + 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000, + 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000, + 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000, + 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000, + 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000, + 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000, + 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000, + 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000, + 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000, + 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000, + 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000, + 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000, + 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000, + 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000, + 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000, + 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000, + 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000, + 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000, + 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000, + 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000, + 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000, + 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000, + 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000, + 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000, + 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000, + 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000, + 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000, + 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000, + 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000, + 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000, + 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000, + 0x281e419700000000}, + {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000, + 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000, + 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000, + 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000, + 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000, + 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000, + 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000, + 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000, + 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000, + 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000, + 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000, + 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000, + 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000, + 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000, + 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000, + 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000, + 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000, + 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000, + 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000, + 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000, + 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000, + 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000, + 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000, + 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000, + 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000, + 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000, + 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000, + 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000, + 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000, + 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000, + 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000, + 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000, + 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000, + 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000, + 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000, + 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000, + 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000, + 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000, + 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000, + 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000, + 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000, + 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000, + 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000, + 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000, + 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000, + 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000, + 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000, + 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000, + 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000, + 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000, + 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000, + 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000, + 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000, + 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000, + 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000, + 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000, + 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000, + 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000, + 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000, + 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000, + 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000, + 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000, + 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000, + 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000, + 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000, + 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000, + 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000, + 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000, + 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000, + 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000, + 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000, + 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000, + 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000, + 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000, + 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000, + 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000, + 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000, + 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000, + 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000, + 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000, + 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000, + 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000, + 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000, + 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000, + 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000, + 0xe4e9223500000000}, + {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000, + 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000, + 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000, + 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000, + 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000, + 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000, + 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000, + 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000, + 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000, + 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000, + 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000, + 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000, + 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000, + 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000, + 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000, + 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000, + 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000, + 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000, + 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000, + 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000, + 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000, + 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000, + 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000, + 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000, + 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000, + 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000, + 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000, + 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000, + 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000, + 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000, + 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000, + 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000, + 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000, + 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000, + 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000, + 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000, + 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000, + 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000, + 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000, + 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000, + 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000, + 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000, + 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000, + 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000, + 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000, + 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000, + 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000, + 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000, + 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000, + 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000, + 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000, + 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000, + 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000, + 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000, + 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000, + 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000, + 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000, + 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000, + 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000, + 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000, + 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000, + 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000, + 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000, + 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000, + 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000, + 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000, + 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000, + 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000, + 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000, + 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000, + 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000, + 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000, + 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000, + 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000, + 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000, + 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000, + 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000, + 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000, + 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000, + 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000, + 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000, + 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000, + 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000, + 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000, + 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000, + 0x880452a700000000}, + {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000, + 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000, + 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000, + 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000, + 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000, + 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000, + 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000, + 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000, + 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000, + 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000, + 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000, + 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000, + 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000, + 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000, + 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000, + 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000, + 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000, + 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000, + 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000, + 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000, + 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000, + 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000, + 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000, + 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000, + 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000, + 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000, + 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000, + 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000, + 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000, + 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000, + 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000, + 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000, + 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000, + 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000, + 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000, + 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000, + 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000, + 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000, + 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000, + 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000, + 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000, + 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000, + 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000, + 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000, + 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000, + 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000, + 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000, + 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000, + 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000, + 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000, + 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000, + 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000, + 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000, + 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000, + 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000, + 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000, + 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000, + 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000, + 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000, + 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000, + 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000, + 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000, + 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000, + 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000, + 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000, + 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000, + 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000, + 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000, + 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000, + 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000, + 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000, + 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000, + 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000, + 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000, + 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000, + 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000, + 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000, + 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000, + 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000, + 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000, + 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000, + 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000, + 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000, + 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000, + 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000, + 0x1659c4e300000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, + 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, + 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, + 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, + 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, + 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, + 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, + 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, + 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, + 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, + 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, + 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, + 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, + 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, + 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, + 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, + 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, + 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, + 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, + 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, + 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, + 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, + 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, + 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, + 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, + 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, + 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, + 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, + 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, + 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, + 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, + 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, + 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, + 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, + 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, + 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, + 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, + 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, + 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, + 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, + 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, + 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, + 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, + 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, + 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, + 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, + 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, + 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, + 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, + 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, + 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, + 0x0d7139d7}, + {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, + 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, + 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, + 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, + 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, + 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, + 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, + 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, + 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, + 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, + 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, + 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, + 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, + 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, + 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, + 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, + 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, + 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, + 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, + 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, + 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, + 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, + 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, + 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, + 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, + 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, + 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, + 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, + 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, + 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, + 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, + 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, + 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, + 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, + 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, + 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, + 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, + 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, + 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, + 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, + 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, + 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, + 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, + 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, + 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, + 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, + 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, + 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, + 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, + 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, + 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, + 0x1c53e98a}, + {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, + 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, + 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, + 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, + 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, + 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, + 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, + 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, + 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, + 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, + 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, + 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, + 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, + 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, + 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, + 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, + 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, + 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, + 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, + 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, + 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, + 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, + 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, + 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, + 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, + 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, + 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, + 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, + 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, + 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, + 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, + 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, + 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, + 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, + 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, + 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, + 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, + 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, + 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, + 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, + 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, + 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, + 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, + 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, + 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, + 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, + 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, + 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, + 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, + 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, + 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, + 0x3f88e851}, + {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, + 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, + 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, + 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, + 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, + 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, + 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, + 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, + 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, + 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, + 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, + 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, + 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, + 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, + 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, + 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, + 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, + 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, + 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, + 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, + 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, + 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, + 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, + 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, + 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, + 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, + 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, + 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, + 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, + 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, + 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, + 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, + 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, + 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, + 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, + 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, + 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, + 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, + 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, + 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, + 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, + 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, + 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, + 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, + 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, + 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, + 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, + 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, + 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, + 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, + 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, + 0x3dee8ca6}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0, + 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587, + 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa, + 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09, + 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee, + 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3, + 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3, + 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce, + 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429, + 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda, + 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7, + 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0, + 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd, + 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0, + 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287, + 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a, + 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9, + 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e, + 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3, + 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3, + 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054, + 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49, + 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da, + 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7, + 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20, + 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d, + 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00, + 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347, + 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14, + 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209, + 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e, + 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33, + 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3, + 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194, + 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9, + 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a, + 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd, + 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0, + 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d, + 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460, + 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87, + 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674, + 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509, + 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e, + 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae, + 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3, + 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694, + 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989, + 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da, + 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d, + 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0, + 0xa68cee3d}, + {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19, + 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae, + 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb, + 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a, + 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55, + 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1, + 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c, + 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8, + 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7, + 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936, + 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453, + 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4, + 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941, + 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5, + 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93, + 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17, + 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e, + 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89, + 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec, + 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0, + 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf, + 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b, + 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b, + 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f, + 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0, + 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e, + 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b, + 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc, + 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5, + 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261, + 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637, + 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3, + 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57, + 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0, + 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85, + 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454, + 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b, + 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f, + 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423, + 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7, + 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8, + 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739, + 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c, + 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb, + 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f, + 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b, + 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd, + 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59, + 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070, + 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7, + 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2, + 0x51e8883f}, + {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a, + 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276, + 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed, + 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55, + 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b, + 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8, + 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320, + 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413, + 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd, + 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75, + 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee, + 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312, + 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca, + 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9, + 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad, + 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e, + 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504, + 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8, + 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63, + 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353, + 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d, + 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be, + 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae, + 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d, + 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943, + 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7, + 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c, + 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390, + 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a, + 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239, + 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d, + 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e, + 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c, + 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0, + 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b, + 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93, + 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d, + 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e, + 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c, + 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f, + 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1, + 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579, + 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2, + 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e, + 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c, + 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f, + 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b, + 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158, + 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2, + 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e, + 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5, + 0x8ae9531c}, + {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4, + 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd, + 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220, + 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf, + 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495, + 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def, + 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90, + 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea, + 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0, + 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f, + 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2, + 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab, + 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e, + 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754, + 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda, + 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0, + 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c, + 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215, + 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8, + 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910, + 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a, + 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30, + 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658, + 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22, + 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478, + 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2, + 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f, + 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606, + 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba, + 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0, + 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e, + 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034, + 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f, + 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996, + 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b, + 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84, + 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de, + 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4, + 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5, + 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f, + 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5, + 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a, + 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7, + 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce, + 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65, + 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f, + 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91, + 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb, + 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57, + 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e, + 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3, + 0xd739710d}}; + +#endif + +#endif + +#if N == 5 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df, + 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8, + 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef, + 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376, + 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201, + 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399, + 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372, + 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea, + 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d, + 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004, + 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353, + 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334, + 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a, + 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2, + 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a, + 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2, + 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b, + 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c, + 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b, + 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f, + 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338, + 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0, + 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6, + 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e, + 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319, + 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3, + 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4, + 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783, + 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a, + 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492, + 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a, + 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2, + 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496, + 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1, + 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6, + 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f, + 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548, + 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0, + 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741, + 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9, + 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae, + 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437, + 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760, + 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707, + 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433, + 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab, + 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703, + 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b, + 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412, + 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475, + 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722, + 0xe9947565}, + {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5, + 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22, + 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c, + 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed, + 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d, + 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1, + 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e, + 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32, + 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142, + 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93, + 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d, + 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a, + 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58, + 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14, + 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81, + 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd, + 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab, + 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c, + 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72, + 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f, + 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff, + 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3, + 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30, + 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c, + 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c, + 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558, + 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146, + 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581, + 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7, + 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab, + 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e, + 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272, + 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838, + 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff, + 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1, + 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330, + 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840, + 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c, + 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb, + 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7, + 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7, + 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616, + 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208, + 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf, + 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85, + 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9, + 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c, + 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10, + 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76, + 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1, + 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf, + 0xf7d05006}, + {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b, + 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774, + 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58, + 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a, + 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb, + 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952, + 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e, + 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7, + 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746, + 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14, + 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338, + 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907, + 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777, + 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de, + 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064, + 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd, + 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951, + 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e, + 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42, + 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b, + 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a, + 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3, + 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904, + 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad, + 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c, + 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d, + 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861, + 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e, + 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2, + 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b, + 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1, + 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78, + 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f, + 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40, + 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c, + 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e, + 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf, + 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166, + 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d, + 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4, + 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805, + 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157, + 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b, + 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644, + 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43, + 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea, + 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850, + 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9, + 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165, + 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a, + 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676, + 0xb2075b94}, + {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf, + 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61, + 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be, + 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd, + 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3, + 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063, + 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105, + 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5, + 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb, + 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8, + 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07, + 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9, + 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5, + 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515, + 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4, + 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014, + 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7, + 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269, + 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6, + 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af, + 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1, + 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111, + 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d, + 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad, + 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3, + 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75, + 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa, + 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74, + 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7, + 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477, + 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6, + 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176, + 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af, + 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71, + 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae, + 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd, + 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3, + 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073, + 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0, + 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400, + 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e, + 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d, + 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2, + 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c, + 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5, + 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505, + 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4, + 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004, + 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7, + 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279, + 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6, + 0xba50bcb9}, + {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897, + 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb, + 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2, + 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2, + 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372, + 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70, + 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92, + 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190, + 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40, + 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430, + 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759, + 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75, + 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2, + 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0, + 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7, + 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5, + 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39, + 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215, + 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c, + 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5, + 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625, + 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27, + 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c, + 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e, + 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee, + 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71, + 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18, + 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134, + 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8, + 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba, + 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd, + 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff, + 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a, + 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6, + 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf, + 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf, + 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f, + 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d, + 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d, + 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f, + 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af, + 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df, + 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6, + 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a, + 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef, + 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed, + 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa, + 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8, + 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624, + 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08, + 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861, + 0x808abcf4}, + {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2, + 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd, + 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76, + 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52, + 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e, + 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124, + 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147, + 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d, + 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31, + 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15, + 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae, + 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1, + 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d, + 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307, + 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9, + 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3, + 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084, + 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb, + 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850, + 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2, + 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe, + 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94, + 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261, + 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b, + 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917, + 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53, + 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8, + 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787, + 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0, + 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba, + 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404, + 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e, + 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af, + 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0, + 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b, + 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f, + 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543, + 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129, + 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627, + 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d, + 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51, + 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75, + 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce, + 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1, + 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760, + 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a, + 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4, + 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde, + 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089, + 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6, + 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d, + 0xefdb3f95}, + {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8, + 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7, + 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945, + 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9, + 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652, + 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc, + 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a, + 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4, + 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f, + 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3, + 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51, + 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e, + 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c, + 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362, + 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11, + 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff, + 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7, + 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8, + 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a, + 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690, + 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b, + 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5, + 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05, + 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb, + 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740, + 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f, + 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded, + 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2, + 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa, + 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714, + 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67, + 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89, + 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7, + 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8, + 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a, + 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6, + 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d, + 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3, + 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9, + 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57, + 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc, + 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540, + 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2, + 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd, + 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93, + 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d, + 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e, + 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0, + 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8, + 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7, + 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75, + 0x0e2fbf43}, + {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc, + 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a, + 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3, + 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7, + 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b, + 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154, + 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3, + 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc, + 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330, + 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264, + 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd, + 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b, + 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a, + 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175, + 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275, + 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a, + 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234, + 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2, + 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b, + 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a, + 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6, + 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189, + 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b, + 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204, + 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8, + 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226, + 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff, + 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219, + 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167, + 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258, + 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158, + 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267, + 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c, + 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da, + 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003, + 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157, + 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b, + 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4, + 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179, + 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246, + 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a, + 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de, + 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107, + 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1, + 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba, + 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285, + 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185, + 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba, + 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4, + 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322, + 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb, + 0xf4377108}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000, + 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000, + 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000, + 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000, + 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000, + 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000, + 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000, + 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000, + 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000, + 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000, + 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000, + 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000, + 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000, + 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000, + 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000, + 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000, + 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000, + 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000, + 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000, + 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000, + 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000, + 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000, + 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000, + 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000, + 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000, + 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000, + 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000, + 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000, + 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000, + 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000, + 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000, + 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000, + 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000, + 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000, + 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000, + 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000, + 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000, + 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000, + 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000, + 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000, + 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000, + 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000, + 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000, + 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000, + 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000, + 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000, + 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000, + 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000, + 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000, + 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000, + 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000, + 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000, + 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000, + 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000, + 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000, + 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000, + 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000, + 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000, + 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000, + 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000, + 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000, + 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000, + 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000, + 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000, + 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000, + 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000, + 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000, + 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000, + 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000, + 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000, + 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000, + 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000, + 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000, + 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000, + 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000, + 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000, + 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000, + 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000, + 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000, + 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000, + 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000, + 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000, + 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000, + 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000, + 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000, + 0x087137f400000000}, + {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000, + 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000, + 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000, + 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000, + 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000, + 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000, + 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000, + 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000, + 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000, + 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000, + 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000, + 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000, + 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000, + 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000, + 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000, + 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000, + 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000, + 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000, + 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000, + 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000, + 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000, + 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000, + 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000, + 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000, + 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000, + 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000, + 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000, + 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000, + 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000, + 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000, + 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000, + 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000, + 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000, + 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000, + 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000, + 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000, + 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000, + 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000, + 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000, + 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000, + 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000, + 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000, + 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000, + 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000, + 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000, + 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000, + 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000, + 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000, + 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000, + 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000, + 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000, + 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000, + 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000, + 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000, + 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000, + 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000, + 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000, + 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000, + 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000, + 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000, + 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000, + 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000, + 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000, + 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000, + 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000, + 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000, + 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000, + 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000, + 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000, + 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000, + 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000, + 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000, + 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000, + 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000, + 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000, + 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000, + 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000, + 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000, + 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000, + 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000, + 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000, + 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000, + 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000, + 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000, + 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000, + 0x43bf2f0e00000000}, + {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000, + 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000, + 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000, + 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000, + 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000, + 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000, + 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000, + 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000, + 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000, + 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000, + 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000, + 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000, + 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000, + 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000, + 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000, + 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000, + 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000, + 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000, + 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000, + 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000, + 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000, + 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000, + 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000, + 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000, + 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000, + 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000, + 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000, + 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000, + 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000, + 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000, + 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000, + 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000, + 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000, + 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000, + 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000, + 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000, + 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000, + 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000, + 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000, + 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000, + 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000, + 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000, + 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000, + 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000, + 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000, + 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000, + 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000, + 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000, + 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000, + 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000, + 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000, + 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000, + 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000, + 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000, + 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000, + 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000, + 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000, + 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000, + 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000, + 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000, + 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000, + 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000, + 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000, + 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000, + 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000, + 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000, + 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000, + 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000, + 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000, + 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000, + 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000, + 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000, + 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000, + 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000, + 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000, + 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000, + 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000, + 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000, + 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000, + 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000, + 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000, + 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000, + 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000, + 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000, + 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000, + 0x953fdbef00000000}, + {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000, + 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000, + 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000, + 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000, + 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000, + 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000, + 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000, + 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000, + 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000, + 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000, + 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000, + 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000, + 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000, + 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000, + 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000, + 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000, + 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000, + 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000, + 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000, + 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000, + 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000, + 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000, + 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000, + 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000, + 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000, + 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000, + 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000, + 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000, + 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000, + 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000, + 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000, + 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000, + 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000, + 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000, + 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000, + 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000, + 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000, + 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000, + 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000, + 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000, + 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000, + 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000, + 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000, + 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000, + 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000, + 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000, + 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000, + 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000, + 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000, + 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000, + 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000, + 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000, + 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000, + 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000, + 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000, + 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000, + 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000, + 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000, + 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000, + 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000, + 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000, + 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000, + 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000, + 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000, + 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000, + 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000, + 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000, + 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000, + 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000, + 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000, + 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000, + 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000, + 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000, + 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000, + 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000, + 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000, + 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000, + 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000, + 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000, + 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000, + 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000, + 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000, + 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000, + 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000, + 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000, + 0xf4bc8a8000000000}, + {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000, + 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000, + 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000, + 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000, + 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000, + 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000, + 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000, + 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000, + 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000, + 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000, + 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000, + 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000, + 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000, + 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000, + 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000, + 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000, + 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000, + 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000, + 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000, + 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000, + 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000, + 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000, + 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000, + 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000, + 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000, + 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000, + 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000, + 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000, + 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000, + 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000, + 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000, + 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000, + 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000, + 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000, + 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000, + 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000, + 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000, + 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000, + 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000, + 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000, + 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000, + 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000, + 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000, + 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000, + 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000, + 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000, + 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000, + 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000, + 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000, + 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000, + 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000, + 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000, + 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000, + 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000, + 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000, + 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000, + 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000, + 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000, + 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000, + 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000, + 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000, + 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000, + 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000, + 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000, + 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000, + 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000, + 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000, + 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000, + 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000, + 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000, + 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000, + 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000, + 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000, + 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000, + 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000, + 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000, + 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000, + 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000, + 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000, + 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000, + 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000, + 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000, + 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000, + 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000, + 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000, + 0xb9bc50ba00000000}, + {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000, + 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000, + 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000, + 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000, + 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000, + 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000, + 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000, + 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000, + 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000, + 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000, + 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000, + 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000, + 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000, + 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000, + 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000, + 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000, + 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000, + 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000, + 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000, + 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000, + 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000, + 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000, + 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000, + 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000, + 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000, + 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000, + 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000, + 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000, + 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000, + 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000, + 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000, + 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000, + 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000, + 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000, + 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000, + 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000, + 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000, + 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000, + 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000, + 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000, + 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000, + 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000, + 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000, + 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000, + 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000, + 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000, + 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000, + 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000, + 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000, + 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000, + 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000, + 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000, + 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000, + 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000, + 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000, + 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000, + 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000, + 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000, + 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000, + 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000, + 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000, + 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000, + 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000, + 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000, + 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000, + 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000, + 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000, + 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000, + 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000, + 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000, + 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000, + 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000, + 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000, + 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000, + 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000, + 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000, + 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000, + 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000, + 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000, + 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000, + 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000, + 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000, + 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000, + 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000, + 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000, + 0x945b07b200000000}, + {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000, + 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000, + 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000, + 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000, + 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000, + 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000, + 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000, + 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000, + 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000, + 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000, + 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000, + 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000, + 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000, + 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000, + 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000, + 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000, + 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000, + 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000, + 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000, + 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000, + 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000, + 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000, + 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000, + 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000, + 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000, + 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000, + 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000, + 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000, + 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000, + 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000, + 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000, + 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000, + 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000, + 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000, + 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000, + 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000, + 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000, + 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000, + 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000, + 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000, + 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000, + 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000, + 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000, + 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000, + 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000, + 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000, + 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000, + 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000, + 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000, + 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000, + 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000, + 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000, + 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000, + 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000, + 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000, + 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000, + 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000, + 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000, + 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000, + 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000, + 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000, + 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000, + 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000, + 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000, + 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000, + 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000, + 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000, + 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000, + 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000, + 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000, + 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000, + 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000, + 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000, + 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000, + 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000, + 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000, + 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000, + 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000, + 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000, + 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000, + 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000, + 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000, + 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000, + 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000, + 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000, + 0x0650d0f700000000}, + {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000, + 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000, + 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000, + 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000, + 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000, + 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000, + 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000, + 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000, + 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000, + 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000, + 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000, + 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000, + 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000, + 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000, + 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000, + 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000, + 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000, + 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000, + 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000, + 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000, + 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000, + 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000, + 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000, + 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000, + 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000, + 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000, + 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000, + 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000, + 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000, + 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000, + 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000, + 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000, + 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000, + 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000, + 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000, + 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000, + 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000, + 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000, + 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000, + 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000, + 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000, + 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000, + 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000, + 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000, + 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000, + 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000, + 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000, + 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000, + 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000, + 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000, + 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000, + 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000, + 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000, + 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000, + 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000, + 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000, + 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000, + 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000, + 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000, + 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000, + 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000, + 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000, + 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000, + 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000, + 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000, + 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000, + 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000, + 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000, + 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000, + 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000, + 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000, + 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000, + 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000, + 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000, + 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000, + 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000, + 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000, + 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000, + 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000, + 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000, + 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000, + 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000, + 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000, + 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000, + 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000, + 0x657594e900000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, + 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, + 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, + 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, + 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, + 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, + 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, + 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, + 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, + 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, + 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, + 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, + 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, + 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, + 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, + 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, + 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, + 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, + 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, + 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, + 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, + 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, + 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, + 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, + 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, + 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, + 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, + 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, + 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, + 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, + 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, + 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, + 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, + 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, + 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, + 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, + 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, + 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, + 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, + 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, + 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, + 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, + 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, + 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, + 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, + 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, + 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, + 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, + 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, + 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, + 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, + 0xd8ac6b35}, + {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, + 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, + 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, + 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, + 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, + 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, + 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, + 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, + 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, + 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, + 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, + 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, + 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, + 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, + 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, + 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, + 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, + 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, + 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, + 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, + 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, + 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, + 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, + 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, + 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, + 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, + 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, + 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, + 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, + 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, + 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, + 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, + 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, + 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, + 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, + 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, + 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, + 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, + 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, + 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, + 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, + 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, + 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, + 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, + 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, + 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, + 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, + 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, + 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, + 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, + 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, + 0xa140efa8}, + {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, + 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, + 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, + 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, + 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, + 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, + 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, + 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, + 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, + 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, + 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, + 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, + 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, + 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, + 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, + 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, + 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, + 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, + 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, + 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, + 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, + 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, + 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, + 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, + 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, + 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, + 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, + 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, + 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, + 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, + 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, + 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, + 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, + 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, + 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, + 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, + 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, + 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, + 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, + 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, + 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, + 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, + 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, + 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, + 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, + 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, + 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, + 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, + 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, + 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, + 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, + 0x917cd6a1}, + {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, + 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, + 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, + 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, + 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, + 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, + 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, + 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, + 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, + 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, + 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, + 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, + 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, + 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, + 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, + 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, + 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, + 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, + 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, + 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, + 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, + 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, + 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, + 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, + 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, + 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, + 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, + 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, + 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, + 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, + 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, + 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, + 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, + 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, + 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, + 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, + 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, + 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, + 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, + 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, + 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, + 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, + 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, + 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, + 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, + 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, + 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, + 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, + 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, + 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, + 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, + 0x18ba364e}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873, + 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661, + 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441, + 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44, + 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1, + 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05, + 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa, + 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e, + 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb, + 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be, + 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e, + 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c, + 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d, + 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9, + 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f, + 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b, + 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39, + 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b, + 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b, + 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20, + 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595, + 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61, + 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0, + 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644, + 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1, + 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d, + 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d, + 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f, + 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad, + 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359, + 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f, + 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b, + 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7, + 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5, + 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5, + 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0, + 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65, + 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091, + 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633, + 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7, + 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272, + 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77, + 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57, + 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145, + 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9, + 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d, + 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb, + 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f, + 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad, + 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf, + 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f, + 0x4e36ba18}, + {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b, + 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8, + 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19, + 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4, + 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239, + 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd, + 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258, + 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc, + 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41, + 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c, + 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d, + 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e, + 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba, + 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e, + 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8, + 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c, + 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f, + 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c, + 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d, + 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d, + 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0, + 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014, + 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc, + 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628, + 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5, + 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941, + 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0, + 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53, + 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880, + 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264, + 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92, + 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776, + 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8, + 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b, + 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea, + 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837, + 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca, + 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e, + 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211, + 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5, + 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08, + 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5, + 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934, + 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7, + 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049, + 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad, + 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b, + 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf, + 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c, + 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f, + 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e, + 0xa1d67c91}, + {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9, + 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de, + 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94, + 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0, + 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a, + 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924, + 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052, + 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c, + 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6, + 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2, + 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8, + 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f, + 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d, + 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273, + 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30, + 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e, + 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7, + 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980, + 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca, + 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8, + 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62, + 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c, + 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c, + 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032, + 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798, + 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d, + 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07, + 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630, + 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389, + 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7, + 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4, + 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca, + 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55, + 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662, + 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828, + 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c, + 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6, + 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98, + 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3, + 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d, + 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037, + 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913, + 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759, + 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e, + 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1, + 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf, + 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c, + 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2, + 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b, + 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c, + 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276, + 0xa8ef40a1}, + {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e, + 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8, + 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819, + 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f, + 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d, + 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756, + 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0, + 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb, + 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9, + 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f, + 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e, + 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8, + 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835, + 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e, + 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62, + 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749, + 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b, + 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d, + 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc, + 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80, + 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2, + 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599, + 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05, + 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e, + 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c, + 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e, + 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef, + 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359, + 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b, + 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0, + 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc, + 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7, + 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f, + 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189, + 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568, + 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e, + 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c, + 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27, + 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794, + 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf, + 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d, + 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db, + 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a, + 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c, + 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544, + 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f, + 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013, + 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38, + 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea, + 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c, + 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd, + 0x356bacd8}}; + +#endif + +#endif + +#if N == 6 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370, + 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d, + 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69, + 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426, + 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3, + 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f, + 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c, + 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490, + 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155, + 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a, + 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e, + 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603, + 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349, + 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5, + 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50, + 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc, + 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b, + 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76, + 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862, + 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9, + 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c, + 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0, + 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937, + 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b, + 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e, + 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e, + 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a, + 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357, + 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0, + 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c, + 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9, + 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165, + 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766, + 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b, + 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f, + 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030, + 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5, + 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59, + 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63, + 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf, + 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a, + 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845, + 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51, + 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c, + 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f, + 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3, + 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46, + 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea, + 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d, + 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60, + 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74, + 0x8568a0a8}, + {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5, + 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf, + 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5, + 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba, + 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf, + 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f, + 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0, + 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450, + 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55, + 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a, + 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620, + 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a, + 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454, + 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4, + 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534, + 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584, + 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694, + 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e, + 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4, + 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1, + 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4, + 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164, + 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1, + 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911, + 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314, + 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c, + 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6, + 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec, + 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc, + 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c, + 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c, + 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c, + 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716, + 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c, + 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676, + 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879, + 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c, + 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc, + 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77, + 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7, + 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2, + 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd, + 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7, + 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad, + 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897, + 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827, + 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7, + 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947, + 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57, + 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d, + 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37, + 0x0d907052}, + {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d, + 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89, + 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31, + 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81, + 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e, + 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0, + 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f, + 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291, + 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e, + 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e, + 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936, + 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2, + 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13, + 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d, + 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f, + 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1, + 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a, + 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae, + 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516, + 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f, + 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20, + 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe, + 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28, + 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6, + 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419, + 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5, + 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d, + 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889, + 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412, + 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c, + 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e, + 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0, + 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02, + 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986, + 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e, + 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e, + 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221, + 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf, + 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913, + 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d, + 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622, + 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592, + 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a, + 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae, + 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c, + 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82, + 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20, + 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe, + 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025, + 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1, + 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719, + 0xfd1a6c8a}, + {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3, + 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb, + 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d, + 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb, + 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9, + 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156, + 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045, + 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa, + 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8, + 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e, + 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8, + 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0, + 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38, + 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87, + 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46, + 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9, + 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585, + 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d, + 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb, + 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531, + 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03, + 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc, + 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33, + 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c, + 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be, + 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d, + 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b, + 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303, + 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f, + 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0, + 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801, + 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe, + 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e, + 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346, + 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620, + 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776, + 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844, + 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb, + 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0, + 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f, + 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d, + 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b, + 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d, + 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75, + 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795, + 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a, + 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb, + 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354, + 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28, + 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30, + 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856, + 0x7895f01a}, + {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188, + 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33, + 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d, + 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445, + 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2, + 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058, + 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43, + 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9, + 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e, + 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06, + 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228, + 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93, + 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e, + 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4, + 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b, + 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371, + 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265, + 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede, + 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0, + 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f, + 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8, + 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32, + 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae, + 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544, + 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3, + 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f, + 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911, + 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa, + 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be, + 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54, + 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b, + 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1, + 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652, + 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9, + 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7, + 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f, + 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68, + 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782, + 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797, + 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d, + 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a, + 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2, + 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc, + 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647, + 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4, + 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e, + 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41, + 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab, + 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf, + 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904, + 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a, + 0x9239b848}, + {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad, + 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0, + 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40, + 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b, + 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d, + 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b, + 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb, + 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d, + 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b, + 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0, + 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840, + 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d, + 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b, + 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d, + 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6, + 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0, + 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580, + 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd, + 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d, + 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b, + 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d, + 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b, + 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6, + 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0, + 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6, + 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c, + 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c, + 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461, + 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841, + 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317, + 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac, + 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa, + 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7, + 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba, + 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a, + 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161, + 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777, + 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21, + 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a, + 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc, + 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da, + 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1, + 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01, + 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c, + 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241, + 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917, + 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac, + 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa, + 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da, + 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397, + 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537, + 0xeb36d3cc}, + {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b, + 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059, + 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251, + 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d, + 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9, + 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c, + 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41, + 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4, + 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10, + 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c, + 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54, + 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476, + 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8, + 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d, + 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92, + 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307, + 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad, + 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f, + 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87, + 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17, + 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3, + 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46, + 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197, + 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02, + 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6, + 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e, + 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96, + 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4, + 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e, + 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b, + 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934, + 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1, + 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7, + 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5, + 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd, + 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1, + 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475, + 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0, + 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155, + 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0, + 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304, + 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348, + 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140, + 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862, + 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14, + 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181, + 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e, + 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab, + 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01, + 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523, + 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b, + 0x38e5f3c5}, + {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06, + 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad, + 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509, + 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba, + 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414, + 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3, + 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733, + 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994, + 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a, + 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889, + 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d, + 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386, + 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621, + 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886, + 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e, + 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389, + 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f, + 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294, + 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30, + 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3, + 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d, + 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba, + 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a, + 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad, + 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03, + 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2, + 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306, + 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad, + 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b, + 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc, + 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914, + 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3, + 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435, + 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e, + 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a, + 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589, + 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27, + 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080, + 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21, + 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586, + 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28, + 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b, + 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f, + 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94, + 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12, + 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5, + 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d, + 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba, + 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c, + 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7, + 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103, + 0x3d3101a2}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000, + 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000, + 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000, + 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000, + 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000, + 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000, + 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000, + 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000, + 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000, + 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000, + 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000, + 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000, + 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000, + 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000, + 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000, + 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000, + 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000, + 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000, + 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000, + 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000, + 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000, + 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000, + 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000, + 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000, + 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000, + 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000, + 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000, + 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000, + 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000, + 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000, + 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000, + 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000, + 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000, + 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000, + 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000, + 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000, + 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000, + 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000, + 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000, + 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000, + 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000, + 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000, + 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000, + 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000, + 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000, + 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000, + 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000, + 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000, + 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000, + 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000, + 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000, + 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000, + 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000, + 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000, + 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000, + 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000, + 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000, + 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000, + 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000, + 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000, + 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000, + 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000, + 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000, + 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000, + 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000, + 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000, + 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000, + 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000, + 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000, + 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000, + 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000, + 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000, + 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000, + 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000, + 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000, + 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000, + 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000, + 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000, + 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000, + 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000, + 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000, + 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000, + 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000, + 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000, + 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000, + 0xa201313d00000000}, + {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000, + 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000, + 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000, + 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000, + 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000, + 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000, + 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000, + 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000, + 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000, + 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000, + 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000, + 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000, + 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000, + 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000, + 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000, + 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000, + 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000, + 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000, + 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000, + 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000, + 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000, + 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000, + 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000, + 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000, + 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000, + 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000, + 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000, + 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000, + 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000, + 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000, + 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000, + 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000, + 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000, + 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000, + 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000, + 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000, + 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000, + 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000, + 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000, + 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000, + 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000, + 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000, + 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000, + 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000, + 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000, + 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000, + 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000, + 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000, + 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000, + 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000, + 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000, + 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000, + 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000, + 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000, + 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000, + 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000, + 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000, + 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000, + 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000, + 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000, + 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000, + 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000, + 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000, + 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000, + 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000, + 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000, + 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000, + 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000, + 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000, + 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000, + 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000, + 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000, + 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000, + 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000, + 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000, + 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000, + 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000, + 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000, + 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000, + 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000, + 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000, + 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000, + 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000, + 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000, + 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000, + 0xc5f3e53800000000}, + {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000, + 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000, + 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000, + 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000, + 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000, + 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000, + 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000, + 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000, + 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000, + 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000, + 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000, + 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000, + 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000, + 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000, + 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000, + 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000, + 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000, + 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000, + 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000, + 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000, + 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000, + 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000, + 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000, + 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000, + 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000, + 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000, + 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000, + 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000, + 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000, + 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000, + 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000, + 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000, + 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000, + 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000, + 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000, + 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000, + 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000, + 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000, + 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000, + 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000, + 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000, + 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000, + 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000, + 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000, + 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000, + 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000, + 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000, + 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000, + 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000, + 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000, + 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000, + 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000, + 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000, + 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000, + 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000, + 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000, + 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000, + 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000, + 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000, + 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000, + 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000, + 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000, + 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000, + 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000, + 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000, + 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000, + 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000, + 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000, + 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000, + 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000, + 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000, + 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000, + 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000, + 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000, + 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000, + 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000, + 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000, + 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000, + 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000, + 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000, + 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000, + 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000, + 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000, + 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000, + 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000, + 0xccd336eb00000000}, + {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000, + 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000, + 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000, + 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000, + 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000, + 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000, + 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000, + 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000, + 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000, + 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000, + 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000, + 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000, + 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000, + 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000, + 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000, + 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000, + 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000, + 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000, + 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000, + 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000, + 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000, + 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000, + 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000, + 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000, + 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000, + 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000, + 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000, + 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000, + 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000, + 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000, + 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000, + 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000, + 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000, + 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000, + 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000, + 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000, + 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000, + 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000, + 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000, + 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000, + 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000, + 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000, + 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000, + 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000, + 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000, + 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000, + 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000, + 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000, + 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000, + 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000, + 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000, + 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000, + 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000, + 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000, + 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000, + 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000, + 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000, + 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000, + 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000, + 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000, + 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000, + 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000, + 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000, + 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000, + 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000, + 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000, + 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000, + 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000, + 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000, + 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000, + 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000, + 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000, + 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000, + 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000, + 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000, + 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000, + 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000, + 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000, + 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000, + 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000, + 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000, + 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000, + 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000, + 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000, + 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000, + 0x48b8399200000000}, + {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000, + 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000, + 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000, + 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000, + 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000, + 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000, + 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000, + 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000, + 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000, + 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000, + 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000, + 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000, + 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000, + 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000, + 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000, + 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000, + 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000, + 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000, + 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000, + 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000, + 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000, + 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000, + 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000, + 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000, + 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000, + 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000, + 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000, + 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000, + 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000, + 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000, + 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000, + 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000, + 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000, + 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000, + 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000, + 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000, + 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000, + 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000, + 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000, + 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000, + 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000, + 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000, + 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000, + 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000, + 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000, + 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000, + 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000, + 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000, + 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000, + 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000, + 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000, + 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000, + 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000, + 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000, + 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000, + 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000, + 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000, + 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000, + 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000, + 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000, + 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000, + 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000, + 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000, + 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000, + 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000, + 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000, + 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000, + 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000, + 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000, + 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000, + 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000, + 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000, + 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000, + 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000, + 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000, + 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000, + 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000, + 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000, + 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000, + 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000, + 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000, + 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000, + 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000, + 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000, + 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000, + 0x1af0957800000000}, + {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000, + 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000, + 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000, + 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000, + 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000, + 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000, + 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000, + 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000, + 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000, + 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000, + 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000, + 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000, + 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000, + 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000, + 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000, + 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000, + 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000, + 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000, + 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000, + 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000, + 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000, + 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000, + 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000, + 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000, + 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000, + 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000, + 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000, + 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000, + 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000, + 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000, + 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000, + 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000, + 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000, + 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000, + 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000, + 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000, + 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000, + 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000, + 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000, + 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000, + 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000, + 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000, + 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000, + 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000, + 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000, + 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000, + 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000, + 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000, + 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000, + 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000, + 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000, + 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000, + 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000, + 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000, + 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000, + 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000, + 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000, + 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000, + 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000, + 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000, + 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000, + 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000, + 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000, + 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000, + 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000, + 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000, + 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000, + 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000, + 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000, + 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000, + 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000, + 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000, + 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000, + 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000, + 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000, + 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000, + 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000, + 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000, + 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000, + 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000, + 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000, + 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000, + 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000, + 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000, + 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000, + 0x8a6c1afd00000000}, + {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000, + 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000, + 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000, + 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000, + 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000, + 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000, + 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000, + 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000, + 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000, + 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000, + 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000, + 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000, + 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000, + 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000, + 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000, + 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000, + 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000, + 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000, + 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000, + 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000, + 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000, + 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000, + 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000, + 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000, + 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000, + 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000, + 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000, + 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000, + 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000, + 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000, + 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000, + 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000, + 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000, + 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000, + 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000, + 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000, + 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000, + 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000, + 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000, + 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000, + 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000, + 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000, + 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000, + 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000, + 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000, + 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000, + 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000, + 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000, + 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000, + 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000, + 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000, + 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000, + 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000, + 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000, + 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000, + 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000, + 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000, + 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000, + 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000, + 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000, + 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000, + 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000, + 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000, + 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000, + 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000, + 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000, + 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000, + 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000, + 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000, + 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000, + 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000, + 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000, + 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000, + 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000, + 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000, + 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000, + 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000, + 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000, + 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000, + 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000, + 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000, + 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000, + 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000, + 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000, + 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000, + 0x5270900d00000000}, + {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000, + 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000, + 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000, + 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000, + 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000, + 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000, + 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000, + 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000, + 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000, + 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000, + 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000, + 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000, + 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000, + 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000, + 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000, + 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000, + 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000, + 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000, + 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000, + 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000, + 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000, + 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000, + 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000, + 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000, + 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000, + 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000, + 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000, + 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000, + 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000, + 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000, + 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000, + 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000, + 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000, + 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000, + 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000, + 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000, + 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000, + 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000, + 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000, + 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000, + 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000, + 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000, + 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000, + 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000, + 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000, + 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000, + 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000, + 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000, + 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000, + 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000, + 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000, + 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000, + 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000, + 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000, + 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000, + 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000, + 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000, + 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000, + 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000, + 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000, + 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000, + 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000, + 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000, + 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000, + 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000, + 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000, + 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000, + 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000, + 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000, + 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000, + 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000, + 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000, + 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000, + 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000, + 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000, + 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000, + 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000, + 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000, + 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000, + 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000, + 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000, + 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000, + 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000, + 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000, + 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000, + 0xa8a0688500000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, + 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, + 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, + 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, + 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, + 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, + 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, + 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, + 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, + 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, + 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, + 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, + 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, + 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, + 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, + 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, + 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, + 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, + 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, + 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, + 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, + 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, + 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, + 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, + 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, + 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, + 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, + 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, + 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, + 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, + 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, + 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, + 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, + 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, + 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, + 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, + 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, + 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, + 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, + 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, + 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, + 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, + 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, + 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, + 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, + 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, + 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, + 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, + 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, + 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, + 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, + 0x09cd8551}, + {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, + 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, + 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, + 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, + 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, + 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, + 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, + 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, + 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, + 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, + 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, + 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, + 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, + 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, + 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, + 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, + 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, + 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, + 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, + 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, + 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, + 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, + 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, + 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, + 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, + 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, + 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, + 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, + 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, + 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, + 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, + 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, + 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, + 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, + 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, + 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, + 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, + 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, + 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, + 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, + 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, + 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, + 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, + 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, + 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, + 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, + 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, + 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, + 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, + 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, + 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, + 0x7bc97a0c}, + {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, + 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, + 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, + 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, + 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, + 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, + 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, + 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, + 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, + 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, + 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, + 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, + 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, + 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, + 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, + 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, + 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, + 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, + 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, + 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, + 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, + 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, + 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, + 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, + 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, + 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, + 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, + 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, + 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, + 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, + 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, + 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, + 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, + 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, + 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, + 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, + 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, + 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, + 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, + 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, + 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, + 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, + 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, + 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, + 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, + 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, + 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, + 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, + 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, + 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, + 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, + 0x7851a2ca}, + {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, + 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, + 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, + 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, + 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, + 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, + 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, + 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, + 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, + 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, + 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, + 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, + 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, + 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, + 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, + 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, + 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, + 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, + 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, + 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, + 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, + 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, + 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, + 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, + 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, + 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, + 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, + 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, + 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, + 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, + 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, + 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, + 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, + 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, + 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, + 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, + 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, + 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, + 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, + 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, + 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, + 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, + 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, + 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, + 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, + 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, + 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, + 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, + 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, + 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, + 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, + 0x566b6848}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912, + 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba, + 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3, + 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30, + 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e, + 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3, + 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73, + 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe, + 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0, + 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643, + 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a, + 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082, + 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4, + 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279, + 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735, + 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8, + 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad, + 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05, + 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c, + 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718, + 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46, + 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb, + 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc, + 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41, + 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f, + 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad, + 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4, + 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c, + 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779, + 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4, + 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8, + 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235, + 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7, + 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f, + 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476, + 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195, + 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb, + 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46, + 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622, + 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af, + 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1, + 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12, + 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b, + 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3, + 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51, + 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc, + 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90, + 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d, + 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708, + 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0, + 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9, + 0x48686b56}, + {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c, + 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae, + 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb, + 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90, + 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410, + 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b, + 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6, + 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed, + 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d, + 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036, + 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953, + 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1, + 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca, + 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781, + 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d, + 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416, + 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f, + 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd, + 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8, + 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b, + 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb, + 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0, + 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5, + 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e, + 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e, + 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558, + 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d, + 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf, + 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6, + 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad, + 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971, + 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a, + 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b, + 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969, + 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c, + 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57, + 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7, + 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c, + 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab, + 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0, + 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160, + 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b, + 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e, + 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac, + 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d, + 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546, + 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a, + 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1, + 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8, + 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a, + 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f, + 0xcaa25178}, + {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00, + 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b, + 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed, + 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777, + 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01, + 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a, + 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef, + 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74, + 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002, + 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498, + 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee, + 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75, + 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05, + 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e, + 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8, + 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73, + 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404, + 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f, + 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9, + 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71, + 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607, + 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c, + 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb, + 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470, + 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806, + 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790, + 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6, + 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d, + 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a, + 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991, + 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7, + 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c, + 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09, + 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92, + 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4, + 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e, + 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08, + 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593, + 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3, + 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778, + 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e, + 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94, + 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2, + 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079, + 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c, + 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497, + 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1, + 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a, + 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d, + 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396, + 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0, + 0x0c7ac97b}, + {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669, + 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853, + 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062, + 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527, + 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad, + 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545, + 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27, + 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf, + 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45, + 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800, + 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031, + 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b, + 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26, + 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce, + 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d, + 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5, + 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130, + 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a, + 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b, + 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480, + 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a, + 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2, + 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e, + 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996, + 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c, + 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc, + 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd, + 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7, + 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232, + 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da, + 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439, + 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1, + 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da, + 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0, + 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1, + 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94, + 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e, + 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6, + 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2, + 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a, + 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0, + 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95, + 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4, + 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e, + 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395, + 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d, + 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e, + 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676, + 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83, + 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9, + 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888, + 0x5185cd09}}; + +#endif + +#endif + +#endif + +local const z_crc_t FAR x2n_table[] = { + 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000, + 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467, + 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0, + 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169, + 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37, + 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a, + 0xc40ba6d0, 0xc4e22c3c}; diff --git a/thirdparty/freetype/src/gzip/ftgzip.c b/thirdparty/freetype/src/gzip/ftgzip.c index 8f98a7d17b..34bbe4dafa 100644 --- a/thirdparty/freetype/src/gzip/ftgzip.c +++ b/thirdparty/freetype/src/gzip/ftgzip.c @@ -8,7 +8,7 @@ * parse compressed PCF fonts, as found with many X11 server * distributions. * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -69,10 +69,21 @@ /* */ /* so that configuration with `FT_CONFIG_OPTION_SYSTEM_ZLIB' might */ /* include the wrong `zconf.h' file, leading to errors. */ -#include "zlib.h" -#undef SLOW -#define SLOW 1 /* we can't use asm-optimized sources here! */ + /* `HAVE_HIDDEN` should be defined if */ + /* */ + /* __attribute__((visibility("hidden"))) */ + /* */ + /* is supported by the compiler, which prevents internal symbols from */ + /* being exported by the library. */ +#if defined( __GNUC__ ) || defined( __clang__ ) +#define HAVE_HIDDEN 1 +#define ZEXPORT +#define ZEXTERN static +#endif + +#define Z_SOLO 1 +#define Z_FREETYPE 1 #if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */ /* We disable the warning `conversion from XXX to YYY, */ @@ -83,24 +94,23 @@ #pragma warning( disable : 4244 ) #endif /* _MSC_VER */ - /* Urgh. `inflate_mask' must not be declared twice -- C++ doesn't like - this. We temporarily disable it and load all necessary header files. */ -#define NO_INFLATE_MASK -#include "zutil.h" -#include "inftrees.h" -#include "infblock.h" -#include "infcodes.h" -#include "infutil.h" -#undef NO_INFLATE_MASK - - /* infutil.c must be included before infcodes.c */ +#if defined( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "zutil.c" -#include "inftrees.c" -#include "infutil.c" -#include "infcodes.c" -#include "infblock.c" +#include "inffast.c" #include "inflate.c" +#include "inftrees.c" #include "adler32.c" +#include "crc32.c" + +#if defined( __GNUC__ ) +#pragma GCC diagnostic pop +#endif #if defined( _MSC_VER ) #pragma warning( pop ) @@ -150,7 +160,7 @@ #if !defined( FT_CONFIG_OPTION_SYSTEM_ZLIB ) && !defined( USE_ZLIB_ZCALLOC ) - local voidpf + voidpf ZLIB_INTERNAL zcalloc ( voidpf opaque, unsigned items, unsigned size ) @@ -158,7 +168,8 @@ return ft_gzip_alloc( opaque, items, size ); } - local void + + void ZLIB_INTERNAL zcfree( voidpf opaque, voidpf ptr ) { @@ -751,16 +762,7 @@ stream.zfree = ft_gzip_free; stream.opaque = memory; - /* This is a temporary fix and will be removed once the internal - * copy of zlib is updated to the newest version. The `|32' flag - * is only supported in the new versions of zlib to enable gzip - * encoded header. - */ -#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB err = inflateInit2( &stream, MAX_WBITS|32 ); -#else - err = inflateInit2( &stream, MAX_WBITS ); -#endif if ( err != Z_OK ) return FT_THROW( Invalid_Argument ); diff --git a/thirdparty/freetype/src/gzip/ftzconf.h b/thirdparty/freetype/src/gzip/ftzconf.h index 3abf0ba03b..5e1d68a004 100644 --- a/thirdparty/freetype/src/gzip/ftzconf.h +++ b/thirdparty/freetype/src/gzip/ftzconf.h @@ -1,109 +1,255 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ -#ifndef _ZCONF_H -#define _ZCONF_H +#ifndef ZCONF_H +#define ZCONF_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". */ -#ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define inflateInit2_ z_inflateInit2_ -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateReset z_inflateReset -# define compress z_compress -# define compress2 z_compress2 -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table - -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp -#endif - -#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -# define WIN32 -#endif -#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) -# ifndef __32BIT__ -# define __32BIT__ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile # endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + #endif + #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif - -/* WinCE doesn't have errno.h */ -#ifdef _WIN32_WCE -# define NO_ERRNO_H +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif #endif - /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ -#if defined(MSDOS) && !defined(__32BIT__) +#ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif -#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) -# define STDC -#endif -#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +#ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const +# define const /* note: need a more gentle solution here */ # endif #endif -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Old Borland C and LCC incorrectly complains about missing returns: */ -#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) -# define NEED_DUMMY_RETURN +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const #endif -#if defined(__LCC__) -# define NEED_DUMMY_RETURN +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include <stddef.h> + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ @@ -133,7 +279,7 @@ Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ @@ -147,75 +293,101 @@ # endif #endif +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ -#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif # endif -#endif -#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) -# ifndef __32BIT__ +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ # define SMALL_MEDIUM -# define FAR _far +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif # endif #endif -/* Compile with -DZLIB_DLL for Windows DLL support */ -#if defined(ZLIB_DLL) -# if defined(_WINDOWS) || defined(WINDOWS) +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif # include <windows.h> -# define ZEXPORT(x) x WINAPI + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI # ifdef WIN32 -# define ZEXPORTVA(x) x WINAPIV +# define ZEXPORTVA WINAPIV # else -# define ZEXPORTVA(x) x FAR _cdecl _export +# define ZEXPORTVA FAR CDECL # endif # endif -# if defined (__BORLANDC__) -# if (__BORLANDC__ >= 0x0500) && defined (WIN32) -# include <windows.h> -# define ZEXPORT(x) x __declspec(dllexport) WINAPI -# define ZEXPORTRVA(x) x __declspec(dllexport) WINAPIV +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) # else -# if defined (_Windows) && defined (__DLL__) -# define ZEXPORT(x) x _export -# define ZEXPORTVA(x) x _export -# endif +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) # endif # endif #endif - +#ifndef ZEXTERN +# define ZEXTERN extern +#endif #ifndef ZEXPORT -# define ZEXPORT(x) static x +# define ZEXPORT #endif #ifndef ZEXPORTVA -# define ZEXPORTVA(x) static x -#endif -#ifndef ZEXTERN -# define ZEXTERN(x) static x -#endif -#ifndef ZEXTERNDEF -# define ZEXTERNDEF(x) static x +# define ZEXPORTVA #endif #ifndef FAR -# define FAR +# define FAR #endif -#if !defined(MACOS) && !defined(TARGET_OS_MAC) +#if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ @@ -233,52 +405,130 @@ typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC - typedef void FAR *voidpf; - typedef void *voidp; + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include <limits.h> +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; #else - typedef Byte FAR *voidpf; - typedef Byte *voidp; + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H #endif -#ifdef HAVE_UNISTD_H -# include <sys/types.h> /* for off_t */ -# include <unistd.h> /* for SEEK_* and off_t */ -# define z_off_t off_t +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H #endif -#ifndef SEEK_SET + +#ifdef STDC +# ifndef Z_SOLO +# include <sys/types.h> /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include <stdarg.h> /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include <stddef.h> /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include <unixio.h> /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif + #ifndef z_off_t -# define z_off_t long +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) -# pragma map(deflateInit_,"DEIN") -# pragma map(deflateInit2_,"DEIN2") -# pragma map(deflateEnd,"DEEND") -# pragma map(inflateInit_,"ININ") -# pragma map(inflateInit2_,"ININ2") -# pragma map(inflateEnd,"INEND") -# pragma map(inflateSync,"INSY") -# pragma map(inflateSetDictionary,"INSEDI") -# pragma map(inflate_blocks,"INBL") -# pragma map(inflate_blocks_new,"INBLNE") -# pragma map(inflate_blocks_free,"INBLFR") -# pragma map(inflate_blocks_reset,"INBLRE") -# pragma map(inflate_codes_free,"INCOFR") -# pragma map(inflate_codes,"INCO") -# pragma map(inflate_fast,"INFA") -# pragma map(inflate_flush,"INFLU") -# pragma map(inflate_mask,"INMA") -# pragma map(inflate_set_dictionary,"INSEDI2") -# pragma map(inflate_copyright,"INCOPY") -# pragma map(inflate_trees_bits,"INTRBI") -# pragma map(inflate_trees_dynamic,"INTRDY") -# pragma map(inflate_trees_fixed,"INTRFI") -# pragma map(inflate_trees_free,"INTRFR") -#endif - -#endif /* _ZCONF_H */ + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/thirdparty/freetype/src/gzip/gzguts.h b/thirdparty/freetype/src/gzip/gzguts.h new file mode 100644 index 0000000000..4f09a52a7a --- /dev/null +++ b/thirdparty/freetype/src/gzip/gzguts.h @@ -0,0 +1,219 @@ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004-2019 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include <stdio.h> +#include "zlib.h" +#ifdef STDC +# include <string.h> +# include <stdlib.h> +# include <limits.h> +#endif + +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif +#include <fcntl.h> + +#ifdef _WIN32 +# include <stddef.h> +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) +# include <io.h> +#endif + +#if defined(_WIN32) +# define WIDECHAR +#endif + +#ifdef WINAPI_FAMILY +# define open _open +# define read _read +# define write _write +# define close _close +#endif + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS +/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 +/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +# ifdef VMS +# define NO_vsnprintf +# endif +# ifdef __OS400__ +# define NO_vsnprintf +# endif +# ifdef __MVS__ +# define NO_vsnprintf +# endif +#endif + +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c where + the result is assured to fit in the space provided */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include <windows.h> +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifndef NO_STRERROR +# include <errno.h> +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY__ 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer (double-sized when writing) */ + unsigned char *out; /* output buffer (double-sized when reading) */ + int direct; /* 0 if processing gzip, 1 if transparent */ + /* just for reading */ + int how; /* 0: get header, 1: copy, 2: decompress */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + int reset; /* true if a reset is pending after a Z_FINISH */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state FAR *gz_statep; + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/thirdparty/freetype/src/gzip/infback.c b/thirdparty/freetype/src/gzip/infback.c new file mode 100644 index 0000000000..5fb8c67941 --- /dev/null +++ b/thirdparty/freetype/src/gzip/infback.c @@ -0,0 +1,641 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2022 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_( + z_streamp strm, + int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size) +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = (uInt)windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->wnext = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables( + struct inflate_state FAR *state) +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack( + z_streamp strm, + in_func in, + void FAR *in_desc, + out_func out, + void FAR *out_desc) +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + /* fallthrough */ + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + state->length = (unsigned)here.val; + + /* process literal */ + if (here.op == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd( + z_streamp strm) +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/thirdparty/freetype/src/gzip/infblock.c b/thirdparty/freetype/src/gzip/infblock.c deleted file mode 100644 index 2b4f0c2b53..0000000000 --- a/thirdparty/freetype/src/gzip/infblock.c +++ /dev/null @@ -1,392 +0,0 @@ -/* infblock.c -- interpret and process block types to last block - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* Table for deflate from PKZIP's appnote.txt. */ -local const uInt border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -local void inflate_blocks_reset( /* s, z, c) */ -inflate_blocks_statef *s, -z_streamp z, -uLongf *c ) -{ - if (c != Z_NULL) - *c = s->check; - if (s->mode == BTREE || s->mode == DTREE) - ZFREE(z, s->sub.trees.blens); - if (s->mode == CODES) - inflate_codes_free(s->sub.decode.codes, z); - s->mode = TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); - Tracev((stderr, "inflate: blocks reset\n")); -} - - -local inflate_blocks_statef *inflate_blocks_new( /* z, c, w) */ -z_streamp z, -check_func c, -uInt w ) -{ - inflate_blocks_statef *s; - - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) - return s; - if ((s->hufts = - (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) - { - ZFREE(z, s); - return Z_NULL; - } - if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s->hufts); - ZFREE(z, s); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = TYPE; - Tracev((stderr, "inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, Z_NULL); - return s; -} - - -local int inflate_blocks( /* s, z, r) */ -inflate_blocks_statef *s, -z_streamp z, -int r ) -{ - uInt t; /* temporary storage */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input based on current state */ - while (1) switch (s->mode) - { - case TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: /* stored */ - Tracev((stderr, "inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; /* go to byte boundary */ - DUMPBITS(t) - s->mode = LENS; /* get length of stored block */ - break; - case 1: /* fixed */ - Tracev((stderr, "inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - inflate_huft *tl, *td; - - inflate_trees_fixed(&bl, &bd, (const inflate_huft**)&tl, - (const inflate_huft**)&td, z); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - } - DUMPBITS(3) - s->mode = CODES; - break; - case 2: /* dynamic */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = TABLE; - break; - case 3: /* illegal */ - DUMPBITS(3) - s->mode = BAD; - z->msg = (char*)"invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case LENS: - NEEDBITS(32) - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - s->mode = BAD; - z->msg = (char*)"invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; /* dump bits */ - Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); - break; - case STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - zmemcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - Tracev((stderr, "inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? DRY : TYPE; - break; - case TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; -#ifndef PKZIP_BUG_WORKAROUND - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = BAD; - z->msg = (char*)"too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } -#endif - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - DUMPBITS(14) - s->sub.trees.index = 0; - Tracev((stderr, "inflate: table sizes ok\n")); - s->mode = BTREE; - /* fall through */ - case BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, s->hufts, z); - if (t != Z_OK) - { - r = t; - if (r == Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - } - LEAVE - } - s->sub.trees.index = 0; - Tracev((stderr, "inflate: bits tree ok\n")); - s->mode = DTREE; - /* fall through */ - case DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->bits; - c = h->base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else /* c == 16..18 */ - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - z->msg = (char*)"invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; /* must be <= 9 for lookahead assumptions */ - bd = 6; /* must be <= 9 for lookahead assumptions */ - t = s->sub.trees.table; - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, - s->hufts, z); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - } - r = t; - LEAVE - } - Tracev((stderr, "inflate: trees ok\n")); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.codes = c; - } - ZFREE(z, s->sub.trees.blens); - s->mode = CODES; - /* fall through */ - case CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - LOAD - Tracev((stderr, "inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = TYPE; - break; - } - s->mode = DRY; - /* fall through */ - case DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = DONE; - /* fall through */ - case DONE: - r = Z_STREAM_END; - LEAVE - case BAD: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -#ifdef NEED_DUMMY_RETURN - return 0; -#endif -} - - -local int inflate_blocks_free( /* s, z) */ -inflate_blocks_statef *s, -z_streamp z ) -{ - inflate_blocks_reset(s, z, Z_NULL); - ZFREE(z, s->window); - ZFREE(z, s->hufts); - ZFREE(z, s); - Tracev((stderr, "inflate: blocks freed\n")); - return Z_OK; -} - - diff --git a/thirdparty/freetype/src/gzip/infblock.h b/thirdparty/freetype/src/gzip/infblock.h deleted file mode 100644 index c2535a1e45..0000000000 --- a/thirdparty/freetype/src/gzip/infblock.h +++ /dev/null @@ -1,36 +0,0 @@ -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFBLOCK_H -#define _INFBLOCK_H - -struct inflate_blocks_state; -typedef struct inflate_blocks_state FAR inflate_blocks_statef; - -local inflate_blocks_statef * inflate_blocks_new OF(( - z_streamp z, - check_func c, /* check function */ - uInt w)); /* window size */ - -local int inflate_blocks OF(( - inflate_blocks_statef *, - z_streamp , - int)); /* initial return code */ - -local void inflate_blocks_reset OF(( - inflate_blocks_statef *, - z_streamp , - uLongf *)); /* check value on output */ - -local int inflate_blocks_free OF(( - inflate_blocks_statef *, - z_streamp)); - -#endif /* _INFBLOCK_H */ diff --git a/thirdparty/freetype/src/gzip/infcodes.c b/thirdparty/freetype/src/gzip/infcodes.c deleted file mode 100644 index ba30654990..0000000000 --- a/thirdparty/freetype/src/gzip/infcodes.c +++ /dev/null @@ -1,254 +0,0 @@ -/* infcodes.c -- process literals and length/distance pairs - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "infblock.h" -#include "infcodes.h" -#include "infutil.h" - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - START, /* x: set up for LEN */ - LEN, /* i: get length/literal/eob next */ - LENEXT, /* i: getting length extra (have base) */ - DIST, /* i: get distance next */ - DISTEXT, /* i: getting distance extra */ - COPY, /* o: copying bytes in window, waiting for space */ - LIT, /* o: got literal, waiting for output space */ - WASH, /* o: got eob, possibly still output waiting */ - END, /* x: got eob and all data flushed */ - BADCODE} /* x: got error */ -inflate_codes_mode; - -/* inflate codes private state */ -struct inflate_codes_state { - - /* mode */ - inflate_codes_mode mode; /* current inflate_codes mode */ - - /* mode dependent information */ - uInt len; - union { - struct { - inflate_huft *tree; /* pointer into tree */ - uInt need; /* bits needed */ - } code; /* if LEN or DIST, where in tree */ - uInt lit; /* if LIT, literal */ - struct { - uInt get; /* bits to get for extra */ - uInt dist; /* distance back to copy from */ - } copy; /* if EXT or COPY, where and how much */ - } sub; /* submode */ - - /* mode independent information */ - Byte lbits; /* ltree bits decoded per branch */ - Byte dbits; /* dtree bits decoder per branch */ - inflate_huft *ltree; /* literal/length/eob tree */ - inflate_huft *dtree; /* distance tree */ - -}; - - -local inflate_codes_statef *inflate_codes_new( /* bl, bd, tl, td, z) */ -uInt bl, uInt bd, -inflate_huft *tl, -inflate_huft *td, /* need separate declaration for Borland C++ */ -z_streamp z ) -{ - inflate_codes_statef *c; - - if ((c = (inflate_codes_statef *) - ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - Tracev((stderr, "inflate: codes new\n")); - } - return c; -} - - -local int inflate_codes( /* s, z, r) */ -inflate_blocks_statef *s, -z_streamp z, -int r ) -{ - uInt j; /* temporary storage */ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - Bytef *f; /* pointer to copy strings from */ - inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input and output based on current state */ - while (1) switch (c->mode) - { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - case START: /* x: set up for LEN */ -#ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } -#endif /* !SLOW */ - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - /* fall through */ - case LEN: /* i: get length/literal/eob next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) /* literal */ - { - c->sub.lit = t->base; - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", t->base)); - c->mode = LIT; - break; - } - if (e & 16) /* length */ - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - if (e & 32) /* end of block */ - { - Tracevv((stderr, "inflate: end of block\n")); - c->mode = WASH; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: /* i: getting length extra (have base) */ - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - Tracevv((stderr, "inflate: length %u\n", c->len)); - c->mode = DIST; - /* fall through */ - case DIST: /* i: get distance next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) /* distance */ - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: /* i: getting distance extra */ - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); - c->mode = COPY; - /* fall through */ - case COPY: /* o: copying bytes in window, waiting for space */ - f = q - c->sub.copy.dist; - while (f < s->window) /* modulo window size-"while" instead */ - f += s->end - s->window; /* of "if" handles invalid distances */ - while (c->len) - { - NEEDOUT - OUTBYTE(*f++) - if (f == s->end) - f = s->window; - c->len--; - } - c->mode = START; - break; - case LIT: /* o: got literal, waiting for output space */ - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: /* o: got eob, possibly more output */ - if (k > 7) /* return unused byte, if any */ - { - Assert(k < 16, "inflate_codes grabbed too many bytes") - k -= 8; - n++; - p--; /* can always return one */ - } - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - /* fall through */ - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: /* x: got error */ - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -#endif -} - - -local void inflate_codes_free( /* c, z) */ -inflate_codes_statef *c, -z_streamp z ) -{ - ZFREE(z, c); - Tracev((stderr, "inflate: codes free\n")); -} diff --git a/thirdparty/freetype/src/gzip/infcodes.h b/thirdparty/freetype/src/gzip/infcodes.h deleted file mode 100644 index 154d7f896c..0000000000 --- a/thirdparty/freetype/src/gzip/infcodes.h +++ /dev/null @@ -1,31 +0,0 @@ -/* infcodes.h -- header to use infcodes.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFCODES_H -#define _INFCODES_H - -struct inflate_codes_state; -typedef struct inflate_codes_state FAR inflate_codes_statef; - -local inflate_codes_statef *inflate_codes_new OF(( - uInt, uInt, - inflate_huft *, inflate_huft *, - z_streamp )); - -local int inflate_codes OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -local void inflate_codes_free OF(( - inflate_codes_statef *, - z_streamp )); - -#endif /* _INFCODES_H */ diff --git a/thirdparty/freetype/src/gzip/inffast.c b/thirdparty/freetype/src/gzip/inffast.c new file mode 100644 index 0000000000..809737b13c --- /dev/null +++ b/thirdparty/freetype/src/gzip/inffast.c @@ -0,0 +1,323 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") +#else + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast( + z_streamp strm, + unsigned start) +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code const *here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - 5); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = lcode + (hold & lmask); + dolen: + op = (unsigned)(here->bits); + hold >>= op; + bits -= op; + op = (unsigned)(here->op); + if (op == 0) { /* literal */ + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here->val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = dcode + (hold & dmask); + dodist: + op = (unsigned)(here->bits); + hold >>= op; + bits -= op; + op = (unsigned)(here->op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here->val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = window; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } while (len > 2); + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode + here->val + (hold & ((1U << op) - 1)); + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode + here->val + (hold & ((1U << op) - 1)); + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/thirdparty/freetype/src/gzip/inffast.h b/thirdparty/freetype/src/gzip/inffast.h new file mode 100644 index 0000000000..e5c1aa4ca8 --- /dev/null +++ b/thirdparty/freetype/src/gzip/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/thirdparty/freetype/src/gzip/inffixed.h b/thirdparty/freetype/src/gzip/inffixed.h index 4d4760ea00..d628327769 100644 --- a/thirdparty/freetype/src/gzip/inffixed.h +++ b/thirdparty/freetype/src/gzip/inffixed.h @@ -1,151 +1,94 @@ -/* inffixed.h -- table for decoding fixed codes - * Generated automatically by the maketree.c program - */ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ -local const uInt fixed_bl = 9; -local const uInt fixed_bd = 5; -local const inflate_huft fixed_tl[] = { - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} - }; -local const inflate_huft fixed_td[] = { - {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, - {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, - {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, - {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, - {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, - {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, - {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, - {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} - }; + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/thirdparty/freetype/src/gzip/inflate.c b/thirdparty/freetype/src/gzip/inflate.c index 95e2653662..5bf5b815e5 100644 --- a/thirdparty/freetype/src/gzip/inflate.c +++ b/thirdparty/freetype/src/gzip/inflate.c @@ -1,283 +1,1610 @@ -/* inflate.c -- zlib interface to inflate modules - * Copyright (C) 1995-2002 Mark Adler +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + #include "zutil.h" -#include "infblock.h" - -#define DONE INFLATE_DONE -#define BAD INFLATE_BAD - -typedef enum { - METHOD, /* waiting for method byte */ - FLAG, /* waiting for flag byte */ - DICT4, /* four dictionary check bytes to go */ - DICT3, /* three dictionary check bytes to go */ - DICT2, /* two dictionary check bytes to go */ - DICT1, /* one dictionary check byte to go */ - DICT0, /* waiting for inflateSetDictionary */ - BLOCKS, /* decompressing blocks */ - CHECK4, /* four check bytes to go */ - CHECK3, /* three check bytes to go */ - CHECK2, /* two check bytes to go */ - CHECK1, /* one check byte to go */ - DONE, /* finished check, done */ - BAD} /* got an error--stay here */ -inflate_mode; - -/* inflate private state */ -struct internal_state { - - /* mode */ - inflate_mode mode; /* current inflate mode */ - - /* mode dependent information */ - union { - uInt method; /* if FLAGS, method byte */ - struct { - uLong was; /* computed check value */ - uLong need; /* stream check value */ - } check; /* if CHECK, check values to compare */ - uInt marker; /* if BAD, inflateSync's marker bytes count */ - } sub; /* submode */ - - /* mode independent information */ - int nowrap; /* flag for no wrapper */ - uInt wbits; /* log2(window size) (8..15, defaults to 15) */ - inflate_blocks_statef - *blocks; /* current inflate_blocks state */ - -}; - - -ZEXPORT(int) inflateReset( /* z) */ -z_streamp z ) +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +#ifndef Z_FREETYPE +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); +#endif + +local int inflateStateCheck( + z_streamp strm) { - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - z->state->mode = z->state->nowrap ? BLOCKS : METHOD; - inflate_blocks_reset(z->state->blocks, z, Z_NULL); - Tracev((stderr, "inflate: reset\n")); - return Z_OK; + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; } +int ZEXPORT inflateResetKeep( + z_streamp strm) +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->flags = -1; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} -ZEXPORT(int) inflateEnd( /* z) */ -z_streamp z ) +int ZEXPORT inflateReset( + z_streamp strm) { - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != Z_NULL) - inflate_blocks_free(z->state->blocks, z); - ZFREE(z, z->state); - z->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); } +int ZEXPORT inflateReset2( + z_streamp strm, + int windowBits) +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} -ZEXPORT(int) inflateInit2_( /* z, w, version, stream_size) */ -z_streamp z, -int w, -const char *version, -int stream_size ) +int ZEXPORT inflateInit2_( + z_streamp strm, + int windowBits, + const char *version, + int stream_size) { - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != sizeof(z_stream)) - return Z_VERSION_ERROR; - - /* initialize state */ - if (z == Z_NULL) - return Z_STREAM_ERROR; - z->msg = Z_NULL; - if (z->zalloc == Z_NULL) - { - z->zalloc = zcalloc; - z->opaque = (voidpf)0; - } - if (z->zfree == Z_NULL) z->zfree = zcfree; - if ((z->state = (struct internal_state FAR *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->blocks = Z_NULL; - - /* handle undocumented nowrap option (no zlib header or check) */ - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } - - /* set window size */ - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; - - /* create inflate_blocks state */ - if ((z->state->blocks = - inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) - == Z_NULL) - { - inflateEnd(z); - return Z_MEM_ERROR; - } - Tracev((stderr, "inflate: allocated\n")); - - /* reset state */ - inflateReset(z); - return Z_OK; + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->strm = strm; + state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; } +int ZEXPORT inflateInit_( + z_streamp strm, + const char *version, + int stream_size) +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} +#ifndef Z_FREETYPE -#undef NEEDBYTE -#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} +int ZEXPORT inflatePrime( + z_streamp strm, + int bits, + int value) +{ + struct inflate_state FAR *state; -#undef NEXTBYTE -#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; + return Z_OK; +} +#endif /* !Z_FREETYPE */ -ZEXPORT(int) inflate( /* z, f) */ -z_streamp z, -int f ) +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables( + struct inflate_state FAR *state) { - int r; - uInt b; - - if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) - return Z_STREAM_ERROR; - f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; - r = Z_BUF_ERROR; - while (1) switch (z->state->mode) - { - case METHOD: - NEEDBYTE - if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) - { - z->state->mode = BAD; - z->msg = (char*)"unknown compression method"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = BAD; - z->msg = (char*)"invalid window size"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - z->state->mode = FLAG; - /* fall through */ - case FLAG: - NEEDBYTE - b = NEXTBYTE; - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = BAD; - z->msg = (char*)"incorrect header check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Tracev((stderr, "inflate: zlib header ok\n")); - if (!(b & PRESET_DICT)) - { - z->state->mode = BLOCKS; - break; - } - z->state->mode = DICT4; - /* fall through */ - case DICT4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = DICT3; - /* fall through */ - case DICT3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = DICT2; - /* fall through */ - case DICT2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = DICT1; - /* fall through */ - case DICT1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - z->adler = z->state->sub.check.need; - z->state->mode = DICT0; - return Z_NEED_DICT; - case DICT0: - z->state->mode = BAD; - z->msg = (char*)"need dictionary"; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_STREAM_ERROR; - case BLOCKS: - r = inflate_blocks(z->state->blocks, z, r); - if (r == Z_DATA_ERROR) - { - z->state->mode = BAD; - z->state->sub.marker = 0; /* can try inflateSync */ - break; - } - if (r == Z_OK) - r = f; - if (r != Z_STREAM_END) - return r; - r = f; - inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = DONE; - break; - } - z->state->mode = CHECK4; - /* fall through */ - case CHECK4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = CHECK3; - /* fall through */ - case CHECK3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = CHECK2; - /* fall through */ - case CHECK2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = CHECK1; - /* fall through */ - case CHECK1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = BAD; - z->msg = (char*)"incorrect data check"; - z->state->sub.marker = 5; /* can't try inflateSync */ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include <stdio.h> + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow( + z_streamp strm, + const Bytef *end, + unsigned copy) +{ + struct inflate_state FAR *state; + unsigned dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + zmemcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE_CHECK(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; break; - } - Tracev((stderr, "inflate: zlib check ok\n")); - z->state->mode = DONE; - /* fall through */ - case DONE: - return Z_STREAM_END; - case BAD: - return Z_DATA_ERROR; - default: - return Z_STREAM_ERROR; - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate( + z_streamp strm, + int flush) +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ #endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + if (len > 15 || len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + state->flags = 0; /* indicate zlib header */ + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + /* fallthrough */ + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + /* fallthrough */ + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + /* fallthrough */ + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + /* fallthrough */ + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + /* fallthrough */ + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + /* fallthrough */ + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + /* fallthrough */ + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + /* fallthrough */ + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + /* fallthrough */ + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + /* fallthrough */ + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + /* fallthrough */ + case COPY_: + state->mode = COPY; + /* fallthrough */ + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + /* fallthrough */ + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + /* fallthrough */ + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (const code FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + /* fallthrough */ + case LEN_: + state->mode = LEN; + /* fallthrough */ + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + /* fallthrough */ + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + /* fallthrough */ + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + /* fallthrough */ + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + /* fallthrough */ + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE_CHECK(state->check, put - out, out); + out = left; + if ((state->wrap & 4) && ( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + /* fallthrough */ + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + /* fallthrough */ + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + /* fallthrough */ + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE_CHECK(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd( + z_streamp strm) +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +#ifndef Z_FREETYPE + +int ZEXPORT inflateGetDictionary( + z_streamp strm, + Bytef *dictionary, + uInt *dictLength) +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary( + z_streamp strm, + const Bytef *dictionary, + uInt dictLength) +{ + struct inflate_state FAR *state; + unsigned long dictid; + int ret; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader( + z_streamp strm, + gz_headerp head) +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch( + unsigned FAR *have, + const unsigned char FAR *buf, + unsigned len) +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync( + z_streamp strm) +{ + unsigned len; /* number of bytes to look at or looked at */ + int flags; /* temporary to save header status */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + if (state->flags == -1) + state->wrap = 0; /* if no header yet, treat as raw */ + else + state->wrap &= ~4; /* no point in computing a check value now */ + flags = state->flags; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->flags = flags; + state->mode = TYPE; + return Z_OK; +} + +#endif /* !Z_FREETYPE */ + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint( + z_streamp strm) +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +#ifndef Z_FREETYPE + +int ZEXPORT inflateCopy( + z_streamp dest, + z_streamp source) +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (inflateStateCheck(source) || dest == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +#endif /* !Z_FREETYPE */ + +int ZEXPORT inflateUndermine( + z_streamp strm, + int subvert) +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; + return Z_OK; +#else + (void)subvert; + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +int ZEXPORT inflateValidate( + z_streamp strm, + int check) +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check && state->wrap) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +#ifndef Z_FREETYPE + +long ZEXPORT inflateMark( + z_streamp strm) +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) + return -(1L << 16); + state = (struct inflate_state FAR *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} + +unsigned long ZEXPORT inflateCodesUsed( + z_streamp strm) +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); } +#endif /* !Z_FREETYPE */ diff --git a/thirdparty/freetype/src/gzip/inflate.h b/thirdparty/freetype/src/gzip/inflate.h new file mode 100644 index 0000000000..c6f5a52e16 --- /dev/null +++ b/thirdparty/freetype/src/gzip/inflate.h @@ -0,0 +1,131 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2019 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef INFLATE_H +#define INFLATE_H + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD = 16180, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ +struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags, 0 if zlib, or + -1 if raw or no header yet */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; + +#endif /* INFLATE_H */ diff --git a/thirdparty/freetype/src/gzip/inftrees.c b/thirdparty/freetype/src/gzip/inftrees.c index 56f52b1701..0b58b29b1b 100644 --- a/thirdparty/freetype/src/gzip/inftrees.c +++ b/thirdparty/freetype/src/gzip/inftrees.c @@ -1,20 +1,15 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2002 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" -#if !defined(BUILDFIXED) && !defined(STDC) -# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ -#endif +#define MAXBITS 15 - -#if 0 -local const char inflate_copyright[] = - " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; -#endif +const char inflate_copyright[] = + " inflate 1.2.12 Copyright 1995-2022 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -22,447 +17,288 @@ local const char inflate_copyright[] = copyright string in the executable of your product. */ -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - - -local int huft_build OF(( - uIntf *, /* code lengths in bits */ - uInt, /* number of codes */ - uInt, /* number of "simple" codes */ - const uIntf *, /* list of base values for non-simple codes */ - const uIntf *, /* list of extra bits for non-simple codes */ - inflate_huft * FAR*,/* result: starting table */ - uIntf *, /* maximum lookup bits (returns actual) */ - inflate_huft *, /* space for trees */ - uInt *, /* hufts used in space */ - uIntf * )); /* space for values */ - -/* Tables for deflate from PKZIP's appnote.txt. */ -local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table( + codetype type, + unsigned short FAR *lens, + unsigned codes, + code FAR * FAR *table, + unsigned FAR *bits, + unsigned short FAR *work) +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + unsigned match; /* use base and extra for symbol >= match */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* see note #13 above about 258 */ -local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ -local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 202}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -local const uInt cpdext[30] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - -/* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose - size is determined by the longest code. However, the time it takes - to build this table can also be a factor if the data being decoded - is not very long. The most common codes are necessarily the - shortest codes, so those codes dominate the decoding time, and hence - the speed. The idea is you can have a shorter table that decodes the - shorter, more probable codes, and then point to subsidiary tables for - the longer codes. The time it costs to decode the longer codes is - then traded against the time it takes to make longer tables. - - This results of this trade are in the variables lbits and dbits - below. lbits is the number of bits the first level table for literal/ - length codes can decode in one step, and dbits is the same thing for - the distance codes. Subsequent tables are also less than or equal to - those sizes. These values may be adjusted either when all of the - codes are shorter than that, in which case the longest code length in - bits is used, or when the shortest code is *longer* than the requested - table size, in which case the length of the shortest code in bits is - used. - - There are two different values for the two tables, since they code a - different number of possibilities each. The literal/length table - codes 286 possible values, or in a flat code, a little over eight - bits. The distance table codes 30 possible values, or a little less - than five bits, flat. The optimum values for speed end up being - about one bit more than those, so lbits is 8+1 and dbits is 5+1. - The optimum values may differ though from machine to machine, and - possibly even between compilers. Your mileage may vary. - */ - - -/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -#define BMAX 15 /* maximum bit length of any code */ - -local int huft_build( /* b, n, s, d, e, t, m, hp, hn, v) */ -uIntf *b, /* code lengths in bits (all assumed <= BMAX) */ -uInt n, /* number of codes (assumed <= 288) */ -uInt s, /* number of simple-valued codes (0..s-1) */ -const uIntf *d, /* list of base values for non-simple codes */ -const uIntf *e, /* list of extra bits for non-simple codes */ -inflate_huft * FAR *t, /* result: starting table */ -uIntf *m, /* maximum lookup bits, returns actual */ -inflate_huft *hp, /* space for trees */ -uInt *hn, /* hufts used in space */ -uIntf *v /* working area: values in order of bit length */ -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - if the given code set is incomplete (the tables are still built in this - case), or Z_DATA_ERROR if the input is invalid. */ -) -{ + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + match = 20; + break; + case LENS: + base = lbase; + extra = lext; + match = 257; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + match = 0; + } - uInt a; /* counter for codes of length k */ - uInt c[BMAX+1]; /* bit length count table */ - uInt f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - uInt i; /* counter, current code */ - uInt j; /* counter */ - int k; /* number of bits in current code */ - int l; /* bits per table (returned in m) */ - uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ - uIntf *p; /* pointer into c[], b[], or v[] */ - inflate_huft *q; /* points to current table */ - struct inflate_huft_s r; /* table entry for structure assignment */ - inflate_huft *u[BMAX]; /* table stack */ - int w; /* bits before this table == (l * h) */ - uInt x[BMAX+1]; /* bit offsets, then code stack */ - uIntf *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - uInt z; /* number of entries in current table */ - - - /* Make compiler happy */ - r.base = 0; - - /* Generate counts for each bit length */ - p = c; -#define C0 *p++ = 0; -#define C2 C0 C0 C0 C0 -#define C4 C2 C2 C2 C2 - C4 /* clear c[]--assume BMAX+1 is 16 */ - p = b; i = n; - do { - c[*p++]++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = (inflate_huft *)Z_NULL; - *m = 0; - return Z_OK; - } - - - /* Find minimum and maximum length, bound *m by those */ - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((uInt)l > i) - l = i; - *m = l; - - - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; - - - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } - - - /* Make a table of values in order of bit lengths */ - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - n = x[g]; /* set n to length of v */ - - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = -l; /* bits decoded == (l * h) */ - u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ - q = (inflate_huft *)Z_NULL; /* ditto */ - z = 0; /* ditto */ - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l) - { - h++; - w += l; /* previous table always l bits */ - - /* compute minimum size table less than or equal to l bits */ - z = g - w; - z = z > (uInt)l ? (uInt)l : z; /* table size upper limit */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - if (j < z) - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if (work[sym] + 1U < match) { + here.op = (unsigned char)0; + here.val = work[sym]; } - z = 1 << j; /* table entries for j-bit table */ - - /* allocate new table */ - if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ - return Z_DATA_ERROR; /* overflow of MANY */ - u[h] = q = hp + *hn; - *hn += z; - - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.bits = (Byte)l; /* bits to dump before this table */ - r.exop = (Byte)j; /* bits in this table */ - j = i >> (w - l); - r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ - u[h-1][j] = r; /* connect to last table */ + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; } - else - *t = q; /* first table is returned result */ - } - - /* set up table entry in r */ - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; /* out of values--invalid code */ - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ - r.base = *p++; /* simple code is just the value */ - } - else - { - r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ - r.base = d[*p++ - s]; - } - - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - /* backup over finished tables */ - mask = (1 << w) - 1; /* needed on HP, cc -O bug */ - while ((i & mask) != x[h]) - { - h--; /* don't need to update q */ - w -= l; - mask = (1 << w) - 1; - } - } - } - - - /* Return Z_BUF_ERROR if we were given an incomplete table */ - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -} + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; -local int inflate_trees_bits( /* c, bb, tb, hp, z) */ -uIntf *c, /* 19 code lengths */ -uIntf *bb, /* bits tree desired/actual depth */ -inflate_huft * FAR *tb, /* bits tree result */ -inflate_huft *hp, /* space for trees */ -z_streamp z /* for messages */ -) -{ - int r; - uInt hn = 0; /* hufts used in space */ - uIntf *v; /* work area for huft_build */ - - if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, - tb, bb, hp, &hn, v); - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR || *bb == 0) - { - z->msg = (char*)"incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; -} + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } -local int inflate_trees_dynamic( /* nl, nd, c, bl, bd, tl, td, hp, z) */ -uInt nl, /* number of literal/length codes */ -uInt nd, /* number of distance codes */ -uIntf *c, /* that many (total) code lengths */ -uIntf *bl, /* literal desired/actual bit depth */ -uIntf *bd, /* distance desired/actual bit depth */ -inflate_huft * FAR *tl, /* literal/length tree result */ -inflate_huft * FAR *td, /* distance tree result */ -inflate_huft *hp, /* space for trees */ -z_streamp z /* for messages */ -) -{ - int r; - uInt hn = 0; /* hufts used in space */ - uIntf *v; /* work area for huft_build */ - - /* allocate work area */ - if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - - /* build literal/length tree */ - r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); - if (r != Z_OK || *bl == 0) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed literal/length tree"; - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; - } - - /* build distance tree */ - r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); - if (r != Z_OK || (*bd == 0 && nl > 257)) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed distance tree"; - else if (r == Z_BUF_ERROR) { -#if 0 - { -#endif -#ifdef PKZIP_BUG_WORKAROUND - r = Z_OK; - } -#else - z->msg = (char*)"incomplete distance tree"; - r = Z_DATA_ERROR; - } - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"empty distance tree with lengths"; - r = Z_DATA_ERROR; + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } } - ZFREE(z, v); - return r; -#endif - } - - /* done */ - ZFREE(z, v); - return Z_OK; -} - -/* build fixed tables only once--keep them here */ -#ifdef BUILDFIXED -local int fixed_built = 0; -#define FIXEDH 544 /* number of hufts used by fixed tables */ -local inflate_huft fixed_mem[FIXEDH]; -local uInt fixed_bl; -local uInt fixed_bd; -local inflate_huft *fixed_tl; -local inflate_huft *fixed_td; -#else -#include "inffixed.h" -#endif - - -local int inflate_trees_fixed( /* bl, bd, tl, td, z) */ -uIntf *bl, /* literal desired/actual bit depth */ -uIntf *bd, /* distance desired/actual bit depth */ -const inflate_huft * FAR *tl, /* literal/length tree result */ -const inflate_huft * FAR *td, /* distance tree result */ -z_streamp z /* for memory allocation */ -) -{ -#ifdef BUILDFIXED - /* build fixed tables if not already */ - if (!fixed_built) - { - int k; /* temporary variable */ - uInt f = 0; /* number of hufts used in fixed_mem */ - uIntf *c; /* length list for huft_build */ - uIntf *v; /* work area for huft_build */ - - /* allocate memory */ - if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - { - ZFREE(z, c); - return Z_MEM_ERROR; + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; } - /* literal table */ - for (k = 0; k < 144; k++) - c[k] = 8; - for (; k < 256; k++) - c[k] = 9; - for (; k < 280; k++) - c[k] = 7; - for (; k < 288; k++) - c[k] = 8; - fixed_bl = 9; - huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, - fixed_mem, &f, v); - - /* distance table */ - for (k = 0; k < 30; k++) - c[k] = 5; - fixed_bd = 5; - huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, - fixed_mem, &f, v); - - /* done */ - ZFREE(z, v); - ZFREE(z, c); - fixed_built = 1; - } -#else - FT_UNUSED(z); -#endif - *bl = fixed_bl; - *bd = fixed_bd; - *tl = fixed_tl; - *td = fixed_td; - return Z_OK; + /* set return parameters */ + *table += used; + *bits = root; + return 0; } diff --git a/thirdparty/freetype/src/gzip/inftrees.h b/thirdparty/freetype/src/gzip/inftrees.h index 07bf2aa0bf..c94eb78b5d 100644 --- a/thirdparty/freetype/src/gzip/inftrees.h +++ b/thirdparty/freetype/src/gzip/inftrees.h @@ -1,63 +1,67 @@ /* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2002 Mark Adler + * Copyright (C) 1995-2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ +#ifndef INFTREES_H +#define INFTREES_H + /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ -/* Huffman code lookup table entry--this entry is four bytes for machines - that have 16-bit pointers (e.g. PC's in the small or medium model). */ - -#ifndef _INFTREES_H -#define _INFTREES_H - -typedef struct inflate_huft_s FAR inflate_huft; - -struct inflate_huft_s { - union { - struct { - Byte Exop; /* number of extra bits or operation */ - Byte Bits; /* number of bits in this code or subcode */ - } what; - uInt pad; /* pad structure to a power of 2 (4 bytes for */ - } word; /* 16-bit, 8 bytes for 32-bit int's) */ - uInt base; /* literal, length base, distance base, - or table offset */ -}; - -/* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1004 huft structures (850 for length/literals - and 154 for distances, the latter actually the result of an - exhaustive search). The actual maximum is not known, but the - value below is more than safe. */ -#define MANY 1440 - -local int inflate_trees_bits OF(( - uIntf *, /* 19 code lengths */ - uIntf *, /* bits tree desired/actual depth */ - inflate_huft * FAR *, /* bits tree result */ - inflate_huft *, /* space for trees */ - z_streamp)); /* for messages */ - -local int inflate_trees_dynamic OF(( - uInt, /* number of literal/length codes */ - uInt, /* number of distance codes */ - uIntf *, /* that many (total) code lengths */ - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *, /* distance tree result */ - inflate_huft *, /* space for trees */ - z_streamp)); /* for messages */ - -local int inflate_trees_fixed OF(( - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - const inflate_huft * FAR *, /* literal/length tree result */ - const inflate_huft * FAR *, /* distance tree result */ - z_streamp)); /* for memory allocation */ - -#endif /* _INFTREES_H */ +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); + +#endif /* INFTREES_H_ */ diff --git a/thirdparty/freetype/src/gzip/infutil.c b/thirdparty/freetype/src/gzip/infutil.c deleted file mode 100644 index 6087b40647..0000000000 --- a/thirdparty/freetype/src/gzip/infutil.c +++ /dev/null @@ -1,86 +0,0 @@ -/* inflate_util.c -- data and routines common to blocks and codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - - -/* And'ing with mask[n] masks the lower n bits */ -local const uInt inflate_mask[17] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - - -/* copy as much as possible from the sliding window to the output area */ -local int inflate_flush( /* s, z, r) */ -inflate_blocks_statef *s, -z_streamp z, -int r ) -{ - uInt n; - Bytef *p; - Bytef *q; - - /* local copies of source and destination pointers */ - p = z->next_out; - q = s->read; - - /* compute number of bytes to copy as far as end of window */ - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy as far as end of window */ - zmemcpy(p, q, n); - p += n; - q += n; - - /* see if more to copy at beginning of window */ - if (q == s->end) - { - /* wrap pointers */ - q = s->window; - if (s->write == s->end) - s->write = s->window; - - /* compute bytes to copy */ - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy */ - zmemcpy(p, q, n); - p += n; - q += n; - } - - /* update pointers */ - z->next_out = p; - s->read = q; - - /* done */ - return r; -} diff --git a/thirdparty/freetype/src/gzip/infutil.h b/thirdparty/freetype/src/gzip/infutil.h deleted file mode 100644 index cdf18b4f90..0000000000 --- a/thirdparty/freetype/src/gzip/infutil.h +++ /dev/null @@ -1,98 +0,0 @@ -/* infutil.h -- types and macros common to blocks and codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFUTIL_H -#define _INFUTIL_H - -typedef enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - DONE, /* finished last block, done */ - BAD} /* got a data error--stuck here */ -inflate_block_mode; - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - inflate_block_mode mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uIntf *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - } trees; /* if DTREE, decoding info for trees */ - struct { - inflate_codes_statef - *codes; - } decode; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - inflate_huft *hufts; /* single malloc for tree space */ - Bytef *window; /* sliding window */ - Bytef *end; /* one byte after sliding window */ - Bytef *read; /* window read pointer */ - Bytef *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - - -/* defines for inflate input/output */ -/* update pointers and return */ -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return inflate_flush(s,z,r);} -/* get bytes and bits */ -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}} -#define DUMPBITS(j) {b>>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} -#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -/* load local pointers */ -#define LOAD {LOADIN LOADOUT} - -/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ -#ifndef NO_INFLATE_MASK -local const uInt inflate_mask[17]; -#endif - -/* copy as much as possible from the sliding window to the output area */ -local int inflate_flush OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -#endif diff --git a/thirdparty/freetype/src/gzip/patches/freetype-zlib.diff b/thirdparty/freetype/src/gzip/patches/freetype-zlib.diff new file mode 100644 index 0000000000..20d84293f3 --- /dev/null +++ b/thirdparty/freetype/src/gzip/patches/freetype-zlib.diff @@ -0,0 +1,372 @@ +[zlib] Fix zlib sources for compilation with FreeType + +We must ensure that they do not issue compiler errors or warnings when they +are compiled as part of `src/gzip/ftgzip.c`. + +* src/gzip/adler32.c: Do not define unused functions when `Z_FREETYPE` +is set. + +* src/gzip/gzguts.h (COPY): Rename to... +(COPY__): ... this since `COPY` and `COPY_` conflict with enum values, +which have the same name in `zlib.h`. + +* src/gzip/inflate.c, src/gzip/adler32.c: Omit unused function +declarations when `Z_FREETYPE` is defined. + +* src/gzip/zlib.h: Include `ftzconf.h` instead of `zconf.h` to avoid +conflicts with system-installed headers. +Omit unused function declarations when `Z_FREETYPE` is defined. + +* src/gzip/zutil.h: Use `ft_memxxx` functions instead of `memxxx`. +Omit unused function declarations when `Z_FREETYPE` is defined. + +* src/gzip/inflate.h, src/gzip/inftrees.h: Add header guard macros to +prevent compiler errors. + +diff --git a/src/gzip/adler32.c b/src/gzip/adler32.c +index be5e8a247..aa032e1dd 100644 +--- a/src/gzip/adler32.c ++++ b/src/gzip/adler32.c +@@ -7,7 +7,9 @@ + + #include "zutil.h" + ++#ifndef Z_FREETYPE + local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); ++#endif + + #define BASE 65521U /* largest prime smaller than 65536 */ + #define NMAX 5552 +@@ -139,6 +141,8 @@ uLong ZEXPORT adler32( + return adler32_z(adler, buf, len); + } + ++#ifndef Z_FREETYPE ++ + /* ========================================================================= */ + local uLong adler32_combine_( + uLong adler1, +@@ -184,3 +188,5 @@ uLong ZEXPORT adler32_combine64( + { + return adler32_combine_(adler1, adler2, len2); + } ++ ++#endif /* !Z_FREETYPE */ +diff --git a/src/gzip/gzguts.h b/src/gzip/gzguts.h +index 57faf3716..4f09a52a7 100644 +--- a/src/gzip/gzguts.h ++++ b/src/gzip/gzguts.h +@@ -163,7 +163,7 @@ + + /* values for gz_state how */ + #define LOOK 0 /* look for a gzip header */ +-#define COPY 1 /* copy input directly */ ++#define COPY__ 1 /* copy input directly */ + #define GZIP 2 /* decompress a gzip stream */ + + /* internal gzip file state data structure */ +diff --git a/src/gzip/inflate.c b/src/gzip/inflate.c +index 4375557b4..5bf5b815e 100644 +--- a/src/gzip/inflate.c ++++ b/src/gzip/inflate.c +@@ -99,8 +99,10 @@ local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + #ifdef BUILDFIXED + void makefixed OF((void)); + #endif ++#ifndef Z_FREETYPE + local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); ++#endif + + local int inflateStateCheck( + z_streamp strm) +@@ -245,6 +247,8 @@ int ZEXPORT inflateInit_( + return inflateInit2_(strm, DEF_WBITS, version, stream_size); + } + ++#ifndef Z_FREETYPE ++ + int ZEXPORT inflatePrime( + z_streamp strm, + int bits, +@@ -266,6 +270,8 @@ int ZEXPORT inflatePrime( + return Z_OK; + } + ++#endif /* !Z_FREETYPE */ ++ + /* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. +@@ -1312,6 +1318,8 @@ int ZEXPORT inflateEnd( + return Z_OK; + } + ++#ifndef Z_FREETYPE ++ + int ZEXPORT inflateGetDictionary( + z_streamp strm, + Bytef *dictionary, +@@ -1471,6 +1479,8 @@ int ZEXPORT inflateSync( + return Z_OK; + } + ++#endif /* !Z_FREETYPE */ ++ + /* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP +@@ -1489,6 +1499,8 @@ int ZEXPORT inflateSyncPoint( + return state->mode == STORED && state->bits == 0; + } + ++#ifndef Z_FREETYPE ++ + int ZEXPORT inflateCopy( + z_streamp dest, + z_streamp source) +@@ -1536,6 +1548,8 @@ int ZEXPORT inflateCopy( + return Z_OK; + } + ++#endif /* !Z_FREETYPE */ ++ + int ZEXPORT inflateUndermine( + z_streamp strm, + int subvert) +@@ -1569,6 +1583,8 @@ int ZEXPORT inflateValidate( + return Z_OK; + } + ++#ifndef Z_FREETYPE ++ + long ZEXPORT inflateMark( + z_streamp strm) + { +@@ -1590,3 +1606,5 @@ unsigned long ZEXPORT inflateCodesUsed( + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); + } ++ ++#endif /* !Z_FREETYPE */ +diff --git a/src/gzip/inflate.h b/src/gzip/inflate.h +index f127b6b1f..c6f5a52e1 100644 +--- a/src/gzip/inflate.h ++++ b/src/gzip/inflate.h +@@ -3,6 +3,9 @@ + * For conditions of distribution and use, see copyright notice in zlib.h + */ + ++#ifndef INFLATE_H ++#define INFLATE_H ++ + /* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. +@@ -124,3 +127,5 @@ struct inflate_state { + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ + }; ++ ++#endif /* INFLATE_H */ +diff --git a/src/gzip/inftrees.h b/src/gzip/inftrees.h +index baa53a0b1..c94eb78b5 100644 +--- a/src/gzip/inftrees.h ++++ b/src/gzip/inftrees.h +@@ -3,6 +3,9 @@ + * For conditions of distribution and use, see copyright notice in zlib.h + */ + ++#ifndef INFTREES_H ++#define INFTREES_H ++ + /* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. +@@ -60,3 +63,5 @@ typedef enum { + int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); ++ ++#endif /* INFTREES_H_ */ +diff --git a/src/gzip/zlib.h b/src/gzip/zlib.h +index 4a98e38bf..d760140c2 100644 +--- a/src/gzip/zlib.h ++++ b/src/gzip/zlib.h +@@ -31,7 +31,7 @@ + #ifndef ZLIB_H + #define ZLIB_H + +-#include "zconf.h" ++#include "ftzconf.h" + + #ifdef __cplusplus + extern "C" { +@@ -211,6 +211,8 @@ typedef gz_header FAR *gz_headerp; + + #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + ++#ifndef Z_FREETYPE ++ + #define zlib_version zlibVersion() + /* for compatibility with versions < 1.0.2 */ + +@@ -246,7 +248,6 @@ ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + this will be done by deflate(). + */ + +- + ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); + /* + deflate compresses as much data as possible, and stops when the input +@@ -373,6 +374,7 @@ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); + deallocated). + */ + ++#endif /* !Z_FREETYPE */ + + /* + ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); +@@ -534,6 +536,8 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); + The following functions are needed only in some special applications. + */ + ++#ifndef Z_FREETYPE ++ + /* + ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, +@@ -956,6 +960,8 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + destination. + */ + ++#endif /* !Z_FREETYPE */ ++ + ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); + /* + This function is equivalent to inflateEnd followed by inflateInit, +@@ -980,6 +986,8 @@ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + the windowBits parameter is invalid. + */ + ++#ifndef Z_FREETYPE ++ + ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +@@ -1069,6 +1077,8 @@ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + stream state was inconsistent. + */ + ++#endif /* !Z_FREETYPE */ ++ + /* + ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); +@@ -1095,6 +1105,8 @@ typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); + typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + ++#ifndef Z_FREETYPE ++ + ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +@@ -1214,6 +1226,8 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); + 27-31: 0 (reserved) + */ + ++#endif /* !Z_FREETYPE */ ++ + #ifndef Z_SOLO + + /* utility functions */ +@@ -1742,6 +1756,8 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); + if (crc != original_crc) error(); + */ + ++#ifndef Z_FREETYPE ++ + ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf, + z_size_t len)); + /* +@@ -1822,6 +1838,19 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + ZLIB_VERSION, (int)sizeof(z_stream)) + #endif + ++#else /* Z_FREETYPE */ ++ ++ ++ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, ++ const char *version, int stream_size)); ++ ++# define inflateInit2(strm, windowBits) \ ++ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ ++ (int)sizeof(z_stream)) ++ ++#endif /* Z_FREETYPE */ ++ ++ + #ifndef Z_SOLO + + /* gzgetc() macro and its supporting function and exposed data structure. Note +@@ -1901,13 +1930,16 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ + + #else /* Z_SOLO */ + ++#ifndef Z_FREETYPE + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); ++#endif + + #endif /* !Z_SOLO */ + + /* undocumented functions */ ++#ifndef Z_FREETYPE + ZEXTERN const char * ZEXPORT zError OF((int)); + ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); + ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +@@ -1927,6 +1959,7 @@ ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + va_list va)); + # endif + #endif ++#endif /* !Z_FREETYPE */ + + #ifdef __cplusplus + } +diff --git a/src/gzip/zutil.h b/src/gzip/zutil.h +index d9a20ae1b..14f0f1a85 100644 +--- a/src/gzip/zutil.h ++++ b/src/gzip/zutil.h +@@ -188,6 +188,8 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + #pragma warn -8066 + #endif + ++#ifndef Z_FREETYPE ++ + /* provide prototypes for these when building zlib without LFS */ + #if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) +@@ -195,6 +197,8 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); + #endif + ++#endif /* !Z_FREETYPE */ ++ + /* common defaults */ + + #ifndef OS_CODE +@@ -226,9 +230,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + # define zmemcmp _fmemcmp + # define zmemzero(dest, len) _fmemset(dest, 0, len) + # else +-# define zmemcpy memcpy +-# define zmemcmp memcmp +-# define zmemzero(dest, len) memset(dest, 0, len) ++# define zmemcpy ft_memcpy ++# define zmemcmp ft_memcmp ++# define zmemzero(dest, len) ft_memset(dest, 0, len) + # endif + #else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); diff --git a/thirdparty/freetype/src/gzip/zlib.h b/thirdparty/freetype/src/gzip/zlib.h index a4e82c6a02..d760140c2e 100644 --- a/thirdparty/freetype/src/gzip/zlib.h +++ b/thirdparty/freetype/src/gzip/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.1.4, March 11th, 2002 + version 1.2.12, March 11th, 2022 - Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -24,12 +24,12 @@ The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ -#ifndef _ZLIB_H -#define _ZLIB_H +#ifndef ZLIB_H +#define ZLIB_H #include "ftzconf.h" @@ -37,27 +37,45 @@ extern "C" { #endif -#define ZLIB_VERSION "1.1.4" +#define ZLIB_VERSION "1.2.12" +#define ZLIB_VERNUM 0x12c0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 12 +#define ZLIB_VER_SUBREVISION 0 /* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output (providing more output space) before each call. - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio. + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); @@ -66,68 +84,95 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ + z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ + uLong total_in; /* total number of input bytes read so far */ - Bytef *next_out; /* next output byte should be put there */ + Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ + uLong total_out; /* total number of bytes output so far */ - char *msg; /* last error message, NULL if no error */ + z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ - int data_type; /* best guess about the data type: ascii or binary */ - uLong adler; /* adler32 value of the uncompressed data */ + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the opaque value. - zalloc must return Z_NULL if there is not enough memory for the object. + zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 -/* Allowed flush values; see deflate() below for details */ +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 @@ -138,8 +183,8 @@ typedef z_stream FAR *z_streamp; #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 @@ -150,636 +195,1522 @@ typedef z_stream FAR *z_streamp; #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 -#define Z_ASCII 1 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 -/* Possible values of the data_type field */ +/* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ +#ifndef Z_FREETYPE + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + /* basic functions */ +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. */ /* -ZEXTERN(int) deflateInit OF((z_streamp strm, int level)); +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). */ - +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); /* deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when forced to flush. - The detailed semantics are as follows. deflate performs one or both of the + The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not + accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - the compression. + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero - avail_out). + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - 0.1% larger than avail_in plus 12 bytes. If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update data_type if it can make a good guess about - the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. */ +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. + This function discards any unprocessed input and does not flush any pending + output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be deallocated). */ +#endif /* !Z_FREETYPE */ /* -ZEXTERN(int) inflateInit OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - Initializes the internal stream state for decompression. The fields + Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. */ -ZEXTERN(int) inflate OF((z_streamp strm, int flush)); +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); /* inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may some - introduce some output latency (reading input without producing any output) - except when forced to flush. + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. - The detailed semantics are as follows. inflate performs one or both of the + The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much - output as possible to the output buffer. The flushing behavior of inflate is - not specified for values of the flush parameter other than Z_SYNC_FLUSH - and Z_FINISH, but the current implementation actually flushes as much output - as possible anyway. + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster routine - may be used for the single inflate() call. - - If a preset dictionary is needed at this point (see inflateSetDictionary - below), inflate sets strm-adler to the adler32 checksum of the - dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise - it sets strm->adler to the adler32 checksum of all output produced - so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or - an error code as described below. At the end of the stream, inflate() - checks that its computed adler32 checksum is equal to that saved by the - compressor and returns Z_STREAM_END only if the checksum is correct. + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect - adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent - (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if no progress is possible or if there was not - enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR - case, the application may then call inflateSync to look for a good - compression block. + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. */ -ZEXTERN(int) inflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. + This function discards any unprocessed input and does not flush any pending + output. - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. */ + /* Advanced functions */ /* The following functions are needed only in some special applications. */ +#ifndef Z_FREETYPE + /* -ZEXTERN(int) deflateInit2 OF((z_streamp strm, +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy)); - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. + This is another version of deflateInit with more compression options. The + fields zalloc, zfree and opaque must be initialized before by the caller. - The method parameter is the compression method. It must be Z_DEFLATED in + The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. - The strategy parameter is used to tune the compression algorithm. Use the + The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match). Filtered data consists mostly of small values with a - somewhat random distribution. In this case, the compression algorithm is - tuned to compress them better. The effect of Z_FILTERED is to force more - Huffman coding and less string matching; it is somewhat intermediate - between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects - the compression ratio but not the correctness of the compressed output even - if it is not set appropriately. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). */ +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a + used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. - Upon return of this function, strm->adler is set to the Adler32 value + Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The Adler32 value + which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). */ +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed + data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and + (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). */ +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); /* Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be + interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. */ +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); /* -ZEXTERN(int) inflateInit2 OF((z_streamp strm, + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits)); - This is another version of inflateInit with an extra parameter. The + This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. If a compressed stream with a larger window size is given as - input, inflate() will return with the error code Z_DATA_ERROR instead of - trying to allocate a larger window. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative - memLevel). msg is set to null if there is no error message. inflateInit2 - does not perform any decompression apart from reading the zlib header if - present: this will be done by inflate(). (So next_in and avail_in may be - modified, but next_out and avail_out are unchanged.) + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. */ +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); /* Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate - if this call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the Adler32 value returned by this call of - inflate. The compressor and decompressor must use exactly the same - dictionary (see deflateSetDictionary). + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect Adler32 value). inflateSetDictionary does not + expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. */ -ZEXTERN(int) inflateReset OF((z_streamp strm)); +#endif /* !Z_FREETYPE */ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +#ifndef Z_FREETYPE + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +#endif /* !Z_FREETYPE */ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). +#ifndef Z_FREETYPE + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. */ +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#endif /* !Z_FREETYPE */ + +#ifndef Z_SOLO /* utility functions */ /* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. */ +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); /* Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least 0.1% larger than - sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); /* - Compresses the source buffer into the destination buffer. The level + Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); /* Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. */ +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h". (See the description - of deflateInit2 for more information about the strategy parameter.) +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Open the gzip (.gz) file at path for reading and decompressing, or + compressing and writing. The mode parameter is as in fopen ("rb" or "wb") + but can also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", + 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression + as in "wb9F". (See the description of deflateInit2 for more information + about the strategy parameter.) 'T' will request transparent writing or + appending with no compression and not using the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); /* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. */ +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. */ +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ + Read and decompress up to len uncompressed bytes from file into buf. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); /* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. */ +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); /* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). + Compress and write the len uncompressed bytes at buf to file. gzwrite + returns the number of uncompressed bytes written or 0 in case of error. */ +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); /* - Writes the given null-terminated string to the compressed file, excluding + Compress and write nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf(), + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Compress and write the given null-terminated string s to file, excluding the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. */ +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); /* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. + Compress and write c, converted to an unsigned char, into file. gzputc + returns the value that was written, or -1 in case of error. */ +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); /* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. + Read and decompress one byte from file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. */ +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); /* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). */ +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); /* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. */ /* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are + extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. - gzseek returns the resulting offset location as measured in bytes from + gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); /* - Rewinds the given file. This function is supported only for reading. + Rewind file. This function is supported only for reading. - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). */ /* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Return true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) */ +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); /* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. */ +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); /* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. */ +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); /* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. + Return the error message for the last error which occurred on file. + errnum is set to zlib error number. If an error occurred in the file system + and not in the compression library, errnum is set to Z_ERRNO and the + application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. */ +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clear the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + /* checksum functions */ /* These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. + anyway because they might be useful in applications using the compression + library. */ -ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len)); - +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: + return the updated checksum. An Adler-32 value is in the range of a 32-bit + unsigned integer. If buf is Z_NULL, this function returns the required + initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: uLong adler = adler32(0L, Z_NULL, 0); @@ -789,11 +1720,32 @@ ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); /* - Update a running crc with the bytes buf[0..len-1] and return the updated - crc. If buf is NULL, this function returns the required initial value - for the crc. Pre- and post-conditioning (one's complement) is performed - within this function so it shouldn't be done by the application. + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. + If buf is Z_NULL, this function returns the required initial value for the + crc. Pre- and post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the application. + Usage example: uLong crc = crc32(0L, Z_NULL, 0); @@ -804,27 +1756,213 @@ ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ +#ifndef Z_FREETYPE + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2)); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). +*/ + +ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. +*/ + /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ -ZEXTERN(int) inflateInit2_ OF((z_streamp strm, int windowBits, +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#else /* Z_FREETYPE */ + + +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) + +#endif /* Z_FREETYPE */ + + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# define z_crc32_combine_gen z_crc32_combine_gen64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# define crc32_combine_gen crc32_combine_gen64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); +#endif + +#else /* Z_SOLO */ + +#ifndef Z_FREETYPE + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); +#endif + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +#ifndef Z_FREETYPE +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif +#endif /* !Z_FREETYPE */ #ifdef __cplusplus } #endif -#endif /* _ZLIB_H */ +#endif /* ZLIB_H */ diff --git a/thirdparty/freetype/src/gzip/zutil.c b/thirdparty/freetype/src/gzip/zutil.c index 7ad0c1f81b..a19ac2b96d 100644 --- a/thirdparty/freetype/src/gzip/zutil.c +++ b/thirdparty/freetype/src/gzip/zutil.c @@ -1,23 +1,155 @@ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. + * Copyright (C) 1995-2017 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" +#ifndef Z_SOLO +# include "gzguts.h" +#endif -#ifndef STDC -extern void exit OF((int)); +z_const char * const z_errmsg[10] = { + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef ZLIB_DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef ZLIB_DEBUG +#include <stdlib.h> +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error ( + char *m) +{ + fprintf(stderr, "%s\n", m); + exit(1); +} #endif +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError( + int err) +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 + /* The older Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif #ifndef HAVE_MEMCPY -void zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; +void ZLIB_INTERNAL zmemcpy( + Bytef* dest, + const Bytef* source, + uInt len) { if (len == 0) return; do { @@ -25,10 +157,10 @@ void zmemcpy(dest, source, len) } while (--len != 0); } -int zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; +int ZLIB_INTERNAL zmemcmp( + const Bytef* s1, + const Bytef* s2, + uInt len) { uInt j; @@ -38,9 +170,9 @@ int zmemcmp(s1, s2, len) return 0; } -void zmemzero(dest, len) - Bytef* dest; - uInt len; +void ZLIB_INTERNAL zmemzero( + Bytef* dest, + uInt len) { if (len == 0) return; do { @@ -49,11 +181,13 @@ void zmemzero(dest, len) } #endif -#if defined( MSDOS ) && defined( __TURBOC__ ) && !defined( MY_ZCALLOC ) -#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) -/* Small and medium model in Turbo C are for now limited to near allocation - * with reduced MAX_WBITS and MAX_MEM_LEVEL - */ +#ifndef Z_SOLO + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + # define MY_ZCALLOC /* Turbo C malloc() does not allow dynamic allocation of 64K bytes @@ -80,11 +214,13 @@ local ptr_table table[MAX_PTR]; * a protected system like OS/2. Use Microsoft C instead. */ -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) { - voidpf buf = opaque; /* just to make some compilers happy */ + voidpf buf; ulg bsize = (ulg)items*size; + (void)opaque; + /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ @@ -104,9 +240,12 @@ voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) return buf; } -void zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { int n; + + (void)opaque; + if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; @@ -122,14 +261,13 @@ void zcfree (voidpf opaque, voidpf ptr) next_ptr--; return; } - ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } -#endif -#endif /* MSDOS && __TURBOC__ */ + +#endif /* __TURBOC__ */ -#if defined(M_I86) && !defined(__32BIT__) && !defined( MY_ZCALLOC ) +#ifdef M_I86 /* Microsoft C in 16-bit mode */ # define MY_ZCALLOC @@ -139,43 +277,49 @@ void zcfree (voidpf opaque, voidpf ptr) # define _hfree hfree #endif -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) { - if (opaque) opaque = 0; /* to make compiler happy */ + (void)opaque; return _halloc((long)items, size); } -void zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { - if (opaque) opaque = 0; /* to make compiler happy */ + (void)opaque; _hfree(ptr); } -#endif /* MSC */ +#endif /* M_I86 */ + +#endif /* SYS16BIT */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC -extern voidp ft_scalloc OF((uInt items, uInt size)); -extern void ft_sfree OF((voidpf ptr)); +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); #endif -voidpf zcalloc (opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; +voidpf ZLIB_INTERNAL zcalloc ( + voidpf opaque, + unsigned items, + unsigned size) { - if (opaque) items += size - size; /* make compiler happy */ - return (voidpf)ft_scalloc(items, size); + (void)opaque; + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); } -void zcfree (opaque, ptr) - voidpf opaque; - voidpf ptr; +void ZLIB_INTERNAL zcfree ( + voidpf opaque, + voidpf ptr) { - ft_sfree(ptr); - if (opaque) return; /* make compiler happy */ + (void)opaque; + free(ptr); } #endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/thirdparty/freetype/src/gzip/zutil.h b/thirdparty/freetype/src/gzip/zutil.h index c9688cd9c0..14f0f1a85e 100644 --- a/thirdparty/freetype/src/gzip/zutil.h +++ b/thirdparty/freetype/src/gzip/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. + * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -10,26 +10,31 @@ /* @(#) $Id$ */ -#ifndef _Z_UTIL_H -#define _Z_UTIL_H +#ifndef ZUTIL_H +#define ZUTIL_H + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif #include "zlib.h" -#ifdef STDC -# include <stddef.h> +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include <stddef.h> +# endif # include <string.h> # include <stdlib.h> #endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include <errno.h> -#endif #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ typedef unsigned char uch; typedef uch FAR uchf; @@ -37,9 +42,24 @@ typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; +#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC) +# include <limits.h> +# if (ULONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long +# elif (ULLONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long long +# elif (UINT_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned +# endif +#endif + +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) + return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ @@ -69,90 +89,129 @@ typedef unsigned long ulg; /* target dependencies */ -#ifdef MSDOS +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include <alloc.h> +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include <alloc.h> +# endif +# else /* MSC or DJGPP */ +# include <malloc.h> # endif -# else /* MSC or DJGPP */ # endif #endif -#ifdef OS2 -# define OS_CODE 0x06 -#endif - -#ifdef WIN32 /* Window 95 & Windows NT */ -# define OS_CODE 0x0b +#ifdef AMIGA +# define OS_CODE 1 #endif #if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 +# define OS_CODE 2 # define F_OPEN(name, mode) \ - ft_fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif -#ifdef AMIGA -# define OS_CODE 0x01 +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif #endif #if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 +# define OS_CODE 5 +#endif + +#ifdef OS2 +# define OS_CODE 6 +# if defined(M_I86) && !defined(Z_SOLO) +# include <malloc.h> +# endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include <unix.h> /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ +# define OS_CODE 7 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include <unix.h> /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif # endif # endif #endif -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0F +#ifdef __acorn +# define OS_CODE 13 +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 +#endif + +#ifdef _BEOS_ +# define OS_CODE 16 #endif -#ifdef TOPS20 -# define OS_CODE 0x0a +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 #endif #if defined(_BEOS_) || defined(RISCOS) # define fdopen(fd,mode) NULL /* No fdopen() */ #endif -#if (defined(_MSC_VER) && (_MSC_VER > 600)) -# define fdopen(fd,type) _fdopen(fd,type) +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif #endif +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif - /* Common defaults */ +#ifndef Z_FREETYPE + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + +#endif /* !Z_FREETYPE */ + + /* common defaults */ #ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ +# define OS_CODE 3 /* assume Unix */ #endif #ifndef F_OPEN -# define F_OPEN(name, mode) ft_fopen((name), (mode)) +# define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ -#ifdef HAVE_STRERROR - extern char *strerror OF((int)); -# define zstrerror(errnum) strerror(errnum) -#else -# define zstrerror(errnum) "" -#endif - -#if defined(pyr) +#if defined(pyr) || defined(Z_SOLO) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) @@ -176,16 +235,16 @@ typedef unsigned long ulg; # define zmemzero(dest, len) ft_memset(dest, 0, len) # endif #else - extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - extern void zmemzero OF((Bytef* dest, uInt len)); + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); #endif /* Diagnostic functions */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG # include <stdio.h> - extern int z_verbose; - extern void z_error OF((char *m)); + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} @@ -201,15 +260,19 @@ typedef unsigned long ulg; # define Tracecv(c,x) #endif - -typedef uLong (*check_func) OF((uLong check, const Bytef *buf, - uInt len)); -local voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -local void zcfree OF((voidpf opaque, voidpf ptr)); +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} -#endif /* _Z_UTIL_H */ +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +#endif /* ZUTIL_H */ diff --git a/thirdparty/freetype/src/lzw/ftlzw.c b/thirdparty/freetype/src/lzw/ftlzw.c index e112418ab1..e12efcaa56 100644 --- a/thirdparty/freetype/src/lzw/ftlzw.c +++ b/thirdparty/freetype/src/lzw/ftlzw.c @@ -8,7 +8,7 @@ * be used to parse compressed PCF fonts, as found with many X11 server * distributions. * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * Albert Chin-A-Young. * * based on code in `src/gzip/ftgzip.c' @@ -369,7 +369,7 @@ FT_ZERO( stream ); stream->memory = memory; - if ( !FT_NEW( zip ) ) + if ( !FT_QNEW( zip ) ) { error = ft_lzw_file_init( zip, stream, source ); if ( error ) diff --git a/thirdparty/freetype/src/lzw/ftzopen.c b/thirdparty/freetype/src/lzw/ftzopen.c index 8b5b357f36..aaa98be211 100644 --- a/thirdparty/freetype/src/lzw/ftzopen.c +++ b/thirdparty/freetype/src/lzw/ftzopen.c @@ -8,7 +8,7 @@ * be used to parse compressed PCF fonts, as found with many X11 server * distributions. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/lzw/ftzopen.h b/thirdparty/freetype/src/lzw/ftzopen.h index 9ada742c73..86fccfe3be 100644 --- a/thirdparty/freetype/src/lzw/ftzopen.h +++ b/thirdparty/freetype/src/lzw/ftzopen.h @@ -8,7 +8,7 @@ * be used to parse compressed PCF fonts, as found with many X11 server * distributions. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvalid.c b/thirdparty/freetype/src/otvalid/otvalid.c index 869233ce8c..f5344ca031 100644 --- a/thirdparty/freetype/src/otvalid/otvalid.c +++ b/thirdparty/freetype/src/otvalid/otvalid.c @@ -4,7 +4,7 @@ * * FreeType validator for OpenType tables (body only). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvalid.h b/thirdparty/freetype/src/otvalid/otvalid.h index f8ca454d6e..6274858f51 100644 --- a/thirdparty/freetype/src/otvalid/otvalid.h +++ b/thirdparty/freetype/src/otvalid/otvalid.h @@ -4,7 +4,7 @@ * * OpenType table validation (specification only). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvbase.c b/thirdparty/freetype/src/otvalid/otvbase.c index 83f998cdb1..70de653b19 100644 --- a/thirdparty/freetype/src/otvalid/otvbase.c +++ b/thirdparty/freetype/src/otvalid/otvbase.c @@ -4,7 +4,7 @@ * * OpenType BASE table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvcommn.c b/thirdparty/freetype/src/otvalid/otvcommn.c index 40624bb159..b9873ff21b 100644 --- a/thirdparty/freetype/src/otvalid/otvcommn.c +++ b/thirdparty/freetype/src/otvalid/otvcommn.c @@ -4,7 +4,7 @@ * * OpenType common tables validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvcommn.h b/thirdparty/freetype/src/otvalid/otvcommn.h index 3b096ecca8..f1e4a6a9a6 100644 --- a/thirdparty/freetype/src/otvalid/otvcommn.h +++ b/thirdparty/freetype/src/otvalid/otvcommn.h @@ -4,7 +4,7 @@ * * OpenType common tables validation (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otverror.h b/thirdparty/freetype/src/otvalid/otverror.h index 3e23234f36..8c75c58299 100644 --- a/thirdparty/freetype/src/otvalid/otverror.h +++ b/thirdparty/freetype/src/otvalid/otverror.h @@ -4,7 +4,7 @@ * * OpenType validation module error codes (specification only). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvgdef.c b/thirdparty/freetype/src/otvalid/otvgdef.c index 5a160a4142..425335336d 100644 --- a/thirdparty/freetype/src/otvalid/otvgdef.c +++ b/thirdparty/freetype/src/otvalid/otvgdef.c @@ -4,7 +4,7 @@ * * OpenType GDEF table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvgpos.c b/thirdparty/freetype/src/otvalid/otvgpos.c index e0d4e420de..52e2cd1c22 100644 --- a/thirdparty/freetype/src/otvalid/otvgpos.c +++ b/thirdparty/freetype/src/otvalid/otvgpos.c @@ -4,7 +4,7 @@ * * OpenType GPOS table validation (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvgpos.h b/thirdparty/freetype/src/otvalid/otvgpos.h index 176a68883f..85ef609160 100644 --- a/thirdparty/freetype/src/otvalid/otvgpos.h +++ b/thirdparty/freetype/src/otvalid/otvgpos.h @@ -4,7 +4,7 @@ * * OpenType GPOS table validator (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvgsub.c b/thirdparty/freetype/src/otvalid/otvgsub.c index b426a17449..3b6dcbb7ae 100644 --- a/thirdparty/freetype/src/otvalid/otvgsub.c +++ b/thirdparty/freetype/src/otvalid/otvgsub.c @@ -4,7 +4,7 @@ * * OpenType GSUB table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvjstf.c b/thirdparty/freetype/src/otvalid/otvjstf.c index 404dda88a1..0934716a5a 100644 --- a/thirdparty/freetype/src/otvalid/otvjstf.c +++ b/thirdparty/freetype/src/otvalid/otvjstf.c @@ -4,7 +4,7 @@ * * OpenType JSTF table validation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvmath.c b/thirdparty/freetype/src/otvalid/otvmath.c index b4bfabb62e..a59557b375 100644 --- a/thirdparty/freetype/src/otvalid/otvmath.c +++ b/thirdparty/freetype/src/otvalid/otvmath.c @@ -4,7 +4,7 @@ * * OpenType MATH table validation (body). * - * Copyright (C) 2007-2021 by + * Copyright (C) 2007-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by George Williams. diff --git a/thirdparty/freetype/src/otvalid/otvmod.c b/thirdparty/freetype/src/otvalid/otvmod.c index b7d674b5e2..3fc2dbe504 100644 --- a/thirdparty/freetype/src/otvalid/otvmod.c +++ b/thirdparty/freetype/src/otvalid/otvmod.c @@ -4,7 +4,7 @@ * * FreeType's OpenType validation module implementation (body). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/otvalid/otvmod.h b/thirdparty/freetype/src/otvalid/otvmod.h index 37c20e0023..2f0bcd6e44 100644 --- a/thirdparty/freetype/src/otvalid/otvmod.h +++ b/thirdparty/freetype/src/otvalid/otvmod.h @@ -5,7 +5,7 @@ * FreeType's OpenType validation module implementation * (specification). * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pcf/pcfread.c b/thirdparty/freetype/src/pcf/pcfread.c index e60a0a5141..f167bcb8ae 100644 --- a/thirdparty/freetype/src/pcf/pcfread.c +++ b/thirdparty/freetype/src/pcf/pcfread.c @@ -1034,16 +1034,6 @@ THE SOFTWARE. enc->lastRow > 0xFF ) return FT_THROW( Invalid_Table ); - nencoding = (FT_ULong)( enc->lastCol - enc->firstCol + 1 ) * - (FT_ULong)( enc->lastRow - enc->firstRow + 1 ); - - if ( FT_NEW_ARRAY( enc->offset, nencoding ) ) - goto Bail; - - error = FT_Stream_EnterFrame( stream, 2 * nencoding ); - if ( error ) - goto Exit; - FT_TRACE5(( "\n" )); defaultCharRow = enc->defaultChar >> 8; @@ -1064,6 +1054,13 @@ THE SOFTWARE. defaultCharCol = enc->firstCol; } + nencoding = (FT_ULong)( enc->lastCol - enc->firstCol + 1 ) * + (FT_ULong)( enc->lastRow - enc->firstRow + 1 ); + + error = FT_Stream_EnterFrame( stream, 2 * nencoding ); + if ( error ) + goto Bail; + /* * FreeType mandates that glyph index 0 is the `undefined glyph', which * PCF calls the `default character'. However, FreeType needs glyph @@ -1109,6 +1106,9 @@ THE SOFTWARE. /* copy metrics of default character to index 0 */ face->metrics[0] = face->metrics[defaultCharEncodingOffset]; + if ( FT_QNEW_ARRAY( enc->offset, nencoding ) ) + goto Bail; + /* now loop over all values */ offset = enc->offset; for ( i = enc->firstRow; i <= enc->lastRow; i++ ) @@ -1131,11 +1131,6 @@ THE SOFTWARE. } FT_Stream_ExitFrame( stream ); - return error; - - Exit: - FT_FREE( enc->offset ); - Bail: return error; } diff --git a/thirdparty/freetype/src/pfr/pfr.c b/thirdparty/freetype/src/pfr/pfr.c index 4058ad5652..1dd38f9393 100644 --- a/thirdparty/freetype/src/pfr/pfr.c +++ b/thirdparty/freetype/src/pfr/pfr.c @@ -4,7 +4,7 @@ * * FreeType PFR driver component. * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrcmap.c b/thirdparty/freetype/src/pfr/pfrcmap.c index 6a7f573594..6fa2417dc1 100644 --- a/thirdparty/freetype/src/pfr/pfrcmap.c +++ b/thirdparty/freetype/src/pfr/pfrcmap.c @@ -4,7 +4,7 @@ * * FreeType PFR cmap handling (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrcmap.h b/thirdparty/freetype/src/pfr/pfrcmap.h index 17c02a2b4b..afde164f9b 100644 --- a/thirdparty/freetype/src/pfr/pfrcmap.h +++ b/thirdparty/freetype/src/pfr/pfrcmap.h @@ -4,7 +4,7 @@ * * FreeType PFR cmap handling (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrdrivr.c b/thirdparty/freetype/src/pfr/pfrdrivr.c index 16b8f79471..2a753c583a 100644 --- a/thirdparty/freetype/src/pfr/pfrdrivr.c +++ b/thirdparty/freetype/src/pfr/pfrdrivr.c @@ -4,7 +4,7 @@ * * FreeType PFR driver interface (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrdrivr.h b/thirdparty/freetype/src/pfr/pfrdrivr.h index 6ff16fea06..cfd749ab0e 100644 --- a/thirdparty/freetype/src/pfr/pfrdrivr.h +++ b/thirdparty/freetype/src/pfr/pfrdrivr.h @@ -4,7 +4,7 @@ * * High-level Type PFR driver interface (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrerror.h b/thirdparty/freetype/src/pfr/pfrerror.h index 255696efed..98b8f2fd58 100644 --- a/thirdparty/freetype/src/pfr/pfrerror.h +++ b/thirdparty/freetype/src/pfr/pfrerror.h @@ -4,7 +4,7 @@ * * PFR error codes (specification only). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrgload.c b/thirdparty/freetype/src/pfr/pfrgload.c index b400042a86..1b8d6cdecc 100644 --- a/thirdparty/freetype/src/pfr/pfrgload.c +++ b/thirdparty/freetype/src/pfr/pfrgload.c @@ -4,7 +4,7 @@ * * FreeType PFR glyph loader (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrgload.h b/thirdparty/freetype/src/pfr/pfrgload.h index b726d564fc..af59296910 100644 --- a/thirdparty/freetype/src/pfr/pfrgload.h +++ b/thirdparty/freetype/src/pfr/pfrgload.h @@ -4,7 +4,7 @@ * * FreeType PFR glyph loader (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrload.c b/thirdparty/freetype/src/pfr/pfrload.c index a9c1e2834a..6bf7979750 100644 --- a/thirdparty/freetype/src/pfr/pfrload.c +++ b/thirdparty/freetype/src/pfr/pfrload.c @@ -4,7 +4,7 @@ * * FreeType PFR loader (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -993,7 +993,7 @@ PFR_CHECK_SIZE( count * Size ); - if ( FT_NEW_ARRAY( phy_font->chars, count ) ) + if ( FT_QNEW_ARRAY( phy_font->chars, count ) ) goto Fail; for ( n = 0; n < count; n++ ) diff --git a/thirdparty/freetype/src/pfr/pfrload.h b/thirdparty/freetype/src/pfr/pfrload.h index 4f467d1bad..5e0f451fa0 100644 --- a/thirdparty/freetype/src/pfr/pfrload.h +++ b/thirdparty/freetype/src/pfr/pfrload.h @@ -4,7 +4,7 @@ * * FreeType PFR loader (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrobjs.c b/thirdparty/freetype/src/pfr/pfrobjs.c index 3080cb650b..5a6e3979d5 100644 --- a/thirdparty/freetype/src/pfr/pfrobjs.c +++ b/thirdparty/freetype/src/pfr/pfrobjs.c @@ -4,7 +4,7 @@ * * FreeType PFR object methods (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -207,7 +207,7 @@ pfrface->height = (FT_Short)( ( pfrface->units_per_EM * 12 ) / 10 ); if ( pfrface->height < pfrface->ascender - pfrface->descender ) - pfrface->height = (FT_Short)(pfrface->ascender - pfrface->descender); + pfrface->height = (FT_Short)( pfrface->ascender - pfrface->descender ); if ( phy_font->num_strikes > 0 ) { diff --git a/thirdparty/freetype/src/pfr/pfrobjs.h b/thirdparty/freetype/src/pfr/pfrobjs.h index 70b05395b8..9ffc297d59 100644 --- a/thirdparty/freetype/src/pfr/pfrobjs.h +++ b/thirdparty/freetype/src/pfr/pfrobjs.h @@ -4,7 +4,7 @@ * * FreeType PFR object methods (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrsbit.c b/thirdparty/freetype/src/pfr/pfrsbit.c index 255fd58772..8b23fa156d 100644 --- a/thirdparty/freetype/src/pfr/pfrsbit.c +++ b/thirdparty/freetype/src/pfr/pfrsbit.c @@ -4,7 +4,7 @@ * * FreeType PFR bitmap loader (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrsbit.h b/thirdparty/freetype/src/pfr/pfrsbit.h index f50d8013aa..b948a3842f 100644 --- a/thirdparty/freetype/src/pfr/pfrsbit.h +++ b/thirdparty/freetype/src/pfr/pfrsbit.h @@ -4,7 +4,7 @@ * * FreeType PFR bitmap loader (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pfr/pfrtypes.h b/thirdparty/freetype/src/pfr/pfrtypes.h index dc4fead700..d9a0c78953 100644 --- a/thirdparty/freetype/src/pfr/pfrtypes.h +++ b/thirdparty/freetype/src/pfr/pfrtypes.h @@ -4,7 +4,7 @@ * * FreeType PFR data structures (specification only). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/afmparse.c b/thirdparty/freetype/src/psaux/afmparse.c index 0ad1760518..bd86129f7e 100644 --- a/thirdparty/freetype/src/psaux/afmparse.c +++ b/thirdparty/freetype/src/psaux/afmparse.c @@ -4,7 +4,7 @@ * * AFM parser (body). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/afmparse.h b/thirdparty/freetype/src/psaux/afmparse.h index 44b05b2cac..eee49e3601 100644 --- a/thirdparty/freetype/src/psaux/afmparse.h +++ b/thirdparty/freetype/src/psaux/afmparse.h @@ -4,7 +4,7 @@ * * AFM parser (specification). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/cffdecode.c b/thirdparty/freetype/src/psaux/cffdecode.c index 29b68a8e4f..92139c93ad 100644 --- a/thirdparty/freetype/src/psaux/cffdecode.c +++ b/thirdparty/freetype/src/psaux/cffdecode.c @@ -4,7 +4,7 @@ * * PostScript CFF (Type 2) decoding routines (body). * - * Copyright (C) 2017-2021 by + * Copyright (C) 2017-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -248,7 +248,7 @@ else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { - CFF_Font cff = (CFF_Font)(face->extra.data); + CFF_Font cff = (CFF_Font)( face->extra.data ); bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); diff --git a/thirdparty/freetype/src/psaux/cffdecode.h b/thirdparty/freetype/src/psaux/cffdecode.h index b1314ed1c1..a9f6761824 100644 --- a/thirdparty/freetype/src/psaux/cffdecode.h +++ b/thirdparty/freetype/src/psaux/cffdecode.h @@ -4,7 +4,7 @@ * * PostScript CFF (Type 2) decoding routines (specification). * - * Copyright (C) 2017-2021 by + * Copyright (C) 2017-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/psaux.c b/thirdparty/freetype/src/psaux/psaux.c index 2960c8b696..2ac7949479 100644 --- a/thirdparty/freetype/src/psaux/psaux.c +++ b/thirdparty/freetype/src/psaux/psaux.c @@ -4,7 +4,7 @@ * * FreeType auxiliary PostScript driver component (body only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/psauxerr.h b/thirdparty/freetype/src/psaux/psauxerr.h index e8ee29166c..1504b34ee5 100644 --- a/thirdparty/freetype/src/psaux/psauxerr.h +++ b/thirdparty/freetype/src/psaux/psauxerr.h @@ -4,7 +4,7 @@ * * PS auxiliary module error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/psauxmod.c b/thirdparty/freetype/src/psaux/psauxmod.c index 52da23365e..113490abcd 100644 --- a/thirdparty/freetype/src/psaux/psauxmod.c +++ b/thirdparty/freetype/src/psaux/psauxmod.c @@ -4,7 +4,7 @@ * * FreeType auxiliary PostScript module implementation (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/psauxmod.h b/thirdparty/freetype/src/psaux/psauxmod.h index e3e8063220..2d508edc2a 100644 --- a/thirdparty/freetype/src/psaux/psauxmod.h +++ b/thirdparty/freetype/src/psaux/psauxmod.h @@ -4,7 +4,7 @@ * * FreeType auxiliary PostScript module implementation (specification). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/psconv.c b/thirdparty/freetype/src/psaux/psconv.c index c28d65df29..9b8c0d90c3 100644 --- a/thirdparty/freetype/src/psaux/psconv.c +++ b/thirdparty/freetype/src/psaux/psconv.c @@ -4,7 +4,7 @@ * * Some convenience conversions (body). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -535,11 +535,11 @@ if ( r & 1 ) { - *buffer = (FT_Byte)(*buffer + c); + *buffer = (FT_Byte)( *buffer + c ); buffer++; } else - *buffer = (FT_Byte)(c << 4); + *buffer = (FT_Byte)( c << 4 ); r++; } @@ -572,8 +572,8 @@ if ( p >= limit ) return 0; - if ( n > (FT_UInt)(limit - p) ) - n = (FT_UInt)(limit - p); + if ( n > (FT_UInt)( limit - p ) ) + n = (FT_UInt)( limit - p ); for ( r = 0; r < n; r++ ) { diff --git a/thirdparty/freetype/src/psaux/psconv.h b/thirdparty/freetype/src/psaux/psconv.h index cd91a7bb56..650d7c93b2 100644 --- a/thirdparty/freetype/src/psaux/psconv.h +++ b/thirdparty/freetype/src/psaux/psconv.h @@ -4,7 +4,7 @@ * * Some convenience conversions (specification). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/psintrp.c b/thirdparty/freetype/src/psaux/psintrp.c index c550533a0f..6c640eebd5 100644 --- a/thirdparty/freetype/src/psaux/psintrp.c +++ b/thirdparty/freetype/src/psaux/psintrp.c @@ -1900,7 +1900,8 @@ /* WeightVector */ { FT_UInt idx; - PS_Blend blend = decoder->blend; + PS_Blend blend = decoder->blend; + FT_UInt len_buildchar = decoder->len_buildchar; if ( arg_cnt != 1 || !blend ) @@ -1908,14 +1909,15 @@ idx = (FT_UInt)cf2_stack_popInt( opStack ); - if ( idx + blend->num_designs > - decoder->len_buildchar ) + if ( len_buildchar < blend->num_designs || + len_buildchar - blend->num_designs < idx ) goto Unexpected_OtherSubr; - ft_memcpy( &decoder->buildchar[idx], - blend->weight_vector, - blend->num_designs * - sizeof ( blend->weight_vector[0] ) ); + if ( decoder->buildchar && blend->weight_vector ) + ft_memcpy( &decoder->buildchar[idx], + blend->weight_vector, + blend->num_designs * + sizeof ( blend->weight_vector[0] ) ); } break; diff --git a/thirdparty/freetype/src/psaux/psobjs.c b/thirdparty/freetype/src/psaux/psobjs.c index 30f501916a..371e538020 100644 --- a/thirdparty/freetype/src/psaux/psobjs.c +++ b/thirdparty/freetype/src/psaux/psobjs.c @@ -4,7 +4,7 @@ * * Auxiliary functions for PostScript fonts (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -99,45 +99,31 @@ } - static void - shift_elements( PS_Table table, - FT_Byte* old_base ) - { - FT_PtrDist delta = table->block - old_base; - FT_Byte** offset = table->elements; - FT_Byte** limit = offset + table->max_elems; - - - for ( ; offset < limit; offset++ ) - { - if ( offset[0] ) - offset[0] += delta; - } - } - - static FT_Error - reallocate_t1_table( PS_Table table, - FT_Offset new_size ) + ps_table_realloc( PS_Table table, + FT_Offset new_size ) { FT_Memory memory = table->memory; FT_Byte* old_base = table->block; FT_Error error; - /* allocate new base block */ - if ( FT_ALLOC( table->block, new_size ) ) - { - table->block = old_base; + /* (re)allocate the base block */ + if ( FT_REALLOC( table->block, table->capacity, new_size ) ) return error; - } - /* copy elements and shift offsets */ - if ( old_base ) + /* rebase offsets if necessary */ + if ( old_base && table->block != old_base ) { - FT_MEM_COPY( table->block, old_base, table->capacity ); - shift_elements( table, old_base ); - FT_FREE( old_base ); + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + for ( ; offset < limit; offset++ ) + { + if ( *offset ) + *offset = table->block + ( *offset - old_base ); + } } table->capacity = new_size; @@ -204,7 +190,7 @@ new_size = FT_PAD_CEIL( new_size, 1024 ); } - error = reallocate_t1_table( table, new_size ); + error = ps_table_realloc( table, new_size ); if ( error ) return error; @@ -234,32 +220,12 @@ * @InOut: * table :: * The target table. - * - * @Note: - * This function does NOT release the heap's memory block. It is up - * to the caller to clean it, or reference it in its own structures. */ FT_LOCAL_DEF( void ) ps_table_done( PS_Table table ) { - FT_Memory memory = table->memory; - FT_Error error; - FT_Byte* old_base = table->block; - - - /* should never fail, because rec.cursor <= rec.size */ - if ( !old_base ) - return; - - if ( FT_QALLOC( table->block, table->cursor ) ) - return; - FT_MEM_COPY( table->block, old_base, table->cursor ); - shift_elements( table, old_base ); - - table->capacity = table->cursor; - FT_FREE( old_base ); - - FT_UNUSED( error ); + /* no problem if shrinking fails */ + ps_table_realloc( table, table->cursor ); } @@ -552,7 +518,7 @@ if ( *cur == '<' ) /* <...> */ { - if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */ + if ( cur + 1 < limit && *( cur + 1 ) == '<' ) /* << */ { cur++; cur++; @@ -1098,7 +1064,6 @@ { FT_Byte* q = (FT_Byte*)objects[idx] + field->offset; FT_Long val; - FT_String* string = NULL; skip_spaces( &cur, limit ); @@ -1148,8 +1113,9 @@ case T1_FIELD_TYPE_STRING: case T1_FIELD_TYPE_KEY: { - FT_Memory memory = parser->memory; - FT_UInt len = (FT_UInt)( limit - cur ); + FT_Memory memory = parser->memory; + FT_UInt len = (FT_UInt)( limit - cur ); + FT_String* string = NULL; if ( cur >= limit ) @@ -1190,7 +1156,6 @@ FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n", field->ident )); FT_FREE( *(FT_String**)q ); - *(FT_String**)q = NULL; } if ( FT_QALLOC( string, len + 1 ) ) diff --git a/thirdparty/freetype/src/psaux/psobjs.h b/thirdparty/freetype/src/psaux/psobjs.h index 99d16959a7..f01d4bd503 100644 --- a/thirdparty/freetype/src/psaux/psobjs.h +++ b/thirdparty/freetype/src/psaux/psobjs.h @@ -4,7 +4,7 @@ * * Auxiliary functions for PostScript fonts (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/t1cmap.c b/thirdparty/freetype/src/psaux/t1cmap.c index 3e7c577a18..f297ce75e1 100644 --- a/thirdparty/freetype/src/psaux/t1cmap.c +++ b/thirdparty/freetype/src/psaux/t1cmap.c @@ -4,7 +4,7 @@ * * Type 1 character map support (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/t1cmap.h b/thirdparty/freetype/src/psaux/t1cmap.h index 8f69600ca4..460d91f590 100644 --- a/thirdparty/freetype/src/psaux/t1cmap.h +++ b/thirdparty/freetype/src/psaux/t1cmap.h @@ -4,7 +4,7 @@ * * Type 1 character map support (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/t1decode.c b/thirdparty/freetype/src/psaux/t1decode.c index 7e65bde632..1cdf436fa7 100644 --- a/thirdparty/freetype/src/psaux/t1decode.c +++ b/thirdparty/freetype/src/psaux/t1decode.c @@ -4,7 +4,7 @@ * * PostScript Type 1 decoding routines (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psaux/t1decode.h b/thirdparty/freetype/src/psaux/t1decode.h index eea9d34b04..d60d61c904 100644 --- a/thirdparty/freetype/src/psaux/t1decode.h +++ b/thirdparty/freetype/src/psaux/t1decode.h @@ -4,7 +4,7 @@ * * PostScript Type 1 decoding routines (specification). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pshinter/pshalgo.c b/thirdparty/freetype/src/pshinter/pshalgo.c index 227caeae33..dca539766f 100644 --- a/thirdparty/freetype/src/pshinter/pshalgo.c +++ b/thirdparty/freetype/src/pshinter/pshalgo.c @@ -4,7 +4,7 @@ * * PostScript hinting algorithm (body). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used @@ -182,13 +182,13 @@ count = hints->num_hints; /* allocate our tables */ - if ( FT_NEW_ARRAY( table->sort, 2 * count ) || - FT_NEW_ARRAY( table->hints, count ) || - FT_NEW_ARRAY( table->zones, 2 * count + 1 ) ) + if ( FT_QNEW_ARRAY( table->sort, 2 * count ) || + FT_QNEW_ARRAY( table->hints, count ) || + FT_QNEW_ARRAY( table->zones, 2 * count + 1 ) ) goto Exit; table->max_hints = count; - table->sort_global = table->sort + count; + table->sort_global = FT_OFFSET( table->sort, count ); table->num_hints = 0; table->num_zones = 0; table->zone = NULL; @@ -1167,8 +1167,8 @@ memory = glyph->memory = globals->memory; /* allocate and setup points + contours arrays */ - if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) || - FT_NEW_ARRAY( glyph->contours, outline->n_contours ) ) + if ( FT_QNEW_ARRAY( glyph->points, outline->n_points ) || + FT_QNEW_ARRAY( glyph->contours, outline->n_contours ) ) goto Exit; glyph->num_points = (FT_UInt)outline->n_points; @@ -1228,8 +1228,9 @@ FT_Pos dxi, dyi, dxo, dyo; + point->flags = 0; if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) ) - point->flags = PSH_POINT_OFF; + psh_point_set_off( point ); dxi = vec[n].x - vec[n_prev].x; dyi = vec[n].y - vec[n_prev].y; @@ -1242,14 +1243,14 @@ point->dir_out = psh_compute_dir( dxo, dyo ); /* detect smooth points */ - if ( point->flags & PSH_POINT_OFF ) - point->flags |= PSH_POINT_SMOOTH; + if ( psh_point_is_off( point ) ) + psh_point_set_smooth( point ); else if ( point->dir_in == point->dir_out ) { if ( point->dir_out != PSH_DIR_NONE || psh_corner_is_flat( dxi, dyi, dxo, dyo ) ) - point->flags |= PSH_POINT_SMOOTH; + psh_point_set_smooth( point ); } } } @@ -1547,8 +1548,9 @@ /* the accepted shift for strong points in fractional pixels */ #define PSH_STRONG_THRESHOLD 32 - /* the maximum shift value in font units */ -#define PSH_STRONG_THRESHOLD_MAXIMUM 30 + /* the maximum shift value in font units tuned to distinguish */ + /* between stems and serifs in URW+ font collection */ +#define PSH_STRONG_THRESHOLD_MAXIMUM 12 /* find strong points in a glyph */ @@ -1797,7 +1799,7 @@ FT_Error error; - if ( FT_NEW_ARRAY( strongs, num_strongs ) ) + if ( FT_QNEW_ARRAY( strongs, num_strongs ) ) return; } @@ -2110,14 +2112,17 @@ FT_Fixed old_x_scale = x_scale; FT_Fixed old_y_scale = y_scale; - FT_Fixed scaled; - FT_Fixed fitted; + FT_Fixed scaled = 0; + FT_Fixed fitted = 0; FT_Bool rescale = FALSE; - scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale ); - fitted = FT_PIX_ROUND( scaled ); + if ( globals->blues.normal_top.count ) + { + scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale ); + fitted = FT_PIX_ROUND( scaled ); + } if ( fitted != 0 && scaled != fitted ) { diff --git a/thirdparty/freetype/src/pshinter/pshalgo.h b/thirdparty/freetype/src/pshinter/pshalgo.h index 999c60192b..ab978bf6d0 100644 --- a/thirdparty/freetype/src/pshinter/pshalgo.h +++ b/thirdparty/freetype/src/pshinter/pshalgo.h @@ -4,7 +4,7 @@ * * PostScript hinting algorithm (specification). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pshinter/pshglob.c b/thirdparty/freetype/src/pshinter/pshglob.c index 2ca0f665c6..887ea8d9c1 100644 --- a/thirdparty/freetype/src/pshinter/pshglob.c +++ b/thirdparty/freetype/src/pshinter/pshglob.c @@ -5,7 +5,7 @@ * PostScript hinter global hinting management (body). * Inspired by the new auto-hinter module. * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used @@ -650,7 +650,7 @@ FT_Error error; - if ( !FT_NEW( globals ) ) + if ( !FT_QNEW( globals ) ) { FT_UInt count; FT_Short* read; diff --git a/thirdparty/freetype/src/pshinter/pshglob.h b/thirdparty/freetype/src/pshinter/pshglob.h index a8f9953fa0..47247f969e 100644 --- a/thirdparty/freetype/src/pshinter/pshglob.h +++ b/thirdparty/freetype/src/pshinter/pshglob.h @@ -4,7 +4,7 @@ * * PostScript hinter global hinting management. * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pshinter/pshinter.c b/thirdparty/freetype/src/pshinter/pshinter.c index 705143dcdc..22315685f9 100644 --- a/thirdparty/freetype/src/pshinter/pshinter.c +++ b/thirdparty/freetype/src/pshinter/pshinter.c @@ -4,7 +4,7 @@ * * FreeType PostScript Hinting module * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pshinter/pshmod.c b/thirdparty/freetype/src/pshinter/pshmod.c index 6674041f7e..a74a4fe99f 100644 --- a/thirdparty/freetype/src/pshinter/pshmod.c +++ b/thirdparty/freetype/src/pshinter/pshmod.c @@ -4,7 +4,7 @@ * * FreeType PostScript hinter module implementation (body). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pshinter/pshmod.h b/thirdparty/freetype/src/pshinter/pshmod.h index 8b229bb077..cdf95b7c20 100644 --- a/thirdparty/freetype/src/pshinter/pshmod.h +++ b/thirdparty/freetype/src/pshinter/pshmod.h @@ -4,7 +4,7 @@ * * PostScript hinter module interface (specification). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pshinter/pshnterr.h b/thirdparty/freetype/src/pshinter/pshnterr.h index 567d765132..789afb5990 100644 --- a/thirdparty/freetype/src/pshinter/pshnterr.h +++ b/thirdparty/freetype/src/pshinter/pshnterr.h @@ -4,7 +4,7 @@ * * PS Hinter error codes (specification only). * - * Copyright (C) 2003-2021 by + * Copyright (C) 2003-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/pshinter/pshrec.c b/thirdparty/freetype/src/pshinter/pshrec.c index 1faabdaafa..2a5cffbada 100644 --- a/thirdparty/freetype/src/pshinter/pshrec.c +++ b/thirdparty/freetype/src/pshinter/pshrec.c @@ -4,7 +4,7 @@ * * FreeType PostScript hints recorder (body). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -63,16 +63,14 @@ { FT_UInt old_max = table->max_hints; FT_UInt new_max = count; - FT_Error error = FT_Err_Ok; + FT_Error error; - if ( new_max > old_max ) - { - /* try to grow the table */ - new_max = FT_PAD_CEIL( new_max, 8 ); - if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) ) - table->max_hints = new_max; - } + /* try to grow the table */ + new_max = FT_PAD_CEIL( new_max, 8 ); + if ( !FT_QRENEW_ARRAY( table->hints, old_max, new_max ) ) + table->max_hints = new_max; + return error; } @@ -90,17 +88,14 @@ count = table->num_hints; count++; - if ( count >= table->max_hints ) + if ( count > table->max_hints ) { error = ps_hint_table_ensure( table, count, memory ); if ( error ) goto Exit; } - hint = table->hints + count - 1; - hint->pos = 0; - hint->len = 0; - hint->flags = 0; + hint = table->hints + count - 1; /* initialized upstream */ table->num_hints = count; @@ -136,14 +131,15 @@ FT_UInt count, FT_Memory memory ) { - FT_UInt old_max = ( mask->max_bits + 7 ) >> 3; - FT_UInt new_max = ( count + 7 ) >> 3; + FT_UInt old_max = mask->max_bits >> 3; + FT_UInt new_max = ( count + 7 ) >> 3; FT_Error error = FT_Err_Ok; if ( new_max > old_max ) { new_max = FT_PAD_CEIL( new_max, 8 ); + /* added bytes are zeroed here */ if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) ) mask->max_bits = new_max * 8; } @@ -154,31 +150,15 @@ /* test a bit value in a given mask */ static FT_Int ps_mask_test_bit( PS_Mask mask, - FT_Int idx ) + FT_UInt idx ) { - if ( (FT_UInt)idx >= mask->num_bits ) + if ( idx >= mask->num_bits ) return 0; return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) ); } - /* clear a given bit */ - static void - ps_mask_clear_bit( PS_Mask mask, - FT_UInt idx ) - { - FT_Byte* p; - - - if ( idx >= mask->num_bits ) - return; - - p = mask->bytes + ( idx >> 3 ); - p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) ); - } - - /* set a given bit, possibly grow the mask */ static FT_Error ps_mask_set_bit( PS_Mask mask, @@ -269,6 +249,10 @@ mask = table->masks + count - 1; mask->num_bits = 0; mask->end_point = 0; + /* reused mask must be cleared */ + if ( mask->max_bits ) + FT_MEM_ZERO( mask->bytes, mask->max_bits >> 3 ); + table->num_masks = count; Exit: @@ -426,7 +410,7 @@ PS_Mask mask2 = table->masks + index2; FT_UInt count1 = mask1->num_bits; FT_UInt count2 = mask2->num_bits; - FT_Int delta; + FT_UInt delta; if ( count2 > 0 ) @@ -437,15 +421,14 @@ /* if "count2" is greater than "count1", we need to grow the */ - /* first bitset, and clear the highest bits */ + /* first bitset */ if ( count2 > count1 ) { error = ps_mask_ensure( mask1, count2, memory ); if ( error ) goto Exit; - for ( pos = count1; pos < count2; pos++ ) - ps_mask_clear_bit( mask1, pos ); + mask1->num_bits = count2; } /* merge (unite) the bitsets */ @@ -467,7 +450,7 @@ mask2->end_point = 0; /* number of masks to move */ - delta = (FT_Int)( table->num_masks - 1 - index2 ); + delta = table->num_masks - 1 - index2; if ( delta > 0 ) { /* move to end of table for reuse */ @@ -476,7 +459,7 @@ ft_memmove( mask2, mask2 + 1, - (FT_UInt)delta * sizeof ( PS_MaskRec ) ); + delta * sizeof ( PS_MaskRec ) ); mask2[delta] = dummy; } @@ -647,7 +630,7 @@ FT_Int pos, FT_Int len, FT_Memory memory, - FT_Int *aindex ) + FT_UInt *aindex ) { FT_Error error = FT_Err_Ok; FT_UInt flags = 0; @@ -665,9 +648,6 @@ len = 0; } - if ( aindex ) - *aindex = -1; - /* now, lookup stem in the current hints table */ { PS_Mask mask; @@ -704,7 +684,7 @@ goto Exit; if ( aindex ) - *aindex = (FT_Int)idx; + *aindex = idx; } Exit: @@ -715,9 +695,9 @@ /* add a "hstem3/vstem3" counter to our dimension table */ static FT_Error ps_dimension_add_counter( PS_Dimension dim, - FT_Int hint1, - FT_Int hint2, - FT_Int hint3, + FT_UInt hint1, + FT_UInt hint2, + FT_UInt hint3, FT_Memory memory ) { FT_Error error = FT_Err_Ok; @@ -744,26 +724,17 @@ } /* now, set the bits for our hints in the counter mask */ - if ( hint1 >= 0 ) - { - error = ps_mask_set_bit( counter, (FT_UInt)hint1, memory ); - if ( error ) - goto Exit; - } + error = ps_mask_set_bit( counter, hint1, memory ); + if ( error ) + goto Exit; - if ( hint2 >= 0 ) - { - error = ps_mask_set_bit( counter, (FT_UInt)hint2, memory ); - if ( error ) - goto Exit; - } + error = ps_mask_set_bit( counter, hint2, memory ); + if ( error ) + goto Exit; - if ( hint3 >= 0 ) - { - error = ps_mask_set_bit( counter, (FT_UInt)hint3, memory ); - if ( error ) - goto Exit; - } + error = ps_mask_set_bit( counter, hint3, memory ); + if ( error ) + goto Exit; Exit: return error; @@ -892,7 +863,7 @@ PS_Dimension dim; FT_Memory memory = hints->memory; FT_Int count; - FT_Int idx[3]; + FT_UInt idx[3]; /* limit "dimension" to 0..1 */ diff --git a/thirdparty/freetype/src/pshinter/pshrec.h b/thirdparty/freetype/src/pshinter/pshrec.h index e483981d9d..a0d37979cc 100644 --- a/thirdparty/freetype/src/pshinter/pshrec.h +++ b/thirdparty/freetype/src/pshinter/pshrec.h @@ -4,7 +4,7 @@ * * Postscript (Type1/Type2) hints recorder (specification). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psnames/psmodule.c b/thirdparty/freetype/src/psnames/psmodule.c index 74adefa15b..e7d51e950e 100644 --- a/thirdparty/freetype/src/psnames/psmodule.c +++ b/thirdparty/freetype/src/psnames/psmodule.c @@ -4,7 +4,7 @@ * * psnames module implementation (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psnames/psmodule.h b/thirdparty/freetype/src/psnames/psmodule.h index e92a975e9d..ff3eda564c 100644 --- a/thirdparty/freetype/src/psnames/psmodule.h +++ b/thirdparty/freetype/src/psnames/psmodule.h @@ -4,7 +4,7 @@ * * High-level psnames module interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psnames/psnamerr.h b/thirdparty/freetype/src/psnames/psnamerr.h index 888b76c4f6..ae56620275 100644 --- a/thirdparty/freetype/src/psnames/psnamerr.h +++ b/thirdparty/freetype/src/psnames/psnamerr.h @@ -4,7 +4,7 @@ * * PS names module error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psnames/psnames.c b/thirdparty/freetype/src/psnames/psnames.c index e7be6707d6..c844a317fd 100644 --- a/thirdparty/freetype/src/psnames/psnames.c +++ b/thirdparty/freetype/src/psnames/psnames.c @@ -4,7 +4,7 @@ * * FreeType psnames module component (body only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psnames/pstables.h b/thirdparty/freetype/src/psnames/pstables.h index 0bcadca9cc..d28d580b9c 100644 --- a/thirdparty/freetype/src/psnames/pstables.h +++ b/thirdparty/freetype/src/psnames/pstables.h @@ -4,7 +4,7 @@ * * PostScript glyph names. * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/psnames/rules.mk b/thirdparty/freetype/src/psnames/rules.mk new file mode 100644 index 0000000000..3768e2f1d8 --- /dev/null +++ b/thirdparty/freetype/src/psnames/rules.mk @@ -0,0 +1,73 @@ +# +# FreeType 2 psnames driver configuration rules +# + + +# Copyright (C) 1996-2022 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# psnames driver directory +# +PSNAMES_DIR := $(SRC_DIR)/psnames + + +# compilation flags for the driver +# +PSNAMES_COMPILE := $(CC) $(ANSIFLAGS) \ + $I$(subst /,$(COMPILER_SEP),$(PSNAMES_DIR)) \ + $(INCLUDE_FLAGS) \ + $(FT_CFLAGS) + + +# psnames driver sources (i.e., C files) +# +PSNAMES_DRV_SRC := $(PSNAMES_DIR)/psmodule.c + + +# psnames driver headers +# +PSNAMES_DRV_H := $(PSNAMES_DRV_SRC:%.c=%.h) \ + $(PSNAMES_DIR)/psnamerr.h \ + $(PSNAMES_DIR)/pstables.h + + +# psnames driver object(s) +# +# PSNAMES_DRV_OBJ_M is used during `multi' builds +# PSNAMES_DRV_OBJ_S is used during `single' builds +# +PSNAMES_DRV_OBJ_M := $(PSNAMES_DRV_SRC:$(PSNAMES_DIR)/%.c=$(OBJ_DIR)/%.$O) +PSNAMES_DRV_OBJ_S := $(OBJ_DIR)/psnames.$O + +# psnames driver source file for single build +# +PSNAMES_DRV_SRC_S := $(PSNAMES_DIR)/psnames.c + + +# psnames driver - single object +# +$(PSNAMES_DRV_OBJ_S): $(PSNAMES_DRV_SRC_S) $(PSNAMES_DRV_SRC) \ + $(FREETYPE_H) $(PSNAMES_DRV_H) + $(PSNAMES_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(PSNAMES_DRV_SRC_S)) + + +# psnames driver - multiple objects +# +$(OBJ_DIR)/%.$O: $(PSNAMES_DIR)/%.c $(FREETYPE_H) $(PSNAMES_DRV_H) + $(PSNAMES_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) + + +# update main driver object lists +# +DRV_OBJS_S += $(PSNAMES_DRV_OBJ_S) +DRV_OBJS_M += $(PSNAMES_DRV_OBJ_M) + + +# EOF diff --git a/thirdparty/freetype/src/raster/ftmisc.h b/thirdparty/freetype/src/raster/ftmisc.h index b12a051234..75fb5f8437 100644 --- a/thirdparty/freetype/src/raster/ftmisc.h +++ b/thirdparty/freetype/src/raster/ftmisc.h @@ -5,7 +5,7 @@ * Miscellaneous macros for stand-alone rasterizer (specification * only). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used diff --git a/thirdparty/freetype/src/raster/ftraster.c b/thirdparty/freetype/src/raster/ftraster.c index bfc059c1e8..68b0e1fdd9 100644 --- a/thirdparty/freetype/src/raster/ftraster.c +++ b/thirdparty/freetype/src/raster/ftraster.c @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -2269,7 +2269,7 @@ /* This is due to the fact that, in the vast majority of cases, */ /* the span length in bytes is relatively small. */ while ( --c2 > 0 ) - *(++target) = 0xFF; + *( ++target ) = 0xFF; target[1] |= f2; } diff --git a/thirdparty/freetype/src/raster/ftraster.h b/thirdparty/freetype/src/raster/ftraster.h index 4affd48b51..e9ece8cf0b 100644 --- a/thirdparty/freetype/src/raster/ftraster.h +++ b/thirdparty/freetype/src/raster/ftraster.h @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used diff --git a/thirdparty/freetype/src/raster/ftrend1.c b/thirdparty/freetype/src/raster/ftrend1.c index 236a8daf0a..f319f03d9c 100644 --- a/thirdparty/freetype/src/raster/ftrend1.c +++ b/thirdparty/freetype/src/raster/ftrend1.c @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer interface (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/raster/ftrend1.h b/thirdparty/freetype/src/raster/ftrend1.h index e4cea53741..14ec336b11 100644 --- a/thirdparty/freetype/src/raster/ftrend1.h +++ b/thirdparty/freetype/src/raster/ftrend1.h @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/raster/module.mk b/thirdparty/freetype/src/raster/module.mk new file mode 100644 index 0000000000..b56a4902ba --- /dev/null +++ b/thirdparty/freetype/src/raster/module.mk @@ -0,0 +1,23 @@ +# +# FreeType 2 renderer module definition +# + + +# Copyright (C) 1996-2022 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +FTMODULE_H_COMMANDS += RASTER_MODULE + +define RASTER_MODULE +$(OPEN_DRIVER) FT_Renderer_Class, ft_raster1_renderer_class $(CLOSE_DRIVER) +$(ECHO_DRIVER)raster $(ECHO_DRIVER_DESC)monochrome bitmap renderer$(ECHO_DRIVER_DONE) +endef + +# EOF diff --git a/thirdparty/freetype/src/raster/raster.c b/thirdparty/freetype/src/raster/raster.c index ad81a39414..324cc5661c 100644 --- a/thirdparty/freetype/src/raster/raster.c +++ b/thirdparty/freetype/src/raster/raster.c @@ -4,7 +4,7 @@ * * FreeType monochrome rasterer module component (body only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/raster/rasterrs.h b/thirdparty/freetype/src/raster/rasterrs.h index 852dd5bc31..8b1ebf07a3 100644 --- a/thirdparty/freetype/src/raster/rasterrs.h +++ b/thirdparty/freetype/src/raster/rasterrs.h @@ -4,7 +4,7 @@ * * monochrome renderer error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sdf/ftbsdf.c b/thirdparty/freetype/src/sdf/ftbsdf.c index 8da5c9d9e0..1328ac4988 100644 --- a/thirdparty/freetype/src/sdf/ftbsdf.c +++ b/thirdparty/freetype/src/sdf/ftbsdf.c @@ -4,7 +4,7 @@ * * Signed Distance Field support for bitmap fonts (body only). * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by Anuj Verma. @@ -177,11 +177,11 @@ * * @Fields: * dist :: - * Vector length of the `near` parameter. Can be squared or absolute + * Vector length of the `prox` parameter. Can be squared or absolute * depending on the `USE_SQUARED_DISTANCES` macro defined in file * `ftsdfcommon.h`. * - * near :: + * prox :: * Vector to the nearest edge. Can also be interpreted as shortest * distance of a point. * @@ -194,7 +194,7 @@ typedef struct ED_ { FT_16D16 dist; - FT_16D16_Vec near; + FT_16D16_Vec prox; FT_Byte alpha; } ED; @@ -595,18 +595,18 @@ worker->rows ) ) { /* approximate the edge distance for edge pixels */ - ed[index].near = compute_edge_distance( ed + index, + ed[index].prox = compute_edge_distance( ed + index, i, j, worker->width, worker->rows ); - ed[index].dist = VECTOR_LENGTH_16D16( ed[index].near ); + ed[index].dist = VECTOR_LENGTH_16D16( ed[index].prox ); } else { /* for non-edge pixels assign far away distances */ ed[index].dist = 400 * ONE; - ed[index].near.x = 200 * ONE; - ed[index].near.y = 200 * ONE; + ed[index].prox.x = 200 * ONE; + ed[index].prox.y = 200 * ONE; } } } @@ -756,8 +756,6 @@ byte = (FT_Byte)( 1 << mod ); t[t_index].alpha = pixel & byte ? 255 : 0; - - pixel = 0; } } } @@ -873,7 +871,7 @@ if ( dist < current->dist ) { - dist_vec = to_check->near; + dist_vec = to_check->prox; dist_vec.x += x_offset * ONE; dist_vec.y += y_offset * ONE; @@ -882,7 +880,7 @@ if ( dist < current->dist ) { current->dist = dist; - current->near = dist_vec; + current->prox = dist_vec; } } } @@ -1098,7 +1096,7 @@ FT_Int i, j; FT_SDFFormat* t_buffer; - FT_16D16 spread; + FT_16D16 sp_sq, spread; if ( !worker || !target ) @@ -1118,11 +1116,13 @@ goto Exit; } + spread = FT_INT_16D16( worker->params.spread ); + #if USE_SQUARED_DISTANCES - spread = FT_INT_16D16( worker->params.spread * - worker->params.spread ); + sp_sq = FT_INT_16D16( worker->params.spread * + worker->params.spread ); #else - spread = FT_INT_16D16( worker->params.spread ); + sp_sq = FT_INT_16D16( worker->params.spread ); #endif for ( j = 0; j < r; j++ ) @@ -1138,8 +1138,8 @@ index = j * w + i; dist = worker->distance_map[index].dist; - if ( dist < 0 || dist > spread ) - dist = spread; + if ( dist < 0 || dist > sp_sq ) + dist = sp_sq; #if USE_SQUARED_DISTANCES dist = square_root( dist ); diff --git a/thirdparty/freetype/src/sdf/ftsdf.c b/thirdparty/freetype/src/sdf/ftsdf.c index f69cf49b47..ffac8bf465 100644 --- a/thirdparty/freetype/src/sdf/ftsdf.c +++ b/thirdparty/freetype/src/sdf/ftsdf.c @@ -4,7 +4,7 @@ * * Signed Distance Field support for outline fonts (body). * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by Anuj Verma. @@ -497,7 +497,7 @@ goto Exit; } - if ( !FT_QALLOC( ptr, sizeof ( *ptr ) ) ) + if ( !FT_QNEW( ptr ) ) { *ptr = null_edge; *edge = ptr; @@ -536,7 +536,7 @@ goto Exit; } - if ( !FT_QALLOC( ptr, sizeof ( *ptr ) ) ) + if ( !FT_QNEW( ptr ) ) { *ptr = null_contour; *contour = ptr; @@ -591,7 +591,7 @@ goto Exit; } - if ( !FT_QALLOC( ptr, sizeof ( *ptr ) ) ) + if ( !FT_QNEW( ptr ) ) { *ptr = null_shape; ptr->memory = memory; @@ -738,6 +738,18 @@ contour = shape->contours; + /* If the control point coincides with any of the end points */ + /* then it is a line and should be treated as one to avoid */ + /* unnecessary complexity later in the algorithm. */ + if ( ( contour->last_pos.x == control_1->x && + contour->last_pos.y == control_1->y ) || + ( control_1->x == to->x && + control_1->y == to->y ) ) + { + sdf_line_to( to, user ); + goto Exit; + } + FT_CALL( sdf_edge_new( memory, &edge ) ); edge->edge_type = SDF_EDGE_CONIC; @@ -764,9 +776,9 @@ const FT_26D6_Vec* to, void* user ) { - SDF_Shape* shape = ( SDF_Shape* )user; - SDF_Edge* edge = NULL; - SDF_Contour* contour = NULL; + SDF_Shape* shape = ( SDF_Shape* )user; + SDF_Edge* edge = NULL; + SDF_Contour* contour = NULL; FT_Error error = FT_Err_Ok; FT_Memory memory = shape->memory; @@ -1065,7 +1077,7 @@ static FT_Error split_sdf_conic( FT_Memory memory, FT_26D6_Vec* control_points, - FT_Int max_splits, + FT_UInt max_splits, SDF_Edge** out ) { FT_Error error = FT_Err_Ok; @@ -1134,26 +1146,41 @@ static FT_Error split_sdf_cubic( FT_Memory memory, FT_26D6_Vec* control_points, - FT_Int max_splits, + FT_UInt max_splits, SDF_Edge** out ) { - FT_Error error = FT_Err_Ok; - FT_26D6_Vec cpos[7]; - SDF_Edge* left,* right; + FT_Error error = FT_Err_Ok; + FT_26D6_Vec cpos[7]; + SDF_Edge* left, *right; + const FT_26D6 threshold = ONE_PIXEL / 4; - if ( !memory || !out ) + if ( !memory || !out ) { error = FT_THROW( Invalid_Argument ); goto Exit; } - /* split the conic */ + /* split the cubic */ cpos[0] = control_points[0]; cpos[1] = control_points[1]; cpos[2] = control_points[2]; cpos[3] = control_points[3]; + /* If the segment is flat enough we won't get any benefit by */ + /* splitting it further, so we can just stop splitting. */ + /* */ + /* Check the deviation of the Bezier curve and stop if it is */ + /* smaller than the pre-defined `threshold` value. */ + if ( FT_ABS( 2 * cpos[0].x - 3 * cpos[1].x + cpos[3].x ) < threshold && + FT_ABS( 2 * cpos[0].y - 3 * cpos[1].y + cpos[3].y ) < threshold && + FT_ABS( cpos[0].x - 3 * cpos[2].x + 2 * cpos[3].x ) < threshold && + FT_ABS( cpos[0].y - 3 * cpos[2].y + 2 * cpos[3].y ) < threshold ) + { + split_cubic( cpos ); + goto Append; + } + split_cubic( cpos ); /* If max number of splits is done */ @@ -1250,13 +1277,32 @@ /* Subdivide the curve and add it to the list. */ { FT_26D6_Vec ctrls[3]; + FT_26D6 dx, dy; + FT_UInt num_splits; ctrls[0] = edge->start_pos; ctrls[1] = edge->control_a; ctrls[2] = edge->end_pos; - error = split_sdf_conic( memory, ctrls, 32, &new_edges ); + dx = FT_ABS( ctrls[2].x + ctrls[0].x - 2 * ctrls[1].x ); + dy = FT_ABS( ctrls[2].y + ctrls[0].y - 2 * ctrls[1].y ); + if ( dx < dy ) + dx = dy; + + /* Calculate the number of necessary bisections. Each */ + /* bisection causes a four-fold reduction of the deviation, */ + /* hence we bisect the Bezier curve until the deviation */ + /* becomes less than 1/8th of a pixel. For more details */ + /* check file `ftgrays.c`. */ + num_splits = 1; + while ( dx > ONE_PIXEL / 8 ) + { + dx >>= 2; + num_splits <<= 1; + } + + error = split_sdf_conic( memory, ctrls, num_splits, &new_edges ); } break; @@ -1277,9 +1323,11 @@ default: error = FT_THROW( Invalid_Argument ); - goto Exit; } + if ( error != FT_Err_Ok ) + goto Exit; + edges = edges->next; } @@ -2966,7 +3014,7 @@ diff = current_dist.distance - min_dist.distance; - if ( FT_ABS(diff ) < CORNER_CHECK_EPSILON ) + if ( FT_ABS( diff ) < CORNER_CHECK_EPSILON ) min_dist = resolve_corner( min_dist, current_dist ); else if ( diff < 0 ) min_dist = current_dist; @@ -3240,7 +3288,7 @@ buffer = (FT_SDFFormat*)bitmap->buffer; if ( USE_SQUARED_DISTANCES ) - sp_sq = fixed_spread * fixed_spread; + sp_sq = FT_INT_16D16( (FT_Int)( spread * spread ) ); else sp_sq = fixed_spread; @@ -3284,6 +3332,7 @@ FT_26D6_Vec grid_point = zero_vector; SDF_Signed_Distance dist = max_sdf; FT_UInt index = 0; + FT_16D16 diff = 0; if ( x < 0 || x >= width ) @@ -3311,7 +3360,7 @@ if ( dist.distance > sp_sq ) continue; - /* square_root the values and fit in a 6.10 fixed-point */ + /* take the square root of the distance if required */ if ( USE_SQUARED_DISTANCES ) dist.distance = square_root( dist.distance ); @@ -3323,11 +3372,15 @@ /* check whether the pixel is set or not */ if ( dists[index].sign == 0 ) dists[index] = dist; - else if ( dists[index].distance > dist.distance ) - dists[index] = dist; - else if ( FT_ABS( dists[index].distance - dist.distance ) - < CORNER_CHECK_EPSILON ) - dists[index] = resolve_corner( dists[index], dist ); + else + { + diff = FT_ABS( dists[index].distance - dist.distance ); + + if ( diff <= CORNER_CHECK_EPSILON ) + dists[index] = resolve_corner( dists[index], dist ); + else if ( dists[index].distance > dist.distance ) + dists[index] = dist; + } } } diff --git a/thirdparty/freetype/src/sdf/ftsdf.h b/thirdparty/freetype/src/sdf/ftsdf.h index 187b418af3..5f6b3f52aa 100644 --- a/thirdparty/freetype/src/sdf/ftsdf.h +++ b/thirdparty/freetype/src/sdf/ftsdf.h @@ -4,7 +4,7 @@ * * Signed Distance Field support (specification). * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by Anuj Verma. diff --git a/thirdparty/freetype/src/sdf/ftsdfcommon.c b/thirdparty/freetype/src/sdf/ftsdfcommon.c index 91aa521bb3..072a36ea6c 100644 --- a/thirdparty/freetype/src/sdf/ftsdfcommon.c +++ b/thirdparty/freetype/src/sdf/ftsdfcommon.c @@ -4,7 +4,7 @@ * * Auxiliary data for Signed Distance Field support (body). * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by Anuj Verma. diff --git a/thirdparty/freetype/src/sdf/ftsdfcommon.h b/thirdparty/freetype/src/sdf/ftsdfcommon.h index 44f6bba53f..af4490bbca 100644 --- a/thirdparty/freetype/src/sdf/ftsdfcommon.h +++ b/thirdparty/freetype/src/sdf/ftsdfcommon.h @@ -4,7 +4,7 @@ * * Auxiliary data for Signed Distance Field support (specification). * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by Anuj Verma. @@ -48,6 +48,8 @@ FT_BEGIN_HEADER #define MIN_SPREAD 2 /* maximum spread supported by the renderer */ #define MAX_SPREAD 32 + /* pixel size in 26.6 */ +#define ONE_PIXEL ( 1 << 6 ) /************************************************************************** diff --git a/thirdparty/freetype/src/sdf/ftsdferrs.h b/thirdparty/freetype/src/sdf/ftsdferrs.h index dbb113d537..b28867609a 100644 --- a/thirdparty/freetype/src/sdf/ftsdferrs.h +++ b/thirdparty/freetype/src/sdf/ftsdferrs.h @@ -4,7 +4,7 @@ * * Signed Distance Field error codes (specification only). * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by Anuj Verma. diff --git a/thirdparty/freetype/src/sdf/ftsdfrend.c b/thirdparty/freetype/src/sdf/ftsdfrend.c index 30f2e62a4f..b0213a40d3 100644 --- a/thirdparty/freetype/src/sdf/ftsdfrend.c +++ b/thirdparty/freetype/src/sdf/ftsdfrend.c @@ -4,7 +4,7 @@ * * Signed Distance Field renderer interface (body). * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by Anuj Verma. @@ -298,15 +298,9 @@ goto Exit; } - /* the rows and pitch must be valid after presetting the */ - /* bitmap using outline */ + /* nothing to render */ if ( !bitmap->rows || !bitmap->pitch ) - { - FT_ERROR(( "ft_sdf_render: failed to preset bitmap\n" )); - - error = FT_THROW( Cannot_Render_Glyph ); - goto Exit; - } + return FT_Err_Ok; /* the padding will simply be equal to the `spread' */ x_pad = sdf_module->spread; @@ -525,13 +519,9 @@ goto Exit; } + /* nothing to render */ if ( !bitmap->rows || !bitmap->pitch ) - { - FT_ERROR(( "ft_bsdf_render: invalid bitmap size\n" )); - - error = FT_THROW( Invalid_Argument ); - goto Exit; - } + return FT_Err_Ok; FT_Bitmap_New( &target ); diff --git a/thirdparty/freetype/src/sdf/ftsdfrend.h b/thirdparty/freetype/src/sdf/ftsdfrend.h index bc88707ec2..cdb9c5f02f 100644 --- a/thirdparty/freetype/src/sdf/ftsdfrend.h +++ b/thirdparty/freetype/src/sdf/ftsdfrend.h @@ -4,7 +4,7 @@ * * Signed Distance Field renderer interface (specification). * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by Anuj Verma. diff --git a/thirdparty/freetype/src/sdf/sdf.c b/thirdparty/freetype/src/sdf/sdf.c index 1bc3fc385c..297ba9ab02 100644 --- a/thirdparty/freetype/src/sdf/sdf.c +++ b/thirdparty/freetype/src/sdf/sdf.c @@ -4,7 +4,7 @@ * * FreeType Signed Distance Field renderer module component (body only). * - * Copyright (C) 2020-2021 by + * Copyright (C) 2020-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by Anuj Verma. diff --git a/thirdparty/freetype/src/sfnt/pngshim.c b/thirdparty/freetype/src/sfnt/pngshim.c index 02fe37440c..0ce4bdb6b5 100644 --- a/thirdparty/freetype/src/sfnt/pngshim.c +++ b/thirdparty/freetype/src/sfnt/pngshim.c @@ -4,7 +4,7 @@ * * PNG Bitmap glyph support. * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * Google, Inc. * Written by Stuart Gill and Behdad Esfahbod. * @@ -367,7 +367,7 @@ } /* transform transparency to alpha */ - if ( png_get_valid(png, info, PNG_INFO_tRNS ) ) + if ( png_get_valid( png, info, PNG_INFO_tRNS ) ) png_set_tRNS_to_alpha( png ); if ( bitdepth == 16 ) @@ -387,7 +387,7 @@ png_set_filler( png, 0xFF, PNG_FILLER_AFTER ); /* recheck header after setting EXPAND options */ - png_read_update_info(png, info ); + png_read_update_info( png, info ); png_get_IHDR( png, info, &imgWidth, &imgHeight, &bitdepth, &color_type, &interlace, diff --git a/thirdparty/freetype/src/sfnt/pngshim.h b/thirdparty/freetype/src/sfnt/pngshim.h index 89efd27545..36d749c3c3 100644 --- a/thirdparty/freetype/src/sfnt/pngshim.h +++ b/thirdparty/freetype/src/sfnt/pngshim.h @@ -4,7 +4,7 @@ * * PNG Bitmap glyph support. * - * Copyright (C) 2013-2021 by + * Copyright (C) 2013-2022 by * Google, Inc. * Written by Stuart Gill and Behdad Esfahbod. * diff --git a/thirdparty/freetype/src/sfnt/sfdriver.c b/thirdparty/freetype/src/sfnt/sfdriver.c index d1d01c99e5..cc121e5790 100644 --- a/thirdparty/freetype/src/sfnt/sfdriver.c +++ b/thirdparty/freetype/src/sfnt/sfdriver.c @@ -4,7 +4,7 @@ * * High-level SFNT driver interface (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -36,6 +36,10 @@ #include "ttcpal.h" #endif +#ifdef FT_CONFIG_OPTION_SVG +#include "ttsvg.h" +#endif + #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES #include "ttpost.h" #endif @@ -491,15 +495,13 @@ char_type_func char_type, FT_Bool report_invalid_characters ) { - FT_Error error = FT_Err_Ok; + FT_Error error; char* result = NULL; FT_String* r; FT_Char* p; FT_UInt len; - FT_UNUSED( error ); - if ( FT_QALLOC( result, entry->stringLength / 2 + 1 ) ) return NULL; @@ -550,15 +552,13 @@ char_type_func char_type, FT_Bool report_invalid_characters ) { - FT_Error error = FT_Err_Ok; + FT_Error error; char* result = NULL; FT_String* r; FT_Char* p; FT_UInt len; - FT_UNUSED( error ); - if ( FT_QALLOC( result, entry->stringLength + 1 ) ) return NULL; @@ -1214,6 +1214,12 @@ #define PUT_COLOR_LAYERS( a ) NULL #endif +#ifdef FT_CONFIG_OPTION_SVG +#define PUT_SVG_SUPPORT( a ) a +#else +#define PUT_SVG_SUPPORT( a ) NULL +#endif + #define PUT_COLOR_LAYERS_V1( a ) PUT_COLOR_LAYERS( a ) #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES @@ -1308,7 +1314,14 @@ tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */ tt_face_get_name, /* TT_Get_Name_Func get_name */ - sfnt_get_name_id /* TT_Get_Name_ID_Func get_name_id */ + sfnt_get_name_id, /* TT_Get_Name_ID_Func get_name_id */ + + PUT_SVG_SUPPORT( tt_face_load_svg ), + /* TT_Load_Table_Func load_svg */ + PUT_SVG_SUPPORT( tt_face_free_svg ), + /* TT_Free_Table_Func free_svg */ + PUT_SVG_SUPPORT( tt_face_load_svg_doc ) + /* TT_Load_Svg_Doc_Func load_svg_doc */ ) diff --git a/thirdparty/freetype/src/sfnt/sfdriver.h b/thirdparty/freetype/src/sfnt/sfdriver.h index 8d5b5ce367..6a2e3e9c7b 100644 --- a/thirdparty/freetype/src/sfnt/sfdriver.h +++ b/thirdparty/freetype/src/sfnt/sfdriver.h @@ -4,7 +4,7 @@ * * High-level SFNT driver interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/sferrors.h b/thirdparty/freetype/src/sfnt/sferrors.h index 78e6f03513..99ef3f9fce 100644 --- a/thirdparty/freetype/src/sfnt/sferrors.h +++ b/thirdparty/freetype/src/sfnt/sferrors.h @@ -4,7 +4,7 @@ * * SFNT error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/sfnt.c b/thirdparty/freetype/src/sfnt/sfnt.c index 97692cdfb0..9b3ceaedc0 100644 --- a/thirdparty/freetype/src/sfnt/sfnt.c +++ b/thirdparty/freetype/src/sfnt/sfnt.c @@ -4,7 +4,7 @@ * * Single object library component. * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -27,6 +27,7 @@ #include "ttcmap.c" #include "ttcolr.c" #include "ttcpal.c" +#include "ttsvg.c" #include "ttkern.c" #include "ttload.c" diff --git a/thirdparty/freetype/src/sfnt/sfobjs.c b/thirdparty/freetype/src/sfnt/sfobjs.c index 7891024790..a0da984e7a 100644 --- a/thirdparty/freetype/src/sfnt/sfobjs.c +++ b/thirdparty/freetype/src/sfnt/sfobjs.c @@ -4,7 +4,7 @@ * * SFNT object management (base). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -566,7 +566,7 @@ face_index = FT_ABS( face_instance_index ) & 0xFFFF; /* value -(N+1) requests information on index N */ - if ( face_instance_index < 0 ) + if ( face_instance_index < 0 && face_index > 0 ) face_index--; if ( face_index >= face->ttc_header.count ) @@ -784,17 +784,23 @@ FT_Int num_params, FT_Parameter* params ) { - FT_Error error; + FT_Error error; #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES - FT_Error psnames_error; + FT_Error psnames_error; #endif - FT_Bool has_outline; - FT_Bool is_apple_sbit; - FT_Bool is_apple_sbix; - FT_Bool has_CBLC; - FT_Bool has_CBDT; - FT_Bool ignore_typographic_family = FALSE; - FT_Bool ignore_typographic_subfamily = FALSE; + + FT_Bool has_outline; + FT_Bool is_apple_sbit; + + FT_Bool has_CBLC; + FT_Bool has_CBDT; + FT_Bool has_EBLC; + FT_Bool has_bloc; + FT_Bool has_sbix; + + FT_Bool ignore_typographic_family = FALSE; + FT_Bool ignore_typographic_subfamily = FALSE; + FT_Bool ignore_sbix = FALSE; SFNT_Service sfnt = (SFNT_Service)face->sfnt; @@ -813,6 +819,8 @@ ignore_typographic_family = TRUE; else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY ) ignore_typographic_subfamily = TRUE; + else if ( params[i].tag == FT_PARAM_TAG_IGNORE_SBIX ) + ignore_sbix = TRUE; } } @@ -848,14 +856,17 @@ tt_face_lookup_table( face, TTAG_CFF2 ) ); #endif - is_apple_sbit = 0; - is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); + /* check which sbit formats are present */ + has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 ); + has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 ); + has_EBLC = !face->goto_table( face, TTAG_EBLC, stream, 0 ); + has_bloc = !face->goto_table( face, TTAG_bloc, stream, 0 ); + has_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); - /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf' - * outline rendered on top. We don't support that yet, so just ignore - * the 'glyf' outline and advertise it as a bitmap-only font. */ - if ( is_apple_sbix ) - has_outline = FALSE; + is_apple_sbit = FALSE; + + if ( ignore_sbix ) + has_sbix = FALSE; /* if this font doesn't contain outlines, we try to load */ /* a `bhed' table */ @@ -867,16 +878,13 @@ /* load the font header (`head' table) if this isn't an Apple */ /* sbit font file */ - if ( !is_apple_sbit || is_apple_sbix ) + if ( !is_apple_sbit || has_sbix ) { LOAD_( head ); if ( error ) goto Exit; } - has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 ); - has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 ); - /* Ignore outlines for CBLC/CBDT fonts. */ if ( has_CBLC || has_CBDT ) has_outline = FALSE; @@ -986,7 +994,11 @@ /* the optional tables */ /* embedded bitmap support */ - if ( sfnt->load_eblc ) + /* TODO: Replace this clumsy check for all possible sbit tables */ + /* with something better (for example, by passing a parameter */ + /* to suppress 'sbix' loading). */ + if ( sfnt->load_eblc && + ( has_CBLC || has_EBLC || has_bloc || has_sbix ) ) LOAD_( eblc ); /* colored glyph support */ @@ -996,6 +1008,10 @@ LOAD_( colr ); } + /* OpenType-SVG glyph support */ + if ( sfnt->load_svg ) + LOAD_( svg ); + /* consider the pclt, kerning, and gasp tables as optional */ LOAD_( pclt ); LOAD_( gasp ); @@ -1050,11 +1066,19 @@ */ if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX || - face->colr ) + face->colr || + face->svg ) flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ if ( has_outline == TRUE ) - flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ + { + /* by default (and for backward compatibility) we handle */ + /* fonts with an 'sbix' table as bitmap-only */ + if ( has_sbix ) + flags |= FT_FACE_FLAG_SBIX; /* with 'sbix' bitmaps */ + else + flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ + } /* The sfnt driver only supports bitmap fonts natively, thus we */ /* don't set FT_FACE_FLAG_HINTER. */ @@ -1277,7 +1301,8 @@ * * Set up metrics. */ - if ( FT_IS_SCALABLE( root ) ) + if ( FT_IS_SCALABLE( root ) || + FT_HAS_SBIX( root ) ) { /* XXX What about if outline header is missing */ /* (e.g. sfnt wrapped bitmap)? */ @@ -1416,6 +1441,12 @@ sfnt->free_cpal( face ); sfnt->free_colr( face ); } + +#ifdef FT_CONFIG_OPTION_SVG + /* free SVG data */ + if ( sfnt->free_svg ) + sfnt->free_svg( face ); +#endif } #ifdef TT_CONFIG_OPTION_BDF diff --git a/thirdparty/freetype/src/sfnt/sfobjs.h b/thirdparty/freetype/src/sfnt/sfobjs.h index 172c47ebb4..1d99bfede4 100644 --- a/thirdparty/freetype/src/sfnt/sfobjs.h +++ b/thirdparty/freetype/src/sfnt/sfobjs.h @@ -4,7 +4,7 @@ * * SFNT object management (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/sfwoff.c b/thirdparty/freetype/src/sfnt/sfwoff.c index 422c816a21..0e8ec3fa93 100644 --- a/thirdparty/freetype/src/sfnt/sfwoff.c +++ b/thirdparty/freetype/src/sfnt/sfwoff.c @@ -4,7 +4,7 @@ * * WOFF format management (base). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -64,7 +64,6 @@ FT_FREE( stream->base ); stream->size = 0; - stream->base = NULL; stream->close = NULL; } diff --git a/thirdparty/freetype/src/sfnt/sfwoff.h b/thirdparty/freetype/src/sfnt/sfwoff.h index 3fbdac0fde..5866a16194 100644 --- a/thirdparty/freetype/src/sfnt/sfwoff.h +++ b/thirdparty/freetype/src/sfnt/sfwoff.h @@ -4,7 +4,7 @@ * * WOFFF format management (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/sfwoff2.c b/thirdparty/freetype/src/sfnt/sfwoff2.c index 5ee8dea28a..b2855b8e72 100644 --- a/thirdparty/freetype/src/sfnt/sfwoff2.c +++ b/thirdparty/freetype/src/sfnt/sfwoff2.c @@ -4,7 +4,7 @@ * * WOFF2 format management (base). * - * Copyright (C) 2019-2021 by + * Copyright (C) 2019-2022 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -84,6 +84,8 @@ #define BBOX_STREAM 5 #define INSTRUCTION_STREAM 6 +#define HAVE_OVERLAP_SIMPLE_BITMAP 0x1 + static void stream_close( FT_Stream stream ) @@ -94,7 +96,6 @@ FT_FREE( stream->base ); stream->size = 0; - stream->base = NULL; stream->close = NULL; } @@ -523,6 +524,7 @@ const WOFF2_Point points, FT_UShort n_contours, FT_UShort instruction_len, + FT_Bool have_overlap, FT_Byte* dst, FT_ULong dst_size, FT_ULong* glyph_size ) @@ -550,6 +552,9 @@ FT_Int dy = point.y - last_y; + if ( i == 0 && have_overlap ) + flag |= GLYF_OVERLAP_SIMPLE; + if ( dx == 0 ) flag |= GLYF_THIS_X_IS_SAME; else if ( dx > -256 && dx < 256 ) @@ -834,15 +839,18 @@ FT_UInt num_substreams = 7; + FT_UShort option_flags; FT_UShort num_glyphs; FT_UShort index_format; FT_ULong expected_loca_length; FT_UInt offset; FT_UInt i; FT_ULong points_size; - FT_ULong bitmap_length; FT_ULong glyph_buf_size; FT_ULong bbox_bitmap_offset; + FT_ULong bbox_bitmap_length; + FT_ULong overlap_bitmap_offset = 0; + FT_ULong overlap_bitmap_length = 0; const FT_ULong glyf_start = *out_offset; FT_ULong dest_offset = *out_offset; @@ -858,15 +866,17 @@ if ( FT_NEW_ARRAY( substreams, num_substreams ) ) goto Fail; - if ( FT_STREAM_SKIP( 4 ) ) + if ( FT_STREAM_SKIP( 2 ) ) + goto Fail; + if ( FT_READ_USHORT( option_flags ) ) goto Fail; if ( FT_READ_USHORT( num_glyphs ) ) goto Fail; if ( FT_READ_USHORT( index_format ) ) goto Fail; - FT_TRACE4(( "num_glyphs = %u; index_format = %u\n", - num_glyphs, index_format )); + FT_TRACE4(( "option_flags = %u; num_glyphs = %u; index_format = %u\n", + option_flags, num_glyphs, index_format )); info->num_glyphs = num_glyphs; @@ -879,7 +889,7 @@ if ( info->loca_table->dst_length != expected_loca_length ) goto Fail; - offset = ( 2 + num_substreams ) * 4; + offset = 2 + 2 + 2 + 2 + ( num_substreams * 4 ); if ( offset > info->glyf_table->TransformLength ) goto Fail; @@ -902,6 +912,20 @@ offset += substream_size; } + if ( option_flags & HAVE_OVERLAP_SIMPLE_BITMAP ) + { + /* Size of overlapBitmap = floor((numGlyphs + 7) / 8) */ + overlap_bitmap_length = ( num_glyphs + 7U ) >> 3; + if ( overlap_bitmap_length > info->glyf_table->TransformLength - offset ) + goto Fail; + + overlap_bitmap_offset = pos + offset; + + FT_TRACE5(( " Overlap bitmap: offset = %lu; size = %lu;\n", + overlap_bitmap_offset, overlap_bitmap_length )); + offset += overlap_bitmap_length; + } + if ( FT_NEW_ARRAY( loca_values, num_glyphs + 1 ) ) goto Fail; @@ -909,8 +933,9 @@ bbox_bitmap_offset = substreams[BBOX_STREAM].offset; /* Size of bboxBitmap = 4 * floor((numGlyphs + 31) / 32) */ - bitmap_length = ( ( num_glyphs + 31U ) >> 5 ) << 2; - substreams[BBOX_STREAM].offset += bitmap_length; + bbox_bitmap_length = ( ( num_glyphs + 31U ) >> 5 ) << 2; + /* bboxStreamSize is the combined size of bboxBitmap and bboxStream. */ + substreams[BBOX_STREAM].offset += bbox_bitmap_length; glyph_buf_size = WOFF2_DEFAULT_GLYPH_BUF; if ( FT_NEW_ARRAY( glyph_buf, glyph_buf_size ) ) @@ -948,7 +973,7 @@ /* composite glyph */ FT_Bool have_instructions = FALSE; FT_UShort instruction_size = 0; - FT_ULong composite_size; + FT_ULong composite_size = 0; FT_ULong size_needed; FT_Byte* pointer = NULL; @@ -1026,8 +1051,11 @@ FT_ULong flag_size; FT_ULong triplet_size; FT_ULong triplet_bytes_used; - FT_Byte* flags_buf = NULL; - FT_Byte* triplet_buf = NULL; + FT_Bool have_overlap = FALSE; + FT_Byte overlap_bitmap; + FT_ULong overlap_offset; + FT_Byte* flags_buf = NULL; + FT_Byte* triplet_buf = NULL; FT_UShort instruction_size; FT_ULong size_needed; FT_Int end_point; @@ -1036,6 +1064,17 @@ FT_Byte* pointer = NULL; + /* Set `have_overlap`. */ + if ( overlap_bitmap_offset ) + { + overlap_offset = overlap_bitmap_offset + ( i >> 3 ); + if ( FT_STREAM_SEEK( overlap_offset ) || + FT_READ_BYTE( overlap_bitmap ) ) + goto Fail; + if ( overlap_bitmap & ( 0x80 >> ( i & 7 ) ) ) + have_overlap = TRUE; + } + if ( FT_NEW_ARRAY( n_points_arr, n_contours ) ) goto Fail; @@ -1156,6 +1195,7 @@ points, n_contours, instruction_size, + have_overlap, glyph_buf, glyph_buf_size, &glyph_size ) ) @@ -2064,7 +2104,7 @@ error = FT_THROW( Invalid_Table ); goto Exit; } - file_offset = ROUND4(woff2.metaOffset + woff2.metaLength); + file_offset = ROUND4( woff2.metaOffset + woff2.metaLength ); } if ( woff2.privOffset ) @@ -2074,7 +2114,7 @@ error = FT_THROW( Invalid_Table ); goto Exit; } - file_offset = ROUND4(woff2.privOffset + woff2.privLength); + file_offset = ROUND4( woff2.privOffset + woff2.privLength ); } if ( file_offset != ( ROUND4( woff2.length ) ) ) @@ -2086,7 +2126,7 @@ /* Validate requested face index. */ *num_faces = woff2.num_fonts; /* value -(N+1) requests information on index N */ - if ( *face_instance_index < 0 ) + if ( *face_instance_index < 0 && face_index > 0 ) face_index--; if ( face_index >= woff2.num_fonts ) diff --git a/thirdparty/freetype/src/sfnt/sfwoff2.h b/thirdparty/freetype/src/sfnt/sfwoff2.h index fa78b02429..e84982ed9c 100644 --- a/thirdparty/freetype/src/sfnt/sfwoff2.h +++ b/thirdparty/freetype/src/sfnt/sfwoff2.h @@ -4,7 +4,7 @@ * * WOFFF2 format management (specification). * - * Copyright (C) 2019-2021 by + * Copyright (C) 2019-2022 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -56,6 +56,7 @@ FT_BEGIN_HEADER #define GLYF_REPEAT 1 << 3 #define GLYF_THIS_X_IS_SAME 1 << 4 #define GLYF_THIS_Y_IS_SAME 1 << 5 +#define GLYF_OVERLAP_SIMPLE 1 << 6 /* Other constants */ #define CONTOUR_OFFSET_END_POINT 10 diff --git a/thirdparty/freetype/src/sfnt/ttbdf.c b/thirdparty/freetype/src/sfnt/ttbdf.c index b8d9473a63..4d2faf2385 100644 --- a/thirdparty/freetype/src/sfnt/ttbdf.c +++ b/thirdparty/freetype/src/sfnt/ttbdf.c @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded BDF properties (body). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttbdf.h b/thirdparty/freetype/src/sfnt/ttbdf.h index 91271d916f..b7b11c9bec 100644 --- a/thirdparty/freetype/src/sfnt/ttbdf.h +++ b/thirdparty/freetype/src/sfnt/ttbdf.h @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded BDF properties (specification). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttcmap.c b/thirdparty/freetype/src/sfnt/ttcmap.c index b369d83788..bfeabacb7d 100644 --- a/thirdparty/freetype/src/sfnt/ttcmap.c +++ b/thirdparty/freetype/src/sfnt/ttcmap.c @@ -4,7 +4,7 @@ * * TrueType character mapping table (cmap) support (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -465,7 +465,7 @@ if ( subheader ) { FT_Byte* p = subheader; - FT_UInt idx = (FT_UInt)(char_code & 0xFF); + FT_UInt idx = (FT_UInt)( char_code & 0xFF ); FT_UInt start, count; FT_Int delta; FT_UInt offset; diff --git a/thirdparty/freetype/src/sfnt/ttcmap.h b/thirdparty/freetype/src/sfnt/ttcmap.h index 504fc951c4..b10860b345 100644 --- a/thirdparty/freetype/src/sfnt/ttcmap.h +++ b/thirdparty/freetype/src/sfnt/ttcmap.h @@ -4,7 +4,7 @@ * * TrueType character mapping table (cmap) support (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttcmapc.h b/thirdparty/freetype/src/sfnt/ttcmapc.h index 4e6cd46ba8..6822a9cd6b 100644 --- a/thirdparty/freetype/src/sfnt/ttcmapc.h +++ b/thirdparty/freetype/src/sfnt/ttcmapc.h @@ -4,7 +4,7 @@ * * TT CMAP classes definitions (specification only). * - * Copyright (C) 2009-2021 by + * Copyright (C) 2009-2022 by * Oran Agra and Mickey Gabel. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttcolr.c b/thirdparty/freetype/src/sfnt/ttcolr.c index 8f5cc8bcd1..d54231fd64 100644 --- a/thirdparty/freetype/src/sfnt/ttcolr.c +++ b/thirdparty/freetype/src/sfnt/ttcolr.c @@ -4,7 +4,7 @@ * * TrueType and OpenType colored glyph layer support (body). * - * Copyright (C) 2018-2021 by + * Copyright (C) 2018-2022 by * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. @@ -522,19 +522,29 @@ else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT ) { + FT_Pos tmp; + + if ( !read_color_line( child_table_p, &apaint->u.radial_gradient.colorline ) ) return 0; + /* In the OpenType specification, `r0` and `r1` are defined as */ + /* `UFWORD`. Since FreeType doesn't have a corresponding 16.16 */ + /* format we convert to `FWORD` and replace negative values with */ + /* (32bit) `FT_INT_MAX`. */ + apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); - apaint->u.radial_gradient.r0 = FT_NEXT_USHORT( p ) << 16; + tmp = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.radial_gradient.r0 = tmp < 0 ? FT_INT_MAX : tmp; apaint->u.radial_gradient.c1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.radial_gradient.c1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); - apaint->u.radial_gradient.r1 = FT_NEXT_USHORT( p ) << 16; + tmp = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.radial_gradient.r1 = tmp < 0 ? FT_INT_MAX : tmp; return 1; } @@ -824,7 +834,7 @@ { Colr* colr; - FT_Byte *p, *p1, *clip_base; + FT_Byte *p, *p1, *clip_base, *limit; FT_Byte clip_list_format; FT_ULong num_clip_boxes, i; @@ -847,16 +857,32 @@ p = colr->clip_list; + /* Limit points to the first byte after the end of the color table. */ + /* Thus, in subsequent limit checks below we need to check whether the */ + /* read pointer is strictly greater than a position offset by certain */ + /* field sizes to the left of that position. */ + limit = (FT_Byte*)colr->table + colr->table_size; + + /* Check whether we can extract one `uint8` and one `uint32`. */ + if ( p > limit - ( 1 + 4 ) ) + return 0; + clip_base = p; clip_list_format = FT_NEXT_BYTE ( p ); /* Format byte used here to be able to upgrade ClipList for >16bit */ - /* glyph ids; for now we can expect it to be 0. */ + /* glyph ids; for now we can expect it to be 0. */ if ( !( clip_list_format == 1 ) ) return 0; num_clip_boxes = FT_NEXT_ULONG( p ); + /* Check whether we can extract two `uint16` and one `Offset24`, */ + /* `num_clip_boxes` times. */ + if ( colr->table_size / ( 2 + 2 + 3 ) < num_clip_boxes || + p > limit - ( 2 + 2 + 3 ) * num_clip_boxes ) + return 0; + for ( i = 0; i < num_clip_boxes; ++i ) { gid_start = FT_NEXT_USHORT( p ); @@ -867,7 +893,8 @@ { p1 = (FT_Byte*)( clip_base + clip_box_offset ); - if ( p1 >= ( (FT_Byte*)colr->table + colr->table_size ) ) + /* Check whether we can extract one `uint8`. */ + if ( p1 > limit - 1 ) return 0; format = FT_NEXT_BYTE( p1 ); @@ -875,6 +902,10 @@ if ( format > 1 ) return 0; + /* Check whether we can extract four `FWORD`. */ + if ( p1 > limit - ( 2 + 2 + 2 + 2 ) ) + return 0; + /* `face->root.size->metrics.x_scale` and `y_scale` are factors */ /* that scale a font unit value in integers to a 26.6 fixed value */ /* according to the requested size, see for example */ diff --git a/thirdparty/freetype/src/sfnt/ttcolr.h b/thirdparty/freetype/src/sfnt/ttcolr.h index b81e4cb958..4200cb2976 100644 --- a/thirdparty/freetype/src/sfnt/ttcolr.h +++ b/thirdparty/freetype/src/sfnt/ttcolr.h @@ -4,7 +4,7 @@ * * TrueType and OpenType colored glyph layer support (specification). * - * Copyright (C) 2018-2021 by + * Copyright (C) 2018-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. diff --git a/thirdparty/freetype/src/sfnt/ttcpal.c b/thirdparty/freetype/src/sfnt/ttcpal.c index a0d84bca3a..9ae535cbda 100644 --- a/thirdparty/freetype/src/sfnt/ttcpal.c +++ b/thirdparty/freetype/src/sfnt/ttcpal.c @@ -4,7 +4,7 @@ * * TrueType and OpenType color palette support (body). * - * Copyright (C) 2018-2021 by + * Copyright (C) 2018-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. diff --git a/thirdparty/freetype/src/sfnt/ttcpal.h b/thirdparty/freetype/src/sfnt/ttcpal.h index 1c5586855b..4717d224fc 100644 --- a/thirdparty/freetype/src/sfnt/ttcpal.h +++ b/thirdparty/freetype/src/sfnt/ttcpal.h @@ -4,7 +4,7 @@ * * TrueType and OpenType color palette support (specification). * - * Copyright (C) 2018-2021 by + * Copyright (C) 2018-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang <shaozhang@fb.com>. diff --git a/thirdparty/freetype/src/sfnt/ttkern.c b/thirdparty/freetype/src/sfnt/ttkern.c index bb1922caf9..ca1c509406 100644 --- a/thirdparty/freetype/src/sfnt/ttkern.c +++ b/thirdparty/freetype/src/sfnt/ttkern.c @@ -5,7 +5,7 @@ * Load the basic TrueType kerning table. This doesn't handle * kerning data within the GPOS table at the moment. * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -94,7 +94,7 @@ p_next = p; - p += 2; /* skip version */ + p += 2; /* skip version */ length = FT_NEXT_USHORT( p ); coverage = FT_NEXT_USHORT( p ); @@ -144,7 +144,7 @@ cur_pair = FT_NEXT_ULONG( p ); - if ( cur_pair <= old_pair ) + if ( cur_pair < old_pair ) break; p += 2; @@ -187,11 +187,18 @@ FT_UInt left_glyph, FT_UInt right_glyph ) { - FT_Int result = 0; - FT_UInt count, mask; - FT_Byte* p = face->kern_table; - FT_Byte* p_limit = p + face->kern_table_size; + FT_Int result = 0; + FT_UInt count, mask; + FT_Byte* p; + FT_Byte* p_limit; + + + if ( !face->kern_table ) + return result; + + p = face->kern_table; + p_limit = p + face->kern_table_size; p += 4; mask = 0x0001; diff --git a/thirdparty/freetype/src/sfnt/ttkern.h b/thirdparty/freetype/src/sfnt/ttkern.h index 3d8f1e8347..f063558313 100644 --- a/thirdparty/freetype/src/sfnt/ttkern.h +++ b/thirdparty/freetype/src/sfnt/ttkern.h @@ -5,7 +5,7 @@ * Load the basic TrueType kerning table. This doesn't handle * kerning data within the GPOS table at the moment. * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttload.c b/thirdparty/freetype/src/sfnt/ttload.c index 51416d80b4..c83bd197fe 100644 --- a/thirdparty/freetype/src/sfnt/ttload.c +++ b/thirdparty/freetype/src/sfnt/ttload.c @@ -5,7 +5,7 @@ * Load the basic TrueType tables, i.e., tables that can be either in * TTF or OTF fonts (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -205,7 +205,6 @@ if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) ) { - nn--; FT_TRACE2(( "check_table_dir:" " can read only %d table%s in font (instead of %d)\n", nn, nn == 1 ? "" : "s", sfnt->num_tables )); diff --git a/thirdparty/freetype/src/sfnt/ttload.h b/thirdparty/freetype/src/sfnt/ttload.h index cab15cd238..5368971c31 100644 --- a/thirdparty/freetype/src/sfnt/ttload.h +++ b/thirdparty/freetype/src/sfnt/ttload.h @@ -5,7 +5,7 @@ * Load the basic TrueType tables, i.e., tables that can be either in * TTF or OTF fonts (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttmtx.c b/thirdparty/freetype/src/sfnt/ttmtx.c index 7aece36fb0..88377327c6 100644 --- a/thirdparty/freetype/src/sfnt/ttmtx.c +++ b/thirdparty/freetype/src/sfnt/ttmtx.c @@ -4,7 +4,7 @@ * * Load the metrics tables common to TTF and OTF fonts (body). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttmtx.h b/thirdparty/freetype/src/sfnt/ttmtx.h index 270170d478..1e45b949a5 100644 --- a/thirdparty/freetype/src/sfnt/ttmtx.h +++ b/thirdparty/freetype/src/sfnt/ttmtx.h @@ -4,7 +4,7 @@ * * Load the metrics tables common to TTF and OTF fonts (specification). * - * Copyright (C) 2006-2021 by + * Copyright (C) 2006-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttpost.c b/thirdparty/freetype/src/sfnt/ttpost.c index b92ca5db14..1a885a15c5 100644 --- a/thirdparty/freetype/src/sfnt/ttpost.c +++ b/thirdparty/freetype/src/sfnt/ttpost.c @@ -5,7 +5,7 @@ * PostScript name table processing for TrueType and OpenType fonts * (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttpost.h b/thirdparty/freetype/src/sfnt/ttpost.h index 6d65b5766c..bf9342a9f5 100644 --- a/thirdparty/freetype/src/sfnt/ttpost.h +++ b/thirdparty/freetype/src/sfnt/ttpost.h @@ -5,7 +5,7 @@ * PostScript name table processing for TrueType and OpenType fonts * (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttsbit.c b/thirdparty/freetype/src/sfnt/ttsbit.c index e9ba697dba..bf73d04e54 100644 --- a/thirdparty/freetype/src/sfnt/ttsbit.c +++ b/thirdparty/freetype/src/sfnt/ttsbit.c @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded bitmap support (body). * - * Copyright (C) 2005-2021 by + * Copyright (C) 2005-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Copyright 2013 by Google, Inc. @@ -172,17 +172,8 @@ goto Exit; } -#ifdef FT_DEBUG_LEVEL_TRACE - /* we currently don't support bit 1; however, it is better to */ - /* draw at least something... */ if ( flags == 3 ) - { - FT_TRACE1(( "tt_face_load_sbit_strikes:" - " sbix overlay not supported yet\n" )); - FT_TRACE1(( " " - " expect bad rendering results\n" )); - } -#endif + face->root.face_flags |= FT_FACE_FLAG_SBIX_OVERLAY; /* * Count the number of strikes available in the table. We are a bit @@ -730,6 +721,9 @@ pitch = bitmap->pitch; line = bitmap->buffer; + if ( !line ) + goto Exit; + width = decoder->metrics->width; height = decoder->metrics->height; @@ -1577,17 +1571,34 @@ if ( !error ) { - FT_Short abearing; + FT_Short abearing; /* not used here */ FT_UShort aadvance; tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance ); metrics->horiBearingX = (FT_Short)originOffsetX; - metrics->horiBearingY = (FT_Short)( -originOffsetY + metrics->height ); + metrics->vertBearingX = (FT_Short)originOffsetX; + + metrics->horiBearingY = (FT_Short)( originOffsetY + metrics->height ); + metrics->vertBearingY = (FT_Short)originOffsetY; + metrics->horiAdvance = (FT_UShort)( aadvance * face->root.size->metrics.x_ppem / face->header.Units_Per_EM ); + + if ( face->vertical_info ) + tt_face_get_metrics( face, TRUE, glyph_index, &abearing, &aadvance ); + else if ( face->os2.version != 0xFFFFU ) + aadvance = (FT_UShort)FT_ABS( face->os2.sTypoAscender - + face->os2.sTypoDescender ); + else + aadvance = (FT_UShort)FT_ABS( face->horizontal.Ascender - + face->horizontal.Descender ); + + metrics->vertAdvance = (FT_UShort)( aadvance * + face->root.size->metrics.x_ppem / + face->header.Units_Per_EM ); } return error; diff --git a/thirdparty/freetype/src/sfnt/ttsbit.h b/thirdparty/freetype/src/sfnt/ttsbit.h index 7a0ed92e92..c967bffba3 100644 --- a/thirdparty/freetype/src/sfnt/ttsbit.h +++ b/thirdparty/freetype/src/sfnt/ttsbit.h @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded bitmap support (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/ttsvg.c b/thirdparty/freetype/src/sfnt/ttsvg.c new file mode 100644 index 0000000000..69277da577 --- /dev/null +++ b/thirdparty/freetype/src/sfnt/ttsvg.c @@ -0,0 +1,403 @@ +/**************************************************************************** + * + * ttsvg.c + * + * OpenType SVG Color (specification). + * + * Copyright (C) 2022 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + + /************************************************************************** + * + * 'SVG' table specification: + * + * https://docs.microsoft.com/en-us/typography/opentype/spec/svg + * + */ + +#include <ft2build.h> +#include <freetype/internal/ftstream.h> +#include <freetype/internal/ftobjs.h> +#include <freetype/internal/ftdebug.h> +#include <freetype/tttags.h> +#include <freetype/ftgzip.h> +#include <freetype/otsvg.h> + + +#ifdef FT_CONFIG_OPTION_SVG + +#include "ttsvg.h" + + + /* NOTE: These table sizes are given by the specification. */ +#define SVG_TABLE_HEADER_SIZE (10U) +#define SVG_DOCUMENT_RECORD_SIZE (12U) +#define SVG_DOCUMENT_LIST_MINIMUM_SIZE (2U + SVG_DOCUMENT_RECORD_SIZE) +#define SVG_MINIMUM_SIZE (SVG_TABLE_HEADER_SIZE + \ + SVG_DOCUMENT_LIST_MINIMUM_SIZE) + + + typedef struct Svg_ + { + FT_UShort version; /* table version (starting at 0) */ + FT_UShort num_entries; /* number of SVG document records */ + + FT_Byte* svg_doc_list; /* pointer to the start of SVG Document List */ + + void* table; /* memory that backs up SVG */ + FT_ULong table_size; + + } Svg; + + + /************************************************************************** + * + * The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, usued to print/log + * messages during execution. + */ +#undef FT_COMPONENT +#define FT_COMPONENT ttsvg + + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_svg( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = face->root.memory; + + FT_ULong table_size; + FT_Byte* table = NULL; + FT_Byte* p = NULL; + Svg* svg = NULL; + FT_ULong offsetToSVGDocumentList; + + + error = face->goto_table( face, TTAG_SVG, stream, &table_size ); + if ( error ) + goto NoSVG; + + if ( table_size < SVG_MINIMUM_SIZE ) + goto InvalidTable; + + if ( FT_FRAME_EXTRACT( table_size, table ) ) + goto NoSVG; + + /* Allocate memory for the SVG object */ + if ( FT_NEW( svg ) ) + goto NoSVG; + + p = table; + svg->version = FT_NEXT_USHORT( p ); + offsetToSVGDocumentList = FT_NEXT_ULONG( p ); + + if ( offsetToSVGDocumentList < SVG_TABLE_HEADER_SIZE || + offsetToSVGDocumentList > table_size - + SVG_DOCUMENT_LIST_MINIMUM_SIZE ) + goto InvalidTable; + + svg->svg_doc_list = (FT_Byte*)( table + offsetToSVGDocumentList ); + + p = svg->svg_doc_list; + svg->num_entries = FT_NEXT_USHORT( p ); + + FT_TRACE3(( "version: %d\n", svg->version )); + FT_TRACE3(( "number of entries: %d\n", svg->num_entries )); + + if ( offsetToSVGDocumentList + + svg->num_entries * SVG_DOCUMENT_RECORD_SIZE > table_size ) + goto InvalidTable; + + svg->table = table; + svg->table_size = table_size; + + face->svg = svg; + face->root.face_flags |= FT_FACE_FLAG_SVG; + + return FT_Err_Ok; + + InvalidTable: + error = FT_THROW( Invalid_Table ); + + NoSVG: + FT_FRAME_RELEASE( table ); + FT_FREE( svg ); + face->svg = NULL; + + return error; + } + + + FT_LOCAL_DEF( void ) + tt_face_free_svg( TT_Face face ) + { + FT_Memory memory = face->root.memory; + FT_Stream stream = face->root.stream; + + Svg* svg = (Svg*)face->svg; + + + if ( svg ) + { + FT_FRAME_RELEASE( svg->table ); + FT_FREE( svg ); + } + } + + + typedef struct Svg_doc_ + { + FT_UShort start_glyph_id; + FT_UShort end_glyph_id; + + FT_ULong offset; + FT_ULong length; + + } Svg_doc; + + + static Svg_doc + extract_svg_doc( FT_Byte* stream ) + { + Svg_doc doc; + + + doc.start_glyph_id = FT_NEXT_USHORT( stream ); + doc.end_glyph_id = FT_NEXT_USHORT( stream ); + + doc.offset = FT_NEXT_ULONG( stream ); + doc.length = FT_NEXT_ULONG( stream ); + + return doc; + } + + + static FT_Int + compare_svg_doc( Svg_doc doc, + FT_UInt glyph_index ) + { + if ( glyph_index < doc.start_glyph_id ) + return -1; + else if ( glyph_index > doc.end_glyph_id ) + return 1; + else + return 0; + } + + + static FT_Error + find_doc( FT_Byte* stream, + FT_UShort num_entries, + FT_UInt glyph_index, + FT_ULong *doc_offset, + FT_ULong *doc_length, + FT_UShort *start_glyph, + FT_UShort *end_glyph ) + { + FT_Error error; + + Svg_doc start_doc; + Svg_doc mid_doc; + Svg_doc end_doc; + + FT_Bool found = FALSE; + FT_UInt i = 0; + + FT_UInt start_index = 0; + FT_UInt end_index = num_entries - 1; + FT_Int comp_res; + + + /* search algorithm */ + if ( num_entries == 0 ) + { + error = FT_THROW( Invalid_Table ); + return error; + } + + start_doc = extract_svg_doc( stream + start_index * 12 ); + end_doc = extract_svg_doc( stream + end_index * 12 ); + + if ( ( compare_svg_doc( start_doc, glyph_index ) == -1 ) || + ( compare_svg_doc( end_doc, glyph_index ) == 1 ) ) + { + error = FT_THROW( Invalid_Glyph_Index ); + return error; + } + + while ( start_index <= end_index ) + { + i = ( start_index + end_index ) / 2; + mid_doc = extract_svg_doc( stream + i * 12 ); + comp_res = compare_svg_doc( mid_doc, glyph_index ); + + if ( comp_res == 1 ) + { + start_index = i + 1; + start_doc = extract_svg_doc( stream + start_index * 4 ); + } + else if ( comp_res == -1 ) + { + end_index = i - 1; + end_doc = extract_svg_doc( stream + end_index * 4 ); + } + else + { + found = TRUE; + break; + } + } + /* search algorithm end */ + + if ( found != TRUE ) + { + FT_TRACE5(( "SVG glyph not found\n" )); + error = FT_THROW( Invalid_Glyph_Index ); + } + else + { + *doc_offset = mid_doc.offset; + *doc_length = mid_doc.length; + + *start_glyph = mid_doc.start_glyph_id; + *end_glyph = mid_doc.end_glyph_id; + + error = FT_Err_Ok; + } + + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_svg_doc( FT_GlyphSlot glyph, + FT_UInt glyph_index ) + { + FT_Byte* doc_list; /* pointer to the SVG doc list */ + FT_UShort num_entries; /* total number of entries in doc list */ + FT_ULong doc_offset; + FT_ULong doc_length; + + FT_UShort start_glyph_id; + FT_UShort end_glyph_id; + + FT_Error error = FT_Err_Ok; + TT_Face face = (TT_Face)glyph->face; + FT_Memory memory = face->root.memory; + Svg* svg = (Svg*)face->svg; + + FT_SVG_Document svg_document = (FT_SVG_Document)glyph->other; + + + FT_ASSERT( !( svg == NULL ) ); + + doc_list = svg->svg_doc_list; + num_entries = FT_NEXT_USHORT( doc_list ); + + error = find_doc( doc_list, num_entries, glyph_index, + &doc_offset, &doc_length, + &start_glyph_id, &end_glyph_id ); + if ( error != FT_Err_Ok ) + goto Exit; + + doc_list = svg->svg_doc_list; /* reset, so we can use it again */ + doc_list = (FT_Byte*)( doc_list + doc_offset ); + + if ( ( doc_list[0] == 0x1F ) && ( doc_list[1] == 0x8B ) + && ( doc_list[2] == 0x08 ) ) + { +#ifdef FT_CONFIG_OPTION_USE_ZLIB + + FT_ULong uncomp_size; + FT_Byte* uncomp_buffer = NULL; + + + /* + * Get the size of the original document. This helps in allotting the + * buffer to accommodate the uncompressed version. The last 4 bytes + * of the compressed document are equal to the original size modulo + * 2^32. Since the size of SVG documents is less than 2^32 bytes we + * can use this accurately. The four bytes are stored in + * little-endian format. + */ + FT_TRACE4(( "SVG document is GZIP compressed\n" )); + uncomp_size = (FT_ULong)doc_list[doc_length - 1] << 24 | + (FT_ULong)doc_list[doc_length - 2] << 16 | + (FT_ULong)doc_list[doc_length - 3] << 8 | + (FT_ULong)doc_list[doc_length - 4]; + + if ( FT_QALLOC( uncomp_buffer, uncomp_size ) ) + goto Exit; + + error = FT_Gzip_Uncompress( memory, + uncomp_buffer, + &uncomp_size, + doc_list, + doc_length ); + if ( error ) + { + FT_FREE( uncomp_buffer ); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + + glyph->internal->flags |= FT_GLYPH_OWN_GZIP_SVG; + + doc_list = uncomp_buffer; + doc_length = uncomp_size; + +#else /* !FT_CONFIG_OPTION_USE_ZLIB */ + + error = FT_THROW( Unimplemented_Feature ); + goto Exit; + +#endif /* !FT_CONFIG_OPTION_USE_ZLIB */ + } + + svg_document->svg_document = doc_list; + svg_document->svg_document_length = doc_length; + + svg_document->metrics = glyph->face->size->metrics; + svg_document->units_per_EM = glyph->face->units_per_EM; + + svg_document->start_glyph_id = start_glyph_id; + svg_document->end_glyph_id = end_glyph_id; + + svg_document->transform.xx = 0x10000; + svg_document->transform.xy = 0; + svg_document->transform.yx = 0; + svg_document->transform.yy = 0x10000; + + svg_document->delta.x = 0; + svg_document->delta.y = 0; + + FT_TRACE5(( "start_glyph_id: %d\n", start_glyph_id )); + FT_TRACE5(( "end_glyph_id: %d\n", end_glyph_id )); + FT_TRACE5(( "svg_document:\n" )); + FT_TRACE5(( " %.*s\n", (FT_UInt)doc_length, doc_list )); + + glyph->other = svg_document; + + Exit: + return error; + } + +#else /* !FT_CONFIG_OPTION_SVG */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_svg_dummy; + +#endif /* !FT_CONFIG_OPTION_SVG */ + + +/* END */ diff --git a/thirdparty/freetype/src/sfnt/ttsvg.h b/thirdparty/freetype/src/sfnt/ttsvg.h new file mode 100644 index 0000000000..7c234fd524 --- /dev/null +++ b/thirdparty/freetype/src/sfnt/ttsvg.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * + * ttsvg.h + * + * OpenType SVG Color (specification). + * + * Copyright (C) 2022 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#ifndef TTSVG_H_ +#define TTSVG_H_ + +#include <freetype/internal/ftstream.h> +#include <freetype/internal/tttypes.h> + + +FT_BEGIN_HEADER + + FT_LOCAL( FT_Error ) + tt_face_load_svg( TT_Face face, + FT_Stream stream ); + + FT_LOCAL( void ) + tt_face_free_svg( TT_Face face ); + + FT_LOCAL( FT_Error ) + tt_face_load_svg_doc( FT_GlyphSlot glyph, + FT_UInt glyph_index ); + +FT_END_HEADER + +#endif /* TTSVG_H_ */ + + +/* END */ diff --git a/thirdparty/freetype/src/sfnt/woff2tags.c b/thirdparty/freetype/src/sfnt/woff2tags.c index fe8f5cf76f..7d79fef39a 100644 --- a/thirdparty/freetype/src/sfnt/woff2tags.c +++ b/thirdparty/freetype/src/sfnt/woff2tags.c @@ -4,7 +4,7 @@ * * WOFF2 Font table tags (base). * - * Copyright (C) 2019-2021 by + * Copyright (C) 2019-2022 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/sfnt/woff2tags.h b/thirdparty/freetype/src/sfnt/woff2tags.h index 4ef0a651c3..05df85aba0 100644 --- a/thirdparty/freetype/src/sfnt/woff2tags.h +++ b/thirdparty/freetype/src/sfnt/woff2tags.h @@ -4,7 +4,7 @@ * * WOFF2 Font table tags (specification). * - * Copyright (C) 2019-2021 by + * Copyright (C) 2019-2022 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/smooth/ftgrays.c b/thirdparty/freetype/src/smooth/ftgrays.c index d982c2820b..622035aa79 100644 --- a/thirdparty/freetype/src/smooth/ftgrays.c +++ b/thirdparty/freetype/src/smooth/ftgrays.c @@ -4,7 +4,7 @@ * * A new `perfect' anti-aliasing renderer (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -333,7 +333,9 @@ typedef ptrdiff_t FT_PtrDist; #define PIXEL_BITS 8 #define ONE_PIXEL ( 1 << PIXEL_BITS ) +#undef TRUNC #define TRUNC( x ) (TCoord)( (x) >> PIXEL_BITS ) +#undef FRACT #define FRACT( x ) (TCoord)( (x) & ( ONE_PIXEL - 1 ) ) #if PIXEL_BITS >= 6 diff --git a/thirdparty/freetype/src/smooth/ftgrays.h b/thirdparty/freetype/src/smooth/ftgrays.h index 3dad0498dc..13bf2baaa2 100644 --- a/thirdparty/freetype/src/smooth/ftgrays.h +++ b/thirdparty/freetype/src/smooth/ftgrays.h @@ -4,7 +4,7 @@ * * FreeType smooth renderer declaration * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/smooth/ftsmerrs.h b/thirdparty/freetype/src/smooth/ftsmerrs.h index dc2c40cc9f..7bc6077988 100644 --- a/thirdparty/freetype/src/smooth/ftsmerrs.h +++ b/thirdparty/freetype/src/smooth/ftsmerrs.h @@ -4,7 +4,7 @@ * * smooth renderer error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/smooth/ftsmooth.c b/thirdparty/freetype/src/smooth/ftsmooth.c index bea3b4a800..df227c3758 100644 --- a/thirdparty/freetype/src/smooth/ftsmooth.c +++ b/thirdparty/freetype/src/smooth/ftsmooth.c @@ -4,7 +4,7 @@ * * Anti-aliasing renderer interface (body). * - * Copyright (C) 2000-2021 by + * Copyright (C) 2000-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/smooth/ftsmooth.h b/thirdparty/freetype/src/smooth/ftsmooth.h index 2dd81e84b8..87f09faea4 100644 --- a/thirdparty/freetype/src/smooth/ftsmooth.h +++ b/thirdparty/freetype/src/smooth/ftsmooth.h @@ -4,7 +4,7 @@ * * Anti-aliasing renderer interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/smooth/smooth.c b/thirdparty/freetype/src/smooth/smooth.c index 9e25440635..f341e8f252 100644 --- a/thirdparty/freetype/src/smooth/smooth.c +++ b/thirdparty/freetype/src/smooth/smooth.c @@ -4,7 +4,7 @@ * * FreeType anti-aliasing rasterer module component (body only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/svg/ftsvg.c b/thirdparty/freetype/src/svg/ftsvg.c new file mode 100644 index 0000000000..55c50718f3 --- /dev/null +++ b/thirdparty/freetype/src/svg/ftsvg.c @@ -0,0 +1,350 @@ +/**************************************************************************** + * + * ftsvg.c + * + * The FreeType SVG renderer interface (body). + * + * Copyright (C) 2022 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#include <freetype/internal/ftdebug.h> +#include <freetype/internal/ftserv.h> +#include <freetype/internal/services/svprop.h> +#include <freetype/otsvg.h> +#include <freetype/internal/svginterface.h> +#include <freetype/ftbbox.h> + +#include "ftsvg.h" +#include "svgtypes.h" + + + /************************************************************************** + * + * The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, usued to print/log + * messages during execution. + */ +#undef FT_COMPONENT +#define FT_COMPONENT otsvg + + +#ifdef FT_CONFIG_OPTION_SVG + + /* ft_svg_init */ + static FT_Error + ft_svg_init( SVG_Renderer svg_module ) + { + FT_Error error = FT_Err_Ok; + + + svg_module->loaded = FALSE; + svg_module->hooks_set = FALSE; + + return error; + } + + + static void + ft_svg_done( SVG_Renderer svg_module ) + { + if ( svg_module->loaded == TRUE && + svg_module->hooks_set == TRUE ) + svg_module->hooks.free_svg( &svg_module->state ); + + svg_module->loaded = FALSE; + } + + + static FT_Error + ft_svg_preset_slot( FT_Module module, + FT_GlyphSlot slot, + FT_Bool cache ) + { + SVG_Renderer svg_renderer = (SVG_Renderer)module; + SVG_RendererHooks hooks = svg_renderer->hooks; + + + if ( svg_renderer->hooks_set == FALSE ) + { + FT_TRACE1(( "Hooks are NOT set. Can't render OT-SVG glyphs\n" )); + return FT_THROW( Missing_SVG_Hooks ); + } + + if ( svg_renderer->loaded == FALSE ) + { + FT_TRACE3(( "ft_svg_preset_slot: first presetting call," + " calling init hook\n" )); + hooks.init_svg( &svg_renderer->state ); + + svg_renderer->loaded = TRUE; + } + + return hooks.preset_slot( slot, cache, &svg_renderer->state ); + } + + + static FT_Error + ft_svg_render( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_Render_Mode mode, + const FT_Vector* origin ) + { + SVG_Renderer svg_renderer = (SVG_Renderer)renderer; + + FT_Library library = renderer->root.library; + FT_Memory memory = library->memory; + FT_Error error; + + FT_ULong size_image_buffer; + + SVG_RendererHooks hooks = svg_renderer->hooks; + + + FT_UNUSED( mode ); + FT_UNUSED( origin ); + + if ( mode != FT_RENDER_MODE_NORMAL ) + return FT_THROW( Bad_Argument ); + + if ( svg_renderer->hooks_set == FALSE ) + { + FT_TRACE1(( "Hooks are NOT set. Can't render OT-SVG glyphs\n" )); + return FT_THROW( Missing_SVG_Hooks ); + } + + if ( svg_renderer->loaded == FALSE ) + { + FT_TRACE3(( "ft_svg_render: first rendering, calling init hook\n" )); + error = hooks.init_svg( &svg_renderer->state ); + + svg_renderer->loaded = TRUE; + } + + ft_svg_preset_slot( (FT_Module)renderer, slot, TRUE ); + + size_image_buffer = (FT_ULong)slot->bitmap.pitch * slot->bitmap.rows; + /* No `FT_QALLOC` here since we need a clean, empty canvas */ + /* to start with. */ + if ( FT_ALLOC( slot->bitmap.buffer, size_image_buffer ) ) + return error; + + error = hooks.render_svg( slot, &svg_renderer->state ); + if ( error ) + FT_FREE( slot->bitmap.buffer ); + else + slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + + return error; + } + + + static const SVG_Interface svg_interface = + { + (Preset_Bitmap_Func)ft_svg_preset_slot + }; + + + static FT_Error + ft_svg_property_set( FT_Module module, + const char* property_name, + const void* value, + FT_Bool value_is_string ) + { + FT_Error error = FT_Err_Ok; + SVG_Renderer renderer = (SVG_Renderer)module; + + + if ( !ft_strcmp( property_name, "svg-hooks" ) ) + { + SVG_RendererHooks* hooks; + + + if ( value_is_string == TRUE ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + hooks = (SVG_RendererHooks*)value; + + if ( !hooks->init_svg || + !hooks->free_svg || + !hooks->render_svg || + !hooks->preset_slot ) + { + FT_TRACE0(( "ft_svg_property_set:" + " SVG rendering hooks not set because\n" )); + FT_TRACE0(( " " + " at least one function pointer is NULL\n" )); + + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + renderer->hooks = *hooks; + renderer->hooks_set = TRUE; + } + else + error = FT_THROW( Missing_Property ); + + Exit: + return error; + } + + + static FT_Error + ft_svg_property_get( FT_Module module, + const char* property_name, + const void* value ) + { + FT_Error error = FT_Err_Ok; + SVG_Renderer renderer = (SVG_Renderer)module; + + + if ( !ft_strcmp( property_name, "svg-hooks" ) ) + { + SVG_RendererHooks* hooks = (SVG_RendererHooks*)value; + + + *hooks = renderer->hooks; + } + else + error = FT_THROW( Missing_Property ); + + return error; + } + + + FT_DEFINE_SERVICE_PROPERTIESREC( + ft_svg_service_properties, + + (FT_Properties_SetFunc)ft_svg_property_set, /* set_property */ + (FT_Properties_GetFunc)ft_svg_property_get /* get_property */ + ) + + + FT_DEFINE_SERVICEDESCREC1( + ft_svg_services, + FT_SERVICE_ID_PROPERTIES, &ft_svg_service_properties ) + + + FT_CALLBACK_DEF( FT_Module_Interface ) + ft_svg_get_interface( FT_Module module, + const char* ft_svg_interface ) + { + FT_Module_Interface result; + + + FT_UNUSED( module ); + + result = ft_service_list_lookup( ft_svg_services, ft_svg_interface ); + if ( result ) + return result; + + return 0; + } + + + static FT_Error + ft_svg_transform( FT_Renderer renderer, + FT_GlyphSlot slot, + const FT_Matrix* _matrix, + const FT_Vector* _delta ) + { + FT_SVG_Document doc = (FT_SVG_Document)slot->other; + FT_Matrix* matrix = (FT_Matrix*)_matrix; + FT_Vector* delta = (FT_Vector*)_delta; + + FT_Matrix tmp_matrix; + FT_Vector tmp_delta; + + FT_Matrix a, b; + FT_Pos x, y; + + + FT_UNUSED( renderer ); + + if ( !matrix ) + { + tmp_matrix.xx = 0x10000; + tmp_matrix.xy = 0; + tmp_matrix.yx = 0; + tmp_matrix.yy = 0x10000; + + matrix = &tmp_matrix; + } + + if ( !delta ) + { + tmp_delta.x = 0; + tmp_delta.y = 0; + + delta = &tmp_delta; + } + + a = doc->transform; + b = *matrix; + FT_Matrix_Multiply( &b, &a ); + + + x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, doc->delta.x ), + FT_MulFix( matrix->xy, doc->delta.y ) ), + delta->x ); + y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, doc->delta.x ), + FT_MulFix( matrix->yy, doc->delta.y ) ), + delta->y ); + + doc->delta.x = x; + doc->delta.y = y; + doc->transform = a; + + return FT_Err_Ok; + } + +#endif /* FT_CONFIG_OPTION_SVG */ + + +#ifdef FT_CONFIG_OPTION_SVG +#define PUT_SVG_MODULE( a ) a +#define SVG_GLYPH_FORMAT FT_GLYPH_FORMAT_SVG +#else +#define PUT_SVG_MODULE( a ) NULL +#define SVG_GLYPH_FORMAT FT_GLYPH_FORMAT_NONE +#endif + + + FT_DEFINE_RENDERER( + ft_svg_renderer_class, + + FT_MODULE_RENDERER, + sizeof ( SVG_RendererRec ), + + "ot-svg", + 0x10000L, + 0x20000L, + + (const void*)PUT_SVG_MODULE( &svg_interface ), /* module specific interface */ + + (FT_Module_Constructor)PUT_SVG_MODULE( ft_svg_init ), /* module_init */ + (FT_Module_Destructor)PUT_SVG_MODULE( ft_svg_done ), /* module_done */ + PUT_SVG_MODULE( ft_svg_get_interface ), /* get_interface */ + + SVG_GLYPH_FORMAT, + + (FT_Renderer_RenderFunc) PUT_SVG_MODULE( ft_svg_render ), /* render_glyph */ + (FT_Renderer_TransformFunc)PUT_SVG_MODULE( ft_svg_transform ), /* transform_glyph */ + NULL, /* get_glyph_cbox */ + NULL, /* set_mode */ + NULL /* raster_class */ + ) + + +/* END */ diff --git a/thirdparty/freetype/src/svg/ftsvg.h b/thirdparty/freetype/src/svg/ftsvg.h new file mode 100644 index 0000000000..73514b8cf3 --- /dev/null +++ b/thirdparty/freetype/src/svg/ftsvg.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * + * ftsvg.h + * + * The FreeType SVG renderer interface (specification). + * + * Copyright (C) 2022 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#ifndef FTSVG_H_ +#define FTSVG_H_ + +#include <ft2build.h> +#include <freetype/ftrender.h> +#include <freetype/internal/ftobjs.h> + + +FT_BEGIN_HEADER + + FT_DECLARE_RENDERER( ft_svg_renderer_class ) + +FT_END_HEADER + +#endif /* FTSVG_H_ */ + + +/* END */ diff --git a/thirdparty/freetype/src/svg/svg.c b/thirdparty/freetype/src/svg/svg.c new file mode 100644 index 0000000000..b7e62a418c --- /dev/null +++ b/thirdparty/freetype/src/svg/svg.c @@ -0,0 +1,24 @@ +/**************************************************************************** + * + * svg.c + * + * FreeType SVG renderer module component (body only). + * + * Copyright (C) 2022 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include "svgtypes.h" +#include "ftsvg.c" + + +/* END */ diff --git a/thirdparty/freetype/src/svg/svgtypes.h b/thirdparty/freetype/src/svg/svgtypes.h new file mode 100644 index 0000000000..34fce47a34 --- /dev/null +++ b/thirdparty/freetype/src/svg/svgtypes.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * + * svgtypes.h + * + * The FreeType SVG renderer internal types (specification). + * + * Copyright (C) 2022 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#ifndef SVGTYPES_H_ +#define SVGTYPES_H_ + +#include <ft2build.h> +#include <freetype/internal/ftobjs.h> +#include <freetype/ftrender.h> +#include <freetype/otsvg.h> + + + typedef struct SVG_RendererRec_ + { + FT_RendererRec root; /* this inherits FT_RendererRec */ + FT_Bool loaded; + FT_Bool hooks_set; + SVG_RendererHooks hooks; /* this holds hooks for SVG rendering */ + FT_Pointer state; /* a place for hooks to store state, if needed */ + + } SVG_RendererRec; + + typedef struct SVG_RendererRec_* SVG_Renderer; + +#endif /* SVGTYPES_H_ */ + + +/* EOF */ diff --git a/thirdparty/freetype/src/truetype/truetype.c b/thirdparty/freetype/src/truetype/truetype.c index 4232aca6ec..41c844acbb 100644 --- a/thirdparty/freetype/src/truetype/truetype.c +++ b/thirdparty/freetype/src/truetype/truetype.c @@ -4,7 +4,7 @@ * * FreeType TrueType driver component (body only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/truetype/ttdriver.c b/thirdparty/freetype/src/truetype/ttdriver.c index 6fcfdb23e4..245d97cb58 100644 --- a/thirdparty/freetype/src/truetype/ttdriver.c +++ b/thirdparty/freetype/src/truetype/ttdriver.c @@ -4,7 +4,7 @@ * * TrueType font driver implementation (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/truetype/ttdriver.h b/thirdparty/freetype/src/truetype/ttdriver.h index 4e6d52d22c..c477c0b1dd 100644 --- a/thirdparty/freetype/src/truetype/ttdriver.h +++ b/thirdparty/freetype/src/truetype/ttdriver.h @@ -4,7 +4,7 @@ * * High-level TrueType driver interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/truetype/tterrors.h b/thirdparty/freetype/src/truetype/tterrors.h index 0ce247e376..2c95ea17b2 100644 --- a/thirdparty/freetype/src/truetype/tterrors.h +++ b/thirdparty/freetype/src/truetype/tterrors.h @@ -4,7 +4,7 @@ * * TrueType error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/truetype/ttgload.c b/thirdparty/freetype/src/truetype/ttgload.c index 11968f6fdc..2ca63d65a3 100644 --- a/thirdparty/freetype/src/truetype/ttgload.c +++ b/thirdparty/freetype/src/truetype/ttgload.c @@ -4,7 +4,7 @@ * * TrueType Glyph Loader (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -1104,8 +1104,8 @@ for ( ; vec < limit; vec++, u++ ) { - vec->x = ( FT_MulFix( u->x, x_scale ) + 32 ) >> 6; - vec->y = ( FT_MulFix( u->y, y_scale ) + 32 ) >> 6; + vec->x = ADD_LONG( FT_MulFix( u->x, x_scale ), 32 ) >> 6; + vec->y = ADD_LONG( FT_MulFix( u->y, y_scale ), 32 ) >> 6; } } else @@ -1228,8 +1228,8 @@ p1 = gloader->base.outline.points + k; p2 = gloader->base.outline.points + l; - x = p1->x - p2->x; - y = p1->y - p2->y; + x = SUB_LONG( p1->x, p2->x ); + y = SUB_LONG( p1->y, p2->y ); } else { @@ -2230,10 +2230,6 @@ FT_UInt glyph_index ) { TT_Face face = loader->face; -#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \ - defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); -#endif FT_BBox bbox; FT_Fixed y_scale; @@ -2256,53 +2252,10 @@ glyph->metrics.horiBearingX = bbox.xMin; glyph->metrics.horiBearingY = bbox.yMax; - glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x); - - /* Adjust advance width to the value contained in the hdmx table */ - /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */ - /* mode of the v40 interpreter is active. See `ttinterp.h' for */ - /* details on backward compatibility mode. */ - if ( -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - ( loader->exec && loader->exec->backward_compatibility ) ) && -#endif - !face->postscript.isFixedPitch && - IS_HINTED( loader->load_flags ) && - !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) ) - { - FT_Byte* widthp; - - - widthp = tt_face_get_device_metrics( face, - size->metrics->x_ppem, - glyph_index ); - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - FT_Bool ignore_x_mode; - - - ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) != - FT_RENDER_MODE_MONO ); - - if ( widthp && - ( ( ignore_x_mode && loader->exec->compatible_widths ) || - !ignore_x_mode || - SPH_OPTION_BITMAP_WIDTHS ) ) - glyph->metrics.horiAdvance = *widthp * 64; - } - else - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - { - if ( widthp ) - glyph->metrics.horiAdvance = *widthp * 64; - } - } + if ( loader->widthp ) + glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64; + else + glyph->metrics.horiAdvance = SUB_LONG( loader->pp2.x, loader->pp1.x ); /* set glyph dimensions */ glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin ); @@ -2735,12 +2688,58 @@ /* note that this flag can also be modified in a glyph's bytecode */ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 && exec->GS.instruct_control & 4 ) - exec->ignore_x_mode = 0; -#endif + exec->ignore_x_mode = FALSE; +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ + +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* + * Toggle backward compatibility according to what font wants, except + * when + * + * 1) we have a `tricky' font that heavily relies on the interpreter to + * render glyphs correctly, for example DFKai-SB, or + * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested. + * + * In those cases, backward compatibility needs to be turned off to get + * correct rendering. The rendering is then completely up to the + * font's programming. + * + */ + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && + subpixel_hinting_lean && + !FT_IS_TRICKY( glyph->face ) ) + exec->backward_compatibility = !( exec->GS.instruct_control & 4 ); + else + exec->backward_compatibility = FALSE; +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */ exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); loader->exec = exec; loader->instructions = exec->glyphIns; + + /* Use the hdmx table if any unless FT_LOAD_COMPUTE_METRICS */ + /* is set or backward compatibility mode of the v38 or v40 */ + /* interpreters is active. See `ttinterp.h' for details on */ + /* backward compatibility mode. */ + if ( IS_HINTED( loader->load_flags ) && + !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && + exec->backward_compatibility ) && +#endif +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + !( driver->interpreter_version == TT_INTERPRETER_VERSION_38 && + !SPH_OPTION_BITMAP_WIDTHS && + FT_LOAD_TARGET_MODE( loader->load_flags ) != + FT_RENDER_MODE_MONO && + exec->compatible_widths ) && +#endif + !face->postscript.isFixedPitch ) + { + loader->widthp = size->widthp; + } + else + loader->widthp = NULL; } #endif /* TT_USE_BYTECODE_INTERPRETER */ @@ -2788,11 +2787,12 @@ * A function used to load a single glyph within a given glyph slot, * for a given size. * - * @Input: + * @InOut: * glyph :: * A handle to a target slot object where the glyph * will be loaded. * + * @Input: * size :: * A handle to the source face size at which the glyph * must be scaled/loaded. @@ -2897,8 +2897,12 @@ } else { - if ( FT_IS_SCALABLE( glyph->face ) ) + if ( FT_IS_SCALABLE( glyph->face ) || + FT_HAS_SBIX( glyph->face ) ) { + TT_Face face = (TT_Face)glyph->face; + + /* for the bbox we need the header only */ (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE ); (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE ); @@ -2906,6 +2910,35 @@ glyph->linearHoriAdvance = loader.linear; glyph->linearVertAdvance = loader.vadvance; + /* Bitmaps from the 'sbix' table need special treatment: */ + /* if there is a glyph contour, the bitmap origin must be */ + /* shifted to be relative to the lower left corner of the */ + /* glyph bounding box, also taking the left-side bearing */ + /* (or top bearing) into account. */ + if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX && + loader.n_contours > 0 ) + { + FT_Int bitmap_left; + FT_Int bitmap_top; + + + if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + { + /* This is a guess, since Apple's CoreText engine doesn't */ + /* really do vertical typesetting. */ + bitmap_left = loader.bbox.xMin; + bitmap_top = loader.top_bearing; + } + else + { + bitmap_left = loader.left_bearing; + bitmap_top = loader.bbox.yMin; + } + + glyph->bitmap_left += FT_MulFix( bitmap_left, x_scale ) >> 6; + glyph->bitmap_top += FT_MulFix( bitmap_top, y_scale ) >> 6; + } + /* sanity checks: if `xxxAdvance' in the sbit metric */ /* structure isn't set, use `linearXXXAdvance' */ if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance ) @@ -2920,6 +2953,12 @@ } } + if ( load_flags & FT_LOAD_SBITS_ONLY ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ @@ -2929,16 +2968,81 @@ goto Exit; } - if ( load_flags & FT_LOAD_SBITS_ONLY ) +#ifdef FT_CONFIG_OPTION_SVG + + /* check for OT-SVG */ + if ( ( load_flags & FT_LOAD_COLOR ) && ( (TT_Face)glyph->face )->svg ) + { + SFNT_Service sfnt; + + FT_Short leftBearing; + FT_Short topBearing; + FT_UShort advanceX; + FT_UShort advanceY; + + + FT_TRACE3(( "Trying to load SVG glyph\n" )); + sfnt = (SFNT_Service)( (TT_Face)glyph->face )->sfnt; + + error = sfnt->load_svg_doc( glyph, glyph_index ); + if ( !error ) + { + TT_Face face = (TT_Face)glyph->face; + + + FT_TRACE3(( "Successfully loaded SVG glyph\n" )); + + glyph->format = FT_GLYPH_FORMAT_SVG; + + sfnt->get_metrics( face, + FALSE, + glyph_index, + &leftBearing, + &advanceX ); + sfnt->get_metrics( face, + TRUE, + glyph_index, + &topBearing, + &advanceY ); + + advanceX = (FT_UShort)FT_MulDiv( advanceX, + glyph->face->size->metrics.x_ppem, + glyph->face->units_per_EM ); + advanceY = (FT_UShort)FT_MulDiv( advanceY, + glyph->face->size->metrics.y_ppem, + glyph->face->units_per_EM ); + + glyph->metrics.horiAdvance = advanceX << 6; + glyph->metrics.vertAdvance = advanceY << 6; + + return error; + } + + FT_TRACE3(( "Failed to load SVG glyph\n" )); + } + + /* return immediately if we only want SVG glyphs */ + if ( load_flags & FT_LOAD_SVG_ONLY ) { error = FT_THROW( Invalid_Argument ); goto Exit; } +#endif /* FT_CONFIG_OPTION_SVG */ + error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); if ( error ) goto Exit; + /* done if we are only interested in the `hdmx` advance */ + if ( load_flags & FT_LOAD_ADVANCE_ONLY && + !( load_flags & FT_LOAD_VERTICAL_LAYOUT ) && + loader.widthp ) + { + glyph->metrics.horiAdvance = loader.widthp[glyph_index] * 64; + goto Done; + } + glyph->format = FT_GLYPH_FORMAT_OUTLINE; glyph->num_subglyphs = 0; glyph->outline.flags = 0; @@ -3017,6 +3121,7 @@ glyph->outline.n_points, glyph->outline.flags )); + Done: tt_loader_done( &loader ); Exit: diff --git a/thirdparty/freetype/src/truetype/ttgload.h b/thirdparty/freetype/src/truetype/ttgload.h index 78fdeaa73d..3195351f78 100644 --- a/thirdparty/freetype/src/truetype/ttgload.h +++ b/thirdparty/freetype/src/truetype/ttgload.h @@ -4,7 +4,7 @@ * * TrueType Glyph Loader (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/truetype/ttgxvar.c b/thirdparty/freetype/src/truetype/ttgxvar.c index 7f2db0cbdc..6a0edef29b 100644 --- a/thirdparty/freetype/src/truetype/ttgxvar.c +++ b/thirdparty/freetype/src/truetype/ttgxvar.c @@ -4,7 +4,7 @@ * * TrueType GX Font Variation loader * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. * * This file is part of the FreeType project, and may only be used, @@ -151,9 +151,7 @@ FT_UInt i, j; FT_UShort first; FT_Memory memory = stream->memory; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); + FT_Error error; *point_cnt = 0; @@ -266,9 +264,7 @@ FT_UInt i, j; FT_UInt bytes_used; FT_Memory memory = stream->memory; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); + FT_Error error; if ( FT_QNEW_ARRAY( deltas, delta_cnt ) ) @@ -361,14 +357,12 @@ FT_Memory memory = stream->memory; GX_Blend blend = face->blend; GX_AVarSegment segment; - FT_Error error = FT_Err_Ok; + FT_Error error; FT_Long version; FT_Long axisCount; FT_Int i, j; FT_ULong table_len; - FT_UNUSED( error ); - FT_TRACE2(( "AVAR " )); @@ -421,7 +415,6 @@ FT_FREE( blend->avar_segment[j].correspondence ); FT_FREE( blend->avar_segment ); - blend->avar_segment = NULL; goto Exit; } @@ -2753,7 +2746,6 @@ /* The cvt table has been loaded already; every time we change the */ /* blend we may need to reload and remodify the cvt table. */ FT_FREE( face->cvt ); - face->cvt = NULL; error = tt_face_load_cvt( face, face->root.stream ); break; @@ -2772,7 +2764,6 @@ /* enforce recomputation of the PostScript name; */ FT_FREE( face->postscript_name ); - face->postscript_name = NULL; Exit: return error; @@ -3476,6 +3467,7 @@ } else { + localpoints = NULL; points = sharedpoints; point_count = spoint_count; } diff --git a/thirdparty/freetype/src/truetype/ttgxvar.h b/thirdparty/freetype/src/truetype/ttgxvar.h index ded9ea1d6d..17915f00d3 100644 --- a/thirdparty/freetype/src/truetype/ttgxvar.h +++ b/thirdparty/freetype/src/truetype/ttgxvar.h @@ -4,7 +4,7 @@ * * TrueType GX Font Variation loader (specification) * - * Copyright (C) 2004-2021 by + * Copyright (C) 2004-2022 by * David Turner, Robert Wilhelm, Werner Lemberg and George Williams. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/truetype/ttinterp.c b/thirdparty/freetype/src/truetype/ttinterp.c index 731095ed0c..e16565c3a5 100644 --- a/thirdparty/freetype/src/truetype/ttinterp.c +++ b/thirdparty/freetype/src/truetype/ttinterp.c @@ -4,7 +4,7 @@ * * TrueType bytecode interpreter (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -5260,16 +5260,21 @@ } } - exc->GS.instruct_control &= ~(FT_Byte)Kf; - exc->GS.instruct_control |= (FT_Byte)L; + /* INSTCTRL should only be used in the CVT program */ + if ( exc->iniRange == tt_coderange_cvt ) + { + exc->GS.instruct_control &= ~(FT_Byte)Kf; + exc->GS.instruct_control |= (FT_Byte)L; + } - if ( K == 3 ) + /* except to change the subpixel flags temporarily */ + else if ( exc->iniRange == tt_coderange_glyph && K == 3 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY /* INSTCTRL modifying flag 3 also has an effect */ /* outside of the CVT program */ if ( SUBPIXEL_HINTING_INFINALITY ) - exc->ignore_x_mode = FT_BOOL( L == 4 ); + exc->ignore_x_mode = !FT_BOOL( L == 4 ); #endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL @@ -5280,6 +5285,8 @@ exc->backward_compatibility = !FT_BOOL( L == 4 ); #endif } + else if ( exc->pedantic_hinting ) + exc->error = FT_THROW( Invalid_Reference ); } @@ -7755,35 +7762,6 @@ #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - exc->iup_called = FALSE; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* - * Toggle backward compatibility according to what font wants, except - * when - * - * 1) we have a `tricky' font that heavily relies on the interpreter to - * render glyphs correctly, for example DFKai-SB, or - * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested. - * - * In those cases, backward compatibility needs to be turned off to get - * correct rendering. The rendering is then completely up to the - * font's programming. - * - */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->subpixel_hinting_lean && - !FT_IS_TRICKY( &exc->face->root ) ) - exc->backward_compatibility = !( exc->GS.instruct_control & 4 ); - else - exc->backward_compatibility = FALSE; - - exc->iupx_called = FALSE; - exc->iupy_called = FALSE; -#endif - /* We restrict the number of twilight points to a reasonable, */ /* heuristic value to avoid slow execution of malformed bytecode. */ num_twilight_points = FT_MAX( 30, @@ -7861,6 +7839,15 @@ Compute_Funcs( exc ); Compute_Round( exc, (FT_Byte)exc->GS.round_state ); + /* These flags cancel execution of some opcodes after IUP is called */ +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + exc->iup_called = FALSE; +#endif +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + exc->iupx_called = FALSE; + exc->iupy_called = FALSE; +#endif + do { exc->opcode = exc->code[exc->IP]; diff --git a/thirdparty/freetype/src/truetype/ttinterp.h b/thirdparty/freetype/src/truetype/ttinterp.h index 9c01ec83cb..48f618dc9d 100644 --- a/thirdparty/freetype/src/truetype/ttinterp.h +++ b/thirdparty/freetype/src/truetype/ttinterp.h @@ -4,7 +4,7 @@ * * TrueType bytecode interpreter (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/truetype/ttobjs.c b/thirdparty/freetype/src/truetype/ttobjs.c index 93fc548447..f4f3c69336 100644 --- a/thirdparty/freetype/src/truetype/ttobjs.c +++ b/thirdparty/freetype/src/truetype/ttobjs.c @@ -4,7 +4,7 @@ * * Objects manager (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -727,7 +727,8 @@ if ( error ) goto Exit; - if ( FT_IS_SCALABLE( ttface ) ) + if ( FT_IS_SCALABLE( ttface ) || + FT_HAS_SBIX( ttface ) ) { #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( !ttface->internal->incremental_interface ) @@ -1435,6 +1436,8 @@ size->ttmetrics.y_ratio = 0x10000L; } + size->widthp = tt_face_get_device_metrics( face, size_metrics->x_ppem, 0 ); + size->metrics = size_metrics; #ifdef TT_USE_BYTECODE_INTERPRETER diff --git a/thirdparty/freetype/src/truetype/ttobjs.h b/thirdparty/freetype/src/truetype/ttobjs.h index fd72378721..5fa239d43a 100644 --- a/thirdparty/freetype/src/truetype/ttobjs.h +++ b/thirdparty/freetype/src/truetype/ttobjs.h @@ -4,7 +4,7 @@ * * Objects manager (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -282,6 +282,8 @@ FT_BEGIN_HEADER TT_Size_Metrics ttmetrics; + FT_Byte* widthp; /* glyph widths from the hdmx table */ + FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */ #ifdef TT_USE_BYTECODE_INTERPRETER diff --git a/thirdparty/freetype/src/truetype/ttpload.c b/thirdparty/freetype/src/truetype/ttpload.c index 71db75ae1f..6982c717ab 100644 --- a/thirdparty/freetype/src/truetype/ttpload.c +++ b/thirdparty/freetype/src/truetype/ttpload.c @@ -4,7 +4,7 @@ * * TrueType-specific tables loader (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -498,6 +498,14 @@ } + FT_COMPARE_DEF( int ) + compare_ppem( const void* a, + const void* b ) + { + return **(FT_Byte**)a - **(FT_Byte**)b; + } + + /************************************************************************** * * @Function: @@ -574,20 +582,21 @@ goto Fail; } - if ( FT_QNEW_ARRAY( face->hdmx_record_sizes, num_records ) ) + if ( FT_QNEW_ARRAY( face->hdmx_records, num_records ) ) goto Fail; - /* XXX: We do not check if the records are sorted by ppem */ - /* and cannot use binary search later. */ for ( nn = 0; nn < num_records; nn++ ) { if ( p + record_size > limit ) break; - - face->hdmx_record_sizes[nn] = p[0]; - p += record_size; + face->hdmx_records[nn] = p; + p += record_size; } + /* The records must be already sorted by ppem but it does not */ + /* hurt to make sure so that the binary search works later. */ + ft_qsort( face->hdmx_records, nn, sizeof ( FT_Byte* ), compare_ppem ); + face->hdmx_record_count = nn; face->hdmx_table_size = table_size; face->hdmx_record_size = record_size; @@ -611,7 +620,7 @@ FT_Memory memory = stream->memory; - FT_FREE( face->hdmx_record_sizes ); + FT_FREE( face->hdmx_records ); FT_FRAME_RELEASE( face->hdmx_table ); } @@ -619,27 +628,34 @@ /************************************************************************** * * Return the advance width table for a given pixel size if it is found - * in the font's `hdmx' table (if any). + * in the font's `hdmx' table (if any). The records must be sorted for + * the binary search to work properly. */ FT_LOCAL_DEF( FT_Byte* ) tt_face_get_device_metrics( TT_Face face, FT_UInt ppem, FT_UInt gindex ) { - FT_UInt nn; - FT_Byte* result = NULL; - FT_ULong record_size = face->hdmx_record_size; - FT_Byte* record = FT_OFFSET( face->hdmx_table, 8 ); + FT_UInt min = 0; + FT_UInt max = face->hdmx_record_count; + FT_UInt mid; + FT_Byte* result = NULL; + + while ( min < max ) + { + mid = ( min + max ) >> 1; - for ( nn = 0; nn < face->hdmx_record_count; nn++ ) - if ( face->hdmx_record_sizes[nn] == ppem ) + if ( face->hdmx_records[mid][0] > ppem ) + max = mid; + else if ( face->hdmx_records[mid][0] < ppem ) + min = mid + 1; + else { - gindex += 2; - if ( gindex < record_size ) - result = record + nn * record_size + gindex; + result = face->hdmx_records[mid] + 2 + gindex; break; } + } return result; } diff --git a/thirdparty/freetype/src/truetype/ttpload.h b/thirdparty/freetype/src/truetype/ttpload.h index 84c42cdaf4..fa5d96ed35 100644 --- a/thirdparty/freetype/src/truetype/ttpload.h +++ b/thirdparty/freetype/src/truetype/ttpload.h @@ -4,7 +4,7 @@ * * TrueType-specific tables loader (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/truetype/ttsubpix.c b/thirdparty/freetype/src/truetype/ttsubpix.c index c484665b95..2438d3a2a2 100644 --- a/thirdparty/freetype/src/truetype/ttsubpix.c +++ b/thirdparty/freetype/src/truetype/ttsubpix.c @@ -4,7 +4,7 @@ * * TrueType Subpixel Hinting. * - * Copyright (C) 2010-2021 by + * Copyright (C) 2010-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/truetype/ttsubpix.h b/thirdparty/freetype/src/truetype/ttsubpix.h index 762b7c98a3..181f83810c 100644 --- a/thirdparty/freetype/src/truetype/ttsubpix.h +++ b/thirdparty/freetype/src/truetype/ttsubpix.h @@ -4,7 +4,7 @@ * * TrueType Subpixel Hinting. * - * Copyright (C) 2010-2021 by + * Copyright (C) 2010-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1afm.c b/thirdparty/freetype/src/type1/t1afm.c index 4c18ed1955..6009e9ee2e 100644 --- a/thirdparty/freetype/src/type1/t1afm.c +++ b/thirdparty/freetype/src/type1/t1afm.c @@ -4,7 +4,7 @@ * * AFM support for Type 1 fonts (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -203,7 +203,7 @@ kp->index1 = FT_Get_Char_Index( t1_face, p[0] ); kp->index2 = FT_Get_Char_Index( t1_face, p[1] ); - kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2); + kp->x = (FT_Int)FT_PEEK_SHORT_LE( p + 2 ); kp->y = 0; kp++; diff --git a/thirdparty/freetype/src/type1/t1afm.h b/thirdparty/freetype/src/type1/t1afm.h index 86fe45ea3e..040ed68298 100644 --- a/thirdparty/freetype/src/type1/t1afm.h +++ b/thirdparty/freetype/src/type1/t1afm.h @@ -4,7 +4,7 @@ * * AFM support for Type 1 fonts (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1driver.c b/thirdparty/freetype/src/type1/t1driver.c index f4d7a089ae..dd31545cf6 100644 --- a/thirdparty/freetype/src/type1/t1driver.c +++ b/thirdparty/freetype/src/type1/t1driver.c @@ -4,7 +4,7 @@ * * Type 1 driver interface (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1driver.h b/thirdparty/freetype/src/type1/t1driver.h index 20a827f898..9fe1940334 100644 --- a/thirdparty/freetype/src/type1/t1driver.h +++ b/thirdparty/freetype/src/type1/t1driver.h @@ -4,7 +4,7 @@ * * High-level Type 1 driver interface (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1errors.h b/thirdparty/freetype/src/type1/t1errors.h index 18ef75452b..1b87c42f18 100644 --- a/thirdparty/freetype/src/type1/t1errors.h +++ b/thirdparty/freetype/src/type1/t1errors.h @@ -4,7 +4,7 @@ * * Type 1 error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1gload.c b/thirdparty/freetype/src/type1/t1gload.c index 86649edf3a..540231561c 100644 --- a/thirdparty/freetype/src/type1/t1gload.c +++ b/thirdparty/freetype/src/type1/t1gload.c @@ -4,7 +4,7 @@ * * Type 1 Glyph Loader (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1gload.h b/thirdparty/freetype/src/type1/t1gload.h index a924d551a9..fdb985264f 100644 --- a/thirdparty/freetype/src/type1/t1gload.h +++ b/thirdparty/freetype/src/type1/t1gload.h @@ -4,7 +4,7 @@ * * Type 1 Glyph Loader (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1load.c b/thirdparty/freetype/src/type1/t1load.c index bb62c79902..66bebd560f 100644 --- a/thirdparty/freetype/src/type1/t1load.c +++ b/thirdparty/freetype/src/type1/t1load.c @@ -4,7 +4,7 @@ * * Type 1 font loader (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -1530,8 +1530,8 @@ /* we use a T1_Table to store our charnames */ loader->num_chars = encode->num_chars = array_size; - if ( FT_NEW_ARRAY( encode->char_index, array_size ) || - FT_NEW_ARRAY( encode->char_name, array_size ) || + if ( FT_QNEW_ARRAY( encode->char_index, array_size ) || + FT_QNEW_ARRAY( encode->char_name, array_size ) || FT_SET_ERROR( psaux->ps_table_funcs->init( char_table, array_size, memory ) ) ) { @@ -1772,7 +1772,7 @@ if ( !loader->subrs_hash ) { - if ( FT_NEW( loader->subrs_hash ) ) + if ( FT_QNEW( loader->subrs_hash ) ) goto Fail; error = ft_hash_num_init( loader->subrs_hash, memory ); @@ -2057,9 +2057,9 @@ name_table->elements[n][len] = '\0'; /* record index of /.notdef */ - if ( *cur == '.' && + if ( *cur == '.' && ft_strcmp( ".notdef", - (const char*)(name_table->elements[n]) ) == 0 ) + (const char*)( name_table->elements[n] ) ) == 0 ) { notdef_index = n; notdef_found = 1; @@ -2331,8 +2331,8 @@ /* in valid Type 1 fonts we don't see `RD' or `-|' directly */ /* since those tokens are handled by parse_subrs and */ /* parse_charstrings */ - else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' && - have_integer ) + else if ( *cur == 'R' && cur + 6 < limit && *( cur + 1 ) == 'D' && + have_integer ) { FT_ULong s; FT_Byte* b; @@ -2344,8 +2344,8 @@ have_integer = 0; } - else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' && - have_integer ) + else if ( *cur == '-' && cur + 6 < limit && *( cur + 1 ) == '|' && + have_integer ) { FT_ULong s; FT_Byte* b; diff --git a/thirdparty/freetype/src/type1/t1load.h b/thirdparty/freetype/src/type1/t1load.h index ba19adb147..a6d46eb1e4 100644 --- a/thirdparty/freetype/src/type1/t1load.h +++ b/thirdparty/freetype/src/type1/t1load.h @@ -4,7 +4,7 @@ * * Type 1 font loader (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1objs.c b/thirdparty/freetype/src/type1/t1objs.c index 50dad038fd..847ae0e64b 100644 --- a/thirdparty/freetype/src/type1/t1objs.c +++ b/thirdparty/freetype/src/type1/t1objs.c @@ -4,7 +4,7 @@ * * Type 1 objects manager (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1objs.h b/thirdparty/freetype/src/type1/t1objs.h index 5f103b5066..e632fb58bd 100644 --- a/thirdparty/freetype/src/type1/t1objs.h +++ b/thirdparty/freetype/src/type1/t1objs.h @@ -4,7 +4,7 @@ * * Type 1 objects manager (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1parse.c b/thirdparty/freetype/src/type1/t1parse.c index 9f226296a9..95dc97d79a 100644 --- a/thirdparty/freetype/src/type1/t1parse.c +++ b/thirdparty/freetype/src/type1/t1parse.c @@ -4,7 +4,7 @@ * * Type 1 parser (body). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1parse.h b/thirdparty/freetype/src/type1/t1parse.h index 247ff73b2c..d9c7e3b56a 100644 --- a/thirdparty/freetype/src/type1/t1parse.h +++ b/thirdparty/freetype/src/type1/t1parse.h @@ -4,7 +4,7 @@ * * Type 1 parser (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/t1tokens.h b/thirdparty/freetype/src/type1/t1tokens.h index 13ac8ac1c7..79080d9e4d 100644 --- a/thirdparty/freetype/src/type1/t1tokens.h +++ b/thirdparty/freetype/src/type1/t1tokens.h @@ -4,7 +4,7 @@ * * Type 1 tokenizer (specification). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type1/type1.c b/thirdparty/freetype/src/type1/type1.c index 003b78cb86..6f11249288 100644 --- a/thirdparty/freetype/src/type1/type1.c +++ b/thirdparty/freetype/src/type1/type1.c @@ -4,7 +4,7 @@ * * FreeType Type 1 driver component (body only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type42/t42drivr.c b/thirdparty/freetype/src/type42/t42drivr.c index e74ba1deba..45d8c3821b 100644 --- a/thirdparty/freetype/src/type42/t42drivr.c +++ b/thirdparty/freetype/src/type42/t42drivr.c @@ -4,7 +4,7 @@ * * High-level Type 42 driver interface (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, @@ -150,22 +150,13 @@ } - static FT_Error - t42_ps_get_font_private( FT_Face face, - PS_PrivateRec* afont_private ) - { - *afont_private = ((T42_Face)face)->type1.private_dict; - - return FT_Err_Ok; - } - - static const FT_Service_PsInfoRec t42_service_ps_info = { (PS_GetFontInfoFunc) t42_ps_get_font_info, /* ps_get_font_info */ (PS_GetFontExtraFunc) t42_ps_get_font_extra, /* ps_get_font_extra */ (PS_HasGlyphNamesFunc) t42_ps_has_glyph_names, /* ps_has_glyph_names */ - (PS_GetFontPrivateFunc)t42_ps_get_font_private, /* ps_get_font_private */ + /* Type42 fonts don't have a Private dict */ + (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ /* not implemented */ (PS_GetFontValueFunc) NULL /* ps_get_font_value */ }; diff --git a/thirdparty/freetype/src/type42/t42drivr.h b/thirdparty/freetype/src/type42/t42drivr.h index c6d8a4409e..95e1207b68 100644 --- a/thirdparty/freetype/src/type42/t42drivr.h +++ b/thirdparty/freetype/src/type42/t42drivr.h @@ -4,7 +4,7 @@ * * High-level Type 42 driver interface (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type42/t42error.h b/thirdparty/freetype/src/type42/t42error.h index 470f5189a8..b278221006 100644 --- a/thirdparty/freetype/src/type42/t42error.h +++ b/thirdparty/freetype/src/type42/t42error.h @@ -4,7 +4,7 @@ * * Type 42 error codes (specification only). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type42/t42objs.c b/thirdparty/freetype/src/type42/t42objs.c index 03955e945b..da1e0732a0 100644 --- a/thirdparty/freetype/src/type42/t42objs.c +++ b/thirdparty/freetype/src/type42/t42objs.c @@ -4,7 +4,7 @@ * * Type 42 objects manager (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, @@ -44,14 +44,8 @@ parser = &loader.parser; - if ( FT_QALLOC( face->ttf_data, 12 ) ) - goto Exit; - - /* while parsing the font we always update `face->ttf_size' so that */ - /* even in case of buggy data (which might lead to premature end of */ - /* scanning without causing an error) the call to `FT_Open_Face' in */ - /* `T42_Face_Init' passes the correct size */ - face->ttf_size = 12; + face->ttf_data = NULL; + face->ttf_size = 0; error = t42_parser_init( parser, face->root.stream, @@ -152,6 +146,11 @@ Exit: t42_loader_done( &loader ); + if ( error ) + { + FT_FREE( face->ttf_data ); + face->ttf_size = 0; + } return error; } diff --git a/thirdparty/freetype/src/type42/t42objs.h b/thirdparty/freetype/src/type42/t42objs.h index cbd344ffbd..e677996a30 100644 --- a/thirdparty/freetype/src/type42/t42objs.h +++ b/thirdparty/freetype/src/type42/t42objs.h @@ -4,7 +4,7 @@ * * Type 42 objects manager (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type42/t42parse.c b/thirdparty/freetype/src/type42/t42parse.c index ea2c5198a9..59cc519ea6 100644 --- a/thirdparty/freetype/src/type42/t42parse.c +++ b/thirdparty/freetype/src/type42/t42parse.c @@ -4,7 +4,7 @@ * * Type 42 font parser (body). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, @@ -92,7 +92,7 @@ #undef T1CODE #define T1CODE T1_FIELD_LOCATION_BBOX - T1_FIELD_BBOX("FontBBox", xMin, 0 ) + T1_FIELD_BBOX( "FontBBox", xMin, 0 ) T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix, 0 ) T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding, 0 ) @@ -363,8 +363,8 @@ /* we use a T1_Table to store our charnames */ loader->num_chars = encode->num_chars = count; - if ( FT_NEW_ARRAY( encode->char_index, count ) || - FT_NEW_ARRAY( encode->char_name, count ) || + if ( FT_QNEW_ARRAY( encode->char_index, count ) || + FT_QNEW_ARRAY( encode->char_name, count ) || FT_SET_ERROR( psaux->ps_table_funcs->init( char_table, count, memory ) ) ) { @@ -538,7 +538,8 @@ FT_Byte* limit = parser->root.limit; FT_Error error; FT_Int num_tables = 0; - FT_Long count; + FT_Long ttf_count; + FT_Long ttf_reserved; FT_ULong n, string_size, old_string_size, real_size; FT_Byte* string_buf = NULL; @@ -546,6 +547,9 @@ T42_Load_Status status; + /** There should only be one sfnts array, but free any previous. */ + FT_FREE( face->ttf_data ); + face->ttf_size = 0; /* The format is */ /* */ @@ -574,7 +578,10 @@ status = BEFORE_START; string_size = 0; old_string_size = 0; - count = 0; + ttf_count = 0; + ttf_reserved = 12; + if ( FT_QALLOC( face->ttf_data, ttf_reserved ) ) + goto Fail; FT_TRACE2(( "\n" )); FT_TRACE2(( "t42_parse_sfnts:\n" )); @@ -589,6 +596,7 @@ if ( *cur == ']' ) { parser->root.cursor++; + face->ttf_size = ttf_count; goto Exit; } @@ -684,7 +692,7 @@ } FT_TRACE2(( " PS string size %5lu bytes, offset 0x%08lx (%lu)\n", - string_size, count, count )); + string_size, ttf_count, ttf_count )); /* The whole TTF is now loaded into `string_buf'. We are */ /* checking its contents while copying it to `ttf_data'. */ @@ -697,43 +705,48 @@ { case BEFORE_START: /* load offset table, 12 bytes */ - if ( count < 12 ) + if ( ttf_count < 12 ) { - face->ttf_data[count++] = string_buf[n]; + face->ttf_data[ttf_count++] = string_buf[n]; continue; } else { - num_tables = 16 * face->ttf_data[4] + face->ttf_data[5]; - status = BEFORE_TABLE_DIR; - face->ttf_size = 12 + 16 * num_tables; + FT_Long ttf_reserved_prev = ttf_reserved; + + + num_tables = 16 * face->ttf_data[4] + face->ttf_data[5]; + status = BEFORE_TABLE_DIR; + ttf_reserved = 12 + 16 * num_tables; FT_TRACE2(( " SFNT directory contains %d tables\n", num_tables )); - if ( (FT_Long)size < face->ttf_size ) + if ( (FT_Long)size < ttf_reserved ) { FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array\n" )); error = FT_THROW( Invalid_File_Format ); goto Fail; } - if ( FT_QREALLOC( face->ttf_data, 12, face->ttf_size ) ) + if ( FT_QREALLOC( face->ttf_data, ttf_reserved_prev, + ttf_reserved ) ) goto Fail; } /* fall through */ case BEFORE_TABLE_DIR: /* the offset table is read; read the table directory */ - if ( count < face->ttf_size ) + if ( ttf_count < ttf_reserved ) { - face->ttf_data[count++] = string_buf[n]; + face->ttf_data[ttf_count++] = string_buf[n]; continue; } else { int i; FT_ULong len; + FT_Long ttf_reserved_prev = ttf_reserved; FT_TRACE2(( "\n" )); @@ -749,7 +762,7 @@ FT_TRACE2(( " %4i 0x%08lx (%lu)\n", i, len, len )); if ( len > size || - face->ttf_size > (FT_Long)( size - len ) ) + ttf_reserved > (FT_Long)( size - len ) ) { FT_ERROR(( "t42_parse_sfnts:" " invalid data in sfnts array\n" )); @@ -758,30 +771,31 @@ } /* Pad to a 4-byte boundary length */ - face->ttf_size += (FT_Long)( ( len + 3 ) & ~3U ); + ttf_reserved += (FT_Long)( ( len + 3 ) & ~3U ); } + ttf_reserved += 1; status = OTHER_TABLES; FT_TRACE2(( "\n" )); - FT_TRACE2(( " allocating %ld bytes\n", face->ttf_size + 1 )); + FT_TRACE2(( " allocating %ld bytes\n", ttf_reserved )); FT_TRACE2(( "\n" )); - if ( FT_QREALLOC( face->ttf_data, 12 + 16 * num_tables, - face->ttf_size + 1 ) ) + if ( FT_QREALLOC( face->ttf_data, ttf_reserved_prev, + ttf_reserved ) ) goto Fail; } /* fall through */ case OTHER_TABLES: /* all other tables are just copied */ - if ( count >= face->ttf_size ) + if ( ttf_count >= ttf_reserved ) { FT_ERROR(( "t42_parse_sfnts: too much binary data\n" )); error = FT_THROW( Invalid_File_Format ); goto Fail; } - face->ttf_data[count++] = string_buf[n]; + face->ttf_data[ttf_count++] = string_buf[n]; } } @@ -795,6 +809,11 @@ parser->root.error = error; Exit: + if ( parser->root.error ) + { + FT_FREE( face->ttf_data ); + face->ttf_size = 0; + } if ( allocated ) FT_FREE( string_buf ); } @@ -989,9 +1008,9 @@ name_table->elements[n][len] = '\0'; /* record index of /.notdef */ - if ( *cur == '.' && + if ( *cur == '.' && ft_strcmp( ".notdef", - (const char*)(name_table->elements[n]) ) == 0 ) + (const char*)( name_table->elements[n] ) ) == 0 ) { notdef_index = n; notdef_found = 1; diff --git a/thirdparty/freetype/src/type42/t42parse.h b/thirdparty/freetype/src/type42/t42parse.h index 0fbd2b5e0b..fa633e7f1e 100644 --- a/thirdparty/freetype/src/type42/t42parse.h +++ b/thirdparty/freetype/src/type42/t42parse.h @@ -4,7 +4,7 @@ * * Type 42 font parser (specification). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type42/t42types.h b/thirdparty/freetype/src/type42/t42types.h index ea2f03e893..985bdfda98 100644 --- a/thirdparty/freetype/src/type42/t42types.h +++ b/thirdparty/freetype/src/type42/t42types.h @@ -4,7 +4,7 @@ * * Type 42 font data types (specification only). * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/type42/type42.c b/thirdparty/freetype/src/type42/type42.c index d8d3936bdf..ccf5d472b8 100644 --- a/thirdparty/freetype/src/type42/type42.c +++ b/thirdparty/freetype/src/type42/type42.c @@ -4,7 +4,7 @@ * * FreeType Type 42 driver component. * - * Copyright (C) 2002-2021 by + * Copyright (C) 2002-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/winfonts/fnterrs.h b/thirdparty/freetype/src/winfonts/fnterrs.h index d582a9b99c..10564e107f 100644 --- a/thirdparty/freetype/src/winfonts/fnterrs.h +++ b/thirdparty/freetype/src/winfonts/fnterrs.h @@ -4,7 +4,7 @@ * * Win FNT/FON error codes (specification only). * - * Copyright (C) 2001-2021 by + * Copyright (C) 2001-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/thirdparty/freetype/src/winfonts/winfnt.c b/thirdparty/freetype/src/winfonts/winfnt.c index b4fabad283..8afd6be6e9 100644 --- a/thirdparty/freetype/src/winfonts/winfnt.c +++ b/thirdparty/freetype/src/winfonts/winfnt.c @@ -4,7 +4,7 @@ * * FreeType font driver for Windows FNT/FON files * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * Copyright 2003 Huw D M Davies for Codeweavers * Copyright 2007 Dmitry Timoshkov for Codeweavers @@ -352,6 +352,10 @@ count = FT_GET_USHORT_LE(); + FT_TRACE2(( type_id == 0x8007U ? "RT_FONTDIR count %hu\n" : + type_id == 0x8008U ? "RT_FONT count %hu\n" : "", + count )); + if ( type_id == 0x8008U ) { font_count = count; @@ -485,7 +489,7 @@ &dir_entry1 ) ) goto Exit; - if ( !(dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ ) + if ( !( dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ ) { error = FT_THROW( Invalid_File_Format ); goto Exit; @@ -509,7 +513,7 @@ &dir_entry2 ) ) goto Exit; - if ( !(dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ ) + if ( !( dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ ) { error = FT_THROW( Invalid_File_Format ); goto Exit; diff --git a/thirdparty/freetype/src/winfonts/winfnt.h b/thirdparty/freetype/src/winfonts/winfnt.h index a7134abd9c..7e6f5915e7 100644 --- a/thirdparty/freetype/src/winfonts/winfnt.h +++ b/thirdparty/freetype/src/winfonts/winfnt.h @@ -4,7 +4,7 @@ * * FreeType font driver for Windows FNT/FON files * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2022 by * David Turner, Robert Wilhelm, and Werner Lemberg. * Copyright 2007 Dmitry Timoshkov for Codeweavers * diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh index 2f99510925..b77c1f4d44 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh @@ -1038,12 +1038,12 @@ struct Chain goto skip; if (reverse) - _hb_ot_layout_reverse_graphemes (c->buffer); + c->buffer->reverse (); subtable->apply (c); if (reverse) - _hb_ot_layout_reverse_graphemes (c->buffer); + c->buffer->reverse (); (void) c->buffer->message (c->font, "end chainsubtable %d", c->lookup_index); diff --git a/thirdparty/harfbuzz/src/hb-blob.cc b/thirdparty/harfbuzz/src/hb-blob.cc index f120002d17..65e44c7f6a 100644 --- a/thirdparty/harfbuzz/src/hb-blob.cc +++ b/thirdparty/harfbuzz/src/hb-blob.cc @@ -631,7 +631,7 @@ hb_blob_create_from_file_or_fail (const char *file_name) Allison Lortie permission but changed a lot to suit our need. */ #if defined(HAVE_MMAP) && !defined(HB_NO_MMAP) hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t)); - if (unlikely (!file)) return hb_blob_get_empty (); + if (unlikely (!file)) return nullptr; int fd = open (file_name, O_RDONLY | O_BINARY, 0); if (unlikely (fd == -1)) goto fail_without_close; @@ -671,7 +671,7 @@ fail_without_close: #elif defined(_WIN32) && !defined(HB_NO_MMAP) hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t)); - if (unlikely (!file)) return hb_blob_get_empty (); + if (unlikely (!file)) return nullptr; HANDLE fd; unsigned int size = strlen (file_name) + 1; diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh index 3faa1e53d5..56e8c5b006 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh @@ -1415,11 +1415,6 @@ static inline void apply_lookup (hb_ot_apply_context_t *c, if (idx >= count) continue; - /* Don't recurse to ourself at same position. - * Note that this test is too naive, it doesn't catch longer loops. */ - if (unlikely (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)) - continue; - unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len (); /* This can happen if earlier recursed lookups deleted many entries. */ @@ -1457,11 +1452,10 @@ static inline void apply_lookup (hb_ot_apply_context_t *c, * NOT the one after it. * * - If buffer length was decreased by n, it does not necessarily - * mean that n match positions where removed, as there might - * have been marks and default-ignorables in the sequence. We - * should instead drop match positions between current-position - * and current-position + n instead. Though, am not sure which - * one is better. Both cases have valid uses. Sigh. + * mean that n match positions where removed, as there recursed-to + * lookup might had a different LookupFlag. Here's a constructed + * case of that: + * https://github.com/harfbuzz/harfbuzz/discussions/3538 * * It should be possible to construct tests for both of these cases. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc index d7ec1632ea..a7d5bf574b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc @@ -110,7 +110,14 @@ collect_features_khmer (hb_ot_shape_planner_t *plan) map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE); map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE); - for (unsigned i = 0; i < KHMER_NUM_FEATURES; i++) + unsigned int i = 0; + for (; i < KHMER_BASIC_FEATURES; i++) + map->add_feature (khmer_features[i]); + + /* https://github.com/harfbuzz/harfbuzz/issues/3531 */ + map->add_gsub_pause (nullptr); + + for (; i < KHMER_NUM_FEATURES; i++) map->add_feature (khmer_features[i]); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc index c7aa80a79a..13beaf4d4c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc @@ -105,8 +105,7 @@ setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_category); HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_position); - /* We cannot setup masks here. We save information about characters - * and setup masks later on in a pause-callback. */ + /* No masks, we just save information about characters. */ unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc index 298cf47786..99aadab3f0 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc @@ -47,6 +47,9 @@ #include "hb-aat-layout.hh" +static inline bool +_hb_codepoint_is_regional_indicator (hb_codepoint_t u) +{ return hb_in_range<hb_codepoint_t> (u, 0x1F1E6u, 0x1F1FFu); } #ifndef HB_NO_AAT_SHAPE static inline bool @@ -504,9 +507,9 @@ hb_set_unicode_props (hb_buffer_t *buffer) } /* Regional_Indicators are hairy as hell... * https://github.com/harfbuzz/harfbuzz/issues/2265 */ - else if (unlikely (i && hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F1E6u, 0x1F1FFu))) + else if (unlikely (i && _hb_codepoint_is_regional_indicator (info[i].codepoint))) { - if (hb_in_range<hb_codepoint_t> (info[i - 1].codepoint, 0x1F1E6u, 0x1F1FFu) && + if (_hb_codepoint_is_regional_indicator (info[i - 1].codepoint) && !_hb_glyph_info_is_continuation (&info[i - 1])) _hb_glyph_info_set_continuation (&info[i]); } @@ -598,24 +601,33 @@ hb_ensure_native_direction (hb_buffer_t *buffer) * direction, so that features like ligatures will work as intended. * * https://github.com/harfbuzz/harfbuzz/issues/501 + * + * Similar thing about Regional_Indicators; They are bidi=L, but Script=Common. + * If they are present in a run of natively-RTL text, they get assigned a script + * with natively RTL direction, which would result in wrong shaping if we + * assign such native RTL direction to them then. Detect that as well. + * + * https://github.com/harfbuzz/harfbuzz/issues/3314 */ if (unlikely (horiz_dir == HB_DIRECTION_RTL && direction == HB_DIRECTION_LTR)) { - bool found_number = false, found_letter = false; + bool found_number = false, found_letter = false, found_ri = false; const auto* info = buffer->info; const auto count = buffer->len; for (unsigned i = 0; i < count; i++) { auto gc = _hb_glyph_info_get_general_category (&info[i]); if (gc == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) - found_number = true; + found_number = true; else if (HB_UNICODE_GENERAL_CATEGORY_IS_LETTER (gc)) { - found_letter = true; - break; + found_letter = true; + break; } + else if (_hb_codepoint_is_regional_indicator (info[i].codepoint)) + found_ri = true; } - if (found_number && !found_letter) + if ((found_number || found_ri) && !found_letter) horiz_dir = HB_DIRECTION_LTR; } diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h index 39fbde45c1..94c73e15bf 100644 --- a/thirdparty/harfbuzz/src/hb-version.h +++ b/thirdparty/harfbuzz/src/hb-version.h @@ -53,14 +53,14 @@ HB_BEGIN_DECLS * * The micro component of the library version available at compile-time. */ -#define HB_VERSION_MICRO 0 +#define HB_VERSION_MICRO 1 /** * HB_VERSION_STRING: * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "4.2.0" +#define HB_VERSION_STRING "4.2.1" /** * HB_VERSION_ATLEAST: diff --git a/thirdparty/icu4c/LICENSE b/thirdparty/icu4c/LICENSE index 970ae074cb..80b587723a 100644 --- a/thirdparty/icu4c/LICENSE +++ b/thirdparty/icu4c/LICENSE @@ -1,6 +1,19 @@ -COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later) +UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE -Copyright © 1991-2020 Unicode, Inc. All rights reserved. +See Terms of Use <https://www.unicode.org/copyright.html> +for definitions of Unicode Inc.’s Data Files and Software. + +NOTICE TO USER: Carefully read the following legal agreement. +BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. +IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +THE DATA FILES OR SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2022 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in https://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining @@ -32,7 +45,7 @@ shall not be used in advertising or otherwise to promote the sale, use or other dealings in these Data Files or Software without prior written authorization of the copyright holder. ---------------------- +---------------------------------------------------------------------- Third-Party Software Licenses @@ -40,7 +53,9 @@ This section contains third-party software notices and/or additional terms for licensed third-party software components included within ICU libraries. -1. ICU License - ICU 1.8.1 to ICU 57.1 +---------------------------------------------------------------------- + +ICU License - ICU 1.8.1 to ICU 57.1 COPYRIGHT AND PERMISSION NOTICE @@ -75,7 +90,9 @@ of the copyright holder. All trademarks and registered trademarks mentioned herein are the property of their respective owners. -2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt) +---------------------------------------------------------------------- + +Chinese/Japanese Word Break Dictionary Data (cjdict.txt) # The Google Chrome software developed by Google is licensed under # the BSD license. Other software included in this distribution is @@ -279,7 +296,9 @@ property of their respective owners. # # ---------------COPYING.ipadic-----END---------------------------------- -3. Lao Word Break Dictionary Data (laodict.txt) +---------------------------------------------------------------------- + +Lao Word Break Dictionary Data (laodict.txt) # Copyright (C) 2016 and later: Unicode, Inc. and others. # License & terms of use: http://www.unicode.org/copyright.html @@ -319,7 +338,9 @@ property of their respective owners. # OF THE POSSIBILITY OF SUCH DAMAGE. # -------------------------------------------------------------------------- -4. Burmese Word Break Dictionary Data (burmesedict.txt) +---------------------------------------------------------------------- + +Burmese Word Break Dictionary Data (burmesedict.txt) # Copyright (c) 2014 International Business Machines Corporation # and others. All Rights Reserved. @@ -359,7 +380,9 @@ property of their respective owners. # SUCH DAMAGE. # -------------------------------------------------------------------------- -5. Time Zone Database +---------------------------------------------------------------------- + +Time Zone Database ICU uses the public domain data and code derived from Time Zone Database for its time zone support. The ownership of the TZ database @@ -382,7 +405,9 @@ Database section 7. # making a contribution to the database or code waives all rights to # future claims in that contribution or in the TZ Database. -6. Google double-conversion +---------------------------------------------------------------------- + +Google double-conversion Copyright 2006-2011, the V8 project authors. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -410,3 +435,85 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- + +File: aclocal.m4 (only for ICU4C) +Section: pkg.m4 - Macros to locate and utilise pkg-config. + + +Copyright © 2004 Scott James Remnant <scott@netsplit.com>. +Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. + +As a special exception to the GNU General Public License, if you +distribute this file as part of a program that contains a +configuration script generated by Autoconf, you may include it under +the same distribution terms that you use for the rest of that +program. + + +(The condition for the exception is fulfilled because +ICU4C includes a configuration script generated by Autoconf, +namely the `configure` script.) + +---------------------------------------------------------------------- + +File: config.guess (only for ICU4C) + + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, see <https://www.gnu.org/licenses/>. + +As a special exception to the GNU General Public License, if you +distribute this file as part of a program that contains a +configuration script generated by Autoconf, you may include it under +the same distribution terms that you use for the rest of that +program. This Exception is an additional permission under section 7 +of the GNU General Public License, version 3 ("GPLv3"). + + +(The condition for the exception is fulfilled because +ICU4C includes a configuration script generated by Autoconf, +namely the `configure` script.) + +---------------------------------------------------------------------- + +File: install-sh (only for ICU4C) + + +Copyright 1991 by the Massachusetts Institute of Technology + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of M.I.T. not be used in advertising or +publicity pertaining to distribution of the software without specific, +written prior permission. M.I.T. makes no representations about the +suitability of this software for any purpose. It is provided "as is" +without express or implied warranty. diff --git a/thirdparty/icu4c/common/brkeng.cpp b/thirdparty/icu4c/common/brkeng.cpp index 52e9c53621..dc9fb99bf1 100644 --- a/thirdparty/icu4c/common/brkeng.cpp +++ b/thirdparty/icu4c/common/brkeng.cpp @@ -79,6 +79,7 @@ UnhandledEngine::findBreaks( UText *text, int32_t /* startPos */, int32_t endPos, UVector32 &/*foundBreaks*/, + UBool /* isPhraseBreaking */, UErrorCode &status) const { if (U_FAILURE(status)) return 0; UChar32 c = utext_current32(text); diff --git a/thirdparty/icu4c/common/brkeng.h b/thirdparty/icu4c/common/brkeng.h index 6843f1cc95..127ba59e18 100644 --- a/thirdparty/icu4c/common/brkeng.h +++ b/thirdparty/icu4c/common/brkeng.h @@ -75,6 +75,7 @@ class LanguageBreakEngine : public UMemory { int32_t startPos, int32_t endPos, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode &status) const = 0; }; @@ -194,6 +195,7 @@ class UnhandledEngine : public LanguageBreakEngine { int32_t startPos, int32_t endPos, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode &status) const override; /** diff --git a/thirdparty/icu4c/common/brkiter.cpp b/thirdparty/icu4c/common/brkiter.cpp index 8b228acf2c..8a1915880e 100644 --- a/thirdparty/icu4c/common/brkiter.cpp +++ b/thirdparty/icu4c/common/brkiter.cpp @@ -30,6 +30,7 @@ #include "unicode/ures.h" #include "unicode/ustring.h" #include "unicode/filteredbrk.h" +#include "bytesinkutil.h" #include "ucln_cmn.h" #include "cstring.h" #include "umutex.h" @@ -115,7 +116,7 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, UErrorCode &st } // Create a RuleBasedBreakIterator - result = new RuleBasedBreakIterator(file, status); + result = new RuleBasedBreakIterator(file, uprv_strstr(type, "phrase") != NULL, status); // If there is a result, set the valid locale and actual locale, and the kind if (U_SUCCESS(status) && result != NULL) { @@ -408,7 +409,6 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) if (U_FAILURE(status)) { return NULL; } - char lbType[kKeyValueLenMax]; BreakIterator *result = NULL; switch (kind) { @@ -428,18 +428,29 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) break; case UBRK_LINE: { + char lb_lw[kKeyValueLenMax]; UTRACE_ENTRY(UTRACE_UBRK_CREATE_LINE); - uprv_strcpy(lbType, "line"); - char lbKeyValue[kKeyValueLenMax] = {0}; + uprv_strcpy(lb_lw, "line"); UErrorCode kvStatus = U_ZERO_ERROR; - int32_t kLen = loc.getKeywordValue("lb", lbKeyValue, kKeyValueLenMax, kvStatus); - if (U_SUCCESS(kvStatus) && kLen > 0 && (uprv_strcmp(lbKeyValue,"strict")==0 || uprv_strcmp(lbKeyValue,"normal")==0 || uprv_strcmp(lbKeyValue,"loose")==0)) { - uprv_strcat(lbType, "_"); - uprv_strcat(lbType, lbKeyValue); + CharString value; + CharStringByteSink valueSink(&value); + loc.getKeywordValue("lb", valueSink, kvStatus); + if (U_SUCCESS(kvStatus) && (value == "strict" || value == "normal" || value == "loose")) { + uprv_strcat(lb_lw, "_"); + uprv_strcat(lb_lw, value.data()); } - result = BreakIterator::buildInstance(loc, lbType, status); + // lw=phrase is only supported in Japanese. + if (uprv_strcmp(loc.getLanguage(), "ja") == 0) { + value.clear(); + loc.getKeywordValue("lw", valueSink, kvStatus); + if (U_SUCCESS(kvStatus) && value == "phrase") { + uprv_strcat(lb_lw, "_"); + uprv_strcat(lb_lw, value.data()); + } + } + result = BreakIterator::buildInstance(loc, lb_lw, status); - UTRACE_DATA1(UTRACE_INFO, "lb=%s", lbKeyValue); + UTRACE_DATA1(UTRACE_INFO, "lb_lw=%s", lb_lw); UTRACE_EXIT_STATUS(status); } break; diff --git a/thirdparty/icu4c/common/dictbe.cpp b/thirdparty/icu4c/common/dictbe.cpp index 4d158e3226..4fdbdf2760 100644 --- a/thirdparty/icu4c/common/dictbe.cpp +++ b/thirdparty/icu4c/common/dictbe.cpp @@ -17,7 +17,10 @@ #include "dictbe.h" #include "unicode/uniset.h" #include "unicode/chariter.h" +#include "unicode/resbund.h" #include "unicode/ubrk.h" +#include "unicode/usetiter.h" +#include "ubrkimpl.h" #include "utracimp.h" #include "uvectr32.h" #include "uvector.h" @@ -48,6 +51,7 @@ DictionaryBreakEngine::findBreaks( UText *text, int32_t startPos, int32_t endPos, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const { if (U_FAILURE(status)) return 0; (void)startPos; // TODO: remove this param? @@ -68,7 +72,7 @@ DictionaryBreakEngine::findBreaks( UText *text, } rangeStart = start; rangeEnd = current; - result = divideUpDictionaryRange(text, rangeStart, rangeEnd, foundBreaks, status); + result = divideUpDictionaryRange(text, rangeStart, rangeEnd, foundBreaks, isPhraseBreaking, status); utext_setNativeIndex(text, current); return result; @@ -199,13 +203,13 @@ ThaiBreakEngine::ThaiBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode { UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Thai"); - fThaiWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Thai:]&[:LineBreak=SA:]]"), status); + UnicodeSet thaiWordSet(UnicodeString(u"[[:Thai:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { - setCharacters(fThaiWordSet); + setCharacters(thaiWordSet); } - fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Thai:]&[:LineBreak=SA:]&[:M:]]"), status); + fMarkSet.applyPattern(UnicodeString(u"[[:Thai:]&[:LineBreak=SA:]&[:M:]]"), status); fMarkSet.add(0x0020); - fEndWordSet = fThaiWordSet; + fEndWordSet = thaiWordSet; fEndWordSet.remove(0x0E31); // MAI HAN-AKAT fEndWordSet.remove(0x0E40, 0x0E44); // SARA E through SARA AI MAIMALAI fBeginWordSet.add(0x0E01, 0x0E2E); // KO KAI through HO NOKHUK @@ -230,6 +234,7 @@ ThaiBreakEngine::divideUpDictionaryRange( UText *text, int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, UErrorCode& status) const { if (U_FAILURE(status)) return 0; utext_setNativeIndex(text, rangeStart); @@ -441,13 +446,13 @@ LaoBreakEngine::LaoBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode &s { UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Laoo"); - fLaoWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Laoo:]&[:LineBreak=SA:]]"), status); + UnicodeSet laoWordSet(UnicodeString(u"[[:Laoo:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { - setCharacters(fLaoWordSet); + setCharacters(laoWordSet); } - fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Laoo:]&[:LineBreak=SA:]&[:M:]]"), status); + fMarkSet.applyPattern(UnicodeString(u"[[:Laoo:]&[:LineBreak=SA:]&[:M:]]"), status); fMarkSet.add(0x0020); - fEndWordSet = fLaoWordSet; + fEndWordSet = laoWordSet; fEndWordSet.remove(0x0EC0, 0x0EC4); // prefix vowels fBeginWordSet.add(0x0E81, 0x0EAE); // basic consonants (including holes for corresponding Thai characters) fBeginWordSet.add(0x0EDC, 0x0EDD); // digraph consonants (no Thai equivalent) @@ -469,6 +474,7 @@ LaoBreakEngine::divideUpDictionaryRange( UText *text, int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, UErrorCode& status) const { if (U_FAILURE(status)) return 0; if ((rangeEnd - rangeStart) < LAO_MIN_WORD_SPAN) { @@ -637,14 +643,13 @@ BurmeseBreakEngine::BurmeseBreakEngine(DictionaryMatcher *adoptDictionary, UErro { UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Mymr"); - fBurmeseWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Mymr:]&[:LineBreak=SA:]]"), status); + fBeginWordSet.add(0x1000, 0x102A); // basic consonants and independent vowels + fEndWordSet.applyPattern(UnicodeString(u"[[:Mymr:]&[:LineBreak=SA:]]"), status); + fMarkSet.applyPattern(UnicodeString(u"[[:Mymr:]&[:LineBreak=SA:]&[:M:]]"), status); + fMarkSet.add(0x0020); if (U_SUCCESS(status)) { - setCharacters(fBurmeseWordSet); + setCharacters(fEndWordSet); } - fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Mymr:]&[:LineBreak=SA:]&[:M:]]"), status); - fMarkSet.add(0x0020); - fEndWordSet = fBurmeseWordSet; - fBeginWordSet.add(0x1000, 0x102A); // basic consonants and independent vowels // Compact for caching. fMarkSet.compact(); @@ -662,6 +667,7 @@ BurmeseBreakEngine::divideUpDictionaryRange( UText *text, int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, UErrorCode& status ) const { if (U_FAILURE(status)) return 0; if ((rangeEnd - rangeStart) < BURMESE_MIN_WORD_SPAN) { @@ -830,13 +836,13 @@ KhmerBreakEngine::KhmerBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCod { UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Khmr"); - fKhmerWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Khmr:]&[:LineBreak=SA:]]"), status); + UnicodeSet khmerWordSet(UnicodeString(u"[[:Khmr:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { - setCharacters(fKhmerWordSet); + setCharacters(khmerWordSet); } - fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Khmr:]&[:LineBreak=SA:]&[:M:]]"), status); + fMarkSet.applyPattern(UnicodeString(u"[[:Khmr:]&[:LineBreak=SA:]&[:M:]]"), status); fMarkSet.add(0x0020); - fEndWordSet = fKhmerWordSet; + fEndWordSet = khmerWordSet; fBeginWordSet.add(0x1780, 0x17B3); //fBeginWordSet.add(0x17A3, 0x17A4); // deprecated vowels //fEndWordSet.remove(0x17A5, 0x17A9); // Khmer independent vowels that can't end a word @@ -867,6 +873,7 @@ KhmerBreakEngine::divideUpDictionaryRange( UText *text, int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, UErrorCode& status ) const { if (U_FAILURE(status)) return 0; if ((rangeEnd - rangeStart) < KHMER_MIN_WORD_SPAN) { @@ -1050,25 +1057,27 @@ CjkBreakEngine::CjkBreakEngine(DictionaryMatcher *adoptDictionary, LanguageType : DictionaryBreakEngine(), fDictionary(adoptDictionary) { UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Hani"); - // Korean dictionary only includes Hangul syllables - fHangulWordSet.applyPattern(UNICODE_STRING_SIMPLE("[\\uac00-\\ud7a3]"), status); - fHanWordSet.applyPattern(UNICODE_STRING_SIMPLE("[:Han:]"), status); - fKatakanaWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Katakana:]\\uff9e\\uff9f]"), status); - fHiraganaWordSet.applyPattern(UNICODE_STRING_SIMPLE("[:Hiragana:]"), status); nfkcNorm2 = Normalizer2::getNFKCInstance(status); - - if (U_SUCCESS(status)) { - // handle Korean and Japanese/Chinese using different dictionaries - if (type == kKorean) { + // Korean dictionary only includes Hangul syllables + fHangulWordSet.applyPattern(UnicodeString(u"[\\uac00-\\ud7a3]"), status); + fHangulWordSet.compact(); + // Digits, open puncutation and Alphabetic characters. + fDigitOrOpenPunctuationOrAlphabetSet.applyPattern( + UnicodeString(u"[[:Nd:][:Pi:][:Ps:][:Alphabetic:]]"), status); + fDigitOrOpenPunctuationOrAlphabetSet.compact(); + fClosePunctuationSet.applyPattern(UnicodeString(u"[[:Pc:][:Pd:][:Pe:][:Pf:][:Po:]]"), status); + fClosePunctuationSet.compact(); + + // handle Korean and Japanese/Chinese using different dictionaries + if (type == kKorean) { + if (U_SUCCESS(status)) { setCharacters(fHangulWordSet); - } else { //Chinese and Japanese - UnicodeSet cjSet; - cjSet.addAll(fHanWordSet); - cjSet.addAll(fKatakanaWordSet); - cjSet.addAll(fHiraganaWordSet); - cjSet.add(0xFF70); // HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK - cjSet.add(0x30FC); // KATAKANA-HIRAGANA PROLONGED SOUND MARK + } + } else { //Chinese and Japanese + UnicodeSet cjSet(UnicodeString(u"[[:Han:][:Hiragana:][:Katakana:]\\u30fc\\uff70\\uff9e\\uff9f]"), status); + if (U_SUCCESS(status)) { setCharacters(cjSet); + initJapanesePhraseParameter(status); } } UTRACE_EXIT_STATUS(status); @@ -1096,14 +1105,12 @@ static inline bool isKatakana(UChar32 value) { (value >= 0xFF66 && value <= 0xFF9f); } - // Function for accessing internal utext flags. // Replicates an internal UText function. static inline int32_t utext_i32_flag(int32_t bitIndex) { return (int32_t)1 << bitIndex; } - /* * @param text A UText representing the text @@ -1117,6 +1124,7 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const { if (U_FAILURE(status)) return 0; if (rangeStart >= rangeEnd) { @@ -1347,6 +1355,31 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, if ((uint32_t)bestSnlp.elementAti(numCodePts) == kuint32max) { t_boundary.addElement(numCodePts, status); numBreaks++; + } else if (isPhraseBreaking) { + t_boundary.addElement(numCodePts, status); + if(U_SUCCESS(status)) { + numBreaks++; + int32_t prevIdx = numCodePts; + + int32_t codeUnitIdx = -1; + int32_t prevCodeUnitIdx = -1; + int32_t length = -1; + for (int32_t i = prev.elementAti(numCodePts); i > 0; i = prev.elementAti(i)) { + codeUnitIdx = inString.moveIndex32(0, i); + prevCodeUnitIdx = inString.moveIndex32(0, prevIdx); + // Calculate the length by using the code unit. + length = prevCodeUnitIdx - codeUnitIdx; + prevIdx = i; + // Keep the breakpoint if the pattern is not in the fSkipSet and continuous Katakana + // characters don't occur. + if (!fSkipSet.containsKey(inString.tempSubString(codeUnitIdx, length)) + && (!isKatakana(inString.char32At(inString.moveIndex32(codeUnitIdx, -1))) + || !isKatakana(inString.char32At(codeUnitIdx)))) { + t_boundary.addElement(i, status); + numBreaks++; + } + } + } } else { for (int32_t i = numCodePts; i > 0; i = prev.elementAti(i)) { t_boundary.addElement(i, status); @@ -1367,7 +1400,8 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, // while reversing t_boundary and pushing values to foundBreaks. int32_t prevCPPos = -1; int32_t prevUTextPos = -1; - for (int32_t i = numBreaks-1; i >= 0; i--) { + int32_t correctedNumBreaks = 0; + for (int32_t i = numBreaks - 1; i >= 0; i--) { int32_t cpPos = t_boundary.elementAti(i); U_ASSERT(cpPos > prevCPPos); int32_t utextPos = inputMap.isValid() ? inputMap->elementAti(cpPos) : cpPos + rangeStart; @@ -1375,7 +1409,15 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, if (utextPos > prevUTextPos) { // Boundaries are added to foundBreaks output in ascending order. U_ASSERT(foundBreaks.size() == 0 || foundBreaks.peeki() < utextPos); - foundBreaks.push(utextPos, status); + // In phrase breaking, there has to be a breakpoint between Cj character and close + // punctuation. + // E.g.[携帯電話]正しい選択 -> [携帯▁電話]▁正しい▁選択 -> breakpoint between ] and 正 + if (utextPos != rangeStart + || (isPhraseBreaking && utextPos > 0 + && fClosePunctuationSet.contains(utext_char32At(inText, utextPos - 1)))) { + foundBreaks.push(utextPos, status); + correctedNumBreaks++; + } } else { // Normalization expanded the input text, the dictionary found a boundary // within the expansion, giving two boundaries with the same index in the @@ -1387,9 +1429,52 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, } (void)prevCPPos; // suppress compiler warnings about unused variable + UChar32 nextChar = utext_char32At(inText, rangeEnd); + if (!foundBreaks.isEmpty() && foundBreaks.peeki() == rangeEnd) { + // In phrase breaking, there has to be a breakpoint between Cj character and + // the number/open punctuation. + // E.g. る文字「そうだ、京都」->る▁文字▁「そうだ、▁京都」-> breakpoint between 字 and「 + // E.g. 乗車率90%程度だろうか -> 乗車▁率▁90%▁程度だろうか -> breakpoint between 率 and 9 + // E.g. しかもロゴがUnicode! -> しかも▁ロゴが▁Unicode!-> breakpoint between が and U + if (isPhraseBreaking) { + if (!fDigitOrOpenPunctuationOrAlphabetSet.contains(nextChar)) { + foundBreaks.popi(); + correctedNumBreaks--; + } + } else { + foundBreaks.popi(); + correctedNumBreaks--; + } + } + // inString goes out of scope // inputMap goes out of scope - return numBreaks; + return correctedNumBreaks; +} + +void CjkBreakEngine::initJapanesePhraseParameter(UErrorCode& error) { + loadJapaneseExtensions(error); + loadHiragana(error); +} + +void CjkBreakEngine::loadJapaneseExtensions(UErrorCode& error) { + const char* tag = "extensions"; + ResourceBundle ja(U_ICUDATA_BRKITR, "ja", error); + if (U_SUCCESS(error)) { + ResourceBundle bundle = ja.get(tag, error); + while (U_SUCCESS(error) && bundle.hasNext()) { + fSkipSet.puti(bundle.getNextString(error), 1, error); + } + } +} + +void CjkBreakEngine::loadHiragana(UErrorCode& error) { + UnicodeSet hiraganaWordSet(UnicodeString(u"[:Hiragana:]"), error); + hiraganaWordSet.compact(); + UnicodeSetIterator iterator(hiraganaWordSet); + while (iterator.next()) { + fSkipSet.puti(UnicodeString(iterator.getCodepoint()), 1, error); + } } #endif diff --git a/thirdparty/icu4c/common/dictbe.h b/thirdparty/icu4c/common/dictbe.h index 4e70ed3817..ca1a3c28b7 100644 --- a/thirdparty/icu4c/common/dictbe.h +++ b/thirdparty/icu4c/common/dictbe.h @@ -15,6 +15,7 @@ #include "unicode/utext.h" #include "brkeng.h" +#include "hash.h" #include "uvectr32.h" U_NAMESPACE_BEGIN @@ -80,6 +81,7 @@ class DictionaryBreakEngine : public LanguageBreakEngine { int32_t startPos, int32_t endPos, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status ) const override; protected: @@ -105,6 +107,7 @@ class DictionaryBreakEngine : public LanguageBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const = 0; }; @@ -127,7 +130,6 @@ class ThaiBreakEngine : public DictionaryBreakEngine { * @internal */ - UnicodeSet fThaiWordSet; UnicodeSet fEndWordSet; UnicodeSet fBeginWordSet; UnicodeSet fSuffixSet; @@ -164,6 +166,7 @@ class ThaiBreakEngine : public DictionaryBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; }; @@ -186,7 +189,6 @@ class LaoBreakEngine : public DictionaryBreakEngine { * @internal */ - UnicodeSet fLaoWordSet; UnicodeSet fEndWordSet; UnicodeSet fBeginWordSet; UnicodeSet fMarkSet; @@ -222,6 +224,7 @@ class LaoBreakEngine : public DictionaryBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; }; @@ -244,7 +247,6 @@ class BurmeseBreakEngine : public DictionaryBreakEngine { * @internal */ - UnicodeSet fBurmeseWordSet; UnicodeSet fEndWordSet; UnicodeSet fBeginWordSet; UnicodeSet fMarkSet; @@ -280,6 +282,7 @@ class BurmeseBreakEngine : public DictionaryBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; }; @@ -302,7 +305,6 @@ class KhmerBreakEngine : public DictionaryBreakEngine { * @internal */ - UnicodeSet fKhmerWordSet; UnicodeSet fEndWordSet; UnicodeSet fBeginWordSet; UnicodeSet fMarkSet; @@ -338,6 +340,7 @@ class KhmerBreakEngine : public DictionaryBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; }; @@ -366,13 +369,22 @@ class CjkBreakEngine : public DictionaryBreakEngine { * @internal */ UnicodeSet fHangulWordSet; - UnicodeSet fHanWordSet; - UnicodeSet fKatakanaWordSet; - UnicodeSet fHiraganaWordSet; + UnicodeSet fDigitOrOpenPunctuationOrAlphabetSet; + UnicodeSet fClosePunctuationSet; DictionaryMatcher *fDictionary; const Normalizer2 *nfkcNorm2; + private: + // Load Japanese extensions. + void loadJapaneseExtensions(UErrorCode& error); + // Load Japanese Hiragana. + void loadHiragana(UErrorCode& error); + // Initialize fSkipSet by loading Japanese Hiragana and extensions. + void initJapanesePhraseParameter(UErrorCode& error); + + Hashtable fSkipSet; + public: /** @@ -404,6 +416,7 @@ class CjkBreakEngine : public DictionaryBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; }; diff --git a/thirdparty/icu4c/common/localematcher.cpp b/thirdparty/icu4c/common/localematcher.cpp index 3d178dfbaf..2cad708d99 100644 --- a/thirdparty/icu4c/common/localematcher.cpp +++ b/thirdparty/icu4c/common/localematcher.cpp @@ -168,12 +168,9 @@ void LocaleMatcher::Builder::clearSupportedLocales() { bool LocaleMatcher::Builder::ensureSupportedLocaleVector() { if (U_FAILURE(errorCode_)) { return false; } if (supportedLocales_ != nullptr) { return true; } - supportedLocales_ = new UVector(uprv_deleteUObject, nullptr, errorCode_); + LocalPointer<UVector> lpSupportedLocales(new UVector(uprv_deleteUObject, nullptr, errorCode_), errorCode_); if (U_FAILURE(errorCode_)) { return false; } - if (supportedLocales_ == nullptr) { - errorCode_ = U_MEMORY_ALLOCATION_ERROR; - return false; - } + supportedLocales_ = lpSupportedLocales.orphan(); return true; } @@ -187,9 +184,8 @@ LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocalesFromListStrin for (int32_t i = 0; i < length; ++i) { Locale *locale = list.orphanLocaleAt(i); if (locale == nullptr) { continue; } - supportedLocales_->addElementX(locale, errorCode_); + supportedLocales_->adoptElement(locale, errorCode_); if (U_FAILURE(errorCode_)) { - delete locale; break; } } @@ -197,35 +193,21 @@ LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocalesFromListStrin } LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocales(Locale::Iterator &locales) { - if (U_FAILURE(errorCode_)) { return *this; } - clearSupportedLocales(); - if (!ensureSupportedLocaleVector()) { return *this; } - while (locales.hasNext()) { - const Locale &locale = locales.next(); - Locale *clone = locale.clone(); - if (clone == nullptr) { - errorCode_ = U_MEMORY_ALLOCATION_ERROR; - break; - } - supportedLocales_->addElementX(clone, errorCode_); - if (U_FAILURE(errorCode_)) { - delete clone; - break; + if (ensureSupportedLocaleVector()) { + clearSupportedLocales(); + while (locales.hasNext() && U_SUCCESS(errorCode_)) { + const Locale &locale = locales.next(); + LocalPointer<Locale> clone (locale.clone(), errorCode_); + supportedLocales_->adoptElement(clone.orphan(), errorCode_); } } return *this; } LocaleMatcher::Builder &LocaleMatcher::Builder::addSupportedLocale(const Locale &locale) { - if (!ensureSupportedLocaleVector()) { return *this; } - Locale *clone = locale.clone(); - if (clone == nullptr) { - errorCode_ = U_MEMORY_ALLOCATION_ERROR; - return *this; - } - supportedLocales_->addElementX(clone, errorCode_); - if (U_FAILURE(errorCode_)) { - delete clone; + if (ensureSupportedLocaleVector()) { + LocalPointer<Locale> clone(locale.clone(), errorCode_); + supportedLocales_->adoptElement(clone.orphan(), errorCode_); } return *this; } diff --git a/thirdparty/icu4c/common/locid.cpp b/thirdparty/icu4c/common/locid.cpp index e8859c7048..73bb8d8aec 100644 --- a/thirdparty/icu4c/common/locid.cpp +++ b/thirdparty/icu4c/common/locid.cpp @@ -1204,14 +1204,11 @@ AliasReplacer::parseLanguageReplacement( // We have multiple field so we have to allocate and parse CharString* str = new CharString( replacement, (int32_t)uprv_strlen(replacement), status); + LocalPointer<CharString> lpStr(str, status); + toBeFreed.adoptElement(lpStr.orphan(), status); if (U_FAILURE(status)) { return; } - if (str == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - toBeFreed.addElementX(str, status); char* data = str->data(); replacedLanguage = (const char*) data; char* endOfField = uprv_strchr(data, '_'); @@ -1420,12 +1417,9 @@ AliasReplacer::replaceTerritory(UVector& toBeFreed, UErrorCode& status) (int32_t)(firstSpace - replacement), status), status); } if (U_FAILURE(status)) { return false; } - if (item.isNull()) { - status = U_MEMORY_ALLOCATION_ERROR; - return false; - } replacedRegion = item->data(); - toBeFreed.addElementX(item.orphan(), status); + toBeFreed.adoptElement(item.orphan(), status); + if (U_FAILURE(status)) { return false; } } U_ASSERT(!same(region, replacedRegion)); region = replacedRegion; @@ -1659,10 +1653,10 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status while ((end = uprv_strchr(start, SEP_CHAR)) != nullptr && U_SUCCESS(status)) { *end = NULL_CHAR; // null terminate inside variantsBuff - variants.addElementX(start, status); + variants.addElement(start, status); start = end + 1; } - variants.addElementX(start, status); + variants.addElement(start, status); } if (U_FAILURE(status)) { return false; } diff --git a/thirdparty/icu4c/common/lstmbe.cpp b/thirdparty/icu4c/common/lstmbe.cpp index 3793abceb3..f6114cdfe2 100644 --- a/thirdparty/icu4c/common/lstmbe.cpp +++ b/thirdparty/icu4c/common/lstmbe.cpp @@ -1,8 +1,8 @@ // © 2021 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html +#include <complex> #include <utility> -#include <ctgmath> #include "unicode/utypes.h" @@ -639,6 +639,7 @@ LSTMBreakEngine::divideUpDictionaryRange( UText *text, int32_t startPos, int32_t endPos, UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, UErrorCode& status) const { if (U_FAILURE(status)) return 0; int32_t beginFoundBreakSize = foundBreaks.size(); diff --git a/thirdparty/icu4c/common/lstmbe.h b/thirdparty/icu4c/common/lstmbe.h index c3f7ecf815..ffdf805eca 100644 --- a/thirdparty/icu4c/common/lstmbe.h +++ b/thirdparty/icu4c/common/lstmbe.h @@ -62,6 +62,7 @@ protected: int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; private: const LSTMData* fData; diff --git a/thirdparty/icu4c/common/normalizer2impl.cpp b/thirdparty/icu4c/common/normalizer2impl.cpp index 5bfd49e8cb..e6bd75e717 100644 --- a/thirdparty/icu4c/common/normalizer2impl.cpp +++ b/thirdparty/icu4c/common/normalizer2impl.cpp @@ -2496,15 +2496,18 @@ void CanonIterData::addToStartSet(UChar32 origin, UChar32 decompLead, UErrorCode // origin is not the first character, or it is U+0000. UnicodeSet *set; if((canonValue&CANON_HAS_SET)==0) { - set=new UnicodeSet; - if(set==NULL) { - errorCode=U_MEMORY_ALLOCATION_ERROR; + LocalPointer<UnicodeSet> lpSet(new UnicodeSet, errorCode); + set=lpSet.getAlias(); + if(U_FAILURE(errorCode)) { return; } UChar32 firstOrigin=(UChar32)(canonValue&CANON_VALUE_MASK); canonValue=(canonValue&~CANON_VALUE_MASK)|CANON_HAS_SET|(uint32_t)canonStartSets.size(); umutablecptrie_set(mutableTrie, decompLead, canonValue, &errorCode); - canonStartSets.addElementX(set, errorCode); + canonStartSets.adoptElement(lpSet.orphan(), errorCode); + if (U_FAILURE(errorCode)) { + return; + } if(firstOrigin!=0) { set->add(firstOrigin); } diff --git a/thirdparty/icu4c/common/rbbi.cpp b/thirdparty/icu4c/common/rbbi.cpp index f65177f232..cae8d154b3 100644 --- a/thirdparty/icu4c/common/rbbi.cpp +++ b/thirdparty/icu4c/common/rbbi.cpp @@ -82,6 +82,19 @@ RuleBasedBreakIterator::RuleBasedBreakIterator(RBBIDataHeader* data, UErrorCode } } +//------------------------------------------------------------------------------- +// +// Constructor from a UDataMemory handle to precompiled break rules +// stored in an ICU data file. This construcotr is private API, +// only for internal use. +// +//------------------------------------------------------------------------------- +RuleBasedBreakIterator::RuleBasedBreakIterator(UDataMemory* udm, UBool isPhraseBreaking, + UErrorCode &status) : RuleBasedBreakIterator(udm, status) +{ + fIsPhraseBreaking = isPhraseBreaking; +} + // // Construct from precompiled binary rules (tables). This constructor is public API, // taking the rules as a (const uint8_t *) to match the type produced by getBinaryRules(). @@ -322,6 +335,7 @@ void RuleBasedBreakIterator::init(UErrorCode &status) { fBreakCache = nullptr; fDictionaryCache = nullptr; fLookAheadMatches = nullptr; + fIsPhraseBreaking = false; // Note: IBM xlC is unable to assign or initialize member fText from UTEXT_INITIALIZER. // fText = UTEXT_INITIALIZER; diff --git a/thirdparty/icu4c/common/rbbi_cache.cpp b/thirdparty/icu4c/common/rbbi_cache.cpp index 6bfe3feca4..26d82df781 100644 --- a/thirdparty/icu4c/common/rbbi_cache.cpp +++ b/thirdparty/icu4c/common/rbbi_cache.cpp @@ -163,7 +163,7 @@ void RuleBasedBreakIterator::DictionaryCache::populateDictionary(int32_t startPo // Ask the language object if there are any breaks. It will add them to the cache and // leave the text pointer on the other side of its range, ready to search for the next one. if (lbe != NULL) { - foundBreakCount += lbe->findBreaks(text, rangeStart, rangeEnd, fBreaks, status); + foundBreakCount += lbe->findBreaks(text, rangeStart, rangeEnd, fBreaks, fBI->fIsPhraseBreaking, status); } // Reload the loop variables for the next go-round diff --git a/thirdparty/icu4c/common/serv.cpp b/thirdparty/icu4c/common/serv.cpp index 0c54a4dce9..c26dbca1a9 100644 --- a/thirdparty/icu4c/common/serv.cpp +++ b/thirdparty/icu4c/common/serv.cpp @@ -625,10 +625,7 @@ ICUService::getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorC } } - LocalPointer<UnicodeString> idClone(new UnicodeString(*id), status); - if (U_SUCCESS(status) && idClone->isBogus()) { - status = U_MEMORY_ALLOCATION_ERROR; - } + LocalPointer<UnicodeString> idClone(id->clone(), status); result.adoptElement(idClone.orphan(), status); } delete fallbackKey; diff --git a/thirdparty/icu4c/common/servls.cpp b/thirdparty/icu4c/common/servls.cpp index 7108afd4a5..98f0a8a12b 100644 --- a/thirdparty/icu4c/common/servls.cpp +++ b/thirdparty/icu4c/common/servls.cpp @@ -179,7 +179,8 @@ private: length = other._ids.size(); for(i = 0; i < length; ++i) { - _ids.addElementX(((UnicodeString *)other._ids.elementAt(i))->clone(), status); + LocalPointer<UnicodeString> clonedId(((UnicodeString *)other._ids.elementAt(i))->clone(), status); + _ids.adoptElement(clonedId.orphan(), status); } if(U_SUCCESS(status)) { diff --git a/thirdparty/icu4c/common/servnotf.cpp b/thirdparty/icu4c/common/servnotf.cpp index 342e0d9f24..d9fb388752 100644 --- a/thirdparty/icu4c/common/servnotf.cpp +++ b/thirdparty/icu4c/common/servnotf.cpp @@ -49,7 +49,11 @@ ICUNotifier::addListener(const EventListener* l, UErrorCode& status) if (acceptsListener(*l)) { Mutex lmx(¬ifyLock); if (listeners == NULL) { - listeners = new UVector(5, status); + LocalPointer<UVector> lpListeners(new UVector(5, status), status); + if (U_FAILURE(status)) { + return; + } + listeners = lpListeners.orphan(); } else { for (int i = 0, e = listeners->size(); i < e; ++i) { const EventListener* el = (const EventListener*)(listeners->elementAt(i)); @@ -59,7 +63,7 @@ ICUNotifier::addListener(const EventListener* l, UErrorCode& status) } } - listeners->addElementX((void*)l, status); // cast away const + listeners->addElement((void*)l, status); // cast away const } #ifdef NOTIFIER_DEBUG else { @@ -102,13 +106,11 @@ ICUNotifier::removeListener(const EventListener *l, UErrorCode& status) void ICUNotifier::notifyChanged(void) { + Mutex lmx(¬ifyLock); if (listeners != NULL) { - Mutex lmx(¬ifyLock); - if (listeners != NULL) { - for (int i = 0, e = listeners->size(); i < e; ++i) { - EventListener* el = (EventListener*)listeners->elementAt(i); - notifyListener(*el); - } + for (int i = 0, e = listeners->size(); i < e; ++i) { + EventListener* el = (EventListener*)listeners->elementAt(i); + notifyListener(*el); } } } diff --git a/thirdparty/icu4c/common/ubrk.cpp b/thirdparty/icu4c/common/ubrk.cpp index bb5bdd1b50..f4e064961f 100644 --- a/thirdparty/icu4c/common/ubrk.cpp +++ b/thirdparty/icu4c/common/ubrk.cpp @@ -168,7 +168,7 @@ ubrk_safeClone( BreakIterator *newBI = ((BreakIterator *)bi)->clone(); if (newBI == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; - } else { + } else if (pBufferSize != NULL) { *status = U_SAFECLONE_ALLOCATED_WARNING; } return (UBreakIterator *)newBI; @@ -176,15 +176,7 @@ ubrk_safeClone( U_CAPI UBreakIterator * U_EXPORT2 ubrk_clone(const UBreakIterator *bi, UErrorCode *status) { - if (U_FAILURE(*status)) { - return nullptr; - } - BreakIterator *newBI = ((BreakIterator *)bi)->clone(); - if (newBI == nullptr) { - *status = U_MEMORY_ALLOCATION_ERROR; - return nullptr; - } - return (UBreakIterator *)newBI; + return ubrk_safeClone(bi, nullptr, nullptr, status); } diff --git a/thirdparty/icu4c/common/ucase.cpp b/thirdparty/icu4c/common/ucase.cpp index 4aa856507a..388c86b1bb 100644 --- a/thirdparty/icu4c/common/ucase.cpp +++ b/thirdparty/icu4c/common/ucase.cpp @@ -22,27 +22,14 @@ #include "unicode/utypes.h" #include "unicode/unistr.h" #include "unicode/uset.h" -#include "unicode/udata.h" /* UDataInfo */ #include "unicode/utf16.h" -#include "ucmndata.h" /* DataHeader */ -#include "udatamem.h" -#include "umutex.h" -#include "uassert.h" #include "cmemory.h" -#include "utrie2.h" +#include "uassert.h" #include "ucase.h" +#include "umutex.h" +#include "utrie2.h" -struct UCaseProps { - UDataMemory *mem; - const int32_t *indexes; - const uint16_t *exceptions; - const uint16_t *unfold; - - UTrie2 trie; - uint8_t formatVersion[4]; -}; - -/* ucase_props_data.h is machine-generated by gencase --csource */ +/* ucase_props_data.h is machine-generated by genprops/casepropsbuilder.cpp */ #define INCLUDED_FROM_UCASE_CPP #include "ucase_props_data.h" @@ -77,6 +64,13 @@ ucase_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode) { /* data access primitives --------------------------------------------------- */ +U_CAPI const struct UCaseProps * U_EXPORT2 +ucase_getSingleton(int32_t *pExceptionsLength, int32_t *pUnfoldLength) { + *pExceptionsLength = UPRV_LENGTHOF(ucase_props_exceptions); + *pUnfoldLength = UPRV_LENGTHOF(ucase_props_unfold); + return &ucase_props_singleton; +} + U_CFUNC const UTrie2 * U_EXPORT2 ucase_getTrie() { return &ucase_props_singleton.trie; @@ -690,7 +684,7 @@ ucase_isCaseSensitive(UChar32 c) { * - The general category of C is * Nonspacing Mark (Mn), or Enclosing Mark (Me), or Format Control (Cf), or * Letter Modifier (Lm), or Symbol Modifier (Sk) - * - C is one of the following characters + * - C is one of the following characters * U+0027 APOSTROPHE * U+00AD SOFT HYPHEN (SHY) * U+2019 RIGHT SINGLE QUOTATION MARK @@ -1064,6 +1058,8 @@ ucase_toFullLower(UChar32 c, // The sign of the result has meaning, input must be non-negative so that it can be returned as is. U_ASSERT(c >= 0); UChar32 result=c; + // Reset the output pointer in case it was uninitialized. + *pString=nullptr; uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c); if(!UCASE_HAS_EXCEPTION(props)) { if(UCASE_IS_UPPER_OR_TITLE(props)) { @@ -1148,7 +1144,6 @@ ucase_toFullLower(UChar32 c, 0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE 0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE */ - *pString=nullptr; return 0; /* remove the dot (continue without output) */ } else if(loc==UCASE_LOC_TURKISH && c==0x49 && !isFollowedByDotAbove(iter, context)) { /* @@ -1215,6 +1210,8 @@ toUpperOrTitle(UChar32 c, // The sign of the result has meaning, input must be non-negative so that it can be returned as is. U_ASSERT(c >= 0); UChar32 result=c; + // Reset the output pointer in case it was uninitialized. + *pString=nullptr; uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c); if(!UCASE_HAS_EXCEPTION(props)) { if(UCASE_GET_TYPE(props)==UCASE_LOWER) { @@ -1252,7 +1249,6 @@ toUpperOrTitle(UChar32 c, 0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE */ - *pString=nullptr; return 0; /* remove the dot (continue without output) */ } else if(c==0x0587) { // See ICU-13416: @@ -1449,6 +1445,8 @@ ucase_toFullFolding(UChar32 c, // The sign of the result has meaning, input must be non-negative so that it can be returned as is. U_ASSERT(c >= 0); UChar32 result=c; + // Reset the output pointer in case it was uninitialized. + *pString=nullptr; uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c); if(!UCASE_HAS_EXCEPTION(props)) { if(UCASE_IS_UPPER_OR_TITLE(props)) { @@ -1542,7 +1540,7 @@ U_CAPI UChar32 U_EXPORT2 u_tolower(UChar32 c) { return ucase_tolower(c); } - + /* Transforms the Unicode character to its upper case equivalent.*/ U_CAPI UChar32 U_EXPORT2 u_toupper(UChar32 c) { diff --git a/thirdparty/icu4c/common/ucase.h b/thirdparty/icu4c/common/ucase.h index a018f82b81..7bf57fd370 100644 --- a/thirdparty/icu4c/common/ucase.h +++ b/thirdparty/icu4c/common/ucase.h @@ -312,6 +312,21 @@ UCaseMapFull(UChar32 c, U_CDECL_END +/* for icuexportdata -------------------------------------------------------- */ + +struct UCaseProps { + void *mem; // TODO: was unused, and type UDataMemory -- remove + const int32_t *indexes; + const uint16_t *exceptions; + const uint16_t *unfold; + + UTrie2 trie; + uint8_t formatVersion[4]; +}; + +U_CAPI const struct UCaseProps * U_EXPORT2 +ucase_getSingleton(int32_t *pExceptionsLength, int32_t *pUnfoldLength); + /* file definitions --------------------------------------------------------- */ #define UCASE_DATA_NAME "ucase" diff --git a/thirdparty/icu4c/common/ucasemap.cpp b/thirdparty/icu4c/common/ucasemap.cpp index ed72bda828..95b55d56a0 100644 --- a/thirdparty/icu4c/common/ucasemap.cpp +++ b/thirdparty/icu4c/common/ucasemap.cpp @@ -112,8 +112,7 @@ ucasemap_setLocale(UCaseMap *csm, const char *locale, UErrorCode *pErrorCode) { if(length==sizeof(csm->locale)) { *pErrorCode=U_BUFFER_OVERFLOW_ERROR; } - if(U_SUCCESS(*pErrorCode)) { - csm->caseLocale=UCASE_LOC_UNKNOWN; + if(U_SUCCESS(*pErrorCode)) { csm->caseLocale = ucase_getCaseLocale(csm->locale); } else { csm->locale[0]=0; @@ -420,6 +419,97 @@ void toUpper(int32_t caseLocale, uint32_t options, #if !UCONFIG_NO_BREAK_ITERATION +namespace { + +constexpr uint8_t ACUTE_BYTE0 = u8"\u0301"[0]; + +constexpr uint8_t ACUTE_BYTE1 = u8"\u0301"[1]; + +/** + * Input: c is a letter I with or without acute accent. + * start is the index in src after c, and is less than segmentLimit. + * If a plain i/I is followed by a plain j/J, + * or an i/I with acute (precomposed or decomposed) is followed by a j/J with acute, + * then we output accordingly. + * + * @return the src index after the titlecased sequence, or the start index if no Dutch IJ + */ +int32_t maybeTitleDutchIJ(const uint8_t *src, UChar32 c, int32_t start, int32_t segmentLimit, + ByteSink &sink, uint32_t options, icu::Edits *edits, UErrorCode &errorCode) { + U_ASSERT(start < segmentLimit); + + int32_t index = start; + bool withAcute = false; + + // If the conditions are met, then the following variables tell us what to output. + int32_t unchanged1 = 0; // code units before the j, or the whole sequence (0..3) + bool doTitleJ = false; // true if the j needs to be titlecased + int32_t unchanged2 = 0; // after the j (0 or 1) + + // next character after the first letter + UChar32 c2; + c2 = src[index++]; + + // Is the first letter an i/I with accent? + if (c == u'I') { + if (c2 == ACUTE_BYTE0 && index < segmentLimit && src[index++] == ACUTE_BYTE1) { + withAcute = true; + unchanged1 = 2; // ACUTE is 2 code units in UTF-8 + if (index == segmentLimit) { return start; } + c2 = src[index++]; + } + } else { // Í + withAcute = true; + } + + // Is the next character a j/J? + if (c2 == u'j') { + doTitleJ = true; + } else if (c2 == u'J') { + ++unchanged1; + } else { + return start; + } + + // A plain i/I must be followed by a plain j/J. + // An i/I with acute must be followed by a j/J with acute. + if (withAcute) { + if ((index + 1) >= segmentLimit || src[index++] != ACUTE_BYTE0 || src[index++] != ACUTE_BYTE1) { + return start; + } + if (doTitleJ) { + unchanged2 = 2; // ACUTE is 2 code units in UTF-8 + } else { + unchanged1 = unchanged1 + 2; // ACUTE is 2 code units in UTF-8 + } + } + + // There must not be another combining mark. + if (index < segmentLimit) { + int32_t cp; + int32_t i = index; + U8_NEXT(src, i, segmentLimit, cp); + uint32_t typeMask = U_GET_GC_MASK(cp); + if ((typeMask & U_GC_M_MASK) != 0) { + return start; + } + } + + // Output the rest of the Dutch IJ. + ByteSinkUtil::appendUnchanged(src + start, unchanged1, sink, options, edits, errorCode); + start += unchanged1; + if (doTitleJ) { + ByteSinkUtil::appendCodePoint(1, u'J', sink, edits); + ++start; + } + ByteSinkUtil::appendUnchanged(src + start, unchanged2, sink, options, edits, errorCode); + + U_ASSERT(start + unchanged2 == index); + return index; +} + +} // namespace + U_CFUNC void U_CALLCONV ucasemap_internalUTF8ToTitle( int32_t caseLocale, uint32_t options, BreakIterator *iter, @@ -504,19 +594,14 @@ ucasemap_internalUTF8ToTitle( } /* Special case Dutch IJ titlecasing */ - if (titleStart+1 < index && - caseLocale == UCASE_LOC_DUTCH && - (src[titleStart] == 0x0049 || src[titleStart] == 0x0069)) { - if (src[titleStart+1] == 0x006A) { - ByteSinkUtil::appendCodePoint(1, 0x004A, sink, edits); - titleLimit++; - } else if (src[titleStart+1] == 0x004A) { - // Keep the capital J from getting lowercased. - if (!ByteSinkUtil::appendUnchanged(src+titleStart+1, 1, - sink, options, edits, errorCode)) { - return; - } - titleLimit++; + if (titleLimit < index && + caseLocale == UCASE_LOC_DUTCH) { + if (c < 0) { + c = ~c; + } + + if (c == u'I' || c == u'Í') { + titleLimit = maybeTitleDutchIJ(src, c, titleLimit, index, sink, options, edits, errorCode); } } diff --git a/thirdparty/icu4c/common/ucnv.cpp b/thirdparty/icu4c/common/ucnv.cpp index 5dcf35e043..019bcb6a79 100644 --- a/thirdparty/icu4c/common/ucnv.cpp +++ b/thirdparty/icu4c/common/ucnv.cpp @@ -252,7 +252,10 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U UTRACE_EXIT_STATUS(*status); return NULL; } - *status = U_SAFECLONE_ALLOCATED_WARNING; + // If pBufferSize was NULL as the input, pBufferSize is set to &stackBufferSize in this function. + if (pBufferSize != &stackBufferSize) { + *status = U_SAFECLONE_ALLOCATED_WARNING; + } /* record the fact that memory was allocated */ *pBufferSize = bufferSizeNeeded; @@ -317,7 +320,11 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U return localConverter; } - +U_CAPI UConverter* U_EXPORT2 +ucnv_clone(const UConverter* cnv, UErrorCode *status) +{ + return ucnv_safeClone(cnv, nullptr, nullptr, status); +} /*Decreases the reference counter in the shared immutable section of the object *and frees the mutable part*/ diff --git a/thirdparty/icu4c/common/ucurr.cpp b/thirdparty/icu4c/common/ucurr.cpp index 67aab4e8ff..6e489e0563 100644 --- a/thirdparty/icu4c/common/ucurr.cpp +++ b/thirdparty/icu4c/common/ucurr.cpp @@ -254,7 +254,7 @@ currSymbolsEquiv_cleanup(void) } /** - * Deleter for OlsonToMetaMappingEntry + * Deleter for IsoCodeEntry */ static void U_CALLCONV deleteIsoCodeEntry(void *obj) { diff --git a/thirdparty/icu4c/common/uloc.cpp b/thirdparty/icu4c/common/uloc.cpp index c8a3f1ff73..99c6a0af39 100644 --- a/thirdparty/icu4c/common/uloc.cpp +++ b/thirdparty/icu4c/common/uloc.cpp @@ -186,10 +186,10 @@ NULL }; static const char* const DEPRECATED_LANGUAGES[]={ - "in", "iw", "ji", "jw", NULL, NULL + "in", "iw", "ji", "jw", "mo", NULL, NULL }; static const char* const REPLACEMENT_LANGUAGES[]={ - "id", "he", "yi", "jv", NULL, NULL + "id", "he", "yi", "jv", "ro", NULL, NULL }; /** @@ -444,7 +444,7 @@ static const char * const COUNTRIES_3[] = { /* "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", */ "VAT", "VCT", "VEN", "VGB", "VIR", "VNM", "VUT", "WLF", /* "WS", "XK", "YE", "YT", "ZA", "ZM", "ZW", */ - "WSM", "XXK", "YEM", "MYT", "ZAF", "ZMB", "ZWE", + "WSM", "XKK", "YEM", "MYT", "ZAF", "ZMB", "ZWE", NULL, /* "AN", "BU", "CS", "FX", "RO", "SU", "TP", "YD", "YU", "ZR" */ "ANT", "BUR", "SCG", "FXX", "ROM", "SUN", "TMP", "YMD", "YUG", "ZAR", diff --git a/thirdparty/icu4c/common/unicode/localematcher.h b/thirdparty/icu4c/common/unicode/localematcher.h index 252bb7fdc2..0f7e04a3af 100644 --- a/thirdparty/icu4c/common/unicode/localematcher.h +++ b/thirdparty/icu4c/common/unicode/localematcher.h @@ -461,13 +461,13 @@ public: * Option for whether to include or ignore one-way (fallback) match data. * By default, they are included. * - * @param direction the match direction to set. + * @param matchDirection the match direction to set. * @return this Builder object * @stable ICU 67 */ - Builder &setDirection(ULocMatchDirection direction) { + Builder &setDirection(ULocMatchDirection matchDirection) { if (U_SUCCESS(errorCode_)) { - direction_ = direction; + direction_ = matchDirection; } return *this; } diff --git a/thirdparty/icu4c/common/unicode/rbbi.h b/thirdparty/icu4c/common/unicode/rbbi.h index 0ce93819f5..0bad0d3897 100644 --- a/thirdparty/icu4c/common/unicode/rbbi.h +++ b/thirdparty/icu4c/common/unicode/rbbi.h @@ -147,6 +147,11 @@ private: */ int32_t *fLookAheadMatches; + /** + * A flag to indicate if phrase based breaking is enabled. + */ + UBool fIsPhraseBreaking; + //======================================================================= // constructors //======================================================================= @@ -163,6 +168,21 @@ private: */ RuleBasedBreakIterator(RBBIDataHeader* data, UErrorCode &status); + /** + * This constructor uses the udata interface to create a BreakIterator + * whose internal tables live in a memory-mapped file. "image" is an + * ICU UDataMemory handle for the pre-compiled break iterator tables. + * @param image handle to the memory image for the break iterator data. + * Ownership of the UDataMemory handle passes to the Break Iterator, + * which will be responsible for closing it when it is no longer needed. + * @param status Information on any errors encountered. + * @param isPhraseBreaking true if phrase based breaking is required, otherwise false. + * @see udata_open + * @see #getBinaryRules + * @internal (private) + */ + RuleBasedBreakIterator(UDataMemory* image, UBool isPhraseBreaking, UErrorCode &status); + /** @internal */ friend class RBBIRuleBuilder; /** @internal */ diff --git a/thirdparty/icu4c/common/unicode/ubrk.h b/thirdparty/icu4c/common/unicode/ubrk.h index c603f7c13f..2b3dc7aa57 100644 --- a/thirdparty/icu4c/common/unicode/ubrk.h +++ b/thirdparty/icu4c/common/unicode/ubrk.h @@ -312,11 +312,12 @@ ubrk_openBinaryRules(const uint8_t *binaryRules, int32_t rulesLength, * If *pBufferSize is not enough for a stack-based safe clone, * new memory will be allocated. * @param status to indicate whether the operation went on smoothly or there were errors - * An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any allocations were necessary. + * An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used + * if pBufferSize != NULL and any allocations were necessary * @return pointer to the new clone * @deprecated ICU 69 Use ubrk_clone() instead. */ -U_CAPI UBreakIterator * U_EXPORT2 +U_DEPRECATED UBreakIterator * U_EXPORT2 ubrk_safeClone( const UBreakIterator *bi, void *stackBuffer, @@ -325,21 +326,17 @@ ubrk_safeClone( #endif /* U_HIDE_DEPRECATED_API */ -#ifndef U_HIDE_DRAFT_API - /** * Thread safe cloning operation. * @param bi iterator to be cloned * @param status to indicate whether the operation went on smoothly or there were errors * @return pointer to the new clone - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI UBreakIterator * U_EXPORT2 ubrk_clone(const UBreakIterator *bi, UErrorCode *status); -#endif // U_HIDE_DRAFT_API - #ifndef U_HIDE_DEPRECATED_API /** diff --git a/thirdparty/icu4c/common/unicode/ucnv.h b/thirdparty/icu4c/common/unicode/ucnv.h index 2687c984d4..20c173b662 100644 --- a/thirdparty/icu4c/common/unicode/ucnv.h +++ b/thirdparty/icu4c/common/unicode/ucnv.h @@ -477,7 +477,7 @@ ucnv_openCCSID(int32_t codepage, * * <p>The name will NOT be looked up in the alias mechanism, nor will the converter be * stored in the converter cache or the alias table. The only way to open further converters - * is call this function multiple times, or use the ucnv_safeClone() function to clone a + * is call this function multiple times, or use the ucnv_clone() function to clone a * 'primary' converter.</p> * * <p>A future version of ICU may add alias table lookups and/or caching @@ -493,7 +493,7 @@ ucnv_openCCSID(int32_t codepage, * @return the created Unicode converter object, or <TT>NULL</TT> if an error occurred * @see udata_open * @see ucnv_open - * @see ucnv_safeClone + * @see ucnv_clone * @see ucnv_close * @stable ICU 2.2 */ @@ -502,6 +502,20 @@ ucnv_openPackage(const char *packageName, const char *converterName, UErrorCode /** * Thread safe converter cloning operation. + * + * You must ucnv_close() the clone. + * + * @param cnv converter to be cloned + * @param status to indicate whether the operation went on smoothly or there were errors + * @return pointer to the new clone + * @stable ICU 71 + */ +U_CAPI UConverter* U_EXPORT2 ucnv_clone(const UConverter *cnv, UErrorCode *status); + +#ifndef U_HIDE_DEPRECATED_API + +/** + * Thread safe converter cloning operation. * For most efficient operation, pass in a stackBuffer (and a *pBufferSize) * with at least U_CNV_SAFECLONE_BUFFERSIZE bytes of space. * If the buffer size is sufficient, then the clone will use the stack buffer; @@ -532,21 +546,19 @@ ucnv_openPackage(const char *packageName, const char *converterName, UErrorCode * pointer to size of allocated space. * @param status to indicate whether the operation went on smoothly or there were errors * An informational status value, U_SAFECLONE_ALLOCATED_WARNING, - * is used if any allocations were necessary. + * is used if pBufferSize != NULL and any allocations were necessary * However, it is better to check if *pBufferSize grew for checking for * allocations because warning codes can be overridden by subsequent * function calls. * @return pointer to the new clone - * @stable ICU 2.0 + * @deprecated ICU 71 Use ucnv_clone() instead. */ -U_CAPI UConverter * U_EXPORT2 +U_DEPRECATED UConverter * U_EXPORT2 ucnv_safeClone(const UConverter *cnv, void *stackBuffer, int32_t *pBufferSize, UErrorCode *status); -#ifndef U_HIDE_DEPRECATED_API - /** * \def U_CNV_SAFECLONE_BUFFERSIZE * Definition of a buffer size that is designed to be large enough for diff --git a/thirdparty/icu4c/common/unicode/uniset.h b/thirdparty/icu4c/common/unicode/uniset.h index 730337a353..310c7c8d20 100644 --- a/thirdparty/icu4c/common/unicode/uniset.h +++ b/thirdparty/icu4c/common/unicode/uniset.h @@ -1229,7 +1229,6 @@ public: */ UnicodeSet& retain(UChar32 c); -#ifndef U_HIDE_DRAFT_API /** * Retains only the specified string from this set if it is present. * Upon return this set will be empty if it did not contain s, or @@ -1238,10 +1237,9 @@ public: * * @param s the source string * @return this object, for chaining - * @draft ICU 69 + * @stable ICU 69 */ UnicodeSet& retain(const UnicodeString &s); -#endif // U_HIDE_DRAFT_API /** * Removes the specified range from this set if it is present. diff --git a/thirdparty/icu4c/common/unicode/urename.h b/thirdparty/icu4c/common/unicode/urename.h index 4605f632ea..d9f9b8f336 100644 --- a/thirdparty/icu4c/common/unicode/urename.h +++ b/thirdparty/icu4c/common/unicode/urename.h @@ -567,6 +567,7 @@ #define ucase_addStringCaseClosure U_ICU_ENTRY_POINT_RENAME(ucase_addStringCaseClosure) #define ucase_fold U_ICU_ENTRY_POINT_RENAME(ucase_fold) #define ucase_getCaseLocale U_ICU_ENTRY_POINT_RENAME(ucase_getCaseLocale) +#define ucase_getSingleton U_ICU_ENTRY_POINT_RENAME(ucase_getSingleton) #define ucase_getTrie U_ICU_ENTRY_POINT_RENAME(ucase_getTrie) #define ucase_getType U_ICU_ENTRY_POINT_RENAME(ucase_getType) #define ucase_getTypeOrIgnorable U_ICU_ENTRY_POINT_RENAME(ucase_getTypeOrIgnorable) @@ -630,6 +631,7 @@ #define ucnv_cbFromUWriteUChars U_ICU_ENTRY_POINT_RENAME(ucnv_cbFromUWriteUChars) #define ucnv_cbToUWriteSub U_ICU_ENTRY_POINT_RENAME(ucnv_cbToUWriteSub) #define ucnv_cbToUWriteUChars U_ICU_ENTRY_POINT_RENAME(ucnv_cbToUWriteUChars) +#define ucnv_clone U_ICU_ENTRY_POINT_RENAME(ucnv_clone) #define ucnv_close U_ICU_ENTRY_POINT_RENAME(ucnv_close) #define ucnv_compareNames U_ICU_ENTRY_POINT_RENAME(ucnv_compareNames) #define ucnv_convert U_ICU_ENTRY_POINT_RENAME(ucnv_convert) @@ -725,6 +727,7 @@ #define ucnvsel_selectForString U_ICU_ENTRY_POINT_RENAME(ucnvsel_selectForString) #define ucnvsel_selectForUTF8 U_ICU_ENTRY_POINT_RENAME(ucnvsel_selectForUTF8) #define ucnvsel_serialize U_ICU_ENTRY_POINT_RENAME(ucnvsel_serialize) +#define ucol_clone U_ICU_ENTRY_POINT_RENAME(ucol_clone) #define ucol_cloneBinary U_ICU_ENTRY_POINT_RENAME(ucol_cloneBinary) #define ucol_close U_ICU_ENTRY_POINT_RENAME(ucol_close) #define ucol_closeElements U_ICU_ENTRY_POINT_RENAME(ucol_closeElements) @@ -904,6 +907,7 @@ #define udatpg_getBestPattern U_ICU_ENTRY_POINT_RENAME(udatpg_getBestPattern) #define udatpg_getBestPatternWithOptions U_ICU_ENTRY_POINT_RENAME(udatpg_getBestPatternWithOptions) #define udatpg_getDateTimeFormat U_ICU_ENTRY_POINT_RENAME(udatpg_getDateTimeFormat) +#define udatpg_getDateTimeFormatForStyle U_ICU_ENTRY_POINT_RENAME(udatpg_getDateTimeFormatForStyle) #define udatpg_getDecimal U_ICU_ENTRY_POINT_RENAME(udatpg_getDecimal) #define udatpg_getDefaultHourCycle U_ICU_ENTRY_POINT_RENAME(udatpg_getDefaultHourCycle) #define udatpg_getFieldDisplayName U_ICU_ENTRY_POINT_RENAME(udatpg_getFieldDisplayName) @@ -918,6 +922,7 @@ #define udatpg_setAppendItemFormat U_ICU_ENTRY_POINT_RENAME(udatpg_setAppendItemFormat) #define udatpg_setAppendItemName U_ICU_ENTRY_POINT_RENAME(udatpg_setAppendItemName) #define udatpg_setDateTimeFormat U_ICU_ENTRY_POINT_RENAME(udatpg_setDateTimeFormat) +#define udatpg_setDateTimeFormatForStyle U_ICU_ENTRY_POINT_RENAME(udatpg_setDateTimeFormatForStyle) #define udatpg_setDecimal U_ICU_ENTRY_POINT_RENAME(udatpg_setDecimal) #define udict_swap U_ICU_ENTRY_POINT_RENAME(udict_swap) #define udtitvfmt_close U_ICU_ENTRY_POINT_RENAME(udtitvfmt_close) diff --git a/thirdparty/icu4c/common/unicode/uset.h b/thirdparty/icu4c/common/unicode/uset.h index 2ef352ef56..33332f2d36 100644 --- a/thirdparty/icu4c/common/unicode/uset.h +++ b/thirdparty/icu4c/common/unicode/uset.h @@ -628,7 +628,6 @@ uset_removeRange(USet* set, UChar32 start, UChar32 end); U_CAPI void U_EXPORT2 uset_removeString(USet* set, const UChar* str, int32_t strLen); -#ifndef U_HIDE_DRAFT_API /** * Removes EACH of the characters in this string. Note: "ch" == {"c", "h"} * A frozen set will not be modified. @@ -636,11 +635,10 @@ uset_removeString(USet* set, const UChar* str, int32_t strLen); * @param set the object to be modified * @param str the string * @param length the length of the string, or -1 if NUL-terminated - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_removeAllCodePoints(USet *set, const UChar *str, int32_t length); -#endif // U_HIDE_DRAFT_API /** * Removes from this set all of its elements that are contained in the @@ -671,7 +669,6 @@ uset_removeAll(USet* set, const USet* removeSet); U_CAPI void U_EXPORT2 uset_retain(USet* set, UChar32 start, UChar32 end); -#ifndef U_HIDE_DRAFT_API /** * Retains only the specified string from this set if it is present. * Upon return this set will be empty if it did not contain s, or @@ -681,7 +678,7 @@ uset_retain(USet* set, UChar32 start, UChar32 end); * @param set the object to be modified * @param str the string * @param length the length of the string, or -1 if NUL-terminated - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_retainString(USet *set, const UChar *str, int32_t length); @@ -693,11 +690,10 @@ uset_retainString(USet *set, const UChar *str, int32_t length); * @param set the object to be modified * @param str the string * @param length the length of the string, or -1 if NUL-terminated - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_retainAllCodePoints(USet *set, const UChar *str, int32_t length); -#endif // U_HIDE_DRAFT_API /** * Retains only the elements in this set that are contained in the @@ -741,7 +737,6 @@ uset_compact(USet* set); U_CAPI void U_EXPORT2 uset_complement(USet* set); -#ifndef U_HIDE_DRAFT_API /** * Complements the specified range in this set. Any character in * the range will be removed if it is in this set, or will be @@ -753,7 +748,7 @@ uset_complement(USet* set); * @param set the object to be modified * @param start first character, inclusive, of range * @param end last character, inclusive, of range - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_complementRange(USet *set, UChar32 start, UChar32 end); @@ -766,7 +761,7 @@ uset_complementRange(USet *set, UChar32 start, UChar32 end); * @param set the object to be modified * @param str the string * @param length the length of the string, or -1 if NUL-terminated - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_complementString(USet *set, const UChar *str, int32_t length); @@ -778,11 +773,10 @@ uset_complementString(USet *set, const UChar *str, int32_t length); * @param set the object to be modified * @param str the string * @param length the length of the string, or -1 if NUL-terminated - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_complementAllCodePoints(USet *set, const UChar *str, int32_t length); -#endif // U_HIDE_DRAFT_API /** * Complements in this set all elements contained in the specified diff --git a/thirdparty/icu4c/common/unicode/uvernum.h b/thirdparty/icu4c/common/unicode/uvernum.h index 42e8865d7e..2706e0b060 100644 --- a/thirdparty/icu4c/common/unicode/uvernum.h +++ b/thirdparty/icu4c/common/unicode/uvernum.h @@ -60,7 +60,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION_MAJOR_NUM 70 +#define U_ICU_VERSION_MAJOR_NUM 71 /** The current ICU minor version as an integer. * This value will change in the subsequent releases of ICU @@ -86,7 +86,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_SUFFIX _70 +#define U_ICU_VERSION_SUFFIX _71 /** * \def U_DEF2_ICU_ENTRY_POINT_RENAME @@ -139,7 +139,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION "70.1" +#define U_ICU_VERSION "71.1" /** * The current ICU library major version number as a string, for library name suffixes. @@ -152,13 +152,13 @@ * * @stable ICU 2.6 */ -#define U_ICU_VERSION_SHORT "70" +#define U_ICU_VERSION_SHORT "71" #ifndef U_HIDE_INTERNAL_API /** Data version in ICU4C. * @internal ICU 4.4 Internal Use Only **/ -#define U_ICU_DATA_VERSION "70.1" +#define U_ICU_DATA_VERSION "71.1" #endif /* U_HIDE_INTERNAL_API */ /*=========================================================================== diff --git a/thirdparty/icu4c/common/unistr.cpp b/thirdparty/icu4c/common/unistr.cpp index 077b4d6ef2..c18665928d 100644 --- a/thirdparty/icu4c/common/unistr.cpp +++ b/thirdparty/icu4c/common/unistr.cpp @@ -334,7 +334,8 @@ Replaceable::clone() const { // UnicodeString overrides clone() with a real implementation UnicodeString * UnicodeString::clone() const { - return new UnicodeString(*this); + LocalPointer<UnicodeString> clonedString(new UnicodeString(*this)); + return clonedString.isValid() && !clonedString->isBogus() ? clonedString.orphan() : nullptr; } //======================================== @@ -1976,7 +1977,12 @@ The vector deleting destructor is already a part of UObject, but defining it here makes sure that it is included with this object file. This makes sure that static library dependencies are kept to a minimum. */ +#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 1100 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" static void uprv_UnicodeStringDummy(void) { delete [] (new UnicodeString[2]); } +#pragma GCC diagnostic pop +#endif #endif diff --git a/thirdparty/icu4c/common/ustrcase.cpp b/thirdparty/icu4c/common/ustrcase.cpp index 36b19e75f2..43910ea520 100644 --- a/thirdparty/icu4c/common/ustrcase.cpp +++ b/thirdparty/icu4c/common/ustrcase.cpp @@ -36,6 +36,12 @@ #include "ustr_imp.h" #include "uassert.h" +/** + * Code point for COMBINING ACUTE ACCENT + * @internal + */ +#define ACUTE u'\u0301' + U_NAMESPACE_BEGIN namespace { @@ -396,6 +402,94 @@ U_NAMESPACE_USE #if !UCONFIG_NO_BREAK_ITERATION +namespace { + +/** + * Input: c is a letter I with or without acute accent. + * start is the index in src after c, and is less than segmentLimit. + * If a plain i/I is followed by a plain j/J, + * or an i/I with acute (precomposed or decomposed) is followed by a j/J with acute, + * then we output accordingly. + * + * @return the src index after the titlecased sequence, or the start index if no Dutch IJ + */ +int32_t maybeTitleDutchIJ(const UChar *src, UChar32 c, int32_t start, int32_t segmentLimit, + UChar *dest, int32_t &destIndex, int32_t destCapacity, uint32_t options, + icu::Edits *edits) { + U_ASSERT(start < segmentLimit); + + int32_t index = start; + bool withAcute = false; + + // If the conditions are met, then the following variables tell us what to output. + int32_t unchanged1 = 0; // code units before the j, or the whole sequence (0..3) + bool doTitleJ = false; // true if the j needs to be titlecased + int32_t unchanged2 = 0; // after the j (0 or 1) + + // next character after the first letter + UChar c2 = src[index++]; + + // Is the first letter an i/I with accent? + if (c == u'I') { + if (c2 == ACUTE) { + withAcute = true; + unchanged1 = 1; + if (index == segmentLimit) { return start; } + c2 = src[index++]; + } + } else { // Í + withAcute = true; + } + + // Is the next character a j/J? + if (c2 == u'j') { + doTitleJ = true; + } else if (c2 == u'J') { + ++unchanged1; + } else { + return start; + } + + // A plain i/I must be followed by a plain j/J. + // An i/I with acute must be followed by a j/J with acute. + if (withAcute) { + if (index == segmentLimit || src[index++] != ACUTE) { return start; } + if (doTitleJ) { + unchanged2 = 1; + } else { + ++unchanged1; + } + } + + // There must not be another combining mark. + if (index < segmentLimit) { + int32_t cp; + int32_t i = index; + U16_NEXT(src, i, segmentLimit, cp); + uint32_t typeMask = U_GET_GC_MASK(cp); + if ((typeMask & U_GC_M_MASK) != 0) { + return start; + } + } + + // Output the rest of the Dutch IJ. + destIndex = appendUnchanged(dest, destIndex, destCapacity, src + start, unchanged1, options, edits); + start += unchanged1; + if (doTitleJ) { + destIndex = appendUChar(dest, destIndex, destCapacity, u'J'); + if (edits != nullptr) { + edits->addReplace(1, 1); + } + ++start; + } + destIndex = appendUnchanged(dest, destIndex, destCapacity, src + start, unchanged2, options, edits); + + U_ASSERT(start + unchanged2 == index); + return index; +} + +} // namespace + U_CFUNC int32_t U_CALLCONV ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *iter, UChar *dest, int32_t destCapacity, @@ -412,14 +506,14 @@ ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *it csc.limit=srcLength; int32_t destIndex=0; int32_t prev=0; - UBool isFirstIndex=TRUE; + bool isFirstIndex=true; /* titlecasing loop */ while(prev<srcLength) { /* find next index where to titlecase */ int32_t index; if(isFirstIndex) { - isFirstIndex=FALSE; + isFirstIndex=false; index=iter->first(); } else { index=iter->next(); @@ -446,7 +540,7 @@ ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *it // Stop with titleStart<titleLimit<=index // if there is a character to be titlecased, // or else stop with titleStart==titleLimit==index. - UBool toCased = (options&U_TITLECASE_ADJUST_TO_CASED) != 0; + bool toCased = (options&U_TITLECASE_ADJUST_TO_CASED) != 0; while (toCased ? UCASE_NONE==ucase_getType(c) : !ustrcase_isLNS(c)) { titleStart=titleLimit; if(titleLimit==index) { @@ -479,27 +573,15 @@ ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *it /* Special case Dutch IJ titlecasing */ if (titleStart+1 < index && - caseLocale == UCASE_LOC_DUTCH && - (src[titleStart] == 0x0049 || src[titleStart] == 0x0069)) { - if (src[titleStart+1] == 0x006A) { - destIndex=appendUChar(dest, destIndex, destCapacity, 0x004A); - if(destIndex<0) { - errorCode=U_INDEX_OUTOFBOUNDS_ERROR; - return 0; - } - if(edits!=NULL) { - edits->addReplace(1, 1); - } - titleLimit++; - } else if (src[titleStart+1] == 0x004A) { - // Keep the capital J from getting lowercased. - destIndex=appendUnchanged(dest, destIndex, destCapacity, - src+titleStart+1, 1, options, edits); - if(destIndex<0) { - errorCode=U_INDEX_OUTOFBOUNDS_ERROR; - return 0; - } - titleLimit++; + caseLocale == UCASE_LOC_DUTCH) { + if (c < 0) { + c = ~c; + } + + if (c == u'I' || c == u'Í') { + titleLimit = maybeTitleDutchIJ(src, c, titleStart + 1, index, + dest, destIndex, destCapacity, options, + edits); } } diff --git a/thirdparty/icu4c/common/uvector.cpp b/thirdparty/icu4c/common/uvector.cpp index 4da8b864e1..844463921e 100644 --- a/thirdparty/icu4c/common/uvector.cpp +++ b/thirdparty/icu4c/common/uvector.cpp @@ -99,14 +99,6 @@ bool UVector::operator==(const UVector& other) const { return true; } -// TODO: delete this function once all call sites have been migrated to the -// new addElement(). -void UVector::addElementX(void* obj, UErrorCode &status) { - if (ensureCapacityX(count + 1, status)) { - elements[count++].pointer = obj; - } -} - void UVector::addElement(void* obj, UErrorCode &status) { U_ASSERT(deleter == nullptr); if (ensureCapacity(count + 1, status)) { @@ -331,38 +323,6 @@ int32_t UVector::indexOf(UElement key, int32_t startIndex, int8_t hint) const { return -1; } -UBool UVector::ensureCapacityX(int32_t minimumCapacity, UErrorCode &status) { - if (minimumCapacity < 0) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return FALSE; - } - if (capacity < minimumCapacity) { - if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check - status = U_ILLEGAL_ARGUMENT_ERROR; - return FALSE; - } - int32_t newCap = capacity * 2; - if (newCap < minimumCapacity) { - newCap = minimumCapacity; - } - if (newCap > (int32_t)(INT32_MAX / sizeof(UElement))) { // integer overflow check - // We keep the original memory contents on bad minimumCapacity. - status = U_ILLEGAL_ARGUMENT_ERROR; - return FALSE; - } - UElement* newElems = (UElement *)uprv_realloc(elements, sizeof(UElement)*newCap); - if (newElems == nullptr) { - // We keep the original contents on the memory failure on realloc or bad minimumCapacity. - status = U_MEMORY_ALLOCATION_ERROR; - return FALSE; - } - elements = newElems; - capacity = newCap; - } - return TRUE; -} - - UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { if (U_FAILURE(status)) { return false; @@ -370,7 +330,7 @@ UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { if (minimumCapacity < 0) { status = U_ILLEGAL_ARGUMENT_ERROR; return false; - } + } if (capacity < minimumCapacity) { if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check status = U_ILLEGAL_ARGUMENT_ERROR; @@ -396,6 +356,7 @@ UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { } return true; } + /** * Change the size of this vector as follows: If newSize is smaller, * then truncate the array, possibly deleting held elements for i >= diff --git a/thirdparty/icu4c/common/uvector.h b/thirdparty/icu4c/common/uvector.h index f61fcc2be6..1eb7d136e7 100644 --- a/thirdparty/icu4c/common/uvector.h +++ b/thirdparty/icu4c/common/uvector.h @@ -123,12 +123,6 @@ public: // java.util.Vector API //------------------------------------------------------------ - /* - * Old version of addElement, with non-standard error handling. - * Will be removed once all uses have been switched to the new addElement(). - */ - void addElementX(void* obj, UErrorCode &status); - /** * Add an element at the end of the vector. * For use only with vectors that do not adopt their elements, which is to say, @@ -197,12 +191,6 @@ public: inline UBool isEmpty(void) const {return count == 0;} - /* - * Old version of ensureCapacity, with non-standard error handling. - * Will be removed once all uses have been switched to the new ensureCapacity(). - */ - UBool ensureCapacityX(int32_t minimumCapacity, UErrorCode &status); - UBool ensureCapacity(int32_t minimumCapacity, UErrorCode &status); /** diff --git a/thirdparty/icu4c/common/uvectr32.cpp b/thirdparty/icu4c/common/uvectr32.cpp index a77ecb689f..2b4d0b8a75 100644 --- a/thirdparty/icu4c/common/uvectr32.cpp +++ b/thirdparty/icu4c/common/uvectr32.cpp @@ -83,7 +83,7 @@ void UVector32::assign(const UVector32& other, UErrorCode &ec) { } -bool UVector32::operator==(const UVector32& other) { +bool UVector32::operator==(const UVector32& other) const { int32_t i; if (count != other.count) return false; for (i=0; i<count; ++i) { diff --git a/thirdparty/icu4c/common/uvectr32.h b/thirdparty/icu4c/common/uvectr32.h index f08c2ade76..ecefb7af3e 100644 --- a/thirdparty/icu4c/common/uvectr32.h +++ b/thirdparty/icu4c/common/uvectr32.h @@ -86,12 +86,12 @@ public: * equal if they are of the same size and all elements are equal, * as compared using this object's comparer. */ - bool operator==(const UVector32& other); + bool operator==(const UVector32& other) const; /** * Equivalent to !operator==() */ - inline bool operator!=(const UVector32& other); + inline bool operator!=(const UVector32& other) const; //------------------------------------------------------------ // java.util.Vector API @@ -268,7 +268,7 @@ inline int32_t UVector32::lastElementi(void) const { return elementAti(count-1); } -inline bool UVector32::operator!=(const UVector32& other) { +inline bool UVector32::operator!=(const UVector32& other) const { return !operator==(other); } diff --git a/thirdparty/icu4c/icudt70l.dat b/thirdparty/icu4c/icudt71l.dat Binary files differindex 7932bc2ccd..4c2c1c4d16 100644 --- a/thirdparty/icu4c/icudt70l.dat +++ b/thirdparty/icu4c/icudt71l.dat diff --git a/thirdparty/misc/polypartition.cpp b/thirdparty/misc/polypartition.cpp index df144c57a6..a725125ed0 100644 --- a/thirdparty/misc/polypartition.cpp +++ b/thirdparty/misc/polypartition.cpp @@ -1357,12 +1357,12 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto // Note that while set doesn't actually have to be implemented as // a tree, complexity requirements for operations are the same as // for the balanced binary search tree. - Set<ScanLineEdge> edgeTree; + RBSet<ScanLineEdge> edgeTree; // Store iterators to the edge tree elements. // This makes deleting existing edges much faster. - Set<ScanLineEdge>::Element **edgeTreeIterators, *edgeIter; - edgeTreeIterators = new Set<ScanLineEdge>::Element *[maxnumvertices]; - //Pair<Set<ScanLineEdge>::iterator, bool> edgeTreeRet; + RBSet<ScanLineEdge>::Element **edgeTreeIterators, *edgeIter; + edgeTreeIterators = new RBSet<ScanLineEdge>::Element *[maxnumvertices]; + //Pair<RBSet<ScanLineEdge>::iterator, bool> edgeTreeRet; for (i = 0; i < numvertices; i++) { edgeTreeIterators[i] = nullptr; } @@ -1569,8 +1569,8 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto // Adds a diagonal to the doubly-connected list of vertices. void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2, - TPPLVertexType *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators, - Set<ScanLineEdge> *edgeTree, long *helpers) { + TPPLVertexType *vertextypes, RBSet<ScanLineEdge>::Element **edgeTreeIterators, + RBSet<ScanLineEdge> *edgeTree, long *helpers) { long newindex1, newindex2; newindex1 = *numvertices; diff --git a/thirdparty/misc/polypartition.h b/thirdparty/misc/polypartition.h index b2d905a3ef..fae7909079 100644 --- a/thirdparty/misc/polypartition.h +++ b/thirdparty/misc/polypartition.h @@ -26,7 +26,7 @@ #include "core/math/vector2.h" #include "core/templates/list.h" -#include "core/templates/set.h" +#include "core/templates/rb_set.h" typedef double tppl_float; @@ -224,8 +224,8 @@ public: // Helper functions for MonotonePartition. bool Below(TPPLPoint &p1, TPPLPoint &p2); void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2, - TPPLVertexType *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators, - Set<ScanLineEdge> *edgeTree, long *helpers); + TPPLVertexType *vertextypes, RBSet<ScanLineEdge>::Element **edgeTreeIterators, + RBSet<ScanLineEdge> *edgeTree, long *helpers); // Triangulates a monotone polygon, used in Triangulate_MONO. int TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles); diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h index d72574bc65..879b70442b 100644 --- a/thirdparty/thorvg/inc/config.h +++ b/thirdparty/thorvg/inc/config.h @@ -13,5 +13,5 @@ #define THORVG_JPG_LOADER_SUPPORT 1 -#define THORVG_VERSION_STRING "0.8.0" +#define THORVG_VERSION_STRING "0.8.1" #endif diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h index be7042d6de..157fdb8f82 100644 --- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h +++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h @@ -99,9 +99,9 @@ struct SwSize struct SwOutline { SwPoint* pts; //the outline's points - uint16_t ptsCnt; //number of points in the glyph - uint16_t reservedPtsCnt; - uint16_t* cntrs; //the contour end points + uint32_t ptsCnt; //number of points in the glyph + uint32_t reservedPtsCnt; + uint32_t* cntrs; //the contour end points uint16_t cntrsCnt; //number of contours in glyph uint16_t reservedCntrsCnt; uint8_t* types; //curve type diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp index f24d2d6f27..c02e28b432 100644 --- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp +++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp @@ -46,7 +46,7 @@ static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool, if (outline->reservedCntrsCnt < 1) { outline->reservedCntrsCnt = 1; - outline->cntrs = static_cast<uint16_t*>(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint16_t))); + outline->cntrs = static_cast<uint32_t*>(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint32_t))); outline->closed = static_cast<bool*>(realloc(outline->closed, outline->reservedCntrsCnt * sizeof(bool))); outline->closed[0] = true; } diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp index 2a2c6a1da3..e5b540bcc3 100644 --- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp +++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp @@ -64,7 +64,7 @@ static bool _growOutlineContour(SwOutline& outline, uint32_t n) { if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return false; outline.reservedCntrsCnt = outline.cntrsCnt + n; - outline.cntrs = static_cast<uint16_t*>(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint16_t))); + outline.cntrs = static_cast<uint32_t*>(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint32_t))); return true; } diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp index 04aa9a36ec..fa213cc5d3 100644 --- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp +++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp @@ -780,7 +780,7 @@ static void _exportBorderOutline(const SwStroke& stroke, SwOutline* outline, uin auto src = border->tags; auto tags = outline->types + outline->ptsCnt; auto cntrs = outline->cntrs + outline->cntrsCnt; - uint16_t idx = outline->ptsCnt; + auto idx = outline->ptsCnt; while (cnt > 0) { @@ -921,7 +921,7 @@ SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid) outline->reservedPtsCnt = ptsCnt; } if (outline->reservedCntrsCnt < cntrsCnt) { - outline->cntrs = static_cast<uint16_t*>(realloc(outline->cntrs, sizeof(uint16_t) * cntrsCnt)); + outline->cntrs = static_cast<uint32_t*>(realloc(outline->cntrs, sizeof(uint32_t) * cntrsCnt)); outline->reservedCntrsCnt = cntrsCnt; } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp index a842b7fa8b..42bfd4de70 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp @@ -337,7 +337,10 @@ static unsigned char _parserColor(const char* value, char** end) r = svgUtilStrtof(value, end); *end = _skipSpace(*end, nullptr); - if (**end == '%') r = 255 * r / 100; + if (**end == '%') { + r = 255 * r / 100; + (*end)++; + } *end = _skipSpace(*end, nullptr); if (r < 0 || r > 255) { @@ -1145,10 +1148,13 @@ static bool _attrParseSymbolNode(void* data, const char* key, const char* value) if (!strcmp(key, "viewBox")) { if (!_parseNumber(&value, &symbol->vx) || !_parseNumber(&value, &symbol->vy)) return false; if (!_parseNumber(&value, &symbol->vw) || !_parseNumber(&value, &symbol->vh)) return false; + symbol->hasViewBox = true; } else if (!strcmp(key, "width")) { symbol->w = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal); + symbol->hasWidth = true; } else if (!strcmp(key, "height")) { symbol->h = _toFloat(loader->svgParse, value, SvgParserLengthType::Vertical); + symbol->hasHeight = true; } else if (!strcmp(key, "preserveAspectRatio")) { if (!strcmp(value, "none")) symbol->preserveAspect = false; } else if (!strcmp(key, "overflow")) { @@ -1306,6 +1312,12 @@ static SvgNode* _createSymbolNode(SvgLoaderData* loader, SvgNode* parent, const loader->svgParse->node->node.symbol.preserveAspect = true; loader->svgParse->node->node.symbol.overflowVisible = false; + loader->svgParse->node->node.symbol.hasViewBox = false; + loader->svgParse->node->node.symbol.hasWidth = false; + loader->svgParse->node->node.symbol.hasHeight = false; + loader->svgParse->node->node.symbol.vx = 0.0f; + loader->svgParse->node->node.symbol.vy = 0.0f; + func(buf, bufLength, _attrParseSymbolNode, loader); return loader->svgParse->node; @@ -2722,6 +2734,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, } /* default value for opacity */ loader->svgParse->gradStop = {0.0f, 0, 0, 0, 255}; + loader->svgParse->flags = SvgStopStyleFlags::StopDefault; simpleXmlParseAttributes(attrs, attrsLength, _attrParseStops, loader); loader->latestGradient->stops.push(loader->svgParse->gradStop); } else if (!isIgnoreUnsupportedLogElements(tagName)) { @@ -2865,7 +2878,7 @@ static SvgStyleGradient* _gradientDup(Array<SvgStyleGradient*>* gradients, const auto gradList = gradients->data; for (uint32_t i = 0; i < gradients->count; ++i) { - if (!strcmp((*gradList)->id, id)) { + if ((*gradList)->id && !strcmp((*gradList)->id, id)) { result = _cloneGradient(*gradList); break; } @@ -2875,7 +2888,7 @@ static SvgStyleGradient* _gradientDup(Array<SvgStyleGradient*>* gradients, const if (result && result->ref) { gradList = gradients->data; for (uint32_t i = 0; i < gradients->count; ++i) { - if (!strcmp((*gradList)->id, result->ref)) { + if ((*gradList)->id && !strcmp((*gradList)->id, result->ref)) { if (result->stops.count == 0) _cloneGradStops(result->stops, (*gradList)->stops); //TODO: Properly inherit other property break; diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h index 1f25e82adc..dc9ed558c3 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h @@ -173,6 +173,9 @@ struct SvgSymbolNode float vx, vy, vw, vh; bool preserveAspect; bool overflowVisible; + bool hasViewBox; + bool hasWidth; + bool hasHeight; }; struct SvgUseNode diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp index 90705f2523..a3f34fd46b 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -576,15 +576,17 @@ static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, c if (node->node.use.symbol) { auto symbol = node->node.use.symbol->node.symbol; - auto width = symbol.w; + auto width = (symbol.hasWidth ? symbol.w : vBox.w); if (node->node.use.isWidthSet) width = node->node.use.w; - auto height = symbol.h; + auto height = (symbol.hasHeight ? symbol.h : vBox.h);; if (node->node.use.isHeightSet) height = node->node.use.h; + auto vw = (symbol.hasViewBox ? symbol.vw : width); + auto vh = (symbol.hasViewBox ? symbol.vh : height); Matrix mViewBox = {1, 0, 0, 0, 1, 0, 0, 0, 1}; - if ((!mathEqual(width, symbol.vw) || !mathEqual(height, symbol.vh)) && symbol.vw > 0 && symbol.vh > 0) { - auto sx = width / symbol.vw; - auto sy = height / symbol.vh; + if ((!mathEqual(width, vw) || !mathEqual(height, vh)) && vw > 0 && vh > 0) { + auto sx = width / vw; + auto sy = height / vh; if (symbol.preserveAspect) { if (sx < sy) sy = sx; else sx = sy; @@ -592,8 +594,8 @@ static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, c auto tvx = symbol.vx * sx; auto tvy = symbol.vy * sy; - auto tvw = symbol.vw * sx; - auto tvh = symbol.vh * sy; + auto tvw = vw * sx; + auto tvh = vh * sy; tvy -= (symbol.h - tvh) * 0.5f; tvx -= (symbol.w - tvw) * 0.5f; mViewBox = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1}; diff --git a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp index a12689c7dd..245bc7603a 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp @@ -26,6 +26,8 @@ #ifdef _WIN32 #include <malloc.h> +#elif __FreeBSD__ + #include<stdlib.h> #else #include <alloca.h> #endif diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh index 29b5677983..77badb8b60 100755 --- a/thirdparty/thorvg/update-thorvg.sh +++ b/thirdparty/thorvg/update-thorvg.sh @@ -1,4 +1,4 @@ -VERSION=0.8.0 +VERSION=0.8.1 rm -rf AUTHORS inc LICENSE src *.zip curl -L -O https://github.com/Samsung/thorvg/archive/refs/tags/v$VERSION.zip bsdtar --strip-components=1 -xvf *.zip |