diff --git a/BINDINGS.md b/BINDINGS.md
index e79d39c36..576d9b463 100644
--- a/BINDINGS.md
+++ b/BINDINGS.md
@@ -31,7 +31,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [raylib-go](https://github.com/gen2brain/raylib-go) | **5.0** | [Go](https://golang.org) | Zlib |
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
| [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) | **???** |
-| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.1-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
+| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.5-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
| [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 4.2 | [Haxe](https://haxe.org) | Zlib |
| [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.5 | [Harbour](https://harbour.github.io) | MIT |
| [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT |
diff --git a/build.zig b/build.zig
index 01e7b49fb..56e69caf4 100644
--- a/build.zig
+++ b/build.zig
@@ -1,11 +1,434 @@
const std = @import("std");
-const raylib = @import("src/build.zig");
+const builtin = @import("builtin");
-// This has been tested to work with zig 0.12.0
-pub fn build(b: *std.Build) !void {
- try raylib.build(b);
+/// Minimum supported version of Zig
+const min_ver = "0.12.0";
+
+comptime {
+ const order = std.SemanticVersion.order;
+ const parse = std.SemanticVersion.parse;
+ if (order(builtin.zig_version, parse(min_ver) catch unreachable) == .lt)
+ @compileError("Raylib requires zig version " ++ min_ver);
}
-// expose helper functions to user's build.zig
-pub const addRaylib = raylib.addRaylib;
-pub const addRaygui = raylib.addRaygui;
+// NOTE(freakmangd): I don't like using a global here, but it prevents having to
+// get the flags a second time when adding raygui
+var raylib_flags_arr: std.ArrayListUnmanaged([]const u8) = .{};
+
+// This has been tested with zig version 0.12.0
+pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
+ const raylib_dep = b.dependencyFromBuildZig(@This(), .{
+ .target = target,
+ .optimize = optimize,
+ .raudio = options.raudio,
+ .rmodels = options.rmodels,
+ .rshapes = options.rshapes,
+ .rtext = options.rtext,
+ .rtextures = options.rtextures,
+ .platform = options.platform,
+ .shared = options.shared,
+ .linux_display_backend = options.linux_display_backend,
+ .opengl_version = options.opengl_version,
+ .config = options.config,
+ });
+ const raylib = raylib_dep.artifact("raylib");
+
+ if (options.raygui) {
+ const raygui_dep = b.dependency(options.raygui_dependency_name, .{});
+ addRaygui(b, raylib, raygui_dep);
+ }
+
+ return raylib;
+}
+
+fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void {
+ raylib.defineCMacro("PLATFORM_DESKTOP", null);
+
+ switch (platform) {
+ .glfw => raylib.defineCMacro("PLATFORM_DESKTOP_GLFW", null),
+ .rgfw => raylib.defineCMacro("PLATFORM_DESKTOP_RGFW", null),
+ .sdl => raylib.defineCMacro("PLATFORM_DESKTOP_SDL", null),
+ else => {},
+ }
+}
+
+/// A list of all flags from `src/config.h` that one may override
+const config_h_flags = outer: {
+ // Set this value higher if compile errors happen as `src/config.h` gets larger
+ @setEvalBranchQuota(1 << 20);
+
+ const config_h = @embedFile("src/config.h");
+ var flags: [std.mem.count(u8, config_h, "\n") + 1][]const u8 = undefined;
+
+ var i = 0;
+ var lines = std.mem.tokenizeScalar(u8, config_h, '\n');
+ while (lines.next()) |line| {
+ if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue;
+ if (std.mem.startsWith(u8, line, "//")) continue;
+ if (std.mem.startsWith(u8, line, "#if")) continue;
+
+ var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace
+ flag = flag["#define ".len - 1 ..]; // Remove #define
+ flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace
+ flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space
+ flag = "-D" ++ flag; // Prepend with -D
+
+ flags[i] = flag;
+ i += 1;
+ }
+
+ // Uncomment this to check what flags normally get passed
+ //@compileLog(flags[0..i].*);
+ break :outer flags[0..i].*;
+};
+
+fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
+ raylib_flags_arr.clearRetainingCapacity();
+
+ const shared_flags = &[_][]const u8{
+ "-fPIC",
+ "-DBUILD_LIBTYPE_SHARED",
+ };
+ try raylib_flags_arr.appendSlice(b.allocator, &[_][]const u8{
+ "-std=gnu99",
+ "-D_GNU_SOURCE",
+ "-DGL_SILENCE_DEPRECATION=199309L",
+ "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674
+ });
+ if (options.config.len > 0) {
+ // Sets a flag indiciating the use of a custom `config.h`
+ try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS");
+
+ // Splits a space-separated list of config flags into multiple flags
+ //
+ // Note: This means certain flags like `-x c++` won't be processed properly.
+ // `-xc++` or similar should be used when possible
+ var config_iter = std.mem.tokenizeScalar(u8, options.config, ' ');
+
+ // Apply config flags supplied by the user
+ while (config_iter.next()) |config_flag|
+ try raylib_flags_arr.append(b.allocator, config_flag);
+
+ // Apply all relevant configs from `src/config.h` *except* the user-specified ones
+ //
+ // Note: Currently using a suboptimal `O(m*n)` time algorithm where:
+ // `m` corresponds roughly to the number of lines in `src/config.h`
+ // `n` corresponds to the number of user-specified flags
+ outer: for (config_h_flags) |flag| {
+ // If a user already specified the flag, skip it
+ while (config_iter.next()) |config_flag| {
+ // For a user-specified flag to match, it must share the same prefix and have the
+ // same length or be followed by an equals sign
+ if (!std.mem.startsWith(u8, config_flag, flag)) continue;
+ if (config_flag.len == flag.len or config_flag[flag.len] == '=') continue :outer;
+ }
+
+ // Otherwise, append default value from config.h to compile flags
+ try raylib_flags_arr.append(b.allocator, flag);
+ }
+ }
+
+ if (options.shared) {
+ try raylib_flags_arr.appendSlice(b.allocator, shared_flags);
+ }
+
+ const raylib = if (options.shared)
+ b.addSharedLibrary(.{
+ .name = "raylib",
+ .target = target,
+ .optimize = optimize,
+ })
+ else
+ b.addStaticLibrary(.{
+ .name = "raylib",
+ .target = target,
+ .optimize = optimize,
+ });
+ raylib.linkLibC();
+
+ // No GLFW required on PLATFORM_DRM
+ if (options.platform != .drm) {
+ raylib.addIncludePath(b.path("src/external/glfw/include"));
+ }
+
+ var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2);
+ c_source_files.appendSliceAssumeCapacity(&.{ "src/rcore.c", "src/utils.c" });
+
+ if (options.raudio) {
+ try c_source_files.append("src/raudio.c");
+ }
+ if (options.rmodels) {
+ try c_source_files.append("src/rmodels.c");
+ }
+ if (options.rshapes) {
+ try c_source_files.append("src/rshapes.c");
+ }
+ if (options.rtext) {
+ try c_source_files.append("src/rtext.c");
+ }
+ if (options.rtextures) {
+ try c_source_files.append("src/rtextures.c");
+ }
+
+ if (options.opengl_version != .auto) {
+ raylib.defineCMacro(options.opengl_version.toCMacroStr(), null);
+ }
+
+ switch (target.result.os.tag) {
+ .windows => {
+ try c_source_files.append("src/rglfw.c");
+ raylib.linkSystemLibrary("winmm");
+ raylib.linkSystemLibrary("gdi32");
+ raylib.linkSystemLibrary("opengl32");
+
+ setDesktopPlatform(raylib, options.platform);
+ },
+ .linux => {
+ if (options.platform != .drm) {
+ try c_source_files.append("src/rglfw.c");
+ raylib.linkSystemLibrary("GL");
+ raylib.linkSystemLibrary("rt");
+ raylib.linkSystemLibrary("dl");
+ raylib.linkSystemLibrary("m");
+
+ raylib.addLibraryPath(.{ .cwd_relative = "/usr/lib" });
+ raylib.addIncludePath(.{ .cwd_relative = "/usr/include" });
+ if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
+ raylib.defineCMacro("_GLFW_X11", null);
+ raylib.linkSystemLibrary("X11");
+ }
+
+ if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
+ _ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
+ std.log.err(
+ \\ `wayland-scanner` may not be installed on the system.
+ \\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
+ , .{});
+ @panic("`wayland-scanner` not found");
+ };
+ raylib.defineCMacro("_GLFW_WAYLAND", null);
+ raylib.linkSystemLibrary("wayland-client");
+ raylib.linkSystemLibrary("wayland-cursor");
+ raylib.linkSystemLibrary("wayland-egl");
+ raylib.linkSystemLibrary("xkbcommon");
+ waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol");
+ waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol");
+ waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol");
+ waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol");
+ waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol");
+ waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol");
+ waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol");
+ waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol");
+ waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol");
+ }
+ setDesktopPlatform(raylib, options.platform);
+ } else {
+ if (options.opengl_version == .auto) {
+ raylib.linkSystemLibrary("GLESv2");
+ raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null);
+ }
+
+ raylib.linkSystemLibrary("EGL");
+ raylib.linkSystemLibrary("drm");
+ raylib.linkSystemLibrary("gbm");
+ raylib.linkSystemLibrary("pthread");
+ raylib.linkSystemLibrary("rt");
+ raylib.linkSystemLibrary("m");
+ raylib.linkSystemLibrary("dl");
+ raylib.addIncludePath(.{ .cwd_relative = "/usr/include/libdrm" });
+
+ raylib.defineCMacro("PLATFORM_DRM", null);
+ raylib.defineCMacro("EGL_NO_X11", null);
+ raylib.defineCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "2048");
+ }
+ },
+ .freebsd, .openbsd, .netbsd, .dragonfly => {
+ try c_source_files.append("rglfw.c");
+ raylib.linkSystemLibrary("GL");
+ raylib.linkSystemLibrary("rt");
+ raylib.linkSystemLibrary("dl");
+ raylib.linkSystemLibrary("m");
+ raylib.linkSystemLibrary("X11");
+ raylib.linkSystemLibrary("Xrandr");
+ raylib.linkSystemLibrary("Xinerama");
+ raylib.linkSystemLibrary("Xi");
+ raylib.linkSystemLibrary("Xxf86vm");
+ raylib.linkSystemLibrary("Xcursor");
+
+ setDesktopPlatform(raylib, options.platform);
+ },
+ .macos => {
+ // On macos rglfw.c include Objective-C files.
+ try raylib_flags_arr.append(b.allocator, "-ObjC");
+ raylib.root_module.addCSourceFile(.{
+ .file = b.path("src/rglfw.c"),
+ .flags = raylib_flags_arr.items,
+ });
+ _ = raylib_flags_arr.pop();
+ raylib.linkFramework("Foundation");
+ raylib.linkFramework("CoreServices");
+ raylib.linkFramework("CoreGraphics");
+ raylib.linkFramework("AppKit");
+ raylib.linkFramework("IOKit");
+
+ setDesktopPlatform(raylib, options.platform);
+ },
+ .emscripten => {
+ raylib.defineCMacro("PLATFORM_WEB", null);
+ if (options.opengl_version == .auto) {
+ raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null);
+ }
+
+ if (b.sysroot == null) {
+ @panic("Pass '--sysroot \"$EMSDK/upstream/emscripten\"'");
+ }
+
+ const cache_include = b.pathJoin(&.{ b.sysroot.?, "cache", "sysroot", "include" });
+
+ var dir = std.fs.openDirAbsolute(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!");
+ dir.close();
+ raylib.addIncludePath(.{ .cwd_relative = cache_include });
+ },
+ else => {
+ @panic("Unsupported OS");
+ },
+ }
+
+ raylib.root_module.addCSourceFiles(.{
+ .files = c_source_files.items,
+ .flags = raylib_flags_arr.items,
+ });
+
+ return raylib;
+}
+
+/// This function does not need to be called if you passed .raygui = true to addRaylib
+pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency) void {
+ if (raylib_flags_arr.items.len == 0) {
+ @panic(
+ \\argument 2 `raylib` in `addRaygui` must come from b.dependency("raylib", ...).artifact("raylib")
+ );
+ }
+
+ var gen_step = b.addWriteFiles();
+ raylib.step.dependOn(&gen_step.step);
+
+ const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
+ raylib.addCSourceFile(.{ .file = raygui_c_path, .flags = raylib_flags_arr.items });
+ raylib.addIncludePath(raygui_dep.path("src"));
+
+ raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
+}
+
+pub const Options = struct {
+ raudio: bool = true,
+ rmodels: bool = true,
+ rshapes: bool = true,
+ rtext: bool = true,
+ rtextures: bool = true,
+ raygui: bool = false,
+ platform: PlatformBackend = .glfw,
+ shared: bool = false,
+ linux_display_backend: LinuxDisplayBackend = .Both,
+ opengl_version: OpenglVersion = .auto,
+ /// config should be a list of space-separated cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL"
+ config: []const u8 = &.{},
+
+ raygui_dependency_name: []const u8 = "raygui",
+
+ const defaults = Options{};
+
+ fn getOptions(b: *std.Build) Options {
+ return .{
+ .platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform,
+ .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio,
+ .raygui = b.option(bool, "raygui", "Compile with raygui support") orelse defaults.raygui,
+ .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels,
+ .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,
+ .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures,
+ .rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes,
+ .shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared,
+ .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend,
+ .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version,
+ .config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse &.{},
+ };
+ }
+};
+
+pub const OpenglVersion = enum {
+ auto,
+ gl_1_1,
+ gl_2_1,
+ gl_3_3,
+ gl_4_3,
+ gles_2,
+ gles_3,
+
+ pub fn toCMacroStr(self: @This()) []const u8 {
+ switch (self) {
+ .auto => @panic("OpenglVersion.auto cannot be turned into a C macro string"),
+ .gl_1_1 => return "GRAPHICS_API_OPENGL_11",
+ .gl_2_1 => return "GRAPHICS_API_OPENGL_21",
+ .gl_3_3 => return "GRAPHICS_API_OPENGL_33",
+ .gl_4_3 => return "GRAPHICS_API_OPENGL_43",
+ .gles_2 => return "GRAPHICS_API_OPENGL_ES2",
+ .gles_3 => return "GRAPHICS_API_OPENGL_ES3",
+ }
+ }
+};
+
+pub const LinuxDisplayBackend = enum {
+ X11,
+ Wayland,
+ Both,
+};
+
+pub const PlatformBackend = enum {
+ glfw,
+ rgfw,
+ sdl,
+ drm,
+};
+
+pub fn build(b: *std.Build) !void {
+ // Standard target options allows the person running `zig build` to choose
+ // what target to build for. Here we do not override the defaults, which
+ // means any target is allowed, and the default is native. Other options
+ // for restricting supported target set are available.
+ const target = b.standardTargetOptions(.{});
+ // Standard optimization options allow the person running `zig build` to select
+ // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
+ // set a preferred release mode, allowing the user to decide how to optimize.
+ const optimize = b.standardOptimizeOption(.{});
+
+ const lib = try compileRaylib(b, target, optimize, Options.getOptions(b));
+
+ lib.installHeader(b.path("src/raylib.h"), "raylib.h");
+ lib.installHeader(b.path("src/raymath.h"), "raymath.h");
+ lib.installHeader(b.path("src/rlgl.h"), "rlgl.h");
+
+ b.installArtifact(lib);
+}
+
+fn waylandGenerate(
+ b: *std.Build,
+ raylib: *std.Build.Step.Compile,
+ comptime protocol: []const u8,
+ comptime basename: []const u8,
+) void {
+ const waylandDir = "src/external/glfw/deps/wayland";
+ const protocolDir = b.pathJoin(&.{ waylandDir, protocol });
+ const clientHeader = basename ++ ".h";
+ const privateCode = basename ++ "-code.h";
+
+ const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" });
+ client_step.addFileArg(b.path(protocolDir));
+ raylib.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname());
+
+ const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
+ private_step.addFileArg(b.path(protocolDir));
+ raylib.addIncludePath(private_step.addOutputFileArg(privateCode).dirname());
+
+ raylib.step.dependOn(&client_step.step);
+ raylib.step.dependOn(&private_step.step);
+}
diff --git a/examples/Makefile b/examples/Makefile
index 01c8e45d7..65ee4fb80 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -549,7 +549,6 @@ TEXTURES = \
textures/textures_sprite_button \
textures/textures_sprite_explosion \
textures/textures_srcrec_dstrec \
- textures/textures_svg_loading \
textures/textures_textured_curve \
textures/textures_to_image
diff --git a/examples/Makefile.Web b/examples/Makefile.Web
index b176217ae..f6c8b785a 100644
--- a/examples/Makefile.Web
+++ b/examples/Makefile.Web
@@ -415,7 +415,6 @@ TEXTURES = \
textures/textures_sprite_button \
textures/textures_sprite_explosion \
textures/textures_srcrec_dstrec \
- textures/textures_svg_loading \
textures/textures_textured_curve \
textures/textures_to_image
@@ -776,10 +775,6 @@ textures/textures_srcrec_dstrec: textures/textures_srcrec_dstrec.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/scarfy.png@resources/scarfy.png
-textures/textures_svg_loading: textures/textures_svg_loading.c
- $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
- --preload-file textures/resources/test.svg
-
textures/textures_textured_curve: textures/textures_textured_curve.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/road.png@resources/road.png
diff --git a/examples/models/models_gpu_skinning.c b/examples/models/models_gpu_skinning.c
index 846f0a890..b6296c96a 100644
--- a/examples/models/models_gpu_skinning.c
+++ b/examples/models/models_gpu_skinning.c
@@ -81,7 +81,6 @@ int main(void)
// Update model animation
ModelAnimation anim = modelAnimations[animIndex];
animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount;
- UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame);
//----------------------------------------------------------------------------------
// Draw
diff --git a/examples/textures/resources/test.svg b/examples/textures/resources/test.svg
deleted file mode 100644
index 3d9bbb113..000000000
--- a/examples/textures/resources/test.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/examples/textures/textures_svg_loading.c b/examples/textures/textures_svg_loading.c
deleted file mode 100644
index 434ec7602..000000000
--- a/examples/textures/textures_svg_loading.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*******************************************************************************************
-*
-* raylib [textures] example - SVG loading and texture creation
-*
-* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM)
-*
-* Example originally created with raylib 4.2, last time updated with raylib 4.2
-*
-* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
-* BSD-like license that allows static linking with closed source software
-*
-* Copyright (c) 2022 Dennis Meinen (@bixxy#4258 on Discord)
-*
-********************************************************************************************/
-
-#include "raylib.h"
-
-//------------------------------------------------------------------------------------
-// Program main entry point
-//------------------------------------------------------------------------------------
-int main(void)
-{
- // Initialization
- //--------------------------------------------------------------------------------------
- const int screenWidth = 800;
- const int screenHeight = 450;
-
- InitWindow(screenWidth, screenHeight, "raylib [textures] example - svg loading");
-
- // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
-
- Image image = LoadImageSvg("resources/test.svg", 400, 350); // Loaded in CPU memory (RAM)
- Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM)
- UnloadImage(image); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM
-
- SetTargetFPS(60); // Set our game to run at 60 frames-per-second
- //---------------------------------------------------------------------------------------
-
- // Main game loop
- while (!WindowShouldClose()) // Detect window close button or ESC key
- {
- // Update
- //----------------------------------------------------------------------------------
- // TODO: Update your variables here
- //----------------------------------------------------------------------------------
-
- // Draw
- //----------------------------------------------------------------------------------
- BeginDrawing();
-
- ClearBackground(RAYWHITE);
-
- DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE);
-
- //Red border to illustrate how the SVG is centered within the specified dimensions
- DrawRectangleLines((screenWidth / 2 - texture.width / 2) - 1, (screenHeight / 2 - texture.height / 2) - 1, texture.width + 2, texture.height + 2, RED);
-
- DrawText("this IS a texture loaded from an SVG file!", 300, 410, 10, GRAY);
-
- EndDrawing();
- //----------------------------------------------------------------------------------
- }
-
- // De-Initialization
- //--------------------------------------------------------------------------------------
- UnloadTexture(texture); // Texture unloading
-
- CloseWindow(); // Close window and OpenGL context
- //--------------------------------------------------------------------------------------
-
- return 0;
-}
\ No newline at end of file
diff --git a/examples/textures/textures_svg_loading.png b/examples/textures/textures_svg_loading.png
deleted file mode 100644
index fa98605fa..000000000
Binary files a/examples/textures/textures_svg_loading.png and /dev/null differ
diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json
index 58fb9d6a8..591fef737 100644
--- a/parser/output/raylib_api.json
+++ b/parser/output/raylib_api.json
@@ -3763,8 +3763,8 @@
]
},
{
- "name": "IsShaderReady",
- "description": "Check if a shader is ready",
+ "name": "IsShaderValid",
+ "description": "Check if a shader is valid (loaded on GPU)",
"returnType": "bool",
"params": [
{
@@ -4691,6 +4691,51 @@
}
]
},
+ {
+ "name": "ComputeCRC32",
+ "description": "Compute CRC32 hash code",
+ "returnType": "unsigned int",
+ "params": [
+ {
+ "type": "unsigned char *",
+ "name": "data"
+ },
+ {
+ "type": "int",
+ "name": "dataSize"
+ }
+ ]
+ },
+ {
+ "name": "ComputeMD5",
+ "description": "Compute MD5 hash code, returns static int[4] (16 bytes)",
+ "returnType": "unsigned int *",
+ "params": [
+ {
+ "type": "unsigned char *",
+ "name": "data"
+ },
+ {
+ "type": "int",
+ "name": "dataSize"
+ }
+ ]
+ },
+ {
+ "name": "ComputeSHA1",
+ "description": "Compute SHA1 hash code, returns static int[5] (20 bytes)",
+ "returnType": "unsigned int *",
+ "params": [
+ {
+ "type": "unsigned char *",
+ "name": "data"
+ },
+ {
+ "type": "int",
+ "name": "dataSize"
+ }
+ ]
+ },
{
"name": "LoadAutomationEventList",
"description": "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS",
@@ -5186,7 +5231,7 @@
},
{
"name": "GetGestureHoldDuration",
- "description": "Get gesture hold time in milliseconds",
+ "description": "Get gesture hold time in seconds",
"returnType": "float"
},
{
@@ -6815,25 +6860,6 @@
}
]
},
- {
- "name": "LoadImageSvg",
- "description": "Load image from SVG file data or string with specified size",
- "returnType": "Image",
- "params": [
- {
- "type": "const char *",
- "name": "fileNameOrString"
- },
- {
- "type": "int",
- "name": "width"
- },
- {
- "type": "int",
- "name": "height"
- }
- ]
- },
{
"name": "LoadImageAnim",
"description": "Load image sequence from file (frames appended to image.data)",
@@ -6908,8 +6934,8 @@
"returnType": "Image"
},
{
- "name": "IsImageReady",
- "description": "Check if an image is ready",
+ "name": "IsImageValid",
+ "description": "Check if an image is valid (data and parameters)",
"returnType": "bool",
"params": [
{
@@ -8372,8 +8398,8 @@
]
},
{
- "name": "IsTextureReady",
- "description": "Check if a texture is ready",
+ "name": "IsTextureValid",
+ "description": "Check if a texture is valid (loaded in GPU)",
"returnType": "bool",
"params": [
{
@@ -8394,8 +8420,8 @@
]
},
{
- "name": "IsRenderTextureReady",
- "description": "Check if a render texture is ready",
+ "name": "IsRenderTextureValid",
+ "description": "Check if a render texture is valid (loaded in GPU)",
"returnType": "bool",
"params": [
{
@@ -8989,8 +9015,8 @@
]
},
{
- "name": "IsFontReady",
- "description": "Check if a font is ready",
+ "name": "IsFontValid",
+ "description": "Check if a font is valid (font data loaded, WARNING: GPU texture not checked)",
"returnType": "bool",
"params": [
{
@@ -10281,8 +10307,8 @@
]
},
{
- "name": "IsModelReady",
- "description": "Check if a model is ready",
+ "name": "IsModelValid",
+ "description": "Check if a model is valid (loaded in GPU, VAO/VBOs)",
"returnType": "bool",
"params": [
{
@@ -10968,8 +10994,8 @@
"returnType": "Material"
},
{
- "name": "IsMaterialReady",
- "description": "Check if a material is ready",
+ "name": "IsMaterialValid",
+ "description": "Check if a material is valid (shader assigned, map textures loaded in GPU)",
"returnType": "bool",
"params": [
{
@@ -11343,8 +11369,8 @@
]
},
{
- "name": "IsWaveReady",
- "description": "Checks if wave data is ready",
+ "name": "IsWaveValid",
+ "description": "Checks if wave data is valid (data loaded and parameters)",
"returnType": "bool",
"params": [
{
@@ -11387,8 +11413,8 @@
]
},
{
- "name": "IsSoundReady",
- "description": "Checks if a sound is ready",
+ "name": "IsSoundValid",
+ "description": "Checks if a sound is valid (data loaded and buffers initialized)",
"returnType": "bool",
"params": [
{
@@ -11685,8 +11711,8 @@
]
},
{
- "name": "IsMusicReady",
- "description": "Checks if a music stream is ready",
+ "name": "IsMusicValid",
+ "description": "Checks if a music stream is valid (context and buffers initialized)",
"returnType": "bool",
"params": [
{
@@ -11874,8 +11900,8 @@
]
},
{
- "name": "IsAudioStreamReady",
- "description": "Checks if an audio stream is ready",
+ "name": "IsAudioStreamValid",
+ "description": "Checks if an audio stream is valid (buffers initialized)",
"returnType": "bool",
"params": [
{
diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua
index bea3813cf..b84e3c08c 100644
--- a/parser/output/raylib_api.lua
+++ b/parser/output/raylib_api.lua
@@ -3589,8 +3589,8 @@ return {
}
},
{
- name = "IsShaderReady",
- description = "Check if a shader is ready",
+ name = "IsShaderValid",
+ description = "Check if a shader is valid (loaded on GPU)",
returnType = "bool",
params = {
{type = "Shader", name = "shader"}
@@ -4190,6 +4190,33 @@ return {
{type = "int *", name = "outputSize"}
}
},
+ {
+ name = "ComputeCRC32",
+ description = "Compute CRC32 hash code",
+ returnType = "unsigned int",
+ params = {
+ {type = "unsigned char *", name = "data"},
+ {type = "int", name = "dataSize"}
+ }
+ },
+ {
+ name = "ComputeMD5",
+ description = "Compute MD5 hash code, returns static int[4] (16 bytes)",
+ returnType = "unsigned int *",
+ params = {
+ {type = "unsigned char *", name = "data"},
+ {type = "int", name = "dataSize"}
+ }
+ },
+ {
+ name = "ComputeSHA1",
+ description = "Compute SHA1 hash code, returns static int[5] (20 bytes)",
+ returnType = "unsigned int *",
+ params = {
+ {type = "unsigned char *", name = "data"},
+ {type = "int", name = "dataSize"}
+ }
+ },
{
name = "LoadAutomationEventList",
description = "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS",
@@ -4550,7 +4577,7 @@ return {
},
{
name = "GetGestureHoldDuration",
- description = "Get gesture hold time in milliseconds",
+ description = "Get gesture hold time in seconds",
returnType = "float"
},
{
@@ -5339,16 +5366,6 @@ return {
{type = "int", name = "headerSize"}
}
},
- {
- name = "LoadImageSvg",
- description = "Load image from SVG file data or string with specified size",
- returnType = "Image",
- params = {
- {type = "const char *", name = "fileNameOrString"},
- {type = "int", name = "width"},
- {type = "int", name = "height"}
- }
- },
{
name = "LoadImageAnim",
description = "Load image sequence from file (frames appended to image.data)",
@@ -5393,8 +5410,8 @@ return {
returnType = "Image"
},
{
- name = "IsImageReady",
- description = "Check if an image is ready",
+ name = "IsImageValid",
+ description = "Check if an image is valid (data and parameters)",
returnType = "bool",
params = {
{type = "Image", name = "image"}
@@ -6158,8 +6175,8 @@ return {
}
},
{
- name = "IsTextureReady",
- description = "Check if a texture is ready",
+ name = "IsTextureValid",
+ description = "Check if a texture is valid (loaded in GPU)",
returnType = "bool",
params = {
{type = "Texture2D", name = "texture"}
@@ -6174,8 +6191,8 @@ return {
}
},
{
- name = "IsRenderTextureReady",
- description = "Check if a render texture is ready",
+ name = "IsRenderTextureValid",
+ description = "Check if a render texture is valid (loaded in GPU)",
returnType = "bool",
params = {
{type = "RenderTexture2D", name = "target"}
@@ -6505,8 +6522,8 @@ return {
}
},
{
- name = "IsFontReady",
- description = "Check if a font is ready",
+ name = "IsFontValid",
+ description = "Check if a font is valid (font data loaded, WARNING: GPU texture not checked)",
returnType = "bool",
params = {
{type = "Font", name = "font"}
@@ -7185,8 +7202,8 @@ return {
}
},
{
- name = "IsModelReady",
- description = "Check if a model is ready",
+ name = "IsModelValid",
+ description = "Check if a model is valid (loaded in GPU, VAO/VBOs)",
returnType = "bool",
params = {
{type = "Model", name = "model"}
@@ -7539,8 +7556,8 @@ return {
returnType = "Material"
},
{
- name = "IsMaterialReady",
- description = "Check if a material is ready",
+ name = "IsMaterialValid",
+ description = "Check if a material is valid (shader assigned, map textures loaded in GPU)",
returnType = "bool",
params = {
{type = "Material", name = "material"}
@@ -7758,8 +7775,8 @@ return {
}
},
{
- name = "IsWaveReady",
- description = "Checks if wave data is ready",
+ name = "IsWaveValid",
+ description = "Checks if wave data is valid (data loaded and parameters)",
returnType = "bool",
params = {
{type = "Wave", name = "wave"}
@@ -7790,8 +7807,8 @@ return {
}
},
{
- name = "IsSoundReady",
- description = "Checks if a sound is ready",
+ name = "IsSoundValid",
+ description = "Checks if a sound is valid (data loaded and buffers initialized)",
returnType = "bool",
params = {
{type = "Sound", name = "sound"}
@@ -7980,8 +7997,8 @@ return {
}
},
{
- name = "IsMusicReady",
- description = "Checks if a music stream is ready",
+ name = "IsMusicValid",
+ description = "Checks if a music stream is valid (context and buffers initialized)",
returnType = "bool",
params = {
{type = "Music", name = "music"}
@@ -8106,8 +8123,8 @@ return {
}
},
{
- name = "IsAudioStreamReady",
- description = "Checks if an audio stream is ready",
+ name = "IsAudioStreamValid",
+ description = "Checks if an audio stream is valid (buffers initialized)",
returnType = "bool",
params = {
{type = "AudioStream", name = "stream"}
diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt
index 9a953b768..e0d5f36b4 100644
--- a/parser/output/raylib_api.txt
+++ b/parser/output/raylib_api.txt
@@ -989,7 +989,7 @@ Callback 006: AudioCallback() (2 input parameters)
Param[1]: bufferData (type: void *)
Param[2]: frames (type: unsigned int)
-Functions found: 578
+Functions found: 580
Function 001: InitWindow() (3 input parameters)
Name: InitWindow
@@ -1378,10 +1378,10 @@ Function 075: LoadShaderFromMemory() (2 input parameters)
Description: Load shader from code strings and bind default locations
Param[1]: vsCode (type: const char *)
Param[2]: fsCode (type: const char *)
-Function 076: IsShaderReady() (1 input parameters)
- Name: IsShaderReady
+Function 076: IsShaderValid() (1 input parameters)
+ Name: IsShaderValid
Return type: bool
- Description: Check if a shader is ready
+ Description: Check if a shader is valid (loaded on GPU)
Param[1]: shader (type: Shader)
Function 077: GetShaderLocation() (2 input parameters)
Name: GetShaderLocation
@@ -1788,294 +1788,312 @@ Function 148: DecodeDataBase64() (2 input parameters)
Description: Decode Base64 string data, memory must be MemFree()
Param[1]: data (type: const unsigned char *)
Param[2]: outputSize (type: int *)
-Function 149: LoadAutomationEventList() (1 input parameters)
+Function 149: ComputeCRC32() (2 input parameters)
+ Name: ComputeCRC32
+ Return type: unsigned int
+ Description: Compute CRC32 hash code
+ Param[1]: data (type: unsigned char *)
+ Param[2]: dataSize (type: int)
+Function 150: ComputeMD5() (2 input parameters)
+ Name: ComputeMD5
+ Return type: unsigned int *
+ Description: Compute MD5 hash code, returns static int[4] (16 bytes)
+ Param[1]: data (type: unsigned char *)
+ Param[2]: dataSize (type: int)
+Function 151: ComputeSHA1() (2 input parameters)
+ Name: ComputeSHA1
+ Return type: unsigned int *
+ Description: Compute SHA1 hash code, returns static int[5] (20 bytes)
+ Param[1]: data (type: unsigned char *)
+ Param[2]: dataSize (type: int)
+Function 152: LoadAutomationEventList() (1 input parameters)
Name: LoadAutomationEventList
Return type: AutomationEventList
Description: Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
Param[1]: fileName (type: const char *)
-Function 150: UnloadAutomationEventList() (1 input parameters)
+Function 153: UnloadAutomationEventList() (1 input parameters)
Name: UnloadAutomationEventList
Return type: void
Description: Unload automation events list from file
Param[1]: list (type: AutomationEventList)
-Function 151: ExportAutomationEventList() (2 input parameters)
+Function 154: ExportAutomationEventList() (2 input parameters)
Name: ExportAutomationEventList
Return type: bool
Description: Export automation events list as text file
Param[1]: list (type: AutomationEventList)
Param[2]: fileName (type: const char *)
-Function 152: SetAutomationEventList() (1 input parameters)
+Function 155: SetAutomationEventList() (1 input parameters)
Name: SetAutomationEventList
Return type: void
Description: Set automation event list to record to
Param[1]: list (type: AutomationEventList *)
-Function 153: SetAutomationEventBaseFrame() (1 input parameters)
+Function 156: SetAutomationEventBaseFrame() (1 input parameters)
Name: SetAutomationEventBaseFrame
Return type: void
Description: Set automation event internal base frame to start recording
Param[1]: frame (type: int)
-Function 154: StartAutomationEventRecording() (0 input parameters)
+Function 157: StartAutomationEventRecording() (0 input parameters)
Name: StartAutomationEventRecording
Return type: void
Description: Start recording automation events (AutomationEventList must be set)
No input parameters
-Function 155: StopAutomationEventRecording() (0 input parameters)
+Function 158: StopAutomationEventRecording() (0 input parameters)
Name: StopAutomationEventRecording
Return type: void
Description: Stop recording automation events
No input parameters
-Function 156: PlayAutomationEvent() (1 input parameters)
+Function 159: PlayAutomationEvent() (1 input parameters)
Name: PlayAutomationEvent
Return type: void
Description: Play a recorded automation event
Param[1]: event (type: AutomationEvent)
-Function 157: IsKeyPressed() (1 input parameters)
+Function 160: IsKeyPressed() (1 input parameters)
Name: IsKeyPressed
Return type: bool
Description: Check if a key has been pressed once
Param[1]: key (type: int)
-Function 158: IsKeyPressedRepeat() (1 input parameters)
+Function 161: IsKeyPressedRepeat() (1 input parameters)
Name: IsKeyPressedRepeat
Return type: bool
Description: Check if a key has been pressed again (Only PLATFORM_DESKTOP)
Param[1]: key (type: int)
-Function 159: IsKeyDown() (1 input parameters)
+Function 162: IsKeyDown() (1 input parameters)
Name: IsKeyDown
Return type: bool
Description: Check if a key is being pressed
Param[1]: key (type: int)
-Function 160: IsKeyReleased() (1 input parameters)
+Function 163: IsKeyReleased() (1 input parameters)
Name: IsKeyReleased
Return type: bool
Description: Check if a key has been released once
Param[1]: key (type: int)
-Function 161: IsKeyUp() (1 input parameters)
+Function 164: IsKeyUp() (1 input parameters)
Name: IsKeyUp
Return type: bool
Description: Check if a key is NOT being pressed
Param[1]: key (type: int)
-Function 162: GetKeyPressed() (0 input parameters)
+Function 165: GetKeyPressed() (0 input parameters)
Name: GetKeyPressed
Return type: int
Description: Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
No input parameters
-Function 163: GetCharPressed() (0 input parameters)
+Function 166: GetCharPressed() (0 input parameters)
Name: GetCharPressed
Return type: int
Description: Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
No input parameters
-Function 164: SetExitKey() (1 input parameters)
+Function 167: SetExitKey() (1 input parameters)
Name: SetExitKey
Return type: void
Description: Set a custom key to exit program (default is ESC)
Param[1]: key (type: int)
-Function 165: IsGamepadAvailable() (1 input parameters)
+Function 168: IsGamepadAvailable() (1 input parameters)
Name: IsGamepadAvailable
Return type: bool
Description: Check if a gamepad is available
Param[1]: gamepad (type: int)
-Function 166: GetGamepadName() (1 input parameters)
+Function 169: GetGamepadName() (1 input parameters)
Name: GetGamepadName
Return type: const char *
Description: Get gamepad internal name id
Param[1]: gamepad (type: int)
-Function 167: IsGamepadButtonPressed() (2 input parameters)
+Function 170: IsGamepadButtonPressed() (2 input parameters)
Name: IsGamepadButtonPressed
Return type: bool
Description: Check if a gamepad button has been pressed once
Param[1]: gamepad (type: int)
Param[2]: button (type: int)
-Function 168: IsGamepadButtonDown() (2 input parameters)
+Function 171: IsGamepadButtonDown() (2 input parameters)
Name: IsGamepadButtonDown
Return type: bool
Description: Check if a gamepad button is being pressed
Param[1]: gamepad (type: int)
Param[2]: button (type: int)
-Function 169: IsGamepadButtonReleased() (2 input parameters)
+Function 172: IsGamepadButtonReleased() (2 input parameters)
Name: IsGamepadButtonReleased
Return type: bool
Description: Check if a gamepad button has been released once
Param[1]: gamepad (type: int)
Param[2]: button (type: int)
-Function 170: IsGamepadButtonUp() (2 input parameters)
+Function 173: IsGamepadButtonUp() (2 input parameters)
Name: IsGamepadButtonUp
Return type: bool
Description: Check if a gamepad button is NOT being pressed
Param[1]: gamepad (type: int)
Param[2]: button (type: int)
-Function 171: GetGamepadButtonPressed() (0 input parameters)
+Function 174: GetGamepadButtonPressed() (0 input parameters)
Name: GetGamepadButtonPressed
Return type: int
Description: Get the last gamepad button pressed
No input parameters
-Function 172: GetGamepadAxisCount() (1 input parameters)
+Function 175: GetGamepadAxisCount() (1 input parameters)
Name: GetGamepadAxisCount
Return type: int
Description: Get gamepad axis count for a gamepad
Param[1]: gamepad (type: int)
-Function 173: GetGamepadAxisMovement() (2 input parameters)
+Function 176: GetGamepadAxisMovement() (2 input parameters)
Name: GetGamepadAxisMovement
Return type: float
Description: Get axis movement value for a gamepad axis
Param[1]: gamepad (type: int)
Param[2]: axis (type: int)
-Function 174: SetGamepadMappings() (1 input parameters)
+Function 177: SetGamepadMappings() (1 input parameters)
Name: SetGamepadMappings
Return type: int
Description: Set internal gamepad mappings (SDL_GameControllerDB)
Param[1]: mappings (type: const char *)
-Function 175: SetGamepadVibration() (3 input parameters)
+Function 178: SetGamepadVibration() (3 input parameters)
Name: SetGamepadVibration
Return type: void
Description: Set gamepad vibration for both motors
Param[1]: gamepad (type: int)
Param[2]: leftMotor (type: float)
Param[3]: rightMotor (type: float)
-Function 176: IsMouseButtonPressed() (1 input parameters)
+Function 179: IsMouseButtonPressed() (1 input parameters)
Name: IsMouseButtonPressed
Return type: bool
Description: Check if a mouse button has been pressed once
Param[1]: button (type: int)
-Function 177: IsMouseButtonDown() (1 input parameters)
+Function 180: IsMouseButtonDown() (1 input parameters)
Name: IsMouseButtonDown
Return type: bool
Description: Check if a mouse button is being pressed
Param[1]: button (type: int)
-Function 178: IsMouseButtonReleased() (1 input parameters)
+Function 181: IsMouseButtonReleased() (1 input parameters)
Name: IsMouseButtonReleased
Return type: bool
Description: Check if a mouse button has been released once
Param[1]: button (type: int)
-Function 179: IsMouseButtonUp() (1 input parameters)
+Function 182: IsMouseButtonUp() (1 input parameters)
Name: IsMouseButtonUp
Return type: bool
Description: Check if a mouse button is NOT being pressed
Param[1]: button (type: int)
-Function 180: GetMouseX() (0 input parameters)
+Function 183: GetMouseX() (0 input parameters)
Name: GetMouseX
Return type: int
Description: Get mouse position X
No input parameters
-Function 181: GetMouseY() (0 input parameters)
+Function 184: GetMouseY() (0 input parameters)
Name: GetMouseY
Return type: int
Description: Get mouse position Y
No input parameters
-Function 182: GetMousePosition() (0 input parameters)
+Function 185: GetMousePosition() (0 input parameters)
Name: GetMousePosition
Return type: Vector2
Description: Get mouse position XY
No input parameters
-Function 183: GetMouseDelta() (0 input parameters)
+Function 186: GetMouseDelta() (0 input parameters)
Name: GetMouseDelta
Return type: Vector2
Description: Get mouse delta between frames
No input parameters
-Function 184: SetMousePosition() (2 input parameters)
+Function 187: SetMousePosition() (2 input parameters)
Name: SetMousePosition
Return type: void
Description: Set mouse position XY
Param[1]: x (type: int)
Param[2]: y (type: int)
-Function 185: SetMouseOffset() (2 input parameters)
+Function 188: SetMouseOffset() (2 input parameters)
Name: SetMouseOffset
Return type: void
Description: Set mouse offset
Param[1]: offsetX (type: int)
Param[2]: offsetY (type: int)
-Function 186: SetMouseScale() (2 input parameters)
+Function 189: SetMouseScale() (2 input parameters)
Name: SetMouseScale
Return type: void
Description: Set mouse scaling
Param[1]: scaleX (type: float)
Param[2]: scaleY (type: float)
-Function 187: GetMouseWheelMove() (0 input parameters)
+Function 190: GetMouseWheelMove() (0 input parameters)
Name: GetMouseWheelMove
Return type: float
Description: Get mouse wheel movement for X or Y, whichever is larger
No input parameters
-Function 188: GetMouseWheelMoveV() (0 input parameters)
+Function 191: GetMouseWheelMoveV() (0 input parameters)
Name: GetMouseWheelMoveV
Return type: Vector2
Description: Get mouse wheel movement for both X and Y
No input parameters
-Function 189: SetMouseCursor() (1 input parameters)
+Function 192: SetMouseCursor() (1 input parameters)
Name: SetMouseCursor
Return type: void
Description: Set mouse cursor
Param[1]: cursor (type: int)
-Function 190: GetTouchX() (0 input parameters)
+Function 193: GetTouchX() (0 input parameters)
Name: GetTouchX
Return type: int
Description: Get touch position X for touch point 0 (relative to screen size)
No input parameters
-Function 191: GetTouchY() (0 input parameters)
+Function 194: GetTouchY() (0 input parameters)
Name: GetTouchY
Return type: int
Description: Get touch position Y for touch point 0 (relative to screen size)
No input parameters
-Function 192: GetTouchPosition() (1 input parameters)
+Function 195: GetTouchPosition() (1 input parameters)
Name: GetTouchPosition
Return type: Vector2
Description: Get touch position XY for a touch point index (relative to screen size)
Param[1]: index (type: int)
-Function 193: GetTouchPointId() (1 input parameters)
+Function 196: GetTouchPointId() (1 input parameters)
Name: GetTouchPointId
Return type: int
Description: Get touch point identifier for given index
Param[1]: index (type: int)
-Function 194: GetTouchPointCount() (0 input parameters)
+Function 197: GetTouchPointCount() (0 input parameters)
Name: GetTouchPointCount
Return type: int
Description: Get number of touch points
No input parameters
-Function 195: SetGesturesEnabled() (1 input parameters)
+Function 198: SetGesturesEnabled() (1 input parameters)
Name: SetGesturesEnabled
Return type: void
Description: Enable a set of gestures using flags
Param[1]: flags (type: unsigned int)
-Function 196: IsGestureDetected() (1 input parameters)
+Function 199: IsGestureDetected() (1 input parameters)
Name: IsGestureDetected
Return type: bool
Description: Check if a gesture have been detected
Param[1]: gesture (type: unsigned int)
-Function 197: GetGestureDetected() (0 input parameters)
+Function 200: GetGestureDetected() (0 input parameters)
Name: GetGestureDetected
Return type: int
Description: Get latest detected gesture
No input parameters
-Function 198: GetGestureHoldDuration() (0 input parameters)
+Function 201: GetGestureHoldDuration() (0 input parameters)
Name: GetGestureHoldDuration
Return type: float
- Description: Get gesture hold time in milliseconds
+ Description: Get gesture hold time in seconds
No input parameters
-Function 199: GetGestureDragVector() (0 input parameters)
+Function 202: GetGestureDragVector() (0 input parameters)
Name: GetGestureDragVector
Return type: Vector2
Description: Get gesture drag vector
No input parameters
-Function 200: GetGestureDragAngle() (0 input parameters)
+Function 203: GetGestureDragAngle() (0 input parameters)
Name: GetGestureDragAngle
Return type: float
Description: Get gesture drag angle
No input parameters
-Function 201: GetGesturePinchVector() (0 input parameters)
+Function 204: GetGesturePinchVector() (0 input parameters)
Name: GetGesturePinchVector
Return type: Vector2
Description: Get gesture pinch delta
No input parameters
-Function 202: GetGesturePinchAngle() (0 input parameters)
+Function 205: GetGesturePinchAngle() (0 input parameters)
Name: GetGesturePinchAngle
Return type: float
Description: Get gesture pinch angle
No input parameters
-Function 203: UpdateCamera() (2 input parameters)
+Function 206: UpdateCamera() (2 input parameters)
Name: UpdateCamera
Return type: void
Description: Update camera position for selected mode
Param[1]: camera (type: Camera *)
Param[2]: mode (type: int)
-Function 204: UpdateCameraPro() (4 input parameters)
+Function 207: UpdateCameraPro() (4 input parameters)
Name: UpdateCameraPro
Return type: void
Description: Update camera movement/rotation
@@ -2083,36 +2101,36 @@ Function 204: UpdateCameraPro() (4 input parameters)
Param[2]: movement (type: Vector3)
Param[3]: rotation (type: Vector3)
Param[4]: zoom (type: float)
-Function 205: SetShapesTexture() (2 input parameters)
+Function 208: SetShapesTexture() (2 input parameters)
Name: SetShapesTexture
Return type: void
Description: Set texture and rectangle to be used on shapes drawing
Param[1]: texture (type: Texture2D)
Param[2]: source (type: Rectangle)
-Function 206: GetShapesTexture() (0 input parameters)
+Function 209: GetShapesTexture() (0 input parameters)
Name: GetShapesTexture
Return type: Texture2D
Description: Get texture that is used for shapes drawing
No input parameters
-Function 207: GetShapesTextureRectangle() (0 input parameters)
+Function 210: GetShapesTextureRectangle() (0 input parameters)
Name: GetShapesTextureRectangle
Return type: Rectangle
Description: Get texture source rectangle that is used for shapes drawing
No input parameters
-Function 208: DrawPixel() (3 input parameters)
+Function 211: DrawPixel() (3 input parameters)
Name: DrawPixel
Return type: void
Description: Draw a pixel using geometry [Can be slow, use with care]
Param[1]: posX (type: int)
Param[2]: posY (type: int)
Param[3]: color (type: Color)
-Function 209: DrawPixelV() (2 input parameters)
+Function 212: DrawPixelV() (2 input parameters)
Name: DrawPixelV
Return type: void
Description: Draw a pixel using geometry (Vector version) [Can be slow, use with care]
Param[1]: position (type: Vector2)
Param[2]: color (type: Color)
-Function 210: DrawLine() (5 input parameters)
+Function 213: DrawLine() (5 input parameters)
Name: DrawLine
Return type: void
Description: Draw a line
@@ -2121,14 +2139,14 @@ Function 210: DrawLine() (5 input parameters)
Param[3]: endPosX (type: int)
Param[4]: endPosY (type: int)
Param[5]: color (type: Color)
-Function 211: DrawLineV() (3 input parameters)
+Function 214: DrawLineV() (3 input parameters)
Name: DrawLineV
Return type: void
Description: Draw a line (using gl lines)
Param[1]: startPos (type: Vector2)
Param[2]: endPos (type: Vector2)
Param[3]: color (type: Color)
-Function 212: DrawLineEx() (4 input parameters)
+Function 215: DrawLineEx() (4 input parameters)
Name: DrawLineEx
Return type: void
Description: Draw a line (using triangles/quads)
@@ -2136,14 +2154,14 @@ Function 212: DrawLineEx() (4 input parameters)
Param[2]: endPos (type: Vector2)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 213: DrawLineStrip() (3 input parameters)
+Function 216: DrawLineStrip() (3 input parameters)
Name: DrawLineStrip
Return type: void
Description: Draw lines sequence (using gl lines)
Param[1]: points (type: const Vector2 *)
Param[2]: pointCount (type: int)
Param[3]: color (type: Color)
-Function 214: DrawLineBezier() (4 input parameters)
+Function 217: DrawLineBezier() (4 input parameters)
Name: DrawLineBezier
Return type: void
Description: Draw line segment cubic-bezier in-out interpolation
@@ -2151,7 +2169,7 @@ Function 214: DrawLineBezier() (4 input parameters)
Param[2]: endPos (type: Vector2)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 215: DrawCircle() (4 input parameters)
+Function 218: DrawCircle() (4 input parameters)
Name: DrawCircle
Return type: void
Description: Draw a color-filled circle
@@ -2159,7 +2177,7 @@ Function 215: DrawCircle() (4 input parameters)
Param[2]: centerY (type: int)
Param[3]: radius (type: float)
Param[4]: color (type: Color)
-Function 216: DrawCircleSector() (6 input parameters)
+Function 219: DrawCircleSector() (6 input parameters)
Name: DrawCircleSector
Return type: void
Description: Draw a piece of a circle
@@ -2169,7 +2187,7 @@ Function 216: DrawCircleSector() (6 input parameters)
Param[4]: endAngle (type: float)
Param[5]: segments (type: int)
Param[6]: color (type: Color)
-Function 217: DrawCircleSectorLines() (6 input parameters)
+Function 220: DrawCircleSectorLines() (6 input parameters)
Name: DrawCircleSectorLines
Return type: void
Description: Draw circle sector outline
@@ -2179,7 +2197,7 @@ Function 217: DrawCircleSectorLines() (6 input parameters)
Param[4]: endAngle (type: float)
Param[5]: segments (type: int)
Param[6]: color (type: Color)
-Function 218: DrawCircleGradient() (5 input parameters)
+Function 221: DrawCircleGradient() (5 input parameters)
Name: DrawCircleGradient
Return type: void
Description: Draw a gradient-filled circle
@@ -2188,14 +2206,14 @@ Function 218: DrawCircleGradient() (5 input parameters)
Param[3]: radius (type: float)
Param[4]: inner (type: Color)
Param[5]: outer (type: Color)
-Function 219: DrawCircleV() (3 input parameters)
+Function 222: DrawCircleV() (3 input parameters)
Name: DrawCircleV
Return type: void
Description: Draw a color-filled circle (Vector version)
Param[1]: center (type: Vector2)
Param[2]: radius (type: float)
Param[3]: color (type: Color)
-Function 220: DrawCircleLines() (4 input parameters)
+Function 223: DrawCircleLines() (4 input parameters)
Name: DrawCircleLines
Return type: void
Description: Draw circle outline
@@ -2203,14 +2221,14 @@ Function 220: DrawCircleLines() (4 input parameters)
Param[2]: centerY (type: int)
Param[3]: radius (type: float)
Param[4]: color (type: Color)
-Function 221: DrawCircleLinesV() (3 input parameters)
+Function 224: DrawCircleLinesV() (3 input parameters)
Name: DrawCircleLinesV
Return type: void
Description: Draw circle outline (Vector version)
Param[1]: center (type: Vector2)
Param[2]: radius (type: float)
Param[3]: color (type: Color)
-Function 222: DrawEllipse() (5 input parameters)
+Function 225: DrawEllipse() (5 input parameters)
Name: DrawEllipse
Return type: void
Description: Draw ellipse
@@ -2219,7 +2237,7 @@ Function 222: DrawEllipse() (5 input parameters)
Param[3]: radiusH (type: float)
Param[4]: radiusV (type: float)
Param[5]: color (type: Color)
-Function 223: DrawEllipseLines() (5 input parameters)
+Function 226: DrawEllipseLines() (5 input parameters)
Name: DrawEllipseLines
Return type: void
Description: Draw ellipse outline
@@ -2228,7 +2246,7 @@ Function 223: DrawEllipseLines() (5 input parameters)
Param[3]: radiusH (type: float)
Param[4]: radiusV (type: float)
Param[5]: color (type: Color)
-Function 224: DrawRing() (7 input parameters)
+Function 227: DrawRing() (7 input parameters)
Name: DrawRing
Return type: void
Description: Draw ring
@@ -2239,7 +2257,7 @@ Function 224: DrawRing() (7 input parameters)
Param[5]: endAngle (type: float)
Param[6]: segments (type: int)
Param[7]: color (type: Color)
-Function 225: DrawRingLines() (7 input parameters)
+Function 228: DrawRingLines() (7 input parameters)
Name: DrawRingLines
Return type: void
Description: Draw ring outline
@@ -2250,7 +2268,7 @@ Function 225: DrawRingLines() (7 input parameters)
Param[5]: endAngle (type: float)
Param[6]: segments (type: int)
Param[7]: color (type: Color)
-Function 226: DrawRectangle() (5 input parameters)
+Function 229: DrawRectangle() (5 input parameters)
Name: DrawRectangle
Return type: void
Description: Draw a color-filled rectangle
@@ -2259,20 +2277,20 @@ Function 226: DrawRectangle() (5 input parameters)
Param[3]: width (type: int)
Param[4]: height (type: int)
Param[5]: color (type: Color)
-Function 227: DrawRectangleV() (3 input parameters)
+Function 230: DrawRectangleV() (3 input parameters)
Name: DrawRectangleV
Return type: void
Description: Draw a color-filled rectangle (Vector version)
Param[1]: position (type: Vector2)
Param[2]: size (type: Vector2)
Param[3]: color (type: Color)
-Function 228: DrawRectangleRec() (2 input parameters)
+Function 231: DrawRectangleRec() (2 input parameters)
Name: DrawRectangleRec
Return type: void
Description: Draw a color-filled rectangle
Param[1]: rec (type: Rectangle)
Param[2]: color (type: Color)
-Function 229: DrawRectanglePro() (4 input parameters)
+Function 232: DrawRectanglePro() (4 input parameters)
Name: DrawRectanglePro
Return type: void
Description: Draw a color-filled rectangle with pro parameters
@@ -2280,7 +2298,7 @@ Function 229: DrawRectanglePro() (4 input parameters)
Param[2]: origin (type: Vector2)
Param[3]: rotation (type: float)
Param[4]: color (type: Color)
-Function 230: DrawRectangleGradientV() (6 input parameters)
+Function 233: DrawRectangleGradientV() (6 input parameters)
Name: DrawRectangleGradientV
Return type: void
Description: Draw a vertical-gradient-filled rectangle
@@ -2290,7 +2308,7 @@ Function 230: DrawRectangleGradientV() (6 input parameters)
Param[4]: height (type: int)
Param[5]: top (type: Color)
Param[6]: bottom (type: Color)
-Function 231: DrawRectangleGradientH() (6 input parameters)
+Function 234: DrawRectangleGradientH() (6 input parameters)
Name: DrawRectangleGradientH
Return type: void
Description: Draw a horizontal-gradient-filled rectangle
@@ -2300,7 +2318,7 @@ Function 231: DrawRectangleGradientH() (6 input parameters)
Param[4]: height (type: int)
Param[5]: left (type: Color)
Param[6]: right (type: Color)
-Function 232: DrawRectangleGradientEx() (5 input parameters)
+Function 235: DrawRectangleGradientEx() (5 input parameters)
Name: DrawRectangleGradientEx
Return type: void
Description: Draw a gradient-filled rectangle with custom vertex colors
@@ -2309,7 +2327,7 @@ Function 232: DrawRectangleGradientEx() (5 input parameters)
Param[3]: bottomLeft (type: Color)
Param[4]: topRight (type: Color)
Param[5]: bottomRight (type: Color)
-Function 233: DrawRectangleLines() (5 input parameters)
+Function 236: DrawRectangleLines() (5 input parameters)
Name: DrawRectangleLines
Return type: void
Description: Draw rectangle outline
@@ -2318,14 +2336,14 @@ Function 233: DrawRectangleLines() (5 input parameters)
Param[3]: width (type: int)
Param[4]: height (type: int)
Param[5]: color (type: Color)
-Function 234: DrawRectangleLinesEx() (3 input parameters)
+Function 237: DrawRectangleLinesEx() (3 input parameters)
Name: DrawRectangleLinesEx
Return type: void
Description: Draw rectangle outline with extended parameters
Param[1]: rec (type: Rectangle)
Param[2]: lineThick (type: float)
Param[3]: color (type: Color)
-Function 235: DrawRectangleRounded() (4 input parameters)
+Function 238: DrawRectangleRounded() (4 input parameters)
Name: DrawRectangleRounded
Return type: void
Description: Draw rectangle with rounded edges
@@ -2333,7 +2351,7 @@ Function 235: DrawRectangleRounded() (4 input parameters)
Param[2]: roundness (type: float)
Param[3]: segments (type: int)
Param[4]: color (type: Color)
-Function 236: DrawRectangleRoundedLines() (4 input parameters)
+Function 239: DrawRectangleRoundedLines() (4 input parameters)
Name: DrawRectangleRoundedLines
Return type: void
Description: Draw rectangle lines with rounded edges
@@ -2341,7 +2359,7 @@ Function 236: DrawRectangleRoundedLines() (4 input parameters)
Param[2]: roundness (type: float)
Param[3]: segments (type: int)
Param[4]: color (type: Color)
-Function 237: DrawRectangleRoundedLinesEx() (5 input parameters)
+Function 240: DrawRectangleRoundedLinesEx() (5 input parameters)
Name: DrawRectangleRoundedLinesEx
Return type: void
Description: Draw rectangle with rounded edges outline
@@ -2350,7 +2368,7 @@ Function 237: DrawRectangleRoundedLinesEx() (5 input parameters)
Param[3]: segments (type: int)
Param[4]: lineThick (type: float)
Param[5]: color (type: Color)
-Function 238: DrawTriangle() (4 input parameters)
+Function 241: DrawTriangle() (4 input parameters)
Name: DrawTriangle
Return type: void
Description: Draw a color-filled triangle (vertex in counter-clockwise order!)
@@ -2358,7 +2376,7 @@ Function 238: DrawTriangle() (4 input parameters)
Param[2]: v2 (type: Vector2)
Param[3]: v3 (type: Vector2)
Param[4]: color (type: Color)
-Function 239: DrawTriangleLines() (4 input parameters)
+Function 242: DrawTriangleLines() (4 input parameters)
Name: DrawTriangleLines
Return type: void
Description: Draw triangle outline (vertex in counter-clockwise order!)
@@ -2366,21 +2384,21 @@ Function 239: DrawTriangleLines() (4 input parameters)
Param[2]: v2 (type: Vector2)
Param[3]: v3 (type: Vector2)
Param[4]: color (type: Color)
-Function 240: DrawTriangleFan() (3 input parameters)
+Function 243: DrawTriangleFan() (3 input parameters)
Name: DrawTriangleFan
Return type: void
Description: Draw a triangle fan defined by points (first vertex is the center)
Param[1]: points (type: const Vector2 *)
Param[2]: pointCount (type: int)
Param[3]: color (type: Color)
-Function 241: DrawTriangleStrip() (3 input parameters)
+Function 244: DrawTriangleStrip() (3 input parameters)
Name: DrawTriangleStrip
Return type: void
Description: Draw a triangle strip defined by points
Param[1]: points (type: const Vector2 *)
Param[2]: pointCount (type: int)
Param[3]: color (type: Color)
-Function 242: DrawPoly() (5 input parameters)
+Function 245: DrawPoly() (5 input parameters)
Name: DrawPoly
Return type: void
Description: Draw a regular polygon (Vector version)
@@ -2389,7 +2407,7 @@ Function 242: DrawPoly() (5 input parameters)
Param[3]: radius (type: float)
Param[4]: rotation (type: float)
Param[5]: color (type: Color)
-Function 243: DrawPolyLines() (5 input parameters)
+Function 246: DrawPolyLines() (5 input parameters)
Name: DrawPolyLines
Return type: void
Description: Draw a polygon outline of n sides
@@ -2398,7 +2416,7 @@ Function 243: DrawPolyLines() (5 input parameters)
Param[3]: radius (type: float)
Param[4]: rotation (type: float)
Param[5]: color (type: Color)
-Function 244: DrawPolyLinesEx() (6 input parameters)
+Function 247: DrawPolyLinesEx() (6 input parameters)
Name: DrawPolyLinesEx
Return type: void
Description: Draw a polygon outline of n sides with extended parameters
@@ -2408,7 +2426,7 @@ Function 244: DrawPolyLinesEx() (6 input parameters)
Param[4]: rotation (type: float)
Param[5]: lineThick (type: float)
Param[6]: color (type: Color)
-Function 245: DrawSplineLinear() (4 input parameters)
+Function 248: DrawSplineLinear() (4 input parameters)
Name: DrawSplineLinear
Return type: void
Description: Draw spline: Linear, minimum 2 points
@@ -2416,7 +2434,7 @@ Function 245: DrawSplineLinear() (4 input parameters)
Param[2]: pointCount (type: int)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 246: DrawSplineBasis() (4 input parameters)
+Function 249: DrawSplineBasis() (4 input parameters)
Name: DrawSplineBasis
Return type: void
Description: Draw spline: B-Spline, minimum 4 points
@@ -2424,7 +2442,7 @@ Function 246: DrawSplineBasis() (4 input parameters)
Param[2]: pointCount (type: int)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 247: DrawSplineCatmullRom() (4 input parameters)
+Function 250: DrawSplineCatmullRom() (4 input parameters)
Name: DrawSplineCatmullRom
Return type: void
Description: Draw spline: Catmull-Rom, minimum 4 points
@@ -2432,7 +2450,7 @@ Function 247: DrawSplineCatmullRom() (4 input parameters)
Param[2]: pointCount (type: int)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 248: DrawSplineBezierQuadratic() (4 input parameters)
+Function 251: DrawSplineBezierQuadratic() (4 input parameters)
Name: DrawSplineBezierQuadratic
Return type: void
Description: Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
@@ -2440,7 +2458,7 @@ Function 248: DrawSplineBezierQuadratic() (4 input parameters)
Param[2]: pointCount (type: int)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 249: DrawSplineBezierCubic() (4 input parameters)
+Function 252: DrawSplineBezierCubic() (4 input parameters)
Name: DrawSplineBezierCubic
Return type: void
Description: Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
@@ -2448,7 +2466,7 @@ Function 249: DrawSplineBezierCubic() (4 input parameters)
Param[2]: pointCount (type: int)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 250: DrawSplineSegmentLinear() (4 input parameters)
+Function 253: DrawSplineSegmentLinear() (4 input parameters)
Name: DrawSplineSegmentLinear
Return type: void
Description: Draw spline segment: Linear, 2 points
@@ -2456,7 +2474,7 @@ Function 250: DrawSplineSegmentLinear() (4 input parameters)
Param[2]: p2 (type: Vector2)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 251: DrawSplineSegmentBasis() (6 input parameters)
+Function 254: DrawSplineSegmentBasis() (6 input parameters)
Name: DrawSplineSegmentBasis
Return type: void
Description: Draw spline segment: B-Spline, 4 points
@@ -2466,7 +2484,7 @@ Function 251: DrawSplineSegmentBasis() (6 input parameters)
Param[4]: p4 (type: Vector2)
Param[5]: thick (type: float)
Param[6]: color (type: Color)
-Function 252: DrawSplineSegmentCatmullRom() (6 input parameters)
+Function 255: DrawSplineSegmentCatmullRom() (6 input parameters)
Name: DrawSplineSegmentCatmullRom
Return type: void
Description: Draw spline segment: Catmull-Rom, 4 points
@@ -2476,7 +2494,7 @@ Function 252: DrawSplineSegmentCatmullRom() (6 input parameters)
Param[4]: p4 (type: Vector2)
Param[5]: thick (type: float)
Param[6]: color (type: Color)
-Function 253: DrawSplineSegmentBezierQuadratic() (5 input parameters)
+Function 256: DrawSplineSegmentBezierQuadratic() (5 input parameters)
Name: DrawSplineSegmentBezierQuadratic
Return type: void
Description: Draw spline segment: Quadratic Bezier, 2 points, 1 control point
@@ -2485,7 +2503,7 @@ Function 253: DrawSplineSegmentBezierQuadratic() (5 input parameters)
Param[3]: p3 (type: Vector2)
Param[4]: thick (type: float)
Param[5]: color (type: Color)
-Function 254: DrawSplineSegmentBezierCubic() (6 input parameters)
+Function 257: DrawSplineSegmentBezierCubic() (6 input parameters)
Name: DrawSplineSegmentBezierCubic
Return type: void
Description: Draw spline segment: Cubic Bezier, 2 points, 2 control points
@@ -2495,14 +2513,14 @@ Function 254: DrawSplineSegmentBezierCubic() (6 input parameters)
Param[4]: p4 (type: Vector2)
Param[5]: thick (type: float)
Param[6]: color (type: Color)
-Function 255: GetSplinePointLinear() (3 input parameters)
+Function 258: GetSplinePointLinear() (3 input parameters)
Name: GetSplinePointLinear
Return type: Vector2
Description: Get (evaluate) spline point: Linear
Param[1]: startPos (type: Vector2)
Param[2]: endPos (type: Vector2)
Param[3]: t (type: float)
-Function 256: GetSplinePointBasis() (5 input parameters)
+Function 259: GetSplinePointBasis() (5 input parameters)
Name: GetSplinePointBasis
Return type: Vector2
Description: Get (evaluate) spline point: B-Spline
@@ -2511,7 +2529,7 @@ Function 256: GetSplinePointBasis() (5 input parameters)
Param[3]: p3 (type: Vector2)
Param[4]: p4 (type: Vector2)
Param[5]: t (type: float)
-Function 257: GetSplinePointCatmullRom() (5 input parameters)
+Function 260: GetSplinePointCatmullRom() (5 input parameters)
Name: GetSplinePointCatmullRom
Return type: Vector2
Description: Get (evaluate) spline point: Catmull-Rom
@@ -2520,7 +2538,7 @@ Function 257: GetSplinePointCatmullRom() (5 input parameters)
Param[3]: p3 (type: Vector2)
Param[4]: p4 (type: Vector2)
Param[5]: t (type: float)
-Function 258: GetSplinePointBezierQuad() (4 input parameters)
+Function 261: GetSplinePointBezierQuad() (4 input parameters)
Name: GetSplinePointBezierQuad
Return type: Vector2
Description: Get (evaluate) spline point: Quadratic Bezier
@@ -2528,7 +2546,7 @@ Function 258: GetSplinePointBezierQuad() (4 input parameters)
Param[2]: c2 (type: Vector2)
Param[3]: p3 (type: Vector2)
Param[4]: t (type: float)
-Function 259: GetSplinePointBezierCubic() (5 input parameters)
+Function 262: GetSplinePointBezierCubic() (5 input parameters)
Name: GetSplinePointBezierCubic
Return type: Vector2
Description: Get (evaluate) spline point: Cubic Bezier
@@ -2537,13 +2555,13 @@ Function 259: GetSplinePointBezierCubic() (5 input parameters)
Param[3]: c3 (type: Vector2)
Param[4]: p4 (type: Vector2)
Param[5]: t (type: float)
-Function 260: CheckCollisionRecs() (2 input parameters)
+Function 263: CheckCollisionRecs() (2 input parameters)
Name: CheckCollisionRecs
Return type: bool
Description: Check collision between two rectangles
Param[1]: rec1 (type: Rectangle)
Param[2]: rec2 (type: Rectangle)
-Function 261: CheckCollisionCircles() (4 input parameters)
+Function 264: CheckCollisionCircles() (4 input parameters)
Name: CheckCollisionCircles
Return type: bool
Description: Check collision between two circles
@@ -2551,27 +2569,27 @@ Function 261: CheckCollisionCircles() (4 input parameters)
Param[2]: radius1 (type: float)
Param[3]: center2 (type: Vector2)
Param[4]: radius2 (type: float)
-Function 262: CheckCollisionCircleRec() (3 input parameters)
+Function 265: CheckCollisionCircleRec() (3 input parameters)
Name: CheckCollisionCircleRec
Return type: bool
Description: Check collision between circle and rectangle
Param[1]: center (type: Vector2)
Param[2]: radius (type: float)
Param[3]: rec (type: Rectangle)
-Function 263: CheckCollisionPointRec() (2 input parameters)
+Function 266: CheckCollisionPointRec() (2 input parameters)
Name: CheckCollisionPointRec
Return type: bool
Description: Check if point is inside rectangle
Param[1]: point (type: Vector2)
Param[2]: rec (type: Rectangle)
-Function 264: CheckCollisionPointCircle() (3 input parameters)
+Function 267: CheckCollisionPointCircle() (3 input parameters)
Name: CheckCollisionPointCircle
Return type: bool
Description: Check if point is inside circle
Param[1]: point (type: Vector2)
Param[2]: center (type: Vector2)
Param[3]: radius (type: float)
-Function 265: CheckCollisionPointTriangle() (4 input parameters)
+Function 268: CheckCollisionPointTriangle() (4 input parameters)
Name: CheckCollisionPointTriangle
Return type: bool
Description: Check if point is inside a triangle
@@ -2579,14 +2597,14 @@ Function 265: CheckCollisionPointTriangle() (4 input parameters)
Param[2]: p1 (type: Vector2)
Param[3]: p2 (type: Vector2)
Param[4]: p3 (type: Vector2)
-Function 266: CheckCollisionPointPoly() (3 input parameters)
+Function 269: CheckCollisionPointPoly() (3 input parameters)
Name: CheckCollisionPointPoly
Return type: bool
Description: Check if point is within a polygon described by array of vertices
Param[1]: point (type: Vector2)
Param[2]: points (type: const Vector2 *)
Param[3]: pointCount (type: int)
-Function 267: CheckCollisionLines() (5 input parameters)
+Function 270: CheckCollisionLines() (5 input parameters)
Name: CheckCollisionLines
Return type: bool
Description: Check the collision between two lines defined by two points each, returns collision point by reference
@@ -2595,7 +2613,7 @@ Function 267: CheckCollisionLines() (5 input parameters)
Param[3]: startPos2 (type: Vector2)
Param[4]: endPos2 (type: Vector2)
Param[5]: collisionPoint (type: Vector2 *)
-Function 268: CheckCollisionPointLine() (4 input parameters)
+Function 271: CheckCollisionPointLine() (4 input parameters)
Name: CheckCollisionPointLine
Return type: bool
Description: Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
@@ -2603,7 +2621,7 @@ Function 268: CheckCollisionPointLine() (4 input parameters)
Param[2]: p1 (type: Vector2)
Param[3]: p2 (type: Vector2)
Param[4]: threshold (type: int)
-Function 269: CheckCollisionCircleLine() (4 input parameters)
+Function 272: CheckCollisionCircleLine() (4 input parameters)
Name: CheckCollisionCircleLine
Return type: bool
Description: Check if circle collides with a line created betweeen two points [p1] and [p2]
@@ -2611,18 +2629,18 @@ Function 269: CheckCollisionCircleLine() (4 input parameters)
Param[2]: radius (type: float)
Param[3]: p1 (type: Vector2)
Param[4]: p2 (type: Vector2)
-Function 270: GetCollisionRec() (2 input parameters)
+Function 273: GetCollisionRec() (2 input parameters)
Name: GetCollisionRec
Return type: Rectangle
Description: Get collision rectangle for two rectangles collision
Param[1]: rec1 (type: Rectangle)
Param[2]: rec2 (type: Rectangle)
-Function 271: LoadImage() (1 input parameters)
+Function 274: LoadImage() (1 input parameters)
Name: LoadImage
Return type: Image
Description: Load image from file into CPU memory (RAM)
Param[1]: fileName (type: const char *)
-Function 272: LoadImageRaw() (5 input parameters)
+Function 275: LoadImageRaw() (5 input parameters)
Name: LoadImageRaw
Return type: Image
Description: Load image from RAW file data
@@ -2631,20 +2649,13 @@ Function 272: LoadImageRaw() (5 input parameters)
Param[3]: height (type: int)
Param[4]: format (type: int)
Param[5]: headerSize (type: int)
-Function 273: LoadImageSvg() (3 input parameters)
- Name: LoadImageSvg
- Return type: Image
- Description: Load image from SVG file data or string with specified size
- Param[1]: fileNameOrString (type: const char *)
- Param[2]: width (type: int)
- Param[3]: height (type: int)
-Function 274: LoadImageAnim() (2 input parameters)
+Function 276: LoadImageAnim() (2 input parameters)
Name: LoadImageAnim
Return type: Image
Description: Load image sequence from file (frames appended to image.data)
Param[1]: fileName (type: const char *)
Param[2]: frames (type: int *)
-Function 275: LoadImageAnimFromMemory() (4 input parameters)
+Function 277: LoadImageAnimFromMemory() (4 input parameters)
Name: LoadImageAnimFromMemory
Return type: Image
Description: Load image sequence from memory buffer
@@ -2652,60 +2663,60 @@ Function 275: LoadImageAnimFromMemory() (4 input parameters)
Param[2]: fileData (type: const unsigned char *)
Param[3]: dataSize (type: int)
Param[4]: frames (type: int *)
-Function 276: LoadImageFromMemory() (3 input parameters)
+Function 278: LoadImageFromMemory() (3 input parameters)
Name: LoadImageFromMemory
Return type: Image
Description: Load image from memory buffer, fileType refers to extension: i.e. '.png'
Param[1]: fileType (type: const char *)
Param[2]: fileData (type: const unsigned char *)
Param[3]: dataSize (type: int)
-Function 277: LoadImageFromTexture() (1 input parameters)
+Function 279: LoadImageFromTexture() (1 input parameters)
Name: LoadImageFromTexture
Return type: Image
Description: Load image from GPU texture data
Param[1]: texture (type: Texture2D)
-Function 278: LoadImageFromScreen() (0 input parameters)
+Function 280: LoadImageFromScreen() (0 input parameters)
Name: LoadImageFromScreen
Return type: Image
Description: Load image from screen buffer and (screenshot)
No input parameters
-Function 279: IsImageReady() (1 input parameters)
- Name: IsImageReady
+Function 281: IsImageValid() (1 input parameters)
+ Name: IsImageValid
Return type: bool
- Description: Check if an image is ready
+ Description: Check if an image is valid (data and parameters)
Param[1]: image (type: Image)
-Function 280: UnloadImage() (1 input parameters)
+Function 282: UnloadImage() (1 input parameters)
Name: UnloadImage
Return type: void
Description: Unload image from CPU memory (RAM)
Param[1]: image (type: Image)
-Function 281: ExportImage() (2 input parameters)
+Function 283: ExportImage() (2 input parameters)
Name: ExportImage
Return type: bool
Description: Export image data to file, returns true on success
Param[1]: image (type: Image)
Param[2]: fileName (type: const char *)
-Function 282: ExportImageToMemory() (3 input parameters)
+Function 284: ExportImageToMemory() (3 input parameters)
Name: ExportImageToMemory
Return type: unsigned char *
Description: Export image to memory buffer
Param[1]: image (type: Image)
Param[2]: fileType (type: const char *)
Param[3]: fileSize (type: int *)
-Function 283: ExportImageAsCode() (2 input parameters)
+Function 285: ExportImageAsCode() (2 input parameters)
Name: ExportImageAsCode
Return type: bool
Description: Export image as code file defining an array of bytes, returns true on success
Param[1]: image (type: Image)
Param[2]: fileName (type: const char *)
-Function 284: GenImageColor() (3 input parameters)
+Function 286: GenImageColor() (3 input parameters)
Name: GenImageColor
Return type: Image
Description: Generate image: plain color
Param[1]: width (type: int)
Param[2]: height (type: int)
Param[3]: color (type: Color)
-Function 285: GenImageGradientLinear() (5 input parameters)
+Function 287: GenImageGradientLinear() (5 input parameters)
Name: GenImageGradientLinear
Return type: Image
Description: Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient
@@ -2714,7 +2725,7 @@ Function 285: GenImageGradientLinear() (5 input parameters)
Param[3]: direction (type: int)
Param[4]: start (type: Color)
Param[5]: end (type: Color)
-Function 286: GenImageGradientRadial() (5 input parameters)
+Function 288: GenImageGradientRadial() (5 input parameters)
Name: GenImageGradientRadial
Return type: Image
Description: Generate image: radial gradient
@@ -2723,7 +2734,7 @@ Function 286: GenImageGradientRadial() (5 input parameters)
Param[3]: density (type: float)
Param[4]: inner (type: Color)
Param[5]: outer (type: Color)
-Function 287: GenImageGradientSquare() (5 input parameters)
+Function 289: GenImageGradientSquare() (5 input parameters)
Name: GenImageGradientSquare
Return type: Image
Description: Generate image: square gradient
@@ -2732,7 +2743,7 @@ Function 287: GenImageGradientSquare() (5 input parameters)
Param[3]: density (type: float)
Param[4]: inner (type: Color)
Param[5]: outer (type: Color)
-Function 288: GenImageChecked() (6 input parameters)
+Function 290: GenImageChecked() (6 input parameters)
Name: GenImageChecked
Return type: Image
Description: Generate image: checked
@@ -2742,14 +2753,14 @@ Function 288: GenImageChecked() (6 input parameters)
Param[4]: checksY (type: int)
Param[5]: col1 (type: Color)
Param[6]: col2 (type: Color)
-Function 289: GenImageWhiteNoise() (3 input parameters)
+Function 291: GenImageWhiteNoise() (3 input parameters)
Name: GenImageWhiteNoise
Return type: Image
Description: Generate image: white noise
Param[1]: width (type: int)
Param[2]: height (type: int)
Param[3]: factor (type: float)
-Function 290: GenImagePerlinNoise() (5 input parameters)
+Function 292: GenImagePerlinNoise() (5 input parameters)
Name: GenImagePerlinNoise
Return type: Image
Description: Generate image: perlin noise
@@ -2758,45 +2769,45 @@ Function 290: GenImagePerlinNoise() (5 input parameters)
Param[3]: offsetX (type: int)
Param[4]: offsetY (type: int)
Param[5]: scale (type: float)
-Function 291: GenImageCellular() (3 input parameters)
+Function 293: GenImageCellular() (3 input parameters)
Name: GenImageCellular
Return type: Image
Description: Generate image: cellular algorithm, bigger tileSize means bigger cells
Param[1]: width (type: int)
Param[2]: height (type: int)
Param[3]: tileSize (type: int)
-Function 292: GenImageText() (3 input parameters)
+Function 294: GenImageText() (3 input parameters)
Name: GenImageText
Return type: Image
Description: Generate image: grayscale image from text data
Param[1]: width (type: int)
Param[2]: height (type: int)
Param[3]: text (type: const char *)
-Function 293: ImageCopy() (1 input parameters)
+Function 295: ImageCopy() (1 input parameters)
Name: ImageCopy
Return type: Image
Description: Create an image duplicate (useful for transformations)
Param[1]: image (type: Image)
-Function 294: ImageFromImage() (2 input parameters)
+Function 296: ImageFromImage() (2 input parameters)
Name: ImageFromImage
Return type: Image
Description: Create an image from another image piece
Param[1]: image (type: Image)
Param[2]: rec (type: Rectangle)
-Function 295: ImageFromChannel() (2 input parameters)
+Function 297: ImageFromChannel() (2 input parameters)
Name: ImageFromChannel
Return type: Image
Description: Create an image from a selected channel of another image (GRAYSCALE)
Param[1]: image (type: Image)
Param[2]: selectedChannel (type: int)
-Function 296: ImageText() (3 input parameters)
+Function 298: ImageText() (3 input parameters)
Name: ImageText
Return type: Image
Description: Create an image from text (default font)
Param[1]: text (type: const char *)
Param[2]: fontSize (type: int)
Param[3]: color (type: Color)
-Function 297: ImageTextEx() (5 input parameters)
+Function 299: ImageTextEx() (5 input parameters)
Name: ImageTextEx
Return type: Image
Description: Create an image from text (custom sprite font)
@@ -2805,76 +2816,76 @@ Function 297: ImageTextEx() (5 input parameters)
Param[3]: fontSize (type: float)
Param[4]: spacing (type: float)
Param[5]: tint (type: Color)
-Function 298: ImageFormat() (2 input parameters)
+Function 300: ImageFormat() (2 input parameters)
Name: ImageFormat
Return type: void
Description: Convert image data to desired format
Param[1]: image (type: Image *)
Param[2]: newFormat (type: int)
-Function 299: ImageToPOT() (2 input parameters)
+Function 301: ImageToPOT() (2 input parameters)
Name: ImageToPOT
Return type: void
Description: Convert image to POT (power-of-two)
Param[1]: image (type: Image *)
Param[2]: fill (type: Color)
-Function 300: ImageCrop() (2 input parameters)
+Function 302: ImageCrop() (2 input parameters)
Name: ImageCrop
Return type: void
Description: Crop an image to a defined rectangle
Param[1]: image (type: Image *)
Param[2]: crop (type: Rectangle)
-Function 301: ImageAlphaCrop() (2 input parameters)
+Function 303: ImageAlphaCrop() (2 input parameters)
Name: ImageAlphaCrop
Return type: void
Description: Crop image depending on alpha value
Param[1]: image (type: Image *)
Param[2]: threshold (type: float)
-Function 302: ImageAlphaClear() (3 input parameters)
+Function 304: ImageAlphaClear() (3 input parameters)
Name: ImageAlphaClear
Return type: void
Description: Clear alpha channel to desired color
Param[1]: image (type: Image *)
Param[2]: color (type: Color)
Param[3]: threshold (type: float)
-Function 303: ImageAlphaMask() (2 input parameters)
+Function 305: ImageAlphaMask() (2 input parameters)
Name: ImageAlphaMask
Return type: void
Description: Apply alpha mask to image
Param[1]: image (type: Image *)
Param[2]: alphaMask (type: Image)
-Function 304: ImageAlphaPremultiply() (1 input parameters)
+Function 306: ImageAlphaPremultiply() (1 input parameters)
Name: ImageAlphaPremultiply
Return type: void
Description: Premultiply alpha channel
Param[1]: image (type: Image *)
-Function 305: ImageBlurGaussian() (2 input parameters)
+Function 307: ImageBlurGaussian() (2 input parameters)
Name: ImageBlurGaussian
Return type: void
Description: Apply Gaussian blur using a box blur approximation
Param[1]: image (type: Image *)
Param[2]: blurSize (type: int)
-Function 306: ImageKernelConvolution() (3 input parameters)
+Function 308: ImageKernelConvolution() (3 input parameters)
Name: ImageKernelConvolution
Return type: void
Description: Apply custom square convolution kernel to image
Param[1]: image (type: Image *)
Param[2]: kernel (type: const float *)
Param[3]: kernelSize (type: int)
-Function 307: ImageResize() (3 input parameters)
+Function 309: ImageResize() (3 input parameters)
Name: ImageResize
Return type: void
Description: Resize image (Bicubic scaling algorithm)
Param[1]: image (type: Image *)
Param[2]: newWidth (type: int)
Param[3]: newHeight (type: int)
-Function 308: ImageResizeNN() (3 input parameters)
+Function 310: ImageResizeNN() (3 input parameters)
Name: ImageResizeNN
Return type: void
Description: Resize image (Nearest-Neighbor scaling algorithm)
Param[1]: image (type: Image *)
Param[2]: newWidth (type: int)
Param[3]: newHeight (type: int)
-Function 309: ImageResizeCanvas() (6 input parameters)
+Function 311: ImageResizeCanvas() (6 input parameters)
Name: ImageResizeCanvas
Return type: void
Description: Resize canvas and fill with color
@@ -2884,12 +2895,12 @@ Function 309: ImageResizeCanvas() (6 input parameters)
Param[4]: offsetX (type: int)
Param[5]: offsetY (type: int)
Param[6]: fill (type: Color)
-Function 310: ImageMipmaps() (1 input parameters)
+Function 312: ImageMipmaps() (1 input parameters)
Name: ImageMipmaps
Return type: void
Description: Compute all mipmap levels for a provided image
Param[1]: image (type: Image *)
-Function 311: ImageDither() (5 input parameters)
+Function 313: ImageDither() (5 input parameters)
Name: ImageDither
Return type: void
Description: Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
@@ -2898,109 +2909,109 @@ Function 311: ImageDither() (5 input parameters)
Param[3]: gBpp (type: int)
Param[4]: bBpp (type: int)
Param[5]: aBpp (type: int)
-Function 312: ImageFlipVertical() (1 input parameters)
+Function 314: ImageFlipVertical() (1 input parameters)
Name: ImageFlipVertical
Return type: void
Description: Flip image vertically
Param[1]: image (type: Image *)
-Function 313: ImageFlipHorizontal() (1 input parameters)
+Function 315: ImageFlipHorizontal() (1 input parameters)
Name: ImageFlipHorizontal
Return type: void
Description: Flip image horizontally
Param[1]: image (type: Image *)
-Function 314: ImageRotate() (2 input parameters)
+Function 316: ImageRotate() (2 input parameters)
Name: ImageRotate
Return type: void
Description: Rotate image by input angle in degrees (-359 to 359)
Param[1]: image (type: Image *)
Param[2]: degrees (type: int)
-Function 315: ImageRotateCW() (1 input parameters)
+Function 317: ImageRotateCW() (1 input parameters)
Name: ImageRotateCW
Return type: void
Description: Rotate image clockwise 90deg
Param[1]: image (type: Image *)
-Function 316: ImageRotateCCW() (1 input parameters)
+Function 318: ImageRotateCCW() (1 input parameters)
Name: ImageRotateCCW
Return type: void
Description: Rotate image counter-clockwise 90deg
Param[1]: image (type: Image *)
-Function 317: ImageColorTint() (2 input parameters)
+Function 319: ImageColorTint() (2 input parameters)
Name: ImageColorTint
Return type: void
Description: Modify image color: tint
Param[1]: image (type: Image *)
Param[2]: color (type: Color)
-Function 318: ImageColorInvert() (1 input parameters)
+Function 320: ImageColorInvert() (1 input parameters)
Name: ImageColorInvert
Return type: void
Description: Modify image color: invert
Param[1]: image (type: Image *)
-Function 319: ImageColorGrayscale() (1 input parameters)
+Function 321: ImageColorGrayscale() (1 input parameters)
Name: ImageColorGrayscale
Return type: void
Description: Modify image color: grayscale
Param[1]: image (type: Image *)
-Function 320: ImageColorContrast() (2 input parameters)
+Function 322: ImageColorContrast() (2 input parameters)
Name: ImageColorContrast
Return type: void
Description: Modify image color: contrast (-100 to 100)
Param[1]: image (type: Image *)
Param[2]: contrast (type: float)
-Function 321: ImageColorBrightness() (2 input parameters)
+Function 323: ImageColorBrightness() (2 input parameters)
Name: ImageColorBrightness
Return type: void
Description: Modify image color: brightness (-255 to 255)
Param[1]: image (type: Image *)
Param[2]: brightness (type: int)
-Function 322: ImageColorReplace() (3 input parameters)
+Function 324: ImageColorReplace() (3 input parameters)
Name: ImageColorReplace
Return type: void
Description: Modify image color: replace color
Param[1]: image (type: Image *)
Param[2]: color (type: Color)
Param[3]: replace (type: Color)
-Function 323: LoadImageColors() (1 input parameters)
+Function 325: LoadImageColors() (1 input parameters)
Name: LoadImageColors
Return type: Color *
Description: Load color data from image as a Color array (RGBA - 32bit)
Param[1]: image (type: Image)
-Function 324: LoadImagePalette() (3 input parameters)
+Function 326: LoadImagePalette() (3 input parameters)
Name: LoadImagePalette
Return type: Color *
Description: Load colors palette from image as a Color array (RGBA - 32bit)
Param[1]: image (type: Image)
Param[2]: maxPaletteSize (type: int)
Param[3]: colorCount (type: int *)
-Function 325: UnloadImageColors() (1 input parameters)
+Function 327: UnloadImageColors() (1 input parameters)
Name: UnloadImageColors
Return type: void
Description: Unload color data loaded with LoadImageColors()
Param[1]: colors (type: Color *)
-Function 326: UnloadImagePalette() (1 input parameters)
+Function 328: UnloadImagePalette() (1 input parameters)
Name: UnloadImagePalette
Return type: void
Description: Unload colors palette loaded with LoadImagePalette()
Param[1]: colors (type: Color *)
-Function 327: GetImageAlphaBorder() (2 input parameters)
+Function 329: GetImageAlphaBorder() (2 input parameters)
Name: GetImageAlphaBorder
Return type: Rectangle
Description: Get image alpha border rectangle
Param[1]: image (type: Image)
Param[2]: threshold (type: float)
-Function 328: GetImageColor() (3 input parameters)
+Function 330: GetImageColor() (3 input parameters)
Name: GetImageColor
Return type: Color
Description: Get image pixel color at (x, y) position
Param[1]: image (type: Image)
Param[2]: x (type: int)
Param[3]: y (type: int)
-Function 329: ImageClearBackground() (2 input parameters)
+Function 331: ImageClearBackground() (2 input parameters)
Name: ImageClearBackground
Return type: void
Description: Clear image background with given color
Param[1]: dst (type: Image *)
Param[2]: color (type: Color)
-Function 330: ImageDrawPixel() (4 input parameters)
+Function 332: ImageDrawPixel() (4 input parameters)
Name: ImageDrawPixel
Return type: void
Description: Draw pixel within an image
@@ -3008,14 +3019,14 @@ Function 330: ImageDrawPixel() (4 input parameters)
Param[2]: posX (type: int)
Param[3]: posY (type: int)
Param[4]: color (type: Color)
-Function 331: ImageDrawPixelV() (3 input parameters)
+Function 333: ImageDrawPixelV() (3 input parameters)
Name: ImageDrawPixelV
Return type: void
Description: Draw pixel within an image (Vector version)
Param[1]: dst (type: Image *)
Param[2]: position (type: Vector2)
Param[3]: color (type: Color)
-Function 332: ImageDrawLine() (6 input parameters)
+Function 334: ImageDrawLine() (6 input parameters)
Name: ImageDrawLine
Return type: void
Description: Draw line within an image
@@ -3025,7 +3036,7 @@ Function 332: ImageDrawLine() (6 input parameters)
Param[4]: endPosX (type: int)
Param[5]: endPosY (type: int)
Param[6]: color (type: Color)
-Function 333: ImageDrawLineV() (4 input parameters)
+Function 335: ImageDrawLineV() (4 input parameters)
Name: ImageDrawLineV
Return type: void
Description: Draw line within an image (Vector version)
@@ -3033,7 +3044,7 @@ Function 333: ImageDrawLineV() (4 input parameters)
Param[2]: start (type: Vector2)
Param[3]: end (type: Vector2)
Param[4]: color (type: Color)
-Function 334: ImageDrawLineEx() (5 input parameters)
+Function 336: ImageDrawLineEx() (5 input parameters)
Name: ImageDrawLineEx
Return type: void
Description: Draw a line defining thickness within an image
@@ -3042,7 +3053,7 @@ Function 334: ImageDrawLineEx() (5 input parameters)
Param[3]: end (type: Vector2)
Param[4]: thick (type: int)
Param[5]: color (type: Color)
-Function 335: ImageDrawCircle() (5 input parameters)
+Function 337: ImageDrawCircle() (5 input parameters)
Name: ImageDrawCircle
Return type: void
Description: Draw a filled circle within an image
@@ -3051,7 +3062,7 @@ Function 335: ImageDrawCircle() (5 input parameters)
Param[3]: centerY (type: int)
Param[4]: radius (type: int)
Param[5]: color (type: Color)
-Function 336: ImageDrawCircleV() (4 input parameters)
+Function 338: ImageDrawCircleV() (4 input parameters)
Name: ImageDrawCircleV
Return type: void
Description: Draw a filled circle within an image (Vector version)
@@ -3059,7 +3070,7 @@ Function 336: ImageDrawCircleV() (4 input parameters)
Param[2]: center (type: Vector2)
Param[3]: radius (type: int)
Param[4]: color (type: Color)
-Function 337: ImageDrawCircleLines() (5 input parameters)
+Function 339: ImageDrawCircleLines() (5 input parameters)
Name: ImageDrawCircleLines
Return type: void
Description: Draw circle outline within an image
@@ -3068,7 +3079,7 @@ Function 337: ImageDrawCircleLines() (5 input parameters)
Param[3]: centerY (type: int)
Param[4]: radius (type: int)
Param[5]: color (type: Color)
-Function 338: ImageDrawCircleLinesV() (4 input parameters)
+Function 340: ImageDrawCircleLinesV() (4 input parameters)
Name: ImageDrawCircleLinesV
Return type: void
Description: Draw circle outline within an image (Vector version)
@@ -3076,7 +3087,7 @@ Function 338: ImageDrawCircleLinesV() (4 input parameters)
Param[2]: center (type: Vector2)
Param[3]: radius (type: int)
Param[4]: color (type: Color)
-Function 339: ImageDrawRectangle() (6 input parameters)
+Function 341: ImageDrawRectangle() (6 input parameters)
Name: ImageDrawRectangle
Return type: void
Description: Draw rectangle within an image
@@ -3086,7 +3097,7 @@ Function 339: ImageDrawRectangle() (6 input parameters)
Param[4]: width (type: int)
Param[5]: height (type: int)
Param[6]: color (type: Color)
-Function 340: ImageDrawRectangleV() (4 input parameters)
+Function 342: ImageDrawRectangleV() (4 input parameters)
Name: ImageDrawRectangleV
Return type: void
Description: Draw rectangle within an image (Vector version)
@@ -3094,14 +3105,14 @@ Function 340: ImageDrawRectangleV() (4 input parameters)
Param[2]: position (type: Vector2)
Param[3]: size (type: Vector2)
Param[4]: color (type: Color)
-Function 341: ImageDrawRectangleRec() (3 input parameters)
+Function 343: ImageDrawRectangleRec() (3 input parameters)
Name: ImageDrawRectangleRec
Return type: void
Description: Draw rectangle within an image
Param[1]: dst (type: Image *)
Param[2]: rec (type: Rectangle)
Param[3]: color (type: Color)
-Function 342: ImageDrawRectangleLines() (4 input parameters)
+Function 344: ImageDrawRectangleLines() (4 input parameters)
Name: ImageDrawRectangleLines
Return type: void
Description: Draw rectangle lines within an image
@@ -3109,7 +3120,7 @@ Function 342: ImageDrawRectangleLines() (4 input parameters)
Param[2]: rec (type: Rectangle)
Param[3]: thick (type: int)
Param[4]: color (type: Color)
-Function 343: ImageDrawTriangle() (5 input parameters)
+Function 345: ImageDrawTriangle() (5 input parameters)
Name: ImageDrawTriangle
Return type: void
Description: Draw triangle within an image
@@ -3118,7 +3129,7 @@ Function 343: ImageDrawTriangle() (5 input parameters)
Param[3]: v2 (type: Vector2)
Param[4]: v3 (type: Vector2)
Param[5]: color (type: Color)
-Function 344: ImageDrawTriangleEx() (7 input parameters)
+Function 346: ImageDrawTriangleEx() (7 input parameters)
Name: ImageDrawTriangleEx
Return type: void
Description: Draw triangle with interpolated colors within an image
@@ -3129,7 +3140,7 @@ Function 344: ImageDrawTriangleEx() (7 input parameters)
Param[5]: c1 (type: Color)
Param[6]: c2 (type: Color)
Param[7]: c3 (type: Color)
-Function 345: ImageDrawTriangleLines() (5 input parameters)
+Function 347: ImageDrawTriangleLines() (5 input parameters)
Name: ImageDrawTriangleLines
Return type: void
Description: Draw triangle outline within an image
@@ -3138,7 +3149,7 @@ Function 345: ImageDrawTriangleLines() (5 input parameters)
Param[3]: v2 (type: Vector2)
Param[4]: v3 (type: Vector2)
Param[5]: color (type: Color)
-Function 346: ImageDrawTriangleFan() (4 input parameters)
+Function 348: ImageDrawTriangleFan() (4 input parameters)
Name: ImageDrawTriangleFan
Return type: void
Description: Draw a triangle fan defined by points within an image (first vertex is the center)
@@ -3146,7 +3157,7 @@ Function 346: ImageDrawTriangleFan() (4 input parameters)
Param[2]: points (type: Vector2 *)
Param[3]: pointCount (type: int)
Param[4]: color (type: Color)
-Function 347: ImageDrawTriangleStrip() (4 input parameters)
+Function 349: ImageDrawTriangleStrip() (4 input parameters)
Name: ImageDrawTriangleStrip
Return type: void
Description: Draw a triangle strip defined by points within an image
@@ -3154,7 +3165,7 @@ Function 347: ImageDrawTriangleStrip() (4 input parameters)
Param[2]: points (type: Vector2 *)
Param[3]: pointCount (type: int)
Param[4]: color (type: Color)
-Function 348: ImageDraw() (5 input parameters)
+Function 350: ImageDraw() (5 input parameters)
Name: ImageDraw
Return type: void
Description: Draw a source image within a destination image (tint applied to source)
@@ -3163,7 +3174,7 @@ Function 348: ImageDraw() (5 input parameters)
Param[3]: srcRec (type: Rectangle)
Param[4]: dstRec (type: Rectangle)
Param[5]: tint (type: Color)
-Function 349: ImageDrawText() (6 input parameters)
+Function 351: ImageDrawText() (6 input parameters)
Name: ImageDrawText
Return type: void
Description: Draw text (using default font) within an image (destination)
@@ -3173,7 +3184,7 @@ Function 349: ImageDrawText() (6 input parameters)
Param[4]: posY (type: int)
Param[5]: fontSize (type: int)
Param[6]: color (type: Color)
-Function 350: ImageDrawTextEx() (7 input parameters)
+Function 352: ImageDrawTextEx() (7 input parameters)
Name: ImageDrawTextEx
Return type: void
Description: Draw text (custom sprite font) within an image (destination)
@@ -3184,79 +3195,79 @@ Function 350: ImageDrawTextEx() (7 input parameters)
Param[5]: fontSize (type: float)
Param[6]: spacing (type: float)
Param[7]: tint (type: Color)
-Function 351: LoadTexture() (1 input parameters)
+Function 353: LoadTexture() (1 input parameters)
Name: LoadTexture
Return type: Texture2D
Description: Load texture from file into GPU memory (VRAM)
Param[1]: fileName (type: const char *)
-Function 352: LoadTextureFromImage() (1 input parameters)
+Function 354: LoadTextureFromImage() (1 input parameters)
Name: LoadTextureFromImage
Return type: Texture2D
Description: Load texture from image data
Param[1]: image (type: Image)
-Function 353: LoadTextureCubemap() (2 input parameters)
+Function 355: LoadTextureCubemap() (2 input parameters)
Name: LoadTextureCubemap
Return type: TextureCubemap
Description: Load cubemap from image, multiple image cubemap layouts supported
Param[1]: image (type: Image)
Param[2]: layout (type: int)
-Function 354: LoadRenderTexture() (2 input parameters)
+Function 356: LoadRenderTexture() (2 input parameters)
Name: LoadRenderTexture
Return type: RenderTexture2D
Description: Load texture for rendering (framebuffer)
Param[1]: width (type: int)
Param[2]: height (type: int)
-Function 355: IsTextureReady() (1 input parameters)
- Name: IsTextureReady
+Function 357: IsTextureValid() (1 input parameters)
+ Name: IsTextureValid
Return type: bool
- Description: Check if a texture is ready
+ Description: Check if a texture is valid (loaded in GPU)
Param[1]: texture (type: Texture2D)
-Function 356: UnloadTexture() (1 input parameters)
+Function 358: UnloadTexture() (1 input parameters)
Name: UnloadTexture
Return type: void
Description: Unload texture from GPU memory (VRAM)
Param[1]: texture (type: Texture2D)
-Function 357: IsRenderTextureReady() (1 input parameters)
- Name: IsRenderTextureReady
+Function 359: IsRenderTextureValid() (1 input parameters)
+ Name: IsRenderTextureValid
Return type: bool
- Description: Check if a render texture is ready
+ Description: Check if a render texture is valid (loaded in GPU)
Param[1]: target (type: RenderTexture2D)
-Function 358: UnloadRenderTexture() (1 input parameters)
+Function 360: UnloadRenderTexture() (1 input parameters)
Name: UnloadRenderTexture
Return type: void
Description: Unload render texture from GPU memory (VRAM)
Param[1]: target (type: RenderTexture2D)
-Function 359: UpdateTexture() (2 input parameters)
+Function 361: UpdateTexture() (2 input parameters)
Name: UpdateTexture
Return type: void
Description: Update GPU texture with new data
Param[1]: texture (type: Texture2D)
Param[2]: pixels (type: const void *)
-Function 360: UpdateTextureRec() (3 input parameters)
+Function 362: UpdateTextureRec() (3 input parameters)
Name: UpdateTextureRec
Return type: void
Description: Update GPU texture rectangle with new data
Param[1]: texture (type: Texture2D)
Param[2]: rec (type: Rectangle)
Param[3]: pixels (type: const void *)
-Function 361: GenTextureMipmaps() (1 input parameters)
+Function 363: GenTextureMipmaps() (1 input parameters)
Name: GenTextureMipmaps
Return type: void
Description: Generate GPU mipmaps for a texture
Param[1]: texture (type: Texture2D *)
-Function 362: SetTextureFilter() (2 input parameters)
+Function 364: SetTextureFilter() (2 input parameters)
Name: SetTextureFilter
Return type: void
Description: Set texture scaling filter mode
Param[1]: texture (type: Texture2D)
Param[2]: filter (type: int)
-Function 363: SetTextureWrap() (2 input parameters)
+Function 365: SetTextureWrap() (2 input parameters)
Name: SetTextureWrap
Return type: void
Description: Set texture wrapping mode
Param[1]: texture (type: Texture2D)
Param[2]: wrap (type: int)
-Function 364: DrawTexture() (4 input parameters)
+Function 366: DrawTexture() (4 input parameters)
Name: DrawTexture
Return type: void
Description: Draw a Texture2D
@@ -3264,14 +3275,14 @@ Function 364: DrawTexture() (4 input parameters)
Param[2]: posX (type: int)
Param[3]: posY (type: int)
Param[4]: tint (type: Color)
-Function 365: DrawTextureV() (3 input parameters)
+Function 367: DrawTextureV() (3 input parameters)
Name: DrawTextureV
Return type: void
Description: Draw a Texture2D with position defined as Vector2
Param[1]: texture (type: Texture2D)
Param[2]: position (type: Vector2)
Param[3]: tint (type: Color)
-Function 366: DrawTextureEx() (5 input parameters)
+Function 368: DrawTextureEx() (5 input parameters)
Name: DrawTextureEx
Return type: void
Description: Draw a Texture2D with extended parameters
@@ -3280,7 +3291,7 @@ Function 366: DrawTextureEx() (5 input parameters)
Param[3]: rotation (type: float)
Param[4]: scale (type: float)
Param[5]: tint (type: Color)
-Function 367: DrawTextureRec() (4 input parameters)
+Function 369: DrawTextureRec() (4 input parameters)
Name: DrawTextureRec
Return type: void
Description: Draw a part of a texture defined by a rectangle
@@ -3288,7 +3299,7 @@ Function 367: DrawTextureRec() (4 input parameters)
Param[2]: source (type: Rectangle)
Param[3]: position (type: Vector2)
Param[4]: tint (type: Color)
-Function 368: DrawTexturePro() (6 input parameters)
+Function 370: DrawTexturePro() (6 input parameters)
Name: DrawTexturePro
Return type: void
Description: Draw a part of a texture defined by a rectangle with 'pro' parameters
@@ -3298,7 +3309,7 @@ Function 368: DrawTexturePro() (6 input parameters)
Param[4]: origin (type: Vector2)
Param[5]: rotation (type: float)
Param[6]: tint (type: Color)
-Function 369: DrawTextureNPatch() (6 input parameters)
+Function 371: DrawTextureNPatch() (6 input parameters)
Name: DrawTextureNPatch
Return type: void
Description: Draws a texture (or part of it) that stretches or shrinks nicely
@@ -3308,119 +3319,119 @@ Function 369: DrawTextureNPatch() (6 input parameters)
Param[4]: origin (type: Vector2)
Param[5]: rotation (type: float)
Param[6]: tint (type: Color)
-Function 370: ColorIsEqual() (2 input parameters)
+Function 372: ColorIsEqual() (2 input parameters)
Name: ColorIsEqual
Return type: bool
Description: Check if two colors are equal
Param[1]: col1 (type: Color)
Param[2]: col2 (type: Color)
-Function 371: Fade() (2 input parameters)
+Function 373: Fade() (2 input parameters)
Name: Fade
Return type: Color
Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f
Param[1]: color (type: Color)
Param[2]: alpha (type: float)
-Function 372: ColorToInt() (1 input parameters)
+Function 374: ColorToInt() (1 input parameters)
Name: ColorToInt
Return type: int
Description: Get hexadecimal value for a Color (0xRRGGBBAA)
Param[1]: color (type: Color)
-Function 373: ColorNormalize() (1 input parameters)
+Function 375: ColorNormalize() (1 input parameters)
Name: ColorNormalize
Return type: Vector4
Description: Get Color normalized as float [0..1]
Param[1]: color (type: Color)
-Function 374: ColorFromNormalized() (1 input parameters)
+Function 376: ColorFromNormalized() (1 input parameters)
Name: ColorFromNormalized
Return type: Color
Description: Get Color from normalized values [0..1]
Param[1]: normalized (type: Vector4)
-Function 375: ColorToHSV() (1 input parameters)
+Function 377: ColorToHSV() (1 input parameters)
Name: ColorToHSV
Return type: Vector3
Description: Get HSV values for a Color, hue [0..360], saturation/value [0..1]
Param[1]: color (type: Color)
-Function 376: ColorFromHSV() (3 input parameters)
+Function 378: ColorFromHSV() (3 input parameters)
Name: ColorFromHSV
Return type: Color
Description: Get a Color from HSV values, hue [0..360], saturation/value [0..1]
Param[1]: hue (type: float)
Param[2]: saturation (type: float)
Param[3]: value (type: float)
-Function 377: ColorTint() (2 input parameters)
+Function 379: ColorTint() (2 input parameters)
Name: ColorTint
Return type: Color
Description: Get color multiplied with another color
Param[1]: color (type: Color)
Param[2]: tint (type: Color)
-Function 378: ColorBrightness() (2 input parameters)
+Function 380: ColorBrightness() (2 input parameters)
Name: ColorBrightness
Return type: Color
Description: Get color with brightness correction, brightness factor goes from -1.0f to 1.0f
Param[1]: color (type: Color)
Param[2]: factor (type: float)
-Function 379: ColorContrast() (2 input parameters)
+Function 381: ColorContrast() (2 input parameters)
Name: ColorContrast
Return type: Color
Description: Get color with contrast correction, contrast values between -1.0f and 1.0f
Param[1]: color (type: Color)
Param[2]: contrast (type: float)
-Function 380: ColorAlpha() (2 input parameters)
+Function 382: ColorAlpha() (2 input parameters)
Name: ColorAlpha
Return type: Color
Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f
Param[1]: color (type: Color)
Param[2]: alpha (type: float)
-Function 381: ColorAlphaBlend() (3 input parameters)
+Function 383: ColorAlphaBlend() (3 input parameters)
Name: ColorAlphaBlend
Return type: Color
Description: Get src alpha-blended into dst color with tint
Param[1]: dst (type: Color)
Param[2]: src (type: Color)
Param[3]: tint (type: Color)
-Function 382: ColorLerp() (3 input parameters)
+Function 384: ColorLerp() (3 input parameters)
Name: ColorLerp
Return type: Color
Description: Get color lerp interpolation between two colors, factor [0.0f..1.0f]
Param[1]: color1 (type: Color)
Param[2]: color2 (type: Color)
Param[3]: factor (type: float)
-Function 383: GetColor() (1 input parameters)
+Function 385: GetColor() (1 input parameters)
Name: GetColor
Return type: Color
Description: Get Color structure from hexadecimal value
Param[1]: hexValue (type: unsigned int)
-Function 384: GetPixelColor() (2 input parameters)
+Function 386: GetPixelColor() (2 input parameters)
Name: GetPixelColor
Return type: Color
Description: Get Color from a source pixel pointer of certain format
Param[1]: srcPtr (type: void *)
Param[2]: format (type: int)
-Function 385: SetPixelColor() (3 input parameters)
+Function 387: SetPixelColor() (3 input parameters)
Name: SetPixelColor
Return type: void
Description: Set color formatted into destination pixel pointer
Param[1]: dstPtr (type: void *)
Param[2]: color (type: Color)
Param[3]: format (type: int)
-Function 386: GetPixelDataSize() (3 input parameters)
+Function 388: GetPixelDataSize() (3 input parameters)
Name: GetPixelDataSize
Return type: int
Description: Get pixel data size in bytes for certain format
Param[1]: width (type: int)
Param[2]: height (type: int)
Param[3]: format (type: int)
-Function 387: GetFontDefault() (0 input parameters)
+Function 389: GetFontDefault() (0 input parameters)
Name: GetFontDefault
Return type: Font
Description: Get the default Font
No input parameters
-Function 388: LoadFont() (1 input parameters)
+Function 390: LoadFont() (1 input parameters)
Name: LoadFont
Return type: Font
Description: Load font from file into GPU memory (VRAM)
Param[1]: fileName (type: const char *)
-Function 389: LoadFontEx() (4 input parameters)
+Function 391: LoadFontEx() (4 input parameters)
Name: LoadFontEx
Return type: Font
Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
@@ -3428,14 +3439,14 @@ Function 389: LoadFontEx() (4 input parameters)
Param[2]: fontSize (type: int)
Param[3]: codepoints (type: int *)
Param[4]: codepointCount (type: int)
-Function 390: LoadFontFromImage() (3 input parameters)
+Function 392: LoadFontFromImage() (3 input parameters)
Name: LoadFontFromImage
Return type: Font
Description: Load font from Image (XNA style)
Param[1]: image (type: Image)
Param[2]: key (type: Color)
Param[3]: firstChar (type: int)
-Function 391: LoadFontFromMemory() (6 input parameters)
+Function 393: LoadFontFromMemory() (6 input parameters)
Name: LoadFontFromMemory
Return type: Font
Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
@@ -3445,12 +3456,12 @@ Function 391: LoadFontFromMemory() (6 input parameters)
Param[4]: fontSize (type: int)
Param[5]: codepoints (type: int *)
Param[6]: codepointCount (type: int)
-Function 392: IsFontReady() (1 input parameters)
- Name: IsFontReady
+Function 394: IsFontValid() (1 input parameters)
+ Name: IsFontValid
Return type: bool
- Description: Check if a font is ready
+ Description: Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
Param[1]: font (type: Font)
-Function 393: LoadFontData() (6 input parameters)
+Function 395: LoadFontData() (6 input parameters)
Name: LoadFontData
Return type: GlyphInfo *
Description: Load font data for further use
@@ -3460,7 +3471,7 @@ Function 393: LoadFontData() (6 input parameters)
Param[4]: codepoints (type: int *)
Param[5]: codepointCount (type: int)
Param[6]: type (type: int)
-Function 394: GenImageFontAtlas() (6 input parameters)
+Function 396: GenImageFontAtlas() (6 input parameters)
Name: GenImageFontAtlas
Return type: Image
Description: Generate image font atlas using chars info
@@ -3470,30 +3481,30 @@ Function 394: GenImageFontAtlas() (6 input parameters)
Param[4]: fontSize (type: int)
Param[5]: padding (type: int)
Param[6]: packMethod (type: int)
-Function 395: UnloadFontData() (2 input parameters)
+Function 397: UnloadFontData() (2 input parameters)
Name: UnloadFontData
Return type: void
Description: Unload font chars info data (RAM)
Param[1]: glyphs (type: GlyphInfo *)
Param[2]: glyphCount (type: int)
-Function 396: UnloadFont() (1 input parameters)
+Function 398: UnloadFont() (1 input parameters)
Name: UnloadFont
Return type: void
Description: Unload font from GPU memory (VRAM)
Param[1]: font (type: Font)
-Function 397: ExportFontAsCode() (2 input parameters)
+Function 399: ExportFontAsCode() (2 input parameters)
Name: ExportFontAsCode
Return type: bool
Description: Export font as code file, returns true on success
Param[1]: font (type: Font)
Param[2]: fileName (type: const char *)
-Function 398: DrawFPS() (2 input parameters)
+Function 400: DrawFPS() (2 input parameters)
Name: DrawFPS
Return type: void
Description: Draw current FPS
Param[1]: posX (type: int)
Param[2]: posY (type: int)
-Function 399: DrawText() (5 input parameters)
+Function 401: DrawText() (5 input parameters)
Name: DrawText
Return type: void
Description: Draw text (using default font)
@@ -3502,7 +3513,7 @@ Function 399: DrawText() (5 input parameters)
Param[3]: posY (type: int)
Param[4]: fontSize (type: int)
Param[5]: color (type: Color)
-Function 400: DrawTextEx() (6 input parameters)
+Function 402: DrawTextEx() (6 input parameters)
Name: DrawTextEx
Return type: void
Description: Draw text using font and additional parameters
@@ -3512,7 +3523,7 @@ Function 400: DrawTextEx() (6 input parameters)
Param[4]: fontSize (type: float)
Param[5]: spacing (type: float)
Param[6]: tint (type: Color)
-Function 401: DrawTextPro() (8 input parameters)
+Function 403: DrawTextPro() (8 input parameters)
Name: DrawTextPro
Return type: void
Description: Draw text using Font and pro parameters (rotation)
@@ -3524,7 +3535,7 @@ Function 401: DrawTextPro() (8 input parameters)
Param[6]: fontSize (type: float)
Param[7]: spacing (type: float)
Param[8]: tint (type: Color)
-Function 402: DrawTextCodepoint() (5 input parameters)
+Function 404: DrawTextCodepoint() (5 input parameters)
Name: DrawTextCodepoint
Return type: void
Description: Draw one character (codepoint)
@@ -3533,7 +3544,7 @@ Function 402: DrawTextCodepoint() (5 input parameters)
Param[3]: position (type: Vector2)
Param[4]: fontSize (type: float)
Param[5]: tint (type: Color)
-Function 403: DrawTextCodepoints() (7 input parameters)
+Function 405: DrawTextCodepoints() (7 input parameters)
Name: DrawTextCodepoints
Return type: void
Description: Draw multiple character (codepoint)
@@ -3544,18 +3555,18 @@ Function 403: DrawTextCodepoints() (7 input parameters)
Param[5]: fontSize (type: float)
Param[6]: spacing (type: float)
Param[7]: tint (type: Color)
-Function 404: SetTextLineSpacing() (1 input parameters)
+Function 406: SetTextLineSpacing() (1 input parameters)
Name: SetTextLineSpacing
Return type: void
Description: Set vertical line spacing when drawing with line-breaks
Param[1]: spacing (type: int)
-Function 405: MeasureText() (2 input parameters)
+Function 407: MeasureText() (2 input parameters)
Name: MeasureText
Return type: int
Description: Measure string width for default font
Param[1]: text (type: const char *)
Param[2]: fontSize (type: int)
-Function 406: MeasureTextEx() (4 input parameters)
+Function 408: MeasureTextEx() (4 input parameters)
Name: MeasureTextEx
Return type: Vector2
Description: Measure string size for Font
@@ -3563,195 +3574,195 @@ Function 406: MeasureTextEx() (4 input parameters)
Param[2]: text (type: const char *)
Param[3]: fontSize (type: float)
Param[4]: spacing (type: float)
-Function 407: GetGlyphIndex() (2 input parameters)
+Function 409: GetGlyphIndex() (2 input parameters)
Name: GetGlyphIndex
Return type: int
Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
Param[1]: font (type: Font)
Param[2]: codepoint (type: int)
-Function 408: GetGlyphInfo() (2 input parameters)
+Function 410: GetGlyphInfo() (2 input parameters)
Name: GetGlyphInfo
Return type: GlyphInfo
Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
Param[1]: font (type: Font)
Param[2]: codepoint (type: int)
-Function 409: GetGlyphAtlasRec() (2 input parameters)
+Function 411: GetGlyphAtlasRec() (2 input parameters)
Name: GetGlyphAtlasRec
Return type: Rectangle
Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
Param[1]: font (type: Font)
Param[2]: codepoint (type: int)
-Function 410: LoadUTF8() (2 input parameters)
+Function 412: LoadUTF8() (2 input parameters)
Name: LoadUTF8
Return type: char *
Description: Load UTF-8 text encoded from codepoints array
Param[1]: codepoints (type: const int *)
Param[2]: length (type: int)
-Function 411: UnloadUTF8() (1 input parameters)
+Function 413: UnloadUTF8() (1 input parameters)
Name: UnloadUTF8
Return type: void
Description: Unload UTF-8 text encoded from codepoints array
Param[1]: text (type: char *)
-Function 412: LoadCodepoints() (2 input parameters)
+Function 414: LoadCodepoints() (2 input parameters)
Name: LoadCodepoints
Return type: int *
Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
Param[1]: text (type: const char *)
Param[2]: count (type: int *)
-Function 413: UnloadCodepoints() (1 input parameters)
+Function 415: UnloadCodepoints() (1 input parameters)
Name: UnloadCodepoints
Return type: void
Description: Unload codepoints data from memory
Param[1]: codepoints (type: int *)
-Function 414: GetCodepointCount() (1 input parameters)
+Function 416: GetCodepointCount() (1 input parameters)
Name: GetCodepointCount
Return type: int
Description: Get total number of codepoints in a UTF-8 encoded string
Param[1]: text (type: const char *)
-Function 415: GetCodepoint() (2 input parameters)
+Function 417: GetCodepoint() (2 input parameters)
Name: GetCodepoint
Return type: int
Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
Param[1]: text (type: const char *)
Param[2]: codepointSize (type: int *)
-Function 416: GetCodepointNext() (2 input parameters)
+Function 418: GetCodepointNext() (2 input parameters)
Name: GetCodepointNext
Return type: int
Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
Param[1]: text (type: const char *)
Param[2]: codepointSize (type: int *)
-Function 417: GetCodepointPrevious() (2 input parameters)
+Function 419: GetCodepointPrevious() (2 input parameters)
Name: GetCodepointPrevious
Return type: int
Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
Param[1]: text (type: const char *)
Param[2]: codepointSize (type: int *)
-Function 418: CodepointToUTF8() (2 input parameters)
+Function 420: CodepointToUTF8() (2 input parameters)
Name: CodepointToUTF8
Return type: const char *
Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter)
Param[1]: codepoint (type: int)
Param[2]: utf8Size (type: int *)
-Function 419: TextCopy() (2 input parameters)
+Function 421: TextCopy() (2 input parameters)
Name: TextCopy
Return type: int
Description: Copy one string to another, returns bytes copied
Param[1]: dst (type: char *)
Param[2]: src (type: const char *)
-Function 420: TextIsEqual() (2 input parameters)
+Function 422: TextIsEqual() (2 input parameters)
Name: TextIsEqual
Return type: bool
Description: Check if two text string are equal
Param[1]: text1 (type: const char *)
Param[2]: text2 (type: const char *)
-Function 421: TextLength() (1 input parameters)
+Function 423: TextLength() (1 input parameters)
Name: TextLength
Return type: unsigned int
Description: Get text length, checks for '\0' ending
Param[1]: text (type: const char *)
-Function 422: TextFormat() (2 input parameters)
+Function 424: TextFormat() (2 input parameters)
Name: TextFormat
Return type: const char *
Description: Text formatting with variables (sprintf() style)
Param[1]: text (type: const char *)
Param[2]: args (type: ...)
-Function 423: TextSubtext() (3 input parameters)
+Function 425: TextSubtext() (3 input parameters)
Name: TextSubtext
Return type: const char *
Description: Get a piece of a text string
Param[1]: text (type: const char *)
Param[2]: position (type: int)
Param[3]: length (type: int)
-Function 424: TextReplace() (3 input parameters)
+Function 426: TextReplace() (3 input parameters)
Name: TextReplace
Return type: char *
Description: Replace text string (WARNING: memory must be freed!)
Param[1]: text (type: const char *)
Param[2]: replace (type: const char *)
Param[3]: by (type: const char *)
-Function 425: TextInsert() (3 input parameters)
+Function 427: TextInsert() (3 input parameters)
Name: TextInsert
Return type: char *
Description: Insert text in a position (WARNING: memory must be freed!)
Param[1]: text (type: const char *)
Param[2]: insert (type: const char *)
Param[3]: position (type: int)
-Function 426: TextJoin() (3 input parameters)
+Function 428: TextJoin() (3 input parameters)
Name: TextJoin
Return type: const char *
Description: Join text strings with delimiter
Param[1]: textList (type: const char **)
Param[2]: count (type: int)
Param[3]: delimiter (type: const char *)
-Function 427: TextSplit() (3 input parameters)
+Function 429: TextSplit() (3 input parameters)
Name: TextSplit
Return type: const char **
Description: Split text into multiple strings
Param[1]: text (type: const char *)
Param[2]: delimiter (type: char)
Param[3]: count (type: int *)
-Function 428: TextAppend() (3 input parameters)
+Function 430: TextAppend() (3 input parameters)
Name: TextAppend
Return type: void
Description: Append text at specific position and move cursor!
Param[1]: text (type: char *)
Param[2]: append (type: const char *)
Param[3]: position (type: int *)
-Function 429: TextFindIndex() (2 input parameters)
+Function 431: TextFindIndex() (2 input parameters)
Name: TextFindIndex
Return type: int
Description: Find first text occurrence within a string
Param[1]: text (type: const char *)
Param[2]: find (type: const char *)
-Function 430: TextToUpper() (1 input parameters)
+Function 432: TextToUpper() (1 input parameters)
Name: TextToUpper
Return type: const char *
Description: Get upper case version of provided string
Param[1]: text (type: const char *)
-Function 431: TextToLower() (1 input parameters)
+Function 433: TextToLower() (1 input parameters)
Name: TextToLower
Return type: const char *
Description: Get lower case version of provided string
Param[1]: text (type: const char *)
-Function 432: TextToPascal() (1 input parameters)
+Function 434: TextToPascal() (1 input parameters)
Name: TextToPascal
Return type: const char *
Description: Get Pascal case notation version of provided string
Param[1]: text (type: const char *)
-Function 433: TextToSnake() (1 input parameters)
+Function 435: TextToSnake() (1 input parameters)
Name: TextToSnake
Return type: const char *
Description: Get Snake case notation version of provided string
Param[1]: text (type: const char *)
-Function 434: TextToCamel() (1 input parameters)
+Function 436: TextToCamel() (1 input parameters)
Name: TextToCamel
Return type: const char *
Description: Get Camel case notation version of provided string
Param[1]: text (type: const char *)
-Function 435: TextToInteger() (1 input parameters)
+Function 437: TextToInteger() (1 input parameters)
Name: TextToInteger
Return type: int
Description: Get integer value from text (negative values not supported)
Param[1]: text (type: const char *)
-Function 436: TextToFloat() (1 input parameters)
+Function 438: TextToFloat() (1 input parameters)
Name: TextToFloat
Return type: float
Description: Get float value from text (negative values not supported)
Param[1]: text (type: const char *)
-Function 437: DrawLine3D() (3 input parameters)
+Function 439: DrawLine3D() (3 input parameters)
Name: DrawLine3D
Return type: void
Description: Draw a line in 3D world space
Param[1]: startPos (type: Vector3)
Param[2]: endPos (type: Vector3)
Param[3]: color (type: Color)
-Function 438: DrawPoint3D() (2 input parameters)
+Function 440: DrawPoint3D() (2 input parameters)
Name: DrawPoint3D
Return type: void
Description: Draw a point in 3D space, actually a small line
Param[1]: position (type: Vector3)
Param[2]: color (type: Color)
-Function 439: DrawCircle3D() (5 input parameters)
+Function 441: DrawCircle3D() (5 input parameters)
Name: DrawCircle3D
Return type: void
Description: Draw a circle in 3D world space
@@ -3760,7 +3771,7 @@ Function 439: DrawCircle3D() (5 input parameters)
Param[3]: rotationAxis (type: Vector3)
Param[4]: rotationAngle (type: float)
Param[5]: color (type: Color)
-Function 440: DrawTriangle3D() (4 input parameters)
+Function 442: DrawTriangle3D() (4 input parameters)
Name: DrawTriangle3D
Return type: void
Description: Draw a color-filled triangle (vertex in counter-clockwise order!)
@@ -3768,14 +3779,14 @@ Function 440: DrawTriangle3D() (4 input parameters)
Param[2]: v2 (type: Vector3)
Param[3]: v3 (type: Vector3)
Param[4]: color (type: Color)
-Function 441: DrawTriangleStrip3D() (3 input parameters)
+Function 443: DrawTriangleStrip3D() (3 input parameters)
Name: DrawTriangleStrip3D
Return type: void
Description: Draw a triangle strip defined by points
Param[1]: points (type: const Vector3 *)
Param[2]: pointCount (type: int)
Param[3]: color (type: Color)
-Function 442: DrawCube() (5 input parameters)
+Function 444: DrawCube() (5 input parameters)
Name: DrawCube
Return type: void
Description: Draw cube
@@ -3784,14 +3795,14 @@ Function 442: DrawCube() (5 input parameters)
Param[3]: height (type: float)
Param[4]: length (type: float)
Param[5]: color (type: Color)
-Function 443: DrawCubeV() (3 input parameters)
+Function 445: DrawCubeV() (3 input parameters)
Name: DrawCubeV
Return type: void
Description: Draw cube (Vector version)
Param[1]: position (type: Vector3)
Param[2]: size (type: Vector3)
Param[3]: color (type: Color)
-Function 444: DrawCubeWires() (5 input parameters)
+Function 446: DrawCubeWires() (5 input parameters)
Name: DrawCubeWires
Return type: void
Description: Draw cube wires
@@ -3800,21 +3811,21 @@ Function 444: DrawCubeWires() (5 input parameters)
Param[3]: height (type: float)
Param[4]: length (type: float)
Param[5]: color (type: Color)
-Function 445: DrawCubeWiresV() (3 input parameters)
+Function 447: DrawCubeWiresV() (3 input parameters)
Name: DrawCubeWiresV
Return type: void
Description: Draw cube wires (Vector version)
Param[1]: position (type: Vector3)
Param[2]: size (type: Vector3)
Param[3]: color (type: Color)
-Function 446: DrawSphere() (3 input parameters)
+Function 448: DrawSphere() (3 input parameters)
Name: DrawSphere
Return type: void
Description: Draw sphere
Param[1]: centerPos (type: Vector3)
Param[2]: radius (type: float)
Param[3]: color (type: Color)
-Function 447: DrawSphereEx() (5 input parameters)
+Function 449: DrawSphereEx() (5 input parameters)
Name: DrawSphereEx
Return type: void
Description: Draw sphere with extended parameters
@@ -3823,7 +3834,7 @@ Function 447: DrawSphereEx() (5 input parameters)
Param[3]: rings (type: int)
Param[4]: slices (type: int)
Param[5]: color (type: Color)
-Function 448: DrawSphereWires() (5 input parameters)
+Function 450: DrawSphereWires() (5 input parameters)
Name: DrawSphereWires
Return type: void
Description: Draw sphere wires
@@ -3832,7 +3843,7 @@ Function 448: DrawSphereWires() (5 input parameters)
Param[3]: rings (type: int)
Param[4]: slices (type: int)
Param[5]: color (type: Color)
-Function 449: DrawCylinder() (6 input parameters)
+Function 451: DrawCylinder() (6 input parameters)
Name: DrawCylinder
Return type: void
Description: Draw a cylinder/cone
@@ -3842,7 +3853,7 @@ Function 449: DrawCylinder() (6 input parameters)
Param[4]: height (type: float)
Param[5]: slices (type: int)
Param[6]: color (type: Color)
-Function 450: DrawCylinderEx() (6 input parameters)
+Function 452: DrawCylinderEx() (6 input parameters)
Name: DrawCylinderEx
Return type: void
Description: Draw a cylinder with base at startPos and top at endPos
@@ -3852,7 +3863,7 @@ Function 450: DrawCylinderEx() (6 input parameters)
Param[4]: endRadius (type: float)
Param[5]: sides (type: int)
Param[6]: color (type: Color)
-Function 451: DrawCylinderWires() (6 input parameters)
+Function 453: DrawCylinderWires() (6 input parameters)
Name: DrawCylinderWires
Return type: void
Description: Draw a cylinder/cone wires
@@ -3862,7 +3873,7 @@ Function 451: DrawCylinderWires() (6 input parameters)
Param[4]: height (type: float)
Param[5]: slices (type: int)
Param[6]: color (type: Color)
-Function 452: DrawCylinderWiresEx() (6 input parameters)
+Function 454: DrawCylinderWiresEx() (6 input parameters)
Name: DrawCylinderWiresEx
Return type: void
Description: Draw a cylinder wires with base at startPos and top at endPos
@@ -3872,7 +3883,7 @@ Function 452: DrawCylinderWiresEx() (6 input parameters)
Param[4]: endRadius (type: float)
Param[5]: sides (type: int)
Param[6]: color (type: Color)
-Function 453: DrawCapsule() (6 input parameters)
+Function 455: DrawCapsule() (6 input parameters)
Name: DrawCapsule
Return type: void
Description: Draw a capsule with the center of its sphere caps at startPos and endPos
@@ -3882,7 +3893,7 @@ Function 453: DrawCapsule() (6 input parameters)
Param[4]: slices (type: int)
Param[5]: rings (type: int)
Param[6]: color (type: Color)
-Function 454: DrawCapsuleWires() (6 input parameters)
+Function 456: DrawCapsuleWires() (6 input parameters)
Name: DrawCapsuleWires
Return type: void
Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos
@@ -3892,51 +3903,51 @@ Function 454: DrawCapsuleWires() (6 input parameters)
Param[4]: slices (type: int)
Param[5]: rings (type: int)
Param[6]: color (type: Color)
-Function 455: DrawPlane() (3 input parameters)
+Function 457: DrawPlane() (3 input parameters)
Name: DrawPlane
Return type: void
Description: Draw a plane XZ
Param[1]: centerPos (type: Vector3)
Param[2]: size (type: Vector2)
Param[3]: color (type: Color)
-Function 456: DrawRay() (2 input parameters)
+Function 458: DrawRay() (2 input parameters)
Name: DrawRay
Return type: void
Description: Draw a ray line
Param[1]: ray (type: Ray)
Param[2]: color (type: Color)
-Function 457: DrawGrid() (2 input parameters)
+Function 459: DrawGrid() (2 input parameters)
Name: DrawGrid
Return type: void
Description: Draw a grid (centered at (0, 0, 0))
Param[1]: slices (type: int)
Param[2]: spacing (type: float)
-Function 458: LoadModel() (1 input parameters)
+Function 460: LoadModel() (1 input parameters)
Name: LoadModel
Return type: Model
Description: Load model from files (meshes and materials)
Param[1]: fileName (type: const char *)
-Function 459: LoadModelFromMesh() (1 input parameters)
+Function 461: LoadModelFromMesh() (1 input parameters)
Name: LoadModelFromMesh
Return type: Model
Description: Load model from generated mesh (default material)
Param[1]: mesh (type: Mesh)
-Function 460: IsModelReady() (1 input parameters)
- Name: IsModelReady
+Function 462: IsModelValid() (1 input parameters)
+ Name: IsModelValid
Return type: bool
- Description: Check if a model is ready
+ Description: Check if a model is valid (loaded in GPU, VAO/VBOs)
Param[1]: model (type: Model)
-Function 461: UnloadModel() (1 input parameters)
+Function 463: UnloadModel() (1 input parameters)
Name: UnloadModel
Return type: void
Description: Unload model (including meshes) from memory (RAM and/or VRAM)
Param[1]: model (type: Model)
-Function 462: GetModelBoundingBox() (1 input parameters)
+Function 464: GetModelBoundingBox() (1 input parameters)
Name: GetModelBoundingBox
Return type: BoundingBox
Description: Compute model bounding box limits (considers all meshes)
Param[1]: model (type: Model)
-Function 463: DrawModel() (4 input parameters)
+Function 465: DrawModel() (4 input parameters)
Name: DrawModel
Return type: void
Description: Draw a model (with texture if set)
@@ -3944,7 +3955,7 @@ Function 463: DrawModel() (4 input parameters)
Param[2]: position (type: Vector3)
Param[3]: scale (type: float)
Param[4]: tint (type: Color)
-Function 464: DrawModelEx() (6 input parameters)
+Function 466: DrawModelEx() (6 input parameters)
Name: DrawModelEx
Return type: void
Description: Draw a model with extended parameters
@@ -3954,7 +3965,7 @@ Function 464: DrawModelEx() (6 input parameters)
Param[4]: rotationAngle (type: float)
Param[5]: scale (type: Vector3)
Param[6]: tint (type: Color)
-Function 465: DrawModelWires() (4 input parameters)
+Function 467: DrawModelWires() (4 input parameters)
Name: DrawModelWires
Return type: void
Description: Draw a model wires (with texture if set)
@@ -3962,7 +3973,7 @@ Function 465: DrawModelWires() (4 input parameters)
Param[2]: position (type: Vector3)
Param[3]: scale (type: float)
Param[4]: tint (type: Color)
-Function 466: DrawModelWiresEx() (6 input parameters)
+Function 468: DrawModelWiresEx() (6 input parameters)
Name: DrawModelWiresEx
Return type: void
Description: Draw a model wires (with texture if set) with extended parameters
@@ -3972,7 +3983,7 @@ Function 466: DrawModelWiresEx() (6 input parameters)
Param[4]: rotationAngle (type: float)
Param[5]: scale (type: Vector3)
Param[6]: tint (type: Color)
-Function 467: DrawModelPoints() (4 input parameters)
+Function 469: DrawModelPoints() (4 input parameters)
Name: DrawModelPoints
Return type: void
Description: Draw a model as points
@@ -3980,7 +3991,7 @@ Function 467: DrawModelPoints() (4 input parameters)
Param[2]: position (type: Vector3)
Param[3]: scale (type: float)
Param[4]: tint (type: Color)
-Function 468: DrawModelPointsEx() (6 input parameters)
+Function 470: DrawModelPointsEx() (6 input parameters)
Name: DrawModelPointsEx
Return type: void
Description: Draw a model as points with extended parameters
@@ -3990,13 +4001,13 @@ Function 468: DrawModelPointsEx() (6 input parameters)
Param[4]: rotationAngle (type: float)
Param[5]: scale (type: Vector3)
Param[6]: tint (type: Color)
-Function 469: DrawBoundingBox() (2 input parameters)
+Function 471: DrawBoundingBox() (2 input parameters)
Name: DrawBoundingBox
Return type: void
Description: Draw bounding box (wires)
Param[1]: box (type: BoundingBox)
Param[2]: color (type: Color)
-Function 470: DrawBillboard() (5 input parameters)
+Function 472: DrawBillboard() (5 input parameters)
Name: DrawBillboard
Return type: void
Description: Draw a billboard texture
@@ -4005,7 +4016,7 @@ Function 470: DrawBillboard() (5 input parameters)
Param[3]: position (type: Vector3)
Param[4]: scale (type: float)
Param[5]: tint (type: Color)
-Function 471: DrawBillboardRec() (6 input parameters)
+Function 473: DrawBillboardRec() (6 input parameters)
Name: DrawBillboardRec
Return type: void
Description: Draw a billboard texture defined by source
@@ -4015,7 +4026,7 @@ Function 471: DrawBillboardRec() (6 input parameters)
Param[4]: position (type: Vector3)
Param[5]: size (type: Vector2)
Param[6]: tint (type: Color)
-Function 472: DrawBillboardPro() (9 input parameters)
+Function 474: DrawBillboardPro() (9 input parameters)
Name: DrawBillboardPro
Return type: void
Description: Draw a billboard texture defined by source and rotation
@@ -4028,13 +4039,13 @@ Function 472: DrawBillboardPro() (9 input parameters)
Param[7]: origin (type: Vector2)
Param[8]: rotation (type: float)
Param[9]: tint (type: Color)
-Function 473: UploadMesh() (2 input parameters)
+Function 475: UploadMesh() (2 input parameters)
Name: UploadMesh
Return type: void
Description: Upload mesh vertex data in GPU and provide VAO/VBO ids
Param[1]: mesh (type: Mesh *)
Param[2]: dynamic (type: bool)
-Function 474: UpdateMeshBuffer() (5 input parameters)
+Function 476: UpdateMeshBuffer() (5 input parameters)
Name: UpdateMeshBuffer
Return type: void
Description: Update mesh vertex data in GPU for a specific buffer index
@@ -4043,19 +4054,19 @@ Function 474: UpdateMeshBuffer() (5 input parameters)
Param[3]: data (type: const void *)
Param[4]: dataSize (type: int)
Param[5]: offset (type: int)
-Function 475: UnloadMesh() (1 input parameters)
+Function 477: UnloadMesh() (1 input parameters)
Name: UnloadMesh
Return type: void
Description: Unload mesh data from CPU and GPU
Param[1]: mesh (type: Mesh)
-Function 476: DrawMesh() (3 input parameters)
+Function 478: DrawMesh() (3 input parameters)
Name: DrawMesh
Return type: void
Description: Draw a 3d mesh with material and transform
Param[1]: mesh (type: Mesh)
Param[2]: material (type: Material)
Param[3]: transform (type: Matrix)
-Function 477: DrawMeshInstanced() (4 input parameters)
+Function 479: DrawMeshInstanced() (4 input parameters)
Name: DrawMeshInstanced
Return type: void
Description: Draw multiple mesh instances with material and different transforms
@@ -4063,35 +4074,35 @@ Function 477: DrawMeshInstanced() (4 input parameters)
Param[2]: material (type: Material)
Param[3]: transforms (type: const Matrix *)
Param[4]: instances (type: int)
-Function 478: GetMeshBoundingBox() (1 input parameters)
+Function 480: GetMeshBoundingBox() (1 input parameters)
Name: GetMeshBoundingBox
Return type: BoundingBox
Description: Compute mesh bounding box limits
Param[1]: mesh (type: Mesh)
-Function 479: GenMeshTangents() (1 input parameters)
+Function 481: GenMeshTangents() (1 input parameters)
Name: GenMeshTangents
Return type: void
Description: Compute mesh tangents
Param[1]: mesh (type: Mesh *)
-Function 480: ExportMesh() (2 input parameters)
+Function 482: ExportMesh() (2 input parameters)
Name: ExportMesh
Return type: bool
Description: Export mesh data to file, returns true on success
Param[1]: mesh (type: Mesh)
Param[2]: fileName (type: const char *)
-Function 481: ExportMeshAsCode() (2 input parameters)
+Function 483: ExportMeshAsCode() (2 input parameters)
Name: ExportMeshAsCode
Return type: bool
Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes
Param[1]: mesh (type: Mesh)
Param[2]: fileName (type: const char *)
-Function 482: GenMeshPoly() (2 input parameters)
+Function 484: GenMeshPoly() (2 input parameters)
Name: GenMeshPoly
Return type: Mesh
Description: Generate polygonal mesh
Param[1]: sides (type: int)
Param[2]: radius (type: float)
-Function 483: GenMeshPlane() (4 input parameters)
+Function 485: GenMeshPlane() (4 input parameters)
Name: GenMeshPlane
Return type: Mesh
Description: Generate plane mesh (with subdivisions)
@@ -4099,42 +4110,42 @@ Function 483: GenMeshPlane() (4 input parameters)
Param[2]: length (type: float)
Param[3]: resX (type: int)
Param[4]: resZ (type: int)
-Function 484: GenMeshCube() (3 input parameters)
+Function 486: GenMeshCube() (3 input parameters)
Name: GenMeshCube
Return type: Mesh
Description: Generate cuboid mesh
Param[1]: width (type: float)
Param[2]: height (type: float)
Param[3]: length (type: float)
-Function 485: GenMeshSphere() (3 input parameters)
+Function 487: GenMeshSphere() (3 input parameters)
Name: GenMeshSphere
Return type: Mesh
Description: Generate sphere mesh (standard sphere)
Param[1]: radius (type: float)
Param[2]: rings (type: int)
Param[3]: slices (type: int)
-Function 486: GenMeshHemiSphere() (3 input parameters)
+Function 488: GenMeshHemiSphere() (3 input parameters)
Name: GenMeshHemiSphere
Return type: Mesh
Description: Generate half-sphere mesh (no bottom cap)
Param[1]: radius (type: float)
Param[2]: rings (type: int)
Param[3]: slices (type: int)
-Function 487: GenMeshCylinder() (3 input parameters)
+Function 489: GenMeshCylinder() (3 input parameters)
Name: GenMeshCylinder
Return type: Mesh
Description: Generate cylinder mesh
Param[1]: radius (type: float)
Param[2]: height (type: float)
Param[3]: slices (type: int)
-Function 488: GenMeshCone() (3 input parameters)
+Function 490: GenMeshCone() (3 input parameters)
Name: GenMeshCone
Return type: Mesh
Description: Generate cone/pyramid mesh
Param[1]: radius (type: float)
Param[2]: height (type: float)
Param[3]: slices (type: int)
-Function 489: GenMeshTorus() (4 input parameters)
+Function 491: GenMeshTorus() (4 input parameters)
Name: GenMeshTorus
Return type: Mesh
Description: Generate torus mesh
@@ -4142,7 +4153,7 @@ Function 489: GenMeshTorus() (4 input parameters)
Param[2]: size (type: float)
Param[3]: radSeg (type: int)
Param[4]: sides (type: int)
-Function 490: GenMeshKnot() (4 input parameters)
+Function 492: GenMeshKnot() (4 input parameters)
Name: GenMeshKnot
Return type: Mesh
Description: Generate trefoil knot mesh
@@ -4150,91 +4161,91 @@ Function 490: GenMeshKnot() (4 input parameters)
Param[2]: size (type: float)
Param[3]: radSeg (type: int)
Param[4]: sides (type: int)
-Function 491: GenMeshHeightmap() (2 input parameters)
+Function 493: GenMeshHeightmap() (2 input parameters)
Name: GenMeshHeightmap
Return type: Mesh
Description: Generate heightmap mesh from image data
Param[1]: heightmap (type: Image)
Param[2]: size (type: Vector3)
-Function 492: GenMeshCubicmap() (2 input parameters)
+Function 494: GenMeshCubicmap() (2 input parameters)
Name: GenMeshCubicmap
Return type: Mesh
Description: Generate cubes-based map mesh from image data
Param[1]: cubicmap (type: Image)
Param[2]: cubeSize (type: Vector3)
-Function 493: LoadMaterials() (2 input parameters)
+Function 495: LoadMaterials() (2 input parameters)
Name: LoadMaterials
Return type: Material *
Description: Load materials from model file
Param[1]: fileName (type: const char *)
Param[2]: materialCount (type: int *)
-Function 494: LoadMaterialDefault() (0 input parameters)
+Function 496: LoadMaterialDefault() (0 input parameters)
Name: LoadMaterialDefault
Return type: Material
Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
No input parameters
-Function 495: IsMaterialReady() (1 input parameters)
- Name: IsMaterialReady
+Function 497: IsMaterialValid() (1 input parameters)
+ Name: IsMaterialValid
Return type: bool
- Description: Check if a material is ready
+ Description: Check if a material is valid (shader assigned, map textures loaded in GPU)
Param[1]: material (type: Material)
-Function 496: UnloadMaterial() (1 input parameters)
+Function 498: UnloadMaterial() (1 input parameters)
Name: UnloadMaterial
Return type: void
Description: Unload material from GPU memory (VRAM)
Param[1]: material (type: Material)
-Function 497: SetMaterialTexture() (3 input parameters)
+Function 499: SetMaterialTexture() (3 input parameters)
Name: SetMaterialTexture
Return type: void
Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
Param[1]: material (type: Material *)
Param[2]: mapType (type: int)
Param[3]: texture (type: Texture2D)
-Function 498: SetModelMeshMaterial() (3 input parameters)
+Function 500: SetModelMeshMaterial() (3 input parameters)
Name: SetModelMeshMaterial
Return type: void
Description: Set material for a mesh
Param[1]: model (type: Model *)
Param[2]: meshId (type: int)
Param[3]: materialId (type: int)
-Function 499: LoadModelAnimations() (2 input parameters)
+Function 501: LoadModelAnimations() (2 input parameters)
Name: LoadModelAnimations
Return type: ModelAnimation *
Description: Load model animations from file
Param[1]: fileName (type: const char *)
Param[2]: animCount (type: int *)
-Function 500: UpdateModelAnimation() (3 input parameters)
+Function 502: UpdateModelAnimation() (3 input parameters)
Name: UpdateModelAnimation
Return type: void
Description: Update model animation pose
Param[1]: model (type: Model)
Param[2]: anim (type: ModelAnimation)
Param[3]: frame (type: int)
-Function 501: UnloadModelAnimation() (1 input parameters)
+Function 503: UnloadModelAnimation() (1 input parameters)
Name: UnloadModelAnimation
Return type: void
Description: Unload animation data
Param[1]: anim (type: ModelAnimation)
-Function 502: UnloadModelAnimations() (2 input parameters)
+Function 504: UnloadModelAnimations() (2 input parameters)
Name: UnloadModelAnimations
Return type: void
Description: Unload animation array data
Param[1]: animations (type: ModelAnimation *)
Param[2]: animCount (type: int)
-Function 503: IsModelAnimationValid() (2 input parameters)
+Function 505: IsModelAnimationValid() (2 input parameters)
Name: IsModelAnimationValid
Return type: bool
Description: Check model animation skeleton match
Param[1]: model (type: Model)
Param[2]: anim (type: ModelAnimation)
-Function 504: UpdateModelAnimationBoneMatrices() (3 input parameters)
+Function 506: UpdateModelAnimationBoneMatrices() (3 input parameters)
Name: UpdateModelAnimationBoneMatrices
Return type: void
Description: Update model animation mesh bone matrices (Note GPU skinning does not work on Mac)
Param[1]: model (type: Model)
Param[2]: anim (type: ModelAnimation)
Param[3]: frame (type: int)
-Function 505: CheckCollisionSpheres() (4 input parameters)
+Function 507: CheckCollisionSpheres() (4 input parameters)
Name: CheckCollisionSpheres
Return type: bool
Description: Check collision between two spheres
@@ -4242,40 +4253,40 @@ Function 505: CheckCollisionSpheres() (4 input parameters)
Param[2]: radius1 (type: float)
Param[3]: center2 (type: Vector3)
Param[4]: radius2 (type: float)
-Function 506: CheckCollisionBoxes() (2 input parameters)
+Function 508: CheckCollisionBoxes() (2 input parameters)
Name: CheckCollisionBoxes
Return type: bool
Description: Check collision between two bounding boxes
Param[1]: box1 (type: BoundingBox)
Param[2]: box2 (type: BoundingBox)
-Function 507: CheckCollisionBoxSphere() (3 input parameters)
+Function 509: CheckCollisionBoxSphere() (3 input parameters)
Name: CheckCollisionBoxSphere
Return type: bool
Description: Check collision between box and sphere
Param[1]: box (type: BoundingBox)
Param[2]: center (type: Vector3)
Param[3]: radius (type: float)
-Function 508: GetRayCollisionSphere() (3 input parameters)
+Function 510: GetRayCollisionSphere() (3 input parameters)
Name: GetRayCollisionSphere
Return type: RayCollision
Description: Get collision info between ray and sphere
Param[1]: ray (type: Ray)
Param[2]: center (type: Vector3)
Param[3]: radius (type: float)
-Function 509: GetRayCollisionBox() (2 input parameters)
+Function 511: GetRayCollisionBox() (2 input parameters)
Name: GetRayCollisionBox
Return type: RayCollision
Description: Get collision info between ray and box
Param[1]: ray (type: Ray)
Param[2]: box (type: BoundingBox)
-Function 510: GetRayCollisionMesh() (3 input parameters)
+Function 512: GetRayCollisionMesh() (3 input parameters)
Name: GetRayCollisionMesh
Return type: RayCollision
Description: Get collision info between ray and mesh
Param[1]: ray (type: Ray)
Param[2]: mesh (type: Mesh)
Param[3]: transform (type: Matrix)
-Function 511: GetRayCollisionTriangle() (4 input parameters)
+Function 513: GetRayCollisionTriangle() (4 input parameters)
Name: GetRayCollisionTriangle
Return type: RayCollision
Description: Get collision info between ray and triangle
@@ -4283,7 +4294,7 @@ Function 511: GetRayCollisionTriangle() (4 input parameters)
Param[2]: p1 (type: Vector3)
Param[3]: p2 (type: Vector3)
Param[4]: p3 (type: Vector3)
-Function 512: GetRayCollisionQuad() (5 input parameters)
+Function 514: GetRayCollisionQuad() (5 input parameters)
Name: GetRayCollisionQuad
Return type: RayCollision
Description: Get collision info between ray and quad
@@ -4292,158 +4303,158 @@ Function 512: GetRayCollisionQuad() (5 input parameters)
Param[3]: p2 (type: Vector3)
Param[4]: p3 (type: Vector3)
Param[5]: p4 (type: Vector3)
-Function 513: InitAudioDevice() (0 input parameters)
+Function 515: InitAudioDevice() (0 input parameters)
Name: InitAudioDevice
Return type: void
Description: Initialize audio device and context
No input parameters
-Function 514: CloseAudioDevice() (0 input parameters)
+Function 516: CloseAudioDevice() (0 input parameters)
Name: CloseAudioDevice
Return type: void
Description: Close the audio device and context
No input parameters
-Function 515: IsAudioDeviceReady() (0 input parameters)
+Function 517: IsAudioDeviceReady() (0 input parameters)
Name: IsAudioDeviceReady
Return type: bool
Description: Check if audio device has been initialized successfully
No input parameters
-Function 516: SetMasterVolume() (1 input parameters)
+Function 518: SetMasterVolume() (1 input parameters)
Name: SetMasterVolume
Return type: void
Description: Set master volume (listener)
Param[1]: volume (type: float)
-Function 517: GetMasterVolume() (0 input parameters)
+Function 519: GetMasterVolume() (0 input parameters)
Name: GetMasterVolume
Return type: float
Description: Get master volume (listener)
No input parameters
-Function 518: LoadWave() (1 input parameters)
+Function 520: LoadWave() (1 input parameters)
Name: LoadWave
Return type: Wave
Description: Load wave data from file
Param[1]: fileName (type: const char *)
-Function 519: LoadWaveFromMemory() (3 input parameters)
+Function 521: LoadWaveFromMemory() (3 input parameters)
Name: LoadWaveFromMemory
Return type: Wave
Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
Param[1]: fileType (type: const char *)
Param[2]: fileData (type: const unsigned char *)
Param[3]: dataSize (type: int)
-Function 520: IsWaveReady() (1 input parameters)
- Name: IsWaveReady
+Function 522: IsWaveValid() (1 input parameters)
+ Name: IsWaveValid
Return type: bool
- Description: Checks if wave data is ready
+ Description: Checks if wave data is valid (data loaded and parameters)
Param[1]: wave (type: Wave)
-Function 521: LoadSound() (1 input parameters)
+Function 523: LoadSound() (1 input parameters)
Name: LoadSound
Return type: Sound
Description: Load sound from file
Param[1]: fileName (type: const char *)
-Function 522: LoadSoundFromWave() (1 input parameters)
+Function 524: LoadSoundFromWave() (1 input parameters)
Name: LoadSoundFromWave
Return type: Sound
Description: Load sound from wave data
Param[1]: wave (type: Wave)
-Function 523: LoadSoundAlias() (1 input parameters)
+Function 525: LoadSoundAlias() (1 input parameters)
Name: LoadSoundAlias
Return type: Sound
Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data
Param[1]: source (type: Sound)
-Function 524: IsSoundReady() (1 input parameters)
- Name: IsSoundReady
+Function 526: IsSoundValid() (1 input parameters)
+ Name: IsSoundValid
Return type: bool
- Description: Checks if a sound is ready
+ Description: Checks if a sound is valid (data loaded and buffers initialized)
Param[1]: sound (type: Sound)
-Function 525: UpdateSound() (3 input parameters)
+Function 527: UpdateSound() (3 input parameters)
Name: UpdateSound
Return type: void
Description: Update sound buffer with new data
Param[1]: sound (type: Sound)
Param[2]: data (type: const void *)
Param[3]: sampleCount (type: int)
-Function 526: UnloadWave() (1 input parameters)
+Function 528: UnloadWave() (1 input parameters)
Name: UnloadWave
Return type: void
Description: Unload wave data
Param[1]: wave (type: Wave)
-Function 527: UnloadSound() (1 input parameters)
+Function 529: UnloadSound() (1 input parameters)
Name: UnloadSound
Return type: void
Description: Unload sound
Param[1]: sound (type: Sound)
-Function 528: UnloadSoundAlias() (1 input parameters)
+Function 530: UnloadSoundAlias() (1 input parameters)
Name: UnloadSoundAlias
Return type: void
Description: Unload a sound alias (does not deallocate sample data)
Param[1]: alias (type: Sound)
-Function 529: ExportWave() (2 input parameters)
+Function 531: ExportWave() (2 input parameters)
Name: ExportWave
Return type: bool
Description: Export wave data to file, returns true on success
Param[1]: wave (type: Wave)
Param[2]: fileName (type: const char *)
-Function 530: ExportWaveAsCode() (2 input parameters)
+Function 532: ExportWaveAsCode() (2 input parameters)
Name: ExportWaveAsCode
Return type: bool
Description: Export wave sample data to code (.h), returns true on success
Param[1]: wave (type: Wave)
Param[2]: fileName (type: const char *)
-Function 531: PlaySound() (1 input parameters)
+Function 533: PlaySound() (1 input parameters)
Name: PlaySound
Return type: void
Description: Play a sound
Param[1]: sound (type: Sound)
-Function 532: StopSound() (1 input parameters)
+Function 534: StopSound() (1 input parameters)
Name: StopSound
Return type: void
Description: Stop playing a sound
Param[1]: sound (type: Sound)
-Function 533: PauseSound() (1 input parameters)
+Function 535: PauseSound() (1 input parameters)
Name: PauseSound
Return type: void
Description: Pause a sound
Param[1]: sound (type: Sound)
-Function 534: ResumeSound() (1 input parameters)
+Function 536: ResumeSound() (1 input parameters)
Name: ResumeSound
Return type: void
Description: Resume a paused sound
Param[1]: sound (type: Sound)
-Function 535: IsSoundPlaying() (1 input parameters)
+Function 537: IsSoundPlaying() (1 input parameters)
Name: IsSoundPlaying
Return type: bool
Description: Check if a sound is currently playing
Param[1]: sound (type: Sound)
-Function 536: SetSoundVolume() (2 input parameters)
+Function 538: SetSoundVolume() (2 input parameters)
Name: SetSoundVolume
Return type: void
Description: Set volume for a sound (1.0 is max level)
Param[1]: sound (type: Sound)
Param[2]: volume (type: float)
-Function 537: SetSoundPitch() (2 input parameters)
+Function 539: SetSoundPitch() (2 input parameters)
Name: SetSoundPitch
Return type: void
Description: Set pitch for a sound (1.0 is base level)
Param[1]: sound (type: Sound)
Param[2]: pitch (type: float)
-Function 538: SetSoundPan() (2 input parameters)
+Function 540: SetSoundPan() (2 input parameters)
Name: SetSoundPan
Return type: void
Description: Set pan for a sound (0.5 is center)
Param[1]: sound (type: Sound)
Param[2]: pan (type: float)
-Function 539: WaveCopy() (1 input parameters)
+Function 541: WaveCopy() (1 input parameters)
Name: WaveCopy
Return type: Wave
Description: Copy a wave to a new wave
Param[1]: wave (type: Wave)
-Function 540: WaveCrop() (3 input parameters)
+Function 542: WaveCrop() (3 input parameters)
Name: WaveCrop
Return type: void
Description: Crop a wave to defined frames range
Param[1]: wave (type: Wave *)
Param[2]: initFrame (type: int)
Param[3]: finalFrame (type: int)
-Function 541: WaveFormat() (4 input parameters)
+Function 543: WaveFormat() (4 input parameters)
Name: WaveFormat
Return type: void
Description: Convert wave data to desired format
@@ -4451,203 +4462,203 @@ Function 541: WaveFormat() (4 input parameters)
Param[2]: sampleRate (type: int)
Param[3]: sampleSize (type: int)
Param[4]: channels (type: int)
-Function 542: LoadWaveSamples() (1 input parameters)
+Function 544: LoadWaveSamples() (1 input parameters)
Name: LoadWaveSamples
Return type: float *
Description: Load samples data from wave as a 32bit float data array
Param[1]: wave (type: Wave)
-Function 543: UnloadWaveSamples() (1 input parameters)
+Function 545: UnloadWaveSamples() (1 input parameters)
Name: UnloadWaveSamples
Return type: void
Description: Unload samples data loaded with LoadWaveSamples()
Param[1]: samples (type: float *)
-Function 544: LoadMusicStream() (1 input parameters)
+Function 546: LoadMusicStream() (1 input parameters)
Name: LoadMusicStream
Return type: Music
Description: Load music stream from file
Param[1]: fileName (type: const char *)
-Function 545: LoadMusicStreamFromMemory() (3 input parameters)
+Function 547: LoadMusicStreamFromMemory() (3 input parameters)
Name: LoadMusicStreamFromMemory
Return type: Music
Description: Load music stream from data
Param[1]: fileType (type: const char *)
Param[2]: data (type: const unsigned char *)
Param[3]: dataSize (type: int)
-Function 546: IsMusicReady() (1 input parameters)
- Name: IsMusicReady
+Function 548: IsMusicValid() (1 input parameters)
+ Name: IsMusicValid
Return type: bool
- Description: Checks if a music stream is ready
+ Description: Checks if a music stream is valid (context and buffers initialized)
Param[1]: music (type: Music)
-Function 547: UnloadMusicStream() (1 input parameters)
+Function 549: UnloadMusicStream() (1 input parameters)
Name: UnloadMusicStream
Return type: void
Description: Unload music stream
Param[1]: music (type: Music)
-Function 548: PlayMusicStream() (1 input parameters)
+Function 550: PlayMusicStream() (1 input parameters)
Name: PlayMusicStream
Return type: void
Description: Start music playing
Param[1]: music (type: Music)
-Function 549: IsMusicStreamPlaying() (1 input parameters)
+Function 551: IsMusicStreamPlaying() (1 input parameters)
Name: IsMusicStreamPlaying
Return type: bool
Description: Check if music is playing
Param[1]: music (type: Music)
-Function 550: UpdateMusicStream() (1 input parameters)
+Function 552: UpdateMusicStream() (1 input parameters)
Name: UpdateMusicStream
Return type: void
Description: Updates buffers for music streaming
Param[1]: music (type: Music)
-Function 551: StopMusicStream() (1 input parameters)
+Function 553: StopMusicStream() (1 input parameters)
Name: StopMusicStream
Return type: void
Description: Stop music playing
Param[1]: music (type: Music)
-Function 552: PauseMusicStream() (1 input parameters)
+Function 554: PauseMusicStream() (1 input parameters)
Name: PauseMusicStream
Return type: void
Description: Pause music playing
Param[1]: music (type: Music)
-Function 553: ResumeMusicStream() (1 input parameters)
+Function 555: ResumeMusicStream() (1 input parameters)
Name: ResumeMusicStream
Return type: void
Description: Resume playing paused music
Param[1]: music (type: Music)
-Function 554: SeekMusicStream() (2 input parameters)
+Function 556: SeekMusicStream() (2 input parameters)
Name: SeekMusicStream
Return type: void
Description: Seek music to a position (in seconds)
Param[1]: music (type: Music)
Param[2]: position (type: float)
-Function 555: SetMusicVolume() (2 input parameters)
+Function 557: SetMusicVolume() (2 input parameters)
Name: SetMusicVolume
Return type: void
Description: Set volume for music (1.0 is max level)
Param[1]: music (type: Music)
Param[2]: volume (type: float)
-Function 556: SetMusicPitch() (2 input parameters)
+Function 558: SetMusicPitch() (2 input parameters)
Name: SetMusicPitch
Return type: void
Description: Set pitch for a music (1.0 is base level)
Param[1]: music (type: Music)
Param[2]: pitch (type: float)
-Function 557: SetMusicPan() (2 input parameters)
+Function 559: SetMusicPan() (2 input parameters)
Name: SetMusicPan
Return type: void
Description: Set pan for a music (0.5 is center)
Param[1]: music (type: Music)
Param[2]: pan (type: float)
-Function 558: GetMusicTimeLength() (1 input parameters)
+Function 560: GetMusicTimeLength() (1 input parameters)
Name: GetMusicTimeLength
Return type: float
Description: Get music time length (in seconds)
Param[1]: music (type: Music)
-Function 559: GetMusicTimePlayed() (1 input parameters)
+Function 561: GetMusicTimePlayed() (1 input parameters)
Name: GetMusicTimePlayed
Return type: float
Description: Get current music time played (in seconds)
Param[1]: music (type: Music)
-Function 560: LoadAudioStream() (3 input parameters)
+Function 562: LoadAudioStream() (3 input parameters)
Name: LoadAudioStream
Return type: AudioStream
Description: Load audio stream (to stream raw audio pcm data)
Param[1]: sampleRate (type: unsigned int)
Param[2]: sampleSize (type: unsigned int)
Param[3]: channels (type: unsigned int)
-Function 561: IsAudioStreamReady() (1 input parameters)
- Name: IsAudioStreamReady
+Function 563: IsAudioStreamValid() (1 input parameters)
+ Name: IsAudioStreamValid
Return type: bool
- Description: Checks if an audio stream is ready
+ Description: Checks if an audio stream is valid (buffers initialized)
Param[1]: stream (type: AudioStream)
-Function 562: UnloadAudioStream() (1 input parameters)
+Function 564: UnloadAudioStream() (1 input parameters)
Name: UnloadAudioStream
Return type: void
Description: Unload audio stream and free memory
Param[1]: stream (type: AudioStream)
-Function 563: UpdateAudioStream() (3 input parameters)
+Function 565: UpdateAudioStream() (3 input parameters)
Name: UpdateAudioStream
Return type: void
Description: Update audio stream buffers with data
Param[1]: stream (type: AudioStream)
Param[2]: data (type: const void *)
Param[3]: frameCount (type: int)
-Function 564: IsAudioStreamProcessed() (1 input parameters)
+Function 566: IsAudioStreamProcessed() (1 input parameters)
Name: IsAudioStreamProcessed
Return type: bool
Description: Check if any audio stream buffers requires refill
Param[1]: stream (type: AudioStream)
-Function 565: PlayAudioStream() (1 input parameters)
+Function 567: PlayAudioStream() (1 input parameters)
Name: PlayAudioStream
Return type: void
Description: Play audio stream
Param[1]: stream (type: AudioStream)
-Function 566: PauseAudioStream() (1 input parameters)
+Function 568: PauseAudioStream() (1 input parameters)
Name: PauseAudioStream
Return type: void
Description: Pause audio stream
Param[1]: stream (type: AudioStream)
-Function 567: ResumeAudioStream() (1 input parameters)
+Function 569: ResumeAudioStream() (1 input parameters)
Name: ResumeAudioStream
Return type: void
Description: Resume audio stream
Param[1]: stream (type: AudioStream)
-Function 568: IsAudioStreamPlaying() (1 input parameters)
+Function 570: IsAudioStreamPlaying() (1 input parameters)
Name: IsAudioStreamPlaying
Return type: bool
Description: Check if audio stream is playing
Param[1]: stream (type: AudioStream)
-Function 569: StopAudioStream() (1 input parameters)
+Function 571: StopAudioStream() (1 input parameters)
Name: StopAudioStream
Return type: void
Description: Stop audio stream
Param[1]: stream (type: AudioStream)
-Function 570: SetAudioStreamVolume() (2 input parameters)
+Function 572: SetAudioStreamVolume() (2 input parameters)
Name: SetAudioStreamVolume
Return type: void
Description: Set volume for audio stream (1.0 is max level)
Param[1]: stream (type: AudioStream)
Param[2]: volume (type: float)
-Function 571: SetAudioStreamPitch() (2 input parameters)
+Function 573: SetAudioStreamPitch() (2 input parameters)
Name: SetAudioStreamPitch
Return type: void
Description: Set pitch for audio stream (1.0 is base level)
Param[1]: stream (type: AudioStream)
Param[2]: pitch (type: float)
-Function 572: SetAudioStreamPan() (2 input parameters)
+Function 574: SetAudioStreamPan() (2 input parameters)
Name: SetAudioStreamPan
Return type: void
Description: Set pan for audio stream (0.5 is centered)
Param[1]: stream (type: AudioStream)
Param[2]: pan (type: float)
-Function 573: SetAudioStreamBufferSizeDefault() (1 input parameters)
+Function 575: SetAudioStreamBufferSizeDefault() (1 input parameters)
Name: SetAudioStreamBufferSizeDefault
Return type: void
Description: Default size for new audio streams
Param[1]: size (type: int)
-Function 574: SetAudioStreamCallback() (2 input parameters)
+Function 576: SetAudioStreamCallback() (2 input parameters)
Name: SetAudioStreamCallback
Return type: void
Description: Audio thread callback to request new data
Param[1]: stream (type: AudioStream)
Param[2]: callback (type: AudioCallback)
-Function 575: AttachAudioStreamProcessor() (2 input parameters)
+Function 577: AttachAudioStreamProcessor() (2 input parameters)
Name: AttachAudioStreamProcessor
Return type: void
Description: Attach audio stream processor to stream, receives the samples as 'float'
Param[1]: stream (type: AudioStream)
Param[2]: processor (type: AudioCallback)
-Function 576: DetachAudioStreamProcessor() (2 input parameters)
+Function 578: DetachAudioStreamProcessor() (2 input parameters)
Name: DetachAudioStreamProcessor
Return type: void
Description: Detach audio stream processor from stream
Param[1]: stream (type: AudioStream)
Param[2]: processor (type: AudioCallback)
-Function 577: AttachAudioMixedProcessor() (1 input parameters)
+Function 579: AttachAudioMixedProcessor() (1 input parameters)
Name: AttachAudioMixedProcessor
Return type: void
Description: Attach audio stream processor to the entire audio pipeline, receives the samples as 'float'
Param[1]: processor (type: AudioCallback)
-Function 578: DetachAudioMixedProcessor() (1 input parameters)
+Function 580: DetachAudioMixedProcessor() (1 input parameters)
Name: DetachAudioMixedProcessor
Return type: void
Description: Detach audio stream processor from the entire audio pipeline
diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml
index 895680f2c..f59faf754 100644
--- a/parser/output/raylib_api.xml
+++ b/parser/output/raylib_api.xml
@@ -675,7 +675,7 @@
-
+
@@ -871,7 +871,7 @@
-
+
@@ -1126,6 +1126,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1269,7 +1281,7 @@
-
+
@@ -1699,11 +1711,6 @@
-
-
-
-
-
@@ -1724,7 +1731,7 @@
-
+
@@ -2109,13 +2116,13 @@
-
+
-
+
@@ -2273,7 +2280,7 @@
-
+
@@ -2613,7 +2620,7 @@
-
+
@@ -2794,7 +2801,7 @@
-
+
@@ -2896,7 +2903,7 @@
-
+
@@ -2908,7 +2915,7 @@
-
+
@@ -2988,7 +2995,7 @@
-
+
@@ -3039,7 +3046,7 @@
-
+
diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln
index 2b262bcfe..1dbd38984 100644
--- a/projects/VS2022/raylib.sln
+++ b/projects/VS2022/raylib.sln
@@ -293,8 +293,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_texture_outline", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_texture_tiling", "examples\shaders_texture_tiling.vcxproj", "{EFA150D4-F93B-4D7D-A69C-9E8B4663BECD}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "textures_svg_loading", "examples\textures_svg_loading.vcxproj", "{D8026C60-CCBC-45DF-9085-BF21569EB414}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_splines_drawing", "examples\shapes_splines_drawing.vcxproj", "{DF25E545-00FF-4E64-844C-7DF98991F901}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_top_down_lights", "examples\shapes_top_down_lights.vcxproj", "{703BE7BA-5B99-4F70-806D-3A259F6A991E}"
diff --git a/projects/VSCode/Makefile b/projects/VSCode/Makefile
index 2f43c9ead..86febfba0 100644
--- a/projects/VSCode/Makefile
+++ b/projects/VSCode/Makefile
@@ -352,9 +352,9 @@ SRC_DIR = src
OBJ_DIR = obj
# Define all object files from source files
-SRC = $(call rwildcard, *.c, *.h)
+SRC = $(call rwildcard, ./, *.c, *.h)
#OBJS = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
-OBJS ?= main.c
+OBJS = $(patsubst %.c,%.o,$(filter %.c,$(SRC)))
# For Android platform we call a custom Makefile.Android
ifeq ($(PLATFORM),PLATFORM_ANDROID)
diff --git a/src/Makefile b/src/Makefile
index 4740f1f01..137c28b53 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -109,8 +109,9 @@ RAYLIB_MODULE_RAYGUI_PATH ?= $(RAYLIB_SRC_PATH)/../../raygui/src
# Use external GLFW library instead of rglfw module
USE_EXTERNAL_GLFW ?= FALSE
-# Enable support for both Wayland and X11 by default on Linux when using GLFW
-GLFW_LINUX_ENABLE_WAYLAND ?= TRUE
+# Enable support for X11 by default on Linux when using GLFW
+# NOTE: Wayland is disabled by default, only enable if you are sure
+GLFW_LINUX_ENABLE_WAYLAND ?= FALSE
GLFW_LINUX_ENABLE_X11 ?= TRUE
# PLATFORM_DESKTOP_SDL: It requires SDL library to be provided externally
diff --git a/src/build.zig b/src/build.zig
deleted file mode 100644
index 71729e4d2..000000000
--- a/src/build.zig
+++ /dev/null
@@ -1,397 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-
-comptime {
- if (builtin.zig_version.minor < 12) @compileError("Raylib requires zig version 0.12.0");
-}
-
-// NOTE(freakmangd): I don't like using a global here, but it prevents having to
-// get the flags a second time when adding raygui
-var raylib_flags_arr: std.ArrayListUnmanaged([]const u8) = .{};
-
-/// we're not inside the actual build script recognized by the
-/// zig build system; use this type where one would otherwise
-/// use `@This()` when inside the actual entrypoint file.
-const BuildScript = @import("../build.zig");
-
-// This has been tested with zig version 0.12.0
-pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
- const raylib_dep = b.dependencyFromBuildZig(BuildScript, .{
- .target = target,
- .optimize = optimize,
- .raudio = options.raudio,
- .rmodels = options.rmodels,
- .rshapes = options.rshapes,
- .rtext = options.rtext,
- .rtextures = options.rtextures,
- .platform_drm = options.platform_drm,
- .shared = options.shared,
- .linux_display_backend = options.linux_display_backend,
- .opengl_version = options.opengl_version,
- .config = options.config,
- });
- const raylib = raylib_dep.artifact("raylib");
-
- if (options.raygui) {
- const raygui_dep = b.dependency(options.raygui_dependency_name, .{});
- addRaygui(b, raylib, raygui_dep);
- }
-
- return raylib;
-}
-
-fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void {
- raylib.defineCMacro("PLATFORM_DESKTOP", null);
-
- switch (platform) {
- .glfw => raylib.defineCMacro("PLATFORM_DESKTOP_GLFW", null),
- .rgfw => raylib.defineCMacro("PLATFORM_DESKTOP_RGFW", null),
- .sdl => raylib.defineCMacro("PLATFORM_DESKTOP_SDL", null),
- else => {},
- }
-}
-
-fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
- raylib_flags_arr.clearRetainingCapacity();
-
- const shared_flags = &[_][]const u8{
- "-fPIC",
- "-DBUILD_LIBTYPE_SHARED",
- };
- try raylib_flags_arr.appendSlice(b.allocator, &[_][]const u8{
- "-std=gnu99",
- "-D_GNU_SOURCE",
- "-DGL_SILENCE_DEPRECATION=199309L",
- "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674
- });
- if (options.config) |config| {
- const file = try std.fs.path.join(b.allocator, &.{ std.fs.path.dirname(@src().file) orelse ".", "config.h" });
- defer b.allocator.free(file);
- const content = try std.fs.cwd().readFileAlloc(b.allocator, file, std.math.maxInt(usize));
- defer b.allocator.free(content);
-
- var lines = std.mem.splitScalar(u8, content, '\n');
- while (lines.next()) |line| {
- if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue;
- if (std.mem.startsWith(u8, line, "//")) continue;
- if (std.mem.startsWith(u8, line, "#if")) continue;
-
- var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace
- flag = flag["#define ".len - 1 ..]; // Remove #define
- flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace
- flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space
- flag = try std.fmt.allocPrint(b.allocator, "-D{s}", .{flag}); // Prepend with -D
-
- // If user specifies the flag skip it
- if (std.mem.containsAtLeast(u8, config, 1, flag)) continue;
-
- // Append default value from config.h to compile flags
- try raylib_flags_arr.append(b.allocator, flag);
- }
-
- // Append config flags supplied by user to compile flags
- try raylib_flags_arr.append(b.allocator, config);
-
- try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS");
- }
-
- if (options.shared) {
- try raylib_flags_arr.appendSlice(b.allocator, shared_flags);
- }
-
- const raylib = if (options.shared)
- b.addSharedLibrary(.{
- .name = "raylib",
- .target = target,
- .optimize = optimize,
- })
- else
- b.addStaticLibrary(.{
- .name = "raylib",
- .target = target,
- .optimize = optimize,
- });
- raylib.linkLibC();
-
- // No GLFW required on PLATFORM_DRM
- if (options.platform != .drm) {
- raylib.addIncludePath(b.path("src/external/glfw/include"));
- }
-
- var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2);
- c_source_files.appendSliceAssumeCapacity(&.{ "rcore.c", "utils.c" });
-
- if (options.raudio) {
- try c_source_files.append("raudio.c");
- }
- if (options.rmodels) {
- try c_source_files.append("rmodels.c");
- }
- if (options.rshapes) {
- try c_source_files.append("rshapes.c");
- }
- if (options.rtext) {
- try c_source_files.append("rtext.c");
- }
- if (options.rtextures) {
- try c_source_files.append("rtextures.c");
- }
-
- if (options.opengl_version != .auto) {
- raylib.defineCMacro(options.opengl_version.toCMacroStr(), null);
- }
-
- switch (target.result.os.tag) {
- .windows => {
- try c_source_files.append("rglfw.c");
- raylib.linkSystemLibrary("winmm");
- raylib.linkSystemLibrary("gdi32");
- raylib.linkSystemLibrary("opengl32");
-
- setDesktopPlatform(raylib, options.platform);
- },
- .linux => {
- if (options.platform != .drm) {
- try c_source_files.append("rglfw.c");
- raylib.linkSystemLibrary("GL");
- raylib.linkSystemLibrary("rt");
- raylib.linkSystemLibrary("dl");
- raylib.linkSystemLibrary("m");
-
- raylib.addLibraryPath(.{ .cwd_relative = "/usr/lib" });
- raylib.addIncludePath(.{ .cwd_relative = "/usr/include" });
- if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
- raylib.defineCMacro("_GLFW_X11", null);
- raylib.linkSystemLibrary("X11");
- }
-
- if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
- _ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
- std.log.err(
- \\ Wayland may not be installed on the system.
- \\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
- , .{});
- @panic("No Wayland");
- };
- raylib.defineCMacro("_GLFW_WAYLAND", null);
- raylib.linkSystemLibrary("wayland-client");
- raylib.linkSystemLibrary("wayland-cursor");
- raylib.linkSystemLibrary("wayland-egl");
- raylib.linkSystemLibrary("xkbcommon");
- raylib.addIncludePath(b.path("src"));
- waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol");
- waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol");
- waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol");
- waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol");
- waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol");
- waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol");
- waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol");
- waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol");
- waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol");
- }
- setDesktopPlatform(raylib, options.platform);
- } else {
- if (options.opengl_version == .auto) {
- raylib.linkSystemLibrary("GLESv2");
- raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null);
- }
-
- raylib.linkSystemLibrary("EGL");
- raylib.linkSystemLibrary("drm");
- raylib.linkSystemLibrary("gbm");
- raylib.linkSystemLibrary("pthread");
- raylib.linkSystemLibrary("rt");
- raylib.linkSystemLibrary("m");
- raylib.linkSystemLibrary("dl");
- raylib.addIncludePath(.{ .cwd_relative = "/usr/include/libdrm" });
-
- raylib.defineCMacro("PLATFORM_DRM", null);
- raylib.defineCMacro("EGL_NO_X11", null);
- raylib.defineCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "2048");
- }
- },
- .freebsd, .openbsd, .netbsd, .dragonfly => {
- try c_source_files.append("rglfw.c");
- raylib.linkSystemLibrary("GL");
- raylib.linkSystemLibrary("rt");
- raylib.linkSystemLibrary("dl");
- raylib.linkSystemLibrary("m");
- raylib.linkSystemLibrary("X11");
- raylib.linkSystemLibrary("Xrandr");
- raylib.linkSystemLibrary("Xinerama");
- raylib.linkSystemLibrary("Xi");
- raylib.linkSystemLibrary("Xxf86vm");
- raylib.linkSystemLibrary("Xcursor");
-
- setDesktopPlatform(raylib, options.platform);
- },
- .macos => {
- // On macos rglfw.c include Objective-C files.
- try raylib_flags_arr.append(b.allocator, "-ObjC");
- raylib.root_module.addCSourceFile(.{
- .file = b.path("src/rglfw.c"),
- .flags = raylib_flags_arr.items,
- });
- _ = raylib_flags_arr.pop();
- raylib.linkFramework("Foundation");
- raylib.linkFramework("CoreServices");
- raylib.linkFramework("CoreGraphics");
- raylib.linkFramework("AppKit");
- raylib.linkFramework("IOKit");
-
- setDesktopPlatform(raylib, options.platform);
- },
- .emscripten => {
- raylib.defineCMacro("PLATFORM_WEB", null);
- if (options.opengl_version == .auto) {
- raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null);
- }
-
- if (b.sysroot == null) {
- @panic("Pass '--sysroot \"$EMSDK/upstream/emscripten\"'");
- }
-
- const cache_include = std.fs.path.join(b.allocator, &.{ b.sysroot.?, "cache", "sysroot", "include" }) catch @panic("Out of memory");
- defer b.allocator.free(cache_include);
-
- var dir = std.fs.openDirAbsolute(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!");
- dir.close();
- raylib.addIncludePath(.{ .cwd_relative = cache_include });
- },
- else => {
- @panic("Unsupported OS");
- },
- }
-
- raylib.addIncludePath(b.path("src"));
- raylib.root_module.addCSourceFiles(.{
- .root = b.path("src"),
- .files = c_source_files.items,
- .flags = raylib_flags_arr.items,
- });
-
- return raylib;
-}
-
-/// This function does not need to be called if you passed .raygui = true to addRaylib
-pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency) void {
- if (raylib_flags_arr.items.len == 0) {
- @panic(
- \\argument 2 `raylib` in `addRaygui` must come from b.dependency("raylib", ...).artifact("raylib")
- );
- }
-
- var gen_step = b.addWriteFiles();
- raylib.step.dependOn(&gen_step.step);
-
- const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
- raylib.addCSourceFile(.{ .file = raygui_c_path, .flags = raylib_flags_arr.items });
- raylib.addIncludePath(raygui_dep.path("src"));
-
- raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
-}
-
-pub const Options = struct {
- raudio: bool = true,
- rmodels: bool = true,
- rshapes: bool = true,
- rtext: bool = true,
- rtextures: bool = true,
- raygui: bool = false,
- platform: PlatformBackend = .glfw,
- shared: bool = false,
- linux_display_backend: LinuxDisplayBackend = .Both,
- opengl_version: OpenglVersion = .auto,
- /// config should be a list of cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL"
- config: ?[]const u8 = null,
-
- raygui_dependency_name: []const u8 = "raygui",
-};
-
-pub const OpenglVersion = enum {
- auto,
- gl_1_1,
- gl_2_1,
- gl_3_3,
- gl_4_3,
- gles_2,
- gles_3,
-
- pub fn toCMacroStr(self: @This()) []const u8 {
- switch (self) {
- .auto => @panic("OpenglVersion.auto cannot be turned into a C macro string"),
- .gl_1_1 => return "GRAPHICS_API_OPENGL_11",
- .gl_2_1 => return "GRAPHICS_API_OPENGL_21",
- .gl_3_3 => return "GRAPHICS_API_OPENGL_33",
- .gl_4_3 => return "GRAPHICS_API_OPENGL_43",
- .gles_2 => return "GRAPHICS_API_OPENGL_ES2",
- .gles_3 => return "GRAPHICS_API_OPENGL_ES3",
- }
- }
-};
-
-pub const LinuxDisplayBackend = enum {
- X11,
- Wayland,
- Both,
-};
-
-pub const PlatformBackend = enum {
- glfw,
- rgfw,
- sdl,
- drm,
-};
-
-pub fn build(b: *std.Build) !void {
- // Standard target options allows the person running `zig build` to choose
- // what target to build for. Here we do not override the defaults, which
- // means any target is allowed, and the default is native. Other options
- // for restricting supported target set are available.
- const target = b.standardTargetOptions(.{});
- // Standard optimization options allow the person running `zig build` to select
- // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
- // set a preferred release mode, allowing the user to decide how to optimize.
- const optimize = b.standardOptimizeOption(.{});
-
- const defaults = Options{};
- const options = Options{
- .platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform,
- .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio,
- .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels,
- .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,
- .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures,
- .rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes,
- .shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared,
- .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend,
- .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version,
- .config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse null,
- };
-
- const lib = try compileRaylib(b, target, optimize, options);
-
- lib.installHeader(b.path("src/raylib.h"), "raylib.h");
- lib.installHeader(b.path("src/raymath.h"), "raymath.h");
- lib.installHeader(b.path("src/rlgl.h"), "rlgl.h");
-
- b.installArtifact(lib);
-}
-
-const waylandDir = "src/external/glfw/deps/wayland";
-
-fn waylandGenerate(b: *std.Build, raylib: *std.Build.Step.Compile, comptime protocol: []const u8, comptime basename: []const u8) void {
- const protocolDir = waylandDir ++ "/" ++ protocol;
- const clientHeader = basename ++ ".h";
- const privateCode = basename ++ "-code.h";
-
- const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" });
- client_step.addFileArg(b.path(protocolDir));
- raylib.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname());
-
- const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
- private_step.addFileArg(b.path(protocolDir));
- raylib.addIncludePath(private_step.addOutputFileArg(privateCode).dirname());
-
- raylib.step.dependOn(&client_step.step);
- raylib.step.dependOn(&private_step.step);
-}
diff --git a/src/config.h b/src/config.h
index 5504a1823..9123a2291 100644
--- a/src/config.h
+++ b/src/config.h
@@ -180,7 +180,6 @@
//#define SUPPORT_FILEFORMAT_ASTC 1
//#define SUPPORT_FILEFORMAT_PKM 1
//#define SUPPORT_FILEFORMAT_PVR 1
-//#define SUPPORT_FILEFORMAT_SVG 1
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
#define SUPPORT_IMAGE_EXPORT 1
diff --git a/src/external/nanosvg.h b/src/external/nanosvg.h
deleted file mode 100644
index b80f540ba..000000000
--- a/src/external/nanosvg.h
+++ /dev/null
@@ -1,3053 +0,0 @@
-/*
- * Copyright (c) 2013-14 Mikko Mononen memon@inside.org
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- *
- * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example
- * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/)
- *
- * Arc calculation code based on canvg (https://code.google.com/p/canvg/)
- *
- * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
- *
- */
-
-#ifndef NANOSVG_H
-#define NANOSVG_H
-
-#ifndef NANOSVG_CPLUSPLUS
-#ifdef __cplusplus
-extern "C" {
-#endif
-#endif
-
-// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes.
-//
-// The library suits well for anything from rendering scalable icons in your editor application to prototyping a game.
-//
-// NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request!
-//
-// The shapes in the SVG images are transformed by the viewBox and converted to specified units.
-// That is, you should get the same looking data as your designed in your favorite app.
-//
-// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose
-// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters.
-//
-// The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.
-// DPI (dots-per-inch) controls how the unit conversion is done.
-//
-// If you don't know or care about the units stuff, "px" and 96 should get you going.
-
-
-/* Example Usage:
- // Load SVG
- NSVGimage* image;
- image = nsvgParseFromFile("test.svg", "px", 96);
- printf("size: %f x %f\n", image->width, image->height);
- // Use...
- for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
- for (NSVGpath *path = shape->paths; path != NULL; path = path->next) {
- for (int i = 0; i < path->npts-1; i += 3) {
- float* p = &path->pts[i*2];
- drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
- }
- }
- }
- // Delete
- nsvgDelete(image);
-*/
-
-enum NSVGpaintType {
- NSVG_PAINT_NONE = 0,
- NSVG_PAINT_COLOR = 1,
- NSVG_PAINT_LINEAR_GRADIENT = 2,
- NSVG_PAINT_RADIAL_GRADIENT = 3
-};
-
-enum NSVGspreadType {
- NSVG_SPREAD_PAD = 0,
- NSVG_SPREAD_REFLECT = 1,
- NSVG_SPREAD_REPEAT = 2
-};
-
-enum NSVGlineJoin {
- NSVG_JOIN_MITER = 0,
- NSVG_JOIN_ROUND = 1,
- NSVG_JOIN_BEVEL = 2
-};
-
-enum NSVGlineCap {
- NSVG_CAP_BUTT = 0,
- NSVG_CAP_ROUND = 1,
- NSVG_CAP_SQUARE = 2
-};
-
-enum NSVGfillRule {
- NSVG_FILLRULE_NONZERO = 0,
- NSVG_FILLRULE_EVENODD = 1
-};
-
-enum NSVGflags {
- NSVG_FLAGS_VISIBLE = 0x01
-};
-
-typedef struct NSVGgradientStop {
- unsigned int color;
- float offset;
-} NSVGgradientStop;
-
-typedef struct NSVGgradient {
- float xform[6];
- char spread;
- float fx, fy;
- int nstops;
- NSVGgradientStop stops[1];
-} NSVGgradient;
-
-typedef struct NSVGpaint {
- char type;
- union {
- unsigned int color;
- NSVGgradient* gradient;
- };
-} NSVGpaint;
-
-typedef struct NSVGpath
-{
- float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
- int npts; // Total number of bezier points.
- char closed; // Flag indicating if shapes should be treated as closed.
- float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
- struct NSVGpath* next; // Pointer to next path, or NULL if last element.
-} NSVGpath;
-
-typedef struct NSVGshape
-{
- char id[64]; // Optional 'id' attr of the shape or its group
- NSVGpaint fill; // Fill paint
- NSVGpaint stroke; // Stroke paint
- float opacity; // Opacity of the shape.
- float strokeWidth; // Stroke width (scaled).
- float strokeDashOffset; // Stroke dash offset (scaled).
- float strokeDashArray[8]; // Stroke dash array (scaled).
- char strokeDashCount; // Number of dash values in dash array.
- char strokeLineJoin; // Stroke join type.
- char strokeLineCap; // Stroke cap type.
- float miterLimit; // Miter limit
- char fillRule; // Fill rule, see NSVGfillRule.
- unsigned char flags; // Logical or of NSVG_FLAGS_* flags
- float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
- NSVGpath* paths; // Linked list of paths in the image.
- struct NSVGshape* next; // Pointer to next shape, or NULL if last element.
-} NSVGshape;
-
-typedef struct NSVGimage
-{
- float width; // Width of the image.
- float height; // Height of the image.
- NSVGshape* shapes; // Linked list of shapes in the image.
-} NSVGimage;
-
-// Parses SVG file from a file, returns SVG image as paths.
-NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi);
-
-// Parses SVG file from a null terminated string, returns SVG image as paths.
-// Important note: changes the string.
-NSVGimage* nsvgParse(char* input, const char* units, float dpi);
-
-// Duplicates a path.
-NSVGpath* nsvgDuplicatePath(NSVGpath* p);
-
-// Deletes an image.
-void nsvgDelete(NSVGimage* image);
-
-#ifndef NANOSVG_CPLUSPLUS
-#ifdef __cplusplus
-}
-#endif
-#endif
-
-#ifdef NANOSVG_IMPLEMENTATION
-
-#include
-#include
-#include
-#include
-
-#define NSVG_PI (3.14159265358979323846264338327f)
-#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs.
-
-#define NSVG_ALIGN_MIN 0
-#define NSVG_ALIGN_MID 1
-#define NSVG_ALIGN_MAX 2
-#define NSVG_ALIGN_NONE 0
-#define NSVG_ALIGN_MEET 1
-#define NSVG_ALIGN_SLICE 2
-
-#define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0)
-#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))
-
-#ifdef _MSC_VER
- #pragma warning (disable: 4996) // Switch off security warnings
- #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings
- #ifdef __cplusplus
- #define NSVG_INLINE inline
- #else
- #define NSVG_INLINE
- #endif
-#else
- #define NSVG_INLINE inline
-#endif
-
-
-static int nsvg__isspace(char c)
-{
- return strchr(" \t\n\v\f\r", c) != 0;
-}
-
-static int nsvg__isdigit(char c)
-{
- return c >= '0' && c <= '9';
-}
-
-static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; }
-static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; }
-
-
-// Simple XML parser
-
-#define NSVG_XML_TAG 1
-#define NSVG_XML_CONTENT 2
-#define NSVG_XML_MAX_ATTRIBS 256
-
-static void nsvg__parseContent(char* s,
- void (*contentCb)(void* ud, const char* s),
- void* ud)
-{
- // Trim start white spaces
- while (*s && nsvg__isspace(*s)) s++;
- if (!*s) return;
-
- if (contentCb)
- (*contentCb)(ud, s);
-}
-
-static void nsvg__parseElement(char* s,
- void (*startelCb)(void* ud, const char* el, const char** attr),
- void (*endelCb)(void* ud, const char* el),
- void* ud)
-{
- const char* attr[NSVG_XML_MAX_ATTRIBS];
- int nattr = 0;
- char* name;
- int start = 0;
- int end = 0;
- char quote;
-
- // Skip white space after the '<'
- while (*s && nsvg__isspace(*s)) s++;
-
- // Check if the tag is end tag
- if (*s == '/') {
- s++;
- end = 1;
- } else {
- start = 1;
- }
-
- // Skip comments, data and preprocessor stuff.
- if (!*s || *s == '?' || *s == '!')
- return;
-
- // Get tag name
- name = s;
- while (*s && !nsvg__isspace(*s)) s++;
- if (*s) { *s++ = '\0'; }
-
- // Get attribs
- while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) {
- char* name = NULL;
- char* value = NULL;
-
- // Skip white space before the attrib name
- while (*s && nsvg__isspace(*s)) s++;
- if (!*s) break;
- if (*s == '/') {
- end = 1;
- break;
- }
- name = s;
- // Find end of the attrib name.
- while (*s && !nsvg__isspace(*s) && *s != '=') s++;
- if (*s) { *s++ = '\0'; }
- // Skip until the beginning of the value.
- while (*s && *s != '\"' && *s != '\'') s++;
- if (!*s) break;
- quote = *s;
- s++;
- // Store value and find the end of it.
- value = s;
- while (*s && *s != quote) s++;
- if (*s) { *s++ = '\0'; }
-
- // Store only well formed attributes
- if (name && value) {
- attr[nattr++] = name;
- attr[nattr++] = value;
- }
- }
-
- // List terminator
- attr[nattr++] = 0;
- attr[nattr++] = 0;
-
- // Call callbacks.
- if (start && startelCb)
- (*startelCb)(ud, name, attr);
- if (end && endelCb)
- (*endelCb)(ud, name);
-}
-
-int nsvg__parseXML(char* input,
- void (*startelCb)(void* ud, const char* el, const char** attr),
- void (*endelCb)(void* ud, const char* el),
- void (*contentCb)(void* ud, const char* s),
- void* ud)
-{
- char* s = input;
- char* mark = s;
- int state = NSVG_XML_CONTENT;
- while (*s) {
- if (*s == '<' && state == NSVG_XML_CONTENT) {
- // Start of a tag
- *s++ = '\0';
- nsvg__parseContent(mark, contentCb, ud);
- mark = s;
- state = NSVG_XML_TAG;
- } else if (*s == '>' && state == NSVG_XML_TAG) {
- // Start of a content or new tag.
- *s++ = '\0';
- nsvg__parseElement(mark, startelCb, endelCb, ud);
- mark = s;
- state = NSVG_XML_CONTENT;
- } else {
- s++;
- }
- }
-
- return 1;
-}
-
-
-/* Simple SVG parser. */
-
-#define NSVG_MAX_ATTR 128
-
-enum NSVGgradientUnits {
- NSVG_USER_SPACE = 0,
- NSVG_OBJECT_SPACE = 1
-};
-
-#define NSVG_MAX_DASHES 8
-
-enum NSVGunits {
- NSVG_UNITS_USER,
- NSVG_UNITS_PX,
- NSVG_UNITS_PT,
- NSVG_UNITS_PC,
- NSVG_UNITS_MM,
- NSVG_UNITS_CM,
- NSVG_UNITS_IN,
- NSVG_UNITS_PERCENT,
- NSVG_UNITS_EM,
- NSVG_UNITS_EX
-};
-
-typedef struct NSVGcoordinate {
- float value;
- int units;
-} NSVGcoordinate;
-
-typedef struct NSVGlinearData {
- NSVGcoordinate x1, y1, x2, y2;
-} NSVGlinearData;
-
-typedef struct NSVGradialData {
- NSVGcoordinate cx, cy, r, fx, fy;
-} NSVGradialData;
-
-typedef struct NSVGgradientData
-{
- char id[64];
- char ref[64];
- char type;
- union {
- NSVGlinearData linear;
- NSVGradialData radial;
- };
- char spread;
- char units;
- float xform[6];
- int nstops;
- NSVGgradientStop* stops;
- struct NSVGgradientData* next;
-} NSVGgradientData;
-
-typedef struct NSVGattrib
-{
- char id[64];
- float xform[6];
- unsigned int fillColor;
- unsigned int strokeColor;
- float opacity;
- float fillOpacity;
- float strokeOpacity;
- char fillGradient[64];
- char strokeGradient[64];
- float strokeWidth;
- float strokeDashOffset;
- float strokeDashArray[NSVG_MAX_DASHES];
- int strokeDashCount;
- char strokeLineJoin;
- char strokeLineCap;
- float miterLimit;
- char fillRule;
- float fontSize;
- unsigned int stopColor;
- float stopOpacity;
- float stopOffset;
- char hasFill;
- char hasStroke;
- char visible;
-} NSVGattrib;
-
-typedef struct NSVGparser
-{
- NSVGattrib attr[NSVG_MAX_ATTR];
- int attrHead;
- float* pts;
- int npts;
- int cpts;
- NSVGpath* plist;
- NSVGimage* image;
- NSVGgradientData* gradients;
- NSVGshape* shapesTail;
- float viewMinx, viewMiny, viewWidth, viewHeight;
- int alignX, alignY, alignType;
- float dpi;
- char pathFlag;
- char defsFlag;
-} NSVGparser;
-
-static void nsvg__xformIdentity(float* t)
-{
- t[0] = 1.0f; t[1] = 0.0f;
- t[2] = 0.0f; t[3] = 1.0f;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetTranslation(float* t, float tx, float ty)
-{
- t[0] = 1.0f; t[1] = 0.0f;
- t[2] = 0.0f; t[3] = 1.0f;
- t[4] = tx; t[5] = ty;
-}
-
-static void nsvg__xformSetScale(float* t, float sx, float sy)
-{
- t[0] = sx; t[1] = 0.0f;
- t[2] = 0.0f; t[3] = sy;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetSkewX(float* t, float a)
-{
- t[0] = 1.0f; t[1] = 0.0f;
- t[2] = tanf(a); t[3] = 1.0f;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetSkewY(float* t, float a)
-{
- t[0] = 1.0f; t[1] = tanf(a);
- t[2] = 0.0f; t[3] = 1.0f;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformSetRotation(float* t, float a)
-{
- float cs = cosf(a), sn = sinf(a);
- t[0] = cs; t[1] = sn;
- t[2] = -sn; t[3] = cs;
- t[4] = 0.0f; t[5] = 0.0f;
-}
-
-static void nsvg__xformMultiply(float* t, float* s)
-{
- float t0 = t[0] * s[0] + t[1] * s[2];
- float t2 = t[2] * s[0] + t[3] * s[2];
- float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
- t[1] = t[0] * s[1] + t[1] * s[3];
- t[3] = t[2] * s[1] + t[3] * s[3];
- t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
- t[0] = t0;
- t[2] = t2;
- t[4] = t4;
-}
-
-static void nsvg__xformInverse(float* inv, float* t)
-{
- double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
- if (det > -1e-6 && det < 1e-6) {
- nsvg__xformIdentity(t);
- return;
- }
- invdet = 1.0 / det;
- inv[0] = (float)(t[3] * invdet);
- inv[2] = (float)(-t[2] * invdet);
- inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
- inv[1] = (float)(-t[1] * invdet);
- inv[3] = (float)(t[0] * invdet);
- inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
-}
-
-static void nsvg__xformPremultiply(float* t, float* s)
-{
- float s2[6];
- memcpy(s2, s, sizeof(float)*6);
- nsvg__xformMultiply(s2, t);
- memcpy(t, s2, sizeof(float)*6);
-}
-
-static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t)
-{
- *dx = x*t[0] + y*t[2] + t[4];
- *dy = x*t[1] + y*t[3] + t[5];
-}
-
-static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t)
-{
- *dx = x*t[0] + y*t[2];
- *dy = x*t[1] + y*t[3];
-}
-
-#define NSVG_EPSILON (1e-12)
-
-static int nsvg__ptInBounds(float* pt, float* bounds)
-{
- return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
-}
-
-
-static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3)
-{
- double it = 1.0-t;
- return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3;
-}
-
-static void nsvg__curveBounds(float* bounds, float* curve)
-{
- int i, j, count;
- double roots[2], a, b, c, b2ac, t, v;
- float* v0 = &curve[0];
- float* v1 = &curve[2];
- float* v2 = &curve[4];
- float* v3 = &curve[6];
-
- // Start the bounding box by end points
- bounds[0] = nsvg__minf(v0[0], v3[0]);
- bounds[1] = nsvg__minf(v0[1], v3[1]);
- bounds[2] = nsvg__maxf(v0[0], v3[0]);
- bounds[3] = nsvg__maxf(v0[1], v3[1]);
-
- // Bezier curve fits inside the convex hull of it's control points.
- // If control points are inside the bounds, we're done.
- if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
- return;
-
- // Add bezier curve inflection points in X and Y.
- for (i = 0; i < 2; i++) {
- a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];
- b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];
- c = 3.0 * v1[i] - 3.0 * v0[i];
- count = 0;
- if (fabs(a) < NSVG_EPSILON) {
- if (fabs(b) > NSVG_EPSILON) {
- t = -c / b;
- if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
- roots[count++] = t;
- }
- } else {
- b2ac = b*b - 4.0*c*a;
- if (b2ac > NSVG_EPSILON) {
- t = (-b + sqrt(b2ac)) / (2.0 * a);
- if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
- roots[count++] = t;
- t = (-b - sqrt(b2ac)) / (2.0 * a);
- if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
- roots[count++] = t;
- }
- }
- for (j = 0; j < count; j++) {
- v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
- bounds[0+i] = nsvg__minf(bounds[0+i], (float)v);
- bounds[2+i] = nsvg__maxf(bounds[2+i], (float)v);
- }
- }
-}
-
-static NSVGparser* nsvg__createParser(void)
-{
- NSVGparser* p;
- p = (NSVGparser*)malloc(sizeof(NSVGparser));
- if (p == NULL) goto error;
- memset(p, 0, sizeof(NSVGparser));
-
- p->image = (NSVGimage*)malloc(sizeof(NSVGimage));
- if (p->image == NULL) goto error;
- memset(p->image, 0, sizeof(NSVGimage));
-
- // Init style
- nsvg__xformIdentity(p->attr[0].xform);
- memset(p->attr[0].id, 0, sizeof p->attr[0].id);
- p->attr[0].fillColor = NSVG_RGB(0,0,0);
- p->attr[0].strokeColor = NSVG_RGB(0,0,0);
- p->attr[0].opacity = 1;
- p->attr[0].fillOpacity = 1;
- p->attr[0].strokeOpacity = 1;
- p->attr[0].stopOpacity = 1;
- p->attr[0].strokeWidth = 1;
- p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
- p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
- p->attr[0].miterLimit = 4;
- p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
- p->attr[0].hasFill = 1;
- p->attr[0].visible = 1;
-
- return p;
-
-error:
- if (p) {
- if (p->image) free(p->image);
- free(p);
- }
- return NULL;
-}
-
-static void nsvg__deletePaths(NSVGpath* path)
-{
- while (path) {
- NSVGpath *next = path->next;
- if (path->pts != NULL)
- free(path->pts);
- free(path);
- path = next;
- }
-}
-
-static void nsvg__deletePaint(NSVGpaint* paint)
-{
- if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)
- free(paint->gradient);
-}
-
-static void nsvg__deleteGradientData(NSVGgradientData* grad)
-{
- NSVGgradientData* next;
- while (grad != NULL) {
- next = grad->next;
- free(grad->stops);
- free(grad);
- grad = next;
- }
-}
-
-static void nsvg__deleteParser(NSVGparser* p)
-{
- if (p != NULL) {
- nsvg__deletePaths(p->plist);
- nsvg__deleteGradientData(p->gradients);
- nsvgDelete(p->image);
- free(p->pts);
- free(p);
- }
-}
-
-static void nsvg__resetPath(NSVGparser* p)
-{
- p->npts = 0;
-}
-
-static void nsvg__addPoint(NSVGparser* p, float x, float y)
-{
- if (p->npts+1 > p->cpts) {
- p->cpts = p->cpts ? p->cpts*2 : 8;
- p->pts = (float*)realloc(p->pts, p->cpts*2*sizeof(float));
- if (!p->pts) return;
- }
- p->pts[p->npts*2+0] = x;
- p->pts[p->npts*2+1] = y;
- p->npts++;
-}
-
-static void nsvg__moveTo(NSVGparser* p, float x, float y)
-{
- if (p->npts > 0) {
- p->pts[(p->npts-1)*2+0] = x;
- p->pts[(p->npts-1)*2+1] = y;
- } else {
- nsvg__addPoint(p, x, y);
- }
-}
-
-static void nsvg__lineTo(NSVGparser* p, float x, float y)
-{
- float px,py, dx,dy;
- if (p->npts > 0) {
- px = p->pts[(p->npts-1)*2+0];
- py = p->pts[(p->npts-1)*2+1];
- dx = x - px;
- dy = y - py;
- nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f);
- nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f);
- nsvg__addPoint(p, x, y);
- }
-}
-
-static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
-{
- if (p->npts > 0) {
- nsvg__addPoint(p, cpx1, cpy1);
- nsvg__addPoint(p, cpx2, cpy2);
- nsvg__addPoint(p, x, y);
- }
-}
-
-static NSVGattrib* nsvg__getAttr(NSVGparser* p)
-{
- return &p->attr[p->attrHead];
-}
-
-static void nsvg__pushAttr(NSVGparser* p)
-{
- if (p->attrHead < NSVG_MAX_ATTR-1) {
- p->attrHead++;
- memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead-1], sizeof(NSVGattrib));
- }
-}
-
-static void nsvg__popAttr(NSVGparser* p)
-{
- if (p->attrHead > 0)
- p->attrHead--;
-}
-
-static float nsvg__actualOrigX(NSVGparser* p)
-{
- return p->viewMinx;
-}
-
-static float nsvg__actualOrigY(NSVGparser* p)
-{
- return p->viewMiny;
-}
-
-static float nsvg__actualWidth(NSVGparser* p)
-{
- return p->viewWidth;
-}
-
-static float nsvg__actualHeight(NSVGparser* p)
-{
- return p->viewHeight;
-}
-
-static float nsvg__actualLength(NSVGparser* p)
-{
- float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);
- return sqrtf(w*w + h*h) / sqrtf(2.0f);
-}
-
-static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- switch (c.units) {
- case NSVG_UNITS_USER: return c.value;
- case NSVG_UNITS_PX: return c.value;
- case NSVG_UNITS_PT: return c.value / 72.0f * p->dpi;
- case NSVG_UNITS_PC: return c.value / 6.0f * p->dpi;
- case NSVG_UNITS_MM: return c.value / 25.4f * p->dpi;
- case NSVG_UNITS_CM: return c.value / 2.54f * p->dpi;
- case NSVG_UNITS_IN: return c.value * p->dpi;
- case NSVG_UNITS_EM: return c.value * attr->fontSize;
- case NSVG_UNITS_EX: return c.value * attr->fontSize * 0.52f; // x-height of Helvetica.
- case NSVG_UNITS_PERCENT: return orig + c.value / 100.0f * length;
- default: return c.value;
- }
- return c.value;
-}
-
-static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)
-{
- NSVGgradientData* grad = p->gradients;
- if (id == NULL || *id == '\0')
- return NULL;
- while (grad != NULL) {
- if (strcmp(grad->id, id) == 0)
- return grad;
- grad = grad->next;
- }
- return NULL;
-}
-
-static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, char* paintType)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- NSVGgradientData* data = NULL;
- NSVGgradientData* ref = NULL;
- NSVGgradientStop* stops = NULL;
- NSVGgradient* grad;
- float ox, oy, sw, sh, sl;
- int nstops = 0;
- int refIter;
-
- data = nsvg__findGradientData(p, id);
- if (data == NULL) return NULL;
-
- // TODO: use ref to fill in all unset values too.
- ref = data;
- refIter = 0;
- while (ref != NULL) {
- NSVGgradientData* nextRef = NULL;
- if (stops == NULL && ref->stops != NULL) {
- stops = ref->stops;
- nstops = ref->nstops;
- break;
- }
- nextRef = nsvg__findGradientData(p, ref->ref);
- if (nextRef == ref) break; // prevent infite loops on malformed data
- ref = nextRef;
- refIter++;
- if (refIter > 32) break; // prevent infite loops on malformed data
- }
- if (stops == NULL) return NULL;
-
- grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(nstops-1));
- if (grad == NULL) return NULL;
-
- // The shape width and height.
- if (data->units == NSVG_OBJECT_SPACE) {
- ox = localBounds[0];
- oy = localBounds[1];
- sw = localBounds[2] - localBounds[0];
- sh = localBounds[3] - localBounds[1];
- } else {
- ox = nsvg__actualOrigX(p);
- oy = nsvg__actualOrigY(p);
- sw = nsvg__actualWidth(p);
- sh = nsvg__actualHeight(p);
- }
- sl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f);
-
- if (data->type == NSVG_PAINT_LINEAR_GRADIENT) {
- float x1, y1, x2, y2, dx, dy;
- x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw);
- y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh);
- x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw);
- y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh);
- // Calculate transform aligned to the line
- dx = x2 - x1;
- dy = y2 - y1;
- grad->xform[0] = dy; grad->xform[1] = -dx;
- grad->xform[2] = dx; grad->xform[3] = dy;
- grad->xform[4] = x1; grad->xform[5] = y1;
- } else {
- float cx, cy, fx, fy, r;
- cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw);
- cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh);
- fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw);
- fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh);
- r = nsvg__convertToPixels(p, data->radial.r, 0, sl);
- // Calculate transform aligned to the circle
- grad->xform[0] = r; grad->xform[1] = 0;
- grad->xform[2] = 0; grad->xform[3] = r;
- grad->xform[4] = cx; grad->xform[5] = cy;
- grad->fx = fx / r;
- grad->fy = fy / r;
- }
-
- nsvg__xformMultiply(grad->xform, data->xform);
- nsvg__xformMultiply(grad->xform, attr->xform);
-
- grad->spread = data->spread;
- memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
- grad->nstops = nstops;
-
- *paintType = data->type;
-
- return grad;
-}
-
-static float nsvg__getAverageScale(float* t)
-{
- float sx = sqrtf(t[0]*t[0] + t[2]*t[2]);
- float sy = sqrtf(t[1]*t[1] + t[3]*t[3]);
- return (sx + sy) * 0.5f;
-}
-
-static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform)
-{
- NSVGpath* path;
- float curve[4*2], curveBounds[4];
- int i, first = 1;
- for (path = shape->paths; path != NULL; path = path->next) {
- nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform);
- for (i = 0; i < path->npts-1; i += 3) {
- nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i+1)*2], path->pts[(i+1)*2+1], xform);
- nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i+2)*2], path->pts[(i+2)*2+1], xform);
- nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i+3)*2], path->pts[(i+3)*2+1], xform);
- nsvg__curveBounds(curveBounds, curve);
- if (first) {
- bounds[0] = curveBounds[0];
- bounds[1] = curveBounds[1];
- bounds[2] = curveBounds[2];
- bounds[3] = curveBounds[3];
- first = 0;
- } else {
- bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
- bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
- bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
- bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
- }
- curve[0] = curve[6];
- curve[1] = curve[7];
- }
- }
-}
-
-static void nsvg__addShape(NSVGparser* p)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- float scale = 1.0f;
- NSVGshape* shape;
- NSVGpath* path;
- int i;
-
- if (p->plist == NULL)
- return;
-
- shape = (NSVGshape*)malloc(sizeof(NSVGshape));
- if (shape == NULL) goto error;
- memset(shape, 0, sizeof(NSVGshape));
-
- memcpy(shape->id, attr->id, sizeof shape->id);
- scale = nsvg__getAverageScale(attr->xform);
- shape->strokeWidth = attr->strokeWidth * scale;
- shape->strokeDashOffset = attr->strokeDashOffset * scale;
- shape->strokeDashCount = (char)attr->strokeDashCount;
- for (i = 0; i < attr->strokeDashCount; i++)
- shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
- shape->strokeLineJoin = attr->strokeLineJoin;
- shape->strokeLineCap = attr->strokeLineCap;
- shape->miterLimit = attr->miterLimit;
- shape->fillRule = attr->fillRule;
- shape->opacity = attr->opacity;
-
- shape->paths = p->plist;
- p->plist = NULL;
-
- // Calculate shape bounds
- shape->bounds[0] = shape->paths->bounds[0];
- shape->bounds[1] = shape->paths->bounds[1];
- shape->bounds[2] = shape->paths->bounds[2];
- shape->bounds[3] = shape->paths->bounds[3];
- for (path = shape->paths->next; path != NULL; path = path->next) {
- shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
- shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
- shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
- shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
- }
-
- // Set fill
- if (attr->hasFill == 0) {
- shape->fill.type = NSVG_PAINT_NONE;
- } else if (attr->hasFill == 1) {
- shape->fill.type = NSVG_PAINT_COLOR;
- shape->fill.color = attr->fillColor;
- shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;
- } else if (attr->hasFill == 2) {
- float inv[6], localBounds[4];
- nsvg__xformInverse(inv, attr->xform);
- nsvg__getLocalBounds(localBounds, shape, inv);
- shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type);
- if (shape->fill.gradient == NULL) {
- shape->fill.type = NSVG_PAINT_NONE;
- }
- }
-
- // Set stroke
- if (attr->hasStroke == 0) {
- shape->stroke.type = NSVG_PAINT_NONE;
- } else if (attr->hasStroke == 1) {
- shape->stroke.type = NSVG_PAINT_COLOR;
- shape->stroke.color = attr->strokeColor;
- shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;
- } else if (attr->hasStroke == 2) {
- float inv[6], localBounds[4];
- nsvg__xformInverse(inv, attr->xform);
- nsvg__getLocalBounds(localBounds, shape, inv);
- shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type);
- if (shape->stroke.gradient == NULL)
- shape->stroke.type = NSVG_PAINT_NONE;
- }
-
- // Set flags
- shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00);
-
- // Add to tail
- if (p->image->shapes == NULL)
- p->image->shapes = shape;
- else
- p->shapesTail->next = shape;
- p->shapesTail = shape;
-
- return;
-
-error:
- if (shape) free(shape);
-}
-
-static void nsvg__addPath(NSVGparser* p, char closed)
-{
- NSVGattrib* attr = nsvg__getAttr(p);
- NSVGpath* path = NULL;
- float bounds[4];
- float* curve;
- int i;
-
- if (p->npts < 4)
- return;
-
- if (closed)
- nsvg__lineTo(p, p->pts[0], p->pts[1]);
-
- // Expect 1 + N*3 points (N = number of cubic bezier segments).
- if ((p->npts % 3) != 1)
- return;
-
- path = (NSVGpath*)malloc(sizeof(NSVGpath));
- if (path == NULL) goto error;
- memset(path, 0, sizeof(NSVGpath));
-
- path->pts = (float*)malloc(p->npts*2*sizeof(float));
- if (path->pts == NULL) goto error;
- path->closed = closed;
- path->npts = p->npts;
-
- // Transform path.
- for (i = 0; i < p->npts; ++i)
- nsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], attr->xform);
-
- // Find bounds
- for (i = 0; i < path->npts-1; i += 3) {
- curve = &path->pts[i*2];
- nsvg__curveBounds(bounds, curve);
- if (i == 0) {
- path->bounds[0] = bounds[0];
- path->bounds[1] = bounds[1];
- path->bounds[2] = bounds[2];
- path->bounds[3] = bounds[3];
- } else {
- path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]);
- path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]);
- path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]);
- path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]);
- }
- }
-
- path->next = p->plist;
- p->plist = path;
-
- return;
-
-error:
- if (path != NULL) {
- if (path->pts != NULL) free(path->pts);
- free(path);
- }
-}
-
-// We roll our own string to float because the std library one uses locale and messes things up.
-static double nsvg__atof(const char* s)
-{
- char* cur = (char*)s;
- char* end = NULL;
- double res = 0.0, sign = 1.0;
- long long intPart = 0, fracPart = 0;
- char hasIntPart = 0, hasFracPart = 0;
-
- // Parse optional sign
- if (*cur == '+') {
- cur++;
- } else if (*cur == '-') {
- sign = -1;
- cur++;
- }
-
- // Parse integer part
- if (nsvg__isdigit(*cur)) {
- // Parse digit sequence
- intPart = strtoll(cur, &end, 10);
- if (cur != end) {
- res = (double)intPart;
- hasIntPart = 1;
- cur = end;
- }
- }
-
- // Parse fractional part.
- if (*cur == '.') {
- cur++; // Skip '.'
- if (nsvg__isdigit(*cur)) {
- // Parse digit sequence
- fracPart = strtoll(cur, &end, 10);
- if (cur != end) {
- res += (double)fracPart / pow(10.0, (double)(end - cur));
- hasFracPart = 1;
- cur = end;
- }
- }
- }
-
- // A valid number should have integer or fractional part.
- if (!hasIntPart && !hasFracPart)
- return 0.0;
-
- // Parse optional exponent
- if (*cur == 'e' || *cur == 'E') {
- long expPart = 0;
- cur++; // skip 'E'
- expPart = strtol(cur, &end, 10); // Parse digit sequence with sign
- if (cur != end) {
- res *= pow(10.0, (double)expPart);
- }
- }
-
- return res * sign;
-}
-
-
-static const char* nsvg__parseNumber(const char* s, char* it, const int size)
-{
- const int last = size-1;
- int i = 0;
-
- // sign
- if (*s == '-' || *s == '+') {
- if (i < last) it[i++] = *s;
- s++;
- }
- // integer part
- while (*s && nsvg__isdigit(*s)) {
- if (i < last) it[i++] = *s;
- s++;
- }
- if (*s == '.') {
- // decimal point
- if (i < last) it[i++] = *s;
- s++;
- // fraction part
- while (*s && nsvg__isdigit(*s)) {
- if (i < last) it[i++] = *s;
- s++;
- }
- }
- // exponent
- if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) {
- if (i < last) it[i++] = *s;
- s++;
- if (*s == '-' || *s == '+') {
- if (i < last) it[i++] = *s;
- s++;
- }
- while (*s && nsvg__isdigit(*s)) {
- if (i < last) it[i++] = *s;
- s++;
- }
- }
- it[i] = '\0';
-
- return s;
-}
-
-static const char* nsvg__getNextPathItem(const char* s, char* it)
-{
- it[0] = '\0';
- // Skip white spaces and commas
- while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
- if (!*s) return s;
- if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) {
- s = nsvg__parseNumber(s, it, 64);
- } else {
- // Parse command
- it[0] = *s++;
- it[1] = '\0';
- return s;
- }
-
- return s;
-}
-
-static unsigned int nsvg__parseColorHex(const char* str)
-{
- unsigned int r=0, g=0, b=0;
- if (sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3 ) // 2 digit hex
- return NSVG_RGB(r, g, b);
- if (sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3 ) // 1 digit hex, e.g. #abc -> 0xccbbaa
- return NSVG_RGB(r*17, g*17, b*17); // same effect as (r<<4|r), (g<<4|g), ..
- return NSVG_RGB(128, 128, 128);
-}
-
-// Parse rgb color. The pointer 'str' must point at "rgb(" (4+ characters).
-// This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors
-// for backwards compatibility. Note: other image viewers return black instead.
-
-static unsigned int nsvg__parseColorRGB(const char* str)
-{
- int i;
- unsigned int rgbi[3];
- float rgbf[3];
- // try decimal integers first
- if (sscanf(str, "rgb(%u, %u, %u)", &rgbi[0], &rgbi[1], &rgbi[2]) != 3) {
- // integers failed, try percent values (float, locale independent)
- const char delimiter[3] = {',', ',', ')'};
- str += 4; // skip "rgb("
- for (i = 0; i < 3; i++) {
- while (*str && (nsvg__isspace(*str))) str++; // skip leading spaces
- if (*str == '+') str++; // skip '+' (don't allow '-')
- if (!*str) break;
- rgbf[i] = nsvg__atof(str);
-
- // Note 1: it would be great if nsvg__atof() returned how many
- // bytes it consumed but it doesn't. We need to skip the number,
- // the '%' character, spaces, and the delimiter ',' or ')'.
-
- // Note 2: The following code does not allow values like "33.%",
- // i.e. a decimal point w/o fractional part, but this is consistent
- // with other image viewers, e.g. firefox, chrome, eog, gimp.
-
- while (*str && nsvg__isdigit(*str)) str++; // skip integer part
- if (*str == '.') {
- str++;
- if (!nsvg__isdigit(*str)) break; // error: no digit after '.'
- while (*str && nsvg__isdigit(*str)) str++; // skip fractional part
- }
- if (*str == '%') str++; else break;
- while (nsvg__isspace(*str)) str++;
- if (*str == delimiter[i]) str++;
- else break;
- }
- if (i == 3) {
- rgbi[0] = roundf(rgbf[0] * 2.55f);
- rgbi[1] = roundf(rgbf[1] * 2.55f);
- rgbi[2] = roundf(rgbf[2] * 2.55f);
- } else {
- rgbi[0] = rgbi[1] = rgbi[2] = 128;
- }
- }
- // clip values as the CSS spec requires
- for (i = 0; i < 3; i++) {
- if (rgbi[i] > 255) rgbi[i] = 255;
- }
- return NSVG_RGB(rgbi[0], rgbi[1], rgbi[2]);
-}
-
-typedef struct NSVGNamedColor {
- const char* name;
- unsigned int color;
-} NSVGNamedColor;
-
-NSVGNamedColor nsvg__colors[] = {
-
- { "red", NSVG_RGB(255, 0, 0) },
- { "green", NSVG_RGB( 0, 128, 0) },
- { "blue", NSVG_RGB( 0, 0, 255) },
- { "yellow", NSVG_RGB(255, 255, 0) },
- { "cyan", NSVG_RGB( 0, 255, 255) },
- { "magenta", NSVG_RGB(255, 0, 255) },
- { "black", NSVG_RGB( 0, 0, 0) },
- { "grey", NSVG_RGB(128, 128, 128) },
- { "gray", NSVG_RGB(128, 128, 128) },
- { "white", NSVG_RGB(255, 255, 255) },
-
-#ifdef NANOSVG_ALL_COLOR_KEYWORDS
- { "aliceblue", NSVG_RGB(240, 248, 255) },
- { "antiquewhite", NSVG_RGB(250, 235, 215) },
- { "aqua", NSVG_RGB( 0, 255, 255) },
- { "aquamarine", NSVG_RGB(127, 255, 212) },
- { "azure", NSVG_RGB(240, 255, 255) },
- { "beige", NSVG_RGB(245, 245, 220) },
- { "bisque", NSVG_RGB(255, 228, 196) },
- { "blanchedalmond", NSVG_RGB(255, 235, 205) },
- { "blueviolet", NSVG_RGB(138, 43, 226) },
- { "brown", NSVG_RGB(165, 42, 42) },
- { "burlywood", NSVG_RGB(222, 184, 135) },
- { "cadetblue", NSVG_RGB( 95, 158, 160) },
- { "chartreuse", NSVG_RGB(127, 255, 0) },
- { "chocolate", NSVG_RGB(210, 105, 30) },
- { "coral", NSVG_RGB(255, 127, 80) },
- { "cornflowerblue", NSVG_RGB(100, 149, 237) },
- { "cornsilk", NSVG_RGB(255, 248, 220) },
- { "crimson", NSVG_RGB(220, 20, 60) },
- { "darkblue", NSVG_RGB( 0, 0, 139) },
- { "darkcyan", NSVG_RGB( 0, 139, 139) },
- { "darkgoldenrod", NSVG_RGB(184, 134, 11) },
- { "darkgray", NSVG_RGB(169, 169, 169) },
- { "darkgreen", NSVG_RGB( 0, 100, 0) },
- { "darkgrey", NSVG_RGB(169, 169, 169) },
- { "darkkhaki", NSVG_RGB(189, 183, 107) },
- { "darkmagenta", NSVG_RGB(139, 0, 139) },
- { "darkolivegreen", NSVG_RGB( 85, 107, 47) },
- { "darkorange", NSVG_RGB(255, 140, 0) },
- { "darkorchid", NSVG_RGB(153, 50, 204) },
- { "darkred", NSVG_RGB(139, 0, 0) },
- { "darksalmon", NSVG_RGB(233, 150, 122) },
- { "darkseagreen", NSVG_RGB(143, 188, 143) },
- { "darkslateblue", NSVG_RGB( 72, 61, 139) },
- { "darkslategray", NSVG_RGB( 47, 79, 79) },
- { "darkslategrey", NSVG_RGB( 47, 79, 79) },
- { "darkturquoise", NSVG_RGB( 0, 206, 209) },
- { "darkviolet", NSVG_RGB(148, 0, 211) },
- { "deeppink", NSVG_RGB(255, 20, 147) },
- { "deepskyblue", NSVG_RGB( 0, 191, 255) },
- { "dimgray", NSVG_RGB(105, 105, 105) },
- { "dimgrey", NSVG_RGB(105, 105, 105) },
- { "dodgerblue", NSVG_RGB( 30, 144, 255) },
- { "firebrick", NSVG_RGB(178, 34, 34) },
- { "floralwhite", NSVG_RGB(255, 250, 240) },
- { "forestgreen", NSVG_RGB( 34, 139, 34) },
- { "fuchsia", NSVG_RGB(255, 0, 255) },
- { "gainsboro", NSVG_RGB(220, 220, 220) },
- { "ghostwhite", NSVG_RGB(248, 248, 255) },
- { "gold", NSVG_RGB(255, 215, 0) },
- { "goldenrod", NSVG_RGB(218, 165, 32) },
- { "greenyellow", NSVG_RGB(173, 255, 47) },
- { "honeydew", NSVG_RGB(240, 255, 240) },
- { "hotpink", NSVG_RGB(255, 105, 180) },
- { "indianred", NSVG_RGB(205, 92, 92) },
- { "indigo", NSVG_RGB( 75, 0, 130) },
- { "ivory", NSVG_RGB(255, 255, 240) },
- { "khaki", NSVG_RGB(240, 230, 140) },
- { "lavender", NSVG_RGB(230, 230, 250) },
- { "lavenderblush", NSVG_RGB(255, 240, 245) },
- { "lawngreen", NSVG_RGB(124, 252, 0) },
- { "lemonchiffon", NSVG_RGB(255, 250, 205) },
- { "lightblue", NSVG_RGB(173, 216, 230) },
- { "lightcoral", NSVG_RGB(240, 128, 128) },
- { "lightcyan", NSVG_RGB(224, 255, 255) },
- { "lightgoldenrodyellow", NSVG_RGB(250, 250, 210) },
- { "lightgray", NSVG_RGB(211, 211, 211) },
- { "lightgreen", NSVG_RGB(144, 238, 144) },
- { "lightgrey", NSVG_RGB(211, 211, 211) },
- { "lightpink", NSVG_RGB(255, 182, 193) },
- { "lightsalmon", NSVG_RGB(255, 160, 122) },
- { "lightseagreen", NSVG_RGB( 32, 178, 170) },
- { "lightskyblue", NSVG_RGB(135, 206, 250) },
- { "lightslategray", NSVG_RGB(119, 136, 153) },
- { "lightslategrey", NSVG_RGB(119, 136, 153) },
- { "lightsteelblue", NSVG_RGB(176, 196, 222) },
- { "lightyellow", NSVG_RGB(255, 255, 224) },
- { "lime", NSVG_RGB( 0, 255, 0) },
- { "limegreen", NSVG_RGB( 50, 205, 50) },
- { "linen", NSVG_RGB(250, 240, 230) },
- { "maroon", NSVG_RGB(128, 0, 0) },
- { "mediumaquamarine", NSVG_RGB(102, 205, 170) },
- { "mediumblue", NSVG_RGB( 0, 0, 205) },
- { "mediumorchid", NSVG_RGB(186, 85, 211) },
- { "mediumpurple", NSVG_RGB(147, 112, 219) },
- { "mediumseagreen", NSVG_RGB( 60, 179, 113) },
- { "mediumslateblue", NSVG_RGB(123, 104, 238) },
- { "mediumspringgreen", NSVG_RGB( 0, 250, 154) },
- { "mediumturquoise", NSVG_RGB( 72, 209, 204) },
- { "mediumvioletred", NSVG_RGB(199, 21, 133) },
- { "midnightblue", NSVG_RGB( 25, 25, 112) },
- { "mintcream", NSVG_RGB(245, 255, 250) },
- { "mistyrose", NSVG_RGB(255, 228, 225) },
- { "moccasin", NSVG_RGB(255, 228, 181) },
- { "navajowhite", NSVG_RGB(255, 222, 173) },
- { "navy", NSVG_RGB( 0, 0, 128) },
- { "oldlace", NSVG_RGB(253, 245, 230) },
- { "olive", NSVG_RGB(128, 128, 0) },
- { "olivedrab", NSVG_RGB(107, 142, 35) },
- { "orange", NSVG_RGB(255, 165, 0) },
- { "orangered", NSVG_RGB(255, 69, 0) },
- { "orchid", NSVG_RGB(218, 112, 214) },
- { "palegoldenrod", NSVG_RGB(238, 232, 170) },
- { "palegreen", NSVG_RGB(152, 251, 152) },
- { "paleturquoise", NSVG_RGB(175, 238, 238) },
- { "palevioletred", NSVG_RGB(219, 112, 147) },
- { "papayawhip", NSVG_RGB(255, 239, 213) },
- { "peachpuff", NSVG_RGB(255, 218, 185) },
- { "peru", NSVG_RGB(205, 133, 63) },
- { "pink", NSVG_RGB(255, 192, 203) },
- { "plum", NSVG_RGB(221, 160, 221) },
- { "powderblue", NSVG_RGB(176, 224, 230) },
- { "purple", NSVG_RGB(128, 0, 128) },
- { "rosybrown", NSVG_RGB(188, 143, 143) },
- { "royalblue", NSVG_RGB( 65, 105, 225) },
- { "saddlebrown", NSVG_RGB(139, 69, 19) },
- { "salmon", NSVG_RGB(250, 128, 114) },
- { "sandybrown", NSVG_RGB(244, 164, 96) },
- { "seagreen", NSVG_RGB( 46, 139, 87) },
- { "seashell", NSVG_RGB(255, 245, 238) },
- { "sienna", NSVG_RGB(160, 82, 45) },
- { "silver", NSVG_RGB(192, 192, 192) },
- { "skyblue", NSVG_RGB(135, 206, 235) },
- { "slateblue", NSVG_RGB(106, 90, 205) },
- { "slategray", NSVG_RGB(112, 128, 144) },
- { "slategrey", NSVG_RGB(112, 128, 144) },
- { "snow", NSVG_RGB(255, 250, 250) },
- { "springgreen", NSVG_RGB( 0, 255, 127) },
- { "steelblue", NSVG_RGB( 70, 130, 180) },
- { "tan", NSVG_RGB(210, 180, 140) },
- { "teal", NSVG_RGB( 0, 128, 128) },
- { "thistle", NSVG_RGB(216, 191, 216) },
- { "tomato", NSVG_RGB(255, 99, 71) },
- { "turquoise", NSVG_RGB( 64, 224, 208) },
- { "violet", NSVG_RGB(238, 130, 238) },
- { "wheat", NSVG_RGB(245, 222, 179) },
- { "whitesmoke", NSVG_RGB(245, 245, 245) },
- { "yellowgreen", NSVG_RGB(154, 205, 50) },
-#endif
-};
-
-static unsigned int nsvg__parseColorName(const char* str)
-{
- int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);
-
- for (i = 0; i < ncolors; i++) {
- if (strcmp(nsvg__colors[i].name, str) == 0) {
- return nsvg__colors[i].color;
- }
- }
-
- return NSVG_RGB(128, 128, 128);
-}
-
-static unsigned int nsvg__parseColor(const char* str)
-{
- size_t len = 0;
- while(*str == ' ') ++str;
- len = strlen(str);
- if (len >= 1 && *str == '#')
- return nsvg__parseColorHex(str);
- else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')
- return nsvg__parseColorRGB(str);
- return nsvg__parseColorName(str);
-}
-
-static float nsvg__parseOpacity(const char* str)
-{
- float val = nsvg__atof(str);
- if (val < 0.0f) val = 0.0f;
- if (val > 1.0f) val = 1.0f;
- return val;
-}
-
-static float nsvg__parseMiterLimit(const char* str)
-{
- float val = nsvg__atof(str);
- if (val < 0.0f) val = 0.0f;
- return val;
-}
-
-static int nsvg__parseUnits(const char* units)
-{
- if (units[0] == 'p' && units[1] == 'x')
- return NSVG_UNITS_PX;
- else if (units[0] == 'p' && units[1] == 't')
- return NSVG_UNITS_PT;
- else if (units[0] == 'p' && units[1] == 'c')
- return NSVG_UNITS_PC;
- else if (units[0] == 'm' && units[1] == 'm')
- return NSVG_UNITS_MM;
- else if (units[0] == 'c' && units[1] == 'm')
- return NSVG_UNITS_CM;
- else if (units[0] == 'i' && units[1] == 'n')
- return NSVG_UNITS_IN;
- else if (units[0] == '%')
- return NSVG_UNITS_PERCENT;
- else if (units[0] == 'e' && units[1] == 'm')
- return NSVG_UNITS_EM;
- else if (units[0] == 'e' && units[1] == 'x')
- return NSVG_UNITS_EX;
- return NSVG_UNITS_USER;
-}
-
-static int nsvg__isCoordinate(const char* s)
-{
- // optional sign
- if (*s == '-' || *s == '+')
- s++;
- // must have at least one digit, or start by a dot
- return (nsvg__isdigit(*s) || *s == '.');
-}
-
-static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str)
-{
- NSVGcoordinate coord = {0, NSVG_UNITS_USER};
- char buf[64];
- coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64));
- coord.value = nsvg__atof(buf);
- return coord;
-}
-
-static NSVGcoordinate nsvg__coord(float v, int units)
-{
- NSVGcoordinate coord = {v, units};
- return coord;
-}
-
-static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length)
-{
- NSVGcoordinate coord = nsvg__parseCoordinateRaw(str);
- return nsvg__convertToPixels(p, coord, orig, length);
-}
-
-static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na)
-{
- const char* end;
- const char* ptr;
- char it[64];
-
- *na = 0;
- ptr = str;
- while (*ptr && *ptr != '(') ++ptr;
- if (*ptr == 0)
- return 1;
- end = ptr;
- while (*end && *end != ')') ++end;
- if (*end == 0)
- return 1;
-
- while (ptr < end) {
- if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) {
- if (*na >= maxNa) return 0;
- ptr = nsvg__parseNumber(ptr, it, 64);
- args[(*na)++] = (float)nsvg__atof(it);
- } else {
- ++ptr;
- }
- }
- return (int)(end - str);
-}
-
-
-static int nsvg__parseMatrix(float* xform, const char* str)
-{
- float t[6];
- int na = 0;
- int len = nsvg__parseTransformArgs(str, t, 6, &na);
- if (na != 6) return len;
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseTranslate(float* xform, const char* str)
-{
- float args[2];
- float t[6];
- int na = 0;
- int len = nsvg__parseTransformArgs(str, args, 2, &na);
- if (na == 1) args[1] = 0.0;
-
- nsvg__xformSetTranslation(t, args[0], args[1]);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseScale(float* xform, const char* str)
-{
- float args[2];
- int na = 0;
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 2, &na);
- if (na == 1) args[1] = args[0];
- nsvg__xformSetScale(t, args[0], args[1]);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseSkewX(float* xform, const char* str)
-{
- float args[1];
- int na = 0;
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 1, &na);
- nsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseSkewY(float* xform, const char* str)
-{
- float args[1];
- int na = 0;
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 1, &na);
- nsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI);
- memcpy(xform, t, sizeof(float)*6);
- return len;
-}
-
-static int nsvg__parseRotate(float* xform, const char* str)
-{
- float args[3];
- int na = 0;
- float m[6];
- float t[6];
- int len = nsvg__parseTransformArgs(str, args, 3, &na);
- if (na == 1)
- args[1] = args[2] = 0.0f;
- nsvg__xformIdentity(m);
-
- if (na > 1) {
- nsvg__xformSetTranslation(t, -args[1], -args[2]);
- nsvg__xformMultiply(m, t);
- }
-
- nsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI);
- nsvg__xformMultiply(m, t);
-
- if (na > 1) {
- nsvg__xformSetTranslation(t, args[1], args[2]);
- nsvg__xformMultiply(m, t);
- }
-
- memcpy(xform, m, sizeof(float)*6);
-
- return len;
-}
-
-static void nsvg__parseTransform(float* xform, const char* str)
-{
- float t[6];
- int len;
- nsvg__xformIdentity(xform);
- while (*str)
- {
- if (strncmp(str, "matrix", 6) == 0)
- len = nsvg__parseMatrix(t, str);
- else if (strncmp(str, "translate", 9) == 0)
- len = nsvg__parseTranslate(t, str);
- else if (strncmp(str, "scale", 5) == 0)
- len = nsvg__parseScale(t, str);
- else if (strncmp(str, "rotate", 6) == 0)
- len = nsvg__parseRotate(t, str);
- else if (strncmp(str, "skewX", 5) == 0)
- len = nsvg__parseSkewX(t, str);
- else if (strncmp(str, "skewY", 5) == 0)
- len = nsvg__parseSkewY(t, str);
- else{
- ++str;
- continue;
- }
- if (len != 0) {
- str += len;
- } else {
- ++str;
- continue;
- }
-
- nsvg__xformPremultiply(xform, t);
- }
-}
-
-static void nsvg__parseUrl(char* id, const char* str)
-{
- int i = 0;
- str += 4; // "url(";
- if (*str && *str == '#')
- str++;
- while (i < 63 && *str && *str != ')') {
- id[i] = *str++;
- i++;
- }
- id[i] = '\0';
-}
-
-static char nsvg__parseLineCap(const char* str)
-{
- if (strcmp(str, "butt") == 0)
- return NSVG_CAP_BUTT;
- else if (strcmp(str, "round") == 0)
- return NSVG_CAP_ROUND;
- else if (strcmp(str, "square") == 0)
- return NSVG_CAP_SQUARE;
- // TODO: handle inherit.
- return NSVG_CAP_BUTT;
-}
-
-static char nsvg__parseLineJoin(const char* str)
-{
- if (strcmp(str, "miter") == 0)
- return NSVG_JOIN_MITER;
- else if (strcmp(str, "round") == 0)
- return NSVG_JOIN_ROUND;
- else if (strcmp(str, "bevel") == 0)
- return NSVG_JOIN_BEVEL;
- // TODO: handle inherit.
- return NSVG_JOIN_MITER;
-}
-
-static char nsvg__parseFillRule(const char* str)
-{
- if (strcmp(str, "nonzero") == 0)
- return NSVG_FILLRULE_NONZERO;
- else if (strcmp(str, "evenodd") == 0)
- return NSVG_FILLRULE_EVENODD;
- // TODO: handle inherit.
- return NSVG_FILLRULE_NONZERO;
-}
-
-static const char* nsvg__getNextDashItem(const char* s, char* it)
-{
- int n = 0;
- it[0] = '\0';
- // Skip white spaces and commas
- while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
- // Advance until whitespace, comma or end.
- while (*s && (!nsvg__isspace(*s) && *s != ',')) {
- if (n < 63)
- it[n++] = *s;
- s++;
- }
- it[n++] = '\0';
- return s;
-}
-
-static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray)
-{
- char item[64];
- int count = 0, i;
- float sum = 0.0f;
-
- // Handle "none"
- if (str[0] == 'n')
- return 0;
-
- // Parse dashes
- while (*str) {
- str = nsvg__getNextDashItem(str, item);
- if (!*item) break;
- if (count < NSVG_MAX_DASHES)
- strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p)));
- }
-
- for (i = 0; i < count; i++)
- sum += strokeDashArray[i];
- if (sum <= 1e-6f)
- count = 0;
-
- return count;
-}
-
-static void nsvg__parseStyle(NSVGparser* p, const char* str);
-
-static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value)
-{
- float xform[6];
- NSVGattrib* attr = nsvg__getAttr(p);
- if (!attr) return 0;
-
- if (strcmp(name, "style") == 0) {
- nsvg__parseStyle(p, value);
- } else if (strcmp(name, "display") == 0) {
- if (strcmp(value, "none") == 0)
- attr->visible = 0;
- // Don't reset ->visible on display:inline, one display:none hides the whole subtree
-
- } else if (strcmp(name, "fill") == 0) {
- if (strcmp(value, "none") == 0) {
- attr->hasFill = 0;
- } else if (strncmp(value, "url(", 4) == 0) {
- attr->hasFill = 2;
- nsvg__parseUrl(attr->fillGradient, value);
- } else {
- attr->hasFill = 1;
- attr->fillColor = nsvg__parseColor(value);
- }
- } else if (strcmp(name, "opacity") == 0) {
- attr->opacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "fill-opacity") == 0) {
- attr->fillOpacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "stroke") == 0) {
- if (strcmp(value, "none") == 0) {
- attr->hasStroke = 0;
- } else if (strncmp(value, "url(", 4) == 0) {
- attr->hasStroke = 2;
- nsvg__parseUrl(attr->strokeGradient, value);
- } else {
- attr->hasStroke = 1;
- attr->strokeColor = nsvg__parseColor(value);
- }
- } else if (strcmp(name, "stroke-width") == 0) {
- attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
- } else if (strcmp(name, "stroke-dasharray") == 0) {
- attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray);
- } else if (strcmp(name, "stroke-dashoffset") == 0) {
- attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
- } else if (strcmp(name, "stroke-opacity") == 0) {
- attr->strokeOpacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "stroke-linecap") == 0) {
- attr->strokeLineCap = nsvg__parseLineCap(value);
- } else if (strcmp(name, "stroke-linejoin") == 0) {
- attr->strokeLineJoin = nsvg__parseLineJoin(value);
- } else if (strcmp(name, "stroke-miterlimit") == 0) {
- attr->miterLimit = nsvg__parseMiterLimit(value);
- } else if (strcmp(name, "fill-rule") == 0) {
- attr->fillRule = nsvg__parseFillRule(value);
- } else if (strcmp(name, "font-size") == 0) {
- attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
- } else if (strcmp(name, "transform") == 0) {
- nsvg__parseTransform(xform, value);
- nsvg__xformPremultiply(attr->xform, xform);
- } else if (strcmp(name, "stop-color") == 0) {
- attr->stopColor = nsvg__parseColor(value);
- } else if (strcmp(name, "stop-opacity") == 0) {
- attr->stopOpacity = nsvg__parseOpacity(value);
- } else if (strcmp(name, "offset") == 0) {
- attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
- } else if (strcmp(name, "id") == 0) {
- strncpy(attr->id, value, 63);
- attr->id[63] = '\0';
- } else {
- return 0;
- }
- return 1;
-}
-
-static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end)
-{
- const char* str;
- const char* val;
- char name[512];
- char value[512];
- int n;
-
- str = start;
- while (str < end && *str != ':') ++str;
-
- val = str;
-
- // Right Trim
- while (str > start && (*str == ':' || nsvg__isspace(*str))) --str;
- ++str;
-
- n = (int)(str - start);
- if (n > 511) n = 511;
- if (n) memcpy(name, start, n);
- name[n] = 0;
-
- while (val < end && (*val == ':' || nsvg__isspace(*val))) ++val;
-
- n = (int)(end - val);
- if (n > 511) n = 511;
- if (n) memcpy(value, val, n);
- value[n] = 0;
-
- return nsvg__parseAttr(p, name, value);
-}
-
-static void nsvg__parseStyle(NSVGparser* p, const char* str)
-{
- const char* start;
- const char* end;
-
- while (*str) {
- // Left Trim
- while(*str && nsvg__isspace(*str)) ++str;
- start = str;
- while(*str && *str != ';') ++str;
- end = str;
-
- // Right Trim
- while (end > start && (*end == ';' || nsvg__isspace(*end))) --end;
- ++end;
-
- nsvg__parseNameValue(p, start, end);
- if (*str) ++str;
- }
-}
-
-static void nsvg__parseAttribs(NSVGparser* p, const char** attr)
-{
- int i;
- for (i = 0; attr[i]; i += 2)
- {
- if (strcmp(attr[i], "style") == 0)
- nsvg__parseStyle(p, attr[i + 1]);
- else
- nsvg__parseAttr(p, attr[i], attr[i + 1]);
- }
-}
-
-static int nsvg__getArgsPerElement(char cmd)
-{
- switch (cmd) {
- case 'v':
- case 'V':
- case 'h':
- case 'H':
- return 1;
- case 'm':
- case 'M':
- case 'l':
- case 'L':
- case 't':
- case 'T':
- return 2;
- case 'q':
- case 'Q':
- case 's':
- case 'S':
- return 4;
- case 'c':
- case 'C':
- return 6;
- case 'a':
- case 'A':
- return 7;
- case 'z':
- case 'Z':
- return 0;
- }
- return -1;
-}
-
-static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel) {
- *cpx += args[0];
- *cpy += args[1];
- } else {
- *cpx = args[0];
- *cpy = args[1];
- }
- nsvg__moveTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel) {
- *cpx += args[0];
- *cpy += args[1];
- } else {
- *cpx = args[0];
- *cpy = args[1];
- }
- nsvg__lineTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel)
- *cpx += args[0];
- else
- *cpx = args[0];
- nsvg__lineTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- if (rel)
- *cpy += args[0];
- else
- *cpy = args[0];
- nsvg__lineTo(p, *cpx, *cpy);
-}
-
-static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x2, y2, cx1, cy1, cx2, cy2;
-
- if (rel) {
- cx1 = *cpx + args[0];
- cy1 = *cpy + args[1];
- cx2 = *cpx + args[2];
- cy2 = *cpy + args[3];
- x2 = *cpx + args[4];
- y2 = *cpy + args[5];
- } else {
- cx1 = args[0];
- cy1 = args[1];
- cx2 = args[2];
- cy2 = args[3];
- x2 = args[4];
- y2 = args[5];
- }
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx2;
- *cpy2 = cy2;
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
-
- x1 = *cpx;
- y1 = *cpy;
- if (rel) {
- cx2 = *cpx + args[0];
- cy2 = *cpy + args[1];
- x2 = *cpx + args[2];
- y2 = *cpy + args[3];
- } else {
- cx2 = args[0];
- cy2 = args[1];
- x2 = args[2];
- y2 = args[3];
- }
-
- cx1 = 2*x1 - *cpx2;
- cy1 = 2*y1 - *cpy2;
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx2;
- *cpy2 = cy2;
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x1, y1, x2, y2, cx, cy;
- float cx1, cy1, cx2, cy2;
-
- x1 = *cpx;
- y1 = *cpy;
- if (rel) {
- cx = *cpx + args[0];
- cy = *cpy + args[1];
- x2 = *cpx + args[2];
- y2 = *cpy + args[3];
- } else {
- cx = args[0];
- cy = args[1];
- x2 = args[2];
- y2 = args[3];
- }
-
- // Convert to cubic bezier
- cx1 = x1 + 2.0f/3.0f*(cx - x1);
- cy1 = y1 + 2.0f/3.0f*(cy - y1);
- cx2 = x2 + 2.0f/3.0f*(cx - x2);
- cy2 = y2 + 2.0f/3.0f*(cy - y2);
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx;
- *cpy2 = cy;
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy,
- float* cpx2, float* cpy2, float* args, int rel)
-{
- float x1, y1, x2, y2, cx, cy;
- float cx1, cy1, cx2, cy2;
-
- x1 = *cpx;
- y1 = *cpy;
- if (rel) {
- x2 = *cpx + args[0];
- y2 = *cpy + args[1];
- } else {
- x2 = args[0];
- y2 = args[1];
- }
-
- cx = 2*x1 - *cpx2;
- cy = 2*y1 - *cpy2;
-
- // Convert to cubix bezier
- cx1 = x1 + 2.0f/3.0f*(cx - x1);
- cy1 = y1 + 2.0f/3.0f*(cy - y1);
- cx2 = x2 + 2.0f/3.0f*(cx - x2);
- cy2 = y2 + 2.0f/3.0f*(cy - y2);
-
- nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
-
- *cpx2 = cx;
- *cpy2 = cy;
- *cpx = x2;
- *cpy = y2;
-}
-
-static float nsvg__sqr(float x) { return x*x; }
-static float nsvg__vmag(float x, float y) { return sqrtf(x*x + y*y); }
-
-static float nsvg__vecrat(float ux, float uy, float vx, float vy)
-{
- return (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy));
-}
-
-static float nsvg__vecang(float ux, float uy, float vx, float vy)
-{
- float r = nsvg__vecrat(ux,uy, vx,vy);
- if (r < -1.0f) r = -1.0f;
- if (r > 1.0f) r = 1.0f;
- return ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r);
-}
-
-static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
-{
- // Ported from canvg (https://code.google.com/p/canvg/)
- float rx, ry, rotx;
- float x1, y1, x2, y2, cx, cy, dx, dy, d;
- float x1p, y1p, cxp, cyp, s, sa, sb;
- float ux, uy, vx, vy, a1, da;
- float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];
- float sinrx, cosrx;
- int fa, fs;
- int i, ndivs;
- float hda, kappa;
-
- rx = fabsf(args[0]); // y radius
- ry = fabsf(args[1]); // x radius
- rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle
- fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc
- fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction
- x1 = *cpx; // start point
- y1 = *cpy;
- if (rel) { // end point
- x2 = *cpx + args[5];
- y2 = *cpy + args[6];
- } else {
- x2 = args[5];
- y2 = args[6];
- }
-
- dx = x1 - x2;
- dy = y1 - y2;
- d = sqrtf(dx*dx + dy*dy);
- if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {
- // The arc degenerates to a line
- nsvg__lineTo(p, x2, y2);
- *cpx = x2;
- *cpy = y2;
- return;
- }
-
- sinrx = sinf(rotx);
- cosrx = cosf(rotx);
-
- // Convert to center point parameterization.
- // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
- // 1) Compute x1', y1'
- x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;
- y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;
- d = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry);
- if (d > 1) {
- d = sqrtf(d);
- rx *= d;
- ry *= d;
- }
- // 2) Compute cx', cy'
- s = 0.0f;
- sa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p);
- sb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p);
- if (sa < 0.0f) sa = 0.0f;
- if (sb > 0.0f)
- s = sqrtf(sa / sb);
- if (fa == fs)
- s = -s;
- cxp = s * rx * y1p / ry;
- cyp = s * -ry * x1p / rx;
-
- // 3) Compute cx,cy from cx',cy'
- cx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp;
- cy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp;
-
- // 4) Calculate theta1, and delta theta.
- ux = (x1p - cxp) / rx;
- uy = (y1p - cyp) / ry;
- vx = (-x1p - cxp) / rx;
- vy = (-y1p - cyp) / ry;
- a1 = nsvg__vecang(1.0f,0.0f, ux,uy); // Initial angle
- da = nsvg__vecang(ux,uy, vx,vy); // Delta angle
-
-// if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI;
-// if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0;
-
- if (fs == 0 && da > 0)
- da -= 2 * NSVG_PI;
- else if (fs == 1 && da < 0)
- da += 2 * NSVG_PI;
-
- // Approximate the arc using cubic spline segments.
- t[0] = cosrx; t[1] = sinrx;
- t[2] = -sinrx; t[3] = cosrx;
- t[4] = cx; t[5] = cy;
-
- // Split arc into max 90 degree segments.
- // The loop assumes an iteration per end point (including start and end), this +1.
- ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);
- hda = (da / (float)ndivs) / 2.0f;
- // Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite)
- if ((hda < 1e-3f) && (hda > -1e-3f))
- hda *= 0.5f;
- else
- hda = (1.0f - cosf(hda)) / sinf(hda);
- kappa = fabsf(4.0f / 3.0f * hda);
- if (da < 0.0f)
- kappa = -kappa;
-
- for (i = 0; i <= ndivs; i++) {
- a = a1 + da * ((float)i/(float)ndivs);
- dx = cosf(a);
- dy = sinf(a);
- nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); // position
- nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); // tangent
- if (i > 0)
- nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y);
- px = x;
- py = y;
- ptanx = tanx;
- ptany = tany;
- }
-
- *cpx = x2;
- *cpy = y2;
-}
-
-static void nsvg__parsePath(NSVGparser* p, const char** attr)
-{
- const char* s = NULL;
- char cmd = '\0';
- float args[10];
- int nargs;
- int rargs = 0;
- char initPoint;
- float cpx, cpy, cpx2, cpy2;
- const char* tmp[4];
- char closedFlag;
- int i;
- char item[64];
-
- for (i = 0; attr[i]; i += 2) {
- if (strcmp(attr[i], "d") == 0) {
- s = attr[i + 1];
- } else {
- tmp[0] = attr[i];
- tmp[1] = attr[i + 1];
- tmp[2] = 0;
- tmp[3] = 0;
- nsvg__parseAttribs(p, tmp);
- }
- }
-
- if (s) {
- nsvg__resetPath(p);
- cpx = 0; cpy = 0;
- cpx2 = 0; cpy2 = 0;
- initPoint = 0;
- closedFlag = 0;
- nargs = 0;
-
- while (*s) {
- s = nsvg__getNextPathItem(s, item);
- if (!*item) break;
- if (cmd != '\0' && nsvg__isCoordinate(item)) {
- if (nargs < 10)
- args[nargs++] = (float)nsvg__atof(item);
- if (nargs >= rargs) {
- switch (cmd) {
- case 'm':
- case 'M':
- nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
- // Moveto can be followed by multiple coordinate pairs,
- // which should be treated as linetos.
- cmd = (cmd == 'm') ? 'l' : 'L';
- rargs = nsvg__getArgsPerElement(cmd);
- cpx2 = cpx; cpy2 = cpy;
- initPoint = 1;
- break;
- case 'l':
- case 'L':
- nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'H':
- case 'h':
- nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'V':
- case 'v':
- nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- case 'C':
- case 'c':
- nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
- break;
- case 'S':
- case 's':
- nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
- break;
- case 'Q':
- case 'q':
- nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
- break;
- case 'T':
- case 't':
- nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0);
- break;
- case 'A':
- case 'a':
- nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);
- cpx2 = cpx; cpy2 = cpy;
- break;
- default:
- if (nargs >= 2) {
- cpx = args[nargs-2];
- cpy = args[nargs-1];
- cpx2 = cpx; cpy2 = cpy;
- }
- break;
- }
- nargs = 0;
- }
- } else {
- cmd = item[0];
- if (cmd == 'M' || cmd == 'm') {
- // Commit path.
- if (p->npts > 0)
- nsvg__addPath(p, closedFlag);
- // Start new subpath.
- nsvg__resetPath(p);
- closedFlag = 0;
- nargs = 0;
- } else if (initPoint == 0) {
- // Do not allow other commands until initial point has been set (moveTo called once).
- cmd = '\0';
- }
- if (cmd == 'Z' || cmd == 'z') {
- closedFlag = 1;
- // Commit path.
- if (p->npts > 0) {
- // Move current point to first point
- cpx = p->pts[0];
- cpy = p->pts[1];
- cpx2 = cpx; cpy2 = cpy;
- nsvg__addPath(p, closedFlag);
- }
- // Start new subpath.
- nsvg__resetPath(p);
- nsvg__moveTo(p, cpx, cpy);
- closedFlag = 0;
- nargs = 0;
- }
- rargs = nsvg__getArgsPerElement(cmd);
- if (rargs == -1) {
- // Command not recognized
- cmd = '\0';
- rargs = 0;
- }
- }
- }
- // Commit path.
- if (p->npts)
- nsvg__addPath(p, closedFlag);
- }
-
- nsvg__addShape(p);
-}
-
-static void nsvg__parseRect(NSVGparser* p, const char** attr)
-{
- float x = 0.0f;
- float y = 0.0f;
- float w = 0.0f;
- float h = 0.0f;
- float rx = -1.0f; // marks not set
- float ry = -1.0f;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "width") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p));
- if (strcmp(attr[i], "height") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p));
- if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
- if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
- }
- }
-
- if (rx < 0.0f && ry > 0.0f) rx = ry;
- if (ry < 0.0f && rx > 0.0f) ry = rx;
- if (rx < 0.0f) rx = 0.0f;
- if (ry < 0.0f) ry = 0.0f;
- if (rx > w/2.0f) rx = w/2.0f;
- if (ry > h/2.0f) ry = h/2.0f;
-
- if (w != 0.0f && h != 0.0f) {
- nsvg__resetPath(p);
-
- if (rx < 0.00001f || ry < 0.0001f) {
- nsvg__moveTo(p, x, y);
- nsvg__lineTo(p, x+w, y);
- nsvg__lineTo(p, x+w, y+h);
- nsvg__lineTo(p, x, y+h);
- } else {
- // Rounded rectangle
- nsvg__moveTo(p, x+rx, y);
- nsvg__lineTo(p, x+w-rx, y);
- nsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry);
- nsvg__lineTo(p, x+w, y+h-ry);
- nsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h);
- nsvg__lineTo(p, x+rx, y+h);
- nsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry);
- nsvg__lineTo(p, x, y+ry);
- nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y);
- }
-
- nsvg__addPath(p, 1);
-
- nsvg__addShape(p);
- }
-}
-
-static void nsvg__parseCircle(NSVGparser* p, const char** attr)
-{
- float cx = 0.0f;
- float cy = 0.0f;
- float r = 0.0f;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "r") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p)));
- }
- }
-
- if (r > 0.0f) {
- nsvg__resetPath(p);
-
- nsvg__moveTo(p, cx+r, cy);
- nsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r);
- nsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy);
- nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r);
- nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy);
-
- nsvg__addPath(p, 1);
-
- nsvg__addShape(p);
- }
-}
-
-static void nsvg__parseEllipse(NSVGparser* p, const char** attr)
-{
- float cx = 0.0f;
- float cy = 0.0f;
- float rx = 0.0f;
- float ry = 0.0f;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
- if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
- }
- }
-
- if (rx > 0.0f && ry > 0.0f) {
-
- nsvg__resetPath(p);
-
- nsvg__moveTo(p, cx+rx, cy);
- nsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry);
- nsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy);
- nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry);
- nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy);
-
- nsvg__addPath(p, 1);
-
- nsvg__addShape(p);
- }
-}
-
-static void nsvg__parseLine(NSVGparser* p, const char** attr)
-{
- float x1 = 0.0;
- float y1 = 0.0;
- float x2 = 0.0;
- float y2 = 0.0;
- int i;
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "x1") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "y1") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- if (strcmp(attr[i], "x2") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
- if (strcmp(attr[i], "y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
- }
- }
-
- nsvg__resetPath(p);
-
- nsvg__moveTo(p, x1, y1);
- nsvg__lineTo(p, x2, y2);
-
- nsvg__addPath(p, 0);
-
- nsvg__addShape(p);
-}
-
-static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag)
-{
- int i;
- const char* s;
- float args[2];
- int nargs, npts = 0;
- char item[64];
-
- nsvg__resetPath(p);
-
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "points") == 0) {
- s = attr[i + 1];
- nargs = 0;
- while (*s) {
- s = nsvg__getNextPathItem(s, item);
- args[nargs++] = (float)nsvg__atof(item);
- if (nargs >= 2) {
- if (npts == 0)
- nsvg__moveTo(p, args[0], args[1]);
- else
- nsvg__lineTo(p, args[0], args[1]);
- nargs = 0;
- npts++;
- }
- }
- }
- }
- }
-
- nsvg__addPath(p, (char)closeFlag);
-
- nsvg__addShape(p);
-}
-
-static void nsvg__parseSVG(NSVGparser* p, const char** attr)
-{
- int i;
- for (i = 0; attr[i]; i += 2) {
- if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "width") == 0) {
- p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
- } else if (strcmp(attr[i], "height") == 0) {
- p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
- } else if (strcmp(attr[i], "viewBox") == 0) {
- const char *s = attr[i + 1];
- char buf[64];
- s = nsvg__parseNumber(s, buf, 64);
- p->viewMinx = nsvg__atof(buf);
- while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++;
- if (!*s) return;
- s = nsvg__parseNumber(s, buf, 64);
- p->viewMiny = nsvg__atof(buf);
- while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++;
- if (!*s) return;
- s = nsvg__parseNumber(s, buf, 64);
- p->viewWidth = nsvg__atof(buf);
- while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++;
- if (!*s) return;
- s = nsvg__parseNumber(s, buf, 64);
- p->viewHeight = nsvg__atof(buf);
- } else if (strcmp(attr[i], "preserveAspectRatio") == 0) {
- if (strstr(attr[i + 1], "none") != 0) {
- // No uniform scaling
- p->alignType = NSVG_ALIGN_NONE;
- } else {
- // Parse X align
- if (strstr(attr[i + 1], "xMin") != 0)
- p->alignX = NSVG_ALIGN_MIN;
- else if (strstr(attr[i + 1], "xMid") != 0)
- p->alignX = NSVG_ALIGN_MID;
- else if (strstr(attr[i + 1], "xMax") != 0)
- p->alignX = NSVG_ALIGN_MAX;
- // Parse X align
- if (strstr(attr[i + 1], "yMin") != 0)
- p->alignY = NSVG_ALIGN_MIN;
- else if (strstr(attr[i + 1], "yMid") != 0)
- p->alignY = NSVG_ALIGN_MID;
- else if (strstr(attr[i + 1], "yMax") != 0)
- p->alignY = NSVG_ALIGN_MAX;
- // Parse meet/slice
- p->alignType = NSVG_ALIGN_MEET;
- if (strstr(attr[i + 1], "slice") != 0)
- p->alignType = NSVG_ALIGN_SLICE;
- }
- }
- }
- }
-}
-
-static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type)
-{
- int i;
- NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData));
- if (grad == NULL) return;
- memset(grad, 0, sizeof(NSVGgradientData));
- grad->units = NSVG_OBJECT_SPACE;
- grad->type = type;
- if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) {
- grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
- grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
- grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT);
- grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
- } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) {
- grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
- grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
- grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
- }
-
- nsvg__xformIdentity(grad->xform);
-
- for (i = 0; attr[i]; i += 2) {
- if (strcmp(attr[i], "id") == 0) {
- strncpy(grad->id, attr[i+1], 63);
- grad->id[63] = '\0';
- } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
- if (strcmp(attr[i], "gradientUnits") == 0) {
- if (strcmp(attr[i+1], "objectBoundingBox") == 0)
- grad->units = NSVG_OBJECT_SPACE;
- else
- grad->units = NSVG_USER_SPACE;
- } else if (strcmp(attr[i], "gradientTransform") == 0) {
- nsvg__parseTransform(grad->xform, attr[i + 1]);
- } else if (strcmp(attr[i], "cx") == 0) {
- grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "cy") == 0) {
- grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "r") == 0) {
- grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "fx") == 0) {
- grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "fy") == 0) {
- grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "x1") == 0) {
- grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "y1") == 0) {
- grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "x2") == 0) {
- grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "y2") == 0) {
- grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]);
- } else if (strcmp(attr[i], "spreadMethod") == 0) {
- if (strcmp(attr[i+1], "pad") == 0)
- grad->spread = NSVG_SPREAD_PAD;
- else if (strcmp(attr[i+1], "reflect") == 0)
- grad->spread = NSVG_SPREAD_REFLECT;
- else if (strcmp(attr[i+1], "repeat") == 0)
- grad->spread = NSVG_SPREAD_REPEAT;
- } else if (strcmp(attr[i], "xlink:href") == 0) {
- const char *href = attr[i+1];
- strncpy(grad->ref, href+1, 62);
- grad->ref[62] = '\0';
- }
- }
- }
-
- grad->next = p->gradients;
- p->gradients = grad;
-}
-
-static void nsvg__parseGradientStop(NSVGparser* p, const char** attr)
-{
- NSVGattrib* curAttr = nsvg__getAttr(p);
- NSVGgradientData* grad;
- NSVGgradientStop* stop;
- int i, idx;
-
- curAttr->stopOffset = 0;
- curAttr->stopColor = 0;
- curAttr->stopOpacity = 1.0f;
-
- for (i = 0; attr[i]; i += 2) {
- nsvg__parseAttr(p, attr[i], attr[i + 1]);
- }
-
- // Add stop to the last gradient.
- grad = p->gradients;
- if (grad == NULL) return;
-
- grad->nstops++;
- grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop)*grad->nstops);
- if (grad->stops == NULL) return;
-
- // Insert
- idx = grad->nstops-1;
- for (i = 0; i < grad->nstops-1; i++) {
- if (curAttr->stopOffset < grad->stops[i].offset) {
- idx = i;
- break;
- }
- }
- if (idx != grad->nstops-1) {
- for (i = grad->nstops-1; i > idx; i--)
- grad->stops[i] = grad->stops[i-1];
- }
-
- stop = &grad->stops[idx];
- stop->color = curAttr->stopColor;
- stop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24;
- stop->offset = curAttr->stopOffset;
-}
-
-static void nsvg__startElement(void* ud, const char* el, const char** attr)
-{
- NSVGparser* p = (NSVGparser*)ud;
-
- if (p->defsFlag) {
- // Skip everything but gradients in defs
- if (strcmp(el, "linearGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
- } else if (strcmp(el, "radialGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
- } else if (strcmp(el, "stop") == 0) {
- nsvg__parseGradientStop(p, attr);
- }
- return;
- }
-
- if (strcmp(el, "g") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseAttribs(p, attr);
- } else if (strcmp(el, "path") == 0) {
- if (p->pathFlag) // Do not allow nested paths.
- return;
- nsvg__pushAttr(p);
- nsvg__parsePath(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "rect") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseRect(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "circle") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseCircle(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "ellipse") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseEllipse(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "line") == 0) {
- nsvg__pushAttr(p);
- nsvg__parseLine(p, attr);
- nsvg__popAttr(p);
- } else if (strcmp(el, "polyline") == 0) {
- nsvg__pushAttr(p);
- nsvg__parsePoly(p, attr, 0);
- nsvg__popAttr(p);
- } else if (strcmp(el, "polygon") == 0) {
- nsvg__pushAttr(p);
- nsvg__parsePoly(p, attr, 1);
- nsvg__popAttr(p);
- } else if (strcmp(el, "linearGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
- } else if (strcmp(el, "radialGradient") == 0) {
- nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
- } else if (strcmp(el, "stop") == 0) {
- nsvg__parseGradientStop(p, attr);
- } else if (strcmp(el, "defs") == 0) {
- p->defsFlag = 1;
- } else if (strcmp(el, "svg") == 0) {
- nsvg__parseSVG(p, attr);
- }
-}
-
-static void nsvg__endElement(void* ud, const char* el)
-{
- NSVGparser* p = (NSVGparser*)ud;
-
- if (strcmp(el, "g") == 0) {
- nsvg__popAttr(p);
- } else if (strcmp(el, "path") == 0) {
- p->pathFlag = 0;
- } else if (strcmp(el, "defs") == 0) {
- p->defsFlag = 0;
- }
-}
-
-static void nsvg__content(void* ud, const char* s)
-{
- NSVG_NOTUSED(ud);
- NSVG_NOTUSED(s);
- // empty
-}
-
-static void nsvg__imageBounds(NSVGparser* p, float* bounds)
-{
- NSVGshape* shape;
- shape = p->image->shapes;
- if (shape == NULL) {
- bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
- return;
- }
- bounds[0] = shape->bounds[0];
- bounds[1] = shape->bounds[1];
- bounds[2] = shape->bounds[2];
- bounds[3] = shape->bounds[3];
- for (shape = shape->next; shape != NULL; shape = shape->next) {
- bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);
- bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);
- bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]);
- bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]);
- }
-}
-
-static float nsvg__viewAlign(float content, float container, int type)
-{
- if (type == NSVG_ALIGN_MIN)
- return 0;
- else if (type == NSVG_ALIGN_MAX)
- return container - content;
- // mid
- return (container - content) * 0.5f;
-}
-
-static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy)
-{
- float t[6];
- nsvg__xformSetTranslation(t, tx, ty);
- nsvg__xformMultiply (grad->xform, t);
-
- nsvg__xformSetScale(t, sx, sy);
- nsvg__xformMultiply (grad->xform, t);
-}
-
-static void nsvg__scaleToViewbox(NSVGparser* p, const char* units)
-{
- NSVGshape* shape;
- NSVGpath* path;
- float tx, ty, sx, sy, us, bounds[4], t[6], avgs;
- int i;
- float* pt;
-
- // Guess image size if not set completely.
- nsvg__imageBounds(p, bounds);
-
- if (p->viewWidth == 0) {
- if (p->image->width > 0) {
- p->viewWidth = p->image->width;
- } else {
- p->viewMinx = bounds[0];
- p->viewWidth = bounds[2] - bounds[0];
- }
- }
- if (p->viewHeight == 0) {
- if (p->image->height > 0) {
- p->viewHeight = p->image->height;
- } else {
- p->viewMiny = bounds[1];
- p->viewHeight = bounds[3] - bounds[1];
- }
- }
- if (p->image->width == 0)
- p->image->width = p->viewWidth;
- if (p->image->height == 0)
- p->image->height = p->viewHeight;
-
- tx = -p->viewMinx;
- ty = -p->viewMiny;
- sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0;
- sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0;
- // Unit scaling
- us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);
-
- // Fix aspect ratio
- if (p->alignType == NSVG_ALIGN_MEET) {
- // fit whole image into viewbox
- sx = sy = nsvg__minf(sx, sy);
- tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;
- ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;
- } else if (p->alignType == NSVG_ALIGN_SLICE) {
- // fill whole viewbox with image
- sx = sy = nsvg__maxf(sx, sy);
- tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;
- ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;
- }
-
- // Transform
- sx *= us;
- sy *= us;
- avgs = (sx+sy) / 2.0f;
- for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
- shape->bounds[0] = (shape->bounds[0] + tx) * sx;
- shape->bounds[1] = (shape->bounds[1] + ty) * sy;
- shape->bounds[2] = (shape->bounds[2] + tx) * sx;
- shape->bounds[3] = (shape->bounds[3] + ty) * sy;
- for (path = shape->paths; path != NULL; path = path->next) {
- path->bounds[0] = (path->bounds[0] + tx) * sx;
- path->bounds[1] = (path->bounds[1] + ty) * sy;
- path->bounds[2] = (path->bounds[2] + tx) * sx;
- path->bounds[3] = (path->bounds[3] + ty) * sy;
- for (i =0; i < path->npts; i++) {
- pt = &path->pts[i*2];
- pt[0] = (pt[0] + tx) * sx;
- pt[1] = (pt[1] + ty) * sy;
- }
- }
-
- if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) {
- nsvg__scaleGradient(shape->fill.gradient, tx,ty, sx,sy);
- memcpy(t, shape->fill.gradient->xform, sizeof(float)*6);
- nsvg__xformInverse(shape->fill.gradient->xform, t);
- }
- if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) {
- nsvg__scaleGradient(shape->stroke.gradient, tx,ty, sx,sy);
- memcpy(t, shape->stroke.gradient->xform, sizeof(float)*6);
- nsvg__xformInverse(shape->stroke.gradient->xform, t);
- }
-
- shape->strokeWidth *= avgs;
- shape->strokeDashOffset *= avgs;
- for (i = 0; i < shape->strokeDashCount; i++)
- shape->strokeDashArray[i] *= avgs;
- }
-}
-
-NSVGimage* nsvgParse(char* input, const char* units, float dpi)
-{
- NSVGparser* p;
- NSVGimage* ret = 0;
-
- p = nsvg__createParser();
- if (p == NULL) {
- return NULL;
- }
- p->dpi = dpi;
-
- nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
-
- // Scale to viewBox
- nsvg__scaleToViewbox(p, units);
-
- ret = p->image;
- p->image = NULL;
-
- nsvg__deleteParser(p);
-
- return ret;
-}
-
-NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
-{
- FILE* fp = NULL;
- size_t size;
- char* data = NULL;
- NSVGimage* image = NULL;
-
- fp = fopen(filename, "rb");
- if (!fp) goto error;
- fseek(fp, 0, SEEK_END);
- size = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- data = (char*)malloc(size+1);
- if (data == NULL) goto error;
- if (fread(data, 1, size, fp) != size) goto error;
- data[size] = '\0'; // Must be null terminated.
- fclose(fp);
- image = nsvgParse(data, units, dpi);
- free(data);
-
- return image;
-
-error:
- if (fp) fclose(fp);
- if (data) free(data);
- if (image) nsvgDelete(image);
- return NULL;
-}
-
-NSVGpath* nsvgDuplicatePath(NSVGpath* p)
-{
- NSVGpath* res = NULL;
-
- if (p == NULL)
- return NULL;
-
- res = (NSVGpath*)malloc(sizeof(NSVGpath));
- if (res == NULL) goto error;
- memset(res, 0, sizeof(NSVGpath));
-
- res->pts = (float*)malloc(p->npts*2*sizeof(float));
- if (res->pts == NULL) goto error;
- memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2);
- res->npts = p->npts;
-
- memcpy(res->bounds, p->bounds, sizeof(p->bounds));
-
- res->closed = p->closed;
-
- return res;
-
-error:
- if (res != NULL) {
- free(res->pts);
- free(res);
- }
- return NULL;
-}
-
-void nsvgDelete(NSVGimage* image)
-{
- NSVGshape *snext, *shape;
- if (image == NULL) return;
- shape = image->shapes;
- while (shape != NULL) {
- snext = shape->next;
- nsvg__deletePaths(shape->paths);
- nsvg__deletePaint(&shape->fill);
- nsvg__deletePaint(&shape->stroke);
- free(shape);
- shape = snext;
- }
- free(image);
-}
-
-#endif // NANOSVG_IMPLEMENTATION
-
-#endif // NANOSVG_H
diff --git a/src/external/nanosvgrast.h b/src/external/nanosvgrast.h
deleted file mode 100644
index 6e23acb7b..000000000
--- a/src/external/nanosvgrast.h
+++ /dev/null
@@ -1,1458 +0,0 @@
-/*
- * Copyright (c) 2013-14 Mikko Mononen memon@inside.org
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- *
- * The polygon rasterization is heavily based on stb_truetype rasterizer
- * by Sean Barrett - http://nothings.org/
- *
- */
-
-#ifndef NANOSVGRAST_H
-#define NANOSVGRAST_H
-
-#include "nanosvg.h"
-
-#ifndef NANOSVGRAST_CPLUSPLUS
-#ifdef __cplusplus
-extern "C" {
-#endif
-#endif
-
-typedef struct NSVGrasterizer NSVGrasterizer;
-
-/* Example Usage:
- // Load SVG
- NSVGimage* image;
- image = nsvgParseFromFile("test.svg", "px", 96);
-
- // Create rasterizer (can be used to render multiple images).
- struct NSVGrasterizer* rast = nsvgCreateRasterizer();
- // Allocate memory for image
- unsigned char* img = malloc(w*h*4);
- // Rasterize
- nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4);
-*/
-
-// Allocated rasterizer context.
-NSVGrasterizer* nsvgCreateRasterizer(void);
-
-// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha)
-// r - pointer to rasterizer context
-// image - pointer to image to rasterize
-// tx,ty - image offset (applied after scaling)
-// scale - image scale
-// dst - pointer to destination image data, 4 bytes per pixel (RGBA)
-// w - width of the image to render
-// h - height of the image to render
-// stride - number of bytes per scaleline in the destination buffer
-void nsvgRasterize(NSVGrasterizer* r,
- NSVGimage* image, float tx, float ty, float scale,
- unsigned char* dst, int w, int h, int stride);
-
-// Deletes rasterizer context.
-void nsvgDeleteRasterizer(NSVGrasterizer*);
-
-
-#ifndef NANOSVGRAST_CPLUSPLUS
-#ifdef __cplusplus
-}
-#endif
-#endif
-
-#ifdef NANOSVGRAST_IMPLEMENTATION
-
-#include
-#include
-#include
-
-#define NSVG__SUBSAMPLES 5
-#define NSVG__FIXSHIFT 10
-#define NSVG__FIX (1 << NSVG__FIXSHIFT)
-#define NSVG__FIXMASK (NSVG__FIX-1)
-#define NSVG__MEMPAGE_SIZE 1024
-
-typedef struct NSVGedge {
- float x0,y0, x1,y1;
- int dir;
- struct NSVGedge* next;
-} NSVGedge;
-
-typedef struct NSVGpoint {
- float x, y;
- float dx, dy;
- float len;
- float dmx, dmy;
- unsigned char flags;
-} NSVGpoint;
-
-typedef struct NSVGactiveEdge {
- int x,dx;
- float ey;
- int dir;
- struct NSVGactiveEdge *next;
-} NSVGactiveEdge;
-
-typedef struct NSVGmemPage {
- unsigned char mem[NSVG__MEMPAGE_SIZE];
- int size;
- struct NSVGmemPage* next;
-} NSVGmemPage;
-
-typedef struct NSVGcachedPaint {
- char type;
- char spread;
- float xform[6];
- unsigned int colors[256];
-} NSVGcachedPaint;
-
-struct NSVGrasterizer
-{
- float px, py;
-
- float tessTol;
- float distTol;
-
- NSVGedge* edges;
- int nedges;
- int cedges;
-
- NSVGpoint* points;
- int npoints;
- int cpoints;
-
- NSVGpoint* points2;
- int npoints2;
- int cpoints2;
-
- NSVGactiveEdge* freelist;
- NSVGmemPage* pages;
- NSVGmemPage* curpage;
-
- unsigned char* scanline;
- int cscanline;
-
- unsigned char* bitmap;
- int width, height, stride;
-};
-
-NSVGrasterizer* nsvgCreateRasterizer(void)
-{
- NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer));
- if (r == NULL) goto error;
- memset(r, 0, sizeof(NSVGrasterizer));
-
- r->tessTol = 0.25f;
- r->distTol = 0.01f;
-
- return r;
-
-error:
- nsvgDeleteRasterizer(r);
- return NULL;
-}
-
-void nsvgDeleteRasterizer(NSVGrasterizer* r)
-{
- NSVGmemPage* p;
-
- if (r == NULL) return;
-
- p = r->pages;
- while (p != NULL) {
- NSVGmemPage* next = p->next;
- free(p);
- p = next;
- }
-
- if (r->edges) free(r->edges);
- if (r->points) free(r->points);
- if (r->points2) free(r->points2);
- if (r->scanline) free(r->scanline);
-
- free(r);
-}
-
-static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur)
-{
- NSVGmemPage *newp;
-
- // If using existing chain, return the next page in chain
- if (cur != NULL && cur->next != NULL) {
- return cur->next;
- }
-
- // Alloc new page
- newp = (NSVGmemPage*)malloc(sizeof(NSVGmemPage));
- if (newp == NULL) return NULL;
- memset(newp, 0, sizeof(NSVGmemPage));
-
- // Add to linked list
- if (cur != NULL)
- cur->next = newp;
- else
- r->pages = newp;
-
- return newp;
-}
-
-static void nsvg__resetPool(NSVGrasterizer* r)
-{
- NSVGmemPage* p = r->pages;
- while (p != NULL) {
- p->size = 0;
- p = p->next;
- }
- r->curpage = r->pages;
-}
-
-static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size)
-{
- unsigned char* buf;
- if (size > NSVG__MEMPAGE_SIZE) return NULL;
- if (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) {
- r->curpage = nsvg__nextPage(r, r->curpage);
- }
- buf = &r->curpage->mem[r->curpage->size];
- r->curpage->size += size;
- return buf;
-}
-
-static int nsvg__ptEquals(float x1, float y1, float x2, float y2, float tol)
-{
- float dx = x2 - x1;
- float dy = y2 - y1;
- return dx*dx + dy*dy < tol*tol;
-}
-
-static void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags)
-{
- NSVGpoint* pt;
-
- if (r->npoints > 0) {
- pt = &r->points[r->npoints-1];
- if (nsvg__ptEquals(pt->x,pt->y, x,y, r->distTol)) {
- pt->flags = (unsigned char)(pt->flags | flags);
- return;
- }
- }
-
- if (r->npoints+1 > r->cpoints) {
- r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
- r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints);
- if (r->points == NULL) return;
- }
-
- pt = &r->points[r->npoints];
- pt->x = x;
- pt->y = y;
- pt->flags = (unsigned char)flags;
- r->npoints++;
-}
-
-static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt)
-{
- if (r->npoints+1 > r->cpoints) {
- r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
- r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints);
- if (r->points == NULL) return;
- }
- r->points[r->npoints] = pt;
- r->npoints++;
-}
-
-static void nsvg__duplicatePoints(NSVGrasterizer* r)
-{
- if (r->npoints > r->cpoints2) {
- r->cpoints2 = r->npoints;
- r->points2 = (NSVGpoint*)realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2);
- if (r->points2 == NULL) return;
- }
-
- memcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints);
- r->npoints2 = r->npoints;
-}
-
-static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1)
-{
- NSVGedge* e;
-
- // Skip horizontal edges
- if (y0 == y1)
- return;
-
- if (r->nedges+1 > r->cedges) {
- r->cedges = r->cedges > 0 ? r->cedges * 2 : 64;
- r->edges = (NSVGedge*)realloc(r->edges, sizeof(NSVGedge) * r->cedges);
- if (r->edges == NULL) return;
- }
-
- e = &r->edges[r->nedges];
- r->nedges++;
-
- if (y0 < y1) {
- e->x0 = x0;
- e->y0 = y0;
- e->x1 = x1;
- e->y1 = y1;
- e->dir = 1;
- } else {
- e->x0 = x1;
- e->y0 = y1;
- e->x1 = x0;
- e->y1 = y0;
- e->dir = -1;
- }
-}
-
-static float nsvg__normalize(float *x, float* y)
-{
- float d = sqrtf((*x)*(*x) + (*y)*(*y));
- if (d > 1e-6f) {
- float id = 1.0f / d;
- *x *= id;
- *y *= id;
- }
- return d;
-}
-
-static float nsvg__absf(float x) { return x < 0 ? -x : x; }
-
-static void nsvg__flattenCubicBez(NSVGrasterizer* r,
- float x1, float y1, float x2, float y2,
- float x3, float y3, float x4, float y4,
- int level, int type)
-{
- float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234;
- float dx,dy,d2,d3;
-
- if (level > 10) return;
-
- x12 = (x1+x2)*0.5f;
- y12 = (y1+y2)*0.5f;
- x23 = (x2+x3)*0.5f;
- y23 = (y2+y3)*0.5f;
- x34 = (x3+x4)*0.5f;
- y34 = (y3+y4)*0.5f;
- x123 = (x12+x23)*0.5f;
- y123 = (y12+y23)*0.5f;
-
- dx = x4 - x1;
- dy = y4 - y1;
- d2 = nsvg__absf(((x2 - x4) * dy - (y2 - y4) * dx));
- d3 = nsvg__absf(((x3 - x4) * dy - (y3 - y4) * dx));
-
- if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) {
- nsvg__addPathPoint(r, x4, y4, type);
- return;
- }
-
- x234 = (x23+x34)*0.5f;
- y234 = (y23+y34)*0.5f;
- x1234 = (x123+x234)*0.5f;
- y1234 = (y123+y234)*0.5f;
-
- nsvg__flattenCubicBez(r, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0);
- nsvg__flattenCubicBez(r, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type);
-}
-
-static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale)
-{
- int i, j;
- NSVGpath* path;
-
- for (path = shape->paths; path != NULL; path = path->next) {
- r->npoints = 0;
- // Flatten path
- nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0);
- for (i = 0; i < path->npts-1; i += 3) {
- float* p = &path->pts[i*2];
- nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, 0);
- }
- // Close path
- nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0);
- // Build edges
- for (i = 0, j = r->npoints-1; i < r->npoints; j = i++)
- nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y);
- }
-}
-
-enum NSVGpointFlags
-{
- NSVG_PT_CORNER = 0x01,
- NSVG_PT_BEVEL = 0x02,
- NSVG_PT_LEFT = 0x04
-};
-
-static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
-{
- float w = lineWidth * 0.5f;
- float dx = p1->x - p0->x;
- float dy = p1->y - p0->y;
- float len = nsvg__normalize(&dx, &dy);
- float px = p0->x + dx*len*0.5f, py = p0->y + dy*len*0.5f;
- float dlx = dy, dly = -dx;
- float lx = px - dlx*w, ly = py - dly*w;
- float rx = px + dlx*w, ry = py + dly*w;
- left->x = lx; left->y = ly;
- right->x = rx; right->y = ry;
-}
-
-static void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)
-{
- float w = lineWidth * 0.5f;
- float px = p->x, py = p->y;
- float dlx = dy, dly = -dx;
- float lx = px - dlx*w, ly = py - dly*w;
- float rx = px + dlx*w, ry = py + dly*w;
-
- nsvg__addEdge(r, lx, ly, rx, ry);
-
- if (connect) {
- nsvg__addEdge(r, left->x, left->y, lx, ly);
- nsvg__addEdge(r, rx, ry, right->x, right->y);
- }
- left->x = lx; left->y = ly;
- right->x = rx; right->y = ry;
-}
-
-static void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)
-{
- float w = lineWidth * 0.5f;
- float px = p->x - dx*w, py = p->y - dy*w;
- float dlx = dy, dly = -dx;
- float lx = px - dlx*w, ly = py - dly*w;
- float rx = px + dlx*w, ry = py + dly*w;
-
- nsvg__addEdge(r, lx, ly, rx, ry);
-
- if (connect) {
- nsvg__addEdge(r, left->x, left->y, lx, ly);
- nsvg__addEdge(r, rx, ry, right->x, right->y);
- }
- left->x = lx; left->y = ly;
- right->x = rx; right->y = ry;
-}
-
-#ifndef NSVG_PI
-#define NSVG_PI (3.14159265358979323846264338327f)
-#endif
-
-static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect)
-{
- int i;
- float w = lineWidth * 0.5f;
- float px = p->x, py = p->y;
- float dlx = dy, dly = -dx;
- float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0;
-
- for (i = 0; i < ncap; i++) {
- float a = (float)i/(float)(ncap-1)*NSVG_PI;
- float ax = cosf(a) * w, ay = sinf(a) * w;
- float x = px - dlx*ax - dx*ay;
- float y = py - dly*ax - dy*ay;
-
- if (i > 0)
- nsvg__addEdge(r, prevx, prevy, x, y);
-
- prevx = x;
- prevy = y;
-
- if (i == 0) {
- lx = x; ly = y;
- } else if (i == ncap-1) {
- rx = x; ry = y;
- }
- }
-
- if (connect) {
- nsvg__addEdge(r, left->x, left->y, lx, ly);
- nsvg__addEdge(r, rx, ry, right->x, right->y);
- }
-
- left->x = lx; left->y = ly;
- right->x = rx; right->y = ry;
-}
-
-static void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
-{
- float w = lineWidth * 0.5f;
- float dlx0 = p0->dy, dly0 = -p0->dx;
- float dlx1 = p1->dy, dly1 = -p1->dx;
- float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w);
- float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w);
- float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w);
- float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w);
-
- nsvg__addEdge(r, lx0, ly0, left->x, left->y);
- nsvg__addEdge(r, lx1, ly1, lx0, ly0);
-
- nsvg__addEdge(r, right->x, right->y, rx0, ry0);
- nsvg__addEdge(r, rx0, ry0, rx1, ry1);
-
- left->x = lx1; left->y = ly1;
- right->x = rx1; right->y = ry1;
-}
-
-static void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
-{
- float w = lineWidth * 0.5f;
- float dlx0 = p0->dy, dly0 = -p0->dx;
- float dlx1 = p1->dy, dly1 = -p1->dx;
- float lx0, rx0, lx1, rx1;
- float ly0, ry0, ly1, ry1;
-
- if (p1->flags & NSVG_PT_LEFT) {
- lx0 = lx1 = p1->x - p1->dmx * w;
- ly0 = ly1 = p1->y - p1->dmy * w;
- nsvg__addEdge(r, lx1, ly1, left->x, left->y);
-
- rx0 = p1->x + (dlx0 * w);
- ry0 = p1->y + (dly0 * w);
- rx1 = p1->x + (dlx1 * w);
- ry1 = p1->y + (dly1 * w);
- nsvg__addEdge(r, right->x, right->y, rx0, ry0);
- nsvg__addEdge(r, rx0, ry0, rx1, ry1);
- } else {
- lx0 = p1->x - (dlx0 * w);
- ly0 = p1->y - (dly0 * w);
- lx1 = p1->x - (dlx1 * w);
- ly1 = p1->y - (dly1 * w);
- nsvg__addEdge(r, lx0, ly0, left->x, left->y);
- nsvg__addEdge(r, lx1, ly1, lx0, ly0);
-
- rx0 = rx1 = p1->x + p1->dmx * w;
- ry0 = ry1 = p1->y + p1->dmy * w;
- nsvg__addEdge(r, right->x, right->y, rx1, ry1);
- }
-
- left->x = lx1; left->y = ly1;
- right->x = rx1; right->y = ry1;
-}
-
-static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap)
-{
- int i, n;
- float w = lineWidth * 0.5f;
- float dlx0 = p0->dy, dly0 = -p0->dx;
- float dlx1 = p1->dy, dly1 = -p1->dx;
- float a0 = atan2f(dly0, dlx0);
- float a1 = atan2f(dly1, dlx1);
- float da = a1 - a0;
- float lx, ly, rx, ry;
-
- if (da < NSVG_PI) da += NSVG_PI*2;
- if (da > NSVG_PI) da -= NSVG_PI*2;
-
- n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap);
- if (n < 2) n = 2;
- if (n > ncap) n = ncap;
-
- lx = left->x;
- ly = left->y;
- rx = right->x;
- ry = right->y;
-
- for (i = 0; i < n; i++) {
- float u = (float)i/(float)(n-1);
- float a = a0 + u*da;
- float ax = cosf(a) * w, ay = sinf(a) * w;
- float lx1 = p1->x - ax, ly1 = p1->y - ay;
- float rx1 = p1->x + ax, ry1 = p1->y + ay;
-
- nsvg__addEdge(r, lx1, ly1, lx, ly);
- nsvg__addEdge(r, rx, ry, rx1, ry1);
-
- lx = lx1; ly = ly1;
- rx = rx1; ry = ry1;
- }
-
- left->x = lx; left->y = ly;
- right->x = rx; right->y = ry;
-}
-
-static void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth)
-{
- float w = lineWidth * 0.5f;
- float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w);
- float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w);
-
- nsvg__addEdge(r, lx, ly, left->x, left->y);
- nsvg__addEdge(r, right->x, right->y, rx, ry);
-
- left->x = lx; left->y = ly;
- right->x = rx; right->y = ry;
-}
-
-static int nsvg__curveDivs(float r, float arc, float tol)
-{
- float da = acosf(r / (r + tol)) * 2.0f;
- int divs = (int)ceilf(arc / da);
- if (divs < 2) divs = 2;
- return divs;
-}
-
-static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth)
-{
- int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol); // Calculate divisions per half circle.
- NSVGpoint left = {0,0,0,0,0,0,0,0}, right = {0,0,0,0,0,0,0,0}, firstLeft = {0,0,0,0,0,0,0,0}, firstRight = {0,0,0,0,0,0,0,0};
- NSVGpoint* p0, *p1;
- int j, s, e;
-
- // Build stroke edges
- if (closed) {
- // Looping
- p0 = &points[npoints-1];
- p1 = &points[0];
- s = 0;
- e = npoints;
- } else {
- // Add cap
- p0 = &points[0];
- p1 = &points[1];
- s = 1;
- e = npoints-1;
- }
-
- if (closed) {
- nsvg__initClosed(&left, &right, p0, p1, lineWidth);
- firstLeft = left;
- firstRight = right;
- } else {
- // Add cap
- float dx = p1->x - p0->x;
- float dy = p1->y - p0->y;
- nsvg__normalize(&dx, &dy);
- if (lineCap == NSVG_CAP_BUTT)
- nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
- else if (lineCap == NSVG_CAP_SQUARE)
- nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
- else if (lineCap == NSVG_CAP_ROUND)
- nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0);
- }
-
- for (j = s; j < e; ++j) {
- if (p1->flags & NSVG_PT_CORNER) {
- if (lineJoin == NSVG_JOIN_ROUND)
- nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap);
- else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL))
- nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth);
- else
- nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth);
- } else {
- nsvg__straightJoin(r, &left, &right, p1, lineWidth);
- }
- p0 = p1++;
- }
-
- if (closed) {
- // Loop it
- nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y);
- nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y);
- } else {
- // Add cap
- float dx = p1->x - p0->x;
- float dy = p1->y - p0->y;
- nsvg__normalize(&dx, &dy);
- if (lineCap == NSVG_CAP_BUTT)
- nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
- else if (lineCap == NSVG_CAP_SQUARE)
- nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
- else if (lineCap == NSVG_CAP_ROUND)
- nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1);
- }
-}
-
-static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin)
-{
- int i, j;
- NSVGpoint* p0, *p1;
-
- p0 = &r->points[r->npoints-1];
- p1 = &r->points[0];
- for (i = 0; i < r->npoints; i++) {
- // Calculate segment direction and length
- p0->dx = p1->x - p0->x;
- p0->dy = p1->y - p0->y;
- p0->len = nsvg__normalize(&p0->dx, &p0->dy);
- // Advance
- p0 = p1++;
- }
-
- // calculate joins
- p0 = &r->points[r->npoints-1];
- p1 = &r->points[0];
- for (j = 0; j < r->npoints; j++) {
- float dlx0, dly0, dlx1, dly1, dmr2, cross;
- dlx0 = p0->dy;
- dly0 = -p0->dx;
- dlx1 = p1->dy;
- dly1 = -p1->dx;
- // Calculate extrusions
- p1->dmx = (dlx0 + dlx1) * 0.5f;
- p1->dmy = (dly0 + dly1) * 0.5f;
- dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy;
- if (dmr2 > 0.000001f) {
- float s2 = 1.0f / dmr2;
- if (s2 > 600.0f) {
- s2 = 600.0f;
- }
- p1->dmx *= s2;
- p1->dmy *= s2;
- }
-
- // Clear flags, but keep the corner.
- p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0;
-
- // Keep track of left turns.
- cross = p1->dx * p0->dy - p0->dx * p1->dy;
- if (cross > 0.0f)
- p1->flags |= NSVG_PT_LEFT;
-
- // Check to see if the corner needs to be beveled.
- if (p1->flags & NSVG_PT_CORNER) {
- if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) {
- p1->flags |= NSVG_PT_BEVEL;
- }
- }
-
- p0 = p1++;
- }
-}
-
-static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float scale)
-{
- int i, j, closed;
- NSVGpath* path;
- NSVGpoint* p0, *p1;
- float miterLimit = shape->miterLimit;
- int lineJoin = shape->strokeLineJoin;
- int lineCap = shape->strokeLineCap;
- float lineWidth = shape->strokeWidth * scale;
-
- for (path = shape->paths; path != NULL; path = path->next) {
- // Flatten path
- r->npoints = 0;
- nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, NSVG_PT_CORNER);
- for (i = 0; i < path->npts-1; i += 3) {
- float* p = &path->pts[i*2];
- nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, NSVG_PT_CORNER);
- }
- if (r->npoints < 2)
- continue;
-
- closed = path->closed;
-
- // If the first and last points are the same, remove the last, mark as closed path.
- p0 = &r->points[r->npoints-1];
- p1 = &r->points[0];
- if (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) {
- r->npoints--;
- p0 = &r->points[r->npoints-1];
- closed = 1;
- }
-
- if (shape->strokeDashCount > 0) {
- int idash = 0, dashState = 1;
- float totalDist = 0, dashLen, allDashLen, dashOffset;
- NSVGpoint cur;
-
- if (closed)
- nsvg__appendPathPoint(r, r->points[0]);
-
- // Duplicate points -> points2.
- nsvg__duplicatePoints(r);
-
- r->npoints = 0;
- cur = r->points2[0];
- nsvg__appendPathPoint(r, cur);
-
- // Figure out dash offset.
- allDashLen = 0;
- for (j = 0; j < shape->strokeDashCount; j++)
- allDashLen += shape->strokeDashArray[j];
- if (shape->strokeDashCount & 1)
- allDashLen *= 2.0f;
- // Find location inside pattern
- dashOffset = fmodf(shape->strokeDashOffset, allDashLen);
- if (dashOffset < 0.0f)
- dashOffset += allDashLen;
-
- while (dashOffset > shape->strokeDashArray[idash]) {
- dashOffset -= shape->strokeDashArray[idash];
- idash = (idash + 1) % shape->strokeDashCount;
- }
- dashLen = (shape->strokeDashArray[idash] - dashOffset) * scale;
-
- for (j = 1; j < r->npoints2; ) {
- float dx = r->points2[j].x - cur.x;
- float dy = r->points2[j].y - cur.y;
- float dist = sqrtf(dx*dx + dy*dy);
-
- if ((totalDist + dist) > dashLen) {
- // Calculate intermediate point
- float d = (dashLen - totalDist) / dist;
- float x = cur.x + dx * d;
- float y = cur.y + dy * d;
- nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER);
-
- // Stroke
- if (r->npoints > 1 && dashState) {
- nsvg__prepareStroke(r, miterLimit, lineJoin);
- nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
- }
- // Advance dash pattern
- dashState = !dashState;
- idash = (idash+1) % shape->strokeDashCount;
- dashLen = shape->strokeDashArray[idash] * scale;
- // Restart
- cur.x = x;
- cur.y = y;
- cur.flags = NSVG_PT_CORNER;
- totalDist = 0.0f;
- r->npoints = 0;
- nsvg__appendPathPoint(r, cur);
- } else {
- totalDist += dist;
- cur = r->points2[j];
- nsvg__appendPathPoint(r, cur);
- j++;
- }
- }
- // Stroke any leftover path
- if (r->npoints > 1 && dashState)
- nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
- } else {
- nsvg__prepareStroke(r, miterLimit, lineJoin);
- nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth);
- }
- }
-}
-
-static int nsvg__cmpEdge(const void *p, const void *q)
-{
- const NSVGedge* a = (const NSVGedge*)p;
- const NSVGedge* b = (const NSVGedge*)q;
-
- if (a->y0 < b->y0) return -1;
- if (a->y0 > b->y0) return 1;
- return 0;
-}
-
-
-static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint)
-{
- NSVGactiveEdge* z;
-
- if (r->freelist != NULL) {
- // Restore from freelist.
- z = r->freelist;
- r->freelist = z->next;
- } else {
- // Alloc new edge.
- z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge));
- if (z == NULL) return NULL;
- }
-
- float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
-// STBTT_assert(e->y0 <= start_point);
- // round dx down to avoid going too far
- if (dxdy < 0)
- z->dx = (int)(-floorf(NSVG__FIX * -dxdy));
- else
- z->dx = (int)floorf(NSVG__FIX * dxdy);
- z->x = (int)floorf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));
-// z->x -= off_x * FIX;
- z->ey = e->y1;
- z->next = 0;
- z->dir = e->dir;
-
- return z;
-}
-
-static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z)
-{
- z->next = r->freelist;
- r->freelist = z;
-}
-
-static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax)
-{
- int i = x0 >> NSVG__FIXSHIFT;
- int j = x1 >> NSVG__FIXSHIFT;
- if (i < *xmin) *xmin = i;
- if (j > *xmax) *xmax = j;
- if (i < len && j >= 0) {
- if (i == j) {
- // x0,x1 are the same pixel, so compute combined coverage
- scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT));
- } else {
- if (i >= 0) // add antialiasing for x0
- scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT));
- else
- i = -1; // clip
-
- if (j < len) // add antialiasing for x1
- scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT));
- else
- j = len; // clip
-
- for (++i; i < j; ++i) // fill pixels between x0 and x1
- scanline[i] = (unsigned char)(scanline[i] + maxWeight);
- }
- }
-}
-
-// note: this routine clips fills that extend off the edges... ideally this
-// wouldn't happen, but it could happen if the truetype glyph bounding boxes
-// are wrong, or if the user supplies a too-small bitmap
-static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule)
-{
- // non-zero winding fill
- int x0 = 0, w = 0;
-
- if (fillRule == NSVG_FILLRULE_NONZERO) {
- // Non-zero
- while (e != NULL) {
- if (w == 0) {
- // if we're currently at zero, we need to record the edge start point
- x0 = e->x; w += e->dir;
- } else {
- int x1 = e->x; w += e->dir;
- // if we went to zero, we need to draw
- if (w == 0)
- nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
- }
- e = e->next;
- }
- } else if (fillRule == NSVG_FILLRULE_EVENODD) {
- // Even-odd
- while (e != NULL) {
- if (w == 0) {
- // if we're currently at zero, we need to record the edge start point
- x0 = e->x; w = 1;
- } else {
- int x1 = e->x; w = 0;
- nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
- }
- e = e->next;
- }
- }
-}
-
-static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); }
-
-static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
-{
- return ((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24);
-}
-
-static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u)
-{
- int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
- int r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8;
- int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8;
- int b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8;
- int a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8;
- return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
-}
-
-static unsigned int nsvg__applyOpacity(unsigned int c, float u)
-{
- int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
- int r = (c) & 0xff;
- int g = (c>>8) & 0xff;
- int b = (c>>16) & 0xff;
- int a = (((c>>24) & 0xff)*iu) >> 8;
- return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
-}
-
-static inline int nsvg__div255(int x)
-{
- return ((x+1) * 257) >> 16;
-}
-
-static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y,
- float tx, float ty, float scale, NSVGcachedPaint* cache)
-{
-
- if (cache->type == NSVG_PAINT_COLOR) {
- int i, cr, cg, cb, ca;
- cr = cache->colors[0] & 0xff;
- cg = (cache->colors[0] >> 8) & 0xff;
- cb = (cache->colors[0] >> 16) & 0xff;
- ca = (cache->colors[0] >> 24) & 0xff;
-
- for (i = 0; i < count; i++) {
- int r,g,b;
- int a = nsvg__div255((int)cover[0] * ca);
- int ia = 255 - a;
- // Premultiply
- r = nsvg__div255(cr * a);
- g = nsvg__div255(cg * a);
- b = nsvg__div255(cb * a);
-
- // Blend over
- r += nsvg__div255(ia * (int)dst[0]);
- g += nsvg__div255(ia * (int)dst[1]);
- b += nsvg__div255(ia * (int)dst[2]);
- a += nsvg__div255(ia * (int)dst[3]);
-
- dst[0] = (unsigned char)r;
- dst[1] = (unsigned char)g;
- dst[2] = (unsigned char)b;
- dst[3] = (unsigned char)a;
-
- cover++;
- dst += 4;
- }
- } else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) {
- // TODO: spread modes.
- // TODO: plenty of opportunities to optimize.
- float fx, fy, dx, gy;
- float* t = cache->xform;
- int i, cr, cg, cb, ca;
- unsigned int c;
-
- fx = ((float)x - tx) / scale;
- fy = ((float)y - ty) / scale;
- dx = 1.0f / scale;
-
- for (i = 0; i < count; i++) {
- int r,g,b,a,ia;
- gy = fx*t[1] + fy*t[3] + t[5];
- c = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)];
- cr = (c) & 0xff;
- cg = (c >> 8) & 0xff;
- cb = (c >> 16) & 0xff;
- ca = (c >> 24) & 0xff;
-
- a = nsvg__div255((int)cover[0] * ca);
- ia = 255 - a;
-
- // Premultiply
- r = nsvg__div255(cr * a);
- g = nsvg__div255(cg * a);
- b = nsvg__div255(cb * a);
-
- // Blend over
- r += nsvg__div255(ia * (int)dst[0]);
- g += nsvg__div255(ia * (int)dst[1]);
- b += nsvg__div255(ia * (int)dst[2]);
- a += nsvg__div255(ia * (int)dst[3]);
-
- dst[0] = (unsigned char)r;
- dst[1] = (unsigned char)g;
- dst[2] = (unsigned char)b;
- dst[3] = (unsigned char)a;
-
- cover++;
- dst += 4;
- fx += dx;
- }
- } else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) {
- // TODO: spread modes.
- // TODO: plenty of opportunities to optimize.
- // TODO: focus (fx,fy)
- float fx, fy, dx, gx, gy, gd;
- float* t = cache->xform;
- int i, cr, cg, cb, ca;
- unsigned int c;
-
- fx = ((float)x - tx) / scale;
- fy = ((float)y - ty) / scale;
- dx = 1.0f / scale;
-
- for (i = 0; i < count; i++) {
- int r,g,b,a,ia;
- gx = fx*t[0] + fy*t[2] + t[4];
- gy = fx*t[1] + fy*t[3] + t[5];
- gd = sqrtf(gx*gx + gy*gy);
- c = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)];
- cr = (c) & 0xff;
- cg = (c >> 8) & 0xff;
- cb = (c >> 16) & 0xff;
- ca = (c >> 24) & 0xff;
-
- a = nsvg__div255((int)cover[0] * ca);
- ia = 255 - a;
-
- // Premultiply
- r = nsvg__div255(cr * a);
- g = nsvg__div255(cg * a);
- b = nsvg__div255(cb * a);
-
- // Blend over
- r += nsvg__div255(ia * (int)dst[0]);
- g += nsvg__div255(ia * (int)dst[1]);
- b += nsvg__div255(ia * (int)dst[2]);
- a += nsvg__div255(ia * (int)dst[3]);
-
- dst[0] = (unsigned char)r;
- dst[1] = (unsigned char)g;
- dst[2] = (unsigned char)b;
- dst[3] = (unsigned char)a;
-
- cover++;
- dst += 4;
- fx += dx;
- }
- }
-}
-
-static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, float scale, NSVGcachedPaint* cache, char fillRule)
-{
- NSVGactiveEdge *active = NULL;
- int y, s;
- int e = 0;
- int maxWeight = (255 / NSVG__SUBSAMPLES); // weight per vertical scanline
- int xmin, xmax;
-
- for (y = 0; y < r->height; y++) {
- memset(r->scanline, 0, r->width);
- xmin = r->width;
- xmax = 0;
- for (s = 0; s < NSVG__SUBSAMPLES; ++s) {
- // find center of pixel for this scanline
- float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f;
- NSVGactiveEdge **step = &active;
-
- // update all active edges;
- // remove all active edges that terminate before the center of this scanline
- while (*step) {
- NSVGactiveEdge *z = *step;
- if (z->ey <= scany) {
- *step = z->next; // delete from list
-// NSVG__assert(z->valid);
- nsvg__freeActive(r, z);
- } else {
- z->x += z->dx; // advance to position for current scanline
- step = &((*step)->next); // advance through list
- }
- }
-
- // resort the list if needed
- for (;;) {
- int changed = 0;
- step = &active;
- while (*step && (*step)->next) {
- if ((*step)->x > (*step)->next->x) {
- NSVGactiveEdge* t = *step;
- NSVGactiveEdge* q = t->next;
- t->next = q->next;
- q->next = t;
- *step = q;
- changed = 1;
- }
- step = &(*step)->next;
- }
- if (!changed) break;
- }
-
- // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
- while (e < r->nedges && r->edges[e].y0 <= scany) {
- if (r->edges[e].y1 > scany) {
- NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany);
- if (z == NULL) break;
- // find insertion point
- if (active == NULL) {
- active = z;
- } else if (z->x < active->x) {
- // insert at front
- z->next = active;
- active = z;
- } else {
- // find thing to insert AFTER
- NSVGactiveEdge* p = active;
- while (p->next && p->next->x < z->x)
- p = p->next;
- // at this point, p->next->x is NOT < z->x
- z->next = p->next;
- p->next = z;
- }
- }
- e++;
- }
-
- // now process all active edges in non-zero fashion
- if (active != NULL)
- nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule);
- }
- // Blit
- if (xmin < 0) xmin = 0;
- if (xmax > r->width-1) xmax = r->width-1;
- if (xmin <= xmax) {
- nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scale, cache);
- }
- }
-
-}
-
-static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride)
-{
- int x,y;
-
- // Unpremultiply
- for (y = 0; y < h; y++) {
- unsigned char *row = &image[y*stride];
- for (x = 0; x < w; x++) {
- int r = row[0], g = row[1], b = row[2], a = row[3];
- if (a != 0) {
- row[0] = (unsigned char)(r*255/a);
- row[1] = (unsigned char)(g*255/a);
- row[2] = (unsigned char)(b*255/a);
- }
- row += 4;
- }
- }
-
- // Defringe
- for (y = 0; y < h; y++) {
- unsigned char *row = &image[y*stride];
- for (x = 0; x < w; x++) {
- int r = 0, g = 0, b = 0, a = row[3], n = 0;
- if (a == 0) {
- if (x-1 > 0 && row[-1] != 0) {
- r += row[-4];
- g += row[-3];
- b += row[-2];
- n++;
- }
- if (x+1 < w && row[7] != 0) {
- r += row[4];
- g += row[5];
- b += row[6];
- n++;
- }
- if (y-1 > 0 && row[-stride+3] != 0) {
- r += row[-stride];
- g += row[-stride+1];
- b += row[-stride+2];
- n++;
- }
- if (y+1 < h && row[stride+3] != 0) {
- r += row[stride];
- g += row[stride+1];
- b += row[stride+2];
- n++;
- }
- if (n > 0) {
- row[0] = (unsigned char)(r/n);
- row[1] = (unsigned char)(g/n);
- row[2] = (unsigned char)(b/n);
- }
- }
- row += 4;
- }
- }
-}
-
-
-static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity)
-{
- int i, j;
- NSVGgradient* grad;
-
- cache->type = paint->type;
-
- if (paint->type == NSVG_PAINT_COLOR) {
- cache->colors[0] = nsvg__applyOpacity(paint->color, opacity);
- return;
- }
-
- grad = paint->gradient;
-
- cache->spread = grad->spread;
- memcpy(cache->xform, grad->xform, sizeof(float)*6);
-
- if (grad->nstops == 0) {
- for (i = 0; i < 256; i++)
- cache->colors[i] = 0;
- } if (grad->nstops == 1) {
- for (i = 0; i < 256; i++)
- cache->colors[i] = nsvg__applyOpacity(grad->stops[i].color, opacity);
- } else {
- unsigned int ca, cb = 0;
- float ua, ub, du, u;
- int ia, ib, count;
-
- ca = nsvg__applyOpacity(grad->stops[0].color, opacity);
- ua = nsvg__clampf(grad->stops[0].offset, 0, 1);
- ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1);
- ia = (int)(ua * 255.0f);
- ib = (int)(ub * 255.0f);
- for (i = 0; i < ia; i++) {
- cache->colors[i] = ca;
- }
-
- for (i = 0; i < grad->nstops-1; i++) {
- ca = nsvg__applyOpacity(grad->stops[i].color, opacity);
- cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity);
- ua = nsvg__clampf(grad->stops[i].offset, 0, 1);
- ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1);
- ia = (int)(ua * 255.0f);
- ib = (int)(ub * 255.0f);
- count = ib - ia;
- if (count <= 0) continue;
- u = 0;
- du = 1.0f / (float)count;
- for (j = 0; j < count; j++) {
- cache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u);
- u += du;
- }
- }
-
- for (i = ib; i < 256; i++)
- cache->colors[i] = cb;
- }
-
-}
-
-/*
-static void dumpEdges(NSVGrasterizer* r, const char* name)
-{
- float xmin = 0, xmax = 0, ymin = 0, ymax = 0;
- NSVGedge *e = NULL;
- int i;
- if (r->nedges == 0) return;
- FILE* fp = fopen(name, "w");
- if (fp == NULL) return;
-
- xmin = xmax = r->edges[0].x0;
- ymin = ymax = r->edges[0].y0;
- for (i = 0; i < r->nedges; i++) {
- e = &r->edges[i];
- xmin = nsvg__minf(xmin, e->x0);
- xmin = nsvg__minf(xmin, e->x1);
- xmax = nsvg__maxf(xmax, e->x0);
- xmax = nsvg__maxf(xmax, e->x1);
- ymin = nsvg__minf(ymin, e->y0);
- ymin = nsvg__minf(ymin, e->y1);
- ymax = nsvg__maxf(ymax, e->y0);
- ymax = nsvg__maxf(ymax, e->y1);
- }
-
- fprintf(fp, "");
- fclose(fp);
-}
-*/
-
-void nsvgRasterize(NSVGrasterizer* r,
- NSVGimage* image, float tx, float ty, float scale,
- unsigned char* dst, int w, int h, int stride)
-{
- NSVGshape *shape = NULL;
- NSVGedge *e = NULL;
- NSVGcachedPaint cache;
- int i;
-
- r->bitmap = dst;
- r->width = w;
- r->height = h;
- r->stride = stride;
-
- if (w > r->cscanline) {
- r->cscanline = w;
- r->scanline = (unsigned char*)realloc(r->scanline, w);
- if (r->scanline == NULL) return;
- }
-
- for (i = 0; i < h; i++)
- memset(&dst[i*stride], 0, w*4);
-
- for (shape = image->shapes; shape != NULL; shape = shape->next) {
- if (!(shape->flags & NSVG_FLAGS_VISIBLE))
- continue;
-
- if (shape->fill.type != NSVG_PAINT_NONE) {
- nsvg__resetPool(r);
- r->freelist = NULL;
- r->nedges = 0;
-
- nsvg__flattenShape(r, shape, scale);
-
- // Scale and translate edges
- for (i = 0; i < r->nedges; i++) {
- e = &r->edges[i];
- e->x0 = tx + e->x0;
- e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
- e->x1 = tx + e->x1;
- e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
- }
-
- // Rasterize edges
- if (r->nedges != 0)
- qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
-
- // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
- nsvg__initPaint(&cache, &shape->fill, shape->opacity);
-
- nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, shape->fillRule);
- }
- if (shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) {
- nsvg__resetPool(r);
- r->freelist = NULL;
- r->nedges = 0;
-
- nsvg__flattenShapeStroke(r, shape, scale);
-
-// dumpEdges(r, "edge.svg");
-
- // Scale and translate edges
- for (i = 0; i < r->nedges; i++) {
- e = &r->edges[i];
- e->x0 = tx + e->x0;
- e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
- e->x1 = tx + e->x1;
- e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
- }
-
- // Rasterize edges
- if (r->nedges != 0)
- qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
-
- // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
- nsvg__initPaint(&cache, &shape->stroke, shape->opacity);
-
- nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, NSVG_FILLRULE_NONZERO);
- }
- }
-
- nsvg__unpremultiplyAlpha(dst, w, h, stride);
-
- r->bitmap = NULL;
- r->width = 0;
- r->height = 0;
- r->stride = 0;
-}
-
-#endif // NANOSVGRAST_IMPLEMENTATION
-
-#endif // NANOSVGRAST_H
diff --git a/src/external/rl_gputex.h b/src/external/rl_gputex.h
index 6b26d1c8d..4043a9239 100644
--- a/src/external/rl_gputex.h
+++ b/src/external/rl_gputex.h
@@ -185,6 +185,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
if (header->ddspf.flags == 0x40) // No alpha channel
{
int data_size = image_pixel_size*sizeof(unsigned short);
+ if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
@@ -196,6 +197,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
if (header->ddspf.a_bit_mask == 0x8000) // 1bit alpha
{
int data_size = image_pixel_size*sizeof(unsigned short);
+ if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
@@ -215,6 +217,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
else if (header->ddspf.a_bit_mask == 0xf000) // 4bit alpha
{
int data_size = image_pixel_size*sizeof(unsigned short);
+ if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
@@ -236,6 +239,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
else if ((header->ddspf.flags == 0x40) && (header->ddspf.rgb_bit_count == 24)) // DDS_RGB, no compressed
{
int data_size = image_pixel_size*3*sizeof(unsigned char);
+ if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
@@ -245,6 +249,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
else if ((header->ddspf.flags == 0x41) && (header->ddspf.rgb_bit_count == 32)) // DDS_RGBA, no compressed
{
int data_size = image_pixel_size*4*sizeof(unsigned char);
+ if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
@@ -265,9 +270,11 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
}
else if (((header->ddspf.flags == 0x04) || (header->ddspf.flags == 0x05)) && (header->ddspf.fourcc > 0)) // Compressed
{
- // NOTE: This forces only 1 mipmap to be loaded which is not really correct but it works
- int data_size = (header->pitch_or_linear_size < file_size - 0x80) ? header->pitch_or_linear_size : file_size - 0x80;
- *mips = 1;
+ int data_size = 0;
+
+ // Calculate data size, including all mipmaps
+ if (header->mipmap_count > 1) data_size = header->pitch_or_linear_size + header->pitch_or_linear_size / 3;
+ else data_size = header->pitch_or_linear_size;
image_data = RL_MALLOC(data_size*sizeof(unsigned char));
diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c
index 6318931cc..88438c9b0 100644
--- a/src/platforms/rcore_android.c
+++ b/src/platforms/rcore_android.c
@@ -704,7 +704,6 @@ void PollInputEvents(void)
}
}
-
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c
index f7b94178c..0bc52ac9e 100644
--- a/src/platforms/rcore_desktop_glfw.c
+++ b/src/platforms/rcore_desktop_glfw.c
@@ -149,7 +149,7 @@ void ToggleFullscreen(void)
{
// Store previous window position (in case we exit fullscreen)
CORE.Window.previousPosition = CORE.Window.position;
-
+
int monitorCount = 0;
int monitorIndex = GetCurrentMonitor();
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
@@ -1234,7 +1234,6 @@ void PollInputEvents(void)
glfwSetWindowShouldClose(platform.handle, GLFW_FALSE);
}
-
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
@@ -1290,7 +1289,7 @@ int InitPlatform(void)
// Disable GlFW auto iconify behaviour
// Auto Iconify automatically minimizes (iconifies) the window if the window loses focus
// additionally auto iconify restores the hardware resolution of the monitor if the window that loses focus is a fullscreen window
- glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
+ glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
// Check window creation flags
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true;
@@ -1580,7 +1579,7 @@ int InitPlatform(void)
int monitorWidth = 0;
int monitorHeight = 0;
glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);
-
+
// Here CORE.Window.render.width/height should be used instead of CORE.Window.screen.width/height to center the window correctly when the high dpi flag is enabled.
int posX = monitorX + (monitorWidth - (int)CORE.Window.render.width)/2;
int posY = monitorY + (monitorHeight - (int)CORE.Window.render.height)/2;
diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c
index 76f4cdd0a..75df48237 100644
--- a/src/platforms/rcore_desktop_rgfw.c
+++ b/src/platforms/rcore_desktop_rgfw.c
@@ -69,7 +69,6 @@ void CloseWindow(void);
#define CloseWindow CloseWindow_win32
#define ShowCursor __imp_ShowCursor
#define _APISETSTRING_
- __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
#endif
#if defined(__APPLE__)
@@ -870,9 +869,8 @@ void PollInputEvents(void)
//-----------------------------------------------------------------------------
CORE.Window.resizedLastFrame = false;
-
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
- #define RGFW_HOLD_MOUSE (1L<<2)
+ #define RGFW_HOLD_MOUSE (1L<<2)
if (platform.window->_winArgs & RGFW_HOLD_MOUSE)
{
CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f };
@@ -883,10 +881,8 @@ void PollInputEvents(void)
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
-
- while (RGFW_window_checkEvent(platform.window))
+ while (RGFW_window_checkEvent(platform.window))
{
-
if ((platform.window->event.type >= RGFW_jsButtonPressed) && (platform.window->event.type <= RGFW_jsAxisMove))
{
if (!CORE.Input.Gamepad.ready[platform.window->event.joystick])
@@ -1196,7 +1192,6 @@ void PollInputEvents(void)
//-----------------------------------------------------------------------------
}
-
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
@@ -1253,7 +1248,6 @@ int InitPlatform(void)
*/
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
-
if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1);
RGFW_window_makeCurrent(platform.window);
diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c
index 90372c2f6..b4ceb78eb 100644
--- a/src/platforms/rcore_desktop_sdl.c
+++ b/src/platforms/rcore_desktop_sdl.c
@@ -1609,7 +1609,6 @@ int InitPlatform(void)
//----------------------------------------------------------------------------
// Define base path for storage
CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory();
- CHDIR(CORE.Storage.basePath);
//----------------------------------------------------------------------------
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully");
diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c
index ee2875838..e77457b1b 100644
--- a/src/platforms/rcore_drm.c
+++ b/src/platforms/rcore_drm.c
@@ -1480,7 +1480,6 @@ static void ConfigureEvdevDevice(char *device)
TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
}
-
if (TEST_BIT(evBits, EV_KEY))
{
// The first 32 keys as defined in input-event-codes.h are pretty much
diff --git a/src/platforms/rcore_template.c b/src/platforms/rcore_template.c
index 938f4ed7d..6bc3432eb 100644
--- a/src/platforms/rcore_template.c
+++ b/src/platforms/rcore_template.c
@@ -430,7 +430,6 @@ void PollInputEvents(void)
// TODO: Poll input events for current platform
}
-
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c
index ff7a92dbc..36af66a47 100644
--- a/src/platforms/rcore_web.c
+++ b/src/platforms/rcore_web.c
@@ -74,6 +74,8 @@
typedef struct {
GLFWwindow *handle; // GLFW window handle (graphic device)
bool ourFullscreen; // Internal var to filter our handling of fullscreen vs the user handling of fullscreen
+ int unmaximizedWidth; // Internal var to store the unmaximized window (canvas) width
+ int unmaximizedHeight; // Internal var to store the unmaximized window (canvas) height
} PlatformData;
//----------------------------------------------------------------------------------
@@ -317,7 +319,18 @@ void ToggleBorderlessWindowed(void)
// Set window state: maximized, if resizable
void MaximizeWindow(void)
{
- TRACELOG(LOG_WARNING, "MaximizeWindow() not available on target platform");
+ if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE && !(CORE.Window.flags & FLAG_WINDOW_MAXIMIZED))
+ {
+ platform.unmaximizedWidth = CORE.Window.screen.width;
+ platform.unmaximizedHeight = CORE.Window.screen.height;
+
+ const int tabWidth = EM_ASM_INT( { return window.innerWidth; }, 0);
+ const int tabHeight = EM_ASM_INT( { return window.innerHeight; }, 0);
+
+ if (tabWidth && tabHeight) glfwSetWindowSize(platform.handle, tabWidth, tabHeight);
+
+ CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
+ }
}
// Set window state: minimized
@@ -329,7 +342,12 @@ void MinimizeWindow(void)
// Set window state: not minimized/maximized
void RestoreWindow(void)
{
- TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
+ if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE && (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED))
+ {
+ if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight);
+
+ CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
+ }
}
// Set window configuration state using flags
@@ -398,9 +416,20 @@ void SetWindowState(unsigned int flags)
}
// State change: FLAG_WINDOW_MAXIMIZED
- if ((flags & FLAG_WINDOW_MAXIMIZED) > 0)
+ if (((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) != (flags & FLAG_WINDOW_MAXIMIZED)) && ((flags & FLAG_WINDOW_MAXIMIZED) > 0))
{
- TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_MAXIMIZED) not available on target platform");
+ if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
+ {
+ platform.unmaximizedWidth = CORE.Window.screen.width;
+ platform.unmaximizedHeight = CORE.Window.screen.height;
+
+ const int tabWidth = EM_ASM_INT( { return window.innerWidth; }, 0);
+ const int tabHeight = EM_ASM_INT( { return window.innerHeight; }, 0);
+
+ if (tabWidth && tabHeight) glfwSetWindowSize(platform.handle, tabWidth, tabHeight);
+
+ CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
+ }
}
// State change: FLAG_WINDOW_UNFOCUSED
@@ -516,9 +545,14 @@ void ClearWindowState(unsigned int flags)
}
// State change: FLAG_WINDOW_MAXIMIZED
- if ((flags & FLAG_WINDOW_MAXIMIZED) > 0)
+ if (((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) && ((flags & FLAG_WINDOW_MAXIMIZED) > 0))
{
- TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_MAXIMIZED) not available on target platform");
+ if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
+ {
+ if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight);
+
+ CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
+ }
}
// State change: FLAG_WINDOW_UNDECORATED
@@ -639,7 +673,9 @@ void SetWindowSize(int width, int height)
// Set window opacity, value opacity is between 0.0 and 1.0
void SetWindowOpacity(float opacity)
{
- TRACELOG(LOG_WARNING, "SetWindowOpacity() not available on target platform");
+ if (opacity >= 1.0f) opacity = 1.0f;
+ else if (opacity <= 0.0f) opacity = 0.0f;
+ EM_ASM({ document.getElementById('canvas').style.opacity = $0; }, opacity);
}
// Set window focused
@@ -935,7 +971,6 @@ void PollInputEvents(void)
// so, if mouse is not moved it returns a (0, 0) position... this behaviour should be reviewed!
//for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };
-
// Gamepad support using emscripten API
// NOTE: GLFW3 joystick functionality not available in web
diff --git a/src/raudio.c b/src/raudio.c
index 79d53b565..15859a661 100644
--- a/src/raudio.c
+++ b/src/raudio.c
@@ -892,8 +892,8 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
return wave;
}
-// Checks if wave data is ready
-bool IsWaveReady(Wave wave)
+// Checks if wave data is valid (data loaded and parameters)
+bool IsWaveValid(Wave wave)
{
bool result = false;
@@ -993,8 +993,8 @@ Sound LoadSoundAlias(Sound source)
}
-// Checks if a sound is ready
-bool IsSoundReady(Sound sound)
+// Checks if a sound is valid (data loaded and buffers initialized)
+bool IsSoundValid(Sound sound)
{
bool result = false;
@@ -1726,8 +1726,8 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
return music;
}
-// Checks if a music stream is ready
-bool IsMusicReady(Music music)
+// Checks if a music stream is valid (context and buffers initialized)
+bool IsMusicValid(Music music)
{
return ((music.ctxData != NULL) && // Validate context loaded
(music.frameCount > 0) && // Validate audio frame count
@@ -2119,8 +2119,8 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
return stream;
}
-// Checks if an audio stream is ready
-bool IsAudioStreamReady(AudioStream stream)
+// Checks if an audio stream is valid (buffers initialized)
+bool IsAudioStreamValid(AudioStream stream)
{
return ((stream.buffer != NULL) && // Validate stream buffer
(stream.sampleRate > 0) && // Validate sample rate is supported
diff --git a/src/raylib.h b/src/raylib.h
index 08121c50c..25ee6943f 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -1044,7 +1044,7 @@ RLAPI void UnloadVrStereoConfig(VrStereoConfig config); // Unload VR s
// NOTE: Shader functionality is not available on OpenGL 1.1
RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
-RLAPI bool IsShaderReady(Shader shader); // Check if a shader is ready
+RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU)
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location
RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value
@@ -1144,6 +1144,10 @@ RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
+RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code
+RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes)
+RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes)
+
// Automation events functionality
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
@@ -1211,7 +1215,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
RLAPI int GetGestureDetected(void); // Get latest detected gesture
-RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
+RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
@@ -1312,13 +1316,12 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);
// NOTE: These functions do not require GPU access
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
-RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot)
-RLAPI bool IsImageReady(Image image); // Check if an image is ready
+RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
@@ -1404,9 +1407,9 @@ RLAPI Texture2D LoadTexture(const char *fileName);
RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data
RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported
RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer)
-RLAPI bool IsTextureReady(Texture2D texture); // Check if a texture is ready
+RLAPI bool IsTextureValid(Texture2D texture); // Check if a texture is valid (loaded in GPU)
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
-RLAPI bool IsRenderTextureReady(RenderTexture2D target); // Check if a render texture is ready
+RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU)
RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM)
RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data
RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data
@@ -1453,7 +1456,7 @@ RLAPI Font LoadFont(const char *fileName);
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
-RLAPI bool IsFontReady(Font font); // Check if a font is ready
+RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
@@ -1543,7 +1546,7 @@ RLAPI void DrawGrid(int slices, float spacing);
// Model management functions
RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials)
RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material)
-RLAPI bool IsModelReady(Model model); // Check if a model is ready
+RLAPI bool IsModelValid(Model model); // Check if a model is valid (loaded in GPU, VAO/VBOs)
RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM)
RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes)
@@ -1586,7 +1589,7 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize);
// Material loading/unloading functions
RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file
RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
-RLAPI bool IsMaterialReady(Material material); // Check if a material is ready
+RLAPI bool IsMaterialValid(Material material); // Check if a material is valid (shader assigned, map textures loaded in GPU)
RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM)
RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
@@ -1624,11 +1627,11 @@ RLAPI float GetMasterVolume(void); // Get mas
// Wave/Sound loading/unloading functions
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
-RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready
+RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters)
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data
-RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready
+RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized)
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
RLAPI void UnloadWave(Wave wave); // Unload wave data
RLAPI void UnloadSound(Sound sound); // Unload sound
@@ -1654,7 +1657,7 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload
// Music management functions
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
-RLAPI bool IsMusicReady(Music music); // Checks if a music stream is ready
+RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized)
RLAPI void UnloadMusicStream(Music music); // Unload music stream
RLAPI void PlayMusicStream(Music music); // Start music playing
RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing
@@ -1671,7 +1674,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur
// AudioStream management functions
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
-RLAPI bool IsAudioStreamReady(AudioStream stream); // Checks if an audio stream is ready
+RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized)
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
diff --git a/src/raymath.h b/src/raymath.h
index 62d52f8fd..d1b5ab01e 100644
--- a/src/raymath.h
+++ b/src/raymath.h
@@ -1,6 +1,6 @@
/**********************************************************************************************
*
-* raymath v1.5 - Math functions to work with Vector2, Vector3, Matrix and Quaternions
+* raymath v2.0 - Math functions to work with Vector2, Vector3, Matrix and Quaternions
*
* CONVENTIONS:
* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all
@@ -12,7 +12,7 @@
* - Functions are always self-contained, no function use another raymath function inside,
* required code is directly re-implemented inside
* - Functions input parameters are always received by value (2 unavoidable exceptions)
-* - Functions use always a "result" variable for return
+* - Functions use always a "result" variable for return (except C++ operators)
* - Functions are always defined inline
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
* - No compound literals used to make sure libray is compatible with C++
@@ -27,6 +27,8 @@
* Define static inline functions code, so #include header suffices for use.
* This may use up lots of memory.
*
+* #define RAYMATH_DISABLE_CPP_OPERATORS
+* Disables C++ operator overloads for raymath types.
*
* LICENSE: zlib/libpng
*
@@ -2580,4 +2582,354 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio
}
}
+#if defined(__cplusplus) && !defined(RAYMATH_DISABLE_CPP_OPERATORS)
+
+// Optional C++ math operators
+//-------------------------------------------------------------------------------
+
+// Vector2 operators
+static constexpr Vector2 Vector2Zeros = { 0, 0 };
+static constexpr Vector2 Vector2Ones = { 1, 1 };
+static constexpr Vector2 Vector2UnitX = { 1, 0 };
+static constexpr Vector2 Vector2UnitY = { 0, 1 };
+
+inline Vector2 operator + (const Vector2& lhs, const Vector2& rhs)
+{
+ return Vector2Add(lhs, rhs);
+}
+
+inline const Vector2& operator += (Vector2& lhs, const Vector2& rhs)
+{
+ lhs = Vector2Add(lhs, rhs);
+ return lhs;
+}
+
+inline Vector2 operator - (const Vector2& lhs, const Vector2& rhs)
+{
+ return Vector2Subtract(lhs, rhs);
+}
+
+inline const Vector2& operator -= (Vector2& lhs, const Vector2& rhs)
+{
+ lhs = Vector2Subtract(lhs, rhs);
+ return lhs;
+}
+
+inline Vector2 operator * (const Vector2& lhs, const float& rhs)
+{
+ return Vector2Scale(lhs, rhs);
+}
+
+inline const Vector2& operator *= (Vector2& lhs, const float& rhs)
+{
+ lhs = Vector2Scale(lhs, rhs);
+ return lhs;
+}
+
+inline Vector2 operator * (const Vector2& lhs, const Vector2& rhs)
+{
+ return Vector2Multiply(lhs, rhs);
+}
+
+inline const Vector2& operator *= (Vector2& lhs, const Vector2& rhs)
+{
+ lhs = Vector2Multiply(lhs, rhs);
+ return lhs;
+}
+
+inline Vector2 operator * (const Vector2& lhs, const Matrix& rhs)
+{
+ return Vector2Transform(lhs, rhs);
+}
+
+inline const Vector2& operator -= (Vector2& lhs, const Matrix& rhs)
+{
+ lhs = Vector2Transform(lhs, rhs);
+ return lhs;
+}
+
+inline Vector2 operator / (const Vector2& lhs, const float& rhs)
+{
+ return Vector2Scale(lhs, 1.0f / rhs);
+}
+
+inline const Vector2& operator /= (Vector2& lhs, const float& rhs)
+{
+ lhs = Vector2Scale(lhs, rhs);
+ return lhs;
+}
+
+inline Vector2 operator / (const Vector2& lhs, const Vector2& rhs)
+{
+ return Vector2Divide(lhs, rhs);
+}
+
+inline const Vector2& operator /= (Vector2& lhs, const Vector2& rhs)
+{
+ lhs = Vector2Divide(lhs, rhs);
+ return lhs;
+}
+
+inline bool operator == (const Vector2& lhs, const Vector2& rhs)
+{
+ return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y);
+}
+
+inline bool operator != (const Vector2& lhs, const Vector2& rhs)
+{
+ return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y);
+}
+
+// Vector3 operators
+static constexpr Vector3 Vector3Zeros = { 0, 0, 0 };
+static constexpr Vector3 Vector3Ones = { 1, 1, 1 };
+static constexpr Vector3 Vector3UnitX = { 1, 0, 0 };
+static constexpr Vector3 Vector3UnitY = { 0, 1, 0 };
+static constexpr Vector3 Vector3UnitZ = { 0, 0, 1 };
+
+inline Vector3 operator + (const Vector3& lhs, const Vector3& rhs)
+{
+ return Vector3Add(lhs, rhs);
+}
+
+inline const Vector3& operator += (Vector3& lhs, const Vector3& rhs)
+{
+ lhs = Vector3Add(lhs, rhs);
+ return lhs;
+}
+
+inline Vector3 operator - (const Vector3& lhs, const Vector3& rhs)
+{
+ return Vector3Subtract(lhs, rhs);
+}
+
+inline const Vector3& operator -= (Vector3& lhs, const Vector3& rhs)
+{
+ lhs = Vector3Subtract(lhs, rhs);
+ return lhs;
+}
+
+inline Vector3 operator * (const Vector3& lhs, const float& rhs)
+{
+ return Vector3Scale(lhs, rhs);
+}
+
+inline const Vector3& operator *= (Vector3& lhs, const float& rhs)
+{
+ lhs = Vector3Scale(lhs, rhs);
+ return lhs;
+}
+
+inline Vector3 operator * (const Vector3& lhs, const Vector3& rhs)
+{
+ return Vector3Multiply(lhs, rhs);
+}
+
+inline const Vector3& operator *= (Vector3& lhs, const Vector3& rhs)
+{
+ lhs = Vector3Multiply(lhs, rhs);
+ return lhs;
+}
+
+inline Vector3 operator * (const Vector3& lhs, const Matrix& rhs)
+{
+ return Vector3Transform(lhs, rhs);
+}
+
+inline const Vector3& operator -= (Vector3& lhs, const Matrix& rhs)
+{
+ lhs = Vector3Transform(lhs, rhs);
+ return lhs;
+}
+
+inline Vector3 operator / (const Vector3& lhs, const float& rhs)
+{
+ return Vector3Scale(lhs, 1.0f / rhs);
+}
+
+inline const Vector3& operator /= (Vector3& lhs, const float& rhs)
+{
+ lhs = Vector3Scale(lhs, rhs);
+ return lhs;
+}
+
+inline Vector3 operator / (const Vector3& lhs, const Vector3& rhs)
+{
+ return Vector3Divide(lhs, rhs);
+}
+
+inline const Vector3& operator /= (Vector3& lhs, const Vector3& rhs)
+{
+ lhs = Vector3Divide(lhs, rhs);
+ return lhs;
+}
+
+inline bool operator == (const Vector3& lhs, const Vector3& rhs)
+{
+ return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z);
+}
+
+inline bool operator != (const Vector3& lhs, const Vector3& rhs)
+{
+ return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z);
+}
+
+// Vector4 operators
+static constexpr Vector4 Vector4Zeros = { 0, 0, 0, 0 };
+static constexpr Vector4 Vector4Ones = { 1, 1, 1, 1 };
+static constexpr Vector4 Vector4UnitX = { 1, 0, 0, 0 };
+static constexpr Vector4 Vector4UnitY = { 0, 1, 0, 0 };
+static constexpr Vector4 Vector4UnitZ = { 0, 0, 1, 0 };
+static constexpr Vector4 Vector4UnitW = { 0, 0, 0, 1 };
+
+inline Vector4 operator + (const Vector4& lhs, const Vector4& rhs)
+{
+ return Vector4Add(lhs, rhs);
+}
+
+inline const Vector4& operator += (Vector4& lhs, const Vector4& rhs)
+{
+ lhs = Vector4Add(lhs, rhs);
+ return lhs;
+}
+
+inline Vector4 operator - (const Vector4& lhs, const Vector4& rhs)
+{
+ return Vector4Subtract(lhs, rhs);
+}
+
+inline const Vector4& operator -= (Vector4& lhs, const Vector4& rhs)
+{
+ lhs = Vector4Subtract(lhs, rhs);
+ return lhs;
+}
+
+inline Vector4 operator * (const Vector4& lhs, const float& rhs)
+{
+ return Vector4Scale(lhs, rhs);
+}
+
+inline const Vector4& operator *= (Vector4& lhs, const float& rhs)
+{
+ lhs = Vector4Scale(lhs, rhs);
+ return lhs;
+}
+
+inline Vector4 operator * (const Vector4& lhs, const Vector4& rhs)
+{
+ return Vector4Multiply(lhs, rhs);
+}
+
+inline const Vector4& operator *= (Vector4& lhs, const Vector4& rhs)
+{
+ lhs = Vector4Multiply(lhs, rhs);
+ return lhs;
+}
+
+inline Vector4 operator / (const Vector4& lhs, const float& rhs)
+{
+ return Vector4Scale(lhs, 1.0f / rhs);
+}
+
+inline const Vector4& operator /= (Vector4& lhs, const float& rhs)
+{
+ lhs = Vector4Scale(lhs, rhs);
+ return lhs;
+}
+
+inline Vector4 operator / (const Vector4& lhs, const Vector4& rhs)
+{
+ return Vector4Divide(lhs, rhs);
+}
+
+inline const Vector4& operator /= (Vector4& lhs, const Vector4& rhs)
+{
+ lhs = Vector4Divide(lhs, rhs);
+ return lhs;
+}
+
+inline bool operator == (const Vector4& lhs, const Vector4& rhs)
+{
+ return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z) && FloatEquals(lhs.w, rhs.w);
+}
+
+inline bool operator != (const Vector4& lhs, const Vector4& rhs)
+{
+ return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z) || !FloatEquals(lhs.w, rhs.w);
+}
+
+// Quaternion operators
+static constexpr Quaternion QuaternionZeros = { 0, 0, 0, 0 };
+static constexpr Quaternion QuaternionOnes = { 1, 1, 1, 1 };
+static constexpr Quaternion QuaternionUnitX = { 0, 0, 0, 1 };
+
+inline Quaternion operator + (const Quaternion& lhs, const float& rhs)
+{
+ return QuaternionAddValue(lhs, rhs);
+}
+
+inline const Quaternion& operator += (Quaternion& lhs, const float& rhs)
+{
+ lhs = QuaternionAddValue(lhs, rhs);
+ return lhs;
+}
+
+inline Quaternion operator - (const Quaternion& lhs, const float& rhs)
+{
+ return QuaternionSubtractValue(lhs, rhs);
+}
+
+inline const Quaternion& operator -= (Quaternion& lhs, const float& rhs)
+{
+ lhs = QuaternionSubtractValue(lhs, rhs);
+ return lhs;
+}
+
+inline Quaternion operator * (const Quaternion& lhs, const Matrix& rhs)
+{
+ return QuaternionTransform(lhs, rhs);
+}
+
+inline const Quaternion& operator *= (Quaternion& lhs, const Matrix& rhs)
+{
+ lhs = QuaternionTransform(lhs, rhs);
+ return lhs;
+}
+
+// Matrix operators
+inline Matrix operator + (const Matrix& lhs, const Matrix& rhs)
+{
+ return MatrixAdd(lhs, rhs);
+}
+
+inline const Matrix& operator += (Matrix& lhs, const Matrix& rhs)
+{
+ lhs = MatrixAdd(lhs, rhs);
+ return lhs;
+}
+
+inline Matrix operator - (const Matrix& lhs, const Matrix& rhs)
+{
+ return MatrixSubtract(lhs, rhs);
+}
+
+inline const Matrix& operator -= (Matrix& lhs, const Matrix& rhs)
+{
+ lhs = MatrixSubtract(lhs, rhs);
+ return lhs;
+}
+
+inline Matrix operator * (const Matrix& lhs, const Matrix& rhs)
+{
+ return MatrixMultiply(lhs, rhs);
+}
+
+inline const Matrix& operator *= (Matrix& lhs, const Matrix& rhs)
+{
+ lhs = MatrixMultiply(lhs, rhs);
+ return lhs;
+}
+//-------------------------------------------------------------------------------
+#endif // C++ operators
+
#endif // RAYMATH_H
diff --git a/src/rcamera.h b/src/rcamera.h
index ccab549c1..bd2b36e03 100644
--- a/src/rcamera.h
+++ b/src/rcamera.h
@@ -162,7 +162,6 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
#endif // RCAMERA_H
-
/***********************************************************************************
*
* CAMERA IMPLEMENTATION
diff --git a/src/rcore.c b/src/rcore.c
index e154d6173..a1771d18e 100644
--- a/src/rcore.c
+++ b/src/rcore.c
@@ -691,7 +691,7 @@ void InitWindow(int width, int height, const char *title)
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
-
+
TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", GetWorkingDirectory());
}
@@ -1342,10 +1342,10 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
return shader;
}
-// Check if a shader is ready
-bool IsShaderReady(Shader shader)
+// Check if a shader is valid (loaded on GPU)
+bool IsShaderValid(Shader shader)
{
- return ((shader.id > 0) && // Validate shader id (loaded successfully)
+ return ((shader.id > 0) && // Validate shader id (GPU loaded successfully)
(shader.locs != NULL)); // Validate memory has been allocated for default shader locations
// The following locations are tried to be set automatically (locs[i] >= 0),
@@ -2577,6 +2577,265 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
return decodedData;
}
+// Compute CRC32 hash code
+unsigned int ComputeCRC32(unsigned char *data, int dataSize)
+{
+ static unsigned int crcTable[256] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+ };
+
+ unsigned int crc = ~0u;
+
+ for (int i = 0; i < dataSize; i++) crc = (crc >> 8) ^ crcTable[data[i] ^ (crc & 0xff)];
+
+ return ~crc;
+}
+
+// Compute MD5 hash code
+// NOTE: Returns a static int[4] array (16 bytes)
+unsigned int *ComputeMD5(unsigned char *data, int dataSize)
+{
+ #define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
+
+ static unsigned int hash[4] = { 0 }; // Hash to be returned
+
+ // WARNING: All variables are unsigned 32 bit and wrap modulo 2^32 when calculating
+
+ // NOTE: r specifies the per-round shift amounts
+ unsigned int r[] = {
+ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
+ 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
+ 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
+ 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
+ };
+
+ // Using binary integer part of the sines of integers (in radians) as constants
+ unsigned int k[] = {
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+ };
+
+ hash[0] = 0x67452301;
+ hash[1] = 0xefcdab89;
+ hash[2] = 0x98badcfe;
+ hash[3] = 0x10325476;
+
+ // Pre-processing: adding a single 1 bit
+ // Append '1' bit to message
+ // NOTE: The input bytes are considered as bits strings,
+ // where the first bit is the most significant bit of the byte
+
+ // Pre-processing: padding with zeros
+ // Append '0' bit until message length in bit 448 (mod 512)
+ // Append length mod (2 pow 64) to message
+
+ int newDataSize = ((((dataSize + 8)/64) + 1)*64) - 8;
+
+ unsigned char *msg = RL_CALLOC(newDataSize + 64, 1); // Initialize with '0' bits, allocating 64 extra bytes
+ memcpy(msg, data, dataSize);
+ msg[dataSize] = 128; // Write the '1' bit
+
+ unsigned int bitsLen = 8*dataSize;
+ memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer
+
+ // Process the message in successive 512-bit chunks for each 512-bit chunk of message
+ for (int offset = 0; offset < newDataSize; offset += (512/8))
+ {
+ // Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
+ unsigned int *w = (unsigned int *)(msg + offset);
+
+ // Initialize hash value for this chunk
+ unsigned int a = hash[0];
+ unsigned int b = hash[1];
+ unsigned int c = hash[2];
+ unsigned int d = hash[3];
+
+ for (int i = 0; i < 64; i++)
+ {
+ unsigned int f = 0;
+ unsigned int g = 0;
+
+ if (i < 16)
+ {
+ f = (b & c) | ((~b) & d);
+ g = i;
+ }
+ else if (i < 32)
+ {
+ f = (d & b) | ((~d) & c);
+ g = (5*i + 1)%16;
+ }
+ else if (i < 48)
+ {
+ f = b ^ c ^ d;
+ g = (3*i + 5)%16;
+ }
+ else
+ {
+ f = c ^ (b | (~d));
+ g = (7*i)%16;
+ }
+
+ unsigned int temp = d;
+ d = c;
+ c = b;
+ b = b + ROTATE_LEFT((a + f + k[i] + w[g]), r[i]);
+ a = temp;
+ }
+
+ // Add chunk's hash to result so far
+ hash[0] += a;
+ hash[1] += b;
+ hash[2] += c;
+ hash[3] += d;
+ }
+
+ RL_FREE(msg);
+
+ return hash;
+}
+
+// Compute SHA-1 hash code
+// NOTE: Returns a static int[5] array (20 bytes)
+unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
+ #define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
+
+ static unsigned int hash[5] = { 0 }; // Hash to be returned
+
+ // Initialize hash values
+ hash[0] = 0x67452301;
+ hash[1] = 0xEFCDAB89;
+ hash[2] = 0x98BADCFE;
+ hash[3] = 0x10325476;
+ hash[4] = 0xC3D2E1F0;
+
+ // Pre-processing: adding a single 1 bit
+ // Append '1' bit to message
+ // NOTE: The input bytes are considered as bits strings,
+ // where the first bit is the most significant bit of the byte
+
+ // Pre-processing: padding with zeros
+ // Append '0' bit until message length in bit 448 (mod 512)
+ // Append length mod (2 pow 64) to message
+
+ int newDataSize = ((((dataSize + 8)/64) + 1)*64);
+
+ unsigned char *msg = RL_CALLOC(newDataSize, 1); // Initialize with '0' bits
+ memcpy(msg, data, dataSize);
+ msg[dataSize] = 128; // Write the '1' bit
+
+ unsigned int bitsLen = 8*dataSize;
+ msg[newDataSize-1] = bitsLen;
+
+ // Process the message in successive 512-bit chunks
+ for (int offset = 0; offset < newDataSize; offset += (512/8))
+ {
+ // Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
+ unsigned int w[80] = {0};
+ for (int i = 0; i < 16; i++) {
+ w[i] = (msg[offset + (i * 4) + 0] << 24) |
+ (msg[offset + (i * 4) + 1] << 16) |
+ (msg[offset + (i * 4) + 2] << 8) |
+ (msg[offset + (i * 4) + 3]);
+ }
+
+ // Message schedule: extend the sixteen 32-bit words into eighty 32-bit words:
+ for (int i = 16; i < 80; ++i) {
+ w[i] = ROTATE_LEFT(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
+ }
+
+ // Initialize hash value for this chunk
+ unsigned int a = hash[0];
+ unsigned int b = hash[1];
+ unsigned int c = hash[2];
+ unsigned int d = hash[3];
+ unsigned int e = hash[4];
+
+ for (int i = 0; i < 80; i++)
+ {
+ unsigned int f = 0;
+ unsigned int k = 0;
+
+ if (i < 20) {
+ f = (b & c) | ((~b) & d);
+ k = 0x5A827999;
+ } else if (i < 40) {
+ f = b ^ c ^ d;
+ k = 0x6ED9EBA1;
+ } else if (i < 60) {
+ f = (b & c) | (b & d) | (c & d);
+ k = 0x8F1BBCDC;
+ } else {
+ f = b ^ c ^ d;
+ k = 0xCA62C1D6;
+ }
+
+ unsigned int temp = ROTATE_LEFT(a, 5) + f + e + k + w[i];
+ e = d;
+ d = c;
+ c = ROTATE_LEFT(b, 30);
+ b = a;
+ a = temp;
+ }
+
+ // Add this chunk's hash to result so far
+ hash[0] += a;
+ hash[1] += b;
+ hash[2] += c;
+ hash[3] += d;
+ hash[4] += e;
+ }
+
+ free(msg);
+
+ return hash;
+}
+
//----------------------------------------------------------------------------------
// Module Functions Definition: Automation Events Recording and Playing
//----------------------------------------------------------------------------------
@@ -3457,14 +3716,14 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
break;
}
}
- else
+ else
{
if ((filter != NULL) && (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0))
{
strcpy(files->paths[files->count], path);
files->count++;
}
-
+
if (files->count >= files->capacity)
{
TRACELOG(LOG_WARNING, "FILEIO: Maximum filepath scan capacity reached (%i files)", files->capacity);
diff --git a/src/rgestures.h b/src/rgestures.h
index 664a6e1cc..b5624be56 100644
--- a/src/rgestures.h
+++ b/src/rgestures.h
@@ -434,7 +434,7 @@ int GetGestureDetected(void)
return (GESTURES.enabledFlags & GESTURES.current);
}
-// Hold time measured in ms
+// Hold time measured in seconds
float GetGestureHoldDuration(void)
{
// NOTE: time is calculated on current gesture HOLD
@@ -517,7 +517,7 @@ static double rgGetCurrentTime(void)
#if defined(_WIN32)
unsigned long long int clockFrequency, currentTime;
- QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
+ QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
QueryPerformanceCounter(¤tTime);
time = (double)currentTime/clockFrequency; // Time in seconds
diff --git a/src/rlgl.h b/src/rlgl.h
index 43698f63a..6cfc2dcfb 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -347,7 +347,6 @@
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6
#endif
-
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
@@ -357,7 +356,6 @@
#endif
#endif
-
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
@@ -2474,25 +2472,47 @@ void rlLoadExtensions(void *loader)
}
// Check instanced rendering support
- if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // Web ANGLE
+ if (strstr(extList[i], (const char*)"instanced_arrays") != NULL) // Broad check for instanced_arrays
{
- glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE");
- glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE");
- glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE");
-
- if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
- }
- else
- {
- if ((strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0) && // Standard EXT
- (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0))
+ // Specific check
+ if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // ANGLE
+ {
+ glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE");
+ glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE");
+ glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE");
+ }
+ else if (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0) // EXT
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT");
-
- if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
}
+ else if (strcmp(extList[i], (const char *)"GL_NV_instanced_arrays") == 0) // NVIDIA GLES
+ {
+ glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV");
+ glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV");
+ glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorNV");
+ }
+
+ // The feature will only be marked as supported if the elements from GL_XXX_instanced_arrays are present
+ if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
+ }
+ else if (strstr(extList[i], (const char *)"draw_instanced") != NULL)
+ {
+ // GL_ANGLE_draw_instanced doesn't exist
+ if (strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0)
+ {
+ glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
+ glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
+ }
+ else if (strcmp(extList[i], (const char*)"GL_NV_draw_instanced") == 0)
+ {
+ glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV");
+ glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV");
+ }
+
+ // But the functions will at least be loaded if only GL_XX_EXT_draw_instanced exist
+ if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
}
// Check NPOT textures support
diff --git a/src/rmodels.c b/src/rmodels.c
index d2bf528ff..30130d9e0 100644
--- a/src/rmodels.c
+++ b/src/rmodels.c
@@ -426,14 +426,14 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
{
#if 0
// Basic implementation, do not use it!
- // For a sphere with 16 rings and 16 slices it requires 8640 cos()/sin() function calls!
+ // For a sphere with 16 rings and 16 slices it requires 8640 cos()/sin() function calls!
// New optimized version below only requires 4 cos()/sin() calls
-
+
rlPushMatrix();
// NOTE: Transformation is applied in inverse order (scale -> translate)
rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
rlScalef(radius, radius, radius);
-
+
rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a);
@@ -488,7 +488,7 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
for (int i = 0; i < rings + 1; i++)
{
- for (int j = 0; j < slices; j++)
+ for (int j = 0; j < slices; j++)
{
vertices[0] = vertices[2]; // Rotate around y axis to set up vertices for next face
vertices[1] = vertices[3];
@@ -702,7 +702,6 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl
rlPopMatrix();
}
-
// Draw a wired cylinder with base at startPos and top at endPos
// NOTE: It could be also used for pyramid and cone
void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color)
@@ -1156,8 +1155,8 @@ Model LoadModelFromMesh(Mesh mesh)
return model;
}
-// Check if a model is ready
-bool IsModelReady(Model model)
+// Check if a model is valid (loaded in GPU, VAO/VBOs)
+bool IsModelValid(Model model)
{
bool result = false;
@@ -1167,7 +1166,23 @@ bool IsModelReady(Model model)
(model.meshCount > 0) && // Validate mesh count
(model.materialCount > 0)) result = true; // Validate material count
- // NOTE: This is a very general model validation, many elements could be validated from a model...
+ // NOTE: Many elements could be validated from a model, including every model mesh VAO/VBOs
+ // but some VBOs could not be used, it depends on Mesh vertex data
+ for (int i = 0; i < model.meshCount; i++)
+ {
+ if ((model.meshes[i].vertices != NULL) && (model.meshes[i].vboId[0] == 0)) { result = false; break; } // Vertex position buffer not uploaded to GPU
+ if ((model.meshes[i].texcoords != NULL) && (model.meshes[i].vboId[1] == 0)) { result = false; break; } // Vertex textcoords buffer not uploaded to GPU
+ if ((model.meshes[i].normals != NULL) && (model.meshes[i].vboId[2] == 0)) { result = false; break; } // Vertex normals buffer not uploaded to GPU
+ if ((model.meshes[i].colors != NULL) && (model.meshes[i].vboId[3] == 0)) { result = false; break; } // Vertex colors buffer not uploaded to GPU
+ if ((model.meshes[i].tangents != NULL) && (model.meshes[i].vboId[4] == 0)) { result = false; break; } // Vertex tangents buffer not uploaded to GPU
+ if ((model.meshes[i].texcoords2 != NULL) && (model.meshes[i].vboId[5] == 0)) { result = false; break; } // Vertex texcoords2 buffer not uploaded to GPU
+ if ((model.meshes[i].indices != NULL) && (model.meshes[i].vboId[6] == 0)) { result = false; break; } // Vertex indices buffer not uploaded to GPU
+ if ((model.meshes[i].boneIds != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIds buffer not uploaded to GPU
+ if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU
+
+ // NOTE: Some OpenGL versions do not support VAO, so we don't check it
+ //if (model.meshes[i].vaoId == 0) { result = false; break }
+ }
return result;
}
@@ -1259,7 +1274,6 @@ void UploadMesh(Mesh *mesh, bool dynamic)
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights
#endif
-
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
mesh->vaoId = rlLoadVertexArray();
rlEnableVertexArray(mesh->vaoId);
@@ -1348,7 +1362,7 @@ void UploadMesh(Mesh *mesh, bool dynamic)
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
if (mesh->boneIds != NULL)
{
- // Enable vertex attribute: boneIds (shader-location = 6)
+ // Enable vertex attribute: boneIds (shader-location = 7)
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = rlLoadVertexBuffer(mesh->boneIds, mesh->vertexCount*4*sizeof(unsigned char), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, 4, RL_UNSIGNED_BYTE, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS);
@@ -1361,10 +1375,10 @@ void UploadMesh(Mesh *mesh, bool dynamic)
rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, value, SHADER_ATTRIB_VEC4, 4);
rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS);
}
-
+
if (mesh->boneWeights != NULL)
{
- // Enable vertex attribute: boneWeights (shader-location = 7)
+ // Enable vertex attribute: boneWeights (shader-location = 8)
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = rlLoadVertexBuffer(mesh->boneWeights, mesh->vertexCount*4*sizeof(float), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS);
@@ -1493,7 +1507,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
- // Upload Bone Transforms
+ // Upload Bone Transforms
if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices)
{
rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount);
@@ -1586,7 +1600,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]);
}
-
+
// Bind mesh VBO data: vertex bone weights (shader-location = 7, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1)
{
@@ -1737,15 +1751,15 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
// Upload model normal matrix (if locations available)
if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
-
+
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
- // Upload Bone Transforms
+ // Upload Bone Transforms
if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices)
{
rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount);
}
#endif
-
+
//-----------------------------------------------------
// Bind active texture maps (if available)
@@ -1831,7 +1845,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]);
}
-
+
// Bind mesh VBO data: vertex bone weights (shader-location = 7, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1)
{
@@ -2098,7 +2112,6 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName)
return success;
}
-
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
// Process obj materials
static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount)
@@ -2185,14 +2198,16 @@ Material LoadMaterialDefault(void)
return material;
}
-// Check if a material is ready
-bool IsMaterialReady(Material material)
+// Check if a material is valid (map textures loaded in GPU)
+bool IsMaterialValid(Material material)
{
bool result = false;
if ((material.maps != NULL) && // Validate material contain some map
(material.shader.id > 0)) result = true; // Validate material shader is valid
+ // TODO: Check if available maps contain loaded textures
+
return result;
}
@@ -2353,20 +2368,20 @@ void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int fram
{
if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL))
{
- if (frame >= anim.frameCount) frame = frame%anim.frameCount;
-
+ if (frame >= anim.frameCount) frame = frame%anim.frameCount;
+
for (int i = 0; i < model.meshCount; i++)
{
if (model.meshes[i].boneMatrices)
{
assert(model.meshes[i].boneCount == anim.boneCount);
-
+
for (int boneId = 0; boneId < model.meshes[i].boneCount; boneId++)
{
Vector3 inTranslation = model.bindPose[boneId].translation;
Quaternion inRotation = model.bindPose[boneId].rotation;
Vector3 inScale = model.bindPose[boneId].scale;
-
+
Vector3 outTranslation = anim.framePoses[frame][boneId].translation;
Quaternion outRotation = anim.framePoses[frame][boneId].rotation;
Vector3 outScale = anim.framePoses[frame][boneId].scale;
@@ -2377,15 +2392,15 @@ void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int fram
Vector3 boneTranslation = Vector3Add(
Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation),
- outRotation), outTranslation);
+ outRotation), outTranslation);
Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation);
Vector3 boneScale = Vector3Multiply(outScale, invScale);
-
+
Matrix boneMatrix = MatrixMultiply(MatrixMultiply(
QuaternionToMatrix(boneRotation),
MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)),
MatrixScale(boneScale.x, boneScale.y, boneScale.z));
-
+
model.meshes[i].boneMatrices[boneId] = boneMatrix;
}
}
@@ -4809,12 +4824,12 @@ static Model LoadIQM(const char *fileName)
}
BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose);
-
+
for (int i = 0; i < model.meshCount; i++)
{
model.meshes[i].boneCount = model.boneCount;
model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
-
+
for (int j = 0; j < model.meshes[i].boneCount; j++)
{
model.meshes[i].boneMatrices[j] = MatrixIdentity();
@@ -5229,17 +5244,19 @@ static Model LoadGLTF(const char *fileName)
***********************************************************************************************/
// Macro to simplify attributes loading code
- #define LOAD_ATTRIBUTE(accesor, numComp, dataType, dstPtr) \
+ #define LOAD_ATTRIBUTE(accesor, numComp, srcType, dstPtr) LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, srcType)
+
+ #define LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, dstType) \
{ \
int n = 0; \
- dataType *buffer = (dataType *)accesor->buffer_view->buffer->data + accesor->buffer_view->offset/sizeof(dataType) + accesor->offset/sizeof(dataType); \
+ srcType *buffer = (srcType *)accesor->buffer_view->buffer->data + accesor->buffer_view->offset/sizeof(srcType) + accesor->offset/sizeof(srcType); \
for (unsigned int k = 0; k < accesor->count; k++) \
{\
for (int l = 0; l < numComp; l++) \
{\
- dstPtr[numComp*k + l] = buffer[n + l];\
+ dstPtr[numComp*k + l] = (dstType)buffer[n + l];\
}\
- n += (int)(accesor->stride/sizeof(dataType));\
+ n += (int)(accesor->stride/sizeof(srcType));\
}\
}
@@ -5680,8 +5697,6 @@ static Model LoadGLTF(const char *fileName)
else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);
}
else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);
-
-
}
// NOTE: Attributes related to animations are processed separately
@@ -5702,23 +5717,25 @@ static Model LoadGLTF(const char *fileName)
// Load unsigned short data type into mesh.indices
LOAD_ATTRIBUTE(attribute, 1, unsigned short, model.meshes[meshIndex].indices)
}
+ else if (attribute->component_type == cgltf_component_type_r_8u)
+ {
+ // Init raylib mesh indices to copy glTF attribute data
+ model.meshes[meshIndex].indices = RL_MALLOC(attribute->count * sizeof(unsigned short));
+ LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned char, model.meshes[meshIndex].indices, unsigned short)
+
+ }
else if (attribute->component_type == cgltf_component_type_r_32u)
{
// Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short));
-
- // Load data into a temp buffer to be converted to raylib data type
- unsigned int *temp = RL_MALLOC(attribute->count*sizeof(unsigned int));
- LOAD_ATTRIBUTE(attribute, 1, unsigned int, temp);
-
- // Convert data to raylib indices data type (unsigned short)
- for (unsigned int d = 0; d < attribute->count; d++) model.meshes[meshIndex].indices[d] = (unsigned short)temp[d];
+ LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned int, model.meshes[meshIndex].indices, unsigned short);
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName);
-
- RL_FREE(temp);
}
- else TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName);
+ else
+ {
+ TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName);
+ }
}
else model.meshes[meshIndex].triangleCount = model.meshes[meshIndex].vertexCount/3; // Unindexed mesh
@@ -5750,7 +5767,7 @@ static Model LoadGLTF(const char *fileName)
// - Only supports linear interpolation (default method in Blender when checked "Always Sample Animations" when exporting a GLTF file)
// - Only supports translation/rotation/scale animation channel.path, weights not considered (i.e. morph targets)
//----------------------------------------------------------------------------------------------------
- if (data->skins_count == 1)
+ if (data->skins_count > 0)
{
cgltf_skin skin = data->skins[0];
model.bones = LoadBoneInfoGLTF(skin, &model.boneCount);
@@ -5770,9 +5787,9 @@ static Model LoadGLTF(const char *fileName)
MatrixDecompose(worldMatrix, &(model.bindPose[i].translation), &(model.bindPose[i].rotation), &(model.bindPose[i].scale));
}
}
- else if (data->skins_count > 1)
+ if (data->skins_count > 1)
{
- TRACELOG(LOG_ERROR, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count);
+ TRACELOG(LOG_WARNING, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count);
}
meshIndex = 0;
@@ -5903,11 +5920,11 @@ static Model LoadGLTF(const char *fileName)
{
memcpy(model.meshes[meshIndex].animNormals, model.meshes[meshIndex].normals, model.meshes[meshIndex].vertexCount*3*sizeof(float));
}
-
+
// Bone Transform Matrices
model.meshes[meshIndex].boneCount = model.boneCount;
model.meshes[meshIndex].boneMatrices = RL_CALLOC(model.meshes[meshIndex].boneCount, sizeof(Matrix));
-
+
for (int j = 0; j < model.meshes[meshIndex].boneCount; j++)
{
model.meshes[meshIndex].boneMatrices[j] = MatrixIdentity();
@@ -6093,7 +6110,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
if (result == cgltf_result_success)
{
- if (data->skins_count == 1)
+ if (data->skins_count > 0)
{
cgltf_skin skin = data->skins[0];
*animCount = (int)data->animations_count;
@@ -6228,7 +6245,11 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
RL_FREE(boneChannels);
}
}
- else TRACELOG(LOG_ERROR, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count);
+
+ if (data->skins_count > 1)
+ {
+ TRACELOG(LOG_WARNING, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count);
+ }
cgltf_free(data);
}
@@ -6680,7 +6701,7 @@ static Model LoadM3D(const char *fileName)
{
memcpy(model.meshes[i].animVertices, model.meshes[i].vertices, model.meshes[i].vertexCount*3*sizeof(float));
memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float));
-
+
model.meshes[i].boneCount = model.boneCount;
model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
for (j = 0; j < model.meshes[i].boneCount; j++)
diff --git a/src/rshapes.c b/src/rshapes.c
index 66dfbf3b6..e9b5ca87b 100644
--- a/src/rshapes.c
+++ b/src/rshapes.c
@@ -828,8 +828,8 @@ void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color)
{
if ((lineThick > rec.width) || (lineThick > rec.height))
{
- if (rec.width > rec.height) lineThick = rec.height/2;
- else if (rec.width < rec.height) lineThick = rec.width/2;
+ if (rec.width >= rec.height) lineThick = rec.height/2;
+ else if (rec.width <= rec.height) lineThick = rec.width/2;
}
// When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following
diff --git a/src/rtext.c b/src/rtext.c
index e4c89d5f1..3510671be 100644
--- a/src/rtext.c
+++ b/src/rtext.c
@@ -581,17 +581,16 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
return font;
}
-// Check if a font is ready
-bool IsFontReady(Font font)
+// Check if a font is valid (font data loaded)
+// WARNING: GPU texture not checked
+bool IsFontValid(Font font)
{
- return ((font.texture.id > 0) && // Validate OpenGL id for font texture atlas
- (font.baseSize > 0) && // Validate font size
+ return ((font.baseSize > 0) && // Validate font size
(font.glyphCount > 0) && // Validate font contains some glyph
(font.recs != NULL) && // Validate font recs defining glyphs on texture atlas
(font.glyphs != NULL)); // Validate glyph data is loaded
- // NOTE: Further validations could be done to verify if recs count and glyphs count
- // match glyphCount and to verify that data contained is valid (glyphs values, metrics...)
+ // NOTE: Further validations could be done to verify if recs and glyphs contain valid data (glyphs values, metrics...)
}
// Load font data for further use
@@ -677,7 +676,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
{
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor);
-
+
if (chh > fontSize) TRACELOG(LOG_WARNING, "FONT: Character [0x%08x] size is bigger than expected font size", ch);
// Load characters images
@@ -1302,15 +1301,15 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
{
byteCounter++;
- int next = 0;
- letter = GetCodepointNext(&text[i], &next);
+ int codepointByteCount = 0;
+ letter = GetCodepointNext(&text[i], &codepointByteCount);
index = GetGlyphIndex(font, letter);
- i += next;
+ i += codepointByteCount;
if (letter != '\n')
{
- if (font.glyphs[index].advanceX != 0) textWidth += font.glyphs[index].advanceX;
+ if (font.glyphs[index].advanceX > 0) textWidth += font.glyphs[index].advanceX;
else textWidth += (font.recs[index].width + font.glyphs[index].offsetX);
}
else
@@ -1930,7 +1929,8 @@ int GetCodepointCount(const char *text)
const char *CodepointToUTF8(int codepoint, int *utf8Size)
{
static char utf8[6] = { 0 };
- int size = 0; // Byte size of codepoint
+ memset(utf8, 0, 6); // Clear static array
+ int size = 0; // Byte size of codepoint
if (codepoint <= 0x7f)
{
diff --git a/src/rtextures.c b/src/rtextures.c
index 6d3c21cf4..a4534a7a2 100644
--- a/src/rtextures.c
+++ b/src/rtextures.c
@@ -225,14 +225,6 @@
#pragma GCC diagnostic pop
#endif
-#if defined(SUPPORT_FILEFORMAT_SVG)
- #define NANOSVG_IMPLEMENTATION // Expands implementation
- #include "external/nanosvg.h"
-
- #define NANOSVGRAST_IMPLEMENTATION
- #include "external/nanosvgrast.h"
-#endif
-
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@@ -335,84 +327,6 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
return image;
}
-// Load an image from a SVG file or string with custom size
-Image LoadImageSvg(const char *fileNameOrString, int width, int height)
-{
- Image image = { 0 };
-
-#if defined(SUPPORT_FILEFORMAT_SVG)
- bool isSvgStringValid = false;
-
- // Validate fileName or string
- if (fileNameOrString != NULL)
- {
- int dataSize = 0;
- unsigned char *fileData = NULL;
-
- if (FileExists(fileNameOrString))
- {
- fileData = LoadFileData(fileNameOrString, &dataSize);
- isSvgStringValid = true;
- }
- else
- {
- // Validate fileData as valid SVG string data
- //