Merge pull request #81202 from YuriSizov/4.1-cherrypicks

Cherry-picks for the 4.1 branch (future 4.1.2) - 1st batch
This commit is contained in:
Rémi Verschelde 2023-09-01 16:28:30 +02:00 committed by GitHub
commit a43c625d4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
358 changed files with 9735 additions and 24449 deletions

View File

@ -204,7 +204,7 @@ License: OFL-1.1
Files: ./thirdparty/freetype/ Files: ./thirdparty/freetype/
Comment: The FreeType Project Comment: The FreeType Project
Copyright: 1996-2022, David Turner, Robert Wilhelm, and Werner Lemberg. Copyright: 1996-2023, David Turner, Robert Wilhelm, and Werner Lemberg.
License: FTL License: FTL
Files: ./thirdparty/glad/ Files: ./thirdparty/glad/
@ -302,7 +302,7 @@ License: CC0-1.0
Files: ./thirdparty/miniupnpc/ Files: ./thirdparty/miniupnpc/
Comment: MiniUPnP Project Comment: MiniUPnP Project
Copyright: 2005-2022, Thomas Bernard Copyright: 2005-2023, Thomas Bernard
License: BSD-3-clause License: BSD-3-clause
Files: ./thirdparty/minizip/ Files: ./thirdparty/minizip/
@ -409,7 +409,7 @@ License: Apache-2.0
Files: ./thirdparty/openxr/ Files: ./thirdparty/openxr/
Comment: OpenXR Loader Comment: OpenXR Loader
Copyright: 2020-2022, The Khronos Group Inc. Copyright: 2020-2023, The Khronos Group Inc.
License: Apache-2.0 License: Apache-2.0
Files: ./thirdparty/pcre2/ Files: ./thirdparty/pcre2/

View File

@ -97,7 +97,6 @@ if env["builtin_zlib"]:
"compress.c", "compress.c",
"crc32.c", "crc32.c",
"deflate.c", "deflate.c",
"infback.c",
"inffast.c", "inffast.c",
"inflate.c", "inflate.c",
"inftrees.c", "inftrees.c",

View File

@ -1344,7 +1344,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/occlusion_culling/bvh_build_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), 2); GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/occlusion_culling/bvh_build_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), 2);
GLOBAL_DEF(PropertyInfo(Variant::INT, "memory/limits/multithreaded_server/rid_pool_prealloc", PROPERTY_HINT_RANGE, "0,500,1"), 60); // No negative and limit to 500 due to crashes. GLOBAL_DEF(PropertyInfo(Variant::INT, "memory/limits/multithreaded_server/rid_pool_prealloc", PROPERTY_HINT_RANGE, "0,500,1"), 60); // No negative and limit to 500 due to crashes.
GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false); GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "internationalization/rendering/root_node_layout_direction", PROPERTY_HINT_RANGE, "Based on Locale,Left-to-Right,Right-to-Left"), 0); GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "internationalization/rendering/root_node_layout_direction", PROPERTY_HINT_ENUM, "Based on Locale,Left-to-Right,Right-to-Left"), 0);
GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/timers/incremental_search_max_interval_msec", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"), 2000); GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/timers/incremental_search_max_interval_msec", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"), 2000);

View File

@ -454,17 +454,21 @@ Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const {
const int s = size(); const int s = size();
int begin = CLAMP(p_begin, -s, s); if (s == 0 || (p_begin < -s && p_step < 0) || (p_begin >= s && p_step > 0)) {
return result;
}
int begin = CLAMP(p_begin, -s, s - 1);
if (begin < 0) { if (begin < 0) {
begin += s; begin += s;
} }
int end = CLAMP(p_end, -s, s); int end = CLAMP(p_end, -s - 1, s);
if (end < 0) { if (end < 0) {
end += s; end += s;
} }
ERR_FAIL_COND_V_MSG(p_step > 0 && begin > end, result, "Slice is positive, but bounds is decreasing."); ERR_FAIL_COND_V_MSG(p_step > 0 && begin > end, result, "Slice step is positive, but bounds are decreasing.");
ERR_FAIL_COND_V_MSG(p_step < 0 && begin < end, result, "Slice is negative, but bounds is increasing."); ERR_FAIL_COND_V_MSG(p_step < 0 && begin < end, result, "Slice step is negative, but bounds are increasing.");
int result_size = (end - begin) / p_step + (((end - begin) % p_step != 0) ? 1 : 0); int result_size = (end - begin) / p_step + (((end - begin) % p_step != 0) ? 1 : 0);
result.resize(result_size); result.resize(result_size);

View File

@ -584,6 +584,7 @@
If either [param begin] or [param end] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). If either [param begin] or [param end] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]).
If specified, [param step] is the relative index between source elements. It can be negative, then [param begin] must be higher than [param end]. For example, [code][0, 1, 2, 3, 4, 5].slice(5, 1, -2)[/code] returns [code][5, 3][/code]. If specified, [param step] is the relative index between source elements. It can be negative, then [param begin] must be higher than [param end]. For example, [code][0, 1, 2, 3, 4, 5].slice(5, 1, -2)[/code] returns [code][5, 3][/code].
If [param deep] is true, each element will be copied by value rather than by reference. If [param deep] is true, each element will be copied by value rather than by reference.
[b]Note:[/b] To include the first element when [param step] is negative, use [code]arr.slice(begin, -arr.size() - 1, step)[/code] (i.e. [code][0, 1, 2].slice(1, -4, -1)[/code] returns [code][1, 0][/code]).
</description> </description>
</method> </method>
<method name="sort"> <method name="sort">

View File

@ -85,7 +85,7 @@
Attenuation factor used if listener is outside of [member emission_angle_degrees] and [member emission_angle_enabled] is set, in decibels. Attenuation factor used if listener is outside of [member emission_angle_degrees] and [member emission_angle_enabled] is set, in decibels.
</member> </member>
<member name="max_db" type="float" setter="set_max_db" getter="get_max_db" default="3.0"> <member name="max_db" type="float" setter="set_max_db" getter="get_max_db" default="3.0">
Sets the absolute maximum of the soundlevel, in decibels. Sets the absolute maximum of the sound level, in decibels.
</member> </member>
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="0.0"> <member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="0.0">
The distance past which the sound can no longer be heard at all. Only has an effect if set to a value greater than [code]0.0[/code]. [member max_distance] works in tandem with [member unit_size]. However, unlike [member unit_size] whose behavior depends on the [member attenuation_model], [member max_distance] always works in a linear fashion. This can be used to prevent the [AudioStreamPlayer3D] from requiring audio mixing when the listener is far away, which saves CPU resources. The distance past which the sound can no longer be heard at all. Only has an effect if set to a value greater than [code]0.0[/code]. [member max_distance] works in tandem with [member unit_size]. However, unlike [member unit_size] whose behavior depends on the [member attenuation_model], [member max_distance] always works in a linear fashion. This can be used to prevent the [AudioStreamPlayer3D] from requiring audio mixing when the listener is far away, which saves CPU resources.

View File

@ -757,7 +757,7 @@
<method name="is_touchscreen_available" qualifiers="const"> <method name="is_touchscreen_available" qualifiers="const">
<return type="bool" /> <return type="bool" />
<description> <description>
Returns [code]true[/code] if touch events are available (Android or iOS), the capability is detected on the Webplatform or if [member ProjectSettings.input_devices/pointing/emulate_touch_from_mouse] is [code]true[/code]. Returns [code]true[/code] if touch events are available (Android or iOS), the capability is detected on the Web platform or if [member ProjectSettings.input_devices/pointing/emulate_touch_from_mouse] is [code]true[/code].
</description> </description>
</method> </method>
<method name="keyboard_get_current_layout" qualifiers="const"> <method name="keyboard_get_current_layout" qualifiers="const">

View File

@ -81,7 +81,7 @@
<return type="Array" /> <return type="Array" />
<description> <description>
Returns an array of [EditorDebuggerSession] currently available to this debugger plugin. Returns an array of [EditorDebuggerSession] currently available to this debugger plugin.
Note: Not sessions in the array may be inactive, check their state via [method EditorDebuggerSession.is_active] [b]Note:[/b] Not sessions in the array may be inactive, check their state via [method EditorDebuggerSession.is_active]
</description> </description>
</method> </method>
</methods> </methods>

View File

@ -1146,7 +1146,7 @@
A factor applied to the movement across the slider axis once the limits get surpassed. The lower, the slower the movement. A factor applied to the movement across the slider axis once the limits get surpassed. The lower, the slower the movement.
</constant> </constant>
<constant name="SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION" value="3" enum="SliderJointParam"> <constant name="SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION" value="3" enum="SliderJointParam">
The amount of restitution once the limits are surpassed. The lower, the more velocityenergy gets lost. The amount of restitution once the limits are surpassed. The lower, the more velocity-energy gets lost.
</constant> </constant>
<constant name="SLIDER_JOINT_LINEAR_LIMIT_DAMPING" value="4" enum="SliderJointParam"> <constant name="SLIDER_JOINT_LINEAR_LIMIT_DAMPING" value="4" enum="SliderJointParam">
The amount of damping once the slider limits are surpassed. The amount of damping once the slider limits are surpassed.

View File

@ -105,7 +105,7 @@
A factor applied to the movement across the slider axis once the limits get surpassed. The lower, the slower the movement. A factor applied to the movement across the slider axis once the limits get surpassed. The lower, the slower the movement.
</constant> </constant>
<constant name="PARAM_LINEAR_LIMIT_RESTITUTION" value="3" enum="Param"> <constant name="PARAM_LINEAR_LIMIT_RESTITUTION" value="3" enum="Param">
The amount of restitution once the limits are surpassed. The lower, the more velocityenergy gets lost. The amount of restitution once the limits are surpassed. The lower, the more velocity-energy gets lost.
</constant> </constant>
<constant name="PARAM_LINEAR_LIMIT_DAMPING" value="4" enum="Param"> <constant name="PARAM_LINEAR_LIMIT_DAMPING" value="4" enum="Param">
The amount of damping once the slider limits are surpassed. The amount of damping once the slider limits are surpassed.

View File

@ -1234,7 +1234,7 @@
<param index="1" name="to_line" type="int" /> <param index="1" name="to_line" type="int" />
<description> <description>
Emitted immediately when the text changes. Emitted immediately when the text changes.
When text is added [param from_line] will be less then [param to_line]. On a remove [param to_line] will be less then [param from_line]. When text is added [param from_line] will be less than [param to_line]. On a remove [param to_line] will be less than [param from_line].
</description> </description>
</signal> </signal>
<signal name="text_changed"> <signal name="text_changed">

View File

@ -1075,6 +1075,7 @@ void MeshStorage::update_mesh_instances() {
} }
glEnable(GL_RASTERIZER_DISCARD); glEnable(GL_RASTERIZER_DISCARD);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Process skeletons and blend shapes using transform feedback // Process skeletons and blend shapes using transform feedback
while (dirty_mesh_instance_arrays.first()) { while (dirty_mesh_instance_arrays.first()) {
MeshInstance *mi = dirty_mesh_instance_arrays.first()->self(); MeshInstance *mi = dirty_mesh_instance_arrays.first()->self();

View File

@ -252,10 +252,10 @@ struct Texture {
} }
Config *config = Config::get_singleton(); Config *config = Config::get_singleton();
state_filter = p_filter; state_filter = p_filter;
GLenum pmin = GL_NEAREST; // param min GLenum pmin = GL_NEAREST;
GLenum pmag = GL_NEAREST; // param mag GLenum pmag = GL_NEAREST;
GLint max_lod = 1000; GLint max_lod = 0;
bool use_anisotropy = false; GLfloat anisotropy = 1.0f;
switch (state_filter) { switch (state_filter) {
case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
pmin = GL_NEAREST; pmin = GL_NEAREST;
@ -268,7 +268,7 @@ struct Texture {
max_lod = 0; max_lod = 0;
} break; } break;
case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
use_anisotropy = true; anisotropy = config->anisotropic_level;
}; };
[[fallthrough]]; [[fallthrough]];
case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
@ -278,12 +278,14 @@ struct Texture {
max_lod = 0; max_lod = 0;
} else if (config->use_nearest_mip_filter) { } else if (config->use_nearest_mip_filter) {
pmin = GL_NEAREST_MIPMAP_NEAREST; pmin = GL_NEAREST_MIPMAP_NEAREST;
max_lod = 1000;
} else { } else {
pmin = GL_NEAREST_MIPMAP_LINEAR; pmin = GL_NEAREST_MIPMAP_LINEAR;
max_lod = 1000;
} }
} break; } break;
case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
use_anisotropy = true; anisotropy = config->anisotropic_level;
}; };
[[fallthrough]]; [[fallthrough]];
case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
@ -293,19 +295,22 @@ struct Texture {
max_lod = 0; max_lod = 0;
} else if (config->use_nearest_mip_filter) { } else if (config->use_nearest_mip_filter) {
pmin = GL_LINEAR_MIPMAP_NEAREST; pmin = GL_LINEAR_MIPMAP_NEAREST;
max_lod = 1000;
} else { } else {
pmin = GL_LINEAR_MIPMAP_LINEAR; pmin = GL_LINEAR_MIPMAP_LINEAR;
max_lod = 1000;
} }
} break; } break;
default: { default: {
return;
} break; } break;
} }
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, pmin); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, pmin);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, pmag); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, pmag);
glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_lod); glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_lod);
if (config->support_anisotropic_filter && use_anisotropy) { if (config->support_anisotropic_filter) {
glTexParameterf(target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, config->anisotropic_level); glTexParameterf(target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
} }
} }
void gl_set_repeat(RS::CanvasItemTextureRepeat p_repeat) { void gl_set_repeat(RS::CanvasItemTextureRepeat p_repeat) {
@ -313,8 +318,11 @@ struct Texture {
return; return;
} }
state_repeat = p_repeat; state_repeat = p_repeat;
GLenum prep = GL_CLAMP_TO_EDGE; // parameter repeat GLenum prep = GL_CLAMP_TO_EDGE;
switch (state_repeat) { switch (state_repeat) {
case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
prep = GL_CLAMP_TO_EDGE;
} break;
case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
prep = GL_REPEAT; prep = GL_REPEAT;
} break; } break;
@ -322,6 +330,7 @@ struct Texture {
prep = GL_MIRRORED_REPEAT; prep = GL_MIRRORED_REPEAT;
} break; } break;
default: { default: {
return;
} break; } break;
} }
glTexParameteri(target, GL_TEXTURE_WRAP_T, prep); glTexParameteri(target, GL_TEXTURE_WRAP_T, prep);
@ -330,8 +339,8 @@ struct Texture {
} }
private: private:
RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_MAX;
RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX;
}; };
struct RenderTarget { struct RenderTarget {

View File

@ -33,30 +33,30 @@ if env["builtin_libpng"]:
# Needed for drivers includes and in platform/web. # Needed for drivers includes and in platform/web.
env.Prepend(CPPPATH=[thirdparty_dir]) env.Prepend(CPPPATH=[thirdparty_dir])
# Currently .ASM filter_neon.S does not compile on NT.
import os
# Enable ARM NEON instructions on 32-bit Android to compile more optimized code.
use_neon = env["platform"] == "android" and env["arch"] == "arm32" and os.name != "nt"
if use_neon:
env_png.Append(CPPDEFINES=[("PNG_ARM_NEON_OPT", 2)])
else:
env_png.Append(CPPDEFINES=[("PNG_ARM_NEON_OPT", 0)])
env_thirdparty = env_png.Clone() env_thirdparty = env_png.Clone()
env_thirdparty.disable_warnings() env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources) env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
if use_neon: if env["arch"].startswith("arm"):
env_neon = env_thirdparty.Clone() if env.msvc: # Can't compile assembly files with MSVC.
if "S_compiler" in env: env_thirdparty.Append(CPPDEFINES=[("PNG_ARM_NEON_OPT"), 0])
env_neon["CC"] = env["S_compiler"] else:
neon_sources = [] env_neon = env_thirdparty.Clone()
neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/arm_init.c")) if "S_compiler" in env:
neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/filter_neon_intrinsics.c")) env_neon["CC"] = env["S_compiler"]
neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/filter_neon.S")) neon_sources = []
neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/palette_neon_intrinsics.c")) neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/arm_init.c"))
thirdparty_obj += neon_sources neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/filter_neon_intrinsics.c"))
neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/filter_neon.S"))
neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/palette_neon_intrinsics.c"))
thirdparty_obj += neon_sources
elif env["arch"].startswith("x86"):
env_thirdparty.Append(CPPDEFINES=["PNG_INTEL_SSE"])
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/intel/intel_init.c")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/intel/filter_sse2_intrinsics.c")
elif env["arch"] == "ppc64":
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/powerpc/powerpc_init.c")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/powerpc/filter_vsx_intrinsics.c")
env.drivers_sources += thirdparty_obj env.drivers_sources += thirdparty_obj

View File

@ -204,6 +204,9 @@ NetSocketPosix::NetError NetSocketPosix::_get_socket_error() const {
if (err == WSAEACCES) { if (err == WSAEACCES) {
return ERR_NET_UNAUTHORIZED; return ERR_NET_UNAUTHORIZED;
} }
if (err == WSAEMSGSIZE || err == WSAENOBUFS) {
return ERR_NET_BUFFER_TOO_SMALL;
}
print_verbose("Socket error: " + itos(err)); print_verbose("Socket error: " + itos(err));
return ERR_NET_OTHER; return ERR_NET_OTHER;
#else #else
@ -222,6 +225,9 @@ NetSocketPosix::NetError NetSocketPosix::_get_socket_error() const {
if (errno == EACCES) { if (errno == EACCES) {
return ERR_NET_UNAUTHORIZED; return ERR_NET_UNAUTHORIZED;
} }
if (errno == ENOBUFS) {
return ERR_NET_BUFFER_TOO_SMALL;
}
print_verbose("Socket error: " + itos(errno)); print_verbose("Socket error: " + itos(errno));
return ERR_NET_OTHER; return ERR_NET_OTHER;
#endif #endif
@ -550,6 +556,10 @@ Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) {
return ERR_BUSY; return ERR_BUSY;
} }
if (err == ERR_NET_BUFFER_TOO_SMALL) {
return ERR_OUT_OF_MEMORY;
}
return FAILED; return FAILED;
} }
@ -571,6 +581,10 @@ Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddr
return ERR_BUSY; return ERR_BUSY;
} }
if (err == ERR_NET_BUFFER_TOO_SMALL) {
return ERR_OUT_OF_MEMORY;
}
return FAILED; return FAILED;
} }
@ -606,6 +620,9 @@ Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) {
if (err == ERR_NET_WOULD_BLOCK) { if (err == ERR_NET_WOULD_BLOCK) {
return ERR_BUSY; return ERR_BUSY;
} }
if (err == ERR_NET_BUFFER_TOO_SMALL) {
return ERR_OUT_OF_MEMORY;
}
return FAILED; return FAILED;
} }
@ -625,6 +642,9 @@ Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP
if (err == ERR_NET_WOULD_BLOCK) { if (err == ERR_NET_WOULD_BLOCK) {
return ERR_BUSY; return ERR_BUSY;
} }
if (err == ERR_NET_BUFFER_TOO_SMALL) {
return ERR_OUT_OF_MEMORY;
}
return FAILED; return FAILED;
} }

View File

@ -56,6 +56,7 @@ private:
ERR_NET_IN_PROGRESS, ERR_NET_IN_PROGRESS,
ERR_NET_ADDRESS_INVALID_OR_UNAVAILABLE, ERR_NET_ADDRESS_INVALID_OR_UNAVAILABLE,
ERR_NET_UNAUTHORIZED, ERR_NET_UNAUTHORIZED,
ERR_NET_BUFFER_TOO_SMALL,
ERR_NET_OTHER, ERR_NET_OTHER,
}; };

View File

@ -4376,6 +4376,9 @@ String EditorNode::_get_system_info() const {
godot_version += " " + hash; godot_version += " " + hash;
} }
#ifdef LINUXBSD_ENABLED
const String display_server = OS::get_singleton()->get_environment("XDG_SESSION_TYPE").capitalize().replace(" ", ""); // `replace` is necessary, because `capitalize` introduces a whitespace between "x" and "11".
#endif // LINUXBSD_ENABLED
String driver_name = GLOBAL_GET("rendering/rendering_device/driver"); String driver_name = GLOBAL_GET("rendering/rendering_device/driver");
String rendering_method = GLOBAL_GET("rendering/renderer/rendering_method"); String rendering_method = GLOBAL_GET("rendering/renderer/rendering_method");
@ -4428,6 +4431,11 @@ String EditorNode::_get_system_info() const {
} else { } else {
info.push_back(distribution_name); info.push_back(distribution_name);
} }
#ifdef LINUXBSD_ENABLED
if (!display_server.is_empty()) {
info.push_back(display_server);
}
#endif // LINUXBSD_ENABLED
info.push_back(vformat("%s (%s)", driver_name, rendering_method)); info.push_back(vformat("%s (%s)", driver_name, rendering_method));
String graphics; String graphics;

View File

@ -772,7 +772,7 @@ void EditorPropertyFlags::setup(const Vector<String> &p_options) {
const int flag_index = flags.size(); // Index of the next element (added by the code below). const int flag_index = flags.size(); // Index of the next element (added by the code below).
// Value for a flag can be explicitly overridden. // Value for a flag can be explicitly overridden.
Vector<String> text_split = p_options[i].split(":"); Vector<String> text_split = option.split(":");
if (text_split.size() != 1) { if (text_split.size() != 1) {
current_val = text_split[1].to_int(); current_val = text_split[1].to_int();
} else { } else {
@ -782,7 +782,7 @@ void EditorPropertyFlags::setup(const Vector<String> &p_options) {
// Create a CheckBox for the current flag. // Create a CheckBox for the current flag.
CheckBox *cb = memnew(CheckBox); CheckBox *cb = memnew(CheckBox);
cb->set_text(option); cb->set_text(text_split[0]);
cb->set_clip_text(true); cb->set_clip_text(true);
cb->connect("pressed", callable_mp(this, &EditorPropertyFlags::_flag_toggled).bind(flag_index)); cb->connect("pressed", callable_mp(this, &EditorPropertyFlags::_flag_toggled).bind(flag_index));
add_focusable(cb); add_focusable(cb);

View File

@ -1 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5.029 1C4.03.989 3.02 1.312 2 2v7c2.017-1.353 4.017-1.314 6 0 1.983-1.314 3.983-1.353 6 0V2c-1.02-.688-2.03-1.011-3.029-1-.662.007-1.318.173-1.971.463V6H8V2c-.982-.645-1.971-.989-2.971-1zM0 10v6h2a3 3 0 0 0 0-6zm5 3a3 3 0 0 0 6 0 3 3 0 0 0-6 0zm9 3h1v-2h-1a1 1 0 0 1 0-2h1v-2h-1a3 3 0 0 0 0 6zM2 12a1 1 0 0 1 0 2zm6 0a1 1 0 0 1 0 2 1 1 0 0 1 0-2z" fill="#e0e0e0" fill-opacity=".59"/></svg> <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M8 2C6 .7 4 .7 2 2v7c2-1.3 4-1.3 6 0 2-1.3 4-1.3 6 0V2C12 .7 10.2.9 9 1.5V6H8zm-8 8v6h2a3 3 0 0 0 0-6zm5 3a3 3 0 0 0 6 0 3 3 0 0 0-6 0zm9 3h1v-2h-1a1 1 0 0 1 0-2h1v-2h-1a3 3 0 0 0 0 6zM2 12a1 1 0 0 1 0 2zm6 0a1 1 0 0 1 0 2 1 1 0 0 1 0-2z" fill="#e0e0e0"/></svg>

Before

Width:  |  Height:  |  Size: 483 B

After

Width:  |  Height:  |  Size: 354 B

View File

@ -166,8 +166,13 @@ void VoxelGIEditorPlugin::_voxel_gi_save_path_and_bake(const String &p_path) {
probe_file->hide(); probe_file->hide();
if (voxel_gi) { if (voxel_gi) {
voxel_gi->bake(); voxel_gi->bake();
ERR_FAIL_COND(voxel_gi->get_probe_data().is_null()); // Ensure the VoxelGIData is always saved to an external resource.
ResourceSaver::save(voxel_gi->get_probe_data(), p_path, ResourceSaver::FLAG_CHANGE_PATH); // This avoids bloating the scene file with large binary data,
// which would be serialized as Base64 if the scene is a `.tscn` file.
Ref<VoxelGIData> voxel_gi_data = voxel_gi->get_probe_data();
ERR_FAIL_COND(voxel_gi_data.is_null());
voxel_gi_data->set_path(p_path);
ResourceSaver::save(voxel_gi_data, p_path, ResourceSaver::FLAG_CHANGE_PATH);
} }
} }

View File

@ -2706,6 +2706,9 @@ bool Main::start() {
} }
uint64_t minimum_time_msec = GLOBAL_DEF(PropertyInfo(Variant::INT, "application/boot_splash/minimum_display_time", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:ms"), 0); uint64_t minimum_time_msec = GLOBAL_DEF(PropertyInfo(Variant::INT, "application/boot_splash/minimum_display_time", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:ms"), 0);
if (Engine::get_singleton()->is_editor_hint()) {
minimum_time_msec = 0;
}
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
#ifdef MODULE_GDSCRIPT_ENABLED #ifdef MODULE_GDSCRIPT_ENABLED

View File

@ -76,7 +76,7 @@ void ENetPacketPeer::throttle_configure(int p_interval, int p_acceleration, int
void ENetPacketPeer::set_timeout(int p_timeout, int p_timeout_min, int p_timeout_max) { void ENetPacketPeer::set_timeout(int p_timeout, int p_timeout_min, int p_timeout_max) {
ERR_FAIL_COND_MSG(peer == nullptr, "Peer not connected"); ERR_FAIL_COND_MSG(peer == nullptr, "Peer not connected");
ERR_FAIL_COND_MSG(p_timeout > p_timeout_min || p_timeout_min > p_timeout_max, "Timeout limit must be less than minimum timeout, which itself must be less then maximum timeout"); ERR_FAIL_COND_MSG(p_timeout > p_timeout_min || p_timeout_min > p_timeout_max, "Timeout limit must be less than minimum timeout, which itself must be less than maximum timeout");
enet_peer_timeout(peer, p_timeout, p_timeout_min, p_timeout_max); enet_peer_timeout(peer, p_timeout, p_timeout_min, p_timeout_max);
} }

View File

@ -1139,6 +1139,7 @@ GDScriptParser::ConstantNode *GDScriptParser::parse_constant(bool p_is_static) {
ConstantNode *constant = alloc_node<ConstantNode>(); ConstantNode *constant = alloc_node<ConstantNode>();
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected constant name after "const".)")) { if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected constant name after "const".)")) {
complete_extents(constant);
return nullptr; return nullptr;
} }
@ -2147,6 +2148,7 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_
ExpressionNode *expression = parse_expression(false); ExpressionNode *expression = parse_expression(false);
if (expression == nullptr) { if (expression == nullptr) {
push_error(R"(Expected expression for match pattern.)"); push_error(R"(Expected expression for match pattern.)");
complete_extents(pattern);
return nullptr; return nullptr;
} else { } else {
if (expression->type == GDScriptParser::Node::LITERAL) { if (expression->type == GDScriptParser::Node::LITERAL) {

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.ComponentModel;
namespace Godot namespace Godot
{ {
@ -623,21 +624,31 @@ namespace Godot
/// </summary> /// </summary>
/// <param name="target">The position to look at.</param> /// <param name="target">The position to look at.</param>
/// <param name="up">The relative up direction.</param> /// <param name="up">The relative up direction.</param>
/// <param name="useModelFront">
/// If true, then the model is oriented in reverse,
/// towards the model front axis (+Z, Vector3.ModelFront),
/// which is more useful for orienting 3D models.
/// </param>
/// <returns>The resulting basis matrix.</returns> /// <returns>The resulting basis matrix.</returns>
public static Basis LookingAt(Vector3 target, Vector3 up) public static Basis LookingAt(Vector3 target, Vector3? up = null, bool useModelFront = false)
{ {
up ??= Vector3.Up;
#if DEBUG #if DEBUG
if (target.IsZeroApprox()) if (target.IsZeroApprox())
{ {
throw new ArgumentException("The vector can't be zero.", nameof(target)); throw new ArgumentException("The vector can't be zero.", nameof(target));
} }
if (up.IsZeroApprox()) if (up.Value.IsZeroApprox())
{ {
throw new ArgumentException("The vector can't be zero.", nameof(up)); throw new ArgumentException("The vector can't be zero.", nameof(up));
} }
#endif #endif
Vector3 column2 = -target.Normalized(); Vector3 column2 = target.Normalized();
Vector3 column0 = up.Cross(column2); if (!useModelFront)
{
column2 = -column2;
}
Vector3 column0 = up.Value.Cross(column2);
#if DEBUG #if DEBUG
if (column0.IsZeroApprox()) if (column0.IsZeroApprox())
{ {
@ -649,6 +660,13 @@ namespace Godot
return new Basis(column0, column1, column2); return new Basis(column0, column1, column2);
} }
/// <inheritdoc cref="LookingAt(Vector3, Nullable{Vector3}, bool)"/>
[EditorBrowsable(EditorBrowsableState.Never)]
public static Basis LookingAt(Vector3 target, Vector3 up)
{
return LookingAt(target, up, false);
}
/// <summary> /// <summary>
/// Returns the orthonormalized version of the basis matrix (useful to /// Returns the orthonormalized version of the basis matrix (useful to
/// call occasionally to avoid rounding errors for orthogonal matrices). /// call occasionally to avoid rounding errors for orthogonal matrices).

View File

@ -500,24 +500,17 @@ namespace Godot
Type? returnType = hasReturn ? DeserializeType(reader) : typeof(void); Type? returnType = hasReturn ? DeserializeType(reader) : typeof(void);
int parametersCount = reader.ReadInt32(); int parametersCount = reader.ReadInt32();
var parameterTypes = parametersCount == 0 ? Type.EmptyTypes : new Type[parametersCount];
if (parametersCount > 0) for (int i = 0; i < parametersCount; i++)
{ {
var parameterTypes = new Type[parametersCount]; Type? parameterType = DeserializeType(reader);
if (parameterType == null)
for (int i = 0; i < parametersCount; i++) return false;
{ parameterTypes[i] = parameterType;
Type? parameterType = DeserializeType(reader);
if (parameterType == null)
return false;
parameterTypes[i] = parameterType;
}
methodInfo = declaringType.GetMethod(methodName, (BindingFlags)flags, null, parameterTypes, null);
return methodInfo != null && methodInfo.ReturnType == returnType;
} }
methodInfo = declaringType.GetMethod(methodName, (BindingFlags)flags); methodInfo = declaringType.GetMethod(methodName, (BindingFlags)flags, null, parameterTypes, null);
return methodInfo != null && methodInfo.ReturnType == returnType; return methodInfo != null && methodInfo.ReturnType == returnType;
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.ComponentModel;
namespace Godot namespace Godot
{ {
@ -175,14 +176,26 @@ namespace Godot
/// </summary> /// </summary>
/// <param name="target">The object to look at.</param> /// <param name="target">The object to look at.</param>
/// <param name="up">The relative up direction.</param> /// <param name="up">The relative up direction.</param>
/// <param name="useModelFront">
/// If true, then the model is oriented in reverse,
/// towards the model front axis (+Z, Vector3.ModelFront),
/// which is more useful for orienting 3D models.
/// </param>
/// <returns>The resulting transform.</returns> /// <returns>The resulting transform.</returns>
public readonly Transform3D LookingAt(Vector3 target, Vector3 up) public readonly Transform3D LookingAt(Vector3 target, Vector3? up = null, bool useModelFront = false)
{ {
Transform3D t = this; Transform3D t = this;
t.SetLookAt(Origin, target, up); t.SetLookAt(Origin, target, up ?? Vector3.Up, useModelFront);
return t; return t;
} }
/// <inheritdoc cref="LookingAt(Vector3, Nullable{Vector3}, bool)"/>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly Transform3D LookingAt(Vector3 target, Vector3 up)
{
return LookingAt(target, up, false);
}
/// <summary> /// <summary>
/// Returns the transform with the basis orthogonal (90 degrees), /// Returns the transform with the basis orthogonal (90 degrees),
/// and normalized axis vectors (scale of 1 or -1). /// and normalized axis vectors (scale of 1 or -1).
@ -247,9 +260,9 @@ namespace Godot
return new Transform3D(Basis * tmpBasis, Origin); return new Transform3D(Basis * tmpBasis, Origin);
} }
private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up) private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up, bool useModelFront = false)
{ {
Basis = Basis.LookingAt(target - eye, up); Basis = Basis.LookingAt(target - eye, up, useModelFront);
Origin = eye; Origin = eye;
} }

View File

@ -660,6 +660,13 @@ namespace Godot
private static readonly Vector3 _forward = new Vector3(0, 0, -1); private static readonly Vector3 _forward = new Vector3(0, 0, -1);
private static readonly Vector3 _back = new Vector3(0, 0, 1); private static readonly Vector3 _back = new Vector3(0, 0, 1);
private static readonly Vector3 _modelLeft = new Vector3(1, 0, 0);
private static readonly Vector3 _modelRight = new Vector3(-1, 0, 0);
private static readonly Vector3 _modelTop = new Vector3(0, 1, 0);
private static readonly Vector3 _modelBottom = new Vector3(0, -1, 0);
private static readonly Vector3 _modelFront = new Vector3(0, 0, 1);
private static readonly Vector3 _modelRear = new Vector3(0, 0, -1);
/// <summary> /// <summary>
/// Zero vector, a vector with all components set to <c>0</c>. /// Zero vector, a vector with all components set to <c>0</c>.
/// </summary> /// </summary>
@ -711,6 +718,31 @@ namespace Godot
/// <value>Equivalent to <c>new Vector3(0, 0, 1)</c>.</value> /// <value>Equivalent to <c>new Vector3(0, 0, 1)</c>.</value>
public static Vector3 Back { get { return _back; } } public static Vector3 Back { get { return _back; } }
/// <summary>
/// Unit vector pointing towards the left side of imported 3D assets.
/// </summary>
public static Vector3 ModelLeft { get { return _modelLeft; } }
/// <summary>
/// Unit vector pointing towards the right side of imported 3D assets.
/// </summary>
public static Vector3 ModelRight { get { return _modelRight; } }
/// <summary>
/// Unit vector pointing towards the top side (up) of imported 3D assets.
/// </summary>
public static Vector3 ModelTop { get { return _modelTop; } }
/// <summary>
/// Unit vector pointing towards the bottom side (down) of imported 3D assets.
/// </summary>
public static Vector3 ModelBottom { get { return _modelBottom; } }
/// <summary>
/// Unit vector pointing towards the front side (facing forward) of imported 3D assets.
/// </summary>
public static Vector3 ModelFront { get { return _modelFront; } }
/// <summary>
/// Unit vector pointing towards the rear side (back) of imported 3D assets.
/// </summary>
public static Vector3 ModelRear { get { return _modelRear; } }
/// <summary> /// <summary>
/// Constructs a new <see cref="Vector3"/> with the given components. /// Constructs a new <see cref="Vector3"/> with the given components.
/// </summary> /// </summary>

View File

@ -115,11 +115,11 @@ void NavRegion::update_polygons() {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (!Math::is_equal_approx(double(map->get_cell_size()), double(mesh->get_cell_size()))) { if (!Math::is_equal_approx(double(map->get_cell_size()), double(mesh->get_cell_size()))) {
ERR_PRINT_ONCE("Navigation map synchronization error. Attempted to update a navigation region with a navigation mesh that uses a different `cell_size` than the `cell_size` set on the navigation map."); ERR_PRINT_ONCE(vformat("Navigation map synchronization error. Attempted to update a navigation region with a navigation mesh that uses a `cell_size` of %s while assigned to a navigation map set to a `cell_size` of %s. The cell size for navigation maps can be changed by using the NavigationServer map_set_cell_size() function. The cell size for default navigation maps can also be changed in the ProjectSettings.", double(map->get_cell_size()), double(mesh->get_cell_size())));
} }
if (!Math::is_equal_approx(double(map->get_cell_height()), double(mesh->get_cell_height()))) { if (!Math::is_equal_approx(double(map->get_cell_height()), double(mesh->get_cell_height()))) {
ERR_PRINT_ONCE("Navigation map synchronization error. Attempted to update a navigation region with a navigation mesh that uses a different `cell_height` than the `cell_height` set on the navigation map."); ERR_PRINT_ONCE(vformat("Navigation map synchronization error. Attempted to update a navigation region with a navigation mesh that uses a `cell_height` of %s while assigned to a navigation map set to a `cell_height` of %s. The cell height for navigation maps can be changed by using the NavigationServer map_set_cell_height() function. The cell height for default navigation maps can also be changed in the ProjectSettings.", double(map->get_cell_height()), double(mesh->get_cell_height())));
} }
if (map && Math::rad_to_deg(map->get_up().angle_to(transform.basis.get_column(1))) >= 90.0f) { if (map && Math::rad_to_deg(map->get_up().angle_to(transform.basis.get_column(1))) >= 90.0f) {

View File

@ -134,6 +134,10 @@ void OpenXRHandTrackingExtension::on_process() {
// process our hands // process our hands
const XrTime time = OpenXRAPI::get_singleton()->get_next_frame_time(); // This data will be used for the next frame we render const XrTime time = OpenXRAPI::get_singleton()->get_next_frame_time(); // This data will be used for the next frame we render
if (time == 0) {
// we don't have timing info yet, or we're skipping a frame...
return;
}
XrResult result; XrResult result;

View File

@ -227,7 +227,6 @@ if env["freetype_enabled"]:
"compress.c", "compress.c",
"crc32.c", "crc32.c",
"deflate.c", "deflate.c",
"infback.c",
"inffast.c", "inffast.c",
"inflate.c", "inflate.c",
"inftrees.c", "inftrees.c",
@ -263,7 +262,6 @@ if env["freetype_enabled"]:
CPPDEFINES=[ CPPDEFINES=[
"FT2_BUILD_LIBRARY", "FT2_BUILD_LIBRARY",
"FT_CONFIG_OPTION_USE_PNG", "FT_CONFIG_OPTION_USE_PNG",
("PNG_ARM_NEON_OPT", 0),
"FT_CONFIG_OPTION_SYSTEM_ZLIB", "FT_CONFIG_OPTION_SYSTEM_ZLIB",
] ]
) )

View File

@ -222,7 +222,6 @@ if env["freetype_enabled"]:
"compress.c", "compress.c",
"crc32.c", "crc32.c",
"deflate.c", "deflate.c",
"infback.c",
"inffast.c", "inffast.c",
"inflate.c", "inflate.c",
"inftrees.c", "inftrees.c",
@ -258,7 +257,6 @@ if env["freetype_enabled"]:
CPPDEFINES=[ CPPDEFINES=[
"FT2_BUILD_LIBRARY", "FT2_BUILD_LIBRARY",
"FT_CONFIG_OPTION_USE_PNG", "FT_CONFIG_OPTION_USE_PNG",
("PNG_ARM_NEON_OPT", 0),
"FT_CONFIG_OPTION_SYSTEM_ZLIB", "FT_CONFIG_OPTION_SYSTEM_ZLIB",
] ]
) )

View File

@ -64,7 +64,7 @@ void AndroidInputHandler::_set_key_modifier_state(Ref<InputEventWithModifiers> e
} }
} }
void AndroidInputHandler::process_key_event(int p_physical_keycode, int p_unicode, int p_key_label, bool p_pressed) { void AndroidInputHandler::process_key_event(int p_physical_keycode, int p_unicode, int p_key_label, bool p_pressed, bool p_echo) {
static char32_t prev_wc = 0; static char32_t prev_wc = 0;
char32_t unicode = p_unicode; char32_t unicode = p_unicode;
if ((p_unicode & 0xfffffc00) == 0xd800) { if ((p_unicode & 0xfffffc00) == 0xd800) {
@ -125,6 +125,7 @@ void AndroidInputHandler::process_key_event(int p_physical_keycode, int p_unicod
ev->set_key_label(fix_key_label(p_key_label, keycode)); ev->set_key_label(fix_key_label(p_key_label, keycode));
ev->set_unicode(fix_unicode(unicode)); ev->set_unicode(fix_unicode(unicode));
ev->set_pressed(p_pressed); ev->set_pressed(p_pressed);
ev->set_echo(p_echo);
_set_key_modifier_state(ev, keycode); _set_key_modifier_state(ev, keycode);

View File

@ -101,7 +101,7 @@ public:
void process_magnify(Point2 p_pos, float p_factor); void process_magnify(Point2 p_pos, float p_factor);
void process_pan(Point2 p_pos, Vector2 p_delta); void process_pan(Point2 p_pos, Vector2 p_delta);
void process_joy_event(JoypadEvent p_event); void process_joy_event(JoypadEvent p_event);
void process_key_event(int p_physical_keycode, int p_unicode, int p_key_label, bool p_pressed); void process_key_event(int p_physical_keycode, int p_unicode, int p_key_label, bool p_pressed, bool p_echo);
}; };
#endif // ANDROID_INPUT_HANDLER_H #endif // ANDROID_INPUT_HANDLER_H

View File

@ -147,7 +147,7 @@ public class GodotLib {
/** /**
* Forward regular key events. * Forward regular key events.
*/ */
public static native void key(int p_physical_keycode, int p_unicode, int p_key_label, boolean p_pressed); public static native void key(int p_physical_keycode, int p_unicode, int p_key_label, boolean p_pressed, boolean p_echo);
/** /**
* Forward game device's key events. * Forward game device's key events.

View File

@ -141,7 +141,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
final int physical_keycode = event.getKeyCode(); final int physical_keycode = event.getKeyCode();
final int unicode = event.getUnicodeChar(); final int unicode = event.getUnicodeChar();
final int key_label = event.getDisplayLabel(); final int key_label = event.getDisplayLabel();
GodotLib.key(physical_keycode, unicode, key_label, false); GodotLib.key(physical_keycode, unicode, key_label, false, event.getRepeatCount() > 0);
}; };
return true; return true;
@ -176,7 +176,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
final int physical_keycode = event.getKeyCode(); final int physical_keycode = event.getKeyCode();
final int unicode = event.getUnicodeChar(); final int unicode = event.getUnicodeChar();
final int key_label = event.getDisplayLabel(); final int key_label = event.getDisplayLabel();
GodotLib.key(physical_keycode, unicode, key_label, true); GodotLib.key(physical_keycode, unicode, key_label, true, event.getRepeatCount() > 0);
} }
return true; return true;

View File

@ -93,8 +93,8 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
@Override @Override
public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) { public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, 0, true); GodotLib.key(KeyEvent.KEYCODE_DEL, 0, 0, true, false);
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, 0, false); GodotLib.key(KeyEvent.KEYCODE_DEL, 0, 0, false, false);
if (mHasSelection) { if (mHasSelection) {
mHasSelection = false; mHasSelection = false;
@ -115,8 +115,8 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
// Return keys are handled through action events // Return keys are handled through action events
continue; continue;
} }
GodotLib.key(0, character, 0, true); GodotLib.key(0, character, 0, true, false);
GodotLib.key(0, character, 0, false); GodotLib.key(0, character, 0, false, false);
} }
} }
@ -127,8 +127,8 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
if (characters != null) { if (characters != null) {
for (int i = 0; i < characters.length(); i++) { for (int i = 0; i < characters.length(); i++) {
final int character = characters.codePointAt(i); final int character = characters.codePointAt(i);
GodotLib.key(0, character, 0, true); GodotLib.key(0, character, 0, true, false);
GodotLib.key(0, character, 0, false); GodotLib.key(0, character, 0, false, false);
} }
} }
} }
@ -136,8 +136,8 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
if (pActionID == EditorInfo.IME_ACTION_DONE) { if (pActionID == EditorInfo.IME_ACTION_DONE) {
// Enter key has been pressed // Enter key has been pressed
mRenderView.queueOnRenderThread(() -> { mRenderView.queueOnRenderThread(() -> {
GodotLib.key(KeyEvent.KEYCODE_ENTER, 0, 0, true); GodotLib.key(KeyEvent.KEYCODE_ENTER, 0, 0, true, false);
GodotLib.key(KeyEvent.KEYCODE_ENTER, 0, 0, false); GodotLib.key(KeyEvent.KEYCODE_ENTER, 0, 0, false, false);
}); });
mRenderView.getView().requestFocus(); mRenderView.getView().requestFocus();
return true; return true;

View File

@ -385,11 +385,11 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(
} }
// Called on the UI thread // Called on the UI thread
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_physical_keycode, jint p_unicode, jint p_key_label, jboolean p_pressed) { JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_physical_keycode, jint p_unicode, jint p_key_label, jboolean p_pressed, jboolean p_echo) {
if (step.get() <= 0) { if (step.get() <= 0) {
return; return;
} }
input_handler->process_key_event(p_physical_keycode, p_unicode, p_key_label, p_pressed); input_handler->process_key_event(p_physical_keycode, p_unicode, p_key_label, p_pressed, p_echo);
} }
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z) { JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z) {

View File

@ -49,7 +49,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_dispatchMouseEvent(JN
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_dispatchTouchEvent(JNIEnv *env, jclass clazz, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jboolean p_double_tap); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_dispatchTouchEvent(JNIEnv *env, jclass clazz, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jboolean p_double_tap);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnify(JNIEnv *env, jclass clazz, jfloat p_x, jfloat p_y, jfloat p_factor); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnify(JNIEnv *env, jclass clazz, jfloat p_x, jfloat p_y, jfloat p_factor);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_pan(JNIEnv *env, jclass clazz, jfloat p_x, jfloat p_y, jfloat p_delta_x, jfloat p_delta_y); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_pan(JNIEnv *env, jclass clazz, jfloat p_x, jfloat p_y, jfloat p_delta_x, jfloat p_delta_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_physical_keycode, jint p_unicode, jint p_key_label, jboolean p_pressed); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_physical_keycode, jint p_unicode, jint p_key_label, jboolean p_pressed, jboolean p_echo);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jclass clazz, jint p_device, jint p_button, jboolean p_pressed); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jclass clazz, jint p_device, jint p_button, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jclass clazz, jint p_device, jint p_axis, jfloat p_value); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jclass clazz, jint p_device, jint p_axis, jfloat p_value);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jclass clazz, jint p_device, jint p_hat_x, jint p_hat_y); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jclass clazz, jint p_device, jint p_hat_x, jint p_hat_y);

View File

@ -85,19 +85,18 @@ def configure(env: "Environment"):
env["ENV"]["PATH"] = env["IOS_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"] env["ENV"]["PATH"] = env["IOS_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}" compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}"
s_compiler_path = "$IOS_TOOLCHAIN_PATH/Developer/usr/bin/"
ccache_path = os.environ.get("CCACHE") ccache_path = os.environ.get("CCACHE")
if ccache_path is None: if ccache_path is None:
env["CC"] = compiler_path + "clang" env["CC"] = compiler_path + "clang"
env["CXX"] = compiler_path + "clang++" env["CXX"] = compiler_path + "clang++"
env["S_compiler"] = s_compiler_path + "gcc" env["S_compiler"] = compiler_path + "clang"
else: else:
# there aren't any ccache wrappers available for iOS, # there aren't any ccache wrappers available for iOS,
# to enable caching we need to prepend the path to the ccache binary # to enable caching we need to prepend the path to the ccache binary
env["CC"] = ccache_path + " " + compiler_path + "clang" env["CC"] = ccache_path + " " + compiler_path + "clang"
env["CXX"] = ccache_path + " " + compiler_path + "clang++" env["CXX"] = ccache_path + " " + compiler_path + "clang++"
env["S_compiler"] = ccache_path + " " + s_compiler_path + "gcc" env["S_compiler"] = ccache_path + " " + compiler_path + "clang"
env["AR"] = compiler_path + "ar" env["AR"] = compiler_path + "ar"
env["RANLIB"] = compiler_path + "ranlib" env["RANLIB"] = compiler_path + "ranlib"

View File

@ -3085,14 +3085,14 @@ bool DisplayServerMacOS::window_is_focused(WindowID p_window) const {
} }
bool DisplayServerMacOS::window_can_draw(WindowID p_window) const { bool DisplayServerMacOS::window_can_draw(WindowID p_window) const {
return window_get_mode(p_window) != WINDOW_MODE_MINIMIZED; return (window_get_mode(p_window) != WINDOW_MODE_MINIMIZED) && [windows[p_window].window_object isOnActiveSpace];
} }
bool DisplayServerMacOS::can_any_window_draw() const { bool DisplayServerMacOS::can_any_window_draw() const {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
for (const KeyValue<WindowID, WindowData> &E : windows) { for (const KeyValue<WindowID, WindowData> &E : windows) {
if (window_get_mode(E.key) != WINDOW_MODE_MINIMIZED) { if ((window_get_mode(E.key) != WINDOW_MODE_MINIMIZED) && [E.value.window_object isOnActiveSpace]) {
return true; return true;
} }
} }

View File

@ -618,7 +618,7 @@ Color DisplayServerWindows::screen_get_pixel(const Point2i &p_position) const {
COLORREF col = GetPixel(dc, p.x, p.y); COLORREF col = GetPixel(dc, p.x, p.y);
if (col != CLR_INVALID) { if (col != CLR_INVALID) {
ReleaseDC(NULL, dc); ReleaseDC(NULL, dc);
return Color(float(col & 0x000000FF) / 256.0, float((col & 0x0000FF00) >> 8) / 256.0, float((col & 0x00FF0000) >> 16) / 256.0, 1.0); return Color(float(col & 0x000000FF) / 255.0f, float((col & 0x0000FF00) >> 8) / 255.0f, float((col & 0x00FF0000) >> 16) / 255.0f, 1.0f);
} }
ReleaseDC(NULL, dc); ReleaseDC(NULL, dc);
} }

View File

@ -41,7 +41,7 @@ void Camera2D::_update_scroll() {
if (Engine::get_singleton()->is_editor_hint()) { if (Engine::get_singleton()->is_editor_hint()) {
queue_redraw(); queue_redraw();
// Only set viewport transform when not bound to the main viewport. // Only set viewport transform when not bound to the main viewport.
if (get_viewport() == get_tree()->get_edited_scene_root()->get_viewport()) { if (get_tree()->get_edited_scene_root() && get_viewport() == get_tree()->get_edited_scene_root()->get_viewport()) {
return; return;
} }
} }

View File

@ -79,7 +79,7 @@ void NavigationObstacle2D::_notification(int p_what) {
previous_transform = get_global_transform(); previous_transform = get_global_transform();
// need to trigger map controlled agent assignment somehow for the fake_agent since obstacles use no callback like regular agents // need to trigger map controlled agent assignment somehow for the fake_agent since obstacles use no callback like regular agents
NavigationServer2D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled); NavigationServer2D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled);
_update_position(get_global_transform().get_origin()); _update_position(get_global_position());
set_physics_process_internal(true); set_physics_process_internal(true);
} break; } break;
@ -112,7 +112,7 @@ void NavigationObstacle2D::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (is_inside_tree()) { if (is_inside_tree()) {
_update_position(get_global_transform().get_origin()); _update_position(get_global_position());
if (velocity_submitted) { if (velocity_submitted) {
velocity_submitted = false; velocity_submitted = false;
@ -164,9 +164,9 @@ NavigationObstacle2D::~NavigationObstacle2D() {
void NavigationObstacle2D::set_vertices(const Vector<Vector2> &p_vertices) { void NavigationObstacle2D::set_vertices(const Vector<Vector2> &p_vertices) {
vertices = p_vertices; vertices = p_vertices;
NavigationServer2D::get_singleton()->obstacle_set_vertices(obstacle, vertices); NavigationServer2D::get_singleton()->obstacle_set_vertices(obstacle, vertices);
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint())) { #ifdef DEBUG_ENABLED
queue_redraw(); queue_redraw();
} #endif // DEBUG_ENABLED
} }
void NavigationObstacle2D::set_navigation_map(RID p_navigation_map) { void NavigationObstacle2D::set_navigation_map(RID p_navigation_map) {
@ -195,9 +195,9 @@ void NavigationObstacle2D::set_radius(real_t p_radius) {
radius = p_radius; radius = p_radius;
NavigationServer2D::get_singleton()->obstacle_set_radius(obstacle, radius); NavigationServer2D::get_singleton()->obstacle_set_radius(obstacle, radius);
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint())) { #ifdef DEBUG_ENABLED
queue_redraw(); queue_redraw();
} #endif // DEBUG_ENABLED
} }
void NavigationObstacle2D::set_avoidance_layers(uint32_t p_layers) { void NavigationObstacle2D::set_avoidance_layers(uint32_t p_layers) {
@ -237,6 +237,9 @@ void NavigationObstacle2D::set_avoidance_enabled(bool p_enabled) {
avoidance_enabled = p_enabled; avoidance_enabled = p_enabled;
NavigationServer2D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled); NavigationServer2D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled);
#ifdef DEBUG_ENABLED
queue_redraw();
#endif // DEBUG_ENABLED
} }
bool NavigationObstacle2D::get_avoidance_enabled() const { bool NavigationObstacle2D::get_avoidance_enabled() const {
@ -255,13 +258,16 @@ void NavigationObstacle2D::_update_map(RID p_map) {
void NavigationObstacle2D::_update_position(const Vector2 p_position) { void NavigationObstacle2D::_update_position(const Vector2 p_position) {
NavigationServer2D::get_singleton()->obstacle_set_position(obstacle, p_position); NavigationServer2D::get_singleton()->obstacle_set_position(obstacle, p_position);
#ifdef DEBUG_ENABLED
queue_redraw();
#endif // DEBUG_ENABLED
} }
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
void NavigationObstacle2D::_update_fake_agent_radius_debug() { void NavigationObstacle2D::_update_fake_agent_radius_debug() {
if (radius > 0.0 && NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_enable_obstacles_radius()) { if (radius > 0.0 && NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_enable_obstacles_radius()) {
Color debug_radius_color = NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_obstacles_radius_color(); Color debug_radius_color = NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_obstacles_radius_color();
draw_circle(get_global_transform().get_origin(), radius, debug_radius_color); RS::get_singleton()->canvas_item_add_circle(get_canvas_item(), Vector2(), radius, debug_radius_color);
} }
} }
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED

View File

@ -273,11 +273,19 @@ void _bake_navigation_mesh(void *p_user_data) {
Ref<NavigationMeshSourceGeometryData3D> source_geometry_data = args->source_geometry_data; Ref<NavigationMeshSourceGeometryData3D> source_geometry_data = args->source_geometry_data;
NavigationServer3D::get_singleton()->bake_from_source_geometry_data(nav_mesh, source_geometry_data); NavigationServer3D::get_singleton()->bake_from_source_geometry_data(nav_mesh, source_geometry_data);
args->nav_region->call_deferred(SNAME("_bake_finished"), nav_mesh); if (!Thread::is_main_thread()) {
args->nav_region->call_deferred(SNAME("_bake_finished"), nav_mesh);
} else {
args->nav_region->_bake_finished(nav_mesh);
}
memdelete(args); memdelete(args);
} else { } else {
ERR_PRINT("Can't bake the navigation mesh if the `NavigationMesh` resource doesn't exist"); ERR_PRINT("Can't bake the navigation mesh if the `NavigationMesh` resource doesn't exist");
args->nav_region->call_deferred(SNAME("_bake_finished"), Ref<NavigationMesh>()); if (!Thread::is_main_thread()) {
args->nav_region->call_deferred(SNAME("_bake_finished"), Ref<NavigationMesh>());
} else {
args->nav_region->_bake_finished(Ref<NavigationMesh>());
}
memdelete(args); memdelete(args);
} }
} }

View File

@ -163,6 +163,7 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
live_editor->_res_set_func(p_args[0], p_args[1], p_args[2]); live_editor->_res_set_func(p_args[0], p_args[1], p_args[2]);
} else if (p_msg == "live_node_call") { } else if (p_msg == "live_node_call") {
ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA);
LocalVector<Variant> args; LocalVector<Variant> args;
LocalVector<Variant *> argptrs; LocalVector<Variant *> argptrs;
args.resize(p_args.size() - 2); args.resize(p_args.size() - 2);
@ -171,11 +172,10 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
args[i] = p_args[i + 2]; args[i] = p_args[i + 2];
argptrs[i] = &args[i]; argptrs[i] = &args[i];
} }
live_editor->_node_call_func(p_args[0], p_args[1], (const Variant **)argptrs.ptr(), argptrs.size()); live_editor->_node_call_func(p_args[0], p_args[1], argptrs.size() ? (const Variant **)argptrs.ptr() : nullptr, argptrs.size());
} else if (p_msg == "live_res_call") { } else if (p_msg == "live_res_call") {
ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA); ERR_FAIL_COND_V(p_args.size() < 2, ERR_INVALID_DATA);
LocalVector<Variant> args; LocalVector<Variant> args;
LocalVector<Variant *> argptrs; LocalVector<Variant *> argptrs;
args.resize(p_args.size() - 2); args.resize(p_args.size() - 2);
@ -184,7 +184,7 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
args[i] = p_args[i + 2]; args[i] = p_args[i + 2];
argptrs[i] = &args[i]; argptrs[i] = &args[i];
} }
live_editor->_res_call_func(p_args[0], p_args[1], (const Variant **)argptrs.ptr(), argptrs.size()); live_editor->_res_call_func(p_args[0], p_args[1], argptrs.size() ? (const Variant **)argptrs.ptr() : nullptr, argptrs.size());
} else if (p_msg == "live_create_node") { } else if (p_msg == "live_create_node") {
ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA);

View File

@ -327,11 +327,8 @@ void Button::_notification(int p_what) {
if (align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER && icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER) { if (align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER && icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER) {
icon_ofs.x = 0.0; icon_ofs.x = 0.0;
} }
int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width; int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width;
text_buf->set_width((clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? text_clip : -1);
int text_width = MAX(1, (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x);
if (_internal_margin[SIDE_LEFT] > 0) { if (_internal_margin[SIDE_LEFT] > 0) {
text_clip -= _internal_margin[SIDE_LEFT] + theme_cache.h_separation; text_clip -= _internal_margin[SIDE_LEFT] + theme_cache.h_separation;
} }
@ -339,6 +336,10 @@ void Button::_notification(int p_what) {
text_clip -= _internal_margin[SIDE_RIGHT] + theme_cache.h_separation; text_clip -= _internal_margin[SIDE_RIGHT] + theme_cache.h_separation;
} }
text_buf->set_width((clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? text_clip : -1);
int text_width = MAX(1, (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x);
Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - text_buf->get_size() - Point2(_internal_margin[SIDE_RIGHT] - _internal_margin[SIDE_LEFT], 0)) / 2.0; Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - text_buf->get_size() - Point2(_internal_margin[SIDE_RIGHT] - _internal_margin[SIDE_LEFT], 0)) / 2.0;
if (vertical_icon_alignment == VERTICAL_ALIGNMENT_TOP) { if (vertical_icon_alignment == VERTICAL_ALIGNMENT_TOP) {

View File

@ -445,13 +445,11 @@ void OptionButton::_select_int(int p_which) {
void OptionButton::_refresh_size_cache() { void OptionButton::_refresh_size_cache() {
cache_refresh_pending = false; cache_refresh_pending = false;
if (!fit_to_longest_item) { if (fit_to_longest_item) {
return; _cached_size = Vector2();
} for (int i = 0; i < get_item_count(); i++) {
_cached_size = _cached_size.max(get_minimum_size_for_text_and_icon(popup->get_item_xl_text(i), get_item_icon(i)));
_cached_size = Vector2(); }
for (int i = 0; i < get_item_count(); i++) {
_cached_size = _cached_size.max(get_minimum_size_for_text_and_icon(popup->get_item_xl_text(i), get_item_icon(i)));
} }
update_minimum_size(); update_minimum_size();
} }

View File

@ -881,6 +881,8 @@ void TabBar::_update_hover() {
if (hover != -1) { if (hover != -1) {
emit_signal(SNAME("tab_hovered"), hover); emit_signal(SNAME("tab_hovered"), hover);
} }
_update_cache();
queue_redraw(); queue_redraw();
} }
@ -988,6 +990,7 @@ void TabBar::_on_mouse_exited() {
highlight_arrow = -1; highlight_arrow = -1;
dragging_valid_tab = false; dragging_valid_tab = false;
_update_cache();
queue_redraw(); queue_redraw();
} }

View File

@ -5565,10 +5565,10 @@ Variant Animation::subtract_variant(const Variant &a, const Variant &b) {
return (b.operator Quaternion()).inverse() * (a.operator Quaternion()); return (b.operator Quaternion()).inverse() * (a.operator Quaternion());
} }
case Variant::TRANSFORM2D: { case Variant::TRANSFORM2D: {
return (b.operator Transform2D()).inverse() * (a.operator Transform2D()); return (b.operator Transform2D()).affine_inverse() * (a.operator Transform2D());
} }
case Variant::TRANSFORM3D: { case Variant::TRANSFORM3D: {
return (b.operator Transform3D()).inverse() * (a.operator Transform3D()); return (b.operator Transform3D()).affine_inverse() * (a.operator Transform3D());
} }
default: { default: {
return Variant::evaluate(Variant::OP_SUBTRACT, a, b); return Variant::evaluate(Variant::OP_SUBTRACT, a, b);

View File

@ -122,7 +122,7 @@ void CameraAttributes::_bind_methods() {
ADD_GROUP("Exposure", "exposure_"); ADD_GROUP("Exposure", "exposure_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_sensitivity", PROPERTY_HINT_RANGE, "0.1,32000.0,0.1,suffix:ISO"), "set_exposure_sensitivity", "get_exposure_sensitivity"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_sensitivity", PROPERTY_HINT_RANGE, "0.1,32000.0,0.1,suffix:ISO"), "set_exposure_sensitivity", "get_exposure_sensitivity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_multiplier", PROPERTY_HINT_RANGE, "0.0,2048.0,0.001"), "set_exposure_multiplier", "get_exposure_multiplier"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_multiplier", PROPERTY_HINT_RANGE, "0.0,8.0,0.001,or_greater"), "set_exposure_multiplier", "get_exposure_multiplier");
ADD_GROUP("Auto Exposure", "auto_exposure_"); ADD_GROUP("Auto Exposure", "auto_exposure_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_auto_exposure_enabled", "is_auto_exposure_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_auto_exposure_enabled", "is_auto_exposure_enabled");

View File

@ -66,20 +66,6 @@ void Shader::set_code(const String &p_code) {
E->disconnect(SNAME("changed"), callable_mp(this, &Shader::_dependency_changed)); E->disconnect(SNAME("changed"), callable_mp(this, &Shader::_dependency_changed));
} }
String type = ShaderLanguage::get_shader_type(p_code);
if (type == "canvas_item") {
mode = MODE_CANVAS_ITEM;
} else if (type == "particles") {
mode = MODE_PARTICLES;
} else if (type == "sky") {
mode = MODE_SKY;
} else if (type == "fog") {
mode = MODE_FOG;
} else {
mode = MODE_SPATIAL;
}
code = p_code; code = p_code;
String pp_code = p_code; String pp_code = p_code;
@ -100,6 +86,21 @@ void Shader::set_code(const String &p_code) {
} }
} }
// Try to get the shader type from the final, fully preprocessed shader code.
String type = ShaderLanguage::get_shader_type(pp_code);
if (type == "canvas_item") {
mode = MODE_CANVAS_ITEM;
} else if (type == "particles") {
mode = MODE_PARTICLES;
} else if (type == "sky") {
mode = MODE_SKY;
} else if (type == "fog") {
mode = MODE_FOG;
} else {
mode = MODE_SPATIAL;
}
for (const Ref<ShaderInclude> &E : include_dependencies) { for (const Ref<ShaderInclude> &E : include_dependencies) {
E->connect(SNAME("changed"), callable_mp(this, &Shader::_dependency_changed)); E->connect(SNAME("changed"), callable_mp(this, &Shader::_dependency_changed));
} }

View File

@ -258,22 +258,10 @@ uint64_t RenderingServerDefault::get_rendering_info(RenderingInfo p_info) {
return RSG::utilities->get_rendering_info(p_info); return RSG::utilities->get_rendering_info(p_info);
} }
String RenderingServerDefault::get_video_adapter_name() const {
return RSG::utilities->get_video_adapter_name();
}
String RenderingServerDefault::get_video_adapter_vendor() const {
return RSG::utilities->get_video_adapter_vendor();
}
RenderingDevice::DeviceType RenderingServerDefault::get_video_adapter_type() const { RenderingDevice::DeviceType RenderingServerDefault::get_video_adapter_type() const {
return RSG::utilities->get_video_adapter_type(); return RSG::utilities->get_video_adapter_type();
} }
String RenderingServerDefault::get_video_adapter_api_version() const {
return RSG::utilities->get_video_adapter_api_version();
}
void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) { void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) {
RSG::utilities->capturing_timestamps = p_enable; RSG::utilities->capturing_timestamps = p_enable;
} }

View File

@ -945,10 +945,27 @@ public:
FUNC0(global_shader_parameters_clear) FUNC0(global_shader_parameters_clear)
#undef server_name #undef server_name
#undef ServerName
/* STATUS INFORMATION */
#define ServerName RendererUtilities
#define server_name RSG::utilities
FUNC0RC(String, get_video_adapter_name)
FUNC0RC(String, get_video_adapter_vendor)
FUNC0RC(String, get_video_adapter_api_version)
#undef server_name
#undef ServerName #undef ServerName
#undef WRITE_ACTION #undef WRITE_ACTION
#undef SYNC_DEBUG #undef SYNC_DEBUG
virtual uint64_t get_rendering_info(RenderingInfo p_info) override;
virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
virtual void set_frame_profiling_enabled(bool p_enable) override;
virtual Vector<FrameProfileArea> get_frame_profile() override;
virtual uint64_t get_frame_profile_frame() override;
virtual RID get_test_cube() override;
/* FREE */ /* FREE */
virtual void free(RID p_rid) override { virtual void free(RID p_rid) override {
@ -970,20 +987,6 @@ public:
virtual void init() override; virtual void init() override;
virtual void finish() override; virtual void finish() override;
/* STATUS INFORMATION */
virtual uint64_t get_rendering_info(RenderingInfo p_info) override;
virtual String get_video_adapter_name() const override;
virtual String get_video_adapter_vendor() const override;
virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
virtual String get_video_adapter_api_version() const override;
virtual void set_frame_profiling_enabled(bool p_enable) override;
virtual Vector<FrameProfileArea> get_frame_profile() override;
virtual uint64_t get_frame_profile_frame() override;
virtual RID get_test_cube() override;
/* TESTING */ /* TESTING */
virtual double get_frame_setup_time_cpu() const override; virtual double get_frame_setup_time_cpu() const override;

View File

@ -8619,7 +8619,12 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
} }
if (uniform.array_size > 0) { if (uniform.array_size > 0) {
if (tk.type != TK_HINT_SOURCE_COLOR) { static Vector<int> supported_hints = {
TK_HINT_SOURCE_COLOR, TK_REPEAT_DISABLE, TK_REPEAT_ENABLE,
TK_FILTER_LINEAR, TK_FILTER_LINEAR_MIPMAP, TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC,
TK_FILTER_NEAREST, TK_FILTER_NEAREST_MIPMAP, TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC
};
if (!supported_hints.has(tk.type)) {
_set_error(RTR("This hint is not supported for uniform arrays.")); _set_error(RTR("This hint is not supported for uniform arrays."));
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
@ -10544,19 +10549,23 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
} }
} else if ((int(completion_base) > int(TYPE_MAT4) && int(completion_base) < int(TYPE_STRUCT))) { } else if ((int(completion_base) > int(TYPE_MAT4) && int(completion_base) < int(TYPE_STRUCT))) {
Vector<String> options; Vector<String> options;
if (current_uniform_filter == FILTER_DEFAULT) {
options.push_back("filter_linear");
options.push_back("filter_linear_mipmap");
options.push_back("filter_linear_mipmap_anisotropic");
options.push_back("filter_nearest");
options.push_back("filter_nearest_mipmap");
options.push_back("filter_nearest_mipmap_anisotropic");
}
if (current_uniform_repeat == REPEAT_DEFAULT) {
options.push_back("repeat_enable");
options.push_back("repeat_disable");
}
if (completion_base_array) { if (completion_base_array) {
if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) { if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) {
options.push_back("source_color"); options.push_back("source_color");
} }
} else { } else {
if (current_uniform_filter == FILTER_DEFAULT) {
options.push_back("filter_linear");
options.push_back("filter_linear_mipmap");
options.push_back("filter_linear_mipmap_anisotropic");
options.push_back("filter_nearest");
options.push_back("filter_nearest_mipmap");
options.push_back("filter_nearest_mipmap_anisotropic");
}
if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) { if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) {
options.push_back("hint_anisotropy"); options.push_back("hint_anisotropy");
options.push_back("hint_default_black"); options.push_back("hint_default_black");
@ -10574,10 +10583,6 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
options.push_back("hint_depth_texture"); options.push_back("hint_depth_texture");
options.push_back("source_color"); options.push_back("source_color");
} }
if (current_uniform_repeat == REPEAT_DEFAULT) {
options.push_back("repeat_enable");
options.push_back("repeat_disable");
}
} }
for (int i = 0; i < options.size(); i++) { for (int i = 0; i < options.size(); i++) {

View File

@ -304,13 +304,31 @@ TEST_CASE("[Array] slice()") {
CHECK(slice8[1] == Variant(3)); CHECK(slice8[1] == Variant(3));
CHECK(slice8[2] == Variant(1)); CHECK(slice8[2] == Variant(1));
ERR_PRINT_OFF; Array slice9 = array.slice(10, 0, -2);
Array slice9 = array.slice(4, 1); CHECK(slice9.size() == 3);
CHECK(slice9.size() == 0); CHECK(slice9[0] == Variant(5));
CHECK(slice9[1] == Variant(3));
CHECK(slice9[2] == Variant(1));
Array slice10 = array.slice(3, -4); Array slice10 = array.slice(2, -10, -1);
CHECK(slice10.size() == 0); CHECK(slice10.size() == 3);
CHECK(slice10[0] == Variant(2));
CHECK(slice10[1] == Variant(1));
CHECK(slice10[2] == Variant(0));
ERR_PRINT_OFF;
Array slice11 = array.slice(4, 1);
CHECK(slice11.size() == 0);
Array slice12 = array.slice(3, -4);
CHECK(slice12.size() == 0);
ERR_PRINT_ON; ERR_PRINT_ON;
Array slice13 = Array().slice(1);
CHECK(slice13.size() == 0);
Array slice14 = array.slice(6);
CHECK(slice14.size() == 0);
} }
TEST_CASE("[Array] Duplicate array") { TEST_CASE("[Array] Duplicate array") {

32
thirdparty/README.md vendored
View File

@ -115,7 +115,7 @@ commits.
## enet ## enet
- Upstream: http://enet.bespin.org - Upstream: http://enet.bespin.org
- Version: 1.3.17 (e0e7045b7e056b454b5093cb34df49dc4cee0bee, 2020) - Version: git (ea4607a90dbfbcf4da2669ea998585253d8e70b1, 2023)
- License: MIT - License: MIT
Files extracted from upstream source: Files extracted from upstream source:
@ -178,14 +178,14 @@ Files extracted from upstream source:
## freetype ## freetype
- Upstream: https://www.freetype.org - Upstream: https://www.freetype.org
- Version: 2.13.0 (de8b92dd7ec634e9e2b25ef534c54a3537555c11, 2023) - Version: 2.13.2 (920c5502cc3ddda88f6c7d85ee834ac611bb11cc, 2023)
- License: FreeType License (BSD-like) - License: FreeType License (BSD-like)
Files extracted from upstream source: Files extracted from upstream source:
- `src/` folder, minus the `dlg` and `tools` subfolders - `src/` folder, minus the `dlg` and `tools` subfolders
* These files can be removed: `.dat`, `.diff`, `.mk`, `.rc`, `README*` * These files can be removed: `.dat`, `.diff`, `.mk`, `.rc`, `README*`
* In `src/gzip/`, remove zlib files (everything but `ftgzip.c` and `ftzconf.h`) * In `src/gzip/`, keep only `ftgzip.c`
- `include/` folder, minus the `dlg` subfolder - `include/` folder, minus the `dlg` subfolder
- `LICENSE.TXT` and `docs/FTL.TXT` - `LICENSE.TXT` and `docs/FTL.TXT`
@ -264,7 +264,7 @@ Files extracted from upstream source:
## icu4c ## icu4c
- Upstream: https://github.com/unicode-org/icu - Upstream: https://github.com/unicode-org/icu
- Version: 73.1 (5861e1fd52f1d7673eee38bc3c965aa18b336062, 2023) - Version: 73.2 (680f521746a3bd6a86f25f25ee50a62d88b489cf, 2023)
- License: Unicode - License: Unicode
Files extracted from upstream source: Files extracted from upstream source:
@ -280,10 +280,11 @@ Files generated from upstream source:
https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md
for instructions). for instructions).
- Step 1: Build ICU with default options - `./runConfigureICU {PLATFORM} && make`. - Step 1: Download and extract both `icu4c-{version}-src.tgz` and `icu4c-{version}-data.zip` (replace `data` subfolder from the main source archive).
- 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 2: Build ICU with default options - `./runConfigureICU {PLATFORM} && make`.
- Step 3: Delete `data/out` folder and rebuild data - `cd data && rm -rf ./out && make`. - Step 3: Reconfigure ICU with custom data config - `ICU_DATA_FILTER_FILE={GODOT_SOURCE}/thirdparty/icu4c/godot_data.json ./runConfigureICU {PLATFORM} --with-data-packaging=common`.
- Step 4: Copy `source/data/out/icudt73l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt73l.dat`. - Step 4: Delete `data/out` folder and rebuild data - `cd data && rm -rf ./out && make`.
- Step 5: Copy `source/data/out/icudt73l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt73l.dat`.
## jpeg-compressor ## jpeg-compressor
@ -314,14 +315,14 @@ Files extracted from upstream source:
## libpng ## libpng
- Upstream: http://libpng.org/pub/png/libpng.html - Upstream: http://libpng.org/pub/png/libpng.html
- Version: 1.6.38 (0a158f3506502dfa23edfc42790dfaed82efba17, 2022) - Version: 1.6.40 (f135775ad4e5d4408d2e12ffcc71bb36e6b48551, 2023)
- License: libpng/zlib - License: libpng/zlib
Files extracted from upstream source: Files extracted from upstream source:
- all .c and .h files of the main directory, except from - all .c and .h files of the main directory, except from
`example.c` and `pngtest.c` `example.c` and `pngtest.c`
- the arm/ folder - `arm/`, `intel/` and `powerpc/` folders
- `scripts/pnglibconf.h.prebuilt` as `pnglibconf.h` - `scripts/pnglibconf.h.prebuilt` as `pnglibconf.h`
- `LICENSE` - `LICENSE`
@ -355,7 +356,7 @@ Files extracted from upstream source:
## libwebp ## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/ - Upstream: https://chromium.googlesource.com/webm/libwebp/
- Version: 1.3.0 (b557776962a3dcc985d83bd4ed94e1e2e50d0fa2, 2022) - Version: 1.3.1 (fd7bb21c0cb56e8a82e9bfa376164b842f433f3b, 2023)
- License: BSD-3-Clause - License: BSD-3-Clause
Files extracted from upstream source: Files extracted from upstream source:
@ -369,7 +370,7 @@ Patch `godot-node-debug-fix.patch` workarounds shadowing of godot's Node class i
## mbedtls ## mbedtls
- Upstream: https://github.com/Mbed-TLS/mbedtls - Upstream: https://github.com/Mbed-TLS/mbedtls
- Version: 2.18.3 (981743de6fcdbe672e482b6fd724d31d0a0d2476, 2023) - Version: 2.28.4 (aeb97a18913a86f051afab11b2c92c6be0c2eb83, 2023)
- License: Apache 2.0 - License: Apache 2.0
File extracted from upstream release tarball: File extracted from upstream release tarball:
@ -421,7 +422,7 @@ to solve some MSVC warnings. See the patches in the `patches` directory.
## miniupnpc ## miniupnpc
- Upstream: https://github.com/miniupnp/miniupnp - Upstream: https://github.com/miniupnp/miniupnp
- Version: 2.2.4 (7d1d8bc3868b08ad003bad235eee57562b95b76d, 2022) - Version: 2.2.5 (58837ef586278d18cbebee50be758835ed4be79a, 2023)
- License: BSD-3-Clause - License: BSD-3-Clause
Files extracted from upstream source: Files extracted from upstream source:
@ -582,7 +583,7 @@ Patch files are provided in `oidn/patches/`.
## openxr ## openxr
- Upstream: https://github.com/KhronosGroup/OpenXR-SDK - Upstream: https://github.com/KhronosGroup/OpenXR-SDK
- Version: 1.0.26 (e2da9ce83a4388c9622da328bf48548471261290, 2022) - Version: 1.0.28 (f5beb0131f1bea8701ace744d1b50df9049bf331, 2023)
- License: Apache 2.0 - License: Apache 2.0
Files extracted from upstream source: Files extracted from upstream source:
@ -600,7 +601,8 @@ Exclude:
- src/external/android-jni-wrappers and src/external/jnipp (not used yet) - src/external/android-jni-wrappers and src/external/jnipp (not used yet)
- All CMake stuff: cmake/, CMakeLists.txt and *.cmake - All CMake stuff: cmake/, CMakeLists.txt and *.cmake
- All Gradle stuff: *gradle*, AndroidManifest.xml - All Gradle stuff: *gradle*, AndroidManifest.xml
- All following files (and their .license files): *.{def,in,json,map,pom,rc} - All following files (and their .license files): *.{def,expsym,in,json,map,pom,rc,txt}
- All dotfiles
## pcre2 ## pcre2

View File

@ -68,7 +68,8 @@ typedef enum _ENetSocketOption
ENET_SOCKOPT_RCVTIMEO = 6, ENET_SOCKOPT_RCVTIMEO = 6,
ENET_SOCKOPT_SNDTIMEO = 7, ENET_SOCKOPT_SNDTIMEO = 7,
ENET_SOCKOPT_ERROR = 8, ENET_SOCKOPT_ERROR = 8,
ENET_SOCKOPT_NODELAY = 9 ENET_SOCKOPT_NODELAY = 9,
ENET_SOCKOPT_TTL = 10
} ENetSocketOption; } ENetSocketOption;
typedef enum _ENetSocketShutdown typedef enum _ENetSocketShutdown
@ -179,7 +180,7 @@ typedef struct _ENetOutgoingCommand
enet_uint16 unreliableSequenceNumber; enet_uint16 unreliableSequenceNumber;
enet_uint32 sentTime; enet_uint32 sentTime;
enet_uint32 roundTripTimeout; enet_uint32 roundTripTimeout;
enet_uint32 roundTripTimeoutLimit; enet_uint32 queueTime;
enet_uint32 fragmentOffset; enet_uint32 fragmentOffset;
enet_uint16 fragmentLength; enet_uint16 fragmentLength;
enet_uint16 sendAttempts; enet_uint16 sendAttempts;
@ -222,7 +223,7 @@ enum
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024, ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024,
ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000,
ENET_HOST_DEFAULT_MTU = 1400, ENET_HOST_DEFAULT_MTU = 1392,
ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024,
ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024,
@ -262,7 +263,8 @@ typedef struct _ENetChannel
typedef enum _ENetPeerFlag typedef enum _ENetPeerFlag
{ {
ENET_PEER_FLAG_NEEDS_DISPATCH = (1 << 0) ENET_PEER_FLAG_NEEDS_DISPATCH = (1 << 0),
ENET_PEER_FLAG_CONTINUE_SENDING = (1 << 1)
} ENetPeerFlag; } ENetPeerFlag;
/** /**
@ -322,7 +324,7 @@ typedef struct _ENetPeer
enet_uint16 outgoingReliableSequenceNumber; enet_uint16 outgoingReliableSequenceNumber;
ENetList acknowledgements; ENetList acknowledgements;
ENetList sentReliableCommands; ENetList sentReliableCommands;
ENetList sentUnreliableCommands; ENetList outgoingSendReliableCommands;
ENetList outgoingCommands; ENetList outgoingCommands;
ENetList dispatchedCommands; ENetList dispatchedCommands;
enet_uint16 flags; enet_uint16 flags;
@ -385,7 +387,7 @@ typedef struct _ENetHost
size_t channelLimit; /**< maximum number of channels allowed for connected peers */ size_t channelLimit; /**< maximum number of channels allowed for connected peers */
enet_uint32 serviceTime; enet_uint32 serviceTime;
ENetList dispatchQueue; ENetList dispatchQueue;
int continueSending; enet_uint32 totalQueued;
size_t packetSize; size_t packetSize;
enet_uint16 headerFlags; enet_uint16 headerFlags;
ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS]; ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
@ -585,6 +587,7 @@ ENET_API void enet_host_channel_limit (ENetHost *, size_t);
ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32); ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
extern void enet_host_bandwidth_throttle (ENetHost *); extern void enet_host_bandwidth_throttle (ENetHost *);
extern enet_uint32 enet_host_random_seed (void); extern enet_uint32 enet_host_random_seed (void);
extern enet_uint32 enet_host_random (ENetHost *);
ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *); ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID); ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
@ -598,6 +601,7 @@ ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32
ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
extern int enet_peer_throttle (ENetPeer *, enet_uint32); extern int enet_peer_throttle (ENetPeer *, enet_uint32);
extern void enet_peer_reset_queues (ENetPeer *); extern void enet_peer_reset_queues (ENetPeer *);
extern int enet_peer_has_outgoing_commands (ENetPeer *);
extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *); extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *);
extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16); extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16);
extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32); extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32);

View File

@ -535,6 +535,10 @@ int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buf
if (err == ERR_BUSY) { if (err == ERR_BUSY) {
return 0; return 0;
} }
if (err == ERR_OUT_OF_MEMORY) {
// A packet above the ENET_PROTOCOL_MAXIMUM_MTU was received.
return -2;
}
if (err != OK) { if (err != OK) {
return -1; return -1;

View File

@ -96,6 +96,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
host -> totalSentPackets = 0; host -> totalSentPackets = 0;
host -> totalReceivedData = 0; host -> totalReceivedData = 0;
host -> totalReceivedPackets = 0; host -> totalReceivedPackets = 0;
host -> totalQueued = 0;
host -> connectedPeers = 0; host -> connectedPeers = 0;
host -> bandwidthLimitedPeers = 0; host -> bandwidthLimitedPeers = 0;
@ -123,8 +124,8 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
enet_list_clear (& currentPeer -> acknowledgements); enet_list_clear (& currentPeer -> acknowledgements);
enet_list_clear (& currentPeer -> sentReliableCommands); enet_list_clear (& currentPeer -> sentReliableCommands);
enet_list_clear (& currentPeer -> sentUnreliableCommands);
enet_list_clear (& currentPeer -> outgoingCommands); enet_list_clear (& currentPeer -> outgoingCommands);
enet_list_clear (& currentPeer -> outgoingSendReliableCommands);
enet_list_clear (& currentPeer -> dispatchedCommands); enet_list_clear (& currentPeer -> dispatchedCommands);
enet_peer_reset (currentPeer); enet_peer_reset (currentPeer);
@ -160,6 +161,16 @@ enet_host_destroy (ENetHost * host)
enet_free (host); enet_free (host);
} }
enet_uint32
enet_host_random (ENetHost * host)
{
/* Mulberry32 by Tommy Ettinger */
enet_uint32 n = (host -> randomSeed += 0x6D2B79F5U);
n = (n ^ (n >> 15)) * (n | 1U);
n ^= n + (n ^ (n >> 7)) * (n | 61U);
return n ^ (n >> 14);
}
/** Initiates a connection to a foreign host. /** Initiates a connection to a foreign host.
@param host host seeking the connection @param host host seeking the connection
@param address destination for the connection @param address destination for the connection
@ -199,7 +210,8 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC
currentPeer -> channelCount = channelCount; currentPeer -> channelCount = channelCount;
currentPeer -> state = ENET_PEER_STATE_CONNECTING; currentPeer -> state = ENET_PEER_STATE_CONNECTING;
currentPeer -> address = * address; currentPeer -> address = * address;
currentPeer -> connectID = ++ host -> randomSeed; currentPeer -> connectID = enet_host_random (host);
currentPeer -> mtu = host -> mtu;
if (host -> outgoingBandwidth == 0) if (host -> outgoingBandwidth == 0)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;

View File

@ -98,53 +98,46 @@ enet_packet_resize (ENetPacket * packet, size_t dataLength)
return 0; return 0;
} }
static int initializedCRC32 = 0; static const enet_uint32 crcTable [256] =
static enet_uint32 crcTable [256];
static enet_uint32
reflect_crc (int val, int bits)
{ {
int result = 0, bit; 0, 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, 0x5005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0xBDBDF21,
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
};
for (bit = 0; bit < bits; bit ++)
{
if(val & 1) result |= 1 << (bits - 1 - bit);
val >>= 1;
}
return result;
}
static void
initialize_crc32 (void)
{
int byte;
for (byte = 0; byte < 256; ++ byte)
{
enet_uint32 crc = reflect_crc (byte, 8) << 24;
int offset;
for(offset = 0; offset < 8; ++ offset)
{
if (crc & 0x80000000)
crc = (crc << 1) ^ 0x04c11db7;
else
crc <<= 1;
}
crcTable [byte] = reflect_crc (crc, 32);
}
initializedCRC32 = 1;
}
enet_uint32 enet_uint32
enet_crc32 (const ENetBuffer * buffers, size_t bufferCount) enet_crc32 (const ENetBuffer * buffers, size_t bufferCount)
{ {
enet_uint32 crc = 0xFFFFFFFF; enet_uint32 crc = 0xFFFFFFFF;
if (! initializedCRC32) initialize_crc32 ();
while (bufferCount -- > 0) while (bufferCount -- > 0)
{ {
@ -153,7 +146,7 @@ enet_crc32 (const ENetBuffer * buffers, size_t bufferCount)
while (data < dataEnd) while (data < dataEnd)
{ {
crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++]; crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++];
} }
++ buffers; ++ buffers;

View File

@ -90,6 +90,13 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
} }
/** Queues a packet to be sent. /** Queues a packet to be sent.
On success, ENet will assume ownership of the packet, and so enet_packet_destroy
should not be called on it thereafter. On failure, the caller still must destroy
the packet on its own as ENet has not queued the packet. The caller can also
check the packet's referenceCount field after sending to check if ENet queued
the packet and thus incremented the referenceCount.
@param peer destination for the packet @param peer destination for the packet
@param channelID channel on which to send @param channelID channel on which to send
@param packet packet to send @param packet packet to send
@ -99,7 +106,7 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
int int
enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
{ {
ENetChannel * channel = & peer -> channels [channelID]; ENetChannel * channel;
ENetProtocol command; ENetProtocol command;
size_t fragmentLength; size_t fragmentLength;
@ -108,6 +115,7 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
packet -> dataLength > peer -> host -> maximumPacketSize) packet -> dataLength > peer -> host -> maximumPacketSize)
return -1; return -1;
channel = & peer -> channels [channelID];
fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment); fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
if (peer -> host -> checksum != NULL) if (peer -> host -> checksum != NULL)
fragmentLength -= sizeof(enet_uint32); fragmentLength -= sizeof(enet_uint32);
@ -320,8 +328,8 @@ enet_peer_reset_queues (ENetPeer * peer)
enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements))); enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements)));
enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands); enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands);
enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingCommands); enet_peer_reset_outgoing_commands (& peer -> outgoingCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingSendReliableCommands);
enet_peer_reset_incoming_commands (& peer -> dispatchedCommands); enet_peer_reset_incoming_commands (& peer -> dispatchedCommands);
if (peer -> channels != NULL && peer -> channelCount > 0) if (peer -> channels != NULL && peer -> channelCount > 0)
@ -563,6 +571,17 @@ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
} }
} }
int
enet_peer_has_outgoing_commands (ENetPeer * peer)
{
if (enet_list_empty (& peer -> outgoingCommands) &&
enet_list_empty (& peer -> outgoingSendReliableCommands) &&
enet_list_empty (& peer -> sentReliableCommands))
return 0;
return 1;
}
/** Request a disconnection from a peer, but only after all queued outgoing packets are sent. /** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
@param peer peer to request a disconnection @param peer peer to request a disconnection
@param data data describing the disconnection @param data data describing the disconnection
@ -573,8 +592,7 @@ void
enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data) enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
{ {
if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) && if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) &&
! (enet_list_empty (& peer -> outgoingCommands) && enet_peer_has_outgoing_commands (peer))
enet_list_empty (& peer -> sentReliableCommands)))
{ {
peer -> state = ENET_PEER_STATE_DISCONNECT_LATER; peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
peer -> eventData = data; peer -> eventData = data;
@ -618,8 +636,6 @@ enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command,
void void
enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand) enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand)
{ {
ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength; peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength;
if (outgoingCommand -> command.header.channelID == 0xFF) if (outgoingCommand -> command.header.channelID == 0xFF)
@ -630,36 +646,40 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin
outgoingCommand -> unreliableSequenceNumber = 0; outgoingCommand -> unreliableSequenceNumber = 0;
} }
else else
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
{ {
++ channel -> outgoingReliableSequenceNumber; ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
channel -> outgoingUnreliableSequenceNumber = 0;
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber; if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
outgoingCommand -> unreliableSequenceNumber = 0; {
} ++ channel -> outgoingReliableSequenceNumber;
else channel -> outgoingUnreliableSequenceNumber = 0;
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
{
++ peer -> outgoingUnsequencedGroup;
outgoingCommand -> reliableSequenceNumber = 0; outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = 0; outgoingCommand -> unreliableSequenceNumber = 0;
}
else
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
{
++ peer -> outgoingUnsequencedGroup;
outgoingCommand -> reliableSequenceNumber = 0;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
{
if (outgoingCommand -> fragmentOffset == 0)
++ channel -> outgoingUnreliableSequenceNumber;
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
}
} }
else
{
if (outgoingCommand -> fragmentOffset == 0)
++ channel -> outgoingUnreliableSequenceNumber;
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
}
outgoingCommand -> sendAttempts = 0; outgoingCommand -> sendAttempts = 0;
outgoingCommand -> sentTime = 0; outgoingCommand -> sentTime = 0;
outgoingCommand -> roundTripTimeout = 0; outgoingCommand -> roundTripTimeout = 0;
outgoingCommand -> roundTripTimeoutLimit = 0;
outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber); outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber);
outgoingCommand -> queueTime = ++ peer -> host -> totalQueued;
switch (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) switch (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK)
{ {
@ -670,12 +690,16 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin
case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
outgoingCommand -> command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup); outgoingCommand -> command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup);
break; break;
default: default:
break; break;
} }
enet_list_insert (enet_list_end (& peer -> outgoingCommands), outgoingCommand); if ((outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0 &&
outgoingCommand -> packet != NULL)
enet_list_insert (enet_list_end (& peer -> outgoingSendReliableCommands), outgoingCommand);
else
enet_list_insert (enet_list_end (& peer -> outgoingCommands), outgoingCommand);
} }
ENetOutgoingCommand * ENetOutgoingCommand *

View File

@ -9,7 +9,7 @@
#include "enet/time.h" #include "enet/time.h"
#include "enet/enet.h" #include "enet/enet.h"
static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] = static const size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
{ {
0, 0,
sizeof (ENetProtocolAcknowledge), sizeof (ENetProtocolAcknowledge),
@ -159,16 +159,16 @@ enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * e
} }
static void static void
enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer, ENetList * sentUnreliableCommands)
{ {
ENetOutgoingCommand * outgoingCommand; ENetOutgoingCommand * outgoingCommand;
if (enet_list_empty (& peer -> sentUnreliableCommands)) if (enet_list_empty (sentUnreliableCommands))
return; return;
do do
{ {
outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands); outgoingCommand = (ENetOutgoingCommand *) enet_list_front (sentUnreliableCommands);
enet_list_remove (& outgoingCommand -> outgoingCommandList); enet_list_remove (& outgoingCommand -> outgoingCommandList);
@ -185,14 +185,38 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
} }
enet_free (outgoingCommand); enet_free (outgoingCommand);
} while (! enet_list_empty (& peer -> sentUnreliableCommands)); } while (! enet_list_empty (sentUnreliableCommands));
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
enet_list_empty (& peer -> outgoingCommands) && ! enet_peer_has_outgoing_commands (peer))
enet_list_empty (& peer -> sentReliableCommands))
enet_peer_disconnect (peer, peer -> eventData); enet_peer_disconnect (peer, peer -> eventData);
} }
static ENetOutgoingCommand *
enet_protocol_find_sent_reliable_command (ENetList * list, enet_uint16 reliableSequenceNumber, enet_uint8 channelID)
{
ENetListIterator currentCommand;
for (currentCommand = enet_list_begin (list);
currentCommand != enet_list_end (list);
currentCommand = enet_list_next (currentCommand))
{
ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) currentCommand;
if (! (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE))
continue;
if (outgoingCommand -> sendAttempts < 1)
break;
if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
outgoingCommand -> command.header.channelID == channelID)
return outgoingCommand;
}
return NULL;
}
static ENetProtocolCommand static ENetProtocolCommand
enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID) enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID)
{ {
@ -214,24 +238,9 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl
if (currentCommand == enet_list_end (& peer -> sentReliableCommands)) if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
{ {
for (currentCommand = enet_list_begin (& peer -> outgoingCommands); outgoingCommand = enet_protocol_find_sent_reliable_command (& peer -> outgoingCommands, reliableSequenceNumber, channelID);
currentCommand != enet_list_end (& peer -> outgoingCommands); if (outgoingCommand == NULL)
currentCommand = enet_list_next (currentCommand)) outgoingCommand = enet_protocol_find_sent_reliable_command (& peer -> outgoingSendReliableCommands, reliableSequenceNumber, channelID);
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
if (! (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE))
continue;
if (outgoingCommand -> sendAttempts < 1) return ENET_PROTOCOL_COMMAND_NONE;
if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
outgoingCommand -> command.header.channelID == channelID)
break;
}
if (currentCommand == enet_list_end (& peer -> outgoingCommands))
return ENET_PROTOCOL_COMMAND_NONE;
wasSent = 0; wasSent = 0;
} }
@ -331,6 +340,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
peer -> connectID = command -> connect.connectID; peer -> connectID = command -> connect.connectID;
peer -> address = host -> receivedAddress; peer -> address = host -> receivedAddress;
peer -> mtu = host -> mtu;
peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID); peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID);
peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth); peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth);
peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth); peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth);
@ -375,7 +385,8 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
mtu = ENET_PROTOCOL_MAXIMUM_MTU; mtu = ENET_PROTOCOL_MAXIMUM_MTU;
peer -> mtu = mtu; if (mtu < peer -> mtu)
peer -> mtu = mtu;
if (host -> outgoingBandwidth == 0 && if (host -> outgoingBandwidth == 0 &&
peer -> incomingBandwidth == 0) peer -> incomingBandwidth == 0)
@ -542,7 +553,8 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet
fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength); fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
* currentData += fragmentLength; * currentData += fragmentLength;
if (fragmentLength > host -> maximumPacketSize || if (fragmentLength <= 0 ||
fragmentLength > host -> maximumPacketSize ||
* currentData < host -> receivedData || * currentData < host -> receivedData ||
* currentData > & host -> receivedData [host -> receivedDataLength]) * currentData > & host -> receivedData [host -> receivedDataLength])
return -1; return -1;
@ -566,6 +578,7 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet
if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT ||
fragmentNumber >= fragmentCount || fragmentNumber >= fragmentCount ||
totalLength > host -> maximumPacketSize || totalLength > host -> maximumPacketSize ||
totalLength < fragmentCount ||
fragmentOffset >= totalLength || fragmentOffset >= totalLength ||
fragmentLength > totalLength - fragmentOffset) fragmentLength > totalLength - fragmentOffset)
return -1; return -1;
@ -921,8 +934,7 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer *
break; break;
case ENET_PEER_STATE_DISCONNECT_LATER: case ENET_PEER_STATE_DISCONNECT_LATER:
if (enet_list_empty (& peer -> outgoingCommands) && if (! enet_peer_has_outgoing_commands (peer))
enet_list_empty (& peer -> sentReliableCommands))
enet_peer_disconnect (peer, peer -> eventData); enet_peer_disconnect (peer, peer -> eventData);
break; break;
@ -1230,6 +1242,9 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
& buffer, & buffer,
1); 1);
if (receivedLength == -2)
continue;
if (receivedLength < 0) if (receivedLength < 0)
return -1; return -1;
@ -1293,7 +1308,7 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] || buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge)) peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
{ {
host -> continueSending = 1; peer -> flags |= ENET_PEER_FLAG_CONTINUE_SENDING;
break; break;
} }
@ -1333,10 +1348,11 @@ static int
enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event) enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
{ {
ENetOutgoingCommand * outgoingCommand; ENetOutgoingCommand * outgoingCommand;
ENetListIterator currentCommand, insertPosition; ENetListIterator currentCommand, insertPosition, insertSendReliablePosition;
currentCommand = enet_list_begin (& peer -> sentReliableCommands); currentCommand = enet_list_begin (& peer -> sentReliableCommands);
insertPosition = enet_list_begin (& peer -> outgoingCommands); insertPosition = enet_list_begin (& peer -> outgoingCommands);
insertSendReliablePosition = enet_list_begin (& peer -> outgoingSendReliableCommands);
while (currentCommand != enet_list_end (& peer -> sentReliableCommands)) while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
{ {
@ -1353,7 +1369,7 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even
if (peer -> earliestTimeout != 0 && if (peer -> earliestTimeout != 0 &&
(ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum || (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum ||
(outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit && ((1 << (outgoingCommand -> sendAttempts - 1)) >= peer -> timeoutLimit &&
ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum))) ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum)))
{ {
enet_protocol_notify_disconnect (host, peer, event); enet_protocol_notify_disconnect (host, peer, event);
@ -1361,14 +1377,18 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even
return 1; return 1;
} }
if (outgoingCommand -> packet != NULL)
peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
++ peer -> packetsLost; ++ peer -> packetsLost;
outgoingCommand -> roundTripTimeout *= 2; outgoingCommand -> roundTripTimeout *= 2;
enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList)); if (outgoingCommand -> packet != NULL)
{
peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
enet_list_insert (insertSendReliablePosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
}
else
enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) && if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
! enet_list_empty (& peer -> sentReliableCommands)) ! enet_list_empty (& peer -> sentReliableCommands))
@ -1383,22 +1403,41 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even
} }
static int static int
enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer) enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer, ENetList * sentUnreliableCommands)
{ {
ENetProtocol * command = & host -> commands [host -> commandCount]; ENetProtocol * command = & host -> commands [host -> commandCount];
ENetBuffer * buffer = & host -> buffers [host -> bufferCount]; ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
ENetOutgoingCommand * outgoingCommand; ENetOutgoingCommand * outgoingCommand;
ENetListIterator currentCommand; ENetListIterator currentCommand, currentSendReliableCommand;
ENetChannel *channel; ENetChannel *channel = NULL;
enet_uint16 reliableWindow; enet_uint16 reliableWindow = 0;
size_t commandSize; size_t commandSize;
int windowExceeded = 0, windowWrap = 0, canPing = 1; int windowWrap = 0, canPing = 1;
currentCommand = enet_list_begin (& peer -> outgoingCommands); currentCommand = enet_list_begin (& peer -> outgoingCommands);
currentSendReliableCommand = enet_list_begin (& peer -> outgoingSendReliableCommands);
while (currentCommand != enet_list_end (& peer -> outgoingCommands))
for (;;)
{ {
outgoingCommand = (ENetOutgoingCommand *) currentCommand; if (currentCommand != enet_list_end (& peer -> outgoingCommands))
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
if (currentSendReliableCommand != enet_list_end (& peer -> outgoingSendReliableCommands) &&
ENET_TIME_LESS (((ENetOutgoingCommand *) currentSendReliableCommand) -> queueTime, outgoingCommand -> queueTime))
goto useSendReliableCommand;
currentCommand = enet_list_next (currentCommand);
}
else
if (currentSendReliableCommand != enet_list_end (& peer -> outgoingSendReliableCommands))
{
useSendReliableCommand:
outgoingCommand = (ENetOutgoingCommand *) currentSendReliableCommand;
currentSendReliableCommand = enet_list_next (currentSendReliableCommand);
}
else
break;
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
{ {
@ -1406,33 +1445,29 @@ enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer)
reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
if (channel != NULL) if (channel != NULL)
{ {
if (! windowWrap && if (windowWrap)
outgoingCommand -> sendAttempts < 1 && continue;
else
if (outgoingCommand -> sendAttempts < 1 &&
! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) && ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) &&
(channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE || (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE ||
channel -> usedReliableWindows & ((((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) << reliableWindow) | channel -> usedReliableWindows & ((((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) << reliableWindow) |
(((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow))))) (((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow)))))
windowWrap = 1;
if (windowWrap)
{ {
currentCommand = enet_list_next (currentCommand); windowWrap = 1;
currentSendReliableCommand = enet_list_end (& peer -> outgoingSendReliableCommands);
continue; continue;
} }
} }
if (outgoingCommand -> packet != NULL) if (outgoingCommand -> packet != NULL)
{ {
if (! windowExceeded) enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE;
if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu))
{ {
enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE; currentSendReliableCommand = enet_list_end (& peer -> outgoingSendReliableCommands);
if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu))
windowExceeded = 1;
}
if (windowExceeded)
{
currentCommand = enet_list_next (currentCommand);
continue; continue;
} }
@ -1448,13 +1483,11 @@ enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer)
(outgoingCommand -> packet != NULL && (outgoingCommand -> packet != NULL &&
(enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength))) (enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength)))
{ {
host -> continueSending = 1; peer -> flags |= ENET_PEER_FLAG_CONTINUE_SENDING;
break; break;
} }
currentCommand = enet_list_next (currentCommand);
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
{ {
if (channel != NULL && outgoingCommand -> sendAttempts < 1) if (channel != NULL && outgoingCommand -> sendAttempts < 1)
@ -1466,10 +1499,7 @@ enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer)
++ outgoingCommand -> sendAttempts; ++ outgoingCommand -> sendAttempts;
if (outgoingCommand -> roundTripTimeout == 0) if (outgoingCommand -> roundTripTimeout == 0)
{ outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout;
}
if (enet_list_empty (& peer -> sentReliableCommands)) if (enet_list_empty (& peer -> sentReliableCommands))
peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout; peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout;
@ -1522,7 +1552,7 @@ enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer)
enet_list_remove (& outgoingCommand -> outgoingCommandList); enet_list_remove (& outgoingCommand -> outgoingCommandList);
if (outgoingCommand -> packet != NULL) if (outgoingCommand -> packet != NULL)
enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand); enet_list_insert (enet_list_end (sentUnreliableCommands), outgoingCommand);
} }
buffer -> data = command; buffer -> data = command;
@ -1555,9 +1585,8 @@ enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer)
host -> bufferCount = buffer - host -> buffers; host -> bufferCount = buffer - host -> buffers;
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
enet_list_empty (& peer -> outgoingCommands) && ! enet_peer_has_outgoing_commands (peer) &&
enet_list_empty (& peer -> sentReliableCommands) && enet_list_empty (sentUnreliableCommands))
enet_list_empty (& peer -> sentUnreliableCommands))
enet_peer_disconnect (peer, peer -> eventData); enet_peer_disconnect (peer, peer -> eventData);
return canPing; return canPing;
@ -1568,22 +1597,24 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
{ {
enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)]; enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)];
ENetProtocolHeader * header = (ENetProtocolHeader *) headerData; ENetProtocolHeader * header = (ENetProtocolHeader *) headerData;
ENetPeer * currentPeer; int sentLength = 0;
int sentLength;
size_t shouldCompress = 0; size_t shouldCompress = 0;
ENetList sentUnreliableCommands;
host -> continueSending = 1;
while (host -> continueSending) enet_list_clear (& sentUnreliableCommands);
for (host -> continueSending = 0,
currentPeer = host -> peers; for (int sendPass = 0, continueSending = 0; sendPass <= continueSending; ++ sendPass)
for (ENetPeer * currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount]; currentPeer < & host -> peers [host -> peerCount];
++ currentPeer) ++ currentPeer)
{ {
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED || if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
currentPeer -> state == ENET_PEER_STATE_ZOMBIE) currentPeer -> state == ENET_PEER_STATE_ZOMBIE ||
(sendPass > 0 && ! (currentPeer -> flags & ENET_PEER_FLAG_CONTINUE_SENDING)))
continue; continue;
currentPeer -> flags &= ~ ENET_PEER_FLAG_CONTINUE_SENDING;
host -> headerFlags = 0; host -> headerFlags = 0;
host -> commandCount = 0; host -> commandCount = 0;
host -> bufferCount = 1; host -> bufferCount = 1;
@ -1600,21 +1631,22 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE) if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
return 1; return 1;
else else
continue; goto nextPeer;
} }
if ((enet_list_empty (& currentPeer -> outgoingCommands) || if (((enet_list_empty (& currentPeer -> outgoingCommands) &&
enet_protocol_check_outgoing_commands (host, currentPeer)) && enet_list_empty (& currentPeer -> outgoingSendReliableCommands)) ||
enet_protocol_check_outgoing_commands (host, currentPeer, & sentUnreliableCommands)) &&
enet_list_empty (& currentPeer -> sentReliableCommands) && enet_list_empty (& currentPeer -> sentReliableCommands) &&
ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= currentPeer -> pingInterval && ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= currentPeer -> pingInterval &&
currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing)) currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
{ {
enet_peer_ping (currentPeer); enet_peer_ping (currentPeer);
enet_protocol_check_outgoing_commands (host, currentPeer); enet_protocol_check_outgoing_commands (host, currentPeer, & sentUnreliableCommands);
} }
if (host -> commandCount == 0) if (host -> commandCount == 0)
continue; goto nextPeer;
if (currentPeer -> packetLossEpoch == 0) if (currentPeer -> packetLossEpoch == 0)
currentPeer -> packetLossEpoch = host -> serviceTime; currentPeer -> packetLossEpoch = host -> serviceTime;
@ -1625,7 +1657,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent; enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
#ifdef ENET_DEBUG #ifdef ENET_DEBUG
printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0); printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingCommands) + enet_list_size (& currentPeer -> outgoingSendReliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0);
#endif #endif
currentPeer -> packetLossVariance = (currentPeer -> packetLossVariance * 3 + ENET_DIFFERENCE (packetLoss, currentPeer -> packetLoss)) / 4; currentPeer -> packetLossVariance = (currentPeer -> packetLossVariance * 3 + ENET_DIFFERENCE (packetLoss, currentPeer -> packetLoss)) / 4;
@ -1687,13 +1719,17 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount); sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
enet_protocol_remove_sent_unreliable_commands (currentPeer); enet_protocol_remove_sent_unreliable_commands (currentPeer, & sentUnreliableCommands);
if (sentLength < 0) if (sentLength < 0)
return -1; return -1;
host -> totalSentData += sentLength; host -> totalSentData += sentLength;
host -> totalSentPackets ++; host -> totalSentPackets ++;
nextPeer:
if (currentPeer -> flags & ENET_PEER_FLAG_CONTINUE_SENDING)
continueSending = sendPass + 1;
} }
return 0; return 0;

View File

@ -661,36 +661,12 @@ FT_BEGIN_HEADER
* not) instructions in a certain way so that all TrueType fonts look like * not) instructions in a certain way so that all TrueType fonts look like
* they do in a Windows ClearType (DirectWrite) environment. See [1] for a * they do in a Windows ClearType (DirectWrite) environment. See [1] for a
* technical overview on what this means. See `ttinterp.h` for more * technical overview on what this means. See `ttinterp.h` for more
* details on the LEAN option. * details on this option.
* *
* There are three possible values. * The new default mode focuses on applying a minimal set of rules to all
* * fonts indiscriminately so that modern and web fonts render well while
* Value 1: * legacy fonts render okay. The corresponding interpreter version is v40.
* This value is associated with the 'Infinality' moniker, contributed by * The so-called Infinality mode (v38) is no longer available in FreeType.
* an individual nicknamed Infinality with the goal of making TrueType
* fonts render better than on Windows. A high amount of configurability
* and flexibility, down to rules for single glyphs in fonts, but also
* very slow. Its experimental and slow nature and the original
* developer losing interest meant that this option was never enabled in
* default builds.
*
* The corresponding interpreter version is v38.
*
* Value 2:
* The new default mode for the TrueType driver. The Infinality code
* base was stripped to the bare minimum and all configurability removed
* in the name of speed and simplicity. The configurability was mainly
* aimed at legacy fonts like 'Arial', 'Times New Roman', or 'Courier'.
* Legacy fonts are fonts that modify vertical stems to achieve clean
* black-and-white bitmaps. The new mode focuses on applying a minimal
* set of rules to all fonts indiscriminately so that modern and web
* fonts render well while legacy fonts render okay.
*
* The corresponding interpreter version is v40.
*
* Value 3:
* Compile both, making both v38 and v40 available (the latter is the
* default).
* *
* By undefining these, you get rendering behavior like on Windows without * By undefining these, you get rendering behavior like on Windows without
* ClearType, i.e., Windows XP without ClearType enabled and Win9x * ClearType, i.e., Windows XP without ClearType enabled and Win9x
@ -705,9 +681,7 @@ FT_BEGIN_HEADER
* [1] * [1]
* https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
*/ */
/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */ #define TT_CONFIG_OPTION_SUBPIXEL_HINTING
#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2
/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */
/************************************************************************** /**************************************************************************
@ -977,21 +951,14 @@ FT_BEGIN_HEADER
/* /*
* The next three macros are defined if native TrueType hinting is * The next two macros are defined if native TrueType hinting is
* requested by the definitions above. Don't change this. * requested by the definitions above. Don't change this.
*/ */
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
#define TT_USE_BYTECODE_INTERPRETER #define TT_USE_BYTECODE_INTERPRETER
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1
#define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
#endif
#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2
#define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL #define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
#endif #endif
#endif
#endif #endif

View File

@ -111,13 +111,13 @@
#include <stdio.h> #include <stdio.h>
#define FT_FILE FILE #define FT_FILE FILE
#define ft_fclose fclose #define ft_fclose fclose
#define ft_fopen fopen #define ft_fopen fopen
#define ft_fread fread #define ft_fread fread
#define ft_fseek fseek #define ft_fseek fseek
#define ft_ftell ftell #define ft_ftell ftell
#define ft_sprintf sprintf #define ft_snprintf snprintf
/************************************************************************** /**************************************************************************

View File

@ -102,61 +102,25 @@ FT_BEGIN_HEADER
*/ */
/*************************************************************************/
/*************************************************************************/
/* */
/* B A S I C T Y P E S */
/* */
/*************************************************************************/
/*************************************************************************/
/************************************************************************** /**************************************************************************
* *
* @section: * @section:
* base_interface * font_testing_macros
* *
* @title: * @title:
* Base Interface * Font Testing Macros
* *
* @abstract: * @abstract:
* The FreeType~2 base font interface. * Macros to test various properties of fonts.
* *
* @description: * @description:
* This section describes the most important public high-level API * Macros to test the most important font properties.
* functions of FreeType~2. *
* It is recommended to use these high-level macros instead of directly
* testing the corresponding flags, which are scattered over various
* structures.
* *
* @order: * @order:
* FT_Library
* FT_Face
* FT_Size
* FT_GlyphSlot
* FT_CharMap
* FT_Encoding
* FT_ENC_TAG
*
* FT_FaceRec
*
* FT_FACE_FLAG_SCALABLE
* FT_FACE_FLAG_FIXED_SIZES
* FT_FACE_FLAG_FIXED_WIDTH
* FT_FACE_FLAG_HORIZONTAL
* FT_FACE_FLAG_VERTICAL
* FT_FACE_FLAG_COLOR
* FT_FACE_FLAG_SFNT
* FT_FACE_FLAG_CID_KEYED
* FT_FACE_FLAG_TRICKY
* FT_FACE_FLAG_KERNING
* FT_FACE_FLAG_MULTIPLE_MASTERS
* FT_FACE_FLAG_VARIATION
* 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_HORIZONTAL
* FT_HAS_VERTICAL * FT_HAS_VERTICAL
* FT_HAS_KERNING * FT_HAS_KERNING
@ -176,21 +140,59 @@ FT_BEGIN_HEADER
* FT_IS_NAMED_INSTANCE * FT_IS_NAMED_INSTANCE
* FT_IS_VARIATION * FT_IS_VARIATION
* *
* FT_STYLE_FLAG_BOLD */
* FT_STYLE_FLAG_ITALIC
/**************************************************************************
* *
* FT_SizeRec * @section:
* FT_Size_Metrics * library_setup
* *
* FT_GlyphSlotRec * @title:
* FT_Glyph_Metrics * Library Setup
* FT_SubGlyph
* *
* FT_Bitmap_Size * @abstract:
* Functions to start and end the usage of the FreeType library.
* *
* @description:
* Functions to start and end the usage of the FreeType library.
*
* Note that @FT_Library_Version and @FREETYPE_XXX are of limited use
* because even a new release of FreeType with only documentation
* changes increases the version number.
*
* @order:
* FT_Library
* FT_Init_FreeType * FT_Init_FreeType
* FT_Done_FreeType * FT_Done_FreeType
* *
* FT_Library_Version
* FREETYPE_XXX
*
*/
/**************************************************************************
*
* @section:
* face_creation
*
* @title:
* Face Creation
*
* @abstract:
* Functions to manage fonts.
*
* @description:
* The functions and structures collected in this section operate on
* fonts globally.
*
* @order:
* FT_Face
* FT_FaceRec
* FT_FACE_FLAG_XXX
* FT_STYLE_FLAG_XXX
*
* FT_New_Face * FT_New_Face
* FT_Done_Face * FT_Done_Face
* FT_Reference_Face * FT_Reference_Face
@ -198,10 +200,36 @@ FT_BEGIN_HEADER
* FT_Face_Properties * FT_Face_Properties
* FT_Open_Face * FT_Open_Face
* FT_Open_Args * FT_Open_Args
* FT_OPEN_XXX
* FT_Parameter * FT_Parameter
* FT_Attach_File * FT_Attach_File
* FT_Attach_Stream * FT_Attach_Stream
* *
*/
/**************************************************************************
*
* @section:
* sizing_and_scaling
*
* @title:
* Sizing and Scaling
*
* @abstract:
* Functions to manage font sizes.
*
* @description:
* The functions and structures collected in this section are related to
* selecting and manipulating the size of a font globally.
*
* @order:
* FT_Size
* FT_SizeRec
* FT_Size_Metrics
*
* FT_Bitmap_Size
*
* FT_Set_Char_Size * FT_Set_Char_Size
* FT_Set_Pixel_Sizes * FT_Set_Pixel_Sizes
* FT_Request_Size * FT_Request_Size
@ -209,44 +237,37 @@ FT_BEGIN_HEADER
* FT_Size_Request_Type * FT_Size_Request_Type
* FT_Size_RequestRec * FT_Size_RequestRec
* FT_Size_Request * FT_Size_Request
*
* FT_Set_Transform * FT_Set_Transform
* FT_Get_Transform * FT_Get_Transform
*
*/
/**************************************************************************
*
* @section:
* glyph_retrieval
*
* @title:
* Glyph Retrieval
*
* @abstract:
* Functions to manage glyphs.
*
* @description:
* The functions and structures collected in this section operate on
* single glyphs, of which @FT_Load_Glyph is most important.
*
* @order:
* FT_GlyphSlot
* FT_GlyphSlotRec
* FT_Glyph_Metrics
*
* FT_Load_Glyph * FT_Load_Glyph
* FT_Get_Char_Index * FT_LOAD_XXX
* FT_Get_First_Char
* FT_Get_Next_Char
* FT_Load_Char
*
* FT_OPEN_MEMORY
* FT_OPEN_STREAM
* FT_OPEN_PATHNAME
* FT_OPEN_DRIVER
* FT_OPEN_PARAMS
*
* FT_LOAD_DEFAULT
* FT_LOAD_RENDER
* FT_LOAD_MONOCHROME
* FT_LOAD_LINEAR_DESIGN
* FT_LOAD_NO_SCALE
* FT_LOAD_NO_HINTING
* FT_LOAD_NO_BITMAP
* FT_LOAD_SBITS_ONLY
* FT_LOAD_NO_AUTOHINT
* FT_LOAD_COLOR
*
* FT_LOAD_VERTICAL_LAYOUT
* FT_LOAD_IGNORE_TRANSFORM
* FT_LOAD_FORCE_AUTOHINT
* FT_LOAD_NO_RECURSE
* FT_LOAD_PEDANTIC
*
* FT_LOAD_TARGET_NORMAL
* FT_LOAD_TARGET_LIGHT
* FT_LOAD_TARGET_MONO
* FT_LOAD_TARGET_LCD
* FT_LOAD_TARGET_LCD_V
*
* FT_LOAD_TARGET_MODE * FT_LOAD_TARGET_MODE
* FT_LOAD_TARGET_XXX
* *
* FT_Render_Glyph * FT_Render_Glyph
* FT_Render_Mode * FT_Render_Mode
@ -254,34 +275,121 @@ FT_BEGIN_HEADER
* FT_Kerning_Mode * FT_Kerning_Mode
* FT_Get_Track_Kerning * FT_Get_Track_Kerning
* *
*/
/**************************************************************************
*
* @section:
* character_mapping
*
* @title:
* Character Mapping
*
* @abstract:
* Functions to manage character-to-glyph maps.
*
* @description:
* This section holds functions and structures that are related to
* mapping character input codes to glyph indices.
*
* Note that for many scripts the simplistic approach used by FreeType
* of mapping a single character to a single glyph is not valid or
* possible! In general, a higher-level library like HarfBuzz or ICU
* should be used for handling text strings.
*
* @order:
* FT_CharMap
* FT_CharMapRec * FT_CharMapRec
* FT_Encoding
* FT_ENC_TAG
*
* FT_Select_Charmap * FT_Select_Charmap
* FT_Set_Charmap * FT_Set_Charmap
* FT_Get_Charmap_Index * FT_Get_Charmap_Index
* *
* FT_Get_Char_Index
* FT_Get_First_Char
* FT_Get_Next_Char
* FT_Load_Char
*
*/
/**************************************************************************
*
* @section:
* information_retrieval
*
* @title:
* Information Retrieval
*
* @abstract:
* Functions to retrieve font and glyph information.
*
* @description:
* Functions to retrieve font and glyph information. Only some very
* basic data is covered; see also the chapter on the format-specific
* API for more.
*
*
* @order:
* FT_Get_Name_Index * FT_Get_Name_Index
* FT_Get_Glyph_Name * FT_Get_Glyph_Name
* FT_Get_Postscript_Name * FT_Get_Postscript_Name
* FT_Get_FSType_Flags * FT_Get_FSType_Flags
* FT_FSTYPE_XXX
* FT_Get_SubGlyph_Info * FT_Get_SubGlyph_Info
* FT_SUBGLYPH_FLAG_XXX
* *
*/
/**************************************************************************
*
* @section:
* other_api_data
*
* @title:
* Other API Data
*
* @abstract:
* Other structures, enumerations, and macros.
*
* @description:
* Other structures, enumerations, and macros. Deprecated functions are
* also listed here.
*
* @order:
* FT_Face_Internal * FT_Face_Internal
* FT_Size_Internal * FT_Size_Internal
* FT_Slot_Internal * FT_Slot_Internal
* *
* FT_FACE_FLAG_XXX * FT_SubGlyph
* FT_STYLE_FLAG_XXX
* FT_OPEN_XXX
* FT_LOAD_XXX
* FT_LOAD_TARGET_XXX
* FT_SUBGLYPH_FLAG_XXX
* FT_FSTYPE_XXX
* *
* FT_HAS_FAST_GLYPHS * FT_HAS_FAST_GLYPHS
* FT_Face_CheckTrueTypePatents
* FT_Face_SetUnpatentedHinting
* *
*/ */
/*************************************************************************/
/*************************************************************************/
/* */
/* B A S I C T Y P E S */
/* */
/*************************************************************************/
/*************************************************************************/
/**************************************************************************
*
* @section:
* glyph_retrieval
*
*/
/************************************************************************** /**************************************************************************
* *
* @struct: * @struct:
@ -349,6 +457,13 @@ FT_BEGIN_HEADER
} FT_Glyph_Metrics; } FT_Glyph_Metrics;
/**************************************************************************
*
* @section:
* sizing_and_scaling
*
*/
/************************************************************************** /**************************************************************************
* *
* @struct: * @struct:
@ -409,6 +524,13 @@ FT_BEGIN_HEADER
/*************************************************************************/ /*************************************************************************/
/*************************************************************************/ /*************************************************************************/
/**************************************************************************
*
* @section:
* library_setup
*
*/
/************************************************************************** /**************************************************************************
* *
* @type: * @type:
@ -483,7 +605,7 @@ FT_BEGIN_HEADER
/************************************************************************** /**************************************************************************
* *
* @section: * @section:
* base_interface * face_creation
* *
*/ */
@ -519,6 +641,13 @@ FT_BEGIN_HEADER
typedef struct FT_FaceRec_* FT_Face; typedef struct FT_FaceRec_* FT_Face;
/**************************************************************************
*
* @section:
* sizing_and_scaling
*
*/
/************************************************************************** /**************************************************************************
* *
* @type: * @type:
@ -551,6 +680,13 @@ FT_BEGIN_HEADER
typedef struct FT_SizeRec_* FT_Size; typedef struct FT_SizeRec_* FT_Size;
/**************************************************************************
*
* @section:
* glyph_retrieval
*
*/
/************************************************************************** /**************************************************************************
* *
* @type: * @type:
@ -570,6 +706,13 @@ FT_BEGIN_HEADER
typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; typedef struct FT_GlyphSlotRec_* FT_GlyphSlot;
/**************************************************************************
*
* @section:
* character_mapping
*
*/
/************************************************************************** /**************************************************************************
* *
* @type: * @type:
@ -877,6 +1020,13 @@ FT_BEGIN_HEADER
/*************************************************************************/ /*************************************************************************/
/**************************************************************************
*
* @section:
* other_api_data
*
*/
/************************************************************************** /**************************************************************************
* *
* @type: * @type:
@ -892,6 +1042,13 @@ FT_BEGIN_HEADER
typedef struct FT_Face_InternalRec_* FT_Face_Internal; typedef struct FT_Face_InternalRec_* FT_Face_Internal;
/**************************************************************************
*
* @section:
* face_creation
*
*/
/************************************************************************** /**************************************************************************
* *
* @struct: * @struct:
@ -918,7 +1075,7 @@ FT_BEGIN_HEADER
* If we have the third named instance of face~4, say, `face_index` is * If we have the third named instance of face~4, say, `face_index` is
* set to 0x00030004. * set to 0x00030004.
* *
* Bit 31 is always zero (this is, `face_index` is always a positive * Bit 31 is always zero (that is, `face_index` is always a positive
* value). * value).
* *
* [Since 2.9] Changing the design coordinates with * [Since 2.9] Changing the design coordinates with
@ -936,7 +1093,7 @@ FT_BEGIN_HEADER
* *
* [Since 2.6.1] Bits 16-30 hold the number of named instances * [Since 2.6.1] Bits 16-30 hold the number of named instances
* available for the current face if we have a GX or OpenType variation * available for the current face if we have a GX or OpenType variation
* (sub)font. Bit 31 is always zero (this is, `style_flags` is always * (sub)font. Bit 31 is always zero (that is, `style_flags` is always
* a positive value). Note that a variation font has always at least * a positive value). Note that a variation font has always at least
* one named instance, namely the default instance. * one named instance, namely the default instance.
* *
@ -1002,7 +1159,7 @@ FT_BEGIN_HEADER
* Note that the bounding box might be off by (at least) one pixel for * Note that the bounding box might be off by (at least) one pixel for
* hinted fonts. See @FT_Size_Metrics for further discussion. * hinted fonts. See @FT_Size_Metrics for further discussion.
* *
* Note that the bounding box does not vary in OpenType variable fonts * Note that the bounding box does not vary in OpenType variation fonts
* and should only be used in relation to the default instance. * and should only be used in relation to the default instance.
* *
* units_per_EM :: * units_per_EM ::
@ -1090,9 +1247,9 @@ FT_BEGIN_HEADER
FT_Generic generic; FT_Generic generic;
/*# The following member variables (down to `underline_thickness`) */ /* The following member variables (down to `underline_thickness`) */
/*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ /* are only relevant to scalable outlines; cf. @FT_Bitmap_Size */
/*# for bitmap fonts. */ /* for bitmap fonts. */
FT_BBox bbox; FT_BBox bbox;
FT_UShort units_per_EM; FT_UShort units_per_EM;
@ -1110,7 +1267,7 @@ FT_BEGIN_HEADER
FT_Size size; FT_Size size;
FT_CharMap charmap; FT_CharMap charmap;
/*@private begin */ /* private fields, internal to FreeType */
FT_Driver driver; FT_Driver driver;
FT_Memory memory; FT_Memory memory;
@ -1123,8 +1280,6 @@ FT_BEGIN_HEADER
FT_Face_Internal internal; FT_Face_Internal internal;
/*@private end */
} FT_FaceRec; } FT_FaceRec;
@ -1207,13 +1362,13 @@ FT_BEGIN_HEADER
* successfully; in all other cases you get an * successfully; in all other cases you get an
* `FT_Err_Invalid_Argument` error. * `FT_Err_Invalid_Argument` error.
* *
* Note that CID-keyed fonts that are in an SFNT wrapper (this is, all * Note that CID-keyed fonts that are in an SFNT wrapper (that is, all
* OpenType/CFF fonts) don't have this flag set since the glyphs are * OpenType/CFF fonts) don't have this flag set since the glyphs are
* accessed in the normal way (using contiguous indices); the * accessed in the normal way (using contiguous indices); the
* 'CID-ness' isn't visible to the application. * 'CID-ness' isn't visible to the application.
* *
* FT_FACE_FLAG_TRICKY :: * FT_FACE_FLAG_TRICKY ::
* The face is 'tricky', this is, it always needs the font format's * The face is 'tricky', that is, it always needs the font format's
* native hinting engine to get a reasonable result. A typical example * native hinting engine to get a reasonable result. A typical example
* is the old Chinese font `mingli.ttf` (but not `mingliu.ttc`) that * is the old Chinese font `mingli.ttf` (but not `mingliu.ttc`) that
* uses TrueType bytecode instructions to move and scale all of its * uses TrueType bytecode instructions to move and scale all of its
@ -1235,8 +1390,8 @@ FT_BEGIN_HEADER
* FT_FACE_FLAG_VARIATION :: * FT_FACE_FLAG_VARIATION ::
* [Since 2.9] Set if the current face (or named instance) has been * [Since 2.9] Set if the current face (or named instance) has been
* altered with @FT_Set_MM_Design_Coordinates, * altered with @FT_Set_MM_Design_Coordinates,
* @FT_Set_Var_Design_Coordinates, or @FT_Set_Var_Blend_Coordinates. * @FT_Set_Var_Design_Coordinates, @FT_Set_Var_Blend_Coordinates, or
* This flag is unset by a call to @FT_Set_Named_Instance. * @FT_Set_MM_WeightVector to select a non-default instance.
* *
* FT_FACE_FLAG_SVG :: * FT_FACE_FLAG_SVG ::
* [Since 2.12] The face has an 'SVG~' OpenType table. * [Since 2.12] The face has an 'SVG~' OpenType table.
@ -1272,6 +1427,13 @@ FT_BEGIN_HEADER
#define FT_FACE_FLAG_SBIX_OVERLAY ( 1L << 18 ) #define FT_FACE_FLAG_SBIX_OVERLAY ( 1L << 18 )
/**************************************************************************
*
* @section:
* font_testing_macros
*
*/
/************************************************************************** /**************************************************************************
* *
* @macro: * @macro:
@ -1381,6 +1543,13 @@ FT_BEGIN_HEADER
( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES ) ) ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES ) )
/**************************************************************************
*
* @section:
* other_api_data
*
*/
/************************************************************************** /**************************************************************************
* *
* @macro: * @macro:
@ -1393,6 +1562,13 @@ FT_BEGIN_HEADER
#define FT_HAS_FAST_GLYPHS( face ) 0 #define FT_HAS_FAST_GLYPHS( face ) 0
/**************************************************************************
*
* @section:
* font_testing_macros
*
*/
/************************************************************************** /**************************************************************************
* *
* @macro: * @macro:
@ -1451,8 +1627,8 @@ FT_BEGIN_HEADER
* *
* @description: * @description:
* A macro that returns true whenever a face object has been altered by * A macro that returns true whenever a face object has been altered by
* @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, or * @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates,
* @FT_Set_Var_Blend_Coordinates. * @FT_Set_Var_Blend_Coordinates, or @FT_Set_MM_WeightVector.
* *
* @since: * @since:
* 2.9 * 2.9
@ -1628,6 +1804,13 @@ FT_BEGIN_HEADER
( !!( (face)->face_flags & FT_FACE_FLAG_SBIX_OVERLAY ) ) ( !!( (face)->face_flags & FT_FACE_FLAG_SBIX_OVERLAY ) )
/**************************************************************************
*
* @section:
* face_creation
*
*/
/************************************************************************** /**************************************************************************
* *
* @enum: * @enum:
@ -1654,6 +1837,13 @@ FT_BEGIN_HEADER
#define FT_STYLE_FLAG_BOLD ( 1 << 1 ) #define FT_STYLE_FLAG_BOLD ( 1 << 1 )
/**************************************************************************
*
* @section:
* other_api_data
*
*/
/************************************************************************** /**************************************************************************
* *
* @type: * @type:
@ -1666,6 +1856,13 @@ FT_BEGIN_HEADER
typedef struct FT_Size_InternalRec_* FT_Size_Internal; typedef struct FT_Size_InternalRec_* FT_Size_Internal;
/**************************************************************************
*
* @section:
* sizing_and_scaling
*
*/
/************************************************************************** /**************************************************************************
* *
* @struct: * @struct:
@ -1817,6 +2014,13 @@ FT_BEGIN_HEADER
} FT_SizeRec; } FT_SizeRec;
/**************************************************************************
*
* @section:
* other_api_data
*
*/
/************************************************************************** /**************************************************************************
* *
* @struct: * @struct:
@ -1848,6 +2052,13 @@ FT_BEGIN_HEADER
typedef struct FT_Slot_InternalRec_* FT_Slot_Internal; typedef struct FT_Slot_InternalRec_* FT_Slot_Internal;
/**************************************************************************
*
* @section:
* glyph_retrieval
*
*/
/************************************************************************** /**************************************************************************
* *
* @struct: * @struct:
@ -2092,6 +2303,13 @@ FT_BEGIN_HEADER
/*************************************************************************/ /*************************************************************************/
/**************************************************************************
*
* @section:
* library_setup
*
*/
/************************************************************************** /**************************************************************************
* *
* @function: * @function:
@ -2149,6 +2367,13 @@ FT_BEGIN_HEADER
FT_Done_FreeType( FT_Library library ); FT_Done_FreeType( FT_Library library );
/**************************************************************************
*
* @section:
* face_creation
*
*/
/************************************************************************** /**************************************************************************
* *
* @enum: * @enum:
@ -2451,7 +2676,7 @@ FT_BEGIN_HEADER
* Each new face object created with this function also owns a default * Each new face object created with this function also owns a default
* @FT_Size object, accessible as `face->size`. * @FT_Size object, accessible as `face->size`.
* *
* One @FT_Library instance can have multiple face objects, this is, * One @FT_Library instance can have multiple face objects, that is,
* @FT_Open_Face and its siblings can be called multiple times using the * @FT_Open_Face and its siblings can be called multiple times using the
* same `library` argument. * same `library` argument.
* *
@ -2650,6 +2875,13 @@ FT_BEGIN_HEADER
FT_Done_Face( FT_Face face ); FT_Done_Face( FT_Face face );
/**************************************************************************
*
* @section:
* sizing_and_scaling
*
*/
/************************************************************************** /**************************************************************************
* *
* @function: * @function:
@ -2679,7 +2911,7 @@ FT_BEGIN_HEADER
* silently uses outlines if there is no bitmap for a given glyph index. * silently uses outlines if there is no bitmap for a given glyph index.
* *
* For GX and OpenType variation fonts, a bitmap strike makes sense only * For GX and OpenType variation fonts, a bitmap strike makes sense only
* if the default instance is active (this is, no glyph variation takes * if the default instance is active (that is, no glyph variation takes
* place); otherwise, FreeType simply ignores bitmap strikes. The same * place); otherwise, FreeType simply ignores bitmap strikes. The same
* is true for all named instances that are different from the default * is true for all named instances that are different from the default
* instance. * instance.
@ -2942,6 +3174,13 @@ FT_BEGIN_HEADER
FT_UInt pixel_height ); FT_UInt pixel_height );
/**************************************************************************
*
* @section:
* glyph_retrieval
*
*/
/************************************************************************** /**************************************************************************
* *
* @function: * @function:
@ -2976,7 +3215,7 @@ FT_BEGIN_HEADER
* glyph may be transformed. See @FT_Set_Transform for the details. * glyph may be transformed. See @FT_Set_Transform for the details.
* *
* For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument` is returned * 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 * for invalid CID values (that is, for CID values that don't have a
* corresponding glyph in the font). See the discussion of the * corresponding glyph in the font). See the discussion of the
* @FT_FACE_FLAG_CID_KEYED flag for more details. * @FT_FACE_FLAG_CID_KEYED flag for more details.
* *
@ -2990,6 +3229,13 @@ FT_BEGIN_HEADER
FT_Int32 load_flags ); FT_Int32 load_flags );
/**************************************************************************
*
* @section:
* character_mapping
*
*/
/************************************************************************** /**************************************************************************
* *
* @function: * @function:
@ -3033,6 +3279,13 @@ FT_BEGIN_HEADER
FT_Int32 load_flags ); FT_Int32 load_flags );
/**************************************************************************
*
* @section:
* glyph_retrieval
*
*/
/************************************************************************** /**************************************************************************
* *
* @enum: * @enum:
@ -3172,10 +3425,11 @@ FT_BEGIN_HEADER
* *
* [Since 2.12] If the glyph index maps to an entry in the face's * [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 * 'SVG~' table, load the associated SVG document from this table and
* set the `format` field of @FT_GlyphSlotRec to @FT_GLYPH_FORMAT_SVG. * set the `format` field of @FT_GlyphSlotRec to @FT_GLYPH_FORMAT_SVG
* Note that FreeType itself can't render SVG documents; however, the * ([since 2.13.1] provided @FT_LOAD_NO_SVG is not set). Note that
* library provides hooks to seamlessly integrate an external renderer. * FreeType itself can't render SVG documents; however, the library
* See sections @ot_svg_driver and @svg_fonts for more. * 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 * [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 face's 'COLR' table with a 'CPAL' palette table (as defined in
@ -3189,6 +3443,9 @@ FT_BEGIN_HEADER
* @FT_Palette_Select instead of setting @FT_LOAD_COLOR for rendering * @FT_Palette_Select instead of setting @FT_LOAD_COLOR for rendering
* so that the client application can handle blending by itself. * so that the client application can handle blending by itself.
* *
* FT_LOAD_NO_SVG ::
* [Since 2.13.1] Ignore SVG glyph data when loading.
*
* FT_LOAD_COMPUTE_METRICS :: * FT_LOAD_COMPUTE_METRICS ::
* [Since 2.6.1] Compute glyph metrics from the glyph data, without the * [Since 2.6.1] Compute glyph metrics from the glyph data, without the
* use of bundled metrics tables (for example, the 'hdmx' table in * use of bundled metrics tables (for example, the 'hdmx' table in
@ -3254,6 +3511,7 @@ FT_BEGIN_HEADER
#define FT_LOAD_COLOR ( 1L << 20 ) #define FT_LOAD_COLOR ( 1L << 20 )
#define FT_LOAD_COMPUTE_METRICS ( 1L << 21 ) #define FT_LOAD_COMPUTE_METRICS ( 1L << 21 )
#define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 ) #define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 )
#define FT_LOAD_NO_SVG ( 1L << 24 )
/* */ /* */
@ -3372,6 +3630,13 @@ FT_BEGIN_HEADER
FT_STATIC_CAST( FT_Render_Mode, ( (x) >> 16 ) & 15 ) FT_STATIC_CAST( FT_Render_Mode, ( (x) >> 16 ) & 15 )
/**************************************************************************
*
* @section:
* sizing_and_scaling
*
*/
/************************************************************************** /**************************************************************************
* *
* @function: * @function:
@ -3447,6 +3712,13 @@ FT_BEGIN_HEADER
FT_Vector* delta ); FT_Vector* delta );
/**************************************************************************
*
* @section:
* glyph_retrieval
*
*/
/************************************************************************** /**************************************************************************
* *
* @enum: * @enum:
@ -3841,6 +4113,13 @@ FT_BEGIN_HEADER
FT_Fixed* akerning ); FT_Fixed* akerning );
/**************************************************************************
*
* @section:
* character_mapping
*
*/
/************************************************************************** /**************************************************************************
* *
* @function: * @function:
@ -4057,6 +4336,13 @@ FT_BEGIN_HEADER
FT_UInt *agindex ); FT_UInt *agindex );
/**************************************************************************
*
* @section:
* face_creation
*
*/
/************************************************************************** /**************************************************************************
* *
* @function: * @function:
@ -4155,6 +4441,13 @@ FT_BEGIN_HEADER
FT_Parameter* properties ); FT_Parameter* properties );
/**************************************************************************
*
* @section:
* information_retrieval
*
*/
/************************************************************************** /**************************************************************************
* *
* @function: * @function:
@ -4266,9 +4559,10 @@ FT_BEGIN_HEADER
* *
* [Since 2.9] Special PostScript names for named instances are only * [Since 2.9] Special PostScript names for named instances are only
* returned if the named instance is set with @FT_Set_Named_Instance (and * returned if the named instance is set with @FT_Set_Named_Instance (and
* the font has corresponding entries in its 'fvar' table). If * the font has corresponding entries in its 'fvar' table or is the
* @FT_IS_VARIATION returns true, the algorithmically derived PostScript * default named instance). If @FT_IS_VARIATION returns true, the
* name is provided, not looking up special entries for named instances. * algorithmically derived PostScript name is provided, not looking up
* special entries for named instances.
*/ */
FT_EXPORT( const char* ) FT_EXPORT( const char* )
FT_Get_Postscript_Name( FT_Face face ); FT_Get_Postscript_Name( FT_Face face );
@ -4900,32 +5194,10 @@ FT_BEGIN_HEADER
/************************************************************************** /**************************************************************************
* *
* @section: * @section:
* version * library_setup
*
* @title:
* FreeType Version
*
* @abstract:
* Functions and macros related to FreeType versions.
*
* @description:
* Note that those functions and macros are of limited use because even a
* new release of FreeType with only documentation changes increases the
* version number.
*
* @order:
* FT_Library_Version
*
* FREETYPE_MAJOR
* FREETYPE_MINOR
* FREETYPE_PATCH
*
* FT_Face_CheckTrueTypePatents
* FT_Face_SetUnpatentedHinting
* *
*/ */
/************************************************************************** /**************************************************************************
* *
* @enum: * @enum:
@ -4950,7 +5222,7 @@ FT_BEGIN_HEADER
*/ */
#define FREETYPE_MAJOR 2 #define FREETYPE_MAJOR 2
#define FREETYPE_MINOR 13 #define FREETYPE_MINOR 13
#define FREETYPE_PATCH 0 #define FREETYPE_PATCH 2
/************************************************************************** /**************************************************************************
@ -4992,6 +5264,13 @@ FT_BEGIN_HEADER
FT_Int *apatch ); FT_Int *apatch );
/**************************************************************************
*
* @section:
* other_api_data
*
*/
/************************************************************************** /**************************************************************************
* *
* @function: * @function:

View File

@ -43,61 +43,61 @@ FT_BEGIN_HEADER
* objects, as well as caching information like character maps and glyph * objects, as well as caching information like character maps and glyph
* images while limiting their maximum memory usage. * images while limiting their maximum memory usage.
* *
* Note that all types and functions begin with the `FTC_` prefix. * Note that all types and functions begin with the `FTC_` prefix rather
* than the usual `FT_` prefix in the rest of FreeType.
* *
* The cache is highly portable and thus doesn't know anything about the * The cache is highly portable and, thus, doesn't know anything about
* fonts installed on your system, or how to access them. This implies * the fonts installed on your system, or how to access them. Therefore,
* the following scheme: * it requires the following.
* *
* First, available or installed font faces are uniquely identified by * * @FTC_FaceID, an arbitrary non-zero value that uniquely identifies
* @FTC_FaceID values, provided to the cache by the client. Note that * available or installed font faces, has to be provided to the
* the cache only stores and compares these values, and doesn't try to * cache by the client. Note that the cache only stores and compares
* interpret them in any way. * these values and doesn't try to interpret them in any way, but they
* have to be persistent on the client side.
* *
* Second, the cache calls, only when needed, a client-provided function * * @FTC_Face_Requester, a method to convert an @FTC_FaceID into a new
* to convert an @FTC_FaceID into a new @FT_Face object. The latter is * @FT_Face object when necessary, has to be provided to the cache by
* then completely managed by the cache, including its termination * the client. The @FT_Face object is completely managed by the cache,
* through @FT_Done_Face. To monitor termination of face objects, the * including its termination through @FT_Done_Face. To monitor
* finalizer callback in the `generic` field of the @FT_Face object can * termination of face objects, the finalizer callback in the `generic`
* be used, which might also be used to store the @FTC_FaceID of the * field of the @FT_Face object can be used, which might also be used
* face. * to store the @FTC_FaceID of the face.
* *
* Clients are free to map face IDs to anything else. The most simple * Clients are free to map face IDs to anything useful. The most simple
* usage is to associate them to a (pathname,face_index) pair that is * usage is, for example, to associate them to a `{pathname,face_index}`
* used to call @FT_New_Face. However, more complex schemes are also * pair that is then used by @FTC_Face_Requester to call @FT_New_Face.
* possible. * However, more complex schemes are also possible.
* *
* Note that for the cache to work correctly, the face ID values must be * Note that for the cache to work correctly, the face ID values must be
* **persistent**, which means that the contents they point to should not * **persistent**, which means that the contents they point to should not
* change at runtime, or that their value should not become invalid. * change at runtime, or that their value should not become invalid.
*
* If this is unavoidable (e.g., when a font is uninstalled at runtime), * If this is unavoidable (e.g., when a font is uninstalled at runtime),
* you should call @FTC_Manager_RemoveFaceID as soon as possible, to let * you should call @FTC_Manager_RemoveFaceID as soon as possible to let
* the cache get rid of any references to the old @FTC_FaceID it may keep * the cache get rid of any references to the old @FTC_FaceID it may keep
* internally. Failure to do so will lead to incorrect behaviour or even * internally. Failure to do so will lead to incorrect behaviour or even
* crashes. * crashes in @FTC_Face_Requester.
* *
* To use the cache, start with calling @FTC_Manager_New to create a new * To use the cache, start with calling @FTC_Manager_New to create a new
* @FTC_Manager object, which models a single cache instance. You can * @FTC_Manager object, which models a single cache instance. You can
* then look up @FT_Face and @FT_Size objects with * then look up @FT_Face and @FT_Size objects with
* @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively. * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively, and
* use them in any FreeType work stream. You can also cache other
* FreeType objects as follows.
* *
* If you want to use the charmap caching, call @FTC_CMapCache_New, then * * If you want to use the charmap caching, call @FTC_CMapCache_New,
* later use @FTC_CMapCache_Lookup to perform the equivalent of * then later use @FTC_CMapCache_Lookup to perform the equivalent of
* @FT_Get_Char_Index, only much faster. * @FT_Get_Char_Index, only much faster.
* *
* If you want to use the @FT_Glyph caching, call @FTC_ImageCache_New, * * If you want to use the @FT_Glyph caching, call @FTC_ImageCache_New,
* then later use @FTC_ImageCache_Lookup to retrieve the corresponding * then later use @FTC_ImageCache_Lookup to retrieve the corresponding
* @FT_Glyph objects from the cache. * @FT_Glyph objects from the cache.
*
* If you need lots of small bitmaps, it is much more memory efficient to
* call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This
* returns @FTC_SBitRec structures, which are used to store small bitmaps
* directly. (A small bitmap is one whose metrics and dimensions all fit
* into 8-bit integers).
*
* We hope to also provide a kerning cache in the near future.
* *
* * If you need lots of small bitmaps, it is much more memory-efficient
* to call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This
* returns @FTC_SBitRec structures, which are used to store small
* bitmaps directly. (A small bitmap is one whose metrics and
* dimensions all fit into 8-bit integers).
* *
* @order: * @order:
* FTC_Manager * FTC_Manager

View File

@ -31,9 +31,28 @@
* Core API * Core API
* *
* @sections: * @sections:
* version
* basic_types * basic_types
* base_interface * library_setup
* face_creation
* font_testing_macros
* sizing_and_scaling
* glyph_retrieval
* character_mapping
* information_retrieval
* other_api_data
*
*/
/**************************************************************************
*
* @chapter:
* extended_api
*
* @title:
* Extended API
*
* @sections:
* glyph_variants * glyph_variants
* color_management * color_management
* layer_management * layer_management

View File

@ -134,7 +134,7 @@ FT_BEGIN_HEADER
* each being rounded to the nearest pixel edge, taking care of overshoot * each being rounded to the nearest pixel edge, taking care of overshoot
* suppression at small sizes, stem darkening, and scaling. * suppression at small sizes, stem darkening, and scaling.
* *
* Hstems (this is, hint values defined in the font to help align * Hstems (that is, hint values defined in the font to help align
* horizontal features) that fall within a blue zone are said to be * horizontal features) that fall within a blue zone are said to be
* 'captured' and are aligned to that zone. Uncaptured stems are moved * 'captured' and are aligned to that zone. Uncaptured stems are moved
* in one of four ways, top edge up or down, bottom edge up or down. * in one of four ways, top edge up or down, bottom edge up or down.
@ -446,7 +446,7 @@ FT_BEGIN_HEADER
* at smaller sizes. * at smaller sizes.
* *
* For the auto-hinter, stem-darkening is experimental currently and thus * For the auto-hinter, stem-darkening is experimental currently and thus
* switched off by default (this is, `no-stem-darkening` is set to TRUE * switched off by default (that is, `no-stem-darkening` is set to TRUE
* by default). Total consistency with the CFF driver is not achieved * by default). Total consistency with the CFF driver is not achieved
* right now because the emboldening method differs and glyphs must be * right now because the emboldening method differs and glyphs must be
* scaled down on the Y-axis to keep outline points inside their * scaled down on the Y-axis to keep outline points inside their
@ -651,11 +651,8 @@ FT_BEGIN_HEADER
* Windows~98; only grayscale and B/W rasterizing is supported. * Windows~98; only grayscale and B/W rasterizing is supported.
* *
* TT_INTERPRETER_VERSION_38 :: * TT_INTERPRETER_VERSION_38 ::
* Version~38 corresponds to MS rasterizer v.1.9; it is roughly * Version~38 is the same Version~40. The original 'Infinality' code is
* equivalent to the hinting provided by DirectWrite ClearType (as can * no longer available.
* be found, for example, in the Internet Explorer~9 running on
* Windows~7). It is used in FreeType to select the 'Infinality'
* subpixel hinting code. The code may be removed in a future version.
* *
* TT_INTERPRETER_VERSION_40 :: * TT_INTERPRETER_VERSION_40 ::
* Version~40 corresponds to MS rasterizer v.2.1; it is roughly * Version~40 corresponds to MS rasterizer v.2.1; it is roughly

View File

@ -19,7 +19,7 @@
/************************************************************************** /**************************************************************************
* *
* Note: A 'raster' is simply a scan-line converter, used to render * Note: A 'raster' is simply a scan-line converter, used to render
* FT_Outlines into FT_Bitmaps. * `FT_Outline`s into `FT_Bitmap`s.
* *
*/ */
@ -256,6 +256,12 @@ FT_BEGIN_HEADER
* palette :: * palette ::
* A typeless pointer to the bitmap palette; this field is intended for * A typeless pointer to the bitmap palette; this field is intended for
* paletted pixel modes. Not used currently. * paletted pixel modes. Not used currently.
*
* @note:
* `width` and `rows` refer to the *physical* size of the bitmap, not the
* *logical* one. For example, if @FT_Pixel_Mode is set to
* `FT_PIXEL_MODE_LCD`, the logical width is a just a third of the
* physical one.
*/ */
typedef struct FT_Bitmap_ typedef struct FT_Bitmap_
{ {
@ -856,7 +862,7 @@ FT_BEGIN_HEADER
* @FT_SpanFunc that takes the y~coordinate of the span as a parameter. * @FT_SpanFunc that takes the y~coordinate of the span as a parameter.
* *
* The anti-aliased rasterizer produces coverage values from 0 to 255, * The anti-aliased rasterizer produces coverage values from 0 to 255,
* this is, from completely transparent to completely opaque. * that is, from completely transparent to completely opaque.
*/ */
typedef struct FT_Span_ typedef struct FT_Span_
{ {

View File

@ -62,7 +62,7 @@ FT_BEGIN_HEADER
* component. * component.
* *
* ``` * ```
* FT_Trace_Set_Level( "any:7 memory:0 ); * FT_Trace_Set_Level( "any:7 memory:0" );
* ``` * ```
* *
* @note: * @note:

View File

@ -153,7 +153,7 @@ FT_BEGIN_HEADER
* @note: * @note:
* The fields `minimum`, `def`, and `maximum` are 16.16 fractional values * The fields `minimum`, `def`, and `maximum` are 16.16 fractional values
* for TrueType GX and OpenType variation fonts. For Adobe MM fonts, the * for TrueType GX and OpenType variation fonts. For Adobe MM fonts, the
* values are integers. * values are whole numbers (i.e., the fractional part is zero).
*/ */
typedef struct FT_Var_Axis_ typedef struct FT_Var_Axis_
{ {
@ -399,8 +399,8 @@ FT_BEGIN_HEADER
* *
* @note: * @note:
* The design coordinates are 16.16 fractional values for TrueType GX and * The design coordinates are 16.16 fractional values for TrueType GX and
* OpenType variation fonts. For Adobe MM fonts, the values are * OpenType variation fonts. For Adobe MM fonts, the values are supposed
* integers. * to be whole numbers (i.e., the fractional part is zero).
* *
* [Since 2.8.1] To reset all axes to the default values, call the * [Since 2.8.1] To reset all axes to the default values, call the
* function with `num_coords` set to zero and `coords` set to `NULL`. * function with `num_coords` set to zero and `coords` set to `NULL`.
@ -446,8 +446,8 @@ FT_BEGIN_HEADER
* *
* @note: * @note:
* The design coordinates are 16.16 fractional values for TrueType GX and * The design coordinates are 16.16 fractional values for TrueType GX and
* OpenType variation fonts. For Adobe MM fonts, the values are * OpenType variation fonts. For Adobe MM fonts, the values are whole
* integers. * numbers (i.e., the fractional part is zero).
* *
* @since: * @since:
* 2.7.1 * 2.7.1
@ -602,10 +602,12 @@ FT_BEGIN_HEADER
* *
* @note: * @note:
* Adobe Multiple Master fonts limit the number of designs, and thus the * Adobe Multiple Master fonts limit the number of designs, and thus the
* length of the weight vector to~16. * length of the weight vector to 16~elements.
* *
* If `len` is zero and `weightvector` is `NULL`, the weight vector array * If `len` is larger than zero, this function sets the
* is reset to the default values. * @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field (i.e.,
* @FT_IS_VARIATION will return true). If `len` is zero, this bit flag
* is unset and the weight vector array is reset to the default values.
* *
* The Adobe documentation also states that the values in the * The Adobe documentation also states that the values in the
* WeightVector array must total 1.0 +/-~0.001. In practice this does * WeightVector array must total 1.0 +/-~0.001. In practice this does
@ -753,6 +755,45 @@ FT_BEGIN_HEADER
FT_Set_Named_Instance( FT_Face face, FT_Set_Named_Instance( FT_Face face,
FT_UInt instance_index ); FT_UInt instance_index );
/**************************************************************************
*
* @function:
* FT_Get_Default_Named_Instance
*
* @description:
* Retrieve the index of the default named instance, to be used with
* @FT_Set_Named_Instance.
*
* The default instance of a variation font is that instance for which
* the nth axis coordinate is equal to `axis[n].def` (as specified in the
* @FT_MM_Var structure), with~n covering all axes.
*
* FreeType synthesizes a named instance for the default instance if the
* font does not contain such an entry.
*
* @input:
* face ::
* A handle to the source face.
*
* @output:
* instance_index ::
* The index of the default named instance.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
* For Adobe MM fonts (which don't have named instances) this function
* always returns zero for `instance_index`.
*
* @since:
* 2.13.1
*/
FT_EXPORT( FT_Error )
FT_Get_Default_Named_Instance( FT_Face face,
FT_UInt *instance_index );
/* */ /* */

View File

@ -118,7 +118,7 @@ FT_BEGIN_HEADER
* attachement. * attachement.
* *
* Similarly, the function returns success for an empty outline also * Similarly, the function returns success for an empty outline also
* (doing nothing, this is, not calling any emitter); if necessary, you * (doing nothing, that is, not calling any emitter); if necessary, you
* should filter this out, too. * should filter this out, too.
*/ */
FT_EXPORT( FT_Error ) FT_EXPORT( FT_Error )

View File

@ -158,7 +158,7 @@ FT_BEGIN_HEADER
FT_Renderer_GetCBoxFunc get_glyph_cbox; FT_Renderer_GetCBoxFunc get_glyph_cbox;
FT_Renderer_SetModeFunc set_mode; FT_Renderer_SetModeFunc set_mode;
FT_Raster_Funcs* raster_class; const FT_Raster_Funcs* raster_class;
} FT_Renderer_Class; } FT_Renderer_Class;

View File

@ -68,6 +68,18 @@ FT_BEGIN_HEADER
FT_EXPORT( void ) FT_EXPORT( void )
FT_GlyphSlot_Embolden( FT_GlyphSlot slot ); FT_GlyphSlot_Embolden( FT_GlyphSlot slot );
/* Precisely adjust the glyph weight either horizontally or vertically. */
/* The `xdelta` and `ydelta` values are fractions of the face Em size */
/* (in fixed-point format). Considering that a regular face would have */
/* stem widths on the order of 0.1 Em, a delta of 0.05 (0x0CCC) should */
/* be very noticeable. To increase or decrease the weight, use positive */
/* or negative values, respectively. */
FT_EXPORT( void )
FT_GlyphSlot_AdjustWeight( FT_GlyphSlot slot,
FT_Fixed xdelta,
FT_Fixed ydelta );
/* Slant an outline glyph to the right by about 12 degrees. */ /* Slant an outline glyph to the right by about 12 degrees. */
FT_EXPORT( void ) FT_EXPORT( void )
FT_GlyphSlot_Oblique( FT_GlyphSlot slot ); FT_GlyphSlot_Oblique( FT_GlyphSlot slot );

View File

@ -229,8 +229,7 @@ FT_BEGIN_HEADER
* A handle to the source stream. * A handle to the source stream.
* *
* offset :: * offset ::
* The offset from the start of the stream to seek to if this is a seek * The offset from the start of the stream to seek to.
* operation (see note).
* *
* buffer :: * buffer ::
* The address of the read buffer. * The address of the read buffer.
@ -239,16 +238,9 @@ FT_BEGIN_HEADER
* The number of bytes to read from the stream. * The number of bytes to read from the stream.
* *
* @return: * @return:
* The number of bytes effectively read by the stream. * If count >~0, return the number of bytes effectively read by the
* * stream (after seeking to `offset`). If count ==~0, return the status
* @note: * of the seek operation (non-zero indicates an error).
* This function performs a seek *or* a read operation depending on the
* argument values. If `count` is zero, the operation is a seek to
* `offset` bytes. If `count` is >~0, the operation is a read of `count`
* bytes from the current position in the stream, and the `offset` value
* should be ignored.
*
* For seek operations, a non-zero return value indicates an error.
* *
*/ */
typedef unsigned long typedef unsigned long

View File

@ -41,8 +41,11 @@ FT_BEGIN_HEADER
# if ( defined( __STDC_VERSION__ ) && __STDC_VERSION__ > 201710L ) || \ # if ( defined( __STDC_VERSION__ ) && __STDC_VERSION__ > 201710L ) || \
( defined( __cplusplus ) && __cplusplus > 201402L ) ( defined( __cplusplus ) && __cplusplus > 201402L )
# define FALL_THROUGH [[__fallthrough__]] # define FALL_THROUGH [[__fallthrough__]]
# elif ( defined( __GNUC__ ) && __GNUC__ >= 7 ) || \ # elif ( defined( __GNUC__ ) && __GNUC__ >= 7 ) || \
( defined( __clang__ ) && __clang_major__ >= 10 ) ( defined( __clang__ ) && \
( defined( __apple_build_version__ ) \
? __apple_build_version__ >= 12000000 \
: __clang_major__ >= 10 ) )
# define FALL_THROUGH __attribute__(( __fallthrough__ )) # define FALL_THROUGH __attribute__(( __fallthrough__ ))
# else # else
# define FALL_THROUGH ( (void)0 ) # define FALL_THROUGH ( (void)0 )

View File

@ -332,9 +332,9 @@ FT_BEGIN_HEADER
* Based on geometric considerations we use the following inequality to * Based on geometric considerations we use the following inequality to
* identify a degenerate matrix. * identify a degenerate matrix.
* *
* 50 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2 * 32 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2
* *
* Value 50 is heuristic. * Value 32 is heuristic.
*/ */
FT_BASE( FT_Bool ) FT_BASE( FT_Bool )
FT_Matrix_Check( const FT_Matrix* matrix ); FT_Matrix_Check( const FT_Matrix* matrix );

View File

@ -157,6 +157,7 @@ FT_BEGIN_HEADER
* A handle to a function used to select a new fixed size. It is used * A handle to a function used to select a new fixed size. It is used
* only if @FT_FACE_FLAG_FIXED_SIZES is set. Can be set to 0 if the * only if @FT_FACE_FLAG_FIXED_SIZES is set. Can be set to 0 if the
* scaling done in the base layer suffices. * scaling done in the base layer suffices.
*
* @note: * @note:
* Most function pointers, with the exception of `load_glyph`, can be set * Most function pointers, with the exception of `load_glyph`, can be set
* to 0 to indicate a default behaviour. * to 0 to indicate a default behaviour.

View File

@ -28,13 +28,19 @@ FT_BEGIN_HEADER
typedef struct GX_ItemVarDataRec_ typedef struct GX_ItemVarDataRec_
{ {
FT_UInt itemCount; /* number of delta sets per item */ FT_UInt itemCount; /* Number of delta sets per item. */
FT_UInt regionIdxCount; /* number of region indices */ FT_UInt regionIdxCount; /* Number of region indices. */
FT_UInt* regionIndices; /* array of `regionCount' indices; */ FT_UInt* regionIndices; /* Array of `regionCount` indices; */
/* these index `varRegionList' */ /* these index `varRegionList`. */
FT_ItemVarDelta* deltaSet; /* array of `itemCount' deltas */ FT_Byte* deltaSet; /* Array of `itemCount` deltas; */
/* use `innerIndex' for this array */ /* use `innerIndex` for this array. */
FT_UShort wordDeltaCount; /* Number of the first 32-bit ints */
/* or 16-bit ints of `deltaSet` */
/* depending on `longWords`. */
FT_Bool longWords; /* If true, `deltaSet` is a 32-bit */
/* array followed by a 16-bit */
/* array, otherwise a 16-bit array */
/* followed by an 8-bit array. */
} GX_ItemVarDataRec, *GX_ItemVarData; } GX_ItemVarDataRec, *GX_ItemVarData;

View File

@ -77,6 +77,9 @@ FT_BEGIN_HEADER
typedef void typedef void
(*FT_Metrics_Adjust_Func)( FT_Face face ); (*FT_Metrics_Adjust_Func)( FT_Face face );
typedef FT_Error
(*FT_Size_Reset_Func)( FT_Size size );
FT_DEFINE_SERVICE( MetricsVariations ) FT_DEFINE_SERVICE( MetricsVariations )
{ {
@ -90,6 +93,7 @@ FT_BEGIN_HEADER
FT_VOrg_Adjust_Func vorg_adjust; FT_VOrg_Adjust_Func vorg_adjust;
FT_Metrics_Adjust_Func metrics_adjust; FT_Metrics_Adjust_Func metrics_adjust;
FT_Size_Reset_Func size_reset;
}; };
@ -101,7 +105,8 @@ FT_BEGIN_HEADER
tsb_adjust_, \ tsb_adjust_, \
bsb_adjust_, \ bsb_adjust_, \
vorg_adjust_, \ vorg_adjust_, \
metrics_adjust_ ) \ metrics_adjust_, \
size_reset_ ) \
static const FT_Service_MetricsVariationsRec class_ = \ static const FT_Service_MetricsVariationsRec class_ = \
{ \ { \
hadvance_adjust_, \ hadvance_adjust_, \
@ -111,7 +116,8 @@ FT_BEGIN_HEADER
tsb_adjust_, \ tsb_adjust_, \
bsb_adjust_, \ bsb_adjust_, \
vorg_adjust_, \ vorg_adjust_, \
metrics_adjust_ \ metrics_adjust_, \
size_reset_ \
}; };
/* */ /* */

View File

@ -60,9 +60,9 @@ FT_BEGIN_HEADER
/* use return value -1 to indicate that the new coordinates */ /* use return value -1 to indicate that the new coordinates */
/* are equal to the current ones; no changes are thus needed */ /* are equal to the current ones; no changes are thus needed */
typedef FT_Error typedef FT_Error
(*FT_Set_MM_Blend_Func)( FT_Face face, (*FT_Set_MM_Blend_Func)( FT_Face face,
FT_UInt num_coords, FT_UInt num_coords,
FT_Long* coords ); FT_Fixed* coords );
typedef FT_Error typedef FT_Error
(*FT_Get_Var_Design_Func)( FT_Face face, (*FT_Get_Var_Design_Func)( FT_Face face,
@ -70,13 +70,17 @@ FT_BEGIN_HEADER
FT_Fixed* coords ); FT_Fixed* coords );
typedef FT_Error typedef FT_Error
(*FT_Set_Instance_Func)( FT_Face face, (*FT_Set_Named_Instance_Func)( FT_Face face,
FT_UInt instance_index ); FT_UInt instance_index );
typedef FT_Error typedef FT_Error
(*FT_Get_MM_Blend_Func)( FT_Face face, (*FT_Get_Default_Named_Instance_Func)( FT_Face face,
FT_UInt num_coords, FT_UInt *instance_index );
FT_Long* coords );
typedef FT_Error
(*FT_Get_MM_Blend_Func)( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
typedef FT_Error typedef FT_Error
(*FT_Get_Var_Blend_Func)( FT_Face face, (*FT_Get_Var_Blend_Func)( FT_Face face,
@ -86,7 +90,7 @@ FT_BEGIN_HEADER
FT_MM_Var* *mm_var ); FT_MM_Var* *mm_var );
typedef void typedef void
(*FT_Done_Blend_Func)( FT_Face ); (*FT_Done_Blend_Func)( FT_Face face );
typedef FT_Error typedef FT_Error
(*FT_Set_MM_WeightVector_Func)( FT_Face face, (*FT_Set_MM_WeightVector_Func)( FT_Face face,
@ -98,6 +102,9 @@ FT_BEGIN_HEADER
FT_UInt* len, FT_UInt* len,
FT_Fixed* weight_vector ); FT_Fixed* weight_vector );
typedef void
(*FT_Construct_PS_Name_Func)( FT_Face face );
typedef FT_Error typedef FT_Error
(*FT_Var_Load_Delta_Set_Idx_Map_Func)( FT_Face face, (*FT_Var_Load_Delta_Set_Idx_Map_Func)( FT_Face face,
FT_ULong offset, FT_ULong offset,
@ -134,11 +141,13 @@ FT_BEGIN_HEADER
FT_Get_MM_Var_Func get_mm_var; FT_Get_MM_Var_Func get_mm_var;
FT_Set_Var_Design_Func set_var_design; FT_Set_Var_Design_Func set_var_design;
FT_Get_Var_Design_Func get_var_design; FT_Get_Var_Design_Func get_var_design;
FT_Set_Instance_Func set_instance; FT_Set_Named_Instance_Func set_named_instance;
FT_Get_Default_Named_Instance_Func get_default_named_instance;
FT_Set_MM_WeightVector_Func set_mm_weightvector; FT_Set_MM_WeightVector_Func set_mm_weightvector;
FT_Get_MM_WeightVector_Func get_mm_weightvector; FT_Get_MM_WeightVector_Func get_mm_weightvector;
/* for internal use; only needed for code sharing between modules */ /* for internal use; only needed for code sharing between modules */
FT_Construct_PS_Name_Func construct_ps_name;
FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map; FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map;
FT_Var_Load_Item_Var_Store_Func load_item_var_store; FT_Var_Load_Item_Var_Store_Func load_item_var_store;
FT_Var_Get_Item_Delta_Func get_item_delta; FT_Var_Get_Item_Delta_Func get_item_delta;
@ -149,43 +158,49 @@ FT_BEGIN_HEADER
}; };
#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \ #define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \
get_mm_, \ get_mm_, \
set_mm_design_, \ set_mm_design_, \
set_mm_blend_, \ set_mm_blend_, \
get_mm_blend_, \ get_mm_blend_, \
get_mm_var_, \ get_mm_var_, \
set_var_design_, \ set_var_design_, \
get_var_design_, \ get_var_design_, \
set_instance_, \ set_named_instance_, \
set_weightvector_, \ get_default_named_instance_, \
get_weightvector_, \ set_mm_weightvector_, \
load_delta_set_idx_map_, \ get_mm_weightvector_, \
load_item_var_store_, \ \
get_item_delta_, \ construct_ps_name_, \
done_item_var_store_, \ load_delta_set_idx_map_, \
done_delta_set_idx_map_, \ load_item_var_store_, \
get_var_blend_, \ get_item_delta_, \
done_blend_ ) \ done_item_var_store_, \
static const FT_Service_MultiMastersRec class_ = \ done_delta_set_idx_map_, \
{ \ get_var_blend_, \
get_mm_, \ done_blend_ ) \
set_mm_design_, \ static const FT_Service_MultiMastersRec class_ = \
set_mm_blend_, \ { \
get_mm_blend_, \ get_mm_, \
get_mm_var_, \ set_mm_design_, \
set_var_design_, \ set_mm_blend_, \
get_var_design_, \ get_mm_blend_, \
set_instance_, \ get_mm_var_, \
set_weightvector_, \ set_var_design_, \
get_weightvector_, \ get_var_design_, \
load_delta_set_idx_map_, \ set_named_instance_, \
load_item_var_store_, \ get_default_named_instance_, \
get_item_delta_, \ set_mm_weightvector_, \
done_item_var_store_, \ get_mm_weightvector_, \
done_delta_set_idx_map_, \ \
get_var_blend_, \ construct_ps_name_, \
done_blend_ \ load_delta_set_idx_map_, \
load_item_var_store_, \
get_item_delta_, \
done_item_var_store_, \
done_delta_set_idx_map_, \
get_var_blend_, \
done_blend_ \
}; };
/* */ /* */

View File

@ -97,7 +97,7 @@ FT_BEGIN_HEADER
(*PS_Unicodes_CharIndexFunc)( PS_Unicodes unicodes, (*PS_Unicodes_CharIndexFunc)( PS_Unicodes unicodes,
FT_UInt32 unicode ); FT_UInt32 unicode );
typedef FT_UInt32 typedef FT_UInt
(*PS_Unicodes_CharNextFunc)( PS_Unicodes unicodes, (*PS_Unicodes_CharNextFunc)( PS_Unicodes unicodes,
FT_UInt32 *unicode ); FT_UInt32 *unicode );

View File

@ -201,30 +201,30 @@ FT_BEGIN_HEADER
typedef struct T1_FaceRec_ typedef struct T1_FaceRec_
{ {
FT_FaceRec root; FT_FaceRec root;
T1_FontRec type1; T1_FontRec type1;
const void* psnames; const void* psnames;
const void* psaux; const void* psaux;
const void* afm_data; const void* afm_data;
FT_CharMapRec charmaprecs[2]; FT_CharMapRec charmaprecs[2];
FT_CharMap charmaps[2]; FT_CharMap charmaps[2];
/* support for Multiple Masters fonts */ /* support for Multiple Masters fonts */
PS_Blend blend; PS_Blend blend;
/* undocumented, optional: indices of subroutines that express */ /* undocumented, optional: indices of subroutines that express */
/* the NormalizeDesignVector and the ConvertDesignVector procedure, */ /* the NormalizeDesignVector and the ConvertDesignVector procedure, */
/* respectively, as Type 2 charstrings; -1 if keywords not present */ /* respectively, as Type 2 charstrings; -1 if keywords not present */
FT_Int ndv_idx; FT_Int ndv_idx;
FT_Int cdv_idx; FT_Int cdv_idx;
/* undocumented, optional: has the same meaning as len_buildchar */ /* undocumented, optional: has the same meaning as len_buildchar */
/* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */ /* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */
FT_UInt len_buildchar; FT_UInt len_buildchar;
FT_Long* buildchar; FT_Long* buildchar;
/* since version 2.1 - interface to PostScript hinter */ /* since version 2.1 - interface to PostScript hinter */
const void* pshinter; const void* pshinter;
} T1_FaceRec; } T1_FaceRec;

View File

@ -779,13 +779,15 @@ FT_BEGIN_HEADER
/************************************************************************** /**************************************************************************
* *
* @struct: * @struct:
* TT_Post_20Rec * TT_Post_NamesRec
* *
* @description: * @description:
* Postscript names sub-table, format 2.0. Stores the PS name of each * Postscript names table, either format 2.0 or 2.5.
* glyph in the font face.
* *
* @fields: * @fields:
* loaded ::
* A flag to indicate whether the PS names are loaded.
*
* num_glyphs :: * num_glyphs ::
* The number of named glyphs in the table. * The number of named glyphs in the table.
* *
@ -798,68 +800,13 @@ FT_BEGIN_HEADER
* glyph_names :: * glyph_names ::
* The PS names not in Mac Encoding. * The PS names not in Mac Encoding.
*/ */
typedef struct TT_Post_20Rec_ typedef struct TT_Post_NamesRec_
{ {
FT_Bool loaded;
FT_UShort num_glyphs; FT_UShort num_glyphs;
FT_UShort num_names; FT_UShort num_names;
FT_UShort* glyph_indices; FT_UShort* glyph_indices;
FT_Char** glyph_names; FT_Byte** glyph_names;
} TT_Post_20Rec, *TT_Post_20;
/**************************************************************************
*
* @struct:
* TT_Post_25Rec
*
* @description:
* Postscript names sub-table, format 2.5. Stores the PS name of each
* glyph in the font face.
*
* @fields:
* num_glyphs ::
* The number of glyphs in the table.
*
* offsets ::
* An array of signed offsets in a normal Mac Postscript name encoding.
*/
typedef struct TT_Post_25_
{
FT_UShort num_glyphs;
FT_Char* offsets;
} TT_Post_25Rec, *TT_Post_25;
/**************************************************************************
*
* @struct:
* TT_Post_NamesRec
*
* @description:
* Postscript names table, either format 2.0 or 2.5.
*
* @fields:
* loaded ::
* A flag to indicate whether the PS names are loaded.
*
* format_20 ::
* The sub-table used for format 2.0.
*
* format_25 ::
* The sub-table used for format 2.5.
*/
typedef struct TT_Post_NamesRec_
{
FT_Bool loaded;
union
{
TT_Post_20Rec format_20;
TT_Post_25Rec format_25;
} names;
} TT_Post_NamesRec, *TT_Post_Names; } TT_Post_NamesRec, *TT_Post_Names;
@ -1253,12 +1200,16 @@ FT_BEGIN_HEADER
* mm :: * mm ::
* A pointer to the Multiple Masters service. * A pointer to the Multiple Masters service.
* *
* var :: * tt_var ::
* A pointer to the Metrics Variations service. * A pointer to the Metrics Variations service for the "truetype"
* driver.
* *
* hdmx :: * face_var ::
* The face's horizontal device metrics ('hdmx' table). This table is * A pointer to the Metrics Variations service for this `TT_Face`'s
* optional in TrueType/OpenType fonts. * driver.
*
* psaux ::
* A pointer to the PostScript Auxiliary service.
* *
* gasp :: * gasp ::
* The grid-fitting and scaling properties table ('gasp'). This table * The grid-fitting and scaling properties table ('gasp'). This table
@ -1364,6 +1315,12 @@ FT_BEGIN_HEADER
* var_postscript_prefix_len :: * var_postscript_prefix_len ::
* The length of the `var_postscript_prefix` string. * The length of the `var_postscript_prefix` string.
* *
* var_default_named_instance ::
* The index of the default named instance.
*
* non_var_style_name ::
* The non-variation style name, used as a backup.
*
* horz_metrics_size :: * horz_metrics_size ::
* The size of the 'hmtx' table. * The size of the 'hmtx' table.
* *
@ -1410,14 +1367,6 @@ FT_BEGIN_HEADER
* A mapping between the strike indices exposed by the API and the * A mapping between the strike indices exposed by the API and the
* indices used in the font's sbit table. * indices used in the font's sbit table.
* *
* cpal ::
* A pointer to data related to the 'CPAL' table. `NULL` if the table
* is not available.
*
* colr ::
* A pointer to data related to the 'COLR' table. `NULL` if the table
* is not available.
*
* kern_table :: * kern_table ::
* A pointer to the 'kern' table. * A pointer to the 'kern' table.
* *
@ -1445,19 +1394,23 @@ FT_BEGIN_HEADER
* vert_metrics_offset :: * vert_metrics_offset ::
* The file offset of the 'vmtx' table. * The file offset of the 'vmtx' table.
* *
* sph_found_func_flags ::
* Flags identifying special bytecode functions (used by the v38
* implementation of the bytecode interpreter).
*
* sph_compatibility_mode ::
* This flag is set if we are in ClearType backward compatibility mode
* (used by the v38 implementation of the bytecode interpreter).
*
* ebdt_start :: * ebdt_start ::
* The file offset of the sbit data table (CBDT, bdat, etc.). * The file offset of the sbit data table (CBDT, bdat, etc.).
* *
* ebdt_size :: * ebdt_size ::
* The size of the sbit data table. * The size of the sbit data table.
*
* cpal ::
* A pointer to data related to the 'CPAL' table. `NULL` if the table
* is not available.
*
* colr ::
* A pointer to data related to the 'COLR' table. `NULL` if the table
* is not available.
*
* svg ::
* A pointer to data related to the 'SVG' table. `NULL` if the table
* is not available.
*/ */
typedef struct TT_FaceRec_ typedef struct TT_FaceRec_
{ {
@ -1508,8 +1461,14 @@ FT_BEGIN_HEADER
void* mm; void* mm;
/* a typeless pointer to the FT_Service_MetricsVariationsRec table */ /* a typeless pointer to the FT_Service_MetricsVariationsRec table */
/* used to handle the HVAR, VVAR, and MVAR OpenType tables */ /* used to handle the HVAR, VVAR, and MVAR OpenType tables by the */
void* var; /* "truetype" driver */
void* tt_var;
/* a typeless pointer to the FT_Service_MetricsVariationsRec table */
/* used to handle the HVAR, VVAR, and MVAR OpenType tables by this */
/* TT_Face's driver */
void* face_var; /* since 2.13.1 */
#endif #endif
/* a typeless pointer to the PostScript Aux service */ /* a typeless pointer to the PostScript Aux service */
@ -1591,6 +1550,9 @@ FT_BEGIN_HEADER
const char* var_postscript_prefix; /* since 2.7.2 */ const char* var_postscript_prefix; /* since 2.7.2 */
FT_UInt var_postscript_prefix_len; /* since 2.7.2 */ FT_UInt var_postscript_prefix_len; /* since 2.7.2 */
FT_UInt var_default_named_instance; /* since 2.13.1 */
const char* non_var_style_name; /* since 2.13.1 */
#endif #endif
/* since version 2.2 */ /* since version 2.2 */
@ -1627,13 +1589,6 @@ FT_BEGIN_HEADER
FT_ULong horz_metrics_offset; FT_ULong horz_metrics_offset;
FT_ULong vert_metrics_offset; FT_ULong vert_metrics_offset;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
/* since 2.4.12 */
FT_ULong sph_found_func_flags; /* special functions found */
/* for this face */
FT_Bool sph_compatibility_mode;
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
/* since 2.7 */ /* since 2.7 */
FT_ULong ebdt_start; /* either `CBDT', `EBDT', or `bdat' */ FT_ULong ebdt_start; /* either `CBDT', `EBDT', or `bdat' */

View File

@ -417,16 +417,14 @@
{ {
FT_Int nn; FT_Int nn;
FT_Int first = 0; FT_Int pp, first, last;
FT_Int last = -1;
for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ ) last = -1;
for ( nn = 0; nn < outline.n_contours; nn++ )
{ {
FT_Int pp; first = last + 1;
last = outline.contours[nn];
last = outline.contours[nn];
/* Avoid single-point contours since they are never rasterized. */ /* Avoid single-point contours since they are never rasterized. */
/* In some fonts, they correspond to mark attachment points */ /* In some fonts, they correspond to mark attachment points */
@ -569,8 +567,8 @@
af_cjk_metrics_check_digits( AF_CJKMetrics metrics, af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
FT_Face face ) FT_Face face )
{ {
FT_Bool started = 0, same_width = 1; FT_Bool started = 0, same_width = 1;
FT_Fixed advance = 0, old_advance = 0; FT_Long advance = 0, old_advance = 0;
/* If HarfBuzz is not available, we need a pointer to a single */ /* If HarfBuzz is not available, we need a pointer to a single */
/* unsigned long value. */ /* unsigned long value. */
@ -635,10 +633,11 @@
/* Initialize global metrics. */ /* Initialize global metrics. */
FT_LOCAL_DEF( FT_Error ) FT_LOCAL_DEF( FT_Error )
af_cjk_metrics_init( AF_CJKMetrics metrics, af_cjk_metrics_init( AF_StyleMetrics metrics_, /* AF_CJKMetrics */
FT_Face face ) FT_Face face )
{ {
FT_CharMap oldmap = face->charmap; AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_;
FT_CharMap oldmap = face->charmap;
metrics->units_per_em = face->units_per_EM; metrics->units_per_em = face->units_per_EM;
@ -756,9 +755,12 @@
/* Scale global values in both directions. */ /* Scale global values in both directions. */
FT_LOCAL_DEF( void ) FT_LOCAL_DEF( void )
af_cjk_metrics_scale( AF_CJKMetrics metrics, af_cjk_metrics_scale( AF_StyleMetrics metrics_, /* AF_CJKMetrics */
AF_Scaler scaler ) AF_Scaler scaler )
{ {
AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_;
/* we copy the whole structure since the x and y scaling values */ /* we copy the whole structure since the x and y scaling values */
/* are not modified, contrary to e.g. the `latin' auto-hinter */ /* are not modified, contrary to e.g. the `latin' auto-hinter */
metrics->root.scaler = *scaler; metrics->root.scaler = *scaler;
@ -771,11 +773,14 @@
/* Extract standard_width from writing system/script specific */ /* Extract standard_width from writing system/script specific */
/* metrics class. */ /* metrics class. */
FT_LOCAL_DEF( void ) FT_CALLBACK_DEF( void )
af_cjk_get_standard_widths( AF_CJKMetrics metrics, af_cjk_get_standard_widths( AF_StyleMetrics metrics_, /* AF_CJKMetrics */
FT_Pos* stdHW, FT_Pos* stdHW,
FT_Pos* stdVW ) FT_Pos* stdVW )
{ {
AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_;
if ( stdHW ) if ( stdHW )
*stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
@ -1376,9 +1381,10 @@
/* Initalize hinting engine. */ /* Initalize hinting engine. */
FT_LOCAL_DEF( FT_Error ) FT_LOCAL_DEF( FT_Error )
af_cjk_hints_init( AF_GlyphHints hints, af_cjk_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics ) AF_StyleMetrics metrics_ ) /* AF_CJKMetrics */
{ {
AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_;
FT_Render_Mode mode; FT_Render_Mode mode;
FT_UInt32 scaler_flags, other_flags; FT_UInt32 scaler_flags, other_flags;
@ -1628,7 +1634,7 @@
stem_edge->pos = base_edge->pos + fitted_width; stem_edge->pos = base_edge->pos + fitted_width;
FT_TRACE5(( " CJKLINK: edge %ld @%d (opos=%.2f) linked to %.2f," FT_TRACE5(( " CJKLINK: edge %td @%d (opos=%.2f) linked to %.2f,"
" dist was %.2f, now %.2f\n", " dist was %.2f, now %.2f\n",
stem_edge - hints->axis[dim].edges, stem_edge->fpos, stem_edge - hints->axis[dim].edges, stem_edge->fpos,
(double)stem_edge->opos / 64, (double)stem_edge->opos / 64,
@ -1852,7 +1858,7 @@
continue; continue;
#ifdef FT_DEBUG_LEVEL_TRACE #ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE5(( " CJKBLUE: edge %ld @%d (opos=%.2f) snapped to %.2f," FT_TRACE5(( " CJKBLUE: edge %td @%d (opos=%.2f) snapped to %.2f,"
" was %.2f\n", " was %.2f\n",
edge1 - edges, edge1->fpos, (double)edge1->opos / 64, edge1 - edges, edge1->fpos, (double)edge1->opos / 64,
(double)blue->fit / 64, (double)edge1->pos / 64 )); (double)blue->fit / 64, (double)edge1->pos / 64 ));
@ -1916,7 +1922,7 @@
/* this should not happen, but it's better to be safe */ /* this should not happen, but it's better to be safe */
if ( edge2->blue_edge ) if ( edge2->blue_edge )
{ {
FT_TRACE5(( "ASSERTION FAILED for edge %ld\n", edge2-edges )); FT_TRACE5(( "ASSERTION FAILED for edge %td\n", edge2 - edges ));
af_cjk_align_linked_edge( hints, dim, edge2, edge ); af_cjk_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE; edge->flags |= AF_EDGE_DONE;
@ -2268,11 +2274,13 @@
/* Apply the complete hinting algorithm to a CJK glyph. */ /* Apply the complete hinting algorithm to a CJK glyph. */
FT_LOCAL_DEF( FT_Error ) FT_LOCAL_DEF( FT_Error )
af_cjk_hints_apply( FT_UInt glyph_index, af_cjk_hints_apply( FT_UInt glyph_index,
AF_GlyphHints hints, AF_GlyphHints hints,
FT_Outline* outline, FT_Outline* outline,
AF_CJKMetrics metrics ) AF_StyleMetrics metrics_ ) /* AF_CJKMetrics */
{ {
AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_;
FT_Error error; FT_Error error;
int dim; int dim;

View File

@ -103,22 +103,22 @@ FT_BEGIN_HEADER
#ifdef AF_CONFIG_OPTION_CJK #ifdef AF_CONFIG_OPTION_CJK
FT_LOCAL( FT_Error ) FT_LOCAL( FT_Error )
af_cjk_metrics_init( AF_CJKMetrics metrics, af_cjk_metrics_init( AF_StyleMetrics metrics,
FT_Face face ); FT_Face face );
FT_LOCAL( void ) FT_LOCAL( void )
af_cjk_metrics_scale( AF_CJKMetrics metrics, af_cjk_metrics_scale( AF_StyleMetrics metrics,
AF_Scaler scaler ); AF_Scaler scaler );
FT_LOCAL( FT_Error ) FT_LOCAL( FT_Error )
af_cjk_hints_init( AF_GlyphHints hints, af_cjk_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics ); AF_StyleMetrics metrics );
FT_LOCAL( FT_Error ) FT_LOCAL( FT_Error )
af_cjk_hints_apply( FT_UInt glyph_index, af_cjk_hints_apply( FT_UInt glyph_index,
AF_GlyphHints hints, AF_GlyphHints hints,
FT_Outline* outline, FT_Outline* outline,
AF_CJKMetrics metrics ); AF_StyleMetrics metrics );
/* shared; called from afindic.c */ /* shared; called from afindic.c */
FT_LOCAL( void ) FT_LOCAL( void )

View File

@ -376,8 +376,11 @@
FT_LOCAL_DEF( void ) FT_LOCAL_DEF( void )
af_face_globals_free( AF_FaceGlobals globals ) af_face_globals_free( void* globals_ )
{ {
AF_FaceGlobals globals = (AF_FaceGlobals)globals_;
if ( globals ) if ( globals )
{ {
FT_Memory memory = globals->face->memory; FT_Memory memory = globals->face->memory;

View File

@ -156,7 +156,7 @@ FT_BEGIN_HEADER
AF_StyleMetrics *ametrics ); AF_StyleMetrics *ametrics );
FT_LOCAL( void ) FT_LOCAL( void )
af_face_globals_free( AF_FaceGlobals globals ); af_face_globals_free( void* globals );
FT_LOCAL( FT_Bool ) FT_LOCAL( FT_Bool )
af_face_globals_is_digit( AF_FaceGlobals globals, af_face_globals_is_digit( AF_FaceGlobals globals,

View File

@ -320,8 +320,9 @@
static char* static char*
af_print_idx( char* p, af_print_idx( char* p,
int idx ) size_t n,
int idx )
{ {
if ( idx == -1 ) if ( idx == -1 )
{ {
@ -330,7 +331,7 @@
p[2] = '\0'; p[2] = '\0';
} }
else else
ft_sprintf( p, "%d", idx ); ft_snprintf( p, n, "%d", idx );
return p; return p;
} }
@ -457,12 +458,12 @@
" %5d %5d %7.2f %7.2f %7.2f %7.2f" " %5d %5d %7.2f %7.2f %7.2f %7.2f"
" %5s %5s %5s %5s\n", " %5s %5s %5s %5s\n",
point_idx, point_idx,
af_print_idx( buf1, af_print_idx( buf1, 16,
af_get_edge_index( hints, segment_idx_1, 1 ) ), af_get_edge_index( hints, segment_idx_1, 1 ) ),
af_print_idx( buf2, segment_idx_1 ), af_print_idx( buf2, 16, segment_idx_1 ),
af_print_idx( buf3, af_print_idx( buf3, 16,
af_get_edge_index( hints, segment_idx_0, 0 ) ), af_get_edge_index( hints, segment_idx_0, 0 ) ),
af_print_idx( buf4, segment_idx_0 ), af_print_idx( buf4, 16, segment_idx_0 ),
( point->flags & AF_FLAG_NEAR ) ( point->flags & AF_FLAG_NEAR )
? " near " ? " near "
: ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) : ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
@ -476,18 +477,22 @@
(double)point->x / 64, (double)point->x / 64,
(double)point->y / 64, (double)point->y / 64,
af_print_idx( buf5, af_get_strong_edge_index( hints, af_print_idx( buf5, 16,
point->before, af_get_strong_edge_index( hints,
1 ) ), point->before,
af_print_idx( buf6, af_get_strong_edge_index( hints, 1 ) ),
point->after, af_print_idx( buf6, 16,
1 ) ), af_get_strong_edge_index( hints,
af_print_idx( buf7, af_get_strong_edge_index( hints, point->after,
point->before, 1 ) ),
0 ) ), af_print_idx( buf7, 16,
af_print_idx( buf8, af_get_strong_edge_index( hints, af_get_strong_edge_index( hints,
point->after, point->before,
0 ) ) )); 0 ) ),
af_print_idx( buf8, 16,
af_get_strong_edge_index( hints,
point->after,
0 ) ) ));
} }
AF_DUMP(( "\n" )); AF_DUMP(( "\n" ));
} }
@ -574,9 +579,12 @@
AF_INDEX_NUM( seg->first, points ), AF_INDEX_NUM( seg->first, points ),
AF_INDEX_NUM( seg->last, points ), AF_INDEX_NUM( seg->last, points ),
af_print_idx( buf1, AF_INDEX_NUM( seg->link, segments ) ), af_print_idx( buf1, 16,
af_print_idx( buf2, AF_INDEX_NUM( seg->serif, segments ) ), AF_INDEX_NUM( seg->link, segments ) ),
af_print_idx( buf3, AF_INDEX_NUM( seg->edge, edges ) ), af_print_idx( buf2, 16,
AF_INDEX_NUM( seg->serif, segments ) ),
af_print_idx( buf3, 16,
AF_INDEX_NUM( seg->edge, edges ) ),
seg->height, seg->height,
seg->height - ( seg->max_coord - seg->min_coord ), seg->height - ( seg->max_coord - seg->min_coord ),
@ -716,8 +724,10 @@
AF_INDEX_NUM( edge, edges ), AF_INDEX_NUM( edge, edges ),
(double)(int)edge->opos / 64, (double)(int)edge->opos / 64,
af_dir_str( (AF_Direction)edge->dir ), af_dir_str( (AF_Direction)edge->dir ),
af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ), af_print_idx( buf1, 16,
af_print_idx( buf2, AF_INDEX_NUM( edge->serif, edges ) ), AF_INDEX_NUM( edge->link, edges ) ),
af_print_idx( buf2, 16,
AF_INDEX_NUM( edge->serif, edges ) ),
edge->blue_edge ? 'y' : 'n', edge->blue_edge ? 'y' : 'n',
(double)edge->opos / 64, (double)edge->opos / 64,

View File

@ -28,9 +28,12 @@
static FT_Error static FT_Error
af_indic_metrics_init( AF_CJKMetrics metrics, af_indic_metrics_init( AF_StyleMetrics metrics_, /* AF_CJKMetrics */
FT_Face face ) FT_Face face )
{ {
AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_;
/* skip blue zone init in CJK routines */ /* skip blue zone init in CJK routines */
FT_CharMap oldmap = face->charmap; FT_CharMap oldmap = face->charmap;
@ -55,8 +58,8 @@
static void static void
af_indic_metrics_scale( AF_CJKMetrics metrics, af_indic_metrics_scale( AF_StyleMetrics metrics,
AF_Scaler scaler ) AF_Scaler scaler )
{ {
/* use CJK routines */ /* use CJK routines */
af_cjk_metrics_scale( metrics, scaler ); af_cjk_metrics_scale( metrics, scaler );
@ -64,8 +67,8 @@
static FT_Error static FT_Error
af_indic_hints_init( AF_GlyphHints hints, af_indic_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics ) AF_StyleMetrics metrics )
{ {
/* use CJK routines */ /* use CJK routines */
return af_cjk_hints_init( hints, metrics ); return af_cjk_hints_init( hints, metrics );
@ -73,10 +76,10 @@
static FT_Error static FT_Error
af_indic_hints_apply( FT_UInt glyph_index, af_indic_hints_apply( FT_UInt glyph_index,
AF_GlyphHints hints, AF_GlyphHints hints,
FT_Outline* outline, FT_Outline* outline,
AF_CJKMetrics metrics ) AF_StyleMetrics metrics )
{ {
/* use CJK routines */ /* use CJK routines */
return af_cjk_hints_apply( glyph_index, hints, outline, metrics ); return af_cjk_hints_apply( glyph_index, hints, outline, metrics );
@ -87,10 +90,13 @@
/* metrics class. */ /* metrics class. */
static void static void
af_indic_get_standard_widths( AF_CJKMetrics metrics, af_indic_get_standard_widths( AF_StyleMetrics metrics_, /* AF_CJKMetrics */
FT_Pos* stdHW, FT_Pos* stdHW,
FT_Pos* stdVW ) FT_Pos* stdVW )
{ {
AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_;
if ( stdHW ) if ( stdHW )
*stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;

View File

@ -496,23 +496,20 @@
/* now compute min or max point indices and coordinates */ /* now compute min or max point indices and coordinates */
points = outline.points; points = outline.points;
best_point = -1; best_point = -1;
best_contour_first = -1;
best_contour_last = -1;
best_y = 0; /* make compiler happy */ best_y = 0; /* make compiler happy */
best_contour_first = 0; /* ditto */
best_contour_last = 0; /* ditto */
{ {
FT_Int nn; FT_Int nn;
FT_Int first = 0; FT_Int pp, first, last;
FT_Int last = -1;
for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ ) last = -1;
for ( nn = 0; nn < outline.n_contours; nn++ )
{ {
FT_Int old_best_point = best_point; first = last + 1;
FT_Int pp; last = outline.contours[nn];
last = outline.contours[nn];
/* Avoid single-point contours since they are never */ /* Avoid single-point contours since they are never */
/* rasterized. In some fonts, they correspond to mark */ /* rasterized. In some fonts, they correspond to mark */
@ -551,7 +548,7 @@
} }
} }
if ( best_point != old_best_point ) if ( best_point > best_contour_last )
{ {
best_contour_first = first; best_contour_first = first;
best_contour_last = last; best_contour_last = last;
@ -1025,7 +1022,7 @@
{ {
*a = *b; *a = *b;
FT_TRACE5(( "blue zone overlap:" FT_TRACE5(( "blue zone overlap:"
" adjusting %s %ld to %ld\n", " adjusting %s %td to %ld\n",
a_is_top ? "overshoot" : "reference", a_is_top ? "overshoot" : "reference",
blue_sorted[i] - axis->blues, blue_sorted[i] - axis->blues,
*a )); *a ));
@ -1068,8 +1065,8 @@
af_latin_metrics_check_digits( AF_LatinMetrics metrics, af_latin_metrics_check_digits( AF_LatinMetrics metrics,
FT_Face face ) FT_Face face )
{ {
FT_Bool started = 0, same_width = 1; FT_Bool started = 0, same_width = 1;
FT_Fixed advance = 0, old_advance = 0; FT_Long advance = 0, old_advance = 0;
/* If HarfBuzz is not available, we need a pointer to a single */ /* If HarfBuzz is not available, we need a pointer to a single */
/* unsigned long value. */ /* unsigned long value. */
@ -1134,9 +1131,11 @@
/* Initialize global metrics. */ /* Initialize global metrics. */
FT_LOCAL_DEF( FT_Error ) FT_LOCAL_DEF( FT_Error )
af_latin_metrics_init( AF_LatinMetrics metrics, af_latin_metrics_init( AF_StyleMetrics metrics_, /* AF_LatinMetrics */
FT_Face face ) FT_Face face )
{ {
AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_;
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_CharMap oldmap = face->charmap; FT_CharMap oldmap = face->charmap;
@ -1489,9 +1488,12 @@
/* Scale global values in both directions. */ /* Scale global values in both directions. */
FT_LOCAL_DEF( void ) FT_LOCAL_DEF( void )
af_latin_metrics_scale( AF_LatinMetrics metrics, af_latin_metrics_scale( AF_StyleMetrics metrics_, /* AF_LatinMetrics */
AF_Scaler scaler ) AF_Scaler scaler )
{ {
AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_;
metrics->root.scaler.render_mode = scaler->render_mode; metrics->root.scaler.render_mode = scaler->render_mode;
metrics->root.scaler.face = scaler->face; metrics->root.scaler.face = scaler->face;
metrics->root.scaler.flags = scaler->flags; metrics->root.scaler.flags = scaler->flags;
@ -1504,11 +1506,14 @@
/* Extract standard_width from writing system/script specific */ /* Extract standard_width from writing system/script specific */
/* metrics class. */ /* metrics class. */
FT_LOCAL_DEF( void ) FT_CALLBACK_DEF( void )
af_latin_get_standard_widths( AF_LatinMetrics metrics, af_latin_get_standard_widths( AF_StyleMetrics metrics_, /* AF_LatinMetrics */
FT_Pos* stdHW, FT_Pos* stdHW,
FT_Pos* stdVW ) FT_Pos* stdVW )
{ {
AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_;
if ( stdHW ) if ( stdHW )
*stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
@ -2041,7 +2046,7 @@
max = seg2->max_coord; max = seg2->max_coord;
/* compute maximum coordinate difference of the two segments */ /* compute maximum coordinate difference of the two segments */
/* (this is, how much they overlap) */ /* (that is, how much they overlap) */
len = max - min; len = max - min;
if ( len >= len_threshold ) if ( len >= len_threshold )
{ {
@ -2610,8 +2615,10 @@
static FT_Error static FT_Error
af_latin_hints_init( AF_GlyphHints hints, af_latin_hints_init( AF_GlyphHints hints,
AF_LatinMetrics metrics ) AF_StyleMetrics metrics_ ) /* AF_LatinMetrics */
{ {
AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_;
FT_Render_Mode mode; FT_Render_Mode mode;
FT_UInt32 scaler_flags, other_flags; FT_UInt32 scaler_flags, other_flags;
FT_Face face = metrics->root.scaler.face; FT_Face face = metrics->root.scaler.face;
@ -2953,7 +2960,7 @@
stem_edge->pos = base_edge->pos + fitted_width; stem_edge->pos = base_edge->pos + fitted_width;
FT_TRACE5(( " LINK: edge %ld (opos=%.2f) linked to %.2f," FT_TRACE5(( " LINK: edge %td (opos=%.2f) linked to %.2f,"
" dist was %.2f, now %.2f\n", " dist was %.2f, now %.2f\n",
stem_edge - hints->axis[dim].edges, stem_edge - hints->axis[dim].edges,
(double)stem_edge->opos / 64, (double)stem_edge->pos / 64, (double)stem_edge->opos / 64, (double)stem_edge->pos / 64,
@ -3078,13 +3085,13 @@
#ifdef FT_DEBUG_LEVEL_TRACE #ifdef FT_DEBUG_LEVEL_TRACE
if ( !anchor ) if ( !anchor )
FT_TRACE5(( " BLUE_ANCHOR: edge %ld (opos=%.2f) snapped to %.2f," FT_TRACE5(( " BLUE_ANCHOR: edge %td (opos=%.2f) snapped to %.2f,"
" was %.2f (anchor=edge %ld)\n", " was %.2f (anchor=edge %td)\n",
edge1 - edges, edge1 - edges,
(double)edge1->opos / 64, (double)blue->fit / 64, (double)edge1->opos / 64, (double)blue->fit / 64,
(double)edge1->pos / 64, edge - edges )); (double)edge1->pos / 64, edge - edges ));
else else
FT_TRACE5(( " BLUE: edge %ld (opos=%.2f) snapped to %.2f," FT_TRACE5(( " BLUE: edge %td (opos=%.2f) snapped to %.2f,"
" was %.2f\n", " was %.2f\n",
edge1 - edges, edge1 - edges,
(double)edge1->opos / 64, (double)blue->fit / 64, (double)edge1->opos / 64, (double)blue->fit / 64,
@ -3134,7 +3141,7 @@
/* this should not happen, but it's better to be safe */ /* this should not happen, but it's better to be safe */
if ( edge2->blue_edge ) if ( edge2->blue_edge )
{ {
FT_TRACE5(( " ASSERTION FAILED for edge %ld\n", edge2 - edges )); FT_TRACE5(( " ASSERTION FAILED for edge %td\n", edge2 - edges ));
af_latin_align_linked_edge( hints, dim, edge2, edge ); af_latin_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE; edge->flags |= AF_EDGE_DONE;
@ -3202,7 +3209,7 @@
anchor = edge; anchor = edge;
edge->flags |= AF_EDGE_DONE; edge->flags |= AF_EDGE_DONE;
FT_TRACE5(( " ANCHOR: edge %ld (opos=%.2f) and %ld (opos=%.2f)" FT_TRACE5(( " ANCHOR: edge %td (opos=%.2f) and %td (opos=%.2f)"
" snapped to %.2f and %.2f\n", " snapped to %.2f and %.2f\n",
edge - edges, (double)edge->opos / 64, edge - edges, (double)edge->opos / 64,
edge2 - edges, (double)edge2->opos / 64, edge2 - edges, (double)edge2->opos / 64,
@ -3231,7 +3238,7 @@
if ( edge2->flags & AF_EDGE_DONE ) if ( edge2->flags & AF_EDGE_DONE )
{ {
FT_TRACE5(( " ADJUST: edge %ld (pos=%.2f) moved to %.2f\n", FT_TRACE5(( " ADJUST: edge %td (pos=%.2f) moved to %.2f\n",
edge - edges, (double)edge->pos / 64, edge - edges, (double)edge->pos / 64,
(double)( edge2->pos - cur_len ) / 64 )); (double)( edge2->pos - cur_len ) / 64 ));
@ -3272,7 +3279,7 @@
edge->pos = cur_pos1 - cur_len / 2; edge->pos = cur_pos1 - cur_len / 2;
edge2->pos = cur_pos1 + cur_len / 2; edge2->pos = cur_pos1 + cur_len / 2;
FT_TRACE5(( " STEM: edge %ld (opos=%.2f) linked to %ld (opos=%.2f)" FT_TRACE5(( " STEM: edge %td (opos=%.2f) linked to %td (opos=%.2f)"
" snapped to %.2f and %.2f\n", " snapped to %.2f and %.2f\n",
edge - edges, (double)edge->opos / 64, edge - edges, (double)edge->opos / 64,
edge2 - edges, (double)edge2->opos / 64, edge2 - edges, (double)edge2->opos / 64,
@ -3303,7 +3310,7 @@
edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2; edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2;
edge2->pos = edge->pos + cur_len; edge2->pos = edge->pos + cur_len;
FT_TRACE5(( " STEM: edge %ld (opos=%.2f) linked to %ld (opos=%.2f)" FT_TRACE5(( " STEM: edge %td (opos=%.2f) linked to %td (opos=%.2f)"
" snapped to %.2f and %.2f\n", " snapped to %.2f and %.2f\n",
edge - edges, (double)edge->opos / 64, edge - edges, (double)edge->opos / 64,
edge2 - edges, (double)edge2->opos / 64, edge2 - edges, (double)edge2->opos / 64,
@ -3326,7 +3333,7 @@
if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 ) if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
{ {
#ifdef FT_DEBUG_LEVEL_TRACE #ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n", FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n",
edge - edges, edge - edges,
(double)edge->pos / 64, (double)edge->pos / 64,
(double)edge[-1].pos / 64 )); (double)edge[-1].pos / 64 ));
@ -3428,7 +3435,7 @@
if ( delta < 64 + 16 ) if ( delta < 64 + 16 )
{ {
af_latin_align_serif_edge( hints, edge->serif, edge ); af_latin_align_serif_edge( hints, edge->serif, edge );
FT_TRACE5(( " SERIF: edge %ld (opos=%.2f) serif to %ld (opos=%.2f)" FT_TRACE5(( " SERIF: edge %td (opos=%.2f) serif to %td (opos=%.2f)"
" aligned to %.2f\n", " aligned to %.2f\n",
edge - edges, (double)edge->opos / 64, edge - edges, (double)edge->opos / 64,
edge->serif - edges, (double)edge->serif->opos / 64, edge->serif - edges, (double)edge->serif->opos / 64,
@ -3438,9 +3445,9 @@
{ {
edge->pos = FT_PIX_ROUND( edge->opos ); edge->pos = FT_PIX_ROUND( edge->opos );
anchor = edge; anchor = edge;
FT_TRACE5(( " SERIF_ANCHOR: edge %ld (opos=%.2f)" FT_TRACE5(( " SERIF_ANCHOR: edge %td (opos=%.2f)"
" snapped to %.2f\n", " snapped to %.2f\n",
edge-edges, edge - edges,
(double)edge->opos / 64, (double)edge->pos / 64 )); (double)edge->opos / 64, (double)edge->pos / 64 ));
} }
else else
@ -3467,8 +3474,8 @@
after->pos - before->pos, after->pos - before->pos,
after->opos - before->opos ); after->opos - before->opos );
FT_TRACE5(( " SERIF_LINK1: edge %ld (opos=%.2f) snapped to %.2f" FT_TRACE5(( " SERIF_LINK1: edge %td (opos=%.2f) snapped to %.2f"
" from %ld (opos=%.2f)\n", " from %td (opos=%.2f)\n",
edge - edges, (double)edge->opos / 64, edge - edges, (double)edge->opos / 64,
(double)edge->pos / 64, (double)edge->pos / 64,
before - edges, (double)before->opos / 64 )); before - edges, (double)before->opos / 64 ));
@ -3477,7 +3484,7 @@
{ {
edge->pos = anchor->pos + edge->pos = anchor->pos +
( ( edge->opos - anchor->opos + 16 ) & ~31 ); ( ( edge->opos - anchor->opos + 16 ) & ~31 );
FT_TRACE5(( " SERIF_LINK2: edge %ld (opos=%.2f)" FT_TRACE5(( " SERIF_LINK2: edge %td (opos=%.2f)"
" snapped to %.2f\n", " snapped to %.2f\n",
edge - edges, edge - edges,
(double)edge->opos / 64, (double)edge->pos / 64 )); (double)edge->opos / 64, (double)edge->pos / 64 ));
@ -3498,7 +3505,7 @@
if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 ) if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
{ {
#ifdef FT_DEBUG_LEVEL_TRACE #ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n", FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n",
edge - edges, edge - edges,
(double)edge->pos / 64, (double)edge->pos / 64,
(double)edge[-1].pos / 64 )); (double)edge[-1].pos / 64 ));
@ -3519,7 +3526,7 @@
if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 ) if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
{ {
#ifdef FT_DEBUG_LEVEL_TRACE #ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n", FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n",
edge - edges, edge - edges,
(double)edge->pos / 64, (double)edge->pos / 64,
(double)edge[1].pos / 64 )); (double)edge[1].pos / 64 ));
@ -3547,8 +3554,10 @@
af_latin_hints_apply( FT_UInt glyph_index, af_latin_hints_apply( FT_UInt glyph_index,
AF_GlyphHints hints, AF_GlyphHints hints,
FT_Outline* outline, FT_Outline* outline,
AF_LatinMetrics metrics ) AF_StyleMetrics metrics_ ) /* AF_LatinMetrics */
{ {
AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_;
FT_Error error; FT_Error error;
int dim; int dim;

View File

@ -116,11 +116,11 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error ) FT_LOCAL( FT_Error )
af_latin_metrics_init( AF_LatinMetrics metrics, af_latin_metrics_init( AF_StyleMetrics metrics,
FT_Face face ); FT_Face face );
FT_LOCAL( void ) FT_LOCAL( void )
af_latin_metrics_scale( AF_LatinMetrics metrics, af_latin_metrics_scale( AF_StyleMetrics metrics,
AF_Scaler scaler ); AF_Scaler scaler );
FT_LOCAL( void ) FT_LOCAL( void )

View File

@ -55,10 +55,8 @@
error = af_face_globals_new( face, &loader->globals, module ); error = af_face_globals_new( face, &loader->globals, module );
if ( !error ) if ( !error )
{ {
face->autohint.data = face->autohint.data = (FT_Pointer)loader->globals;
(FT_Pointer)loader->globals; face->autohint.finalizer = af_face_globals_free;
face->autohint.finalizer =
(FT_Generic_Finalizer)af_face_globals_free;
} }
} }

View File

@ -89,10 +89,8 @@
error = af_face_globals_new( face, &globals, module ); error = af_face_globals_new( face, &globals, module );
if ( !error ) if ( !error )
{ {
face->autohint.data = face->autohint.data = (FT_Pointer)globals;
(FT_Pointer)globals; face->autohint.finalizer = af_face_globals_free;
face->autohint.finalizer =
(FT_Generic_Finalizer)af_face_globals_free;
} }
} }
@ -374,8 +372,9 @@
FT_DEFINE_SERVICE_PROPERTIESREC( FT_DEFINE_SERVICE_PROPERTIESREC(
af_service_properties, af_service_properties,
(FT_Properties_SetFunc)af_property_set, /* set_property */ af_property_set, /* FT_Properties_SetFunc set_property */
(FT_Properties_GetFunc)af_property_get ) /* get_property */ af_property_get /* FT_Properties_GetFunc get_property */
)
FT_DEFINE_SERVICEDESCREC1( FT_DEFINE_SERVICEDESCREC1(
@ -430,12 +429,14 @@
FT_CALLBACK_DEF( FT_Error ) FT_CALLBACK_DEF( FT_Error )
af_autofitter_load_glyph( AF_Module module, af_autofitter_load_glyph( FT_AutoHinter module_,
FT_GlyphSlot slot, FT_GlyphSlot slot,
FT_Size size, FT_Size size,
FT_UInt glyph_index, FT_UInt glyph_index,
FT_Int32 load_flags ) FT_Int32 load_flags )
{ {
AF_Module module = (AF_Module)module_;
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_Memory memory = module->root.library->memory; FT_Memory memory = module->root.library->memory;
@ -499,10 +500,10 @@
FT_DEFINE_AUTOHINTER_INTERFACE( FT_DEFINE_AUTOHINTER_INTERFACE(
af_autofitter_interface, af_autofitter_interface,
NULL, /* reset_face */ NULL, /* FT_AutoHinter_GlobalResetFunc reset_face */
NULL, /* get_global_hints */ NULL, /* FT_AutoHinter_GlobalGetFunc get_global_hints */
NULL, /* done_global_hints */ NULL, /* FT_AutoHinter_GlobalDoneFunc done_global_hints */
(FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph /* load_glyph */ af_autofitter_load_glyph /* FT_AutoHinter_GlyphLoadFunc load_glyph */
) )
FT_DEFINE_MODULE( FT_DEFINE_MODULE(
@ -517,9 +518,9 @@
(const void*)&af_autofitter_interface, (const void*)&af_autofitter_interface,
(FT_Module_Constructor)af_autofitter_init, /* module_init */ af_autofitter_init, /* FT_Module_Constructor module_init */
(FT_Module_Destructor) af_autofitter_done, /* module_done */ af_autofitter_done, /* FT_Module_Destructor module_done */
(FT_Module_Requester) af_get_interface /* get_interface */ af_get_interface /* FT_Module_Requester get_interface */
) )

View File

@ -258,7 +258,7 @@
/* /*
* We now check whether we can construct blue zones, using glyphs * We now check whether we can construct blue zones, using glyphs
* covered by the feature only. In case there is not a single zone * covered by the feature only. In case there is not a single zone
* (this is, not a single character is covered), we skip this coverage. * (that is, not a single character is covered), we skip this coverage.
* *
*/ */
if ( style_class->coverage != AF_COVERAGE_DEFAULT ) if ( style_class->coverage != AF_COVERAGE_DEFAULT )
@ -313,9 +313,9 @@
* hinted and usually rendered glyph. * hinted and usually rendered glyph.
* *
* Consider the superscript feature of font `pala.ttf': Some of the * Consider the superscript feature of font `pala.ttf': Some of the
* glyphs are `real', this is, they have a zero vertical offset, but * glyphs are `real', that is, they have a zero vertical offset, but
* most of them are small caps glyphs shifted up to the superscript * most of them are small caps glyphs shifted up to the superscript
* position (this is, the `sups' feature is present in both the GSUB and * position (that is, the `sups' feature is present in both the GSUB and
* GPOS tables). The code for blue zones computation actually uses a * GPOS tables). The code for blue zones computation actually uses a
* feature's y offset so that the `real' glyphs get correct hints. But * feature's y offset so that the `real' glyphs get correct hints. But
* later on it is impossible to decide whether a glyph index belongs to, * later on it is impossible to decide whether a glyph index belongs to,

View File

@ -108,7 +108,7 @@ hb_ft_font_create_ (FT_Face ft_face,
#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ #else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
/* ANSI C doesn't like empty source files */ /* ANSI C doesn't like empty source files */
typedef int _ft_hb_dummy; typedef int ft_hb_dummy_;
#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ #endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */

View File

@ -82,10 +82,13 @@
* @Return: * @Return:
* Always 0. Needed for the interface only. * Always 0. Needed for the interface only.
*/ */
static int FT_CALLBACK_DEF( int )
BBox_Move_To( FT_Vector* to, BBox_Move_To( const FT_Vector* to,
TBBox_Rec* user ) void* user_ )
{ {
TBBox_Rec* user = (TBBox_Rec*)user_;
FT_UPDATE_BBOX( to, user->bbox ); FT_UPDATE_BBOX( to, user->bbox );
user->last = *to; user->last = *to;
@ -116,10 +119,13 @@
* @Return: * @Return:
* Always 0. Needed for the interface only. * Always 0. Needed for the interface only.
*/ */
static int FT_CALLBACK_DEF( int )
BBox_Line_To( FT_Vector* to, BBox_Line_To( const FT_Vector* to,
TBBox_Rec* user ) void* user_ )
{ {
TBBox_Rec* user = (TBBox_Rec*)user_;
user->last = *to; user->last = *to;
return 0; return 0;
@ -205,11 +211,14 @@
* In the case of a non-monotonous arc, we compute directly the * In the case of a non-monotonous arc, we compute directly the
* extremum coordinates, as it is sufficiently fast. * extremum coordinates, as it is sufficiently fast.
*/ */
static int FT_CALLBACK_DEF( int )
BBox_Conic_To( FT_Vector* control, BBox_Conic_To( const FT_Vector* control,
FT_Vector* to, const FT_Vector* to,
TBBox_Rec* user ) void* user_ )
{ {
TBBox_Rec* user = (TBBox_Rec*)user_;
/* in case `to' is implicit and not included in bbox yet */ /* in case `to' is implicit and not included in bbox yet */
FT_UPDATE_BBOX( to, user->bbox ); FT_UPDATE_BBOX( to, user->bbox );
@ -410,12 +419,15 @@
* In the case of a non-monotonous arc, we don't compute directly * In the case of a non-monotonous arc, we don't compute directly
* extremum coordinates, we subdivide instead. * extremum coordinates, we subdivide instead.
*/ */
static int FT_CALLBACK_DEF( int )
BBox_Cubic_To( FT_Vector* control1, BBox_Cubic_To( const FT_Vector* control1,
FT_Vector* control2, const FT_Vector* control2,
FT_Vector* to, const FT_Vector* to,
TBBox_Rec* user ) void* user_ )
{ {
TBBox_Rec* user = (TBBox_Rec*)user_;
/* We don't need to check `to' since it is always an on-point, */ /* We don't need to check `to' since it is always an on-point, */
/* thus within the bbox. Only segments with an off-point outside */ /* thus within the bbox. Only segments with an off-point outside */
/* the bbox can possibly reach new extreme values. */ /* the bbox can possibly reach new extreme values. */

View File

@ -749,65 +749,43 @@
FT_BASE_DEF( FT_Bool ) FT_BASE_DEF( FT_Bool )
FT_Matrix_Check( const FT_Matrix* matrix ) FT_Matrix_Check( const FT_Matrix* matrix )
{ {
FT_Matrix m; FT_Fixed xx, xy, yx, yy;
FT_Fixed val[4]; FT_Fixed val;
FT_Fixed nonzero_minval, maxval; FT_Int shift;
FT_Fixed temp1, temp2; FT_ULong temp1, temp2;
FT_UInt i;
if ( !matrix ) if ( !matrix )
return 0; return 0;
val[0] = FT_ABS( matrix->xx ); xx = matrix->xx;
val[1] = FT_ABS( matrix->xy ); xy = matrix->xy;
val[2] = FT_ABS( matrix->yx ); yx = matrix->yx;
val[3] = FT_ABS( matrix->yy ); yy = matrix->yy;
val = FT_ABS( xx ) | FT_ABS( xy ) | FT_ABS( yx ) | FT_ABS( yy );
/* /* we only handle non-zero 32-bit values */
* To avoid overflow, we ensure that each value is not larger than if ( !val || val > 0x7FFFFFFFL )
*
* int(sqrt(2^31 / 4)) = 23170 ;
*
* we also check that no value becomes zero if we have to scale.
*/
maxval = 0;
nonzero_minval = FT_LONG_MAX;
for ( i = 0; i < 4; i++ )
{
if ( val[i] > maxval )
maxval = val[i];
if ( val[i] && val[i] < nonzero_minval )
nonzero_minval = val[i];
}
/* we only handle 32bit values */
if ( maxval > 0x7FFFFFFFL )
return 0; return 0;
if ( maxval > 23170 ) /* Scale matrix to avoid the temp1 overflow, which is */
/* more stringent than avoiding the temp2 overflow. */
shift = FT_MSB( val ) - 12;
if ( shift > 0 )
{ {
FT_Fixed scale = FT_DivFix( maxval, 23170 ); xx >>= shift;
xy >>= shift;
yx >>= shift;
if ( !FT_DivFix( nonzero_minval, scale ) ) yy >>= shift;
return 0; /* value range too large */
m.xx = FT_DivFix( matrix->xx, scale );
m.xy = FT_DivFix( matrix->xy, scale );
m.yx = FT_DivFix( matrix->yx, scale );
m.yy = FT_DivFix( matrix->yy, scale );
} }
else
m = *matrix;
temp1 = FT_ABS( m.xx * m.yy - m.xy * m.yx ); temp1 = 32U * (FT_ULong)FT_ABS( xx * yy - xy * yx );
temp2 = m.xx * m.xx + m.xy * m.xy + m.yx * m.yx + m.yy * m.yy; temp2 = (FT_ULong)( xx * xx ) + (FT_ULong)( xy * xy ) +
(FT_ULong)( yx * yx ) + (FT_ULong)( yy * yy );
if ( temp1 == 0 || if ( temp1 <= temp2 )
temp2 / temp1 > 50 )
return 0; return 0;
return 1; return 1;
@ -1061,7 +1039,7 @@
/* */ /* */
/* This approach has the advantage that the angle between */ /* This approach has the advantage that the angle between */
/* `in' and `out' is not checked. In case one of the two */ /* `in' and `out' is not checked. In case one of the two */
/* vectors is `dominant', this is, much larger than the */ /* vectors is `dominant', that is, much larger than the */
/* other vector, we thus always have a flat corner. */ /* other vector, we thus always have a flat corner. */
/* */ /* */
/* hypotenuse */ /* hypotenuse */
@ -1092,9 +1070,6 @@
{ {
FT_UInt i; FT_UInt i;
FT_Int64 temp; FT_Int64 temp;
#ifndef FT_INT64
FT_Int64 halfUnit;
#endif
#ifdef FT_INT64 #ifdef FT_INT64
@ -1103,7 +1078,7 @@
for ( i = 0; i < count; ++i ) for ( i = 0; i < count; ++i )
temp += (FT_Int64)s[i] * f[i]; temp += (FT_Int64)s[i] * f[i];
return ( temp + 0x8000 ) >> 16; return (FT_Int32)( ( temp + 0x8000 ) >> 16 );
#else #else
temp.hi = 0; temp.hi = 0;
temp.lo = 0; temp.lo = 0;
@ -1139,13 +1114,10 @@
FT_Add64( &temp, &multResult, &temp ); FT_Add64( &temp, &multResult, &temp );
} }
/* Round value. */ /* Shift and round value. */
halfUnit.hi = 0; return (FT_Int32)( ( ( temp.hi << 16 ) | ( temp.lo >> 16 ) )
halfUnit.lo = 0x8000; + ( 1 & ( temp.lo >> 15 ) ) );
FT_Add64( &temp, &halfUnit, &temp );
return (FT_Int32)( ( (FT_Int32)( temp.hi & 0xFFFF ) << 16 ) |
( temp.lo >> 16 ) );
#endif /* !FT_INT64 */ #endif /* !FT_INT64 */

View File

@ -963,7 +963,7 @@
#else /* !FT_DEBUG_MEMORY */ #else /* !FT_DEBUG_MEMORY */
/* ANSI C doesn't like empty source files */ /* ANSI C doesn't like empty source files */
typedef int _debug_mem_dummy; typedef int debug_mem_dummy_;
#endif /* !FT_DEBUG_MEMORY */ #endif /* !FT_DEBUG_MEMORY */

View File

@ -1082,7 +1082,7 @@
#else /* !FT_MACINTOSH */ #else /* !FT_MACINTOSH */
/* ANSI C doesn't like empty source files */ /* ANSI C doesn't like empty source files */
typedef int _ft_mac_dummy; typedef int ft_mac_dummy_;
#endif /* !FT_MACINTOSH */ #endif /* !FT_MACINTOSH */

Some files were not shown because too many files have changed in this diff Show More