packages feed

h-raylib 5.5.0.0 → 5.5.1.0

raw patch · 84 files changed

+23340/−23783 lines, 84 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Raylib.Core.Textures: c'loadImageSvg :: CString -> CInt -> CInt -> IO (Ptr Image)
- Raylib.Core.Textures: loadImageSvg :: String -> Int -> Int -> IO Image
- Raylib.Types.Util.GUI: Icon228 :: GuiIconName
+ Raylib.Core: c'makeDirectory :: CString -> IO CInt
+ Raylib.Core: makeDirectory :: String -> IO Bool
+ Raylib.Core: setTraceLogCallback :: TraceLogCallback -> IO ()
+ Raylib.Core.Models: c'drawModelPoints :: Ptr Model -> Ptr Vector3 -> CFloat -> Ptr Color -> IO ()
+ Raylib.Core.Models: c'drawModelPointsEx :: Ptr Model -> Ptr Vector3 -> Ptr Vector3 -> CFloat -> Ptr Vector3 -> Ptr Color -> IO ()
+ Raylib.Core.Models: c'updateModelAnimationBoneMatrices :: Ptr Model -> Ptr ModelAnimation -> CInt -> IO ()
+ Raylib.Core.Models: drawModelPoints :: Model -> Vector3 -> Float -> Color -> IO ()
+ Raylib.Core.Models: drawModelPointsEx :: Model -> Vector3 -> Vector3 -> Float -> Vector3 -> Color -> IO ()
+ Raylib.Core.Models: updateModelAnimationBoneMatrices :: Model -> ModelAnimation -> Int -> IO ()
+ Raylib.Core.Textures: c'colorLerp :: Ptr Color -> Ptr Color -> CFloat -> IO (Ptr Color)
+ Raylib.Core.Textures: colorLerp :: Color -> Color -> Float -> Color
+ Raylib.Types.Core: type C'TraceLogCallback = FunPtr CInt -> CString -> IO ()
+ Raylib.Types.Core: type TraceLogCallback = TraceLogLevel -> String -> IO ()
+ Raylib.Types.Core.Models: DefaultShaderAttribLocationBoneIds :: DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: DefaultShaderAttribLocationBoneWeights :: DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: DefaultShaderAttribLocationColor :: DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: DefaultShaderAttribLocationIndices :: DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: DefaultShaderAttribLocationNormal :: DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: DefaultShaderAttribLocationPosition :: DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: DefaultShaderAttribLocationTangent :: DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: DefaultShaderAttribLocationTexcoord :: DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: DefaultShaderAttribLocationTexcoord2 :: DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: ShaderLocBoneMatrices :: ShaderLocationIndex
+ Raylib.Types.Core.Models: ShaderLocVertexBoneIds :: ShaderLocationIndex
+ Raylib.Types.Core.Models: ShaderLocVertexBoneWeights :: ShaderLocationIndex
+ Raylib.Types.Core.Models: [mesh'boneCount] :: Mesh -> Int
+ Raylib.Types.Core.Models: [mesh'boneMatrices] :: Mesh -> Maybe [Matrix]
+ Raylib.Types.Core.Models: data DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: instance GHC.Classes.Eq Raylib.Types.Core.Models.DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: instance GHC.Enum.Enum Raylib.Types.Core.Models.DefaultShaderAttributeLocation
+ Raylib.Types.Core.Models: instance GHC.Show.Show Raylib.Types.Core.Models.DefaultShaderAttributeLocation
+ Raylib.Types.Util.GUI: DropdownRollUp :: GuiDropdownBoxProperty
+ Raylib.Types.Util.GUI: IconHot :: GuiIconName
+ Raylib.Types.Util.RLGL: RLShaderUniformUIVec2 :: RLShaderUniformDataType
+ Raylib.Types.Util.RLGL: RLShaderUniformUIVec3 :: RLShaderUniformDataType
+ Raylib.Types.Util.RLGL: RLShaderUniformUIVec4 :: RLShaderUniformDataType
+ Raylib.Types.Util.RLGL: RLShaderUniformUInt :: RLShaderUniformDataType
+ Raylib.Util.Lenses: _mesh'boneCount :: Lens' Mesh Int
+ Raylib.Util.Lenses: _mesh'boneMatrices :: Lens' Mesh (Maybe [Matrix])
+ Raylib.Util.RLGL: c'rlSetUniformMatrices :: CInt -> Ptr Matrix -> CInt -> IO ()
+ Raylib.Util.RLGL: rlSetUniformMatrices :: Int -> [Matrix] -> IO ()
- Raylib.Core: setLoadFileDataCallback :: LoadFileDataCallback -> IO C'LoadFileDataCallback
+ Raylib.Core: setLoadFileDataCallback :: LoadFileDataCallback -> IO ()
- Raylib.Core: setLoadFileTextCallback :: LoadFileTextCallback -> IO C'LoadFileTextCallback
+ Raylib.Core: setLoadFileTextCallback :: LoadFileTextCallback -> IO ()
- Raylib.Core: setSaveFileDataCallback :: Storable a => SaveFileDataCallback a -> IO C'SaveFileDataCallback
+ Raylib.Core: setSaveFileDataCallback :: Storable a => SaveFileDataCallback a -> IO ()
- Raylib.Core: setSaveFileTextCallback :: SaveFileTextCallback -> IO C'SaveFileTextCallback
+ Raylib.Core: setSaveFileTextCallback :: SaveFileTextCallback -> IO ()
- Raylib.Types.Core: type C'LoadFileDataCallback = FunPtr (CString -> Ptr CUInt -> IO (Ptr CUChar))
+ Raylib.Types.Core: type C'LoadFileDataCallback = FunPtr CString -> Ptr CUInt -> IO Ptr CUChar
- Raylib.Types.Core: type C'LoadFileTextCallback = FunPtr (CString -> IO CString)
+ Raylib.Types.Core: type C'LoadFileTextCallback = FunPtr CString -> IO CString
- Raylib.Types.Core: type C'SaveFileDataCallback = FunPtr (CString -> Ptr () -> CUInt -> IO CInt)
+ Raylib.Types.Core: type C'SaveFileDataCallback = FunPtr CString -> Ptr () -> CUInt -> IO CInt
- Raylib.Types.Core: type C'SaveFileTextCallback = FunPtr (CString -> CString -> IO CInt)
+ Raylib.Types.Core: type C'SaveFileTextCallback = FunPtr CString -> CString -> IO CInt
- Raylib.Types.Core.Audio: type C'AudioCallback = FunPtr (Ptr () -> CUInt -> IO ())
+ Raylib.Types.Core.Audio: type C'AudioCallback = FunPtr Ptr () -> CUInt -> IO ()
- Raylib.Types.Core.Models: Mesh :: Int -> Int -> [Vector3] -> [Vector2] -> Maybe [Vector2] -> [Vector3] -> Maybe [Vector4] -> Maybe [Color] -> Maybe [Word16] -> Maybe [Vector3] -> Maybe [Vector3] -> Maybe [Word8] -> Maybe [Float] -> Integer -> Maybe [Integer] -> Mesh
+ Raylib.Types.Core.Models: Mesh :: Int -> Int -> [Vector3] -> [Vector2] -> Maybe [Vector2] -> [Vector3] -> Maybe [Vector4] -> Maybe [Color] -> Maybe [Word16] -> Maybe [Vector3] -> Maybe [Vector3] -> Maybe [Word8] -> Maybe [Float] -> Maybe [Matrix] -> Int -> Integer -> Maybe [Integer] -> Mesh

Files

CHANGELOG.md view
@@ -1,5 +1,20 @@ # h-raylib changelog +## Changelog guidelines (apply to `5.5.0.0` onward)++Changes ported from the upstream raylib code are not mentioned unless they are breaking changes. Changes and bug fixes in the h-raylib API are mentioned, breaking and non-breaking. Internal changes that do not change the API or affect functionality are not mentioned (e.g. performance improvements).++### Versioning scheme++h-raylib's version numbers do not follow the usual format. The first two numbers in the version track the underlying C raylib version. For example, `5.1.x.x` versions use raylib 5.1 under the hood. The third number represents breaking changes (renamed/deleted functions or modules). The last number represents non-breaking changes (new functions or modules, bug fixes, etc). The safest version bound format to use is `h-raylib >=x.y.z.w && <x.y.(z+1)` (instead of the usual `^>=` bound).++## Version 5.5.1.0+_11 October 2024_++- **BREAKING CHANGE**: `set*Callback` functions are no longer managed and do not return `IO C'*Callback` values+- **BREAKING CHANGE**: Removed `loadImageSvg` (upstream change in raylib)+- \[[#58](https://github.com/Anut-py/h-raylib/issues/58)\] Added support for `setTraceLogCallback`+ ## Version 5.5.0.0 _12 July 2024_ 
CONTRIBUTING.md view
@@ -12,27 +12,27 @@  [DOCUMENTATION.md](https://github.com/Anut-py/h-raylib/blob/master/DOCUMENTATION.md) has information that is specific to h-raylib. -# h-raylib roadmap+## h-raylib roadmap  This is a list of features that may be added to this project. Contributors are welcome to help implement these. -## Pending+### Pending  Items which have not yet been worked on. Feel free to work on one of these.  - Bind `rgestures` -## In progress+### In progress  - Add web build support \[[#4](https://github.com/Anut-py/h-raylib/issues/4)\] -## Implemented+### Implemented  Items which have been completed but not published to hackage.  (none) -## Published+### Published  Items which have been published to hackage. 
README.md view
@@ -1,6 +1,6 @@ # h-raylib: Haskell bindings for Raylib -[![cabal-build](https://github.com/Anut-py/h-raylib/actions/workflows/cabal-build.yml/badge.svg)](https://github.com/Anut-py/h-raylib/actions/workflows/cabal-build.yml) [![nix-build](https://github.com/Anut-py/h-raylib/actions/workflows/nix-build.yml/badge.svg)](https://github.com/Anut-py/h-raylib/actions/workflows/nix-build.yml) ![Hackage Version](https://img.shields.io/hackage/v/h-raylib)+[![cabal-build](https://github.com/Anut-py/h-raylib/actions/workflows/cabal-build.yml/badge.svg)](https://github.com/Anut-py/h-raylib/actions/workflows/cabal-build.yml) [![nix-build](https://github.com/Anut-py/h-raylib/actions/workflows/nix-build.yml/badge.svg)](https://github.com/Anut-py/h-raylib/actions/workflows/nix-build.yml) [![Hackage Version](https://img.shields.io/hackage/v/h-raylib)](https://hackage.haskell.org/package/h-raylib)   This library includes Haskell bindings to the [Raylib](https://www.raylib.com/) library.@@ -109,7 +109,7 @@ - When I try to compile an h-raylib program I get the error `Missing (or bad) C libraries: gcc_eh`   - See [#36](https://github.com/Anut-py/h-raylib/issues/36) -If you find a bug, please [create an issue on GitHub](https://github.com/Anut-py/h-raylib/issues).+If you find a bug, please [create an issue on GitHub](https://github.com/Anut-py/h-raylib/issues). There are probably some bindings that are incomplete or do not work properly, so if something seems wrong then it is most likely a bug.  If you have a question about the library that is not related to a bug, ask it on [GitHub discussions](https://github.com/Anut-py/h-raylib/discussions) or in the [Haskell GameDev Discord server](https://discord.gg/aKHNgxc59t). 
default.nix view
@@ -3,7 +3,7 @@ }: mkDerivation {   pname = "h-raylib";-  version = "5.5.0.0";+  version = "5.5.1.0";   src = ./.;   isLibrary = true;   isExecutable = buildExamples;
examples/basic-callbacks/src/Main.hs view
@@ -2,9 +2,9 @@ module Main where  import Paths_h_raylib (getDataFileName)-import Raylib.Core (clearBackground, initWindow, setTargetFPS, windowShouldClose, closeWindow, setLoadFileTextCallback, loadFileText)+import Raylib.Core (clearBackground, initWindow, setTargetFPS, windowShouldClose, closeWindow, setLoadFileTextCallback, setTraceLogCallback, loadFileText) import Raylib.Core.Text (drawText)-import Raylib.Util (drawing, raylibApplication, WindowResources, managed)+import Raylib.Util (drawing, raylibApplication, WindowResources) import Raylib.Util.Colors (black, rayWhite)  filePath :: String@@ -14,9 +14,10 @@  startup :: IO AppState startup = do+  setTraceLogCallback (\logLevel text -> putStrLn (show logLevel ++ ": " ++ text))   window <- initWindow 600 450 "raylib [core] example - basic callbacks"   setTargetFPS 60-  _ <- managed window $ setLoadFileTextCallback (\s -> putStrLn ("opening file: " ++ s) >> readFile s)+  setLoadFileTextCallback (\s -> putStrLn ("opening file: " ++ s) >> readFile s)   text <- loadFileText =<< getDataFileName filePath   return (text, window) 
flake.nix view
@@ -9,10 +9,10 @@       forAllSystems' = nixpkgs.lib.genAttrs;       forAllSystems = forAllSystems' supportedSystems; -      raylibRev = "8d5374a443509036063a350d1649408e009425e7";-      raylibHash = "sha256-kYuqEUkyw8dngy5yBneNn+Br0xQr6NagP/s2CPM+q44=";-      rayguiRev = "3fb9d77a67243497e10ae0448374a52a2a65e26f";-      rayguiHash = "sha256-aWfXimbGU7RYqqOd44GmH3jPN8gcN4D/ygB71jIEr2c=";+      raylibRev = "f5328a9bb63a0e0eca7dead15cfa01a3ec1417c2";+      raylibHash = "sha256-gAv1jfMdbKWnlIqqBddVn+WE0BOIARMmagpK61bxVnU=";+      rayguiRev = "1e03efca48c50c5ea4b4a053d5bf04bad58d3e43";+      rayguiHash = "sha256-PzQZxCz63EPd7sVFBYY0T1s9jA5kOAxF9K4ojRoIMz4=";        pkgsForSystem =         system:
h-raylib.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               h-raylib-version:            5.5.0.0+version:            5.5.1.0 synopsis:           Raylib bindings for Haskell category:           graphics description:@@ -17,6 +17,10 @@   DOCUMENTATION.md   README.md +-- Requires >= 9.6.5 on Mac because this bug fix is required: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/12079+-- Works with >= 9.2.8 on Windows+tested-with: GHC >= 9.6.5+ extra-source-files:   default.nix   flake.nix@@ -108,15 +112,14 @@       , base       , h-raylib -    other-modules: Paths_h_raylib-    autogen-modules: Paths_h_raylib-+    other-modules:    Paths_h_raylib+    autogen-modules:  Paths_h_raylib     other-extensions:       BangPatterns       TemplateHaskell-      -    ghc-options: -Wall +    ghc-options:      -Wall+     if flag(platform-web)       ghc-options:         -no-hs-main -optl-mexec-model=reactor@@ -257,9 +260,9 @@     ScopedTypeVariables     TemplateHaskell     TemplateHaskellQuotes-  -  ghc-options: -Wall +  ghc-options:      -Wall+   if (flag(platform-windows) || (flag(detect-platform) && os(windows)))     if flag(mingw-cross)       extra-libraries:@@ -310,8 +313,8 @@    else -  -- Unsupported OS, do nothing. If you can get it working on an-  -- OS that isn't listed here, please add it here.+  --   Unsupported OS, do nothing. If you can get it working on an+  --   OS that isn't listed here, please add it here.   if flag(platform-nixos)     extra-libraries: raylib @@ -322,7 +325,9 @@     c-sources:   lib/web.c    else-    cc-options: -DPLATFORM_DESKTOP_GLFW -Wno-int-to-void-pointer-cast+    cc-options:+      -DPLATFORM_DESKTOP_GLFW -Wno-int-to-void-pointer-cast+     c-sources:       lib/rgui_bindings.c       lib/rl_bindings.c
lib/rl_bindings.c view
@@ -3,6 +3,7 @@  */  #include "rl_bindings.h"+#include <stdio.h>  RLBIND void SetWindowIcon_(Image *a) {@@ -642,13 +643,6 @@     return ptr; } -RLBIND Image *LoadImageSvg_(char *a, int b, int c)-{-    Image *ptr = (Image *)malloc(sizeof(Image));-    *ptr = LoadImageSvg(a, b, c);-    return ptr;-}- RLBIND Image *LoadImageAnim_(char *a, int *b) {     Image *ptr = (Image *)malloc(sizeof(Image));@@ -1144,6 +1138,13 @@     return ptr; } +RLBIND Color *ColorLerp_(Color *a, Color *b, float c)+{+    Color *ptr = (Color *)malloc(sizeof(Color));+    *ptr = ColorLerp(*a, *b, c);+    return ptr;+}+ RLBIND Color *GetColor_(unsigned int a) {     Color *ptr = (Color *)malloc(sizeof(Color));@@ -1443,6 +1444,16 @@     DrawModelWiresEx(*a, *b, *c, d, *e, *f); } +RLBIND void DrawModelPoints_(Model *a, Vector3 *b, float c, Color *d)+{+    DrawModelPoints(*a, *b, c, *d);+}++RLBIND void DrawModelPointsEx_(Model *a, Vector3 *b, Vector3 *c, float d, Vector3 *e, Color *f)+{+    DrawModelPointsEx(*a, *b, *c, d, *e, *f);+}+ RLBIND void DrawBoundingBox_(BoundingBox *a, Color *b) {     DrawBoundingBox(*a, *b);@@ -1614,6 +1625,11 @@     return IsModelAnimationValid(*a, *b); } +RLBIND void UpdateModelAnimationBoneMatrices_(Model *a, ModelAnimation *b, int c)+{+    UpdateModelAnimationBoneMatrices(*a, *b, c);+}+ RLBIND bool CheckCollisionSpheres_(Vector3 *a, float b, Vector3 *c, float d) {     return CheckCollisionSpheres(*a, b, *c, d);@@ -2362,6 +2378,22 @@     OpenURL(a); } +TraceLogCallback_ customCallback;++void CustomCallback(int logLevel, const char *text, va_list args)+{+    size_t n = vsnprintf(NULL, 0, text, args) + 1;+    char *buffer = malloc(n);+    vsnprintf(buffer, n, text, args);+    customCallback(logLevel, buffer);+}++RLBIND void SetTraceLogCallback_(TraceLogCallback_ a)+{+    customCallback = a;+    SetTraceLogCallback(&CustomCallback);+}+ RLBIND void SetLoadFileDataCallback_(LoadFileDataCallback a) {     SetLoadFileDataCallback(a);@@ -2470,6 +2502,11 @@ RLBIND const char *GetApplicationDirectory_() {     return GetApplicationDirectory();+}++RLBIND int MakeDirectory_(const char *a)+{+    return MakeDirectory(a); }  RLBIND bool ChangeDirectory_(const char *a)
lib/rl_bindings.h view
@@ -10,6 +10,8 @@  #include "rl_common.h" +typedef void (*TraceLogCallback_)(int logLevel, char *text);+ void SetWindowIcon_(Image *a);  Vector2 *GetMonitorPosition_(int a);@@ -238,8 +240,6 @@  Image *LoadImageRaw_(char *a, int b, int c, int d, int e); -Image *LoadImageSvg_(char *a, int b, int c);- Image *LoadImageAnim_(char *a, int *b);  Image *LoadImageAnimFromMemory_(char *a, unsigned char *b, int c, int *d);@@ -404,6 +404,8 @@  Color *ColorAlphaBlend_(Color *a, Color *b, Color *c); +Color *ColorLerp_(Color *a, Color *b, float c);+ Color *GetColor_(unsigned int a);  Color *GetPixelColor_(void *a, int b);@@ -510,6 +512,10 @@  void DrawModelWiresEx_(Model *a, Vector3 *b, Vector3 *c, float d, Vector3 *e, Color *f); +void DrawModelPoints_(Model *a, Vector3 *b, float c, Color *d);++void DrawModelPointsEx_(Model *a, Vector3 *b, Vector3 *c, float d, Vector3 *e, Color *f);+ void DrawBoundingBox_(BoundingBox *a, Color *b);  void DrawBillboard_(Camera3D *a, Texture *b, Vector3 *c, float d, Color *e);@@ -568,6 +574,8 @@  bool IsModelAnimationValid_(Model *a, ModelAnimation *b); +void UpdateModelAnimationBoneMatrices_(Model *a, ModelAnimation *b, int c);+ bool CheckCollisionSpheres_(Vector3 *a, float b, Vector3 *c, float d);  bool CheckCollisionBoxes_(BoundingBox *a, BoundingBox *b);@@ -856,6 +864,8 @@  void OpenURL_(const char *a); +void SetTraceLogCallback_(TraceLogCallback_ a);+ void SetLoadFileDataCallback_(LoadFileDataCallback a);  void SetSaveFileDataCallback_(SaveFileDataCallback a);@@ -899,6 +909,8 @@ const char *GetWorkingDirectory_();  const char *GetApplicationDirectory_();++int MakeDirectory_(const char *a);  bool ChangeDirectory_(const char *a); 
lib/rlgl_bindings.c view
@@ -21,6 +21,11 @@   rlSetUniformMatrix(locIndex, *mat); } +RLBIND void rlSetUniformMatrices_(int locIndex, const Matrix *mat, int count)+{+  rlSetUniformMatrices(locIndex, mat, count);+}+ RLBIND Matrix *rlGetMatrixProjectionStereo_(int eye) {   Matrix *ptr = (Matrix *)malloc(sizeof(Matrix));
lib/rlgl_bindings.h view
@@ -12,6 +12,8 @@  void rlSetUniformMatrix_(int locIndex, Matrix *mat); +void rlSetUniformMatrices_(int locIndex, const Matrix *mat, int count);+ Matrix *rlGetMatrixProjectionStereo_(int eye);  Matrix *rlGetMatrixViewOffsetStereo_(int eye);
raygui/src/raygui.h view
@@ -1,6 +1,6 @@ /******************************************************************************************* *-*   raygui v4.1-dev - A simple and easy-to-use immediate-mode gui library+*   raygui v4.5-dev - A simple and easy-to-use immediate-mode gui library * *   DESCRIPTION: *       raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also@@ -141,8 +141,23 @@ *           Draw text bounds rectangles for debug * *   VERSIONS HISTORY:-*       4.1-dev (2024)    Current dev version...+*       4.5-dev (Sep-2024)    Current dev version... *                         ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes+*                         ADDED: GuiValueBoxFloat()+*                         ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP+*                         ADDED: GuiListView() property: LIST_ITEMS_BORDER_WIDTH+*                         ADDED: Multiple new icons+*                         REVIEWED: GuiTabBar(), close tab with mouse middle button+*                         REVIEWED: GuiScrollPanel(), scroll speed proportional to content+*                         REVIEWED: GuiDropdownBox(), support roll up and hidden arrow+*                         REVIEWED: GuiTextBox(), cursor position initialization+*                         REVIEWED: GuiSliderPro(), control value change check+*                         REVIEWED: GuiGrid(), simplified implementation+*                         REVIEWED: GuiIconText(), increase buffer size and reviewed padding+*                         REVIEWED: GuiDrawText(), improved wrap mode drawing+*                         REVIEWED: GuiScrollBar(), minor tweaks+*                         REVIEWED: Functions descriptions, removed wrong return value reference+*                         REDESIGNED: GuiColorPanel(), improved HSV <-> RGBA convertion * *       4.0 (12-Sep-2023) ADDED: GuiToggleSlider() *                         ADDED: GuiColorPickerHSV() and GuiColorPanelHSV()@@ -317,9 +332,9 @@ #define RAYGUI_H  #define RAYGUI_VERSION_MAJOR 4-#define RAYGUI_VERSION_MINOR 1+#define RAYGUI_VERSION_MINOR 5 #define RAYGUI_VERSION_PATCH 0-#define RAYGUI_VERSION  "4.1-dev"+#define RAYGUI_VERSION  "4.5-dev"  #if !defined(RAYGUI_STANDALONE)     #include "raylib.h"@@ -617,7 +632,8 @@ typedef enum {     ARROW_PADDING = 16,         // DropdownBox arrow separation from border and items     DROPDOWN_ITEMS_SPACING,     // DropdownBox items separation-    DROPDOWN_ARROW_HIDDEN       // DropdownBox arrow hidden+    DROPDOWN_ARROW_HIDDEN,      // DropdownBox arrow hidden+    DROPDOWN_ROLL_UP            // DropdownBox roll up flag (default rolls down) } GuiDropdownBoxProperty;  // TextBox/TextBoxMulti/ValueBox/Spinner@@ -977,12 +993,12 @@     ICON_WARNING                  = 220,     ICON_HELP_BOX                 = 221,     ICON_INFO_BOX                 = 222,-    ICON_223                      = 223,-    ICON_224                      = 224,-    ICON_225                      = 225,-    ICON_226                      = 226,-    ICON_227                      = 227,-    ICON_228                      = 228,+    ICON_PRIORITY                 = 223,+    ICON_LAYERS_ISO               = 224,+    ICON_LAYERS2                  = 225,+    ICON_MLAYERS                  = 226,+    ICON_MAPS                     = 227,+    ICON_HOT                      = 228,     ICON_229                      = 229,     ICON_230                      = 230,     ICON_231                      = 231,@@ -1029,6 +1045,7 @@  #if defined(RAYGUI_IMPLEMENTATION) +#include <ctype.h>              // required for: isspace() [GuiTextBox()] #include <stdio.h>              // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()] #include <stdlib.h>             // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()] #include <string.h>             // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy()@@ -1300,7 +1317,7 @@     0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0,      // ICON_LAYERS2     0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0,      // ICON_MLAYERS     0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0,      // ICON_MAPS-    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_228+    0x04200000, 0x1cf00c60, 0x11f019f0, 0x0f3807b8, 0x1e3c0f3c, 0x1c1c1e1c, 0x1e3c1c1c, 0x00000f70,      // ICON_HOT     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_229     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_230     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_231@@ -1623,9 +1640,9 @@      // Draw control     //---------------------------------------------------------------------    GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)));-    GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)));-    GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)));+    GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)));+    GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)));+    GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)));      GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text);     //--------------------------------------------------------------------@@ -1646,7 +1663,7 @@     int result = 0;     GuiState state = guiState; -    Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR));+    Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR));      // Draw control     //--------------------------------------------------------------------@@ -1694,7 +1711,7 @@     //--------------------------------------------------------------------     if (text != NULL) GuiStatusBar(statusBar, text);  // Draw panel header as status bar -    GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED: LINE_COLOR)),+    GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED: (int)LINE_COLOR)),                      GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BASE_COLOR_DISABLED : BACKGROUND_COLOR)));     //-------------------------------------------------------------------- @@ -2335,12 +2352,16 @@     int itemSelected = *active;     int itemFocused = -1; +    int direction = 0; // Dropdown box open direction: down (default)+    if (GuiGetStyle(DROPDOWNBOX, DROPDOWN_ROLL_UP) == 1) direction = 1; // Up+     // Get substrings items from text (items pointers, lengths and count)     int itemCount = 0;     const char **items = GuiTextSplit(text, ';', &itemCount, NULL);      Rectangle boundsOpen = bounds;     boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));+    if (direction == 1) boundsOpen.y -= itemCount*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)) + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING);      Rectangle itemBounds = bounds; @@ -2367,7 +2388,8 @@             for (int i = 0; i < itemCount; i++)             {                 // Update item rectangle y position for next item-                itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));+                if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));+                else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));                  if (CheckCollisionPointRec(mousePoint, itemBounds))                 {@@ -2411,7 +2433,8 @@         for (int i = 0; i < itemCount; i++)         {             // Update item rectangle y position for next item-            itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));+            if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));+            else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));              if (i == itemSelected)             {@@ -2434,7 +2457,7 @@         GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },             TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); #else-        GuiDrawText("#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },+        GuiDrawText(direction? "#121#" : "#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },             TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));   // ICON_ARROW_DOWN_FILL #endif     }@@ -2581,24 +2604,59 @@                 }             } -            // Delete codepoint from text, before current cursor position-            if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))))+            // Delete related codepoints from text, before current cursor position+            if ((textLength > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))             {-                autoCursorDelayCounter++;+                int i = textBoxCursorIndex - 1;+                int accCodepointSize = 0; -                if (IsKeyPressed(KEY_BACKSPACE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0)      // Delay every movement some frames+                // Move cursor to the end of word if on space already+                while ((i > 0) && isspace(text[i]))                 {                     int prevCodepointSize = 0;-                    GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);+                    GetCodepointPrevious(text + i, &prevCodepointSize);+                    i -= prevCodepointSize;+                    accCodepointSize += prevCodepointSize;+                } -                    // Move backward text from cursor position-                    for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize];+                // Move cursor to the start of the word+                while ((i > 0) && !isspace(text[i]))+                {+                    int prevCodepointSize = 0;+                    GetCodepointPrevious(text + i, &prevCodepointSize);+                    i -= prevCodepointSize;+                    accCodepointSize += prevCodepointSize;+                } -                    // TODO Check: >= cursor+codepointsize and <= length-codepointsize+                // Move forward text from cursor position+                for (int j = (textBoxCursorIndex - accCodepointSize); j < textLength; j++) text[j] = text[j + accCodepointSize]; +                // Prevent cursor index from decrementing past 0+                if (textBoxCursorIndex > 0)+                {+                    textBoxCursorIndex -= accCodepointSize;+                    textLength -= accCodepointSize;+                }++                // Make sure text last character is EOL+                text[textLength] = '\0';+            } +            else if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))))+            {+                autoCursorDelayCounter++;++                if (IsKeyPressed(KEY_BACKSPACE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0)      // Delay every movement some frames+                {+                    int prevCodepointSize = 0;+                     // Prevent cursor index from decrementing past 0                     if (textBoxCursorIndex > 0)                     {+                        GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);++                        // Move backward text from cursor position+                        for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize];+                         textBoxCursorIndex -= codepointSize;                         textLength -= codepointSize;                     }@@ -2616,7 +2674,7 @@                 if (IsKeyPressed(KEY_LEFT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0)      // Delay every movement some frames                 {                     int prevCodepointSize = 0;-                    GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);+                    if (textBoxCursorIndex > 0) GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);                      if (textBoxCursorIndex >= prevCodepointSize) textBoxCursorIndex -= prevCodepointSize;                 }@@ -2903,7 +2961,7 @@             //if (*value > maxValue) *value = maxValue;             //else if (*value < minValue) *value = minValue; -            if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))+            if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))             {                 if (*value > maxValue) *value = maxValue;                 else if (*value < minValue) *value = minValue;@@ -3019,7 +3077,7 @@              if (valueHasChanged) *value = TextToFloat(textValue); -            if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1;+            if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1;         }         else         {@@ -3404,7 +3462,7 @@      // Draw control     //---------------------------------------------------------------------    GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));     // Draw background+    GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));     // Draw background      // Draw visible items     for (int i = 0; ((i < visibleItems) && (text != NULL)); i++)@@ -3859,7 +3917,7 @@     buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount;     buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; -    int textWidth = GetTextWidth(message) + 2;+    //int textWidth = GetTextWidth(message) + 2;      Rectangle textBounds = { 0 };     textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;@@ -4463,7 +4521,7 @@                 // NOTE: All DEFAULT properties should be defined first in the file                 GuiSetStyle(0, (int)propertyId, propertyValue); -                if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) GuiSetStyle(i, (int)propertyId, propertyValue);+                if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int j = 1; j < RAYGUI_MAX_CONTROLS; j++) GuiSetStyle(j, (int)propertyId, propertyValue);             }             else GuiSetStyle((int)controlId, (int)propertyId, propertyValue);         }
raygui/styles/amber/style_amber.h view
@@ -7,599 +7,596 @@ // more info and bugs-report:  github.com/raysan5/raygui                        // // feedback and support:       ray[at]raylibtech.com                            // //                                                                              //-// Copyright (c) 2020-2023 raylib technologies (@raylibtech)                    //-//                                                                              //-//////////////////////////////////////////////////////////////////////////////////--#define AMBER_STYLE_PROPS_COUNT  17--// Custom style name: Amber-static const GuiStyleProp amberStyleProps[AMBER_STYLE_PROPS_COUNT] = {-    { 0, 0, 0x898988ff },    // DEFAULT_BORDER_COLOR_NORMAL -    { 0, 1, 0x292929ff },    // DEFAULT_BASE_COLOR_NORMAL -    { 0, 2, 0xd4d4d4ff },    // DEFAULT_TEXT_COLOR_NORMAL -    { 0, 3, 0xf1850dff },    // DEFAULT_BORDER_COLOR_FOCUSED -    { 0, 4, 0x292929ff },    // DEFAULT_BASE_COLOR_FOCUSED -    { 0, 5, 0xffffffff },    // DEFAULT_TEXT_COLOR_FOCUSED -    { 0, 6, 0xf1850dff },    // DEFAULT_BORDER_COLOR_PRESSED -    { 0, 7, 0xf1850dff },    // DEFAULT_BASE_COLOR_PRESSED -    { 0, 8, 0xffffffff },    // DEFAULT_TEXT_COLOR_PRESSED -    { 0, 9, 0x6a6a6aff },    // DEFAULT_BORDER_COLOR_DISABLED -    { 0, 10, 0x818181ff },    // DEFAULT_BASE_COLOR_DISABLED -    { 0, 11, 0x606060ff },    // DEFAULT_TEXT_COLOR_DISABLED -    { 0, 16, 0x00000010 },    // DEFAULT_TEXT_SIZE -    { 0, 18, 0xf1850dff },    // DEFAULT_LINE_COLOR -    { 0, 19, 0x333333ff },    // DEFAULT_BACKGROUND_COLOR -    { 0, 20, 0x00000018 },    // DEFAULT_TEXT_LINE_SPACING -    { 10, 7, 0x202020ff },    // VALUEBOX_BASE_COLOR_PRESSED -};--// WARNING: This style uses a custom font: "Inter-Regular.ttf" (size: 16, spacing: 1)--#define AMBER_STYLE_FONT_ATLAS_COMP_SIZE 6417--// Font atlas image pixels data: DEFLATE compressed-static unsigned char amberFontData[AMBER_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,-    0x9d, 0x07, 0x78, 0x15, 0xc5, 0xda, 0xc7, 0x4f, 0x1a, 0x3d, 0x20, 0x4d, 0x10, 0x41, 0x45, 0xa5, 0x89, 0x8a, 0x7a, 0x45,-    0xb0, 0x60, 0x47, 0x51, 0xb0, 0xe3, 0xc5, 0x02, 0x36, 0x14, 0x95, 0x0b, 0x28, 0x88, 0x5c, 0xf1, 0x43, 0x6c, 0x20, 0xd2,-    0x14, 0x15, 0xb1, 0x80, 0xc1, 0x02, 0xd8, 0x50, 0x14, 0x51, 0x41, 0x91, 0x2e, 0x1d, 0x2e, 0xc5, 0x84, 0x2e, 0xed, 0x86,-    0x16, 0x02, 0x84, 0x10, 0x02, 0x21, 0xe4, 0xf7, 0x3d, 0x3b, 0x67, 0xcf, 0xc9, 0x81, 0xf3, 0xce, 0x9e, 0x9c, 0x18, 0x10,-    0xb8, 0x2f, 0xbf, 0xe7, 0x21, 0xc9, 0xce, 0xd6, 0xf9, 0xcf, 0xce, 0xcc, 0xee, 0xfe, 0xdf, 0x19, 0x7c, 0x8a, 0xa2, 0x28,-    0x8a, 0xa2, 0x28, 0x87, 0xf0, 0x1c, 0xf7, 0x84, 0x2d, 0x7b, 0x94, 0x07, 0x68, 0xca, 0x0b, 0xe2, 0xfa, 0x75, 0xe9, 0x62,-    0x7e, 0xf6, 0xe3, 0x24, 0xeb, 0x3e, 0x63, 0x48, 0xb0, 0xa4, 0xc4, 0xd2, 0x93, 0x71, 0xb4, 0x72, 0xff, 0x2a, 0xc1, 0x3b,-    0x54, 0xb0, 0xac, 0xd9, 0x84, 0x21, 0x0c, 0xe4, 0x74, 0x4b, 0xaa, 0x73, 0x86, 0xd2, 0xf2, 0x8b, 0x29, 0x19, 0xb6, 0xac,-    0x02, 0xe7, 0x58, 0xcf, 0xf4, 0x64, 0xba, 0x5b, 0xd3, 0xea, 0xf0, 0x1f, 0x6b, 0x5a, 0x23, 0x2e, 0x0f, 0x5b, 0x56, 0x86,-    0x11, 0x2e, 0xa7, 0x84, 0xa5, 0x75, 0xa0, 0x85, 0x65, 0x4f, 0xa5, 0x29, 0x21, 0x2e, 0xbf, 0x84, 0xf7, 0xf9, 0x8a, 0xb6,-    0xd6, 0x7c, 0x7c, 0x8a, 0x24, 0xce, 0x2c, 0x02, 0xfd, 0x27, 0xd1, 0x2f, 0x6c, 0xd9, 0x07, 0x0c, 0xe2, 0x71, 0xa6, 0x89,-    0xeb, 0xb7, 0x65, 0x08, 0x3e, 0x8a, 0x91, 0x41, 0xac, 0x75, 0x9f, 0xb5, 0xf8, 0xc4, 0x92, 0x72, 0x2f, 0x13, 0xb9, 0x90,-    0x54, 0x4e, 0x35, 0x7f, 0x0d, 0x10, 0x8e, 0x1d, 0x28, 0x65, 0x99, 0x74, 0x64, 0x28, 0x6b, 0x88, 0x11, 0xd3, 0x9d, 0x33,-    0x0c, 0x5f, 0x7a, 0x35, 0xa9, 0xc4, 0x87, 0x2d, 0x3d, 0x95, 0x3d, 0x54, 0x13, 0xd6, 0x2e, 0xce, 0xd3, 0xd4, 0xe4, 0x57,-    0x6a, 0xd2, 0x5a, 0x3c, 0xc6, 0xb9, 0xa4, 0x59, 0xaf, 0x70, 0x22, 0x3d, 0xc3, 0x96, 0x95, 0xa0, 0xa3, 0x4b, 0xf9, 0xb0,-    0xb4, 0x05, 0x0c, 0xb5, 0xec, 0x69, 0x2a, 0xb7, 0x8b, 0xe5, 0x2b, 0x8b, 0x89, 0xf4, 0x63, 0x3f, 0xbd, 0x85, 0xd4, 0xca,-    0x8c, 0x67, 0x11, 0x79, 0x34, 0x2a, 0x02, 0xfd, 0x7f, 0xa5, 0x4f, 0xd8, 0xb2, 0x37, 0x79, 0x8d, 0x36, 0x8c, 0x17, 0xd7,-    0x1f, 0x40, 0x07, 0x93, 0x37, 0x0b, 0xad, 0x7b, 0x6c, 0xca, 0xe7, 0x6c, 0xe0, 0x15, 0xf1, 0xde, 0x7d, 0xc9, 0xd4, 0x2a,-    0x93, 0x69, 0x82, 0x8f, 0xab, 0x58, 0x44, 0x71, 0xcb, 0x3e, 0xfe, 0xcd, 0x38, 0x7c, 0x54, 0x23, 0xcf, 0x52, 0x3f, 0x38,-    0x67, 0x18, 0xbe, 0xf4, 0x07, 0x5e, 0x16, 0xd7, 0xfe, 0x56, 0x5c, 0x3b, 0x91, 0xfe, 0x2c, 0x61, 0x33, 0x0b, 0x69, 0x19,-    0x96, 0xd6, 0x90, 0x66, 0x3c, 0xce, 0x2e, 0x9a, 0xd1, 0x8c, 0xb3, 0x84, 0x6d, 0x37, 0xd2, 0x38, 0xaa, 0x5c, 0x8e, 0xb7,-    0x94, 0xe3, 0x32, 0xec, 0xa5, 0x9c, 0xb0, 0x7c, 0x20, 0xef, 0x99, 0x2d, 0xae, 0xe2, 0xbf, 0x42, 0xea, 0xc3, 0x0c, 0xa1,-    0x04, 0x07, 0x8b, 0x44, 0xff, 0xf1, 0xf4, 0x0a, 0x5b, 0xd6, 0x9b, 0x1e, 0xb4, 0xe4, 0xdb, 0xb0, 0xe5, 0x67, 0x90, 0x4d,-    0x2e, 0xfb, 0xc9, 0x66, 0x3f, 0x07, 0xc9, 0x16, 0xca, 0xb9, 0x8f, 0x27, 0x49, 0x67, 0x18, 0xb3, 0xf9, 0x8e, 0x2d, 0x42,-    0xfd, 0xd4, 0x9c, 0xf9, 0xb4, 0x62, 0x13, 0x15, 0x48, 0x64, 0x05, 0x17, 0x58, 0xcf, 0xea, 0x5a, 0x76, 0x70, 0x36, 0xdf,-    0x58, 0xca, 0xa0, 0xff, 0x0c, 0x0f, 0x5f, 0x56, 0x8a, 0x7d, 0x34, 0x10, 0xd7, 0x6e, 0x4d, 0xb2, 0xb0, 0x34, 0x8e, 0xd6,-    0x2c, 0x25, 0x93, 0xef, 0x39, 0x4f, 0xc8, 0xff, 0x49, 0xcc, 0x21, 0x87, 0x49, 0x4c, 0xa2, 0x8d, 0x50, 0x72, 0xd2, 0x89,-    0x2b, 0x92, 0xd6, 0xb7, 0x39, 0x33, 0xc5, 0xe5, 0xf3, 0xb8, 0xcd, 0x3d, 0xc7, 0x3d, 0x9c, 0x2d, 0x5c, 0xa9, 0xf3, 0x7f,-    0xd1, 0xe8, 0xff, 0x23, 0x2f, 0x85, 0x2d, 0x4b, 0x20, 0x81, 0x38, 0xe1, 0xde, 0x8c, 0x21, 0x9e, 0xf5, 0x54, 0x27, 0x9e,-    0x57, 0xe8, 0x21, 0xd4, 0xb4, 0x0e, 0x2b, 0x78, 0xd4, 0xad, 0xff, 0xbf, 0xe0, 0x61, 0x51, 0x8b, 0x41, 0xa6, 0xed, 0x1c,-    0xc6, 0xf3, 0x9e, 0xe7, 0xf5, 0x2d, 0x39, 0x4c, 0xa0, 0xac, 0x25, 0x35, 0x41, 0xe8, 0x61, 0xdc, 0x48, 0x9a, 0xa5, 0x4d,-    0x3a, 0x95, 0x3c, 0xa1, 0x05, 0xa8, 0xc0, 0x50, 0x2e, 0xe0, 0x17, 0xae, 0xb5, 0xd4, 0x1a, 0xf6, 0xfa, 0xbf, 0x0c, 0x57,-    0x16, 0x51, 0xef, 0x6b, 0x90, 0x78, 0xec, 0xb2, 0xe4, 0x52, 0xdd, 0xfd, 0x7d, 0x06, 0x8f, 0x58, 0xb6, 0x2d, 0x1a, 0xfd,-    0xc7, 0x5a, 0xfa, 0x79, 0xb6, 0x2b, 0x4f, 0x37, 0x3f, 0xbf, 0xe2, 0x0e, 0x6b, 0x7b, 0xd6, 0xc3, 0xa3, 0xfd, 0x0f, 0x70,-    0x0b, 0x33, 0x89, 0x23, 0x96, 0x3a, 0x96, 0x16, 0xe0, 0x16, 0x32, 0x58, 0xcb, 0x87, 0xf8, 0x38, 0x85, 0xf3, 0x0b, 0x78,-    0x6e, 0x4f, 0xf3, 0x9b, 0x35, 0x6d, 0x1b, 0xd7, 0x59, 0x4a, 0xc6, 0x87, 0xd6, 0x6d, 0xbc, 0xda, 0xff, 0xa2, 0x22, 0xd9,-    0xb4, 0x84, 0x87, 0x53, 0x93, 0x3c, 0x4a, 0x07, 0xf5, 0x79, 0xee, 0x88, 0xea, 0x3f, 0x9c, 0xa7, 0x0a, 0xbc, 0x6e, 0x7b,-    0xbe, 0x65, 0x07, 0xc3, 0x19, 0xce, 0x36, 0xc6, 0x72, 0xb7, 0xb8, 0xce, 0x75, 0x6c, 0x65, 0x3e, 0x53, 0xac, 0x3d, 0x77,-    0x87, 0x4a, 0xac, 0xa1, 0x16, 0x09, 0xcc, 0x60, 0x12, 0x6b, 0x85, 0x35, 0xab, 0xb0, 0x87, 0x7b, 0xa9, 0xce, 0x26, 0x3a,-    0xf2, 0x1c, 0x1f, 0x17, 0xf0, 0xec, 0xfa, 0x32, 0xd2, 0x9a, 0xb6, 0xc4, 0xd2, 0xc7, 0xf3, 0xa2, 0x1c, 0x77, 0x1d, 0x61,-    0xf5, 0x4f, 0x65, 0xb7, 0xe5, 0x49, 0xe9, 0xbf, 0xc1, 0xe7, 0x8b, 0x8d, 0x62, 0x09, 0x29, 0x3a, 0xfd, 0xa3, 0xe1, 0x5a,-    0x86, 0x32, 0x9e, 0x7b, 0x68, 0x43, 0x36, 0xf7, 0x50, 0xd7, 0x5a, 0x47, 0xbc, 0xcc, 0x6e, 0x0e, 0xf0, 0x99, 0xb5, 0x77,-    0x37, 0x9a, 0x7f, 0x99, 0x27, 0x9c, 0x39, 0xf8, 0x78, 0x83, 0xce, 0x61, 0xe9, 0xd7, 0xb3, 0xdb, 0xd4, 0xe4, 0x97, 0xb0,-    0x9b, 0xf5, 0x3c, 0x5e, 0xc0, 0xb3, 0xeb, 0xc3, 0x28, 0x6b, 0xda, 0x52, 0xee, 0x3b, 0x06, 0x9f, 0xbd, 0x1f, 0x64, 0xac,-    0x25, 0x65, 0x94, 0x7b, 0x57, 0x56, 0x25, 0xdb, 0x9a, 0x8b, 0x45, 0xa3, 0x7f, 0x7b, 0x9a, 0x47, 0xb1, 0xf6, 0xeb, 0x3c,-    0x8d, 0x8f, 0x7a, 0x2c, 0xf1, 0x5c, 0xcb, 0xa9, 0xff, 0xcf, 0x24, 0x99, 0x17, 0x2d, 0xbd, 0xb1, 0x09, 0xa6, 0x6f, 0xdb,-    0x90, 0xb9, 0xa6, 0x05, 0xec, 0x14, 0xb6, 0xc6, 0x49, 0xec, 0xa3, 0x1d, 0x09, 0x34, 0x66, 0x1e, 0x50, 0xbf, 0x80, 0xe7,-    0xf6, 0x08, 0xf3, 0xac, 0x4f, 0xcb, 0x7b, 0xb9, 0xf8, 0x18, 0xd4, 0x7f, 0x84, 0x70, 0xed, 0x7e, 0xda, 0xb1, 0x95, 0xd6,-    0x9c, 0xcb, 0x74, 0x8f, 0x36, 0xad, 0x68, 0xf4, 0xb7, 0x3f, 0x99, 0xca, 0xbd, 0x85, 0x1b, 0xf1, 0x71, 0x17, 0x5f, 0x58,-    0xd2, 0xcb, 0xd3, 0x8b, 0x8a, 0x6e, 0xfb, 0x3f, 0x98, 0xaf, 0x84, 0x35, 0xaa, 0xf3, 0xa7, 0xdb, 0xb7, 0x49, 0x60, 0x0a,-    0xb3, 0x59, 0xe3, 0xbe, 0x0b, 0x38, 0xbc, 0x06, 0x58, 0x45, 0x16, 0x39, 0x8c, 0xe4, 0x0d, 0x52, 0xc4, 0x27, 0x24, 0xe9,-    0x8d, 0x91, 0xed, 0x9d, 0xc4, 0x99, 0x60, 0xed, 0x49, 0xfe, 0x7d, 0xc4, 0xb0, 0x99, 0x7a, 0x96, 0xb4, 0x38, 0x06, 0x91,-    0x45, 0x2e, 0x33, 0x83, 0xfd, 0xc0, 0x23, 0xa5, 0xbf, 0xed, 0xc9, 0xb4, 0xb0, 0x4c, 0x67, 0x04, 0x4d, 0xf8, 0x8c, 0xe6,-    0xec, 0xa2, 0x5d, 0xc4, 0xb5, 0x4f, 0xb7, 0x3c, 0x45, 0xf8, 0xcb, 0x52, 0xb1, 0xa8, 0x8e, 0x5c, 0x9c, 0xcd, 0xdc, 0x64,-    0x79, 0xc7, 0x39, 0xe5, 0x18, 0xbc, 0xfb, 0xcf, 0x67, 0xa3, 0x67, 0x7a, 0xc2, 0x31, 0x58, 0x66, 0x23, 0x73, 0x1e, 0x5f,-    0x90, 0x45, 0x1e, 0xdb, 0x78, 0xa9, 0x88, 0x4b, 0x56, 0x64, 0x7a, 0x0a, 0xef, 0x2c, 0x9c, 0xfb, 0x6c, 0x95, 0xf5, 0x69,-    0xe5, 0xef, 0xa4, 0x0b, 0xc3, 0x4f, 0xd0, 0x6f, 0x0a, 0xe7, 0xf1, 0xb5, 0xc7, 0xdb, 0xe1, 0x23, 0xc7, 0xc9, 0xcc, 0x24,-    0x51, 0x38, 0x9b, 0x5f, 0x8a, 0xe8, 0x6d, 0x4d, 0xd1, 0x72, 0x13, 0x17, 0x9e, 0xa0, 0xfa, 0x97, 0xe3, 0x1a, 0xfd, 0xb2,-    0xa6, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0x72, 0x54, 0xb9, 0x8d, 0x8f,-    0xf9, 0xd4, 0xc3, 0xd7, 0x72, 0x2b, 0x1f, 0xf1, 0x25, 0x8f, 0x79, 0x7e, 0xb9, 0xa9, 0x49, 0x92, 0xe8, 0x19, 0x68, 0x40,-    0x92, 0x4b, 0x4f, 0xcb, 0x96, 0xb5, 0x79, 0x83, 0x31, 0x3c, 0x27, 0x3a, 0xde, 0x2f, 0x0b, 0x6e, 0x9d, 0x24, 0x38, 0x92,-    0xfd, 0x9e, 0xb0, 0x24, 0x3e, 0xe7, 0x11, 0xeb, 0xb9, 0xb5, 0x34, 0xe7, 0xde, 0x52, 0x4c, 0xfb, 0x84, 0x6e, 0xc2, 0xd2,-    0xee, 0x24, 0x79, 0x7e, 0x7f, 0x2b, 0x2d, 0x38, 0x6f, 0x7f, 0x08, 0xd2, 0x50, 0x78, 0xef, 0xed, 0x9d, 0xfb, 0x67, 0x31,-    0x88, 0x31, 0x74, 0xb7, 0x3a, 0x3a, 0x02, 0xfe, 0x99, 0xcb, 0x38, 0x2d, 0xe2, 0x17, 0x96, 0x24, 0x2e, 0x8b, 0x5a, 0xfd,-    0x27, 0xd8, 0xc2, 0x8b, 0xbc, 0xc0, 0x66, 0x3a, 0x8a, 0xe9, 0x9d, 0xd9, 0x4c, 0x67, 0x9e, 0xe1, 0x4f, 0xfa, 0x7b, 0x3a,-    0x86, 0x0f, 0x8a, 0x51, 0x13, 0x8f, 0xb1, 0x8a, 0x67, 0x0d, 0x6d, 0x2c, 0x9e, 0xfe, 0x6d, 0xcc, 0xa6, 0x33, 0x0b, 0x99,-    0x28, 0xa4, 0xd6, 0x77, 0xb7, 0x7d, 0x96, 0xc9, 0xc6, 0x17, 0x12, 0x9e, 0xf3, 0xdb, 0x79, 0xd9, 0x9c, 0x9b, 0x1c, 0x33,-    0xd0, 0x8d, 0x74, 0x9e, 0xa7, 0x1b, 0x9b, 0x44, 0xbf, 0xdc, 0x30, 0x37, 0x6a, 0xe5, 0x50, 0x9e, 0xe5, 0x03, 0xeb, 0x57,-    0xf1, 0x87, 0x58, 0x2d, 0x78, 0xbc, 0xff, 0xc1, 0x03, 0x41, 0xaa, 0x0b, 0xdf, 0x99, 0xa7, 0x72, 0xb5, 0xc7, 0xd7, 0xa9,-    0x34, 0x3e, 0xe6, 0x21, 0xe6, 0x32, 0xda, 0xea, 0x08, 0x78, 0x81, 0x85, 0xac, 0xe7, 0x07, 0x16, 0xb1, 0x99, 0x6e, 0x1e,-    0x5f, 0xad, 0xde, 0x61, 0x1d, 0x5f, 0x46, 0xad, 0xff, 0x62, 0xe3, 0xdd, 0x77, 0xdc, 0x25, 0x29, 0x16, 0xcf, 0xed, 0x0d,-    0xe6, 0xe7, 0xdd, 0xa4, 0x5b, 0xef, 0xb2, 0xfb, 0x49, 0xe6, 0x67, 0x51, 0xff, 0x5e, 0x1e, 0xfe, 0x3b, 0xff, 0x3d, 0xf8,-    0xbe, 0xd9, 0x6b, 0x55, 0x66, 0x0b, 0x9e, 0xe6, 0xfc, 0x28, 0x8a, 0x8d, 0xdc, 0x2f, 0xfa, 0x0a, 0x7a, 0xba, 0x77, 0xf9,-    0x76, 0xe1, 0xdc, 0xe2, 0xc9, 0x74, 0xbf, 0xfd, 0x37, 0x62, 0x8f, 0xe8, 0x4b, 0x2f, 0x38, 0x71, 0x3c, 0xc0, 0x2a, 0xfe,-    0xa0, 0xb5, 0x87, 0x37, 0x41, 0xe6, 0x24, 0xfe, 0x8f, 0x6d, 0x4c, 0xb6, 0xb8, 0x83, 0x9b, 0x31, 0xd1, 0xec, 0xb1, 0x11,-    0x39, 0x42, 0x94, 0x92, 0xa3, 0xfe, 0x3b, 0x4c, 0x0d, 0x46, 0x1b, 0x54, 0x66, 0x8c, 0xd5, 0x1d, 0x96, 0x40, 0x1a, 0x77,-    0xb0, 0xd7, 0x23, 0x02, 0xcb, 0xe6, 0x37, 0x2c, 0xe6, 0xe6, 0xe1, 0x4a, 0xcf, 0xf5, 0x9e, 0xb2, 0xfa, 0xbb, 0x2a, 0xb2,-    0x85, 0x2b, 0xf8, 0x5e, 0xd4, 0xff, 0x53, 0xfa, 0x50, 0x9f, 0x8b, 0x2d, 0xa5, 0x36, 0x8e, 0x6c, 0x5a, 0x50, 0x81, 0xc6,-    0x96, 0x78, 0xa7, 0x00, 0x1d, 0x59, 0x26, 0xee, 0xe1, 0x73, 0xde, 0x71, 0xe3, 0x0b, 0x16, 0x8b, 0x2d, 0x0b, 0xee, 0x97,-    0xdf, 0x58, 0xb2, 0xb9, 0xe2, 0x2f, 0xa8, 0x7f, 0x0f, 0x2b, 0x98, 0xcd, 0x6d, 0x96, 0xf2, 0xdf, 0x83, 0xd4, 0x20, 0xd7,-    0x8b, 0x6b, 0x94, 0xa2, 0x13, 0xeb, 0x99, 0xe8, 0xe1, 0x37, 0xbb, 0x97, 0xad, 0xe2, 0xde, 0xbb, 0x32, 0x8f, 0xb2, 0x24,-    0xd0, 0x94, 0x27, 0x39, 0x9b, 0xdb, 0x88, 0x65, 0xb6, 0x78, 0x27, 0x38, 0xad, 0xf4, 0x3a, 0x62, 0x58, 0xc8, 0x63, 0x85,-    0xba, 0xc2, 0x92, 0x2c, 0xe6, 0x19, 0x6b, 0xea, 0xa3, 0x8c, 0x64, 0x05, 0xd7, 0x5a, 0x52, 0x93, 0x78, 0x1f, 0x9f, 0x45,-    0xff, 0x29, 0xa4, 0xb1, 0x92, 0x6d, 0x6c, 0x15, 0xe3, 0x3a, 0x9c, 0x58, 0x9e, 0xde, 0x64, 0xf0, 0x27, 0x59, 0xd6, 0x58,-    0x38, 0xe7, 0xdc, 0x52, 0x2d, 0x4e, 0xcd, 0x3a, 0xcc, 0xe1, 0x5b, 0x86, 0xb3, 0x4c, 0xbc, 0xbb, 0xe2, 0xc9, 0x70, 0x23,-    0x26, 0x6e, 0x04, 0x4b, 0xfb, 0x53, 0x30, 0x26, 0xb3, 0x89, 0x5b, 0xac, 0xb5, 0x5f, 0x55, 0xce, 0x0d, 0x92, 0x68, 0xbd,-    0x86, 0xce, 0xe4, 0x08, 0x51, 0x15, 0x01, 0xf5, 0x77, 0xf3, 0x90, 0xe5, 0xc8, 0x4e, 0xa9, 0x1b, 0xc5, 0x34, 0xde, 0x67,-    0x0d, 0xbb, 0xf0, 0xd1, 0x42, 0x6c, 0x29, 0x1d, 0xf7, 0xfd, 0x00, 0xd3, 0xda, 0x4c, 0x2f, 0xc4, 0xf5, 0xc5, 0x32, 0x9a,-    0x09, 0x1e, 0x35, 0xdb, 0xab, 0xfc, 0xce, 0x2a, 0x8b, 0xb7, 0xfb, 0x1a, 0x52, 0x4d, 0x9d, 0x23, 0xeb, 0x5f, 0xcf, 0x38,-    0x35, 0x63, 0x79, 0x83, 0x75, 0x62, 0xef, 0x10, 0x26, 0x98, 0x7b, 0xbf, 0x35, 0xd9, 0xd6, 0xa8, 0xcf, 0xa7, 0x48, 0xb1,-    0xd4, 0x1f, 0xb7, 0xb0, 0x81, 0x29, 0x8c, 0x64, 0xbd, 0xdb, 0x86, 0x85, 0x6f, 0x99, 0x41, 0x7f, 0x06, 0x92, 0x4c, 0x6a,-    0x30, 0xbe, 0x34, 0x52, 0xfc, 0xa5, 0x14, 0xc5, 0x19, 0xcb, 0x3f, 0xf9, 0x83, 0x25, 0xdc, 0x17, 0x75, 0xed, 0xef, 0xef,-    0x01, 0x3e, 0xc7, 0x16, 0x7e, 0xe2, 0x12, 0x4b, 0xfa, 0xa5, 0xec, 0xa3, 0x99, 0xa5, 0xc7, 0xe1, 0x44, 0x29, 0x5e, 0xcc,-    0x12, 0x73, 0xdc, 0x3b, 0x8c, 0xfe, 0xa7, 0xb2, 0x4d, 0x6c, 0x65, 0xb2, 0x4d, 0xed, 0x72, 0x1a, 0x07, 0xc5, 0xd8, 0x34,-    0x6f, 0xde, 0x63, 0x71, 0x44, 0x5f, 0xd9, 0x55, 0xe4, 0x52, 0x55, 0x68, 0x99, 0x57, 0xd0, 0x86, 0x92, 0x94, 0xe4, 0x07,-    0x7a, 0x7a, 0xf4, 0x61, 0xcb, 0x73, 0x90, 0x5a, 0x42, 0xef, 0x87, 0x60, 0xbd, 0xbc, 0xd6, 0xbd, 0x57, 0xc3, 0xef, 0x9c,-    0xcd, 0x42, 0x34, 0xb2, 0xff, 0xd8, 0xbb, 0xdd, 0xda, 0xee, 0x5c, 0x72, 0x2d, 0xae, 0xc9, 0x1b, 0x79, 0xcb, 0xc4, 0x9e,-    0xec, 0x13, 0xea, 0x7f, 0xd9, 0xe5, 0x3a, 0xd1, 0xf2, 0xa4, 0x12, 0xcb, 0x3d, 0xa4, 0xb0, 0x9a, 0x9a, 0x51, 0xe6, 0xed,-    0xad, 0xec, 0x64, 0xbc, 0x67, 0x64, 0x60, 0x37, 0x7e, 0xb4, 0xa4, 0xd4, 0x33, 0x5a, 0x3f, 0xe2, 0x9e, 0x67, 0x35, 0x57,-    0xff, 0x4c, 0xb1, 0x86, 0xce, 0x63, 0x1a, 0x53, 0x99, 0xca, 0x3e, 0x6b, 0x2d, 0x63, 0xa3, 0x17, 0x2b, 0x05, 0x65, 0x03,-    0x51, 0x6d, 0x1d, 0xa9, 0xe8, 0xf6, 0x2f, 0x76, 0x09, 0xf7, 0xcb, 0xa5, 0x84, 0xfe, 0x9b, 0x25, 0x44, 0x06, 0x9f, 0xe5,-    0x2a, 0x9d, 0x27, 0x7a, 0x7a, 0x77, 0xb9, 0xbd, 0xcb, 0x18, 0xd2, 0x2c, 0xd1, 0x38, 0x5d, 0xf8, 0xc3, 0xe2, 0x1b, 0xab,-    0x05, 0xd4, 0x70, 0xef, 0x93, 0x74, 0xee, 0x0c, 0x4b, 0x2f, 0x46, 0x17, 0xaa, 0x04, 0x5d, 0xc0, 0x89, 0x05, 0x74, 0xb9,-    0x7a, 0x45, 0x71, 0xc6, 0x71, 0x9f, 0x50, 0x8a, 0xbd, 0x69, 0x16, 0xf1, 0x99, 0xac, 0xac, 0xb5, 0x6f, 0x5a, 0x89, 0xfd,-    0xc4, 0x73, 0x3d, 0x93, 0xdc, 0xb2, 0x9c, 0x61, 0x1c, 0xf2, 0x2b, 0xc4, 0x08, 0xab, 0xe1, 0xdc, 0x6e, 0x18, 0xc0, 0xea,-    0xa8, 0x3c, 0x96, 0x4f, 0x93, 0xc6, 0x3f, 0xa8, 0x64, 0x88, 0x15, 0xfa, 0x9f, 0x6b, 0x18, 0x45, 0x0d, 0xaa, 0xd0, 0x87,-    0x2c, 0xa1, 0x6f, 0x19, 0x47, 0x69, 0x97, 0x9f, 0x78, 0x51, 0xe8, 0xc1, 0x7e, 0xcd, 0x64, 0x6a, 0x52, 0x89, 0x51, 0xcc,-    0x16, 0x8f, 0xfe, 0x32, 0x8b, 0xa9, 0x45, 0x39, 0x06, 0x92, 0xea, 0x46, 0x30, 0x1e, 0xde, 0x73, 0xda, 0xc2, 0x3f, 0xad,-    0x4f, 0x46, 0xeb, 0xf9, 0x88, 0x1a, 0x54, 0xa4, 0x27, 0xfb, 0xa9, 0x24, 0x3e, 0x1f, 0x8c, 0xa6, 0x1a, 0x37, 0x93, 0xcc,-    0xc0, 0x02, 0xe6, 0x46, 0xd1, 0x45, 0x71, 0x46, 0xf3, 0xfe, 0xc5, 0xee, 0x89, 0xde, 0x4e, 0x5d, 0x4a, 0xb3, 0x82, 0x97,-    0x68, 0xc3, 0x34, 0x72, 0x68, 0xc1, 0x68, 0xde, 0x12, 0x62, 0x70, 0xf3, 0x82, 0xf5, 0x5f, 0x79, 0xb1, 0xae, 0xb3, 0xfb,-    0xcd, 0xf3, 0x42, 0xee, 0xdf, 0xd3, 0xc5, 0xbb, 0x6c, 0x06, 0x39, 0x1c, 0x60, 0xb1, 0xb5, 0xfd, 0x0a, 0x44, 0x01, 0x74,-    0x17, 0x9f, 0x0d, 0xc6, 0x99, 0xd8, 0xe0, 0x5f, 0xa8, 0x6c, 0xa9, 0xdd, 0xdf, 0x27, 0x87, 0xfd, 0xcc, 0xb1, 0xd4, 0xdf,-    0x5d, 0x59, 0xea, 0x39, 0xa6, 0xc0, 0xef, 0xe4, 0x90, 0x43, 0xb2, 0xe5, 0x8a, 0x4f, 0x65, 0x1a, 0x07, 0xd8, 0xcb, 0x87,-    0xd6, 0xb1, 0x27, 0x8e, 0x5c, 0x14, 0x67, 0xc1, 0xf9, 0xd4, 0x12, 0xef, 0xeb, 0x1f, 0xd3, 0xe0, 0x13, 0x73, 0x9d, 0x83,-    0xf8, 0x92, 0xab, 0x78, 0x84, 0xa9, 0x0c, 0x11, 0x5a, 0xea, 0xff, 0x3b, 0x64, 0x54, 0x8a, 0x6f, 0x3d, 0xe2, 0x17, 0x0b,-    0x47, 0x09, 0x6b, 0xbf, 0xb6, 0x60, 0x5b, 0x97, 0x8a, 0xe0, 0xd1, 0x4f, 0x3c, 0x82, 0xe7, 0x96, 0x18, 0x65, 0xc4, 0xc0,-    0xdf, 0x11, 0xf3, 0x61, 0xaf, 0x71, 0x2a, 0xb0, 0x95, 0x67, 0x8e, 0x49, 0xa7, 0xb2, 0x72, 0x74, 0xa8, 0xc5, 0xaf, 0x2c,-    0x65, 0x30, 0x4f, 0xf1, 0x2c, 0x5f, 0x58, 0x9e, 0xc1, 0x94, 0x13, 0x9b, 0x7f, 0xd0, 0x9a, 0x97, 0x79, 0x81, 0x3b, 0x8e,-    0xcb, 0xe8, 0x1f, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0xe5, 0xe8,-    0xd3, 0xdb, 0x78, 0xeb, 0x3f, 0xa0, 0xa3, 0xe8, 0xce, 0xf0, 0x7f, 0xa1, 0xbd, 0x8b, 0x0f, 0xf8, 0x9c, 0xa7, 0xc4, 0xaf,-    0x78, 0xfe, 0xed, 0xdf, 0xa4, 0xa5, 0xeb, 0xb4, 0x90, 0xd3, 0xfd, 0xc4, 0x7b, 0xa4, 0x0e, 0xb5, 0xf8, 0x26, 0xef, 0x66,-    0x28, 0x23, 0xe8, 0x20, 0x7a, 0x63, 0x9d, 0xed, 0xaf, 0x0c, 0xf1, 0xd0, 0x3d, 0xe9, 0x99, 0x2e, 0x6d, 0xdd, 0xc4, 0x63,-    0x8b, 0x26, 0x24, 0x09, 0x8e, 0x64, 0xaf, 0x3d, 0xf6, 0x66, 0x68, 0x88, 0x03, 0xaa, 0x2c, 0x49, 0xc2, 0x78, 0xd4, 0xbd,-    0x43, 0xdc, 0x39, 0xd7, 0x59, 0xc6, 0x42, 0x74, 0x72, 0xfc, 0x7d, 0x3e, 0xe6, 0x7e, 0x4b, 0xec, 0x80, 0x3f, 0xd7, 0x86,-    0xd0, 0xd6, 0xea, 0xda, 0x89, 0xb4, 0x87, 0x7c, 0x52, 0x18, 0x4d, 0x37, 0x5e, 0xe4, 0x77, 0x36, 0x8a, 0x25, 0x20, 0x9e,-    0x71, 0xac, 0xa6, 0x1f, 0xdd, 0x59, 0xc0, 0x22, 0x61, 0x0e, 0x03, 0xff, 0xf6, 0x43, 0xd8, 0x49, 0x96, 0xf8, 0x0d, 0xde,-    0x9f, 0xee, 0x27, 0xce, 0x23, 0xb5, 0xab, 0xe8, 0x68, 0x1e, 0xcf, 0x2a, 0xfa, 0xd2, 0x97, 0xd5, 0x2c, 0x10, 0x8e, 0xed,-    0x6c, 0x9f, 0x3f, 0x17, 0xc2, 0x9b, 0xc2, 0xc8, 0x82, 0x29, 0xd6, 0xb9, 0x12, 0xfc, 0xa9, 0x8f, 0x58, 0xb7, 0xb8, 0x90,-    0x5d, 0x62, 0x74, 0x88, 0xd7, 0x1e, 0x53, 0xc8, 0x0d, 0x71, 0x19, 0xb6, 0xe3, 0x80, 0xe0, 0x79, 0x49, 0x21, 0x2f, 0xe8,-    0x54, 0xea, 0xc8, 0x7c, 0x31, 0xc7, 0x7f, 0x60, 0x35, 0xfd, 0x79, 0x85, 0xa5, 0xcc, 0x11, 0xa2, 0x4d, 0x9c, 0x7d, 0x7c,-    0xc5, 0xb3, 0xf4, 0x66, 0x19, 0x6b, 0xc5, 0x98, 0x90, 0xc8, 0x7b, 0x08, 0xbf, 0x9e, 0x18, 0x92, 0xcd, 0xf8, 0xab, 0x87,-    0xd3, 0x9f, 0xe5, 0xae, 0x2f, 0x33, 0x81, 0x49, 0xc6, 0x61, 0x2a, 0x6f, 0x5f, 0x92, 0xae, 0xec, 0x14, 0xbc, 0x71, 0x91,-    0x14, 0xf0, 0x4a, 0x1d, 0xc8, 0x32, 0xd7, 0x19, 0x55, 0x8a, 0x95, 0xbc, 0x7d, 0x14, 0xf5, 0xaf, 0xcd, 0x56, 0x4b, 0xbc,-    0x91, 0xb7, 0xfe, 0x93, 0xf9, 0x35, 0xf8, 0xd7, 0x6c, 0x26, 0x8b, 0xfa, 0x7f, 0x49, 0xaa, 0x7b, 0x57, 0xca, 0xfa, 0xf7,-    0x0d, 0xe6, 0x78, 0x09, 0x66, 0x8a, 0xa3, 0xd7, 0xe6, 0x9f, 0xc3, 0x42, 0x71, 0x26, 0x88, 0xc8, 0x7b, 0x08, 0xdf, 0x57,-    0x3c, 0x6b, 0x79, 0x42, 0x48, 0x0f, 0x1d, 0x25, 0xaf, 0xae, 0xe0, 0xc3, 0xcc, 0x3f, 0x97, 0x04, 0x76, 0x08, 0x7b, 0xf8,-    0x2b, 0xfa, 0xaf, 0x0e, 0x39, 0x76, 0x7d, 0xee, 0x3d, 0x6a, 0xfa, 0x57, 0x63, 0x9d, 0x1b, 0x95, 0x12, 0xad, 0xfe, 0x9d,-    0xc8, 0x75, 0xef, 0x81, 0xfa, 0x64, 0xd1, 0x4d, 0xd4, 0xbf, 0x0d, 0xd3, 0x79, 0xcf, 0x43, 0xff, 0x95, 0x21, 0x57, 0x7d,-    0x09, 0x99, 0x62, 0xad, 0x19, 0x38, 0x87, 0xb7, 0xf9, 0xa6, 0x50, 0x7b, 0x08, 0xdd, 0xd7, 0x27, 0x3c, 0xc6, 0xd3, 0x4c,-    0x61, 0xb4, 0xd0, 0xbe, 0x57, 0x20, 0x2f, 0x42, 0xd4, 0x59, 0x68, 0x7e, 0x8c, 0xe0, 0x23, 0xcb, 0xfe, 0x1d, 0x9a, 0x89,-    0x5b, 0xf7, 0xe5, 0x4a, 0x43, 0xcd, 0x42, 0x1c, 0xdb, 0xd9, 0xfe, 0xeb, 0x60, 0xeb, 0x32, 0xbd, 0x88, 0xf4, 0xef, 0xc8,-    0x22, 0x0f, 0xcf, 0x99, 0xb7, 0xfe, 0x2d, 0x99, 0xc4, 0xab, 0x6e, 0xdd, 0x35, 0x8a, 0x0e, 0xa2, 0xfe, 0x8f, 0x72, 0xbe,-    0xeb, 0xd0, 0x93, 0xf4, 0x3f, 0xf4, 0xaa, 0x8b, 0x93, 0x23, 0xcc, 0x43, 0x11, 0x38, 0x87, 0x04, 0x96, 0x09, 0x5e, 0xe5,-    0x82, 0xec, 0x21, 0x74, 0x5f, 0x33, 0xf9, 0x94, 0x11, 0x2c, 0x65, 0x9a, 0x10, 0xbb, 0x76, 0x76, 0x30, 0x82, 0xa6, 0x20,-    0xfa, 0xf7, 0x17, 0x46, 0xda, 0x4c, 0x61, 0x21, 0x63, 0x0c, 0x3d, 0xc4, 0xad, 0x37, 0xb1, 0xcc, 0xd0, 0xd5, 0xe3, 0xd8,-    0xfd, 0x49, 0x36, 0x94, 0x10, 0xb6, 0x9f, 0x61, 0x46, 0x9e, 0x77, 0x48, 0x2e, 0x22, 0xfd, 0xd3, 0xf8, 0x89, 0xbd, 0xdc,-    0x5a, 0x48, 0xfd, 0xef, 0x65, 0x23, 0x71, 0x14, 0x33, 0x73, 0x0b, 0xc8, 0xfa, 0x3b, 0x8e, 0xf5, 0xd7, 0x48, 0xa1, 0xb8,-    0xa8, 0xff, 0xa1, 0x39, 0x1e, 0xc3, 0x4e, 0x21, 0x76, 0x30, 0x85, 0x5f, 0x78, 0x83, 0x24, 0xd2, 0x58, 0xec, 0x7a, 0xb3,-    0xbd, 0x34, 0x4b, 0xb7, 0xc6, 0xed, 0x1c, 0xda, 0xfe, 0x8f, 0xe0, 0x6b, 0xc1, 0x99, 0xb6, 0x33, 0xa4, 0x8f, 0x1c, 0x2b,-    0xf8, 0xfb, 0x43, 0xf3, 0x63, 0x85, 0x30, 0x7b, 0x47, 0xe1, 0xeb, 0xff, 0xfc, 0x63, 0xd7, 0xe1, 0x0a, 0x3a, 0x45, 0xa8,-    0x09, 0x0b, 0x5e, 0xff, 0x57, 0x0d, 0xc6, 0x77, 0xc8, 0xfa, 0x8f, 0x23, 0x81, 0x0e, 0xa4, 0x89, 0xfd, 0xcd, 0xc8, 0xfa,-    0x17, 0x67, 0x3b, 0x37, 0x71, 0x87, 0x99, 0xa3, 0xca, 0xae, 0x7f, 0x09, 0x56, 0xd2, 0x93, 0x0e, 0x82, 0xfe, 0x31, 0xec,-    0x08, 0xc9, 0xf1, 0x9a, 0x1c, 0x14, 0x1c, 0x3f, 0xce, 0x39, 0x3a, 0x73, 0xdd, 0xdc, 0x44, 0x19, 0x31, 0xdf, 0xfc, 0x7b,-    0x88, 0x31, 0x75, 0xd8, 0x29, 0x20, 0x3a, 0xa3, 0xc3, 0xaf, 0xe7, 0x21, 0x31, 0xfe, 0x73, 0x7c, 0xc8, 0x93, 0x59, 0x7f,-    0x21, 0x4e, 0x21, 0x7f, 0xfb, 0x73, 0x41, 0x2c, 0xab, 0x85, 0x6f, 0xff, 0x27, 0x84, 0xb4, 0x27, 0xaf, 0x32, 0xa1, 0x88,-    0xda, 0xff, 0xab, 0xc8, 0x30, 0x8e, 0xd0, 0x38, 0xd2, 0xcc, 0xb8, 0xe5, 0xd2, 0x16, 0x31, 0xfc, 0xe8, 0x8e, 0x47, 0x1f,-    0xad, 0xfe, 0xce, 0xdc, 0x05, 0x9f, 0xf0, 0x85, 0xb9, 0x13, 0xec, 0xfa, 0x3b, 0x51, 0x53, 0x59, 0xf4, 0x12, 0xdb, 0xff,-    0x9f, 0x19, 0x16, 0xfc, 0xfd, 0x25, 0x96, 0x46, 0x9d, 0x6b, 0x81, 0x3d, 0x54, 0x60, 0x1d, 0x2d, 0xe9, 0xc9, 0xb2, 0x08,-    0xf5, 0xf7, 0xd3, 0x9c, 0x4c, 0x35, 0x6e, 0x67, 0x89, 0x18, 0xf7, 0x5c, 0x9b, 0x34, 0x06, 0x50, 0x8f, 0xaa, 0x74, 0x61,-    0x8f, 0x30, 0x82, 0xab, 0x7f, 0xfb, 0x2b, 0x19, 0x4e, 0xa6, 0xd8, 0x17, 0xf5, 0xa7, 0xfb, 0x89, 0x8d, 0xf2, 0x4a, 0x9c,-    0x63, 0xbf, 0xc9, 0xb9, 0x9c, 0x4a, 0x27, 0xf6, 0x8a, 0xb1, 0x5a, 0x85, 0xd1, 0x3f, 0x96, 0x75, 0x74, 0x35, 0x71, 0x2d,-    0x9b, 0x84, 0x37, 0x12, 0x81, 0x2d, 0xaa, 0xb0, 0x55, 0x8c, 0x0e, 0xcf, 0xbf, 0x9e, 0x0a, 0x16, 0xfd, 0xeb, 0xb1, 0x9d,-    0x1d, 0x66, 0x66, 0x21, 0x2f, 0xfd, 0x7d, 0x7c, 0xc4, 0x76, 0x51, 0xff, 0x5a, 0x6c, 0xe3, 0x0d, 0xce, 0xa1, 0x26, 0xdd,-    0xc9, 0x14, 0x47, 0x73, 0x8f, 0xa4, 0x7f, 0x60, 0x0f, 0x2d, 0xc8, 0x20, 0x2b, 0xc2, 0x9c, 0x64, 0x29, 0xc6, 0xf7, 0x7f,-    0x90, 0x15, 0xbc, 0x67, 0x79, 0xc7, 0xd2, 0x90, 0x1f, 0xd9, 0x43, 0x2e, 0x8b, 0xc5, 0x28, 0x76, 0xff, 0xf6, 0xdb, 0xf8,-    0x4e, 0x7c, 0x7a, 0x08, 0xa4, 0xfb, 0xff, 0x55, 0x8e, 0xfa, 0x4a, 0x2e, 0x61, 0x9c, 0x99, 0x35, 0x64, 0x3e, 0xb7, 0x44,-    0xac, 0x3f, 0x0a, 0xde, 0xff, 0x6f, 0x6e, 0xa2, 0x02, 0x7e, 0x17, 0xe3, 0xcd, 0xf2, 0xb7, 0x68, 0x4e, 0xb6, 0x10, 0xb3,-    0x9a, 0x7f, 0x3d, 0xcb, 0x2c, 0xfa, 0xfb, 0x98, 0xe6, 0xc6, 0x68, 0x7b, 0xeb, 0x5f, 0x9e, 0x2d, 0xa2, 0xfe, 0xce, 0x7c,-    0x95, 0xe3, 0xc8, 0x64, 0x1f, 0xbf, 0xb9, 0xb1, 0x51, 0xd1, 0xe6, 0x5a, 0x60, 0x0f, 0x07, 0x59, 0xc7, 0x8a, 0x08, 0xe3,-    0x4a, 0x14, 0x8c, 0x62, 0x62, 0x4b, 0x73, 0x74, 0x48, 0x38, 0x22, 0xc7, 0x2e, 0x73, 0x8c, 0xbf, 0x97, 0x2d, 0x16, 0x21,-    0x66, 0xa2, 0x20, 0x7b, 0x48, 0x24, 0x86, 0x2f, 0xa2, 0x9a, 0xc9, 0x4b, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14,-    0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x39, 0x31, 0xfc, 0xff, 0x43, 0x68, 0x67, 0xf5, 0xff, 0x3b,-    0xf3, 0xae, 0xbf, 0xcb, 0xf7, 0xbc, 0x2a, 0xce, 0x3a, 0x1e, 0x3a, 0x42, 0xbf, 0x13, 0x07, 0xe0, 0xe5, 0x97, 0x6f, 0x25,-    0x38, 0x8c, 0x5b, 0xf1, 0x6c, 0xc8, 0x5f, 0x6d, 0x85, 0x35, 0x5a, 0xd3, 0xde, 0xfd, 0xed, 0x1c, 0x92, 0x38, 0xdf, 0xfd,-    0xfd, 0x71, 0x61, 0xbc, 0xdc, 0x33, 0x48, 0xe2, 0x4c, 0xf7, 0xf7, 0x93, 0xf9, 0x88, 0xba, 0xc2, 0x97, 0xdf, 0xb7, 0x83,-    0xdf, 0xfc, 0x13, 0x18, 0x2c, 0xf8, 0x3f, 0xce, 0x3c, 0xe4, 0x7a, 0xc2, 0x67, 0x34, 0xa8, 0x41, 0x43, 0x1a, 0x0a, 0x4e,-    0x86, 0x44, 0xeb, 0x77, 0xd6, 0xd2, 0x66, 0x8b, 0x8a, 0x62, 0xda, 0x85, 0x96, 0x31, 0x2f, 0x43, 0xff, 0x49, 0x23, 0x63,-    0x97, 0xb3, 0x8e, 0x43, 0x5b, 0x8d, 0xa6, 0xe2, 0x48, 0xcb, 0xf6, 0xef, 0xff, 0x8e, 0x97, 0xbc, 0x17, 0x0b, 0x49, 0xb5,-    0x8c, 0xbf, 0xde, 0x8e, 0xed, 0xbc, 0x45, 0x7b, 0x7e, 0x60, 0x8b, 0xe0, 0xd2, 0xac, 0x6f, 0xbc, 0x97, 0x23, 0x8d, 0x5b,-    0xbe, 0x9b, 0xa0, 0x5e, 0xe8, 0xb7, 0xea, 0x01, 0x82, 0x5b, 0xf5, 0x6a, 0xb2, 0x83, 0x31, 0x0a, 0xb1, 0xa4, 0xf2, 0xb0,-    0xa0, 0x7f, 0x60, 0xe4, 0xe0, 0xe7, 0xc9, 0xe5, 0xe5, 0xa0, 0x2f, 0x59, 0xfa, 0x06, 0x3e, 0x92, 0xa9, 0xae, 0x36, 0xdf,-    0xf3, 0x9d, 0x90, 0x7e, 0x92, 0x99, 0xcb, 0xc0, 0xff, 0xfb, 0xb3, 0x6c, 0x14, 0xbc, 0x8d, 0xa7, 0x04, 0xfd, 0xa4, 0xaf,-    0x91, 0xc7, 0xcd, 0x61, 0xe9, 0xfd, 0xd8, 0xcc, 0x2c, 0x61, 0x44, 0xb9, 0x01, 0xa2, 0xfb, 0xc5, 0x67, 0xfc, 0x20, 0xb3,-    0xc8, 0x10, 0x47, 0x9f, 0x2e, 0xce, 0x06, 0xd2, 0x85, 0x52, 0xea, 0x78, 0x77, 0xf2, 0x91, 0x5c, 0x48, 0x5f, 0xf2, 0xba,-    0x78, 0xac, 0x1e, 0x64, 0x33, 0x9f, 0x5d, 0x8c, 0x2f, 0xf0, 0x98, 0x77, 0xf9, 0xfa, 0xcc, 0xa1, 0xaf, 0x65, 0x8d, 0x7f,-    0xb9, 0xea, 0x8c, 0xb6, 0x8c, 0x51, 0xed, 0xe3, 0x9f, 0x6c, 0x28, 0x80, 0xc3, 0x4b, 0xd2, 0xdf, 0x71, 0xe3, 0x04, 0x5c,-    0x78, 0x8e, 0x27, 0x2a, 0xdc, 0xed, 0x56, 0x85, 0x3c, 0x77, 0x0c, 0xd9, 0xdf, 0xf8, 0x91, 0x19, 0xe6, 0xb7, 0xd3, 0x82,-    0x23, 0xbf, 0x1e, 0x4a, 0x79, 0x36, 0x1a, 0x7d, 0x1f, 0x61, 0x0b, 0x27, 0x8b, 0xe7, 0x73, 0x0f, 0xbb, 0x4d, 0x4d, 0x77,-    0x1a, 0x7b, 0x22, 0xcc, 0xff, 0xfe, 0x1d, 0x9f, 0x09, 0x4b, 0xfb, 0x09, 0xa3, 0x6f, 0xfa, 0xcc, 0xd8, 0xac, 0x73, 0x3d,-    0xf6, 0x35, 0x49, 0xd4, 0xff, 0x31, 0x7e, 0xa4, 0x3b, 0x1f, 0x17, 0xa2, 0xd6, 0x3e, 0x99, 0xc9, 0x42, 0xbd, 0x50, 0x8a,-    0xe1, 0xe6, 0xde, 0x2f, 0x43, 0x86, 0xc7, 0x8c, 0x13, 0x36, 0x7d, 0xde, 0x15, 0xfc, 0x33, 0x3e, 0x33, 0xb2, 0x6c, 0xcf,-    0x88, 0x7b, 0x29, 0xbc, 0xfe, 0xce, 0xe8, 0xc3, 0x81, 0xf1, 0xcc, 0x3f, 0xb0, 0xc4, 0x2a, 0x2c, 0x32, 0x9e, 0x99, 0x92,-    0x64, 0x73, 0x2d, 0x39, 0xc6, 0xb9, 0xf1, 0xa0, 0x65, 0xae, 0x0a, 0x1f, 0x37, 0xb0, 0x87, 0x46, 0xec, 0xb2, 0xf8, 0x85,-    0xfc, 0x8e, 0x46, 0xe7, 0x3a, 0xbf, 0xe1, 0x7b, 0xcf, 0x2b, 0x7a, 0x90, 0x54, 0x71, 0x3c, 0x72, 0x9b, 0xfe, 0xa5, 0xc8,-    0xb2, 0x8e, 0x5f, 0x2e, 0xeb, 0x1f, 0xc7, 0x6a, 0xae, 0xa1, 0x3c, 0xe9, 0x9c, 0x51, 0x84, 0xed, 0x79, 0x49, 0x2e, 0xe0,-    0x6e, 0xb6, 0x78, 0x8c, 0x28, 0x2b, 0xeb, 0x53, 0x97, 0x54, 0x3a, 0x89, 0x6b, 0x5c, 0xc7, 0x56, 0x7e, 0xa3, 0x83, 0x38,-    0x36, 0x6c, 0x51, 0xe8, 0x5f, 0x9b, 0x5c, 0x73, 0x47, 0x26, 0xb0, 0x5d, 0xa8, 0x6f, 0xfd, 0x79, 0xee, 0x94, 0x8b, 0xa6,-    0xac, 0x35, 0xf5, 0xfe, 0xcd, 0x66, 0xd6, 0x90, 0x41, 0xd6, 0x73, 0x19, 0xcc, 0x1e, 0xcf, 0xf1, 0x4f, 0xcf, 0x34, 0x91,-    0x19, 0x99, 0x9e, 0xb1, 0x05, 0xd5, 0xd9, 0x69, 0x99, 0x8f, 0xc0, 0xa6, 0xbf, 0x53, 0x3b, 0xb5, 0x8c, 0x4a, 0xff, 0xc6,-    0x7c, 0x6a, 0x7e, 0x76, 0x8d, 0xe8, 0xe6, 0x2a, 0xb8, 0xe3, 0x67, 0x18, 0xbb, 0x98, 0xcb, 0x27, 0xac, 0xe1, 0xf1, 0x02,-    0xeb, 0xbf, 0x91, 0x25, 0xac, 0x03, 0x86, 0x5b, 0x1d, 0x47, 0x65, 0xe8, 0x62, 0x1c, 0x73, 0x9f, 0x59, 0xfb, 0x38, 0x7f,-    0x45, 0x7f, 0x1f, 0xb3, 0xcc, 0xcc, 0x13, 0xcd, 0xd9, 0x62, 0xe9, 0xd5, 0x34, 0x65, 0x33, 0x31, 0xbc, 0x6e, 0x9c, 0xc8,-    0x43, 0xcc, 0x48, 0xce, 0x1b, 0x2c, 0x25, 0xc5, 0xdf, 0x06, 0xe6, 0x0a, 0xfd, 0xd0, 0x50, 0xba, 0x83, 0xc7, 0x5c, 0x17,-    0x8e, 0xfb, 0xf7, 0x67, 0x86, 0x5b, 0xd2, 0xec, 0xfa, 0x77, 0xb7, 0xce, 0x1b, 0x64, 0xab, 0xff, 0x8b, 0x9a, 0xdb, 0x82,-    0xad, 0xde, 0xc2, 0x28, 0xf4, 0x1f, 0xc8, 0xf5, 0xdc, 0xcf, 0x41, 0x61, 0xe6, 0xaa, 0xc3, 0xef, 0x9b, 0x64, 0x4b, 0xbc,-    0xaa, 0x97, 0xfe, 0x4b, 0x43, 0x7c, 0xa1, 0x83, 0x2c, 0x2d, 0xcc, 0x93, 0xcc, 0x33, 0xa3, 0x20, 0xdb, 0x54, 0x2b, 0xc1,-    0x5e, 0xce, 0x61, 0xae, 0x19, 0x07, 0xfc, 0x0e, 0x16, 0x70, 0x36, 0xfb, 0xac, 0x51, 0x8d, 0x17, 0x93, 0xc5, 0x9d, 0x64,-    0x0b, 0x4e, 0xe5, 0xd0, 0xe7, 0x04, 0x8c, 0x3f, 0xd7, 0x46, 0x5b, 0x36, 0x5a, 0x67, 0xd1, 0xb1, 0xeb, 0x7f, 0x31, 0x6b,-    0xfe, 0x66, 0xfd, 0xaf, 0x67, 0x07, 0x55, 0x88, 0xe1, 0x76, 0x72, 0xa3, 0xd0, 0xdf, 0x7f, 0x7f, 0x8e, 0x62, 0xb2, 0x98,-    0x7e, 0x12, 0xbd, 0x82, 0xfd, 0xf3, 0x81, 0xd6, 0xd9, 0xa5, 0xec, 0xfa, 0x7f, 0x1a, 0xe2, 0x66, 0x9f, 0x21, 0x8e, 0x10,-    0xee, 0xf4, 0x76, 0xf7, 0x51, 0x8b, 0x5d, 0x5c, 0xe4, 0x11, 0x09, 0xd0, 0x85, 0xfd, 0xe6, 0x19, 0xaa, 0x1c, 0xfb, 0xe8,-    0xe4, 0x8e, 0x87, 0x2f, 0xb5, 0xc2, 0xcb, 0x4c, 0x19, 0xed, 0xc1, 0x3a, 0x8f, 0x91, 0x52, 0xbd, 0xf5, 0x3f, 0x8d, 0x5d,-    0xc2, 0x73, 0x61, 0x64, 0xfd, 0x63, 0xd9, 0x6e, 0x9d, 0x79, 0xe3, 0xe8, 0xe8, 0x9f, 0xc0, 0x08, 0x0e, 0x90, 0xce, 0x8f,-    0x4c, 0x8f, 0x5a, 0xff, 0xb3, 0xd8, 0x2f, 0xce, 0xdf, 0xe7, 0xe4, 0xfd, 0x50, 0xca, 0x11, 0xc7, 0x35, 0x6c, 0xe6, 0xd1,-    0xa8, 0xf5, 0xbf, 0x91, 0x7d, 0x74, 0xa4, 0x32, 0x35, 0xe8, 0xcb, 0x6e, 0xf1, 0x59, 0xc7, 0xe7, 0xf6, 0xc6, 0x92, 0x3d,-    0xce, 0xf2, 0x19, 0x96, 0x9b, 0x3a, 0xc2, 0xe1, 0x77, 0x56, 0x8a, 0xb3, 0xb9, 0xf9, 0xdb, 0xfe, 0x39, 0xa6, 0x0d, 0x89,-    0x67, 0xb6, 0xb5, 0x06, 0xf7, 0xd6, 0x3f, 0x86, 0x5f, 0x18, 0x46, 0x25, 0xd7, 0xe3, 0x5f, 0x3a, 0x0a, 0xfd, 0x9d, 0x19,-    0x78, 0x9e, 0xf8, 0x5b, 0xf5, 0xf7, 0xdf, 0xaf, 0x55, 0xa2, 0x5a, 0x3f, 0xbf, 0x7d, 0x1e, 0xcc, 0x52, 0x31, 0x52, 0xb4,-    0x1e, 0xa3, 0x48, 0x67, 0x1f, 0x69, 0xf4, 0xb0, 0xce, 0x2b, 0x61, 0xd7, 0xdf, 0xc7, 0xed, 0x24, 0x73, 0x90, 0x03, 0xcc,-    0xf3, 0x98, 0xfd, 0xea, 0x36, 0xb0, 0x6a, 0xea, 0x70, 0x3e, 0xf0, 0x5a, 0x30, 0x26, 0x06, 0x4b, 0x4d, 0x71, 0x13, 0x7b,-    0xa8, 0x13, 0xec, 0x55, 0xee, 0xb1, 0xcc, 0x27, 0xe3, 0xad, 0x7f, 0x9d, 0x43, 0xde, 0xbd, 0xf4, 0x89, 0x4a, 0xff, 0xc7,-    0xac, 0x73, 0xf8, 0x1d, 0x3d, 0xfd, 0x8f, 0x0c, 0xf1, 0x9e, 0xed, 0x65, 0x41, 0x4a, 0x65, 0xe9, 0x13, 0xe4, 0x7d, 0xa9,-    0x97, 0xfe, 0x35, 0xd9, 0x61, 0x89, 0xb5, 0x3e, 0xde, 0xf5, 0x57, 0x42, 0x9f, 0x45, 0x2f, 0xb0, 0xd6, 0x83, 0xab, 0x84,-    0x39, 0x52, 0x4a, 0x71, 0x01, 0x73, 0x55, 0xff, 0x13, 0x84, 0xa7, 0x98, 0xcf, 0x7c, 0xeb, 0xdb, 0xd5, 0x16, 0xc1, 0xef,-    0x13, 0xf9, 0x9c, 0x63, 0xb6, 0xb8, 0x59, 0xf3, 0x4e, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14,-    0x45, 0x51, 0x14, 0x45, 0x39, 0x8a, 0x0c, 0x15, 0x7d, 0xb4, 0x87, 0x7e, 0x11, 0x6f, 0x10, 0xfc, 0xaa, 0x6a, 0xc3, 0x19,-    0xeb, 0xbe, 0x8c, 0x65, 0xeb, 0x0b, 0x69, 0x68, 0x75, 0xab, 0xfb, 0xdd, 0x3d, 0x31, 0x96, 0x6f, 0x8e, 0x97, 0x52, 0x8b,-    0x58, 0x1a, 0x0b, 0x73, 0xb7, 0x7b, 0x9d, 0x75, 0x05, 0xfe, 0x10, 0x47, 0xa2, 0xaf, 0xc4, 0x1f, 0xc1, 0x91, 0x3f, 0x0b,-    0x7a, 0xfd, 0x52, 0x6a, 0x23, 0x4a, 0x50, 0x8b, 0xcb, 0xcc, 0x59, 0x9f, 0xc1, 0x0d, 0xe2, 0x08, 0xfb, 0xce, 0x3a, 0x55,-    0xb9, 0xc4, 0xfa, 0x9d, 0xc8, 0xc9, 0xd3, 0x73, 0x2c, 0x69, 0xce, 0xb6, 0xa7, 0xd3, 0xc4, 0x63, 0xdc, 0xb6, 0x04, 0x93,-    0x33, 0x71, 0x34, 0x16, 0xf2, 0xd5, 0xd9, 0xba, 0x76, 0x84, 0x99, 0xfa, 0x43, 0xc9, 0xa1, 0x81, 0x67, 0x7a, 0x2d, 0x36,-    0xb0, 0x96, 0xff, 0x92, 0x62, 0x9d, 0x6b, 0xc0, 0xef, 0x47, 0x96, 0x47, 0x19, 0xad, 0xc3, 0x46, 0x52, 0x48, 0x67, 0x89,-    0x25, 0x97, 0xcb, 0x32, 0x9e, 0x83, 0xa2, 0xef, 0xfc, 0x22, 0xd2, 0x59, 0x4d, 0x06, 0xaf, 0x83, 0xe0, 0x68, 0xf0, 0x3a,-    0xeb, 0x04, 0x7a, 0x8a, 0xb1, 0x2c, 0xce, 0xf2, 0x6a, 0x51, 0x5e, 0xbf, 0x94, 0x9a, 0x43, 0x3f, 0x96, 0xb1, 0x93, 0xe1,-    0x74, 0x67, 0x2d, 0x1b, 0x59, 0x27, 0x1c, 0x2d, 0x87, 0x1e, 0x6c, 0x61, 0x2b, 0xab, 0xa9, 0x65, 0xcd, 0xd3, 0x54, 0x56,-    0x88, 0xe7, 0x99, 0x43, 0x1f, 0xb2, 0x48, 0x61, 0x0f, 0xd7, 0x8b, 0xe7, 0xe4, 0xe4, 0xcc, 0x2a, 0x76, 0xd3, 0x5b, 0xcc,-    0xf3, 0x1c, 0x86, 0x92, 0xe1, 0xe1, 0x8e, 0x95, 0xae, 0xd0, 0xab, 0xb4, 0x2d, 0xe7, 0x15, 0x62, 0x88, 0xe1, 0x5d, 0xfa,-    0x79, 0x94, 0x45, 0x59, 0xff, 0x18, 0x96, 0x9b, 0xd8, 0x9d, 0x52, 0x7c, 0x23, 0x8c, 0x0c, 0xed, 0x70, 0xbf, 0x99, 0x75,-    0xa2, 0xb8, 0xe0, 0xa5, 0xda, 0x60, 0xbc, 0x62, 0xe5, 0x19, 0x63, 0xd5, 0xbf, 0x9a, 0xf5, 0xfe, 0x6a, 0x64, 0x71, 0xb2,-    0x4a, 0xcb, 0x03, 0x0a, 0xd7, 0xa1, 0x5e, 0x81, 0xf5, 0x7f, 0xd3, 0x9c, 0x59, 0x26, 0xa3, 0x89, 0x25, 0x96, 0xd5, 0x74,-    0x10, 0xd6, 0x19, 0x49, 0x02, 0xc5, 0x98, 0x28, 0x7a, 0xe7, 0x03, 0x79, 0xfa, 0x0e, 0x33, 0xc5, 0x63, 0xce, 0x30, 0xe5,-    0xf4, 0x61, 0x76, 0x08, 0xf1, 0x29, 0x81, 0x9c, 0xa9, 0xc8, 0x0f, 0x16, 0xfd, 0x47, 0x59, 0xc6, 0xf1, 0xb4, 0xe9, 0x3f,-    0xc8, 0xa3, 0xb4, 0x9d, 0xc9, 0x01, 0x31, 0xfe, 0xe8, 0xf0, 0xb2, 0xf8, 0x86, 0x78, 0x2e, 0x8e, 0xd3, 0xba, 0x21, 0x17,-    0x71, 0x11, 0xed, 0xd9, 0x21, 0x46, 0x3f, 0xbd, 0xc5, 0x4c, 0x1a, 0x0b, 0xe3, 0x82, 0xd6, 0x61, 0xbf, 0x5b, 0xeb, 0xdf,-    0x6c, 0xd1, 0xbf, 0xaf, 0xc7, 0xfd, 0x65, 0xbb, 0xa7, 0x73, 0x45, 0x35, 0x9d, 0x65, 0xb7, 0x92, 0x26, 0xfa, 0x5f, 0x65,-    0xfd, 0x1b, 0xbb, 0xf1, 0x32, 0x7e, 0xe7, 0xd4, 0x30, 0xc1, 0xb7, 0x9a, 0xe3, 0xc6, 0x75, 0xb5, 0x67, 0xba, 0x47, 0x9e,-    0x56, 0x22, 0xcf, 0x9d, 0xdf, 0xe2, 0xd0, 0x6d, 0x03, 0x2e, 0xb2, 0xcd, 0xc2, 0x5c, 0x33, 0xb5, 0xc9, 0x71, 0xbf, 0x3e,-    0xdf, 0x6e, 0xd1, 0xff, 0xf2, 0xa8, 0xda, 0x7f, 0xef, 0xd2, 0x76, 0x03, 0xa9, 0x1e, 0xdb, 0x46, 0x2a, 0x8b, 0x37, 0xb0,-    0x9f, 0xd9, 0x41, 0xc2, 0x1d, 0x40, 0xa3, 0x59, 0xc7, 0x4e, 0x66, 0x0a, 0xbe, 0xc3, 0xa6, 0xa4, 0xb9, 0xf7, 0xf6, 0x59,-    0x16, 0xfd, 0x47, 0x79, 0xdc, 0x5f, 0xd1, 0xea, 0xdf, 0x8c, 0x34, 0x2e, 0x8d, 0xa2, 0xfe, 0x6f, 0xe0, 0xea, 0xff, 0xa0,-    0xf9, 0xf9, 0xa1, 0x50, 0xdb, 0x06, 0xd6, 0x79, 0x40, 0x88, 0x0a, 0x0a, 0xcd, 0xd3, 0x2c, 0xc1, 0x13, 0x97, 0x13, 0x1c,-    0xff, 0x7b, 0xbe, 0x10, 0x6f, 0x75, 0x63, 0x70, 0xeb, 0xb3, 0x2d, 0xfa, 0x37, 0x88, 0x52, 0x7f, 0xaf, 0xd2, 0x56, 0x8d,-    0x83, 0x6e, 0xff, 0x26, 0x51, 0xd0, 0x2f, 0x52, 0x59, 0xac, 0xce, 0x41, 0xcf, 0xa8, 0x11, 0xc7, 0xd7, 0xf9, 0x93, 0xb8,-    0xbc, 0x0a, 0xb8, 0x51, 0x8c, 0x6d, 0x2d, 0xfa, 0x07, 0xee, 0xaf, 0x19, 0x7f, 0x59, 0xff, 0x2e, 0xec, 0xb4, 0xce, 0xe9,-    0x74, 0x24, 0xf4, 0xcf, 0xcf, 0xd3, 0x1a, 0xe4, 0x0a, 0xb9, 0x9a, 0xe3, 0xce, 0x3b, 0x14, 0xcf, 0x2e, 0xa1, 0x1f, 0x77,-    0x5a, 0x70, 0x44, 0xf8, 0x36, 0x45, 0xa4, 0xbf, 0x57, 0x69, 0xf3, 0x31, 0x9d, 0x8f, 0x29, 0x4b, 0x79, 0xbe, 0x13, 0xa2,-    0x1b, 0x22, 0x95, 0x45, 0xc7, 0xab, 0xfb, 0xa9, 0x69, 0xdf, 0xdf, 0x76, 0x67, 0x3c, 0x29, 0xa8, 0xfe, 0x3e, 0xc6, 0xb2,-    0x88, 0x56, 0x3c, 0xc1, 0x42, 0xcf, 0xfe, 0xdf, 0x03, 0xe2, 0x08, 0xca, 0xd1, 0xe9, 0xbf, 0xd9, 0x44, 0x0c, 0x1c, 0x3d,-    0xfd, 0x03, 0x79, 0x5a, 0x81, 0x6f, 0xc5, 0x18, 0xb4, 0x1c, 0xf3, 0xfc, 0x52, 0x82, 0xbe, 0xfc, 0x29, 0xb6, 0xbd, 0x0b,-    0xcc, 0xb3, 0xd6, 0x05, 0xcc, 0x2a, 0x22, 0xfd, 0xbd, 0x4a, 0x9b, 0xd3, 0x46, 0x4d, 0x24, 0x93, 0x0c, 0xc6, 0x08, 0xcf,-    0x77, 0x91, 0xca, 0xa2, 0xb3, 0xf5, 0x2f, 0x64, 0x91, 0xc1, 0x74, 0x4b, 0xb4, 0x95, 0x5d, 0xff, 0x52, 0x0c, 0x64, 0x21,-    0x13, 0xb8, 0xea, 0x88, 0xeb, 0x7f, 0x25, 0x0f, 0x90, 0x61, 0x71, 0xa6, 0x1f, 0x19, 0xfd, 0xfd, 0x79, 0x9a, 0xc9, 0x58,-    0x71, 0x6e, 0x95, 0x1c, 0x9e, 0x66, 0x07, 0x7b, 0x59, 0xca, 0xb9, 0x96, 0xf8, 0x84, 0xb9, 0xec, 0x65, 0x0f, 0xed, 0x8b,-    0x48, 0xff, 0xa5, 0x9e, 0xa5, 0xcd, 0x5f, 0xf7, 0xdb, 0x7a, 0x94, 0x81, 0xb2, 0x38, 0xd3, 0x63, 0x96, 0x89, 0x52, 0x1e,-    0x33, 0xc8, 0xd8, 0xf5, 0x2f, 0xeb, 0xc6, 0x71, 0x37, 0x21, 0x5b, 0x38, 0xaf, 0xa2, 0xd4, 0xbf, 0x81, 0x89, 0x2a, 0x5b,-    0x66, 0xd1, 0xa2, 0xc1, 0x11, 0x7a, 0xef, 0x92, 0x68, 0x8d, 0xb6, 0x73, 0x8e, 0x19, 0x6f, 0x89, 0x5e, 0x0e, 0x50, 0x91,-    0x62, 0xd6, 0x67, 0x6e, 0x5f, 0x94, 0xfa, 0xb7, 0xf3, 0x2c, 0x6d, 0xde, 0x04, 0xca, 0xe2, 0x43, 0x85, 0x3c, 0x17, 0xbb,-    0xfe, 0x3f, 0x33, 0x82, 0x2b, 0xb8, 0x93, 0xd9, 0x8c, 0xf1, 0xd0, 0xa5, 0xa8, 0xf4, 0x2f, 0xc6, 0x2c, 0xbe, 0x11, 0x9e,-    0x26, 0x8f, 0x9c, 0xfe, 0x85, 0x7f, 0x23, 0x13, 0xe9, 0x9d, 0x4b, 0x61, 0xdc, 0xfd, 0x27, 0xff, 0x85, 0xad, 0x2b, 0x16,-    0x78, 0xac, 0x81, 0x68, 0xf4, 0xaf, 0x44, 0x6f, 0xa6, 0x30, 0x95, 0x5e, 0x9e, 0xcf, 0x9f, 0xd1, 0x50, 0x9c, 0x83, 0xe2,-    0xd3, 0xe2, 0xb1, 0xc6, 0x18, 0x61, 0x94, 0x0d, 0x9f, 0x38, 0x06, 0xc8, 0x58, 0x8f, 0x18, 0x37, 0xe5, 0xf0, 0x08, 0x94,-    0x0f, 0x58, 0xa5, 0xf9, 0xf0, 0x3f, 0xcb, 0x69, 0xf4, 0x13, 0xdf, 0xf0, 0x29, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a,-    0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0xca, 0x89, 0x4a, 0x15, 0xae, 0x16, 0x7c, 0x88, 0x7e, 0x26, 0x72, 0x9f,-    0xa7, 0x97, 0xb6, 0x32, 0xe7, 0x09, 0x0e, 0xc7, 0x5a, 0xc1, 0xaf, 0xdc, 0x8d, 0x85, 0xb1, 0xf2, 0x6b, 0xb8, 0x6e, 0x8b,-    0xc4, 0xa0, 0x83, 0xfd, 0x22, 0x61, 0x7c, 0xfc, 0x4a, 0x34, 0x72, 0xbf, 0xc8, 0xd6, 0x0d, 0x8e, 0xea, 0x2f, 0x1d, 0xa3,-    0x8c, 0x78, 0x0c, 0xc7, 0x1d, 0x1f, 0xa0, 0x92, 0x47, 0xac, 0xc0, 0xe1, 0x4b, 0x2e, 0xe5, 0x95, 0xb0, 0x65, 0x25, 0x3d,-    0x1c, 0xb5, 0x31, 0xc7, 0xbd, 0xfa, 0x9d, 0xc9, 0x60, 0x0a, 0x69, 0xc2, 0x75, 0x3b, 0x0e, 0xdd, 0x3f, 0x78, 0x55, 0x9c,-    0x4f, 0xc0, 0xeb, 0x0b, 0xfc, 0x43, 0xac, 0x75, 0xf3, 0xa5, 0x0b, 0x0b, 0x85, 0x6d, 0x5b, 0xba, 0xa3, 0x05, 0x3e, 0x0a,-    0xc6, 0x7d, 0x56, 0x91, 0x5c, 0x21, 0xc2, 0xa4, 0x1c, 0xeb, 0xcd, 0xc8, 0xf0, 0x75, 0xc8, 0x14, 0x9c, 0x49, 0xf9, 0xc7,-    0xe8, 0x2c, 0x1e, 0x23, 0x91, 0x55, 0x86, 0xf5, 0xc0, 0x5d, 0x56, 0xef, 0xc2, 0xd4, 0xb0, 0xa5, 0xb7, 0x31, 0x2e, 0x6c,-    0xd9, 0x39, 0x6c, 0x63, 0xb0, 0xb8, 0x8f, 0x16, 0xa4, 0xb1, 0xc9, 0xdc, 0x21, 0x6d, 0xe9, 0x7a, 0x5c, 0xaa, 0x9f, 0x40,-    0x26, 0xd7, 0x9a, 0x3a, 0x60, 0xb0, 0xe0, 0xc3, 0x1f, 0x4d, 0x26, 0xab, 0xc4, 0x51, 0x7b, 0xbd, 0xf4, 0x2f, 0xc3, 0x6e,-    0xd7, 0x55, 0xb8, 0x80, 0x8e, 0xa2, 0x36, 0xfb, 0x4c, 0xf4, 0xcb, 0x57, 0x2c, 0x30, 0xa5, 0xae, 0x15, 0xcb, 0xc5, 0x73,-    0xbb, 0x9e, 0xed, 0x54, 0x66, 0xb2, 0x38, 0xb3, 0x42, 0x19, 0x32, 0x3d, 0x8f, 0x11, 0x60, 0x30, 0xbf, 0x59, 0xc6, 0xe4,-    0xeb, 0xc0, 0x48, 0xe1, 0xee, 0x95, 0xf4, 0x77, 0xdc, 0x48, 0x19, 0xe2, 0xe8, 0xee, 0xb3, 0x79, 0x82, 0xcb, 0x59, 0xc3,-    0x64, 0x76, 0x58, 0x47, 0x9b, 0x3c, 0xd6, 0xf9, 0x0f, 0x5f, 0x70, 0xb1, 0x25, 0x8f, 0x9c, 0x2b, 0x7c, 0xc8, 0xd3, 0xa5,-    0x22, 0x3b, 0x70, 0x86, 0xf1, 0xbe, 0xb9, 0x6f, 0xf6, 0x59, 0xe6, 0x3d, 0x99, 0x40, 0x67, 0xe2, 0x48, 0xe3, 0x0e, 0x66,-    0xe1, 0x23, 0x89, 0xfe, 0x96, 0xa3, 0xbf, 0xcb, 0x42, 0x96, 0x58, 0xfc, 0x25, 0x49, 0xe6, 0x18, 0xf5, 0xd9, 0xe7, 0x31,-    0xee, 0x7e, 0x6b, 0x52, 0xad, 0xe3, 0xa1, 0x8e, 0x14, 0xe2, 0x36, 0x6c, 0xfa, 0x3b, 0x6e, 0x3f, 0x69, 0x4c, 0xe0, 0xda,-    0xe6, 0x9e, 0x49, 0xa4, 0x95, 0xc5, 0x3f, 0x7e, 0x3c, 0x50, 0x83, 0x21, 0x6c, 0x25, 0x35, 0x38, 0xcb, 0x4e, 0x51, 0xe8,-    0x7f, 0x39, 0xe9, 0x14, 0xe3, 0x35, 0xeb, 0x78, 0xd1, 0xff, 0xe2, 0x27, 0x2e, 0x61, 0x1e, 0xc5, 0xd8, 0x49, 0x59, 0x36,-    0x5a, 0xfd, 0xd7, 0x57, 0x82, 0xb5, 0x5e, 0x6d, 0x62, 0x8e, 0xd1, 0xc7, 0x7a, 0x0c, 0x1f, 0xe7, 0xb1, 0x2b, 0xe8, 0x6e,-    0x0e, 0x47, 0x1e, 0xad, 0xd7, 0xa6, 0xff, 0xef, 0x96, 0xf9, 0x00, 0x4e, 0x0c, 0x62, 0xf8, 0x37, 0x79, 0xa2, 0x3b, 0xca,-    0xa6, 0xff, 0x56, 0x9a, 0x9a, 0x9f, 0xaf, 0x8a, 0xfa, 0x3b, 0x91, 0x5f, 0x2d, 0x58, 0x43, 0x33, 0xab, 0x1b, 0x63, 0x37,-    0xcf, 0xf3, 0xaa, 0x99, 0x65, 0xa5, 0x13, 0xdb, 0x2d, 0xb5, 0x4f, 0x09, 0x92, 0x79, 0x99, 0x34, 0x4b, 0x0c, 0x41, 0x0c,-    0x2b, 0x69, 0xc1, 0x9f, 0xd6, 0xb1, 0xba, 0xcb, 0xb1, 0xf2, 0x90, 0xb9, 0xa5, 0x0e, 0x6f, 0xf7, 0x96, 0x8b, 0xae, 0x6f,-    0x9b, 0xfe, 0x63, 0x82, 0x33, 0x0f, 0x9d, 0x58, 0x54, 0x66, 0xbd, 0x89, 0x41, 0xb9, 0x8c, 0x03, 0xd4, 0x8e, 0x42, 0xff,-    0x0f, 0x19, 0xcb, 0x29, 0x5c, 0x4a, 0xb2, 0xa8, 0xbf, 0x8f, 0x7f, 0x33, 0x9d, 0x8d, 0xd6, 0x56, 0xc5, 0x99, 0xd3, 0xe5,-    0x4f, 0x2e, 0x33, 0xf3, 0x78, 0xad, 0x75, 0xe7, 0xc1, 0x08, 0x67, 0x20, 0x93, 0x89, 0xa1, 0x0f, 0x93, 0x85, 0xfe, 0xbd,-    0xcf, 0xcc, 0x07, 0x35, 0x83, 0x0d, 0x96, 0x63, 0xc4, 0xf0, 0x1d, 0x93, 0xa8, 0x4c, 0x25, 0x2a, 0x09, 0x4e, 0xdb, 0xb2,-    0x6c, 0x65, 0x80, 0xd8, 0xab, 0xb7, 0xe9, 0x5f, 0x97, 0xb9, 0x1e, 0x23, 0x8a, 0x1f, 0xcf, 0xb4, 0x27, 0x95, 0x1d, 0xec,-    0xb6, 0xcc, 0x88, 0xf1, 0xb5, 0xb9, 0x4b, 0xc3, 0xa9, 0xcf, 0x78, 0x72, 0x98, 0xcf, 0x93, 0x16, 0xfd, 0x4f, 0xe1, 0x00,-    0xbd, 0x3c, 0x8e, 0xfa, 0x0a, 0xe9, 0x46, 0x39, 0x67, 0x26, 0xa7, 0xbb, 0xc5, 0x35, 0xae, 0x62, 0xb7, 0x19, 0x4f, 0xbf,-    0x04, 0xcb, 0x2d, 0xe7, 0x56, 0x9d, 0x5c, 0xeb, 0x31, 0xce, 0x0f, 0x19, 0xc5, 0xfb, 0x05, 0xc1, 0x0b, 0xfa, 0x3a, 0x2b,-    0x44, 0x9f, 0xa5, 0x4d, 0xff, 0x76, 0x2c, 0xa5, 0xd5, 0x09, 0x5b, 0xff, 0x9f, 0x62, 0xb9, 0xc3, 0x9c, 0x56, 0x76, 0x25,-    0xdb, 0x2c, 0xa9, 0xc5, 0xff, 0xe6, 0xb3, 0xae, 0xca, 0x7e, 0xeb, 0x8c, 0x0b, 0x91, 0x99, 0x14, 0x9c, 0x77, 0xac, 0x20,-    0xfa, 0x4f, 0x16, 0xd7, 0xfe, 0xdf, 0x20, 0xf1, 0x98, 0x3c, 0xab, 0x3b, 0xf9, 0xa5, 0x50, 0x73, 0xa7, 0x05, 0xf8, 0x32,-    0xca, 0xfe, 0x5f, 0x73, 0x7d, 0x53, 0x78, 0x0c, 0x11, 0xcf, 0xd8, 0x90, 0x99, 0x69, 0x0a, 0xc3, 0x10, 0x9e, 0x8f, 0x42,-    0xff, 0x65, 0x34, 0xd2, 0x5c, 0x3f, 0xa1, 0xb8, 0x95, 0xa5, 0xc2, 0x2c, 0x51, 0x92, 0xfe, 0xa5, 0x78, 0x82, 0x34, 0x8f,-    0xbe, 0xac, 0x72, 0x3c, 0x52, 0x9c, 0xb6, 0x42, 0xe4, 0xa6, 0xa4, 0x7f, 0x5d, 0xde, 0x15, 0x47, 0x14, 0x52, 0x4e, 0x3c,-    0x6c, 0xf5, 0xbf, 0xa2, 0xfa, 0x2b, 0xaa, 0xbf, 0x72, 0x62, 0x53, 0xc2, 0xe3, 0x6b, 0x92, 0xa2, 0x28, 0x8a, 0xa2, 0x28,-    0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2,-    0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a,-    0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28,-    0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2,-    0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a,-    0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28,-    0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2,-    0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a,-    0xa2, 0x28, 0x8a, 0xe2, 0xe0, 0xff, 0xa7, 0xf9, 0xa0, 0xfa, 0x2b, 0xff, 0xb3, 0xfa, 0xff, 0x3f };--// Font glyphs rectangles data (on atlas)-static const Rectangle amberFontRecs[95] = {-    { 4, 4, 3 , 16 },-    { 15, 4, 2 , 11 },-    { 25, 4, 4 , 5 },-    { 37, 4, 9 , 10 },-    { 54, 4, 8 , 14 },-    { 70, 4, 11 , 11 },-    { 89, 4, 9 , 11 },-    { 106, 4, 2 , 5 },-    { 116, 4, 4 , 13 },-    { 128, 4, 4 , 13 },-    { 140, 4, 6 , 6 },-    { 154, 4, 7 , 7 },-    { 169, 4, 3 , 5 },-    { 180, 4, 6 , 2 },-    { 194, 4, 2 , 3 },-    { 204, 4, 5 , 13 },-    { 217, 4, 8 , 11 },-    { 233, 4, 5 , 10 },-    { 4, 28, 8 , 10 },-    { 20, 28, 8 , 11 },-    { 36, 28, 8 , 10 },-    { 52, 28, 7 , 11 },-    { 67, 28, 8 , 11 },-    { 83, 28, 7 , 10 },-    { 98, 28, 8 , 11 },-    { 114, 28, 8 , 11 },-    { 130, 28, 2 , 8 },-    { 140, 28, 3 , 10 },-    { 151, 28, 7 , 8 },-    { 166, 28, 7 , 5 },-    { 181, 28, 7 , 8 },-    { 196, 28, 7 , 11 },-    { 211, 28, 12 , 13 },-    { 231, 28, 9 , 10 },-    { 4, 52, 7 , 10 },-    { 19, 52, 9 , 11 },-    { 36, 52, 8 , 10 },-    { 52, 52, 7 , 10 },-    { 67, 52, 6 , 10 },-    { 81, 52, 10 , 11 },-    { 99, 52, 8 , 10 },-    { 115, 52, 2 , 10 },-    { 125, 52, 7 , 11 },-    { 140, 52, 8 , 10 },-    { 156, 52, 6 , 10 },-    { 170, 52, 10 , 10 },-    { 188, 52, 8 , 10 },-    { 204, 52, 10 , 11 },-    { 222, 52, 7 , 10 },-    { 237, 52, 10 , 11 },-    { 4, 76, 8 , 10 },-    { 20, 76, 8 , 11 },-    { 36, 76, 8 , 10 },-    { 52, 76, 8 , 11 },-    { 68, 76, 9 , 10 },-    { 85, 76, 13 , 10 },-    { 106, 76, 9 , 10 },-    { 123, 76, 9 , 10 },-    { 140, 76, 8 , 10 },-    { 156, 76, 4 , 13 },-    { 168, 76, 5 , 13 },-    { 181, 76, 4 , 13 },-    { 193, 76, 6 , 5 },-    { 207, 76, 7 , 2 },-    { 222, 76, 4 , 3 },-    { 234, 76, 7 , 9 },-    { 4, 100, 7 , 11 },-    { 19, 100, 7 , 9 },-    { 34, 100, 8 , 11 },-    { 50, 100, 8 , 9 },-    { 66, 100, 5 , 11 },-    { 79, 100, 8 , 11 },-    { 95, 100, 6 , 10 },-    { 109, 100, 3 , 10 },-    { 120, 100, 4 , 13 },-    { 132, 100, 7 , 10 },-    { 147, 100, 2 , 10 },-    { 157, 100, 10 , 8 },-    { 175, 100, 6 , 8 },-    { 189, 100, 8 , 9 },-    { 205, 100, 7 , 11 },-    { 220, 100, 8 , 11 },-    { 236, 100, 4 , 8 },-    { 4, 124, 7 , 9 },-    { 19, 124, 5 , 10 },-    { 32, 124, 6 , 9 },-    { 46, 124, 8 , 8 },-    { 62, 124, 11 , 8 },-    { 81, 124, 7 , 8 },-    { 96, 124, 8 , 11 },-    { 112, 124, 7 , 8 },-    { 127, 124, 5 , 13 },-    { 140, 124, 2 , 17 },-    { 150, 124, 5 , 13 },-    { 163, 124, 7 , 4 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo amberFontGlyphs[95] = {-    { 32, 0, 12, 3, { 0 }},-    { 33, 1, 2, 3, { 0 }},-    { 34, 1, 2, 6, { 0 }},-    { 35, 0, 2, 8, { 0 }},-    { 36, 0, 0, 8, { 0 }},-    { 37, 1, 2, 12, { 0 }},-    { 38, 0, 2, 8, { 0 }},-    { 39, 1, 2, 3, { 0 }},-    { 40, 1, 1, 4, { 0 }},-    { 41, 0, 1, 4, { 0 }},-    { 42, 0, 2, 6, { 0 }},-    { 43, 1, 5, 8, { 0 }},-    { 44, 0, 10, 3, { 0 }},-    { 45, 0, 7, 6, { 0 }},-    { 46, 1, 10, 3, { 0 }},-    { 47, 0, 1, 4, { 0 }},-    { 48, 0, 2, 8, { 0 }},-    { 49, 0, 2, 5, { 0 }},-    { 50, 0, 2, 8, { 0 }},-    { 51, 0, 2, 8, { 0 }},-    { 52, 0, 2, 8, { 0 }},-    { 53, 1, 2, 8, { 0 }},-    { 54, 0, 2, 8, { 0 }},-    { 55, 0, 2, 7, { 0 }},-    { 56, 0, 2, 8, { 0 }},-    { 57, 0, 2, 8, { 0 }},-    { 58, 1, 5, 3, { 0 }},-    { 59, 0, 5, 3, { 0 }},-    { 60, 1, 4, 8, { 0 }},-    { 61, 1, 6, 8, { 0 }},-    { 62, 1, 4, 8, { 0 }},-    { 63, 0, 2, 6, { 0 }},-    { 64, 0, 2, 12, { 0 }},-    { 65, 0, 2, 9, { 0 }},-    { 66, 1, 2, 8, { 0 }},-    { 67, 0, 2, 9, { 0 }},-    { 68, 1, 2, 9, { 0 }},-    { 69, 1, 2, 7, { 0 }},-    { 70, 1, 2, 7, { 0 }},-    { 71, 0, 2, 9, { 0 }},-    { 72, 1, 2, 9, { 0 }},-    { 73, 1, 2, 3, { 0 }},-    { 74, 0, 2, 7, { 0 }},-    { 75, 1, 2, 8, { 0 }},-    { 76, 1, 2, 7, { 0 }},-    { 77, 1, 2, 11, { 0 }},-    { 78, 1, 2, 9, { 0 }},-    { 79, 0, 2, 10, { 0 }},-    { 80, 1, 2, 8, { 0 }},-    { 81, 0, 2, 10, { 0 }},-    { 82, 1, 2, 8, { 0 }},-    { 83, 0, 2, 8, { 0 }},-    { 84, 0, 2, 8, { 0 }},-    { 85, 1, 2, 9, { 0 }},-    { 86, 0, 2, 9, { 0 }},-    { 87, 0, 2, 13, { 0 }},-    { 88, 0, 2, 9, { 0 }},-    { 89, 0, 2, 8, { 0 }},-    { 90, 0, 2, 8, { 0 }},-    { 91, 1, 1, 4, { 0 }},-    { 92, 0, 1, 4, { 0 }},-    { 93, 0, 1, 4, { 0 }},-    { 94, 0, 2, 6, { 0 }},-    { 95, 0, 12, 6, { 0 }},-    { 96, 0, 1, 4, { 0 }},-    { 97, 0, 4, 7, { 0 }},-    { 98, 1, 2, 8, { 0 }},-    { 99, 0, 4, 7, { 0 }},-    { 100, 0, 2, 8, { 0 }},-    { 101, 0, 4, 7, { 0 }},-    { 102, 0, 1, 4, { 0 }},-    { 103, 0, 4, 8, { 0 }},-    { 104, 1, 2, 7, { 0 }},-    { 105, 0, 2, 3, { 0 }},-    { 106, -1, 2, 3, { 0 }},-    { 107, 1, 2, 7, { 0 }},-    { 108, 1, 2, 3, { 0 }},-    { 109, 1, 4, 11, { 0 }},-    { 110, 1, 4, 7, { 0 }},-    { 111, 0, 4, 7, { 0 }},-    { 112, 1, 4, 8, { 0 }},-    { 113, 0, 4, 8, { 0 }},-    { 114, 1, 4, 4, { 0 }},-    { 115, 0, 4, 6, { 0 }},-    { 116, 0, 3, 4, { 0 }},-    { 117, 1, 4, 7, { 0 }},-    { 118, 0, 4, 7, { 0 }},-    { 119, 0, 4, 10, { 0 }},-    { 120, 0, 4, 7, { 0 }},-    { 121, 0, 4, 7, { 0 }},-    { 122, 0, 4, 7, { 0 }},-    { 123, 0, 1, 5, { 0 }},-    { 124, 1, -1, 4, { 0 }},-    { 125, 0, 1, 5, { 0 }},-    { 126, 1, 6, 8, { 0 }},-};--// Style loading function: Amber-static void GuiLoadStyleAmber(void)-{-    // Load style properties provided-    // NOTE: Default properties are propagated-    for (int i = 0; i < AMBER_STYLE_PROPS_COUNT; i++)-    {-        GuiSetStyle(amberStyleProps[i].controlId, amberStyleProps[i].propertyId, amberStyleProps[i].propertyValue);-    }--    // Custom font loading-    // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function-    int amberFontDataSize = 0;-    unsigned char *data = DecompressData(amberFontData, AMBER_STYLE_FONT_ATLAS_COMP_SIZE, &amberFontDataSize);-    Image imFont = { data, 256, 256, 1, 2 };--    Font font = { 0 };-    font.baseSize = 16;-    font.glyphCount = 95;--    // Load texture from image-    font.texture = LoadTextureFromImage(imFont);-    UnloadImage(imFont);  // Uncompressed image data can be unloaded from memory--    // Copy char recs data from global fontRecs-    // NOTE: Required to avoid issues if trying to free font-    font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));-    memcpy(font.recs, amberFontRecs, font.glyphCount*sizeof(Rectangle));--    // Copy font char info data from global fontChars-    // NOTE: Required to avoid issues if trying to free font-    font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));-    memcpy(font.glyphs, amberFontGlyphs, font.glyphCount*sizeof(GlyphInfo));--    GuiSetFont(font);--    // Setup a white rectangle on the font to be used on shapes drawing,-    // it makes possible to draw shapes and text (full UI) in a single draw call-    Rectangle fontWhiteRec = { 254, 126, 1, 1 };+// Copyright (c) 2020-2024 raylib technologies (@raylibtech)                    //+//                                                                              //+//////////////////////////////////////////////////////////////////////////////////++#define AMBER_STYLE_PROPS_COUNT  16++// Custom style name: Amber+static const GuiStyleProp amberStyleProps[AMBER_STYLE_PROPS_COUNT] = {+    { 0, 0, (int)0x898988ff },    // DEFAULT_BORDER_COLOR_NORMAL +    { 0, 1, (int)0x292929ff },    // DEFAULT_BASE_COLOR_NORMAL +    { 0, 2, (int)0xd4d4d4ff },    // DEFAULT_TEXT_COLOR_NORMAL +    { 0, 3, (int)0xeb891dff },    // DEFAULT_BORDER_COLOR_FOCUSED +    { 0, 4, (int)0x292929ff },    // DEFAULT_BASE_COLOR_FOCUSED +    { 0, 5, (int)0xffffffff },    // DEFAULT_TEXT_COLOR_FOCUSED +    { 0, 6, (int)0xf1cf9dff },    // DEFAULT_BORDER_COLOR_PRESSED +    { 0, 7, (int)0xf39333ff },    // DEFAULT_BASE_COLOR_PRESSED +    { 0, 8, (int)0x282020ff },    // DEFAULT_TEXT_COLOR_PRESSED +    { 0, 9, (int)0x6a6a6aff },    // DEFAULT_BORDER_COLOR_DISABLED +    { 0, 10, (int)0x818181ff },    // DEFAULT_BASE_COLOR_DISABLED +    { 0, 11, (int)0x606060ff },    // DEFAULT_TEXT_COLOR_DISABLED +    { 0, 16, (int)0x00000010 },    // DEFAULT_TEXT_SIZE +    { 0, 18, (int)0xef922aff },    // DEFAULT_LINE_COLOR +    { 0, 19, (int)0x333333ff },    // DEFAULT_BACKGROUND_COLOR +    { 0, 20, (int)0x00000018 },    // DEFAULT_TEXT_LINE_SPACING +};++// WARNING: This style uses a custom font: "hello-world.ttf" (size: 16, spacing: 1)++#define AMBER_STYLE_FONT_ATLAS_COMP_SIZE 2605++// Font atlas image pixels data: DEFLATE compressed+static unsigned char amberFontData[AMBER_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+    0xdd, 0x8b, 0x8e, 0x9c, 0xb8, 0x12, 0x00, 0x50, 0xf8, 0xff, 0x7f, 0x76, 0x5d, 0xe9, 0x66, 0xb3, 0xd2, 0xee, 0x8e, 0x6d,+    0xaa, 0x30, 0x8f, 0xee, 0x9c, 0x1c, 0x45, 0x91, 0x9a, 0x34, 0x18, 0xdb, 0x85, 0x0d, 0x33, 0x94, 0x63, 0x03, 0x00, 0x00,+    0x00, 0x88, 0x2d, 0x5a, 0xe7, 0xb3, 0xcc, 0xe7, 0x5b, 0xf7, 0xf3, 0xf6, 0xd7, 0xe7, 0x6d, 0xb0, 0xed, 0xe8, 0xbe, 0xfa,+    0x65, 0xda, 0x92, 0xfb, 0x89, 0xee, 0x37, 0xe2, 0x87, 0x4f, 0x7e, 0xff, 0xc9, 0xec, 0xa7, 0x77, 0xbe, 0xf9, 0xda, 0xcb,+    0x6e, 0x19, 0x1f, 0xbd, 0x25, 0x4b, 0x56, 0xff, 0xce, 0xd1, 0x7a, 0xcf, 0xd4, 0xe1, 0xef, 0x3f, 0x2d, 0xb1, 0x97, 0x71,+    0x79, 0x7e, 0xde, 0xdb, 0x36, 0x39, 0xeb, 0xdc, 0x79, 0xb7, 0xe9, 0x96, 0xda, 0xb7, 0xd6, 0xc4, 0x7f, 0xaf, 0x4d, 0x32,+    0x9f, 0x6f, 0xdd, 0x7a, 0xfc, 0x15, 0x37, 0xbd, 0xb8, 0xdd, 0x13, 0xfd, 0xa4, 0x17, 0x23, 0xfb, 0x20, 0xca, 0x23, 0xb5,+    0xff, 0x71, 0x2f, 0x5a, 0x71, 0x4d, 0xed, 0x95, 0xf6, 0xe7, 0xab, 0x4b, 0xff, 0x1b, 0x6d, 0x78, 0xe6, 0xb5, 0x6b, 0x55,+    0xbf, 0x1e, 0xf7, 0x1f, 0xbe, 0x5b, 0x2b, 0xdb, 0xf1, 0x72, 0x45, 0xba, 0x2d, 0x62, 0xd8, 0x6b, 0xf6, 0xee, 0x35, 0x23,+    0x77, 0x76, 0x51, 0x38, 0xef, 0x98, 0x6c, 0xd9, 0x52, 0xa3, 0x5a, 0x5b, 0x3c, 0xfe, 0xaf, 0x88, 0xff, 0xf8, 0x7f, 0x2d,+    0xee, 0xa9, 0xf1, 0x36, 0x92, 0x65, 0xca, 0x47, 0xed, 0xde, 0x39, 0x6e, 0x7f, 0x3c, 0xbf, 0xba, 0x4e, 0x7b, 0xdb, 0xf6,+    0x42, 0x6d, 0xf4, 0xb6, 0xb4, 0xee, 0x79, 0x6f, 0xe5, 0xab, 0x5e, 0x24, 0xce, 0x26, 0x4e, 0x5f, 0x4b, 0x63, 0xd0, 0xd2,+    0xe3, 0xb6, 0x8b, 0x74, 0x49, 0xa3, 0xf0, 0x9d, 0xf1, 0x96, 0x6d, 0xe9, 0x77, 0xae, 0x1b, 0xa3, 0xf2, 0xfb, 0x1b, 0xcf,+    0xbe, 0xa2, 0x18, 0x0f, 0xe7, 0xcb, 0xb9, 0xa7, 0xaf, 0x89, 0x71, 0xf1, 0x3d, 0x55, 0x36, 0xfe, 0xb7, 0x85, 0xf1, 0x1f,+    0xe9, 0xfa, 0xbe, 0x2f, 0xfe, 0x9f, 0x18, 0xff, 0xb7, 0x49, 0xfc, 0x6f, 0xe2, 0x3f, 0xf5, 0x7f, 0x73, 0xf7, 0x05, 0xe3,+    0x71, 0x3b, 0x12, 0xf3, 0x99, 0x58, 0x18, 0xcf, 0x71, 0x7b, 0xf4, 0x8f, 0x7a, 0x5b, 0x65, 0x26, 0xd8, 0xbf, 0xdf, 0xea,+    0xc7, 0xd9, 0xe8, 0x1e, 0x2d, 0xd2, 0x33, 0xce, 0xd1, 0xdd, 0x55, 0xe6, 0x79, 0x49, 0x2c, 0xeb, 0x99, 0x5b, 0x29, 0xfe,+    0x23, 0xf5, 0xcc, 0x27, 0x26, 0x35, 0x9f, 0x8d, 0xff, 0x18, 0x5c, 0xff, 0x46, 0xfd, 0x28, 0x2e, 0xbd, 0xff, 0xcf, 0xc6,+    0xff, 0x36, 0x99, 0x95, 0x6d, 0xa9, 0x9e, 0x5a, 0x29, 0x65, 0x7b, 0xd1, 0x13, 0xd5, 0x95, 0xf1, 0x1f, 0xc9, 0xb3, 0x8e,+    0x03, 0x4f, 0xc3, 0x7a, 0xc7, 0xa8, 0xdc, 0xbd, 0xb5, 0x93, 0xfd, 0x2a, 0x1e, 0x6c, 0x93, 0x33, 0x23, 0x76, 0x7b, 0x7c,+    0xfc, 0x8f, 0xc7, 0xe6, 0xff, 0x91, 0x9e, 0x1b, 0x5c, 0x1f, 0xff, 0xf1, 0xf2, 0xe8, 0xaf, 0xcd, 0xff, 0xa3, 0x38, 0x2f,+    0x8f, 0x45, 0x73, 0xf9, 0xea, 0xdd, 0xcc, 0xbb, 0x5a, 0x64, 0x9b, 0x3e, 0x4f, 0xf8, 0xc4, 0xf9, 0x7f, 0x3c, 0x54, 0x8f,+    0x51, 0xb8, 0x37, 0x10, 0xff, 0x95, 0xf8, 0xaf, 0xcd, 0x69, 0x67, 0x4f, 0x37, 0x63, 0xe9, 0x95, 0xe9, 0xb3, 0xe3, 0xbf,+    0x1e, 0xb1, 0xe2, 0xff, 0xe8, 0xdc, 0x36, 0x86, 0xcf, 0x65, 0x63, 0x49, 0x1b, 0x7e, 0xc6, 0x58, 0xb3, 0x2e, 0xfe, 0xe3,+    0xc4, 0x5d, 0xc3, 0x9f, 0x18, 0xff, 0xdb, 0x8d, 0xf1, 0x1f, 0x5f, 0x3b, 0xff, 0xaf, 0xdc, 0xff, 0xc7, 0xf0, 0x27, 0xd2,+    0xb1, 0x68, 0x06, 0xf0, 0xfe, 0xd1, 0xbf, 0xf2, 0xb4, 0x67, 0xfc, 0x9b, 0x47, 0x91, 0xfe, 0xb9, 0x40, 0xe5, 0x69, 0xd3,+    0x6c, 0xee, 0xbc, 0xa5, 0xcb, 0xf6, 0xe9, 0xe3, 0x7f, 0xfe, 0xbc, 0x63, 0xba, 0x25, 0x0a, 0xfd, 0xe8, 0x6d, 0xd7, 0xd7,+    0x78, 0x7c, 0x64, 0x05, 0xbe, 0x97, 0xf8, 0x07, 0x57, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+    0x00, 0x00, 0xc0, 0x77, 0x6a, 0xff, 0xfa, 0xf7, 0x9f, 0xdb, 0xda, 0x8f, 0xd9, 0x8c, 0x5b, 0x77, 0x4b, 0x6f, 0x5f, 0xad,+    0x70, 0xfc, 0x7c, 0xc9, 0x56, 0xe7, 0x60, 0xdf, 0x06, 0x67, 0x5a, 0xaf, 0x83, 0xeb, 0xb7, 0x8c, 0x4b, 0x9d, 0x69, 0x9b,+    0x7e, 0xbd, 0x6c, 0xa9, 0x77, 0x92, 0x73, 0x79, 0x02, 0xdb, 0xe4, 0x0d, 0xd7, 0xec, 0xba, 0x0e, 0xb3, 0x1c, 0x86, 0x99,+    0xcc, 0x87, 0xed, 0x50, 0x34, 0xcd, 0x3f, 0xcf, 0x96, 0x67, 0x1b, 0x66, 0xc5, 0x8c, 0x72, 0xde, 0xbf, 0x5a, 0xee, 0xe9,+    0x3d, 0x99, 0xf9, 0x69, 0xf4, 0x3e, 0x7a, 0x4b, 0x67, 0x67, 0xbe, 0x2b, 0x07, 0xfb, 0xa8, 0x3e, 0xf7, 0x74, 0xf6, 0x8b,+    0xca, 0x96, 0xbd, 0xbb, 0xae, 0xca, 0x2c, 0xd7, 0xc3, 0x7e, 0xb8, 0x15, 0x46, 0x39, 0x92, 0xf7, 0x6e, 0x1e, 0xf1, 0x5c,+    0x5f, 0x5b, 0x95, 0xfb, 0x3e, 0xa6, 0x25, 0x8e, 0xe4, 0x77, 0xda, 0xf0, 0x38, 0x71, 0xd9, 0x3b, 0x65, 0x91, 0xac, 0xad,+    0xed, 0xef, 0x1c, 0x1b, 0xb9, 0xba, 0x3c, 0x13, 0xff, 0x95, 0xfc, 0xd2, 0x5b, 0x3a, 0x03, 0xea, 0xde, 0xc9, 0x4b, 0xff,+    0xfb, 0x7a, 0x76, 0x57, 0xa6, 0x95, 0x6c, 0x5b, 0xdf, 0x11, 0xff, 0xf3, 0xdc, 0x69, 0x91, 0x1a, 0x07, 0xf3, 0x7d, 0xf1,+    0x89, 0xdc, 0x0d, 0x77, 0xe5, 0x23, 0x3f, 0xd3, 0x8a, 0x57, 0xc6, 0x7f, 0x3e, 0x4f, 0x6c, 0x3d, 0xf3, 0xcf, 0xfa, 0xf8,+    0xcf, 0xe7, 0xab, 0x8a, 0x6e, 0x3e, 0x15, 0xf1, 0x5f, 0x8d, 0xff, 0xf8, 0x80, 0xf8, 0x5f, 0x99, 0x49, 0x7b, 0xb6, 0xb7,+    0x48, 0x65, 0x3e, 0x9f, 0x65, 0xf9, 0x69, 0x83, 0xb9, 0xec, 0xb1, 0xbb, 0x8f, 0x38, 0x30, 0xff, 0xb8, 0x27, 0xfe, 0x67,+    0x99, 0x7b, 0x73, 0xfd, 0xab, 0xba, 0x9f, 0x55, 0x6b, 0x30, 0xcc, 0x7a, 0x4e, 0xb6, 0x45, 0x23, 0xb9, 0x52, 0xe0, 0xea,+    0xf8, 0x1f, 0x47, 0x6d, 0xad, 0x6c, 0xdb, 0xd2, 0x11, 0xf7, 0xec, 0x08, 0x18, 0x4b, 0xef, 0x0c, 0xee, 0xb9, 0x8a, 0xef,+    0xa7, 0x57, 0x8f, 0x8b, 0xe1, 0x1d, 0xe6, 0xba, 0xbe, 0x75, 0xef, 0xf8, 0x1f, 0x8b, 0xf3, 0xa9, 0xc7, 0x8d, 0x99, 0x56,+    0xf3, 0xab, 0x5c, 0x64, 0xeb, 0xb3, 0x92, 0x23, 0x35, 0x9f, 0x55, 0xf9, 0x5b, 0xe2, 0xff, 0xfa, 0x2d, 0xeb, 0x23, 0x2d,+    0x17, 0xff, 0x71, 0xc3, 0xdc, 0xf2, 0x13, 0xe6, 0xff, 0xdb, 0x30, 0x5f, 0xfd, 0x5d, 0xf1, 0x5f, 0x6d, 0x8d, 0x6b, 0xe3,+    0x3f, 0x0a, 0xf3, 0xf6, 0x95, 0xf3, 0xfc, 0x67, 0xe6, 0xff, 0xe3, 0x31, 0x26, 0xd2, 0xf5, 0x5e, 0xcd, 0x61, 0x7a, 0x65,+    0xfc, 0xc7, 0x2d, 0xf7, 0x96, 0xf7, 0xc7, 0xff, 0xda, 0xb8, 0x5c, 0x1b, 0xff, 0x2b, 0xd7, 0xab, 0x10, 0xff, 0xf7, 0xcf,+    0x0c, 0xd6, 0x7e, 0xa7, 0x72, 0x77, 0xf0, 0xe4, 0xf8, 0x7f, 0x7f, 0x5d, 0x3f, 0x1f, 0xff, 0x2b, 0xe7, 0xff, 0xf1, 0x70,+    0xfc, 0x57, 0xd6, 0xff, 0xba, 0x67, 0x96, 0x2f, 0xfe, 0x9f, 0x88, 0xff, 0x37, 0xd4, 0x7a, 0x7e, 0xde, 0x34, 0x7f, 0x5a,+    0x98, 0x5b, 0x35, 0xb1, 0xf6, 0x54, 0x3c, 0x8a, 0x2b, 0x87, 0x47, 0xa1, 0xd4, 0x95, 0x99, 0xe3, 0xb6, 0xe4, 0x5e, 0xbe,+    0x76, 0x35, 0xa9, 0x64, 0x8e, 0xaf, 0xae, 0x33, 0x76, 0xe7, 0x7d, 0xc1, 0x35, 0xdf, 0xca, 0xb5, 0x62, 0x4c, 0xeb, 0x7e,+    0xc5, 0x75, 0x64, 0x7b, 0x61, 0x16, 0x7f, 0x3e, 0x5d, 0xdc, 0xf4, 0x1d, 0xd4, 0x22, 0xe2, 0x1f, 0xb5, 0xc8, 0x9b, 0x7a,+    0x61, 0x24, 0xef, 0xa9, 0xcd, 0x42, 0xd7, 0xd4, 0xba, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+    0x00, 0x56, 0xfd, 0x7e, 0x72, 0x36, 0xa7, 0xf8, 0x28, 0x6f, 0x62, 0x7e, 0x7f, 0xb3, 0x2c, 0x68, 0xed, 0xc1, 0x2d, 0xa3,+    0x5a, 0x68, 0x07, 0xcf, 0xa6, 0x25, 0xf3, 0xbc, 0xf5, 0xeb, 0xa4, 0x9f, 0x5f, 0xbe, 0x25, 0xb7, 0xb5, 0xc9, 0x1e, 0x8f,+    0xee, 0xfd, 0x78, 0x1b, 0xf7, 0xb3, 0xa8, 0xe5, 0xea, 0xbd, 0x9f, 0x99, 0xbf, 0x25, 0x57, 0x2c, 0x98, 0xd5, 0xe8, 0x96,+    0x68, 0xc9, 0x23, 0xbd, 0x69, 0xb4, 0xd6, 0xc4, 0xd1, 0x76, 0x38, 0x7a, 0x0e, 0x71, 0xf0, 0xad, 0xa3, 0x59, 0xae, 0xc5,+    0xd1, 0x96, 0x4c, 0x56, 0xa3, 0x33, 0xb9, 0x27, 0x56, 0xe6, 0xd2, 0x5d, 0x95, 0x4b, 0x3f, 0x97, 0xbb, 0x71, 0x1f, 0xb6,+    0x51, 0x9c, 0xbc, 0x52, 0xb7, 0xc1, 0x31, 0x5a, 0x21, 0xef, 0xc3, 0xf1, 0xbd, 0x1f, 0x6f, 0xe3, 0x3d, 0x9d, 0xdd, 0x64,+    0x65, 0xfe, 0xfd, 0x96, 0xce, 0xd8, 0xb9, 0x27, 0x57, 0xc4, 0x38, 0x9e, 0x4f, 0x62, 0x4f, 0x67, 0xae, 0x98, 0xf5, 0xc3,+    0xfd, 0xc4, 0x15, 0xe0, 0xce, 0xfc, 0x3b, 0x6f, 0x88, 0xff, 0x55, 0xb9, 0xb4, 0xaf, 0xce, 0xca, 0xd3, 0xba, 0xa5, 0x6f,+    0x17, 0xd7, 0x6d, 0x3d, 0xe2, 0x62, 0x98, 0x01, 0x23, 0xca, 0x63, 0xd4, 0xd1, 0x63, 0x8c, 0x22, 0x67, 0xb4, 0x62, 0xd1,+    0xf1, 0xeb, 0x66, 0x2c, 0x88, 0xff, 0x33, 0x6f, 0x03, 0x1f, 0x1f, 0x5b, 0x8e, 0xd6, 0xef, 0x7d, 0x19, 0xf3, 0xc7, 0x39,+    0xd8, 0x73, 0x59, 0xd8, 0x57, 0x67, 0xcc, 0x59, 0x17, 0xe7, 0xab, 0xf2, 0xe8, 0xe4, 0xa2, 0x25, 0xd2, 0xf3, 0xf1, 0x4c,+    0xfc, 0xc7, 0xe1, 0xd9, 0x7f, 0x36, 0x9f, 0x4d, 0x3e, 0x1a, 0x62, 0xf1, 0x1b, 0xb5, 0xfd, 0xf2, 0xb6, 0x8b, 0xc6, 0xff,+    0xd5, 0xf1, 0xbf, 0x9d, 0x88, 0xfe, 0x7b, 0x57, 0xcc, 0xd8, 0x8a, 0xeb, 0x52, 0x5c, 0x9d, 0x4b, 0x33, 0x0a, 0x65, 0x7b,+    0x2e, 0xfe, 0xb3, 0x2b, 0x18, 0x8c, 0x8e, 0xd0, 0x0e, 0x97, 0xa4, 0x5d, 0x14, 0x9b, 0x51, 0xec, 0xd5, 0xf1, 0x48, 0x66,+    0x8e, 0x73, 0xe3, 0xff, 0x76, 0x3a, 0xfe, 0xd7, 0xd7, 0xab, 0xf8, 0xaf, 0xcf, 0x67, 0xee, 0x8d, 0xff, 0xad, 0xb0, 0x4e,+    0x4b, 0x14, 0x66, 0x5d, 0xf5, 0x2b, 0xc0, 0x5d, 0xfd, 0xfa, 0xed, 0xcf, 0xd3, 0x67, 0xfd, 0xe0, 0x5d, 0xe7, 0x30, 0xeb,+    0x21, 0x99, 0x7e, 0x15, 0x93, 0xa3, 0xe4, 0xef, 0x8d, 0x2b, 0x7d, 0x7e, 0x2b, 0x66, 0x88, 0xaf, 0xe4, 0x2d, 0x3d, 0x7f,+    0xbf, 0x70, 0xfe, 0x2a, 0x52, 0x5d, 0xbf, 0x2b, 0x4e, 0xf7, 0x91, 0x4c, 0x7b, 0xad, 0xed, 0xaf, 0xef, 0xbd, 0x0e, 0xcc,+    0xb3, 0xc6, 0x7e, 0x46, 0x3e, 0xa0, 0xb8, 0xed, 0x5a, 0xfc, 0x96, 0xfa, 0x88, 0x45, 0x77, 0x8e, 0x57, 0x8d, 0xff, 0x6b,+    0x9f, 0xad, 0x66, 0xe3, 0xe8, 0xfb, 0xb2, 0x58, 0xc5, 0x25, 0xd7, 0x92, 0x58, 0x7a, 0xbf, 0x23, 0xfe, 0xc5, 0xff, 0x15,+    0xf1, 0x7f, 0xfc, 0x18, 0xf1, 0xb5, 0xf1, 0xff, 0x44, 0x2f, 0x12, 0xff, 0x67, 0xe6, 0x97, 0x6f, 0x9a, 0x51, 0x5e, 0x1b,+    0xff, 0xeb, 0xc6, 0xb1, 0xca, 0x7d, 0xd7, 0x9b, 0x5a, 0x47, 0xfc, 0xf3, 0x49, 0xed, 0xfc, 0x9e, 0x75, 0x34, 0x00, 0xf1,+    0x0f, 0x5c, 0x33, 0xef, 0x3e, 0xf6, 0x93, 0x7b, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+    0xc0, 0x59, 0xad, 0x9b, 0x59, 0x3c, 0xba, 0x59, 0xcc, 0xff, 0xf9, 0xef, 0xcf, 0x5b, 0x9f, 0x3d, 0x9f, 0x2d, 0x55, 0xb6,+    0x36, 0xcc, 0xf8, 0xde, 0x1e, 0x2e, 0xf5, 0x95, 0x47, 0x68, 0xb7, 0x9d, 0xe1, 0xda, 0x5a, 0xe9, 0xbd, 0x47, 0xdb, 0x6e,+    0xa8, 0xc9, 0x5a, 0x7b, 0xb5, 0xe1, 0xb6, 0x96, 0xee, 0xb3, 0xb5, 0x2d, 0xff, 0xfd, 0x9f, 0xfb, 0xb0, 0x86, 0xf7, 0x64,+    0x5e, 0xde, 0xda, 0x9b, 0xd1, 0xb5, 0x6c, 0x5a, 0x3f, 0x6f, 0xdb, 0xff, 0xfa, 0xdb, 0xdb, 0x96, 0xa9, 0x83, 0x71, 0xee,+    0xfb, 0x95, 0xe7, 0x33, 0x2a, 0xf5, 0x9a, 0x0c, 0xc4, 0x3f, 0x1f, 0x21, 0x06, 0x67, 0x18, 0xa5, 0x6c, 0x66, 0x77, 0xb5,+    0x65, 0x6f, 0x4d, 0x86, 0xbd, 0xb0, 0xda, 0xca, 0x1d, 0xed, 0x15, 0xa5, 0xf5, 0x1b, 0xb6, 0x49, 0xdf, 0xcc, 0xf5, 0xe7,+    0x4c, 0xdd, 0x8f, 0xf2, 0xcd, 0x8e, 0xce, 0xb3, 0x7f, 0xe4, 0xfe, 0x99, 0xec, 0xc9, 0x33, 0xf9, 0xf5, 0xf9, 0x9e, 0xbc,+    0x96, 0xb6, 0xc1, 0x3c, 0xa7, 0xf2, 0xd6, 0xee, 0xca, 0xf3, 0x19, 0x8d, 0xc3, 0xfd, 0x3a, 0xc8, 0x1f, 0xe3, 0x78, 0x5b,+    0x8e, 0xea, 0xf8, 0xf9, 0xb6, 0x1c, 0xf5, 0xcc, 0x48, 0x47, 0x52, 0xbe, 0xcc, 0xfd, 0xbe, 0xde, 0xdb, 0xdb, 0x6c, 0x3d,+    0x9d, 0x67, 0xde, 0x11, 0x9f, 0xc5, 0x7f, 0xa4, 0xe3, 0x7f, 0xbc, 0x0a, 0xcc, 0xf1, 0x4f, 0x47, 0x57, 0xd9, 0x7d, 0x30,+    0x96, 0xf7, 0x6a, 0xb9, 0x0d, 0xeb, 0xbf, 0xf6, 0xd6, 0xfe, 0xaa, 0xf3, 0xa9, 0x1c, 0x67, 0x4f, 0xd7, 0x59, 0x2e, 0x2b,+    0xea, 0x3e, 0x3c, 0x93, 0x67, 0xdb, 0x72, 0xd4, 0x9b, 0xdb, 0x20, 0x4b, 0xff, 0xea, 0xf6, 0x8a, 0xc4, 0xde, 0xaa, 0x6b,+    0xd6, 0x8c, 0xd6, 0xe0, 0xcb, 0x6e, 0xe9, 0x45, 0x79, 0x65, 0xf6, 0x97, 0x9d, 0x13, 0xe7, 0xc7, 0xe5, 0xea, 0x58, 0xbe,+    0xa5, 0xb3, 0x96, 0xcf, 0x56, 0xc9, 0xc8, 0x8c, 0xd8, 0x95, 0x2d, 0x51, 0xb8, 0x37, 0x6c, 0xe9, 0x27, 0x16, 0xa3, 0x9c,+    0xe2, 0x91, 0x1c, 0xe3, 0x9e, 0x6d, 0xcb, 0xd9, 0x68, 0x96, 0x39, 0x9b, 0xca, 0x96, 0xd1, 0xac, 0xa9, 0xff, 0x9d, 0xfc,+    0xca, 0x98, 0x67, 0x56, 0xe7, 0x6b, 0x97, 0xcd, 0xff, 0xe7, 0x39, 0xb6, 0xd7, 0x8c, 0xcb, 0xd5, 0xb1, 0x7c, 0x2b, 0xac,+    0x5a, 0x10, 0x97, 0xdf, 0x31, 0x56, 0x57, 0x47, 0xdb, 0xbb, 0xf7, 0xc6, 0xb9, 0xcf, 0xab, 0x6b, 0x1f, 0xc4, 0x0b, 0xdb,+    0x32, 0x1f, 0xff, 0xd7, 0xac, 0x73, 0xb1, 0x76, 0x6d, 0xbc, 0x76, 0x5b, 0x9f, 0x3a, 0x3e, 0xca, 0xaf, 0x5e, 0xe5, 0xee,+    0xfa, 0x5a, 0xae, 0xe5, 0xf2, 0x7f, 0x3a, 0xfe, 0x63, 0xe1, 0x8a, 0x02, 0xab, 0xe2, 0xbf, 0xbd, 0x24, 0x62, 0xfe, 0x94,+    0xf8, 0xcf, 0xad, 0xc2, 0x11, 0xa5, 0x95, 0x3b, 0x32, 0x31, 0x9e, 0x7f, 0x96, 0xff, 0x9e, 0x5a, 0xfe, 0x9e, 0xf1, 0xff,+    0xb9, 0xf8, 0x8f, 0x0f, 0x8c, 0xff, 0xf7, 0x96, 0xf9, 0xf9, 0xb1, 0xf1, 0xd9, 0xf8, 0xaf, 0x8c, 0xcb, 0xf5, 0x75, 0x79,+    0xd6, 0xc6, 0x7f, 0x24, 0x46, 0xec, 0xf5, 0x99, 0xb8, 0x9f, 0x8a, 0xff, 0xf7, 0x8e, 0xa5, 0xb3, 0xba, 0x7a, 0xb2, 0x64,+    0xb3, 0x55, 0xe6, 0xdf, 0x15, 0xff, 0xd5, 0x15, 0x55, 0x23, 0x39, 0x93, 0x7d, 0xff, 0xf8, 0x1f, 0xa9, 0x35, 0xf7, 0xbe,+    0x67, 0xfc, 0x8f, 0xc9, 0xda, 0xbc, 0x9f, 0x37, 0xff, 0x8f, 0x47, 0x63, 0x2c, 0x4a, 0x2b, 0xc9, 0x66, 0x57, 0xda, 0x5b,+    0x35, 0xff, 0xbf, 0xf3, 0xe7, 0x8c, 0x9f, 0x36, 0x9b, 0x3c, 0xf7, 0xa4, 0xe3, 0x33, 0xe2, 0x7f, 0x3e, 0x92, 0x7e, 0x5e,+    0x8b, 0x3d, 0x3d, 0xc6, 0xca, 0xf6, 0xfc, 0x4d, 0xf1, 0xbf, 0xdd, 0x32, 0xfe, 0x57, 0x57, 0x3a, 0xcd, 0xfe, 0xfe, 0xd9,+    0x27, 0xc5, 0xff, 0xca, 0x95, 0x87, 0xee, 0x2c, 0x99, 0xf8, 0x7f, 0xdb, 0x3d, 0xce, 0x8a, 0x92, 0xdf, 0xf5, 0x13, 0x99,+    0xbb, 0xc7, 0xf9, 0xf7, 0x5e, 0xb1, 0xdf, 0xdb, 0xff, 0xaa, 0xbf, 0xe7, 0x2e, 0xfe, 0x3f, 0x2f, 0xfe, 0xb3, 0x23, 0x76,+    0x65, 0xcb, 0xfc, 0x48, 0xe7, 0x3f, 0x5f, 0xd7, 0x62, 0xeb, 0x9f, 0x7e, 0xde, 0x71, 0xb7, 0x7a, 0x5f, 0xc9, 0xc4, 0x3f,+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xad, 0x36, 0xcc, 0xe4, 0x9f, 0xcd, 0x4a, 0x3e, 0xca, 0x0c,+    0x18, 0xb7, 0xe4, 0x38, 0xaf, 0xe6, 0xff, 0x3f, 0xfe, 0x79, 0xbe, 0xc6, 0x2a, 0x65, 0x5a, 0x7b, 0xee, 0x6d, 0xd2, 0x66,+    0x3f, 0x7f, 0xde, 0x0a, 0xab, 0x3c, 0xdc, 0xd1, 0x62, 0xad, 0xd4, 0x9f, 0xf9, 0xa9, 0xb6, 0xf6, 0x85, 0xb5, 0x35, 0x5b,+    0x33, 0xe0, 0x99, 0x1c, 0xe7, 0xb3, 0xe3, 0xb4, 0x45, 0xc7, 0x18, 0x67, 0xb8, 0xce, 0x95, 0xa9, 0x72, 0xee, 0xeb, 0xdb,+    0xb2, 0x5f, 0x8a, 0x7b, 0x5a, 0xac, 0xf9, 0x0d, 0xfb, 0x47, 0xdf, 0xd9, 0xa9, 0x64, 0x18, 0x8e, 0x64, 0xf6, 0xa3, 0xfb,+    0x4a, 0xbd, 0xee, 0x08, 0xfd, 0xab, 0xd8, 0xfe, 0xd2, 0xb1, 0x67, 0x9c, 0x7b, 0x76, 0x94, 0x15, 0xb1, 0xdd, 0xf4, 0x66,+    0x58, 0x4b, 0xbf, 0xcb, 0xd3, 0x16, 0xed, 0x4d, 0x94, 0xaf, 0xca, 0x3d, 0xbc, 0x4d, 0xf3, 0x72, 0xad, 0xba, 0xce, 0xe4,+    0x4b, 0xbd, 0x0d, 0xf6, 0x95, 0xfb, 0x7c, 0x4b, 0xe6, 0x6a, 0x89, 0xc5, 0x59, 0xdc, 0xd7, 0xd6, 0xca, 0x36, 0xb9, 0x8e,+    0x47, 0x22, 0xc6, 0xce, 0x6c, 0xc9, 0x1f, 0xe7, 0x6d, 0x6b, 0x69, 0x7c, 0xee, 0x7b, 0xb9, 0xfb, 0xa2, 0xdc, 0xc3, 0xf5,+    0x4c, 0x9a, 0xab, 0x72, 0x9c, 0xd7, 0x32, 0xb3, 0xac, 0xcb, 0xa4, 0xb7, 0x77, 0xfb, 0xf1, 0xda, 0x33, 0xbc, 0xbe, 0x56,+    0x3e, 0x21, 0x97, 0xee, 0x1b, 0xdf, 0x0c, 0xff, 0xec, 0xf7, 0xf3, 0x8f, 0x8c, 0x67, 0xdb, 0x74, 0xce, 0xf8, 0x64, 0xfb,+    0x5f, 0x9f, 0x49, 0x67, 0xfb, 0xc8, 0x0c, 0x87, 0x5b, 0x39, 0x03, 0x98, 0xf8, 0xff, 0xf6, 0xf9, 0x7f, 0xdc, 0x90, 0x17,+    0x69, 0x76, 0x2d, 0x59, 0x9b, 0xff, 0x77, 0x13, 0xff, 0x27, 0xa3, 0xe2, 0xf9, 0x5c, 0x9a, 0xf3, 0xab, 0xfc, 0x26, 0xfe,+    0x17, 0x8d, 0xfb, 0xdf, 0x96, 0x49, 0xd3, 0xf8, 0x7f, 0x5d, 0x54, 0x7c, 0xea, 0x5a, 0x1a, 0x6c, 0x85, 0xb1, 0x7c, 0x65,+    0x86, 0xe1, 0xb8, 0xe1, 0x0a, 0x54, 0xc9, 0xcc, 0x98, 0xff, 0xfc, 0xd3, 0xa2, 0x7c, 0x65, 0x8e, 0xad, 0x6b, 0xca, 0xb6,+    0x26, 0xfe, 0xdf, 0x99, 0xfd, 0xfa, 0x13, 0xe7, 0xff, 0xf7, 0x3c, 0x63, 0xd8, 0x6e, 0xce, 0xcc, 0x16, 0x4b, 0x3e, 0xdf,+    0x92, 0x77, 0x38, 0x2b, 0xef, 0x97, 0x9e, 0xcf, 0xa4, 0x77, 0x5f, 0x56, 0xfa, 0xda, 0x5d, 0x9e, 0xf1, 0x1f, 0xbe, 0xfb,+    0xd9, 0xb4, 0xf8, 0x07, 0xf1, 0x6f, 0xf6, 0x0f, 0xee, 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xc7, 0xaf, 0x3f, 0xea, 0x01, 0xc4, 0x3f, 0xf0, 0xc7,+    0xc5, 0xff, 0xff, 0x00 };++// Font glyphs rectangles data (on atlas)+static const Rectangle amberFontRecs[189] = {+    { 4, 4, 5 , 16 },+    { 17, 4, 2 , 10 },+    { 27, 4, 4 , 4 },+    { 39, 4, 5 , 10 },+    { 52, 4, 5 , 11 },+    { 65, 4, 5 , 10 },+    { 78, 4, 5 , 10 },+    { 91, 4, 2 , 4 },+    { 101, 4, 4 , 13 },+    { 113, 4, 5 , 13 },+    { 126, 4, 4 , 4 },+    { 138, 4, 5 , 6 },+    { 151, 4, 3 , 2 },+    { 162, 4, 5 , 2 },+    { 175, 4, 2 , 1 },+    { 185, 4, 5 , 10 },+    { 198, 4, 5 , 10 },+    { 211, 4, 4 , 10 },+    { 223, 4, 5 , 10 },+    { 236, 4, 5 , 10 },+    { 249, 4, 5 , 10 },+    { 262, 4, 5 , 10 },+    { 275, 4, 5 , 10 },+    { 288, 4, 5 , 10 },+    { 301, 4, 5 , 10 },+    { 314, 4, 5 , 10 },+    { 327, 4, 2 , 6 },+    { 337, 4, 2 , 6 },+    { 347, 4, 5 , 6 },+    { 360, 4, 5 , 4 },+    { 373, 4, 5 , 6 },+    { 386, 4, 5 , 10 },+    { 399, 4, 5 , 7 },+    { 412, 4, 5 , 10 },+    { 425, 4, 5 , 10 },+    { 438, 4, 5 , 10 },+    { 451, 4, 5 , 10 },+    { 464, 4, 5 , 10 },+    { 477, 4, 5 , 10 },+    { 490, 4, 5 , 10 },+    { 4, 28, 5 , 10 },+    { 17, 28, 4 , 10 },+    { 29, 28, 5 , 10 },+    { 42, 28, 5 , 10 },+    { 55, 28, 5 , 10 },+    { 68, 28, 5 , 10 },+    { 81, 28, 5 , 10 },+    { 94, 28, 5 , 10 },+    { 107, 28, 5 , 10 },+    { 120, 28, 5 , 10 },+    { 133, 28, 5 , 10 },+    { 146, 28, 5 , 10 },+    { 159, 28, 5 , 10 },+    { 172, 28, 5 , 10 },+    { 185, 28, 5 , 10 },+    { 198, 28, 5 , 10 },+    { 211, 28, 5 , 10 },+    { 224, 28, 5 , 10 },+    { 237, 28, 5 , 10 },+    { 250, 28, 3 , 13 },+    { 261, 28, 5 , 10 },+    { 274, 28, 3 , 13 },+    { 285, 28, 4 , 3 },+    { 297, 28, 5 , 1 },+    { 310, 28, 3 , 3 },+    { 321, 28, 5 , 7 },+    { 334, 28, 5 , 10 },+    { 347, 28, 5 , 7 },+    { 360, 28, 5 , 10 },+    { 373, 28, 5 , 7 },+    { 386, 28, 5 , 10 },+    { 399, 28, 5 , 10 },+    { 412, 28, 5 , 10 },+    { 425, 28, 4 , 10 },+    { 437, 28, 3 , 13 },+    { 448, 28, 5 , 10 },+    { 461, 28, 5 , 10 },+    { 474, 28, 5 , 7 },+    { 487, 28, 5 , 7 },+    { 4, 52, 5 , 7 },+    { 17, 52, 5 , 10 },+    { 30, 52, 5 , 10 },+    { 43, 52, 5 , 7 },+    { 56, 52, 5 , 7 },+    { 69, 52, 5 , 10 },+    { 82, 52, 5 , 7 },+    { 95, 52, 5 , 7 },+    { 108, 52, 5 , 7 },+    { 121, 52, 5 , 7 },+    { 134, 52, 5 , 10 },+    { 147, 52, 5 , 7 },+    { 160, 52, 4 , 13 },+    { 172, 52, 2 , 13 },+    { 182, 52, 4 , 13 },+    { 194, 52, 5 , 4 },+    { 207, 52, 2 , 9 },+    { 217, 52, 5 , 7 },+    { 230, 52, 5 , 10 },+    { 243, 52, 5 , 10 },+    { 256, 52, 5 , 10 },+    { 269, 52, 0 , 0 },+    { 277, 52, 5 , 10 },+    { 290, 52, 0 , 0 },+    { 298, 52, 5 , 7 },+    { 311, 52, 3 , 5 },+    { 322, 52, 5 , 5 },+    { 335, 52, 5 , 3 },+    { 348, 52, 5 , 7 },+    { 361, 52, 5 , 2 },+    { 374, 52, 4 , 4 },+    { 386, 52, 5 , 8 },+    { 399, 52, 3 , 5 },+    { 410, 52, 3 , 6 },+    { 421, 52, 0 , 0 },+    { 429, 52, 5 , 10 },+    { 442, 52, 5 , 10 },+    { 455, 52, 2 , 3 },+    { 465, 52, 0 , 0 },+    { 473, 52, 3 , 5 },+    { 484, 52, 4 , 4 },+    { 496, 52, 5 , 5 },+    { 4, 76, 5 , 10 },+    { 17, 76, 5 , 7 },+    { 30, 76, 5 , 10 },+    { 43, 76, 5 , 10 },+    { 56, 76, 5 , 14 },+    { 69, 76, 5 , 14 },+    { 82, 76, 5 , 14 },+    { 95, 76, 5 , 14 },+    { 108, 76, 5 , 12 },+    { 121, 76, 5 , 12 },+    { 134, 76, 5 , 10 },+    { 147, 76, 5 , 13 },+    { 160, 76, 5 , 14 },+    { 173, 76, 5 , 14 },+    { 186, 76, 5 , 14 },+    { 199, 76, 5 , 12 },+    { 212, 76, 4 , 14 },+    { 224, 76, 4 , 14 },+    { 236, 76, 4 , 14 },+    { 248, 76, 4 , 12 },+    { 260, 76, 5 , 10 },+    { 273, 76, 5 , 14 },+    { 286, 76, 5 , 14 },+    { 299, 76, 5 , 14 },+    { 312, 76, 5 , 14 },+    { 325, 76, 5 , 14 },+    { 338, 76, 5 , 12 },+    { 351, 76, 4 , 3 },+    { 363, 76, 5 , 10 },+    { 376, 76, 5 , 14 },+    { 389, 76, 5 , 14 },+    { 402, 76, 5 , 14 },+    { 415, 76, 5 , 12 },+    { 428, 76, 5 , 14 },+    { 441, 76, 5 , 10 },+    { 454, 76, 5 , 10 },+    { 467, 76, 5 , 10 },+    { 480, 76, 5 , 10 },+    { 493, 76, 5 , 10 },+    { 4, 100, 5 , 10 },+    { 17, 100, 5 , 9 },+    { 30, 100, 5 , 9 },+    { 43, 100, 5 , 7 },+    { 56, 100, 5 , 10 },+    { 69, 100, 5 , 10 },+    { 82, 100, 5 , 10 },+    { 95, 100, 5 , 10 },+    { 108, 100, 5 , 9 },+    { 121, 100, 4 , 10 },+    { 133, 100, 4 , 10 },+    { 145, 100, 4 , 10 },+    { 157, 100, 4 , 9 },+    { 169, 100, 5 , 10 },+    { 182, 100, 5 , 10 },+    { 195, 100, 5 , 10 },+    { 208, 100, 5 , 10 },+    { 221, 100, 5 , 10 },+    { 234, 100, 5 , 10 },+    { 247, 100, 5 , 9 },+    { 260, 100, 5 , 6 },+    { 273, 100, 5 , 7 },+    { 286, 100, 5 , 10 },+    { 299, 100, 5 , 10 },+    { 312, 100, 5 , 10 },+    { 325, 100, 5 , 9 },+    { 338, 100, 5 , 13 },+    { 351, 100, 5 , 10 },+    { 364, 100, 5 , 12 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo amberFontGlyphs[189] = {+    { 32, 0, 0, 5, { 0 }},+    { 33, 1, 3, 5, { 0 }},+    { 34, 0, 3, 5, { 0 }},+    { 35, 0, 3, 5, { 0 }},+    { 36, 0, 3, 5, { 0 }},+    { 37, 0, 3, 5, { 0 }},+    { 38, 0, 3, 5, { 0 }},+    { 39, 1, 4, 5, { 0 }},+    { 40, 0, 3, 5, { 0 }},+    { 41, 0, 3, 5, { 0 }},+    { 42, 0, 3, 5, { 0 }},+    { 43, 0, 7, 5, { 0 }},+    { 44, 0, 12, 5, { 0 }},+    { 45, 0, 9, 5, { 0 }},+    { 46, 1, 12, 5, { 0 }},+    { 47, 0, 3, 5, { 0 }},+    { 48, 0, 3, 5, { 0 }},+    { 49, 0, 3, 5, { 0 }},+    { 50, 0, 3, 5, { 0 }},+    { 51, 0, 3, 5, { 0 }},+    { 52, 0, 3, 5, { 0 }},+    { 53, 0, 3, 5, { 0 }},+    { 54, 0, 3, 5, { 0 }},+    { 55, 0, 3, 5, { 0 }},+    { 56, 0, 3, 5, { 0 }},+    { 57, 0, 3, 5, { 0 }},+    { 58, 0, 7, 5, { 0 }},+    { 59, 0, 7, 5, { 0 }},+    { 60, 0, 7, 5, { 0 }},+    { 61, 0, 8, 5, { 0 }},+    { 62, 0, 7, 5, { 0 }},+    { 63, 0, 3, 5, { 0 }},+    { 64, 0, 6, 5, { 0 }},+    { 65, 0, 3, 5, { 0 }},+    { 66, 0, 3, 5, { 0 }},+    { 67, 0, 3, 5, { 0 }},+    { 68, 0, 3, 5, { 0 }},+    { 69, 0, 3, 5, { 0 }},+    { 70, 0, 3, 5, { 0 }},+    { 71, 0, 3, 5, { 0 }},+    { 72, 0, 3, 5, { 0 }},+    { 73, 0, 3, 5, { 0 }},+    { 74, 0, 3, 5, { 0 }},+    { 75, 0, 3, 5, { 0 }},+    { 76, 0, 3, 5, { 0 }},+    { 77, 0, 3, 5, { 0 }},+    { 78, 0, 3, 5, { 0 }},+    { 79, 0, 3, 5, { 0 }},+    { 80, 0, 3, 5, { 0 }},+    { 81, 0, 3, 5, { 0 }},+    { 82, 0, 3, 5, { 0 }},+    { 83, 0, 3, 5, { 0 }},+    { 84, 0, 3, 5, { 0 }},+    { 85, 0, 3, 5, { 0 }},+    { 86, 0, 3, 5, { 0 }},+    { 87, 0, 3, 5, { 0 }},+    { 88, 0, 3, 5, { 0 }},+    { 89, 0, 3, 5, { 0 }},+    { 90, 0, 3, 5, { 0 }},+    { 91, 0, 3, 5, { 0 }},+    { 92, 0, 3, 5, { 0 }},+    { 93, 0, 3, 5, { 0 }},+    { 94, 0, 3, 5, { 0 }},+    { 95, 0, 12, 5, { 0 }},+    { 96, 1, 4, 5, { 0 }},+    { 97, 0, 6, 5, { 0 }},+    { 98, 0, 3, 5, { 0 }},+    { 99, 0, 6, 5, { 0 }},+    { 100, 0, 3, 5, { 0 }},+    { 101, 0, 6, 5, { 0 }},+    { 102, 0, 3, 5, { 0 }},+    { 103, 0, 6, 5, { 0 }},+    { 104, 0, 3, 5, { 0 }},+    { 105, 0, 3, 5, { 0 }},+    { 106, 0, 3, 5, { 0 }},+    { 107, 0, 3, 5, { 0 }},+    { 108, 0, 3, 5, { 0 }},+    { 109, 0, 6, 5, { 0 }},+    { 110, 0, 6, 5, { 0 }},+    { 111, 0, 6, 5, { 0 }},+    { 112, 0, 6, 5, { 0 }},+    { 113, 0, 6, 5, { 0 }},+    { 114, 0, 6, 5, { 0 }},+    { 115, 0, 6, 5, { 0 }},+    { 116, 0, 3, 5, { 0 }},+    { 117, 0, 6, 5, { 0 }},+    { 118, 0, 6, 5, { 0 }},+    { 119, 0, 6, 5, { 0 }},+    { 120, 0, 6, 5, { 0 }},+    { 121, 0, 6, 5, { 0 }},+    { 122, 0, 6, 5, { 0 }},+    { 123, 0, 3, 5, { 0 }},+    { 124, 1, 3, 5, { 0 }},+    { 125, 0, 3, 5, { 0 }},+    { 126, 0, 8, 5, { 0 }},+    { 161, 1, 4, 5, { 0 }},+    { 162, 0, 6, 5, { 0 }},+    { 163, 0, 3, 5, { 0 }},+    { 8364, 0, 3, 5, { 0 }},+    { 165, 0, 3, 5, { 0 }},+    { 352, 0, 0, 0, { 0 }},+    { 167, 0, 3, 5, { 0 }},+    { 353, 0, 0, 0, { 0 }},+    { 169, 0, 6, 5, { 0 }},+    { 170, 2, 3, 5, { 0 }},+    { 171, 0, 8, 5, { 0 }},+    { 172, 0, 6, 5, { 0 }},+    { 174, 0, 6, 5, { 0 }},+    { 175, 0, 3, 5, { 0 }},+    { 176, 1, 3, 5, { 0 }},+    { 177, 0, 5, 5, { 0 }},+    { 178, 2, 3, 5, { 0 }},+    { 179, 2, 3, 5, { 0 }},+    { 381, 0, 0, 0, { 0 }},+    { 181, 0, 6, 5, { 0 }},+    { 182, 0, 3, 5, { 0 }},+    { 183, 1, 6, 5, { 0 }},+    { 382, 0, 0, 0, { 0 }},+    { 185, 0, 3, 5, { 0 }},+    { 186, 0, 3, 5, { 0 }},+    { 187, 0, 8, 5, { 0 }},+    { 338, 0, 3, 5, { 0 }},+    { 339, 0, 6, 5, { 0 }},+    { 376, 0, 3, 5, { 0 }},+    { 191, 0, 3, 5, { 0 }},+    { 192, 0, -1, 5, { 0 }},+    { 193, 0, -1, 5, { 0 }},+    { 194, 0, -1, 5, { 0 }},+    { 195, 0, -1, 5, { 0 }},+    { 196, 0, 1, 5, { 0 }},+    { 197, 0, 1, 5, { 0 }},+    { 198, 0, 3, 5, { 0 }},+    { 199, 0, 3, 5, { 0 }},+    { 200, 0, -1, 5, { 0 }},+    { 201, 0, -1, 5, { 0 }},+    { 202, 0, -1, 5, { 0 }},+    { 203, 0, 1, 5, { 0 }},+    { 204, 0, -1, 5, { 0 }},+    { 205, 0, -1, 5, { 0 }},+    { 206, 0, -1, 5, { 0 }},+    { 207, 0, 1, 5, { 0 }},+    { 208, 0, 3, 5, { 0 }},+    { 209, 0, -1, 5, { 0 }},+    { 210, 0, -1, 5, { 0 }},+    { 211, 0, -1, 5, { 0 }},+    { 212, 0, -1, 5, { 0 }},+    { 213, 0, -1, 5, { 0 }},+    { 214, 0, 1, 5, { 0 }},+    { 215, 0, 10, 5, { 0 }},+    { 216, 0, 3, 5, { 0 }},+    { 217, 0, -1, 5, { 0 }},+    { 218, 0, -1, 5, { 0 }},+    { 219, 0, -1, 5, { 0 }},+    { 220, 0, 1, 5, { 0 }},+    { 221, 0, -1, 5, { 0 }},+    { 222, 0, 3, 5, { 0 }},+    { 223, 0, 3, 5, { 0 }},+    { 224, 0, 3, 5, { 0 }},+    { 225, 0, 3, 5, { 0 }},+    { 226, 0, 3, 5, { 0 }},+    { 227, 0, 3, 5, { 0 }},+    { 228, 0, 4, 5, { 0 }},+    { 229, 0, 4, 5, { 0 }},+    { 230, 0, 6, 5, { 0 }},+    { 231, 0, 6, 5, { 0 }},+    { 232, 0, 3, 5, { 0 }},+    { 233, 0, 3, 5, { 0 }},+    { 234, 0, 3, 5, { 0 }},+    { 235, 0, 4, 5, { 0 }},+    { 236, 0, 3, 5, { 0 }},+    { 237, 0, 3, 5, { 0 }},+    { 238, 0, 3, 5, { 0 }},+    { 239, 0, 4, 5, { 0 }},+    { 240, 0, 3, 5, { 0 }},+    { 241, 0, 3, 5, { 0 }},+    { 242, 0, 3, 5, { 0 }},+    { 243, 0, 3, 5, { 0 }},+    { 244, 0, 3, 5, { 0 }},+    { 245, 0, 3, 5, { 0 }},+    { 246, 0, 4, 5, { 0 }},+    { 247, 0, 7, 5, { 0 }},+    { 248, 0, 6, 5, { 0 }},+    { 249, 0, 3, 5, { 0 }},+    { 250, 0, 3, 5, { 0 }},+    { 251, 0, 3, 5, { 0 }},+    { 252, 0, 4, 5, { 0 }},+    { 253, 0, 3, 5, { 0 }},+    { 254, 0, 3, 5, { 0 }},+    { 255, 0, 4, 5, { 0 }},+};++// Style loading function: Amber+static void GuiLoadStyleAmber(void)+{+    // Load style properties provided+    // NOTE: Default properties are propagated+    for (int i = 0; i < AMBER_STYLE_PROPS_COUNT; i++)+    {+        GuiSetStyle(amberStyleProps[i].controlId, amberStyleProps[i].propertyId, amberStyleProps[i].propertyValue);+    }++    // Custom font loading+    // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+    int amberFontDataSize = 0;+    unsigned char *data = DecompressData(amberFontData, AMBER_STYLE_FONT_ATLAS_COMP_SIZE, &amberFontDataSize);+    Image imFont = { data, 512, 256, 1, 2 };++    Font font = { 0 };+    font.baseSize = 16;+    font.glyphCount = 189;++    // Load texture from image+    font.texture = LoadTextureFromImage(imFont);+    UnloadImage(imFont);  // Uncompressed image data can be unloaded from memory++    // Copy char recs data from global fontRecs+    // NOTE: Required to avoid issues if trying to free font+    font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+    memcpy(font.recs, amberFontRecs, font.glyphCount*sizeof(Rectangle));++    // Copy font char info data from global fontChars+    // NOTE: Required to avoid issues if trying to free font+    font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+    memcpy(font.glyphs, amberFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++    GuiSetFont(font);++    // Setup a white rectangle on the font to be used on shapes drawing,+    // it makes possible to draw shapes and text (full UI) in a single draw call+    Rectangle fontWhiteRec = { 510, 254, 1, 1 };     SetShapesTexture(font.texture, fontWhiteRec);      //-----------------------------------------------------------------
raylib/examples/audio/audio_mixed_processor.c view
@@ -97,7 +97,7 @@             DrawRectangle(199, 199, 402, 34, LIGHTGRAY);             for (int i = 0; i < 400; i++)             {-                DrawLine(201 + i, 232 - (int)averageVolume[i] * 32, 201 + i, 232, MAROON);+                DrawLine(201 + i, 232 - (int)(averageVolume[i] * 32), 201 + i, 232, MAROON);             }             DrawRectangleLines(199, 199, 402, 34, GRAY); 
raylib/examples/core/core_automation_events.c view
@@ -88,7 +88,7 @@         // Update         //----------------------------------------------------------------------------------         float deltaTime = 0.015f;//GetFrameTime();-        +                // Dropped files logic         //----------------------------------------------------------------------------------         if (IsFileDropped())@@ -157,11 +157,6 @@         }         else player.canJump = true; -        camera.zoom += ((float)GetMouseWheelMove()*0.05f);--        if (camera.zoom > 3.0f) camera.zoom = 3.0f;-        else if (camera.zoom < 0.25f) camera.zoom = 0.25f;-         if (IsKeyPressed(KEY_R))         {             // Reset game state@@ -176,12 +171,44 @@         }         //---------------------------------------------------------------------------------- +        // Events playing+        // NOTE: Logic must be before Camera update because it depends on mouse-wheel value, +        // that can be set by the played event... but some other inputs could be affected+        //----------------------------------------------------------------------------------+        if (eventPlaying)+        {+            // NOTE: Multiple events could be executed in a single frame+            while (playFrameCounter == aelist.events[currentPlayFrame].frame)+            {+                PlayAutomationEvent(aelist.events[currentPlayFrame]);+                currentPlayFrame++;++                if (currentPlayFrame == aelist.count)+                {+                    eventPlaying = false;+                    currentPlayFrame = 0;+                    playFrameCounter = 0;++                    TraceLog(LOG_INFO, "FINISH PLAYING!");+                    break;+                }+            }++            playFrameCounter++;+        }+        //----------------------------------------------------------------------------------+         // Update camera         //----------------------------------------------------------------------------------         camera.target = player.position;         camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };         float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000; +        // WARNING: On event replay, mouse-wheel internal value is set+        camera.zoom += ((float)GetMouseWheelMove()*0.05f);+        if (camera.zoom > 3.0f) camera.zoom = 3.0f;+        else if (camera.zoom < 0.25f) camera.zoom = 0.25f;+         for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)         {             EnvElement *element = &envElements[i];@@ -200,8 +227,8 @@         if (min.y > 0) camera.offset.y = screenHeight/2 - min.y;         //----------------------------------------------------------------------------------         -        // Toggle events recording-        if (IsKeyPressed(KEY_S))+        // Events management+        if (IsKeyPressed(KEY_S))    // Toggle events recording         {             if (!eventPlaying)             {@@ -222,7 +249,7 @@                 }             }         }-        else if (IsKeyPressed(KEY_A))+        else if (IsKeyPressed(KEY_A)) // Toggle events playing (WARNING: Starts next frame)         {             if (!eventRecording && (aelist.count > 0))             {@@ -241,32 +268,7 @@                 camera.zoom = 1.0f;             }         }-        -        if (eventPlaying)-        {-            // NOTE: Multiple events could be executed in a single frame-            while (playFrameCounter == aelist.events[currentPlayFrame].frame)-            {-                TraceLog(LOG_INFO, "PLAYING: PlayFrameCount: %i | currentPlayFrame: %i | Event Frame: %i, param: %i", -                    playFrameCounter, currentPlayFrame, aelist.events[currentPlayFrame].frame, aelist.events[currentPlayFrame].params[0]);-                -                PlayAutomationEvent(aelist.events[currentPlayFrame]);-                currentPlayFrame++; -                if (currentPlayFrame == aelist.count)-                {-                    eventPlaying = false;-                    currentPlayFrame = 0;-                    playFrameCounter = 0;--                    TraceLog(LOG_INFO, "FINISH PLAYING!");-                    break;-                }-            }-            -            playFrameCounter++;-        }-                 if (eventRecording || eventPlaying) frameCounter++;         else frameCounter = 0;         //----------------------------------------------------------------------------------
raylib/examples/core/core_input_gamepad_info.c view
@@ -47,25 +47,25 @@              ClearBackground(RAYWHITE); -            for (int i = 0, y = 10; i < 4; i++)     // MAX_GAMEPADS = 4+            for (int i = 0, y = 5; i < 4; i++)     // MAX_GAMEPADS = 4             {                 if (IsGamepadAvailable(i))                 {-                    DrawText(TextFormat("Gamepad name: %s", GetGamepadName(i)), 10, y, 20, BLACK);-                    y += 30;-                    DrawText(TextFormat("\tAxis count:   %d", GetGamepadAxisCount(i)), 10, y, 20, BLACK);-                    y += 30;+                    DrawText(TextFormat("Gamepad name: %s", GetGamepadName(i)), 10, y, 10, BLACK);+                    y += 11;+                    DrawText(TextFormat("\tAxis count:   %d", GetGamepadAxisCount(i)), 10, y, 10, BLACK);+                    y += 11;                      for (int axis = 0; axis < GetGamepadAxisCount(i); axis++)                     {-                        DrawText(TextFormat("\tAxis %d = %f", axis, GetGamepadAxisMovement(i, axis)), 10, y, 20, BLACK);-                        y += 30;+                        DrawText(TextFormat("\tAxis %d = %f", axis, GetGamepadAxisMovement(i, axis)), 10, y, 10, BLACK);+                        y += 11;                     }                      for (int button = 0; button < 32; button++)                     {-                        DrawText(TextFormat("\tButton %d = %d", button, IsGamepadButtonDown(i, button)), 10, y, 20, BLACK);-                        y += 30;+                        DrawText(TextFormat("\tButton %d = %d", button, IsGamepadButtonDown(i, button)), 10, y, 10, BLACK);+                        y += 11;                     }                 }             }
+ raylib/examples/core/core_input_virtual_controls.c view
@@ -0,0 +1,123 @@+/*******************************************************************************************+*+*   raylib [core] example - input virtual controls+*+*   Example originally created with raylib 5.0, last time updated with raylib 5.0+*+*   Example create by GreenSnakeLinux (@GreenSnakeLinux),+*   lighter by oblerion (@oblerion) and +*   reviewed by Ramon Santamaria (@raysan5)+*+*   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) 2024 Ramon Santamaria (@raysan5)+*+********************************************************************************************/++#include "raylib.h"+#include <math.h>+//------------------------------------------------------------------------------------+// Program main entry point+//------------------------------------------------------------------------------------+int main(void)+{+    // Initialization+    //--------------------------------------------------------------------------------------+    const int screenWidth = 800;+    const int screenHeight = 450;++    InitWindow(screenWidth, screenHeight, "raylib [core] example - input virtual controls");++    const int dpadX = 90;+    const int dpadY = 300;+    const int dpadRad = 25;//radius of each pad+    Color dpadColor = BLUE;+    int dpadKeydown = -1;//-1 if not down, else 0,1,2,3 ++    +    const float dpadCollider[4][2]= // collider array with x,y position+    {+        {dpadX,dpadY-dpadRad*1.5},//up+        {dpadX-dpadRad*1.5,dpadY},//left+        {dpadX+dpadRad*1.5,dpadY},//right+        {dpadX,dpadY+dpadRad*1.5}//down+    };+    const char dpadLabel[4]="XYBA";//label of Dpad++    float playerX=100;+    float playerY=100;++    SetTargetFPS(60);+    //--------------------------------------------------------------------------------------++    // Main game loop+    while (!WindowShouldClose())    // Detect window close button or ESC key+    {+	// Update +	//--------------------------------------------------------------------------+        dpadKeydown = -1; //reset+        float inputX=0;+        float inputY=0;+        if(GetTouchPointCount()>0)+        {//use touch pos+            inputX = GetTouchX();+            inputY = GetTouchY();+        }+        else+        {//use mouse pos+            inputX = GetMouseX();+            inputY = GetMouseY();+        }+        for(int i=0;i<4;i++)+        {+            //test distance each collider and input < radius+            if( fabsf(dpadCollider[i][1]-inputY) + fabsf(dpadCollider[i][0]-inputX) < dpadRad)+            {+                dpadKeydown = i;+                break;+            }+        }+        // move player+        switch(dpadKeydown){+            case 0: playerY -= 50*GetFrameTime();+            break;+            case 1: playerX -= 50*GetFrameTime();+            break;+            case 2: playerX += 50*GetFrameTime();+            break;+            case 3: playerY += 50*GetFrameTime();+            default:;+        };+	//--------------------------------------------------------------------------+	    +	// Draw +	//--------------------------------------------------------------------------+       BeginDrawing();+            ClearBackground(RAYWHITE);+            for(int i=0;i<4;i++)+            {+                //draw all pad+                DrawCircle(dpadCollider[i][0],dpadCollider[i][1],dpadRad,dpadColor);+                if(i!=dpadKeydown)+                {+                    //draw label+                    DrawText(TextSubtext(dpadLabel,i,1),+                             dpadCollider[i][0]-5,+                             dpadCollider[i][1]-5,16,BLACK);+                }++            }+            DrawText("Player",playerX,playerY,16,BLACK);+        EndDrawing();+	//--------------------------------------------------------------------------+    }++    // De-Initialization+    //--------------------------------------------------------------------------------------+    CloseWindow();        // Close window and OpenGL context+    //--------------------------------------------------------------------------------------++    return 0;+}+
raylib/examples/core/core_vr_simulator.c view
@@ -100,7 +100,7 @@      DisableCursor();                    // Limit cursor to relative movement inside the window -    SetTargetFPS(90);                   // Set our game to run at 90 frames-per-second+    SetTargetFPS(60);                   // Set our game to run at 60 frames-per-second     //--------------------------------------------------------------------------------------      // Main game loop
raylib/examples/models/models_box_collisions.c view
@@ -109,7 +109,7 @@              EndMode3D(); -            DrawText("Move player with cursors to collide", 220, 40, 20, GRAY);+            DrawText("Move player with arrow keys to collide", 220, 40, 20, GRAY);              DrawFPS(10, 10); 
+ raylib/examples/models/models_gpu_skinning.c view
@@ -0,0 +1,119 @@+/*******************************************************************************************
+*
+*   raylib [core] example - Doing skinning on the gpu using a vertex shader
+* 
+*   Example originally created with raylib 4.5, last time updated with raylib 4.5
+*
+*   Example contributed by Daniel Holden (@orangeduck) and reviewed by Ramon Santamaria (@raysan5)
+*
+*   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) 2024 Daniel Holden (@orangeduck)
+* 
+*   Note: Due to limitations in the Apple OpenGL driver, this feature does not work on MacOS
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include "raymath.h"
+
+#if defined(PLATFORM_DESKTOP)
+    #define GLSL_VERSION            330
+#else   // PLATFORM_ANDROID, PLATFORM_WEB
+    #define GLSL_VERSION            100
+#endif
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    const int screenWidth = 800;
+    const int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raylib [models] example - GPU skinning");
+
+    // Define the camera to look into our 3d world
+    Camera camera = { 0 };
+    camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
+    camera.target = (Vector3){ 0.0f, 2.0f, 0.0f };  // Camera looking at point
+    camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };      // Camera up vector (rotation towards target)
+    camera.fovy = 45.0f;                            // Camera field-of-view Y
+    camera.projection = CAMERA_PERSPECTIVE;         // Camera projection type
+
+    // Load gltf model
+    Model characterModel = LoadModel("resources/models/gltf/greenman.glb"); // Load character model
+    
+    // Load skinning shader
+    Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
+                                       TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
+    
+    characterModel.materials[1].shader = skinningShader;
+    
+    // Load gltf model animations
+    int animsCount = 0;
+    unsigned int animIndex = 0;
+    unsigned int animCurrentFrame = 0;
+    ModelAnimation *modelAnimations = LoadModelAnimations("resources/models/gltf/greenman.glb", &animsCount);
+
+    Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
+
+    DisableCursor();                    // Limit cursor to relative movement inside the window
+
+    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
+        //----------------------------------------------------------------------------------
+        UpdateCamera(&camera, CAMERA_THIRD_PERSON);
+        
+        // Select current animation
+        if (IsKeyPressed(KEY_T)) animIndex = (animIndex + 1)%animsCount;
+        else if (IsKeyPressed(KEY_G)) animIndex = (animIndex + animsCount - 1)%animsCount;
+
+        // Update model animation
+        ModelAnimation anim = modelAnimations[animIndex];
+        animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount;
+        UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame);
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(RAYWHITE);
+
+            BeginMode3D(camera);
+            
+                // Draw character
+                characterModel.transform = MatrixTranslate(position.x, position.y, position.z);
+                UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame);
+                DrawMesh(characterModel.meshes[0], characterModel.materials[1], characterModel.transform);
+
+                DrawGrid(10, 1.0f);
+            EndMode3D();
+
+            DrawText("Use the T/G to switch animation", 10, 10, 20, GRAY);
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    UnloadModelAnimations(modelAnimations, animsCount);
+    UnloadModel(characterModel);         // Unload character model and meshes/material
+    UnloadShader(skinningShader);
+    
+    CloseWindow();              // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}
+ raylib/examples/models/models_point_rendering.c view
@@ -0,0 +1,182 @@+/*******************************************************************************************+*+*   raylib example - point rendering+*+*   Example originally created with raylib 5.0, last time updated with raylib 5.0+*+*   Example contributed by Reese Gallagher (@satchelfrost) and reviewed by Ramon Santamaria (@raysan5)+*+*   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) 2024 Reese Gallagher (@satchelfrost)+*+********************************************************************************************/++#include "raylib.h"++#include <stdlib.h>             // Required for: rand()+#include <math.h>               // Required for: cos(), sin()++#define MAX_POINTS 10000000     // 10 million+#define MIN_POINTS 1000         // 1 thousand++// Generate mesh using points+Mesh GenMeshPoints(int numPoints);++//------------------------------------------------------------------------------------+// Program main entry point+//------------------------------------------------------------------------------------+int main()+{+    // Initialization+    //--------------------------------------------------------------------------------------+    const int screenWidth = 800;+    const int screenHeight = 450;+    +    InitWindow(screenWidth, screenHeight, "raylib [models] example - point rendering");++    Camera camera = {+        .position   = { 3.0f, 3.0f, 3.0f },+        .target     = { 0.0f, 0.0f, 0.0f },+        .up         = { 0.0f, 1.0f, 0.0f },+        .fovy       = 45.0f,+        .projection = CAMERA_PERSPECTIVE+    };++    Vector3 position = { 0.0f, 0.0f, 0.0f };+    bool useDrawModelPoints = true;+    bool numPointsChanged = false;+    int numPoints = 1000;+    +    Mesh mesh = GenMeshPoints(numPoints);+    Model model = LoadModelFromMesh(mesh);+    +    //SetTargetFPS(60);+    //--------------------------------------------------------------------------------------++    // Main game loop+    while(!WindowShouldClose())+    {+        // Update+        //----------------------------------------------------------------------------------+        UpdateCamera(&camera, CAMERA_ORBITAL);++        if (IsKeyPressed(KEY_SPACE)) useDrawModelPoints = !useDrawModelPoints;+        if (IsKeyPressed(KEY_UP))+        {+            numPoints = (numPoints*10 > MAX_POINTS)? MAX_POINTS : numPoints*10;+            numPointsChanged = true;+        }+        if (IsKeyPressed(KEY_DOWN))+        {+            numPoints = (numPoints/10 < MIN_POINTS)? MIN_POINTS : numPoints/10;+            numPointsChanged = true;+        }++        // Upload a different point cloud size+        if (numPointsChanged)+        {+            UnloadModel(model);+            mesh = GenMeshPoints(numPoints);+            model = LoadModelFromMesh(mesh);+            numPointsChanged = false;+        }+        //----------------------------------------------------------------------------------++        // Draw+        //----------------------------------------------------------------------------------+        BeginDrawing();+            ClearBackground(BLACK);++            BeginMode3D(camera);++                // The new method only uploads the points once to the GPU+                if (useDrawModelPoints)+                {+                    DrawModelPoints(model, position, 1.0f, WHITE);+                }+                else+                {+                    // The old method must continually draw the "points" (lines)+                    for (int i = 0; i < numPoints; i++)+                    {+                        Vector3 pos = {+                            .x = mesh.vertices[i*3 + 0],+                            .y = mesh.vertices[i*3 + 1],+                            .z = mesh.vertices[i*3 + 2],+                        };+                        Color color = {+                            .r = mesh.colors[i*4 + 0],+                            .g = mesh.colors[i*4 + 1],+                            .b = mesh.colors[i*4 + 2],+                            .a = mesh.colors[i*4 + 3],+                        };+                        +                        DrawPoint3D(pos, color);+                    }+                }++                // Draw a unit sphere for reference+                DrawSphereWires(position, 1.0f, 10, 10, YELLOW);+                +            EndMode3D();++            // Draw UI text+            DrawText(TextFormat("Point Count: %d", numPoints), 20, screenHeight - 50, 40, WHITE);+            DrawText("Up - increase points", 20, 70, 20, WHITE);+            DrawText("Down - decrease points", 20, 100, 20, WHITE);+            DrawText("Space - drawing function", 20, 130, 20, WHITE);+            +            if (useDrawModelPoints) DrawText("Using: DrawModelPoints()", 20, 160, 20, GREEN);+            else DrawText("Using: DrawPoint3D()", 20, 160, 20, RED);+            +            DrawFPS(10, 10);+            +        EndDrawing();+        //----------------------------------------------------------------------------------+    }++    // De-Initialization+    //--------------------------------------------------------------------------------------+    UnloadModel(model);++    CloseWindow();+    //--------------------------------------------------------------------------------------+    return 0;+}++// Generate a spherical point cloud+Mesh GenMeshPoints(int numPoints)+{+    Mesh mesh = { +        .triangleCount = 1,+        .vertexCount = numPoints,+        .vertices = (float *)MemAlloc(numPoints*3*sizeof(float)),+        .colors = (unsigned char*)MemAlloc(numPoints*4*sizeof(unsigned char)),+    };++    // https://en.wikipedia.org/wiki/Spherical_coordinate_system+    for (int i = 0; i < numPoints; i++)+    {+        float theta = PI*rand()/RAND_MAX;+        float phi = 2.0f*PI*rand()/RAND_MAX;+        float r = 10.0f*rand()/RAND_MAX;+        +        mesh.vertices[i*3 + 0] = r*sin(theta)*cos(phi);+        mesh.vertices[i*3 + 1] = r*sin(theta)*sin(phi);+        mesh.vertices[i*3 + 2] = r*cos(theta);+        +        Color color = ColorFromHSV(r*360.0f, 1.0f, 1.0f);+        +        mesh.colors[i*4 + 0] = color.r;+        mesh.colors[i*4 + 1] = color.g;+        mesh.colors[i*4 + 2] = color.b;+        mesh.colors[i*4 + 3] = color.a;+    }++    // Upload mesh data from CPU (RAM) to GPU (VRAM) memory+    UploadMesh(&mesh, false);+    +    return mesh;+}
raylib/examples/models/models_yaw_pitch_roll.c view
@@ -114,6 +114,7 @@     // De-Initialization     //--------------------------------------------------------------------------------------     UnloadModel(model);     // Unload model data+    UnloadTexture(texture); // Unload texture data      CloseWindow();          // Close window and OpenGL context     //--------------------------------------------------------------------------------------
raylib/examples/shaders/shaders_basic_pbr.c view
@@ -236,7 +236,7 @@                 float emissiveIntensity = 0.01f;                 SetShaderValue(shader, emissiveIntensityLoc, &emissiveIntensity, SHADER_UNIFORM_FLOAT);                 -                DrawModel(car, (Vector3){ 0.0f, 0.0f, 0.0f }, 0.005f, WHITE);   // Draw car model+                DrawModel(car, (Vector3){ 0.0f, 0.0f, 0.0f }, 0.25f, WHITE);   // Draw car model                  // Draw spheres to show the lights positions                 for (int i = 0; i < MAX_LIGHTS; i++)
raylib/examples/shaders/shaders_lightmap.c view
@@ -164,6 +164,8 @@     //--------------------------------------------------------------------------------------     UnloadMesh(mesh);       // Unload the mesh     UnloadShader(shader);   // Unload shader+    UnloadTexture(texture); // Unload texture+    UnloadTexture(light);   // Unload texture      CloseWindow();          // Close window and OpenGL context     //--------------------------------------------------------------------------------------
raylib/examples/shaders/shaders_texture_drawing.c view
@@ -77,6 +77,7 @@     // De-Initialization     //--------------------------------------------------------------------------------------     UnloadShader(shader);+    UnloadTexture(texture);      CloseWindow();        // Close window and OpenGL context     //--------------------------------------------------------------------------------------
+ raylib/examples/shaders/shaders_vertex_displacement.c view
@@ -0,0 +1,119 @@+/*******************************************************************************************+*+*   raylib [shaders] example - Vertex displacement+*+*   Example originally created with raylib 5.0, last time updated with raylib 4.5+*+*   Example contributed by <Alex ZH> (@ZzzhHe) and reviewed by Ramon Santamaria (@raysan5)+*+*   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) 2023 <Alex ZH> (@ZzzhHe)+*+********************************************************************************************/++#include "raylib.h"++#include "rlgl.h"++#define RLIGHTS_IMPLEMENTATION+#include "rlights.h"++#if defined(PLATFORM_DESKTOP)+    #define GLSL_VERSION            330+#else   // PLATFORM_ANDROID, PLATFORM_WEB+    #define GLSL_VERSION            100+#endif++//------------------------------------------------------------------------------------+// Program main entry point+//------------------------------------------------------------------------------------+int main(void)+{+    // Initialization+    //--------------------------------------------------------------------------------------+    const int screenWidth = 800;+    const int screenHeight = 450;++    InitWindow(screenWidth, screenHeight, "raylib [shaders] example - vertex displacement");++    // set up camera+    Camera camera = {0};+    camera.position = (Vector3) {20.0f, 5.0f, -20.0f};+    camera.target = (Vector3) {0.0f, 0.0f, 0.0f};+    camera.up = (Vector3) {0.0f, 1.0f, 0.0f};+    camera.fovy = 60.0f;+    camera.projection = CAMERA_PERSPECTIVE;++    // Load vertex and fragment shaders+    Shader shader = LoadShader(+        TextFormat("resources/shaders/glsl%i/vertex_displacement.vs", GLSL_VERSION),+        TextFormat("resources/shaders/glsl%i/vertex_displacement.fs", GLSL_VERSION));+    +    // Load perlin noise texture+    Image perlinNoiseImage = GenImagePerlinNoise(512, 512, 0, 0, 1.0f);+    Texture perlinNoiseMap = LoadTextureFromImage(perlinNoiseImage);+    UnloadImage(perlinNoiseImage);++    // Set shader uniform location+    int perlinNoiseMapLoc = GetShaderLocation(shader, "perlinNoiseMap");+    rlEnableShader(shader.id);+    rlActiveTextureSlot(1);+    rlEnableTexture(perlinNoiseMap.id);+    rlSetUniformSampler(perlinNoiseMapLoc, 1);+    +    // Create a plane mesh and model+    Mesh planeMesh = GenMeshPlane(50, 50, 50, 50);+    Model planeModel = LoadModelFromMesh(planeMesh);+    // Set plane model material+    planeModel.materials[0].shader = shader;++    float time = 0.0f;++    SetTargetFPS(60);+    //--------------------------------------------------------------------------------------++    // Main game loop+    while (!WindowShouldClose())    // Detect window close button or ESC key+    {+        // Update+        //----------------------------------------------------------------------------------+        UpdateCamera(&camera, CAMERA_FREE); // Update camera++        time += GetFrameTime(); // Update time variable+        SetShaderValue(shader, GetShaderLocation(shader, "time"), &time, SHADER_UNIFORM_FLOAT); // Send time value to shader++        // Draw+        //----------------------------------------------------------------------------------+        BeginDrawing();++            ClearBackground(RAYWHITE);++            BeginMode3D(camera);++                BeginShaderMode(shader);+                    // Draw plane model+                    DrawModel(planeModel, (Vector3){ 0.0f, 0.0f, 0.0f }, 1.0f, (Color) {255, 255, 255, 255});+                EndShaderMode();++            EndMode3D();++            DrawText("Vertex displacement", 10, 10, 20, DARKGRAY);+            DrawFPS(10, 40);++        EndDrawing();+        //----------------------------------------------------------------------------------+    }++    // De-Initialization+    //--------------------------------------------------------------------------------------+    UnloadShader(shader);+    UnloadModel(planeModel);+    UnloadTexture(perlinNoiseMap);++    CloseWindow();        // Close window and OpenGL context+    //--------------------------------------------------------------------------------------++    return 0;+}
raylib/examples/shapes/raygui.h view
@@ -1,6 +1,6 @@ /******************************************************************************************* *-*   raygui v4.0 - A simple and easy-to-use immediate-mode gui library+*   raygui v4.5-dev - A simple and easy-to-use immediate-mode gui library * *   DESCRIPTION: *       raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also@@ -26,7 +26,7 @@ *   NOTES: *       - WARNING: GuiLoadStyle() and GuiLoadStyle{Custom}() functions, allocate memory for *         font atlas recs and glyphs, freeing that memory is (usually) up to the user,-*         no unload function is explicitly provided... but note that GuiLoadStyleDefaulf() unloads+*         no unload function is explicitly provided... but note that GuiLoadStyleDefault() unloads *         by default any previously loaded font (texture, recs, glyphs). *       - Global UI alpha (guiAlpha) is applied inside GuiDrawRectangle() and GuiDrawText() functions *@@ -141,6 +141,24 @@ *           Draw text bounds rectangles for debug * *   VERSIONS HISTORY:+*       4.5-dev (Sep-2024)    Current dev version...+*                         ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes+*                         ADDED: GuiValueBoxFloat()+*                         ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP+*                         ADDED: GuiListView() property: LIST_ITEMS_BORDER_WIDTH+*                         ADDED: Multiple new icons+*                         REVIEWED: GuiTabBar(), close tab with mouse middle button+*                         REVIEWED: GuiScrollPanel(), scroll speed proportional to content+*                         REVIEWED: GuiDropdownBox(), support roll up and hidden arrow+*                         REVIEWED: GuiTextBox(), cursor position initialization+*                         REVIEWED: GuiSliderPro(), control value change check+*                         REVIEWED: GuiGrid(), simplified implementation+*                         REVIEWED: GuiIconText(), increase buffer size and reviewed padding+*                         REVIEWED: GuiDrawText(), improved wrap mode drawing+*                         REVIEWED: GuiScrollBar(), minor tweaks+*                         REVIEWED: Functions descriptions, removed wrong return value reference+*                         REDESIGNED: GuiColorPanel(), improved HSV <-> RGBA convertion+* *       4.0 (12-Sep-2023) ADDED: GuiToggleSlider() *                         ADDED: GuiColorPickerHSV() and GuiColorPanelHSV() *                         ADDED: Multiple new icons, mostly compiler related@@ -314,9 +332,9 @@ #define RAYGUI_H  #define RAYGUI_VERSION_MAJOR 4-#define RAYGUI_VERSION_MINOR 0+#define RAYGUI_VERSION_MINOR 5 #define RAYGUI_VERSION_PATCH 0-#define RAYGUI_VERSION  "4.0"+#define RAYGUI_VERSION  "4.5-dev"  #if !defined(RAYGUI_STANDALONE)     #include "raylib.h"@@ -441,7 +459,6 @@     } Font; #endif - // Style property // NOTE: Used when exporting style as code for convenience typedef struct GuiStyleProp {@@ -546,7 +563,6 @@ // TEXT_SIZE, TEXT_SPACING, TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE are global and // should be configured by user as needed while defining the UI layout - // Gui extended properties depend on control // NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default, max 8 properties) //----------------------------------------------------------------------------------@@ -562,12 +578,12 @@     TEXT_ALIGNMENT_VERTICAL,    // Text vertical alignment inside text bounds (after border and padding)     TEXT_WRAP_MODE              // Text wrap-mode inside text bounds     //TEXT_DECORATION             // Text decoration: 0-None, 1-Underline, 2-Line-through, 3-Overline-    //TEXT_DECORATION_THICK       // Text decoration line thikness+    //TEXT_DECORATION_THICK       // Text decoration line thickness } GuiDefaultProperty;  // Other possible text properties: // TEXT_WEIGHT                  // Normal, Italic, Bold -> Requires specific font change-// TEXT_INDENT	                // Text indentation -> Now using TEXT_PADDING...+// TEXT_INDENT                  // Text indentation -> Now using TEXT_PADDING...  // Label //typedef enum { } GuiLabelProperty;@@ -615,7 +631,9 @@ // DropdownBox typedef enum {     ARROW_PADDING = 16,         // DropdownBox arrow separation from border and items-    DROPDOWN_ITEMS_SPACING      // DropdownBox items separation+    DROPDOWN_ITEMS_SPACING,     // DropdownBox items separation+    DROPDOWN_ARROW_HIDDEN,      // DropdownBox arrow hidden+    DROPDOWN_ROLL_UP            // DropdownBox roll up flag (default rolls down) } GuiDropdownBoxProperty;  // TextBox/TextBoxMulti/ValueBox/Spinner@@ -635,6 +653,7 @@     LIST_ITEMS_SPACING,         // ListView items separation     SCROLLBAR_WIDTH,            // ListView scrollbar size (usually width)     SCROLLBAR_SIDE,             // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE)+    LIST_ITEMS_BORDER_WIDTH     // ListView items border width } GuiListViewProperty;  // ColorPicker@@ -698,7 +717,6 @@ RAYGUIAPI void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color); // Draw icon using pixel size at specified position #endif - // Controls //---------------------------------------------------------------------------------------------------------- // Container/separator controls, useful for controls organization@@ -710,29 +728,30 @@ RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control  // Basic controls set-RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text);                                            // Label control, shows text+RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text);                                            // Label control RAYGUIAPI int GuiButton(Rectangle bounds, const char *text);                                           // Button control, returns true when clicked-RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text);                                      // Label button control, show true when clicked-RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active);                             // Toggle Button control, returns true when active-RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active);                         // Toggle Group control, returns active toggle index-RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active);                        // Toggle Slider control, returns true when clicked+RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text);                                      // Label button control, returns true when clicked+RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active);                             // Toggle Button control+RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active);                         // Toggle Group control+RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active);                        // Toggle Slider control RAYGUIAPI int GuiCheckBox(Rectangle bounds, const char *text, bool *checked);                          // Check Box control, returns true when active-RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active);                            // Combo Box control, returns selected item index+RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active);                            // Combo Box control -RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode);          // Dropdown Box control, returns selected item-RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control, returns selected value+RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode);          // Dropdown Box control+RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control RAYGUIAPI int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Value Box control, updates input text with numbers+RAYGUIAPI int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode); // Value box control for float values RAYGUIAPI int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode);                   // Text Box control, updates input text -RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control, returns selected value-RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control, returns selected value-RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control, shows current progress value+RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control+RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control+RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control RAYGUIAPI int GuiStatusBar(Rectangle bounds, const char *text);                                        // Status Bar control, shows info text RAYGUIAPI int GuiDummyRec(Rectangle bounds, const char *text);                                         // Dummy control for placeholders-RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control, returns mouse cell position+RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control  // Advance controls set-RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active);          // List View control, returns selected list item index+RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active);          // List View control RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret@@ -741,10 +760,9 @@ RAYGUIAPI int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha);                      // Color Bar Alpha control RAYGUIAPI int GuiColorBarHue(Rectangle bounds, const char *text, float *value);                        // Color Bar Hue control RAYGUIAPI int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv);                // Color Picker control that avoids conversion to RGB on each call (multiple color controls)-RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv);                 // Color Panel control that returns HSV color value, used by GuiColorPickerHSV()+RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv);                 // Color Panel control that updates Hue-Saturation-Value color value, used by GuiColorPickerHSV() //---------------------------------------------------------------------------------------------------------- - #if !defined(RAYGUI_NO_ICONS)  #if !defined(RAYGUI_CUSTOM_ICONS)@@ -972,14 +990,14 @@     ICON_FOLDER                   = 217,     ICON_FILE                     = 218,     ICON_SAND_TIMER               = 219,-    ICON_220                      = 220,-    ICON_221                      = 221,-    ICON_222                      = 222,-    ICON_223                      = 223,-    ICON_224                      = 224,-    ICON_225                      = 225,-    ICON_226                      = 226,-    ICON_227                      = 227,+    ICON_WARNING                  = 220,+    ICON_HELP_BOX                 = 221,+    ICON_INFO_BOX                 = 222,+    ICON_PRIORITY                 = 223,+    ICON_LAYERS_ISO               = 224,+    ICON_LAYERS2                  = 225,+    ICON_MLAYERS                  = 226,+    ICON_MAPS                     = 227,     ICON_228                      = 228,     ICON_229                      = 229,     ICON_230                      = 230,@@ -1290,14 +1308,14 @@     0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000,      // ICON_FOLDER     0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x00003ffc,      // ICON_FILE     0x1ff00000, 0x20082008, 0x17d02fe8, 0x05400ba0, 0x09200540, 0x23881010, 0x2fe827c8, 0x00001ff0,      // ICON_SAND_TIMER-    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_220-    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_221-    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_222-    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_223-    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_224-    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_225-    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_226-    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_227+    0x01800000, 0x02400240, 0x05a00420, 0x09900990, 0x11881188, 0x21842004, 0x40024182, 0x00003ffc,      // ICON_WARNING+    0x7ffe0000, 0x4ff24002, 0x4c324ff2, 0x4f824c02, 0x41824f82, 0x41824002, 0x40024182, 0x00007ffe,      // ICON_HELP_BOX+    0x7ffe0000, 0x41824002, 0x40024182, 0x41824182, 0x41824182, 0x41824182, 0x40024182, 0x00007ffe,      // ICON_INFO_BOX+    0x01800000, 0x04200240, 0x10080810, 0x7bde2004, 0x0a500a50, 0x08500bd0, 0x08100850, 0x00000ff0,      // ICON_PRIORITY+    0x01800000, 0x18180660, 0x80016006, 0x98196006, 0x99996666, 0x19986666, 0x01800660, 0x00000000,      // ICON_LAYERS_ISO+    0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0,      // ICON_LAYERS2+    0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0,      // ICON_MLAYERS+    0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0,      // ICON_MAPS     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_228     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_229     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_230@@ -1328,7 +1346,7 @@     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_255 }; -// NOTE: We keep a pointer to the icons array, useful to point to other sets if required+// NOTE: A pointer to current icons array should be defined static unsigned int *guiIconsPtr = guiIcons;  #endif      // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS@@ -1363,8 +1381,8 @@ static bool guiTooltip = false;                 // Tooltip enabled/disabled static const char *guiTooltipPtr = NULL;        // Tooltip string pointer (string provided by user) -static bool guiSliderDragging = false;          // Gui slider drag state (no inputs processed except dragged slider)-static Rectangle guiSliderActive = { 0 };       // Gui slider active bounds rectangle, used as an unique identifier+static bool guiControlExclusiveMode = false;    // Gui control exclusive mode (no inputs processed except current control)+static Rectangle guiControlExclusiveRec = { 0 }; // Gui control exclusive bounds rectangle, used as an unique identifier  static int textBoxCursorIndex = 0;              // Cursor index, shared by all GuiTextBox*() //static int blinkCursorFrameCounter = 0;       // Frame counter for cursor blinking@@ -1450,6 +1468,7 @@ static const char *TextFormat(const char *text, ...);               // Formatting of text with variables to 'embed' static const char **TextSplit(const char *text, char delimiter, int *count);    // Split text into multiple strings static int TextToInteger(const char *text);         // Get integer value from text+static float TextToFloat(const char *text);         // Get float value from text  static int GetCodepointNext(const char *text, int *codepointSize);  // Get next codepoint in a UTF-8 encoded text static const char *CodepointToUTF8(int codepoint, int *byteSize);   // Encode codepoint into UTF-8 text (char array size returned as parameter)@@ -1744,6 +1763,9 @@                 if (toggle) *active = i;             } +            // Close tab with middle mouse button pressed+            if (CheckCollisionPointRec(GetMousePosition(), tabBounds) && IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) result = i;+             GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding);             GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment); @@ -1775,10 +1797,10 @@ {     #define RAYGUI_MIN_SCROLLBAR_WIDTH     40     #define RAYGUI_MIN_SCROLLBAR_HEIGHT    40+    #define RAYGUI_MIN_MOUSE_WHEEL_SPEED   20      int result = 0;     GuiState state = guiState;-    float mouseWheelSpeed = 20.0f;      // Default movement speed with mouse wheel      Rectangle temp = { 0 };     if (view == NULL) view = &temp;@@ -1820,17 +1842,8 @@     };      // Make sure scroll bars have a minimum width/height-    // NOTE: If content >>> bounds, size could be very small or even 0-    if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH)-    {-        horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH;-        mouseWheelSpeed = 30.0f;    // TODO: Calculate speed increment based on content.height vs bounds.height-    }-    if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT)-    {-        verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT;-        mouseWheelSpeed = 30.0f;    // TODO: Calculate speed increment based on content.width vs bounds.width-    }+    if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH;+    if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT;      // Calculate view area (area without the scrollbars)     *view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)?@@ -1873,9 +1886,14 @@ #endif             float wheelMove = GetMouseWheelMove(); +            // Set scrolling speed with mouse wheel based on ratio between bounds and content+            Vector2 mouseWheelSpeed = { content.width/bounds.width, content.height/bounds.height };+            if (mouseWheelSpeed.x < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.x = RAYGUI_MIN_MOUSE_WHEEL_SPEED;+            if (mouseWheelSpeed.y < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.y = RAYGUI_MIN_MOUSE_WHEEL_SPEED;+             // Horizontal and vertical scrolling with mouse wheel-            if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed;-            else scrollPos.y += wheelMove*mouseWheelSpeed; // Vertical scroll+            if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed.x;+            else scrollPos.y += wheelMove*mouseWheelSpeed.y; // Vertical scroll         }     } @@ -1921,7 +1939,7 @@     }      // Draw scrollbar lines depending on current state-    GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK);+    GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK);      // Set scrollbar slider size back to the way it was before     GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider);@@ -1959,7 +1977,7 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)     {         Vector2 mousePoint = GetMousePosition(); @@ -1997,7 +2015,7 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)     {         Vector2 mousePoint = GetMousePosition(); @@ -2020,7 +2038,7 @@     return pressed; } -// Toggle Button control, returns true when active+// Toggle Button control int GuiToggle(Rectangle bounds, const char *text, bool *active) {     int result = 0;@@ -2031,7 +2049,7 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)     {         Vector2 mousePoint = GetMousePosition(); @@ -2068,7 +2086,7 @@     return result; } -// Toggle Group control, returns toggled button codepointIndex+// Toggle Group control int GuiToggleGroup(Rectangle bounds, const char *text, int *active) {     #if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS)@@ -2117,7 +2135,7 @@     return result; } -// Toggle Slider control extended, returns true when clicked+// Toggle Slider control extended int GuiToggleSlider(Rectangle bounds, const char *text, int *active) {     int result = 0;@@ -2211,7 +2229,7 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)     {         Vector2 mousePoint = GetMousePosition(); @@ -2256,7 +2274,7 @@     return result; } -// Combo Box control, returns selected item codepointIndex+// Combo Box control int GuiComboBox(Rectangle bounds, const char *text, int *active) {     int result = 0;@@ -2279,7 +2297,7 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiControlExclusiveMode)     {         Vector2 mousePoint = GetMousePosition(); @@ -2327,21 +2345,28 @@     int result = 0;     GuiState state = guiState; +    int temp = 0;+    if (active == NULL) active = &temp;+     int itemSelected = *active;     int itemFocused = -1; +    int direction = 0; // Dropdown box open direction: down (default)+    if (GuiGetStyle(DROPDOWNBOX, DROPDOWN_ROLL_UP) == 1) direction = 1; // Up+     // Get substrings items from text (items pointers, lengths and count)     int itemCount = 0;     const char **items = GuiTextSplit(text, ';', &itemCount, NULL);      Rectangle boundsOpen = bounds;     boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));+    if (direction == 1) boundsOpen.y -= itemCount*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)) + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING);      Rectangle itemBounds = bounds;      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiSliderDragging)+    if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiControlExclusiveMode)     {         Vector2 mousePoint = GetMousePosition(); @@ -2362,7 +2387,8 @@             for (int i = 0; i < itemCount; i++)             {                 // Update item rectangle y position for next item-                itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));+                if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));+                else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));                  if (CheckCollisionPointRec(mousePoint, itemBounds))                 {@@ -2406,7 +2432,8 @@         for (int i = 0; i < itemCount; i++)         {             // Update item rectangle y position for next item-            itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));+            if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));+            else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));              if (i == itemSelected)             {@@ -2422,14 +2449,17 @@         }     } -    // Draw arrows (using icon if available)+    if (!GuiGetStyle(DROPDOWNBOX, DROPDOWN_ARROW_HIDDEN))+    {+        // Draw arrows (using icon if available) #if defined(RAYGUI_NO_ICONS)-    GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },-                TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));+        GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },+            TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); #else-    GuiDrawText("#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },-                TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));   // ICON_ARROW_DOWN_FILL+        GuiDrawText(direction? "#121#" : "#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },+            TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));   // ICON_ARROW_DOWN_FILL #endif+    }     //--------------------------------------------------------------------      *active = itemSelected;@@ -2440,7 +2470,7 @@  // Text Box control // NOTE: Returns true on ENTER pressed (useful for data validation)-int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)+int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode) {     #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)         #define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN  40        // Frames to wait for autocursor movement@@ -2456,7 +2486,10 @@     int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE);      Rectangle textBounds = GetTextBounds(TEXTBOX, bounds);-    int textWidth = GetTextWidth(text) - GetTextWidth(text + textBoxCursorIndex);+    int textLength = (int)strlen(text);     // Get current text length+    int thisCursorIndex = textBoxCursorIndex;+    if (thisCursorIndex > textLength) thisCursorIndex = textLength;+    int textWidth = GetTextWidth(text) - GetTextWidth(text + thisCursorIndex);     int textIndexOffset = 0;    // Text index offset to start drawing in the box      // Cursor rectangle@@ -2496,7 +2529,7 @@     if ((state != STATE_DISABLED) &&                // Control not disabled         !GuiGetStyle(TEXTBOX, TEXT_READONLY) &&     // TextBox not on read-only mode         !guiLocked &&                               // Gui not locked-        !guiSliderDragging &&                       // No gui slider on dragging+        !guiControlExclusiveMode &&                       // No gui slider on dragging         (wrapMode == TEXT_WRAP_NONE))               // No wrap mode     {         Vector2 mousePosition = GetMousePosition();@@ -2505,6 +2538,8 @@         {             state = STATE_PRESSED; +            if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;+             // If text does not fit in the textbox and current cursor position is out of bounds,             // we add an index offset to text for drawing only what requires depending on cursor             while (textWidth >= textBounds.width)@@ -2517,19 +2552,16 @@                 textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex);             } -            int textLength = (int)strlen(text);     // Get current text length             int codepoint = GetCharPressed();       // Get Unicode codepoint             if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n'; -            if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;-             // Encode codepoint as UTF-8             int codepointSize = 0;             const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize);              // Add codepoint to text, at current cursor position             // NOTE: Make sure we do not overflow buffer size-            if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < bufferSize))+            if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < textSize))             {                 // Move forward data from cursor position                 for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize];@@ -2564,6 +2596,7 @@                     for (int i = textBoxCursorIndex; i < textLength; i++) text[i] = text[i + nextCodepointSize];                      textLength -= codepointSize;+                    if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;                      // Make sure text last character is EOL                     text[textLength] = '\0';@@ -2583,6 +2616,8 @@                     // Move backward text from cursor position                     for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize]; +                    // TODO Check: >= cursor+codepointsize and <= length-codepointsize+                     // Prevent cursor index from decrementing past 0                     if (textBoxCursorIndex > 0)                     {@@ -2653,7 +2688,7 @@                 if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2))                 {                     mouseCursor.x = textBounds.x + textEndWidth;-                    mouseCursorIndex = (int)strlen(text);+                    mouseCursorIndex = textLength;                 }                  // Place cursor at required index on mouse click@@ -2685,7 +2720,7 @@                  if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))                 {-                    textBoxCursorIndex = (int)strlen(text);   // GLOBAL: Place cursor index to the end of current text+                    textBoxCursorIndex = textLength;   // GLOBAL: Place cursor index to the end of current text                     result = 1;                 }             }@@ -2727,7 +2762,7 @@ /* // Text Box control with multiple lines and word-wrap // NOTE: This text-box is readonly, no editing supported by default-bool GuiTextBoxMulti(Rectangle bounds, char *text, int bufferSize, bool editMode)+bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode) {     bool pressed = false; @@ -2736,7 +2771,7 @@     GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP);      // TODO: Implement methods to calculate cursor position properly-    pressed = GuiTextBox(bounds, text, bufferSize, editMode);+    pressed = GuiTextBox(bounds, text, textSize, editMode);      GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE);     GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE);@@ -2771,7 +2806,7 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)     {         Vector2 mousePoint = GetMousePosition(); @@ -2846,7 +2881,7 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)     {         Vector2 mousePoint = GetMousePosition(); @@ -2890,7 +2925,13 @@             //if (*value > maxValue) *value = maxValue;             //else if (*value < minValue) *value = minValue; -            if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1;+            if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))+            {+                if (*value > maxValue) *value = maxValue;+                else if (*value < minValue) *value = minValue;++                result = 1;+            }         }         else         {@@ -2930,55 +2971,152 @@     return result; } +// Floating point Value Box control, updates input val_str with numbers+// NOTE: Requires static variables: frameCounter+int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode)+{+    #if !defined(RAYGUI_VALUEBOX_MAX_CHARS)+        #define RAYGUI_VALUEBOX_MAX_CHARS  32+    #endif++    int result = 0;+    GuiState state = guiState;++    //char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";+    //sprintf(textValue, "%2.2f", *value);++    Rectangle textBounds = {0};+    if (text != NULL)+    {+        textBounds.width = (float)GetTextWidth(text) + 2;+        textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);+        textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);+        textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;+        if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);+    }++    // Update control+    //--------------------------------------------------------------------+    if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)+    {+        Vector2 mousePoint = GetMousePosition();++        bool valueHasChanged = false;++        if (editMode)+        {+            state = STATE_PRESSED;++            int keyCount = (int)strlen(textValue);++            // Only allow keys in range [48..57]+            if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)+            {+                if (GetTextWidth(textValue) < bounds.width)+                {+                    int key = GetCharPressed();+                    if (((key >= 48) && (key <= 57)) ||+                        (key == '.') ||+                        ((keyCount == 0) && (key == '+')) ||  // NOTE: Sign can only be in first position+                        ((keyCount == 0) && (key == '-')))+                    {+                        textValue[keyCount] = (char)key;+                        keyCount++;++                        valueHasChanged = true;+                    }+                }+            }++            // Pressed backspace+            if (IsKeyPressed(KEY_BACKSPACE))+            {+                if (keyCount > 0)+                {+                    keyCount--;+                    textValue[keyCount] = '\0';+                    valueHasChanged = true;+                }+            }++            if (valueHasChanged) *value = TextToFloat(textValue);++            if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1;+        }+        else+        {+            if (CheckCollisionPointRec(mousePoint, bounds))+            {+                state = STATE_FOCUSED;+                if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;+            }+        }+    }+    //--------------------------------------------------------------------++    // Draw control+    //--------------------------------------------------------------------+    Color baseColor = BLANK;+    if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));+    else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));++    GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor);+    GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))));++    // Draw cursor+    if (editMode)+    {+        // NOTE: ValueBox internal text is always centered+        Rectangle cursor = {bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1,+                            bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4,+                            bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH)};+        GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)));+    }++    // Draw text label if provided+    GuiDrawText(text, textBounds,+                (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT,+                GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));+    //--------------------------------------------------------------------++    return result;+}+ // Slider control with pro parameters // NOTE: Other GuiSlider*() controls use this one int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth) {     int result = 0;-    float oldValue = *value;     GuiState state = guiState;      float temp = (maxValue - minValue)/2.0f;     if (value == NULL) value = &temp;--    int sliderValue = (int)(((*value - minValue)/(maxValue - minValue))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH)));+    float oldValue = *value;      Rectangle slider = { bounds.x, bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),                          0, bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) }; -    if (sliderWidth > 0)        // Slider-    {-        slider.x += (sliderValue - sliderWidth/2);-        slider.width = (float)sliderWidth;-    }-    else if (sliderWidth == 0)  // SliderBar-    {-        slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH);-        slider.width = (float)sliderValue;-    }-     // Update control     //--------------------------------------------------------------------     if ((state != STATE_DISABLED) && !guiLocked)     {         Vector2 mousePoint = GetMousePosition(); -        if (guiSliderDragging) // Keep dragging outside of bounds+        if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds         {             if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))             {-                if (CHECK_BOUNDS_ID(bounds, guiSliderActive))+                if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))                 {                     state = STATE_PRESSED;-                     // Get equivalent value and slider position from mousePosition.x-                    *value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue;+                    *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue;                 }             }             else             {-                guiSliderDragging = false;-                guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };+                guiControlExclusiveMode = false;+                guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };             }         }         else if (CheckCollisionPointRec(mousePoint, bounds))@@ -2986,16 +3124,13 @@             if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))             {                 state = STATE_PRESSED;-                guiSliderDragging = true;-                guiSliderActive = bounds; // Store bounds as an identifier when dragging starts+                guiControlExclusiveMode = true;+                guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts                  if (!CheckCollisionPointRec(mousePoint, slider))                 {                     // Get equivalent value and slider position from mousePosition.x-                    *value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue;--                    if (sliderWidth > 0) slider.x = mousePoint.x - slider.width/2;      // Slider-                    else if (sliderWidth == 0) slider.width = (float)sliderValue;       // SliderBar+                    *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue;                 }             }             else state = STATE_FOCUSED;@@ -3006,17 +3141,22 @@     }      // Control value change check-    if(oldValue == *value) result = 0;+    if (oldValue == *value) result = 0;     else result = 1; -    // Bar limits check+    // Slider bar limits check+    float sliderValue = (((*value - minValue)/(maxValue - minValue))*(bounds.width - sliderWidth - 2*GuiGetStyle(SLIDER, BORDER_WIDTH)));     if (sliderWidth > 0)        // Slider     {+        slider.x += sliderValue;+        slider.width = (float)sliderWidth;         if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH);         else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH);     }     else if (sliderWidth == 0)  // SliderBar     {+        slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH);+        slider.width = sliderValue;         if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH);     }     //--------------------------------------------------------------------@@ -3171,7 +3311,7 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)     {         Vector2 mousePoint = GetMousePosition(); @@ -3238,7 +3378,7 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)     {         Vector2 mousePoint = GetMousePosition(); @@ -3291,6 +3431,8 @@     // Draw visible items     for (int i = 0; ((i < visibleItems) && (text != NULL)); i++)     {+        GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK);+         if (state == STATE_DISABLED)         {             if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)));@@ -3353,83 +3495,32 @@     return result; } -// Color Panel control+// Color Panel control - Color (RGBA) variant. int GuiColorPanel(Rectangle bounds, const char *text, Color *color) {     int result = 0;-    GuiState state = guiState;-    Vector2 pickerSelector = { 0 }; -    const Color colWhite = { 255, 255, 255, 255 };-    const Color colBlack = { 0, 0, 0, 255 };-     Vector3 vcolor = { (float)color->r/255.0f, (float)color->g/255.0f, (float)color->b/255.0f };     Vector3 hsv = ConvertRGBtoHSV(vcolor);--    pickerSelector.x = bounds.x + (float)hsv.y*bounds.width;            // HSV: Saturation-    pickerSelector.y = bounds.y + (1.0f - (float)hsv.z)*bounds.height;  // HSV: Value--    Vector3 maxHue = { hsv.x, 1.0f, 1.0f };-    Vector3 rgbHue = ConvertHSVtoRGB(maxHue);-    Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x),-                      (unsigned char)(255.0f*rgbHue.y),-                      (unsigned char)(255.0f*rgbHue.z), 255 };--    // Update control-    //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)-    {-        Vector2 mousePoint = GetMousePosition();--        if (CheckCollisionPointRec(mousePoint, bounds))-        {-            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))-            {-                state = STATE_PRESSED;-                pickerSelector = mousePoint;--                // Calculate color from picker-                Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };--                colorPick.x /= (float)bounds.width;     // Get normalized value on x-                colorPick.y /= (float)bounds.height;    // Get normalized value on y--                hsv.y = colorPick.x;-                hsv.z = 1.0f - colorPick.y;--                Vector3 rgb = ConvertHSVtoRGB(hsv);--                // NOTE: Vector3ToColor() only available on raylib 1.8.1-                *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x),-                                 (unsigned char)(255.0f*rgb.y),-                                 (unsigned char)(255.0f*rgb.z),-                                 (unsigned char)(255.0f*(float)color->a/255.0f) };+    Vector3 prevHsv = hsv; // workaround to see if GuiColorPanelHSV modifies the hsv. -            }-            else state = STATE_FOCUSED;-        }-    }-    //--------------------------------------------------------------------+    GuiColorPanelHSV(bounds, text, &hsv); -    // Draw control-    //---------------------------------------------------------------------    if (state != STATE_DISABLED)+    // Check if the hsv was changed, only then change the color.+    // This is required, because the Color->HSV->Color conversion has precision errors.+    // Thus the assignment from HSV to Color should only be made, if the HSV has a new user-entered value.+    // Otherwise GuiColorPanel would often modify it's color without user input.+    // TODO: GuiColorPanelHSV could return 1 if the slider was dragged, to simplify this check.+    if (hsv.x != prevHsv.x || hsv.y != prevHsv.y || hsv.z != prevHsv.z)     {-        DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha));-        DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0));+        Vector3 rgb = ConvertHSVtoRGB(hsv); -        // Draw color picker: selector-        Rectangle selector = { pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE) };-        GuiDrawRectangle(selector, 0, BLANK, colWhite);-    }-    else-    {-        DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha));+        // NOTE: Vector3ToColor() only available on raylib 1.8.1+        *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x),+                            (unsigned char)(255.0f*rgb.y),+                            (unsigned char)(255.0f*rgb.z),+                            color->a };     }--    GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);-    //---------------------------------------------------------------------     return result; } @@ -3451,11 +3542,11 @@     {         Vector2 mousePoint = GetMousePosition(); -        if (guiSliderDragging) // Keep dragging outside of bounds+        if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds         {             if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))             {-                if (CHECK_BOUNDS_ID(bounds, guiSliderActive))+                if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))                 {                     state = STATE_PRESSED; @@ -3466,8 +3557,8 @@             }             else             {-                guiSliderDragging = false;-                guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };+                guiControlExclusiveMode = false;+                guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };             }         }         else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector))@@ -3475,8 +3566,8 @@             if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))             {                 state = STATE_PRESSED;-                guiSliderDragging = true;-                guiSliderActive = bounds; // Store bounds as an identifier when dragging starts+                guiControlExclusiveMode = true;+                guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts                  *alpha = (mousePoint.x - bounds.x)/bounds.width;                 if (*alpha <= 0.0f) *alpha = 0.0f;@@ -3537,11 +3628,11 @@     {         Vector2 mousePoint = GetMousePosition(); -        if (guiSliderDragging) // Keep dragging outside of bounds+        if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds         {             if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))             {-                if (CHECK_BOUNDS_ID(bounds, guiSliderActive))+                if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))                 {                     state = STATE_PRESSED; @@ -3552,8 +3643,8 @@             }             else             {-                guiSliderDragging = false;-                guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };+                guiControlExclusiveMode = false;+                guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };             }         }         else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector))@@ -3561,8 +3652,8 @@             if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))             {                 state = STATE_PRESSED;-                guiSliderDragging = true;-                guiSliderActive = bounds; // Store bounds as an identifier when dragging starts+                guiControlExclusiveMode = true;+                guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts                  *hue = (mousePoint.y - bounds.y)*360/bounds.height;                 if (*hue <= 0.0f) *hue = 0.0f;@@ -3615,6 +3706,7 @@ //      float GuiColorBarAlpha(Rectangle bounds, float alpha) //      float GuiColorBarHue(Rectangle bounds, float value) // NOTE: bounds define GuiColorPanel() size+// NOTE: this picker converts RGB to HSV, which can cause the Hue control to jump. If you have this problem, consider using the HSV variant instead int GuiColorPicker(Rectangle bounds, const char *text, Color *color) {     int result = 0;@@ -3627,6 +3719,7 @@     Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height };     //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) }; +    // NOTE: this conversion can cause low hue-resolution, if the r, g and b value are very similar, which causes the hue bar to shift around when only the GuiColorPanel is used.     Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f });      GuiColorBarHue(boundsHue, NULL, &hsv.x);@@ -3668,8 +3761,7 @@     return result; } -// Color Panel control, returns HSV color value in *colorHsv.-// Used by GuiColorPickerHSV()+// Color Panel control - HSV variant int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) {     int result = 0;@@ -3690,15 +3782,47 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked)     {         Vector2 mousePoint = GetMousePosition(); -        if (CheckCollisionPointRec(mousePoint, bounds))+        if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds         {             if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))             {+                if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))+                {+                    pickerSelector = mousePoint;++                    if (pickerSelector.x < bounds.x) pickerSelector.x = bounds.x;+                    if (pickerSelector.x > bounds.x + bounds.width) pickerSelector.x = bounds.x + bounds.width;+                    if (pickerSelector.y < bounds.y) pickerSelector.y = bounds.y;+                    if (pickerSelector.y > bounds.y + bounds.height) pickerSelector.y = bounds.y + bounds.height;++                    // Calculate color from picker+                    Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };++                    colorPick.x /= (float)bounds.width;     // Get normalized value on x+                    colorPick.y /= (float)bounds.height;    // Get normalized value on y++                    colorHsv->y = colorPick.x;+                    colorHsv->z = 1.0f - colorPick.y;++                }+            }+            else+            {+                guiControlExclusiveMode = false;+                guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };+            }+        }+        else if (CheckCollisionPointRec(mousePoint, bounds))+        {+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))+            {                 state = STATE_PRESSED;+                guiControlExclusiveMode = true;+                guiControlExclusiveRec = bounds;                 pickerSelector = mousePoint;                  // Calculate color from picker@@ -3760,9 +3884,9 @@     int textWidth = GetTextWidth(message) + 2;      Rectangle textBounds = { 0 };-    textBounds.x = bounds.x + bounds.width/2 - textWidth/2;+    textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;     textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING;-    textBounds.width = (float)textWidth;+    textBounds.width = bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*2;     textBounds.height = bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3*RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT;      // Draw control@@ -3905,7 +4029,7 @@      // Update control     //---------------------------------------------------------------------    if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)+    if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)     {         if (CheckCollisionPointRec(mousePoint, bounds))         {@@ -3925,14 +4049,14 @@         // Draw vertical grid lines         for (int i = 0; i < linesV; i++)         {-            Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height };+            Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height + 1 };             GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA));         }          // Draw horizontal grid lines         for (int i = 0; i < linesH; i++)         {-            Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width, 1 };+            Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width + 1, 1 };             GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA));         }     }@@ -3954,7 +4078,6 @@ // Set tooltip string void GuiSetTooltip(const char *tooltip) { guiTooltipPtr = tooltip; } - //---------------------------------------------------------------------------------- // Styles loading functions //----------------------------------------------------------------------------------@@ -3967,6 +4090,7 @@     #define MAX_LINE_BUFFER_SIZE    256      bool tryBinary = false;+    if (!guiStyleLoaded) GuiLoadStyleDefault();      // Try reading the files as text file first     FILE *rgsFile = fopen(fileName, "rt");@@ -4600,7 +4724,7 @@             }         } -        if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE - ICON_TEXT_PADDING);+        if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING);     }      return (int)textSize.x;@@ -4773,6 +4897,7 @@         // Get text position depending on alignment and iconId         //---------------------------------------------------------------------------------         Vector2 textBoundsPosition = { textBounds.x, textBounds.y };+        float textBoundsWidthOffset = 0.0f;          // NOTE: We get text size after icon has been processed         // WARNING: GetTextWidth() also processes text icon to get width! -> Really needed?@@ -4798,6 +4923,8 @@             default: break;         } +        if (textSizeX > textBounds.width && (lines[i] != NULL) && (lines[i][0] != '\0')) textBoundsPosition.x = textBounds.x;+         switch (alignmentVertical)         {             // Only valid in case of wordWrap = 0;@@ -4820,7 +4947,8 @@         {             // NOTE: We consider icon height, probably different than text size             GuiDrawIcon(iconId, (int)textBoundsPosition.x, (int)(textBounds.y + textBounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height)), guiIconScale, tint);-            textBoundsPosition.x += (RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);+            textBoundsPosition.x += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);+            textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);         } #endif         // Get size in bytes of text,@@ -4829,9 +4957,15 @@         for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n') && (lines[i][c] != '\r'); c++, lineSize++){ }         float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize; +        int lastSpaceIndex = 0;+        bool tempWrapCharMode = false;+         int textOffsetY = 0;         float textOffsetX = 0.0f;         float glyphWidth = 0;++        int ellipsisWidth = GetTextWidth("...");+        bool textOverflow = false;         for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize)         {             int codepoint = GetCodepointNext(&lines[i][c], &codepointSize);@@ -4839,36 +4973,51 @@              // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)             // but we need to draw all of the bad bytes using the '?' symbol moving one byte-            if (codepoint == 0x3f) codepointSize = 1;       // TODO: Review not recognized codepoints size+            if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size -            // Wrap mode text measuring to space to validate if it can be drawn or-            // a new line is required+            // Get glyph width to check if it goes out of bounds+            if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor);+            else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor;++            // Wrap mode text measuring, to validate if+            // it can be drawn or a new line is required             if (wrapMode == TEXT_WRAP_CHAR)             {-                // Get glyph width to check if it goes out of bounds-                if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor);-                else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor;-                 // Jump to next line if current character reach end of the box limits-                if ((textOffsetX + glyphWidth) > textBounds.width)+                if ((textOffsetX + glyphWidth) > textBounds.width - textBoundsWidthOffset)                 {                     textOffsetX = 0.0f;                     textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);++                    if (tempWrapCharMode)   // Wrap at char level when too long words+                    {+                        wrapMode = TEXT_WRAP_WORD;+                        tempWrapCharMode = false;+                    }                 }             }             else if (wrapMode == TEXT_WRAP_WORD)             {+                if (codepoint == 32) lastSpaceIndex = c;+                 // Get width to next space in line                 int nextSpaceIndex = 0;                 float nextSpaceWidth = GetNextSpaceWidth(lines[i] + c, &nextSpaceIndex); -                if ((textOffsetX + nextSpaceWidth) > textBounds.width)+                int nextSpaceIndex2 = 0;+                float nextWordSize = GetNextSpaceWidth(lines[i] + lastSpaceIndex + 1, &nextSpaceIndex2);++                if (nextWordSize > textBounds.width - textBoundsWidthOffset)                 {+                    // Considering the case the next word is longer than bounds+                    tempWrapCharMode = true;+                    wrapMode = TEXT_WRAP_CHAR;+                }+                else if ((textOffsetX + nextSpaceWidth) > textBounds.width - textBoundsWidthOffset)+                {                     textOffsetX = 0.0f;                     textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);                 }--                // TODO: Consider case: (nextSpaceWidth >= textBounds.width)             }              if (codepoint == '\n') break;   // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint@@ -4881,8 +5030,24 @@                     if (wrapMode == TEXT_WRAP_NONE)                     {                         // Draw only required text glyphs fitting the textBounds.width-                        if (textOffsetX <= (textBounds.width - glyphWidth))+                        if (textSizeX > textBounds.width)                         {+                            if (textOffsetX <= (textBounds.width - glyphWidth - textBoundsWidthOffset - ellipsisWidth))+                            {+                                DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));+                            }+                            else if (!textOverflow)+                            {+                                textOverflow = true;++                                for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3)+                                {+                                    DrawTextCodepoint(guiFont, '.', RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX + j, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));+                                }+                            }+                        }+                        else+                        {                             DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));                         }                     }@@ -4937,7 +5102,7 @@ // Draw tooltip using control bounds static void GuiTooltip(Rectangle controlRec) {-    if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiSliderDragging)+    if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode)     {         Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); @@ -5003,7 +5168,7 @@             buffer[i] = '\0';   // Set an end of string at this point              counter++;-            if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break;+            if (counter > RAYGUI_TEXTSPLIT_MAX_ITEMS) break;         }     } @@ -5163,8 +5328,11 @@     if (value > maxValue) value = maxValue;     if (value < minValue) value = minValue; -    const int valueRange = maxValue - minValue;+    int valueRange = maxValue - minValue;+    if (valueRange <= 0) valueRange = 1;+     int sliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);+    if (sliderSize < 1) sliderSize = 1;  // TODO: Consider a minimum slider size      // Calculate rectangles for all of the components     arrowUpLeft = RAYGUI_CLITERAL(Rectangle){@@ -5205,13 +5373,13 @@     {         Vector2 mousePoint = GetMousePosition(); -        if (guiSliderDragging) // Keep dragging outside of bounds+        if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds         {             if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) &&                 !CheckCollisionPointRec(mousePoint, arrowUpLeft) &&                 !CheckCollisionPointRec(mousePoint, arrowDownRight))             {-                if (CHECK_BOUNDS_ID(bounds, guiSliderActive))+                if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))                 {                     state = STATE_PRESSED; @@ -5221,8 +5389,8 @@             }             else             {-                guiSliderDragging = false;-                guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };+                guiControlExclusiveMode = false;+                guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };             }         }         else if (CheckCollisionPointRec(mousePoint, bounds))@@ -5236,8 +5404,8 @@             // Handle mouse button down             if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))             {-                guiSliderDragging = true;-                guiSliderActive = bounds; // Store bounds as an identifier when dragging starts+                guiControlExclusiveMode = true;+                guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts                  // Check arrows click                 if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);@@ -5437,6 +5605,37 @@     return value*sign; } +// Get float value from text+// NOTE: This function replaces atof() [stdlib.h]+// WARNING: Only '.' character is understood as decimal point+static float TextToFloat(const char *text)+{+    float value = 0.0f;+    float sign = 1.0f;++    if ((text[0] == '+') || (text[0] == '-'))+    {+        if (text[0] == '-') sign = -1.0f;+        text++;+    }++    int i = 0;+    for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0');++    if (text[i++] != '.') value *= sign;+    else+    {+        float divisor = 10.0f;+        for (; ((text[i] >= '0') && (text[i] <= '9')); i++)+        {+            value += ((float)(text[i] - '0'))/divisor;+            divisor = divisor*10.0f;+        }+    }++    return value;+}+ // Encode codepoint into UTF-8 text (char array size returned as parameter) static const char *CodepointToUTF8(int codepoint, int *byteSize) {@@ -5490,21 +5689,21 @@     if (0xf0 == (0xf8 & ptr[0]))     {         // 4 byte UTF-8 codepoint-        if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks+        if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks         codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);         *codepointSize = 4;     }     else if (0xe0 == (0xf0 & ptr[0]))     {         // 3 byte UTF-8 codepoint */-        if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks+        if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks         codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);         *codepointSize = 3;     }     else if (0xc0 == (0xe0 & ptr[0]))     {         // 2 byte UTF-8 codepoint-        if((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks+        if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks         codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);         *codepointSize = 2;     }@@ -5514,7 +5713,6 @@         codepoint = ptr[0];         *codepointSize = 1;     }-      return codepoint; }
raylib/examples/shapes/shapes_bouncing_ball.c view
@@ -62,7 +62,7 @@             ClearBackground(RAYWHITE);              DrawCircleV(ballPosition, (float)ballRadius, MAROON);-            //DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY);+            DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY);              // On pause, we draw a blinking message             if (pause && ((framesCounter/30)%2)) DrawText("PAUSED", 350, 200, 30, GRAY);
raylib/examples/shapes/shapes_draw_circle_sector.c view
@@ -63,11 +63,11 @@              // Draw GUI controls             //-------------------------------------------------------------------------------            GuiSliderBar((Rectangle){ 600, 40, 120, 20}, "StartAngle", NULL, &startAngle, 0, 720);-            GuiSliderBar((Rectangle){ 600, 70, 120, 20}, "EndAngle", NULL, &endAngle, 0, 720);+            GuiSliderBar((Rectangle){ 600, 40, 120, 20}, "StartAngle", TextFormat("%.2f", startAngle), &startAngle, 0, 720);+            GuiSliderBar((Rectangle){ 600, 70, 120, 20}, "EndAngle", TextFormat("%.2f", endAngle), &endAngle, 0, 720); -            GuiSliderBar((Rectangle){ 600, 140, 120, 20}, "Radius", NULL, &outerRadius, 0, 200);-            GuiSliderBar((Rectangle){ 600, 170, 120, 20}, "Segments", NULL, &segments, 0, 100);+            GuiSliderBar((Rectangle){ 600, 140, 120, 20}, "Radius", TextFormat("%.2f", outerRadius), &outerRadius, 0, 200);+            GuiSliderBar((Rectangle){ 600, 170, 120, 20}, "Segments", TextFormat("%.2f", segments), &segments, 0, 100);             //------------------------------------------------------------------------------              minSegments = truncf(ceilf((endAngle - startAngle) / 90));
raylib/examples/shapes/shapes_draw_rectangle_rounded.c view
@@ -66,11 +66,11 @@              // Draw GUI controls             //-------------------------------------------------------------------------------            GuiSliderBar((Rectangle){ 640, 40, 105, 20 }, "Width", NULL, &width, 0, (float)GetScreenWidth() - 300);-            GuiSliderBar((Rectangle){ 640, 70, 105, 20 }, "Height", NULL, &height, 0, (float)GetScreenHeight() - 50);-            GuiSliderBar((Rectangle){ 640, 140, 105, 20 }, "Roundness", NULL, &roundness, 0.0f, 1.0f);-            GuiSliderBar((Rectangle){ 640, 170, 105, 20 }, "Thickness", NULL, &lineThick, 0, 20);-            GuiSliderBar((Rectangle){ 640, 240, 105, 20}, "Segments", NULL, &segments, 0, 60);+            GuiSliderBar((Rectangle){ 640, 40, 105, 20 }, "Width", TextFormat("%.2f", width), &width, 0, (float)GetScreenWidth() - 300);+            GuiSliderBar((Rectangle){ 640, 70, 105, 20 }, "Height", TextFormat("%.2f", height), &height, 0, (float)GetScreenHeight() - 50);+            GuiSliderBar((Rectangle){ 640, 140, 105, 20 }, "Roundness", TextFormat("%.2f", roundness), &roundness, 0.0f, 1.0f);+            GuiSliderBar((Rectangle){ 640, 170, 105, 20 }, "Thickness", TextFormat("%.2f", lineThick), &lineThick, 0, 20);+            GuiSliderBar((Rectangle){ 640, 240, 105, 20}, "Segments", TextFormat("%.2f", segments), &segments, 0, 60);              GuiCheckBox((Rectangle){ 640, 320, 20, 20 }, "DrawRoundedRect", &drawRoundedRect);             GuiCheckBox((Rectangle){ 640, 350, 20, 20 }, "DrawRoundedLines", &drawRoundedLines);
raylib/examples/shapes/shapes_draw_ring.c view
@@ -69,13 +69,13 @@              // Draw GUI controls             //-------------------------------------------------------------------------------            GuiSliderBar((Rectangle){ 600, 40, 120, 20 }, "StartAngle", NULL, &startAngle, -450, 450);-            GuiSliderBar((Rectangle){ 600, 70, 120, 20 }, "EndAngle", NULL, &endAngle, -450, 450);+            GuiSliderBar((Rectangle){ 600, 40, 120, 20 }, "StartAngle", TextFormat("%.2f", startAngle), &startAngle, -450, 450);+            GuiSliderBar((Rectangle){ 600, 70, 120, 20 }, "EndAngle", TextFormat("%.2f", endAngle), &endAngle, -450, 450); -            GuiSliderBar((Rectangle){ 600, 140, 120, 20 }, "InnerRadius", NULL, &innerRadius, 0, 100);-            GuiSliderBar((Rectangle){ 600, 170, 120, 20 }, "OuterRadius", NULL, &outerRadius, 0, 200);+            GuiSliderBar((Rectangle){ 600, 140, 120, 20 }, "InnerRadius", TextFormat("%.2f", innerRadius), &innerRadius, 0, 100);+            GuiSliderBar((Rectangle){ 600, 170, 120, 20 }, "OuterRadius", TextFormat("%.2f", outerRadius), &outerRadius, 0, 200); -            GuiSliderBar((Rectangle){ 600, 240, 120, 20 }, "Segments", NULL, &segments, 0, 100);+            GuiSliderBar((Rectangle){ 600, 240, 120, 20 }, "Segments", TextFormat("%.2f", segments), &segments, 0, 100);              GuiCheckBox((Rectangle){ 600, 320, 20, 20 }, "Draw Ring", &drawRing);             GuiCheckBox((Rectangle){ 600, 350, 20, 20 }, "Draw RingLines", &drawRingLines);
raylib/examples/text/text_input_box.c view
@@ -35,7 +35,7 @@      int framesCounter = 0; -    SetTargetFPS(10);               // Set our game to run at 10 frames-per-second+    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second     //--------------------------------------------------------------------------------------      // Main game loop
raylib/examples/text/text_writing_anim.c view
@@ -52,7 +52,7 @@             DrawText(TextSubtext(message, 0, framesCounter/10), 210, 160, 20, MAROON);              DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, LIGHTGRAY);-            DrawText("PRESS [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY);+            DrawText("HOLD [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY);          EndDrawing();         //----------------------------------------------------------------------------------
raylib/examples/textures/textures_blend_modes.c view
@@ -43,6 +43,9 @@     const int blendCountMax = 4;     BlendMode blendMode = 0; +    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second+    //---------------------------------------------------------------------------------------+     // Main game loop     while (!WindowShouldClose())    // Detect window close button or ESC key     {
raylib/examples/textures/textures_image_drawing.c view
@@ -47,7 +47,7 @@      UnloadImage(cat);       // Unload image from RAM -    // Load custom font for frawing on image+    // Load custom font for drawing on image     Font font = LoadFont("resources/custom_jupiter_crash.png");      // Draw over image using custom font
raylib/examples/textures/textures_image_rotate.c view
@@ -43,6 +43,8 @@     textures[2] = LoadTextureFromImage(imageNeg90);      int currentTexture = 0;++    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second     //---------------------------------------------------------------------------------------      // Main game loop
raylib/examples/textures/textures_logo_raylib.c view
@@ -27,6 +27,8 @@      // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)     Texture2D texture = LoadTexture("resources/raylib_logo.png");        // Texture loading++    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second     //---------------------------------------------------------------------------------------      // Main game loop
raylib/examples/textures/textures_raw_data.c view
@@ -63,6 +63,8 @@      Texture2D checked = LoadTextureFromImage(checkedIm);     UnloadImage(checkedIm);         // Unload CPU (RAM) image data (pixels)++    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second     //---------------------------------------------------------------------------------------      // Main game loop
raylib/examples/textures/textures_sprite_explosion.c view
@@ -48,8 +48,8 @@     bool active = false;     int framesCounter = 0; -    SetTargetFPS(120);-    //--------------------------------------------------------------------------------------+    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second+    //---------------------------------------------------------------------------------------      // Main game loop     while (!WindowShouldClose())    // Detect window close button or ESC key
− raylib/examples/textures/textures_svg_loading.c
@@ -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;-}
raylib/examples/textures/textures_to_image.c view
@@ -38,6 +38,8 @@      texture = LoadTextureFromImage(image);                 // Recreate texture from retrieved image data (RAM -> VRAM)     UnloadImage(image);                                    // Unload retrieved image data from CPU memory (RAM)++    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second     //---------------------------------------------------------------------------------------      // Main game loop
raylib/parser/raylib_parser.c view
@@ -72,7 +72,7 @@ #define MAX_CALLBACKS_TO_PARSE    64    // Maximum number of callbacks to parse #define MAX_FUNCS_TO_PARSE      1024    // Maximum number of functions to parse -#define MAX_LINE_LENGTH          512    // Maximum length of one line (including comments)+#define MAX_LINE_LENGTH         1024    // Maximum length of one line (including comments)  #define MAX_STRUCT_FIELDS         64    // Maximum number of struct fields #define MAX_ENUM_VALUES          512    // Maximum number of enum values@@ -139,7 +139,7 @@ // Function info data typedef struct FunctionInfo {     char name[64];              // Function name-    char desc[128];             // Function description (comment at the end)+    char desc[512];             // Function description (comment at the end)     char retType[32];           // Return value type     int paramCount;             // Number of function parameters     char paramType[MAX_FUNCTION_PARAMETERS][32];   // Parameters type
raylib/src/config.h view
@@ -113,13 +113,23 @@ #define RL_CULL_DISTANCE_FAR              1000.0      // Default projection matrix far cull distance  // Default shader vertex attribute locations-#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION  0-#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD  1-#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL    2-#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR     3-#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT   4-#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION    0+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD    1+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL      2+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR       3+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT     4+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2   5+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES     6 ++#define RL_SUPPORT_MESH_GPU_SKINNING                   // Remove this if your GPU does not support more than 8 VBOs++#ifdef RL_SUPPORT_MESH_GPU_SKINNING+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS     7+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8+#endif++ // Default shader vertex attribute names to set location points // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION     "vertexPosition"    // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION@@ -170,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@@ -225,7 +234,12 @@ // rmodels: Configuration values //------------------------------------------------------------------------------------ #define MAX_MATERIAL_MAPS              12       // Maximum number of shader maps supported++#ifdef RL_SUPPORT_MESH_GPU_SKINNING+#define MAX_MESH_VERTEX_BUFFERS         9       // Maximum vertex buffers (VBO) per mesh+#else #define MAX_MESH_VERTEX_BUFFERS         7       // Maximum vertex buffers (VBO) per mesh+#endif  //------------------------------------------------------------------------------------ // Module: raudio - Configuration Flags
raylib/src/external/RGFW.h view
@@ -54,6580 +54,8940 @@ 	#define RGFW_MALLOC x - choose what function to use to allocate, by default the standard malloc is used 	#define RGFW_CALLOC x - choose what function to use to allocate (calloc), by default the standard calloc is used 	#define RGFW_FREE x - choose what function to use to allocated memory, by default the standard free is used-*/--/*-	Credits :-		EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support, siliapp.h -> referencing --		stb - This project is heavily inspired by the stb single header files--		GLFW:-			certain parts of winapi and X11 are very poorly documented,-			GLFW's source code was referenced and used throughout the project (used code is marked in some way),-			this mainly includes, code for drag and drops, code for setting the icon to a bitmap and the code for managing the clipboard for X11 (as these parts are not documented very well)--			GLFW Copyright, https::/github.com/GLFW/GLFW--			Copyright (c) 2002-2006 Marcus Geelnard-			Copyright (c) 2006-2019 Camilla Löwy--		contributors : (feel free to put yourself here if you contribute)-		krisvers -> code review-		EimaMei (SaCode) -> code review-		Code-Nycticebus -> bug fixes-		Rob Rohan -> X11 bugs and missing features-		AICDG (@THISISAGOODNAME) -> vulkan support (example)-*/--#ifndef RGFW_MALLOC-#include <stdlib.h>-#include <time.h>-#define RGFW_MALLOC malloc-#define RGFW_CALLOC calloc-#define RGFW_FREE free-#endif--#if !_MSC_VER-#ifndef inline-#ifndef __APPLE__-#define inline __inline-#endif-#endif-#endif--/* for windows 95 testing (not that it works well) */-#ifdef RGFW_WIN95-#define RGFW_NO_MONITOR-#define RGFW_NO_PASSTHROUGH-#endif--#ifndef RGFWDEF-#ifdef __APPLE__-#define RGFWDEF static inline-#else-#define RGFWDEF inline-#endif-#endif--#ifndef RGFW_ENUM-#define RGFW_ENUM(type, name) type name; enum-#endif--#ifndef RGFW_UNUSED-#define RGFW_UNUSED(x) (void)(x);-#endif--#ifdef __cplusplus-extern "C" {-#endif--	/* makes sure the header file part is only defined once by default */-#ifndef RGFW_HEADER--#define RGFW_HEADER--#if !defined(u8)-	#if defined(_MSC_VER) || defined(__SYMBIAN32__)-		typedef unsigned char 	u8;-		typedef signed char		i8;-		typedef unsigned short  u16;-		typedef signed short 	i16;-		typedef unsigned int 	u32;-		typedef signed int		i32;-		typedef unsigned long	u64;-		typedef signed long		i64;-	#else-		#include <stdint.h>--		typedef uint8_t     u8;-		typedef int8_t      i8;-		typedef uint16_t   u16;-		typedef int16_t    i16;-		typedef uint32_t   u32;-		typedef int32_t    i32;-		typedef uint64_t   u64;-		typedef int64_t    i64;-	#endif-#endif--#if !defined(b8)-	typedef u8 b8;-#endif--#if defined(RGFW_X11) && defined(__APPLE__)-#define RGFW_MACOS_X11-#undef __APPLE__-#endif--#if defined(_WIN32) && !defined(RGFW_X11) /* (if you're using X11 on windows some how) */--	/* this name looks better */-	/* plus it helps with cross-compiling because RGFW_X11 won't be accidently defined */-	-#define RGFW_WINDOWS--#if defined(_WIN32) && !defined(WIN32)-#define WIN32-#endif--#if defined(_WIN64)--#ifndef WIN64-#define WIN64-#endif--#define _AMD64_-#undef _X86_-#else-#undef _AMD64_-#ifndef _X86_-#define _X86_-#endif-#endif--#ifndef RGFW_NO_XINPUT-#ifdef __MINGW32__-#include <xinput.h>-#else-#include <XInput.h>-#endif-#endif--#else -#if defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)-#define RGFW_MACOS_X11-#define RGFW_X11-#include <X11/Xlib.h>-#endif-#endif 	--#if defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11)-#define RGFW_MACOS-#endif--#if (defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)) && !defined(RGFW_EGL)-#define RGFW_EGL-#endif-#if defined(RGFW_EGL) && defined(__APPLE__)-	#warning  EGL is not supported for Cocoa, switching back to the native opengl api-#undef RGFW_EGL-#endif--#if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API)-#define RGFW_OPENGL-#endif--#if defined(RGFW_X11) && (defined(RGFW_OPENGL))-#ifndef GLX_MESA_swap_control-#define  GLX_MESA_swap_control-#endif-#include <GL/glx.h> /* GLX defs, xlib.h, gl.h */-#endif--#ifdef RGFW_EGL-#include <EGL/egl.h>-#endif--#ifdef RGFW_OSMESA-#ifndef __APPLE__-#include <GL/osmesa.h>-#else-#include <OpenGL/osmesa.h>-#endif-#endif--#if defined(RGFW_DIRECTX) && defined(RGFW_WINDOWS)-#include <d3d11.h>-#include <dxgi.h>-#include <dxgi.h>-#include <d3dcompiler.h>--#ifndef __cplusplus-#define __uuidof(T) IID_##T-#endif-#endif--#ifndef RGFW_ALPHA-#define RGFW_ALPHA 128 /* alpha value for RGFW_TRANSPARENT_WINDOW (WINAPI ONLY, macOS + linux don't need this) */-#endif--/*! Optional arguments for making a windows */-#define RGFW_TRANSPARENT_WINDOW		(1L<<9) /*!< the window is transparent (only properly works on X11 and MacOS, although it's although for windows) */-#define RGFW_NO_BORDER		(1L<<3) /*!< the window doesn't have border */-#define RGFW_NO_RESIZE		(1L<<4) /*!< the window cannot be resized  by the user */-#define RGFW_ALLOW_DND     (1L<<5) /*!< the window supports drag and drop*/-#define RGFW_HIDE_MOUSE (1L<<6) /*! the window should hide the mouse or not (can be toggled later on) using `RGFW_window_mouseShow*/-#define RGFW_FULLSCREEN (1L<<8) /* the window is fullscreen by default or not */-#define RGFW_CENTER (1L<<10) /*! center the window on the screen */-#define RGFW_OPENGL_SOFTWARE (1L<<11) /*! use OpenGL software rendering */-#define RGFW_COCOA_MOVE_TO_RESOURCE_DIR (1L << 12) /* (cocoa only), move to resource folder */-#define RGFW_SCALE_TO_MONITOR (1L << 13) /* scale the window to the screen */-#define RGFW_NO_INIT_API (1L << 2) /* DO not init an API (mostly for bindings, you should use `#define RGFW_NO_API` in C */--#define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/-#define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/---/*! event codes */-#define RGFW_keyPressed 2 /* a key has been pressed */-#define RGFW_keyReleased 3 /*!< a key has been released*/-/*! key event note-	the code of the key pressed is stored in-	RGFW_Event.keyCode-	!!Keycodes defined at the bottom of the RGFW_HEADER part of this file!!--	while a string version is stored in-	RGFW_Event.KeyString--	RGFW_Event.lockState holds the current lockState-	this means if CapsLock, NumLock are active or not-*/-#define RGFW_mouseButtonPressed 4 /*!< a mouse button has been pressed (left,middle,right)*/-#define RGFW_mouseButtonReleased 5 /*!< a mouse button has been released (left,middle,right)*/-#define RGFW_mousePosChanged 6 /*!< the position of the mouse has been changed*/-/*! mouse event note-	the x and y of the mouse can be found in the vector, RGFW_Event.point--	RGFW_Event.button holds which mouse button was pressed-*/-#define RGFW_jsButtonPressed 7 /*!< a joystick button was pressed */-#define RGFW_jsButtonReleased 8 /*!< a joystick button was released */-#define RGFW_jsAxisMove 9 /*!< an axis of a joystick was moved*/-/*! joystick event note-	RGFW_Event.joystick holds which joystick was altered, if any-	RGFW_Event.button holds which joystick button was pressed--	RGFW_Event.axis holds the data of all the axis-	RGFW_Event.axisCount says how many axis there are-*/-#define RGFW_windowMoved 10 /*!< the window was moved (by the user) */-#define RGFW_windowResized 11 /*!< the window was resized (by the user) */--#define RGFW_focusIn 12 /*!< window is in focus now */-#define RGFW_focusOut 13 /*!< window is out of focus now */--#define RGFW_mouseEnter 14 /* mouse entered the window */-#define RGFW_mouseLeave 15 /* mouse left the window */--#define RGFW_windowRefresh 16 /* The window content needs to be refreshed */--/* attribs change event note-	The event data is sent straight to the window structure-	with win->r.x, win->r.y, win->r.w and win->r.h-*/-#define RGFW_quit 33 /*!< the user clicked the quit button*/ -#define RGFW_dnd 34 /*!< a file has been dropped into the window*/-#define RGFW_dnd_init 35 /*!< the start of a dnd event, when the place where the file drop is known */-/* dnd data note-	The x and y coords of the drop are stored in the vector RGFW_Event.point--	RGFW_Event.droppedFilesCount holds how many files were dropped--	This is also the size of the array which stores all the dropped file string,-	RGFW_Event.droppedFiles-*/--/*! mouse button codes (RGFW_Event.button) */-#define RGFW_mouseLeft  1 /*!< left mouse button is pressed*/-#define RGFW_mouseMiddle  2 /*!< mouse-wheel-button is pressed*/-#define RGFW_mouseRight  3 /*!< right mouse button is pressed*/-#define RGFW_mouseScrollUp  4 /*!< mouse wheel is scrolling up*/-#define RGFW_mouseScrollDown  5 /*!< mouse wheel is scrolling down*/--#ifndef RGFW_MAX_PATH-#define RGFW_MAX_PATH 260 /* max length of a path (for dnd) */-#endif-#ifndef RGFW_MAX_DROPS-#define RGFW_MAX_DROPS 260 /* max items you can drop at once */-#endif---/* for RGFW_Event.lockstate */-#define RGFW_CAPSLOCK (1L << 1)-#define RGFW_NUMLOCK (1L << 2)--/*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */-#ifndef RGFW_joystick_codes--typedef RGFW_ENUM(u8, RGFW_joystick_codes) {-	RGFW_JS_A = 0, /* or PS X button */-	RGFW_JS_B = 1, /* or PS circle button */-	RGFW_JS_Y = 2, /* or PS triangle button */-	RGFW_JS_X = 3, /* or PS square button */-	RGFW_JS_START = 9, /* start button */-	RGFW_JS_SELECT = 8, /* select button */-	RGFW_JS_HOME = 10, /* home button */-	RGFW_JS_UP = 13, /* dpad up */-	RGFW_JS_DOWN = 14, /* dpad down*/-	RGFW_JS_LEFT = 15, /* dpad left */-	RGFW_JS_RIGHT = 16, /* dpad right */-	RGFW_JS_L1 = 4, /* left bump */-	RGFW_JS_L2 = 5, /* left trigger*/- 	RGFW_JS_R1 = 6, /* right bumper */-	RGFW_JS_R2 = 7, /* right trigger */-};--#endif--/* basic vector type, if there's not already a point/vector type of choice */-#ifndef RGFW_vector-typedef struct { i32 x, y; } RGFW_vector;-#endif--	/* basic rect type, if there's not already a rect type of choice */-#ifndef RGFW_rect-	typedef struct { i32 x, y, w, h; } RGFW_rect;-#endif--	/* basic area type, if there's not already a area type of choice */-#ifndef RGFW_area-	typedef struct { u32 w, h; } RGFW_area;-#endif--#define RGFW_VECTOR(x, y) (RGFW_vector){x, y}-#define RGFW_RECT(x, y, w, h) (RGFW_rect){x, y, w, h}-#define RGFW_AREA(w, h) (RGFW_area){w, h}--	#ifndef RGFW_NO_MONITOR-	typedef struct RGFW_monitor {-		char name[128];  /* monitor name */-		RGFW_rect rect; /* monitor Workarea */-		float scaleX, scaleY; /* monitor content scale*/-		float physW, physH; /* monitor physical size */-	} RGFW_monitor;--	/*-	NOTE : Monitor functions should be ran only as many times as needed (not in a loop)-	*/--	/* get an array of all the monitors (max 6) */-	RGFWDEF RGFW_monitor* RGFW_getMonitors(void);-	/* get the primary monitor */-	RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void);-	#endif--	/* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */-	typedef struct RGFW_Event {-		char keyName[16]; /* key name of event*/--		/*! drag and drop data */-		/* 260 max paths with a max length of 260 */-#ifdef RGFW_ALLOC_DROPFILES-		char** droppedFiles;-#else-		char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH]; /*!< dropped files*/-#endif-		u32 droppedFilesCount; /*!< house many files were dropped */--		u32 type; /*!< which event has been sent?*/-		RGFW_vector point; /*!< mouse x, y of event (or drop point) */-		-		u32 fps; /*the current fps of the window [the fps is checked when events are checked]*/-		u64 frameTime, frameTime2; /* this is used for counting the fps */-		-		u8 keyCode; /*!< keycode of event 	!!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */--		b8 inFocus;  /*if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */--		u8 lockState;--		u16 joystick; /* which joystick this event applies to (if applicable to any) */--		u8 button; /*!< which mouse button has been clicked (0) left (1) middle (2) right OR which joystick button was pressed*/-		double scroll; /* the raw mouse scroll value */--		u8 axisesCount; /* number of axises */-		RGFW_vector axis[2]; /* x, y of axises (-100 to 100) */-	} RGFW_Event; /*!< Event structure for checking/getting events */--	/* source data for the window (used by the APIs) */-	typedef struct RGFW_window_src {-#ifdef RGFW_WINDOWS-		HWND window; /*!< source window */-		HDC hdc; /*!< source HDC */-		u32 hOffset; /*!< height offset for window */-#endif-#ifdef RGFW_X11-		Display* display; /*!< source display */-		Window window; /*!< source window */-#endif-#ifdef RGFW_MACOS-		u32 display;-		void* displayLink;-		void* window;-		b8 dndPassed;-#endif--#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA)-#ifdef RGFW_MACOS-		void* rSurf; /*!< source graphics context */-#endif-#ifdef RGFW_WINDOWS-		HGLRC rSurf; /*!< source graphics context */-#endif-#ifdef RGFW_X11-		GLXContext rSurf; /*!< source graphics context */-#endif-#else--#ifdef RGFW_OSMESA-		OSMesaContext rSurf;-#endif-#endif--#ifdef RGFW_WINDOWS-		RGFW_area maxSize, minSize;-#if defined(RGFW_DIRECTX)-		IDXGISwapChain* swapchain;-		ID3D11RenderTargetView* renderTargetView;-		ID3D11DepthStencilView* pDepthStencilView;-#endif-#endif--#if defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11)-		void* view; /*apple viewpoint thingy*/-#endif--#ifdef RGFW_EGL-		EGLSurface EGL_surface;-		EGLDisplay EGL_display;-		EGLContext EGL_context;-#endif--#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) -#ifdef RGFW_WINDOWS-		HBITMAP bitmap;-#endif-#ifdef RGFW_X11-		XImage* bitmap;-		GC gc;-#endif-#ifdef RGFW_MACOS-		void* bitmap; /* API's bitmap for storing or managing */-		void* image;-#endif-#if defined(RGFW_BUFFER) && defined(RGFW_WINDOWS)-		HDC hdcMem; /* window stored in memory that winapi needs to render buffers */-#endif-#endif--		u8 jsPressed[4][16]; /* if a key is currently pressed or not (per joystick) */--		i32 joysticks[4]; /* limit of 4 joysticks at a time */-		u16 joystickCount; /* the actual amount of joysticks */--		RGFW_area scale; /* window scaling */--#ifdef RGFW_MACOS-		b8 cursorChanged; /* for steve jobs */-#endif--		u32 winArgs; /* windows args (for RGFW to check) */-		/*-			!< if dnd is enabled or on (based on window creating args)-			cursorChanged-		*/-	} RGFW_window_src;--	typedef struct RGFW_window {-		RGFW_window_src src;--#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) -		u8* buffer; /* buffer for non-GPU systems (OSMesa, basic software rendering) */-		/* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */-#endif--		RGFW_Event event; /*!< current event */--		RGFW_rect r; /* the x, y, w and h of the struct */--		u32 fpsCap; /*!< the fps cap of the window should run at (change this var to change the fps cap, 0 = no limit)*/-		/*[the fps is capped when events are checked]*/-	} RGFW_window; /*!< Window structure for managing the window */--#if defined(RGFW_X11) || defined(RGFW_MACOS)-	typedef u64 RGFW_thread; /* thread type unix */-#else-	typedef void* RGFW_thread; /* thread type for window */-#endif--	/* this has to be set before createWindow is called, else the fulscreen size is used */-	RGFWDEF void RGFW_setBufferSize(RGFW_area size); /* the buffer cannot be resized (by RGFW) */--	RGFW_window* RGFW_createWindow(-		const char* name, /* name of the window */-		RGFW_rect rect, /* rect of window */-		u16 args /* extra arguments (NULL / (u16)0 means no args used)*/-	); /*!< function to create a window struct */--	/* get the size of the screen to an area struct */-	RGFWDEF RGFW_area RGFW_getScreenSize(void);--	/*-		this function checks an *individual* event (and updates window structure attributes)-		this means, using this function without a while loop may cause event lag--		ex.--		while (RGFW_window_checkEvent(win) != NULL) [this keeps checking events until it reaches the last one]--		this function is optional if you choose to use event callbacks, -		although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents`-	*/--	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/--	/* -		check all the events until there are none left,  -		this should only be used if you're using callbacks only-	*/-	RGFWDEF void RGFW_window_checkEvents(RGFW_window* win);---	/*! window managment functions*/-	RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */--	RGFWDEF void RGFW_window_move(RGFW_window* win,-		RGFW_vector v/* new pos*/-	);--	#ifndef RGFW_NO_MONITOR-	/* move to a specific monitor */-	RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m);-	#endif-	RGFWDEF void RGFW_window_resize(RGFW_window* win,-		RGFW_area a/* new size*/-	);--	/* set the minimum size a user can shrink a window */-	RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a);-	/* set the minimum size a user can extend a window */-	RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a);--	RGFWDEF void RGFW_window_maximize(RGFW_window* win); /* maximize the window size */-	RGFWDEF void RGFW_window_minimize(RGFW_window* win); /* minimize the window (in taskbar (per OS))*/-	RGFWDEF void RGFW_window_restore(RGFW_window* win); /* restore the window from minimized (per OS)*/--	RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border); /* if the window should have a border or not (borderless) based on bool value of `border` */-	-	RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow); /* turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/--	#ifndef RGFW_NO_PASSTHROUGH-	RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough); /* turn on / off mouse passthrough */-	#endif --	RGFWDEF void RGFW_window_setName(RGFW_window* win,-		char* name-	);--	void RGFW_window_setIcon(RGFW_window* win, /*!< source window */-		u8* icon /*!< icon bitmap */,-		RGFW_area a /*!< width and height of the bitmap*/,-		i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */-	); /*!< image resized by default */--	/*!< sets mouse to bitmap (very simular to RGFW_window_setIcon), image NOT resized by default*/-	RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels);--	/*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */-	RGFWDEF	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse);--	RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /* sets the mouse to1` the default mouse image */-	/*-		holds the mouse in place by moving the mouse back each time it moves-		you can still use win->event.point to see how much it moved before it was put back in place--		this is useful for a 3D camera-	*/-	RGFWDEF void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area);-	/* undo hold */-	RGFWDEF void RGFW_window_mouseUnhold(RGFW_window* win);--	/* hide the window */-	RGFWDEF void RGFW_window_hide(RGFW_window* win);-	/* show the window */-	RGFWDEF void RGFW_window_show(RGFW_window* win);--	/*-		makes it so `RGFW_window_shouldClose` returns true-		by setting the window event.type to RGFW_quit-	*/-	RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win);--	/* where the mouse is on the screen */-	RGFWDEF RGFW_vector RGFW_getGlobalMousePoint(void);--	/* where the mouse is on the window */-	RGFWDEF RGFW_vector RGFW_window_getMousePoint(RGFW_window* win);--	/* show the mouse or hide the mouse*/-	RGFWDEF void RGFW_window_showMouse(RGFW_window* win, i8 show);-	/* move the mouse to a set x, y pos*/-	RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v);--	/* if the window should close (RGFW_close was sent or escape was pressed) */-	RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win);-	/* if window is fullscreen'd */-	RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win);-	/* if window is hidden */-	RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win);-	/* if window is minimized */-	RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win);-	/* if window is maximized */-	RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win);---	#ifndef RGFW_NO_MONITOR-	/*-	scale the window to the monitor,-	this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation-	*/-	RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win);-	/* get the struct of the window's monitor  */-	RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win);-	#endif--	/*!< make the window the current opengl drawing context */-	RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win);--	/*error handling*/-	RGFWDEF b8 RGFW_Error(void); /* returns true if an error has occurred (doesn't print errors itself) */--	/*!< if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/-	RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/--	RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks prev keymap only) (key code)*/--	RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code)*/-	RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/--	RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key);--	RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button);-	RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button);-	RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button);-	RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button);--/*! clipboard functions*/-	RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */-	RGFWDEF void RGFW_clipboardFree(char* str); /* the string returned from RGFW_readClipboard must be freed */--	RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */--	/* -		-		-		Event callbacks, -		these are completely optional, you can use the normal -		RGFW_checkEvent() method if you prefer that--	*/--	/* RGFW_windowMoved, the window and its new rect value  */-	typedef void (* RGFW_windowmovefunc)(RGFW_window* win, RGFW_rect r);-	/* RGFW_windowResized, the window and its new rect value  */-	typedef void (* RGFW_windowresizefunc)(RGFW_window* win, RGFW_rect r);-	/* RGFW_quit, the window that was closed */-	typedef void (* RGFW_windowquitfunc)(RGFW_window* win);-	/* RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */-	typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus);-	/* RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */-	typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_vector point, b8 status);-	/* RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse  */-	typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_vector point);-	/* RGFW_dnd_init, the window, the point of the drop on the windows */-	typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_vector point);-	/* RGFW_windowRefresh, the window that needs to be refreshed */-	typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win);-	/* RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */-	typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed);-	/* RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release)  */-	typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed);-	/* RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */-	typedef void (* RGFW_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed);-	/* RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */-	typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_vector axis[2], u8 axisesCount);-	-	/*  RGFW_dnd, the window that had the drop, the drop data and the amount files dropped */-	#ifdef RGFW_ALLOC_DROPFILES-	typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount);-	#else-	typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount);-	#endif--	RGFWDEF void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func);-	RGFWDEF void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func);-	RGFWDEF void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func);-	RGFWDEF void RGFW_setMousePosCallback(RGFW_mouseposfunc func);-	RGFWDEF void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func);-	RGFWDEF void RGFW_setFocusCallback(RGFW_focusfunc func);-	RGFWDEF void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func);-	RGFWDEF void RGFW_setDndCallback(RGFW_dndfunc func);-	RGFWDEF void RGFW_setDndInitCallback(RGFW_dndInitfunc func);-	RGFWDEF void RGFW_setKeyCallback(RGFW_keyfunc func);-	RGFWDEF void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func);-	RGFWDEF void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func);-	RGFWDEF void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func);---#ifndef RGFW_NO_THREADS-	/*! threading functions*/--	/*! NOTE! (for X11/linux) : if you define a window in a thread, it must be run after the original thread's window is created or else there will be a memory error */-	/*-		I'd suggest you use sili's threading functions instead-		if you're going to use sili-		which is a good idea generally-	*/--	#if defined(__unix__) || defined(__APPLE__) -	typedef void* (* RGFW_threadFunc_ptr)(void*);-	#else-	typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter);  -	#endif--	RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/-	RGFWDEF void RGFW_cancelThread(RGFW_thread thread); /*!< cancels a thread*/-	RGFWDEF void RGFW_joinThread(RGFW_thread thread); /*!< join thread to current thread */-	RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority  */-#endif--	/*! gamepad/joystick functions (linux-only currently) */--	/*! joystick count starts at 0*/-	/*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/-	RGFWDEF u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber);-	RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file);--	RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button);--	/*! native opengl functions */-#ifdef RGFW_OPENGL-/*! Get max OpenGL version */-	RGFWDEF u8* RGFW_getMaxGLVersion(void);-	/* OpenGL init hints */-	RGFWDEF void RGFW_setGLStencil(i32 stencil); /* set stencil buffer bit size (8 by default) */-	RGFWDEF void RGFW_setGLSamples(i32 samples); /* set number of sampiling buffers (4 by default) */-	RGFWDEF void RGFW_setGLStereo(i32 stereo); /* use GL_STEREO (GL_FALSE by default) */-	RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /* number of aux buffers (0 by default) */--	/*! Set OpenGL version hint */-	RGFWDEF void RGFW_setGLVersion(i32 major, i32 minor);-	RGFWDEF void* RGFW_getProcAddress(const char* procname); /* get native opengl proc address */-	RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /* to be called by RGFW_window_makeCurrent */-#endif-	/* supports openGL, directX, OSMesa, EGL and software rendering */-	RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /* swap the rendering buffer */-	RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval);--	RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set);-	RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set);-#ifdef RGFW_DIRECTX-	typedef struct {-		IDXGIFactory* pFactory;-		IDXGIAdapter* pAdapter;-		ID3D11Device* pDevice;-		ID3D11DeviceContext* pDeviceContext;-	} RGFW_directXinfo;--	/*-		RGFW stores a global instance of RGFW_directXinfo,-		you can use this function to get a pointer the instance-	*/-	RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void);-#endif--	/*! Supporting functions */-	RGFWDEF void RGFW_window_checkFPS(RGFW_window* win); /*!< updates fps / sets fps to cap (ran by RGFW_window_checkEvent)*/-	RGFWDEF u64 RGFW_getTime(void); /* get time in seconds */-	RGFWDEF u64 RGFW_getTimeNS(void); /* get time in nanoseconds */-	RGFWDEF void RGFW_sleep(u64 microsecond); /* sleep for a set time */--	typedef RGFW_ENUM(u8, RGFW_Key) {-		RGFW_KEY_NULL = 0,-		RGFW_Escape,-		RGFW_F1,-		RGFW_F2,-		RGFW_F3,-		RGFW_F4,-		RGFW_F5,-		RGFW_F6,-		RGFW_F7,-		RGFW_F8,-		RGFW_F9,-		RGFW_F10,-		RGFW_F11,-		RGFW_F12,--		RGFW_Backtick,--		RGFW_0,-		RGFW_1,-		RGFW_2,-		RGFW_3,-		RGFW_4,-		RGFW_5,-		RGFW_6,-		RGFW_7,-		RGFW_8,-		RGFW_9,--		RGFW_Minus,-		RGFW_Equals,-		RGFW_BackSpace,-		RGFW_Tab,-		RGFW_CapsLock,-		RGFW_ShiftL,-		RGFW_ControlL,-		RGFW_AltL,-		RGFW_SuperL,-		RGFW_ShiftR,-		RGFW_ControlR,-		RGFW_AltR,-		RGFW_SuperR,-		RGFW_Space,--		RGFW_a,-		RGFW_b,-		RGFW_c,-		RGFW_d,-		RGFW_e,-		RGFW_f,-		RGFW_g,-		RGFW_h,-		RGFW_i,-		RGFW_j,-		RGFW_k,-		RGFW_l,-		RGFW_m,-		RGFW_n,-		RGFW_o,-		RGFW_p,-		RGFW_q,-		RGFW_r,-		RGFW_s,-		RGFW_t,-		RGFW_u,-		RGFW_v,-		RGFW_w,-		RGFW_x,-		RGFW_y,-		RGFW_z,--		RGFW_Period,-		RGFW_Comma,-		RGFW_Slash,-		RGFW_Bracket,-		RGFW_CloseBracket,-		RGFW_Semicolon,-		RGFW_Return,-		RGFW_Quote,-		RGFW_BackSlash,--		RGFW_Up,-		RGFW_Down,-		RGFW_Left,-		RGFW_Right,--		RGFW_Delete,-		RGFW_Insert,-		RGFW_End,-		RGFW_Home,-		RGFW_PageUp,-		RGFW_PageDown,--		RGFW_Numlock,-		RGFW_KP_Slash,-		RGFW_Multiply,-		RGFW_KP_Minus,-		RGFW_KP_1,-		RGFW_KP_2,-		RGFW_KP_3,-		RGFW_KP_4,-		RGFW_KP_5,-		RGFW_KP_6,-		RGFW_KP_7,-		RGFW_KP_8,-		RGFW_KP_9,-		RGFW_KP_0,-		RGFW_KP_Period,-		RGFW_KP_Return,--		final_key,-	};--	typedef RGFW_ENUM(u8, RGFW_mouseIcons) {-		RGFW_MOUSE_NORMAL = 0,-		RGFW_MOUSE_ARROW,-		RGFW_MOUSE_IBEAM,-		RGFW_MOUSE_CROSSHAIR,-		RGFW_MOUSE_POINTING_HAND,-		RGFW_MOUSE_RESIZE_EW,-		RGFW_MOUSE_RESIZE_NS,-		RGFW_MOUSE_RESIZE_NWSE,-		RGFW_MOUSE_RESIZE_NESW,-		RGFW_MOUSE_RESIZE_ALL,-		RGFW_MOUSE_NOT_ALLOWED,-	};--#endif /* RGFW_HEADER */--	/*-	Example to get you started :--	linux : gcc main.c -lX11 -lXcursor -lGL-	windows : gcc main.c -lopengl32 -lshell32 -lgdi32-	macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo--	#define RGFW_IMPLEMENTATION-	#include "RGFW.h"--	u8 icon[4 * 3 * 3] = {0xFF, 0x00, 0x00, 0xFF,    0xFF, 0x00, 0x00, 0xFF,     0xFF, 0x00, 0x00, 0xFF,   0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF,     0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF};--	int main() {-		RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0);--		RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4);--		for (;;) {-			RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag-			if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape))-				break;--			RGFW_window_swapBuffers(win);--			glClearColor(0xFF, 0XFF, 0xFF, 0xFF);-			glClear(GL_COLOR_BUFFER_BIT);-		}--		RGFW_window_close(win);-	}--		compiling :--		if you wish to compile the library all you have to do is create a new file with this in it--		rgfw.c-		#define RGFW_IMPLEMENTATION-		#include "RGFW.h"--		then you can use gcc (or whatever compile you wish to use) to compile the library into object file--		ex. gcc -c RGFW.c -fPIC--		after you compile the library into an object file, you can also turn the object file into an static or shared library--		(commands ar and gcc can be replaced with whatever equivalent your system uses)-		static : ar rcs RGFW.a RGFW.o-		shared :-			windows:-				gcc -shared RGFW.o -lopengl32 -lshell32 -lgdi32 -o RGFW.dll-			linux:-				gcc -shared RGFW.o -lX11 -lXcursor -lGL -o RGFW.so-			macos:-				gcc -shared RGFW.o -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo-	*/--#ifdef RGFW_X11-#define RGFW_OS_BASED_VALUE(l, w, m) l-#endif-#ifdef RGFW_WINDOWS-#define RGFW_OS_BASED_VALUE(l, w, m) w-#endif-#ifdef RGFW_MACOS-#define RGFW_OS_BASED_VALUE(l, w, m) m-#endif-#ifdef RGFW_IMPLEMENTATION--#include <stdio.h>-#include <string.h>-#include <math.h>-#include <assert.h>--/*-RGFW_IMPLEMENTATION starts with generic RGFW defines--This is the start of keycode data--Why not use macros instead of the numbers itself?-Windows -> Not all virtual keys are macros (VK_0 - VK_1, VK_a - VK_z)-Linux -> Only symcodes are values, (XK_0 - XK_1, XK_a - XK_z) are larger than 0xFF00, I can't find any way to work with them without making the array an unreasonable size-MacOS -> windows and linux already don't have keycodes as macros, so there's no point-*/--	u8 RGFW_keycodes[] = {-		[RGFW_OS_BASED_VALUE(49, 192, 50)] = RGFW_Backtick,--		[RGFW_OS_BASED_VALUE(19, 0x30, 29)] = RGFW_0,-		[RGFW_OS_BASED_VALUE(10, 0x31, 18)] = RGFW_1,-		[RGFW_OS_BASED_VALUE(11, 0x32, 19)] = RGFW_2,-		[RGFW_OS_BASED_VALUE(12, 0x33, 20)] = RGFW_3,-		[RGFW_OS_BASED_VALUE(13, 0x34, 21)] = RGFW_4,-		[RGFW_OS_BASED_VALUE(14, 0x35, 23)] = RGFW_5,-		[RGFW_OS_BASED_VALUE(15, 0x36, 22)] = RGFW_6,-		[RGFW_OS_BASED_VALUE(16, 0x37, 26)] = RGFW_7,-		[RGFW_OS_BASED_VALUE(17, 0x38, 28)] = RGFW_8,-		[RGFW_OS_BASED_VALUE(18, 0x39, 25)] = RGFW_9,--		[RGFW_OS_BASED_VALUE(65, 0x20, 49)] = RGFW_Space,--		[RGFW_OS_BASED_VALUE(38, 0x41, 0)] = RGFW_a,-		[RGFW_OS_BASED_VALUE(56, 0x42, 11)] = RGFW_b,-		[RGFW_OS_BASED_VALUE(54, 0x43, 8)] = RGFW_c,-		[RGFW_OS_BASED_VALUE(40, 0x44, 2)] = RGFW_d,-		[RGFW_OS_BASED_VALUE(26, 0x45, 14)] = RGFW_e,-		[RGFW_OS_BASED_VALUE(41, 0x46, 3)] = RGFW_f,-		[RGFW_OS_BASED_VALUE(42, 0x47, 5)] = RGFW_g,-		[RGFW_OS_BASED_VALUE(43, 0x48, 4)] = RGFW_h,-		[RGFW_OS_BASED_VALUE(31, 0x49, 34)] = RGFW_i,-		[RGFW_OS_BASED_VALUE(44, 0x4A, 38)] = RGFW_j,-		[RGFW_OS_BASED_VALUE(45, 0x4B, 40)] = RGFW_k,-		[RGFW_OS_BASED_VALUE(46, 0x4C, 37)] = RGFW_l,-		[RGFW_OS_BASED_VALUE(58, 0x4D, 46)] = RGFW_m,-		[RGFW_OS_BASED_VALUE(57, 0x4E, 45)] = RGFW_n,-		[RGFW_OS_BASED_VALUE(32, 0x4F, 31)] = RGFW_o,-		[RGFW_OS_BASED_VALUE(33, 0x50, 35)] = RGFW_p,-		[RGFW_OS_BASED_VALUE(24, 0x51, 12)] = RGFW_q,-		[RGFW_OS_BASED_VALUE(27, 0x52, 15)] = RGFW_r,-		[RGFW_OS_BASED_VALUE(39, 0x53, 1)] = RGFW_s,-		[RGFW_OS_BASED_VALUE(28, 0x54, 17)] = RGFW_t,-		[RGFW_OS_BASED_VALUE(30, 0x55, 32)] = RGFW_u,-		[RGFW_OS_BASED_VALUE(55, 0x56, 9)] = RGFW_v,-		[RGFW_OS_BASED_VALUE(25, 0x57, 13)] = RGFW_w,-		[RGFW_OS_BASED_VALUE(53, 0x58, 7)] = RGFW_x,-		[RGFW_OS_BASED_VALUE(29, 0x59, 16)] = RGFW_y,-		[RGFW_OS_BASED_VALUE(52, 0x5A, 6)] = RGFW_z,--		[RGFW_OS_BASED_VALUE(60, 190, 47)] = RGFW_Period,-		[RGFW_OS_BASED_VALUE(59, 188, 43)] = RGFW_Comma,-		[RGFW_OS_BASED_VALUE(61, 191, 44)] = RGFW_Slash,-		[RGFW_OS_BASED_VALUE(34, 219, 33)] = RGFW_Bracket,-		[RGFW_OS_BASED_VALUE(35, 221, 30)] = RGFW_CloseBracket,-		[RGFW_OS_BASED_VALUE(47, 186, 41)] = RGFW_Semicolon,-		[RGFW_OS_BASED_VALUE(48, 222, 39)] = RGFW_Quote,-		[RGFW_OS_BASED_VALUE(51, 322, 42)] = RGFW_BackSlash,-		-		[RGFW_OS_BASED_VALUE(36, 0x0D, 36)] = RGFW_Return,-		[RGFW_OS_BASED_VALUE(119, 0x2E, 118)] = RGFW_Delete,-		[RGFW_OS_BASED_VALUE(77, 0x90, 72)] = RGFW_Numlock,-		[RGFW_OS_BASED_VALUE(106, 0x6F, 82)] = RGFW_KP_Slash,-		[RGFW_OS_BASED_VALUE(63, 0x6A, 76)] = RGFW_Multiply,-		[RGFW_OS_BASED_VALUE(82, 0x6D, 67)] = RGFW_KP_Minus,-		[RGFW_OS_BASED_VALUE(87, 0x61, 84)] = RGFW_KP_1,-		[RGFW_OS_BASED_VALUE(88, 0x62, 85)] = RGFW_KP_2,-		[RGFW_OS_BASED_VALUE(89, 0x63, 86)] = RGFW_KP_3,-		[RGFW_OS_BASED_VALUE(83, 0x64, 87)] = RGFW_KP_4,-		[RGFW_OS_BASED_VALUE(84, 0x65, 88)] = RGFW_KP_5,-		[RGFW_OS_BASED_VALUE(85, 0x66, 89)] = RGFW_KP_6,-		[RGFW_OS_BASED_VALUE(79, 0x67, 90)] = RGFW_KP_7,-		[RGFW_OS_BASED_VALUE(80, 0x68, 92)] = RGFW_KP_8,-		[RGFW_OS_BASED_VALUE(81, 0x69, 93)] = RGFW_KP_9,-		[RGFW_OS_BASED_VALUE(90, 0x60, 83)] = RGFW_KP_0,-		[RGFW_OS_BASED_VALUE(91, 0x6E, 65)] = RGFW_KP_Period,-		[RGFW_OS_BASED_VALUE(104, 0x92, 77)] = RGFW_KP_Return,-		-		[RGFW_OS_BASED_VALUE(20, 189, 27)] = RGFW_Minus,-		[RGFW_OS_BASED_VALUE(21, 187, 24)] = RGFW_Equals,-		[RGFW_OS_BASED_VALUE(22, 8, 51)] = RGFW_BackSpace,-		[RGFW_OS_BASED_VALUE(23, 0x09, 48)] = RGFW_Tab,-		[RGFW_OS_BASED_VALUE(66, 20, 57)] = RGFW_CapsLock,-		[RGFW_OS_BASED_VALUE(50, 0xA0, 56)] = RGFW_ShiftL,-		[RGFW_OS_BASED_VALUE(37, 0x11, 59)] = RGFW_ControlL,-		[RGFW_OS_BASED_VALUE(64, 164, 58)] = RGFW_AltL,-		[RGFW_OS_BASED_VALUE(133, 0x5B, 55)] = RGFW_SuperL,-		-		#if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS)-		[RGFW_OS_BASED_VALUE(105, 0x11, 59)] = RGFW_ControlR,-		[RGFW_OS_BASED_VALUE(135, 0xA4, 55)] = RGFW_SuperR,-		#endif--		#if !defined(RGFW_MACOS)-		[RGFW_OS_BASED_VALUE(62, 0x5C, 56)] = RGFW_ShiftR,-		[RGFW_OS_BASED_VALUE(108, 165, 58)] = RGFW_AltR,-		#endif--		[RGFW_OS_BASED_VALUE(67, 0x70, 127)] = RGFW_F1,-		[RGFW_OS_BASED_VALUE(68, 0x71, 121)] = RGFW_F2,-		[RGFW_OS_BASED_VALUE(69, 0x72, 100)] = RGFW_F3,-		[RGFW_OS_BASED_VALUE(70, 0x73, 119)] = RGFW_F4,-		[RGFW_OS_BASED_VALUE(71, 0x74, 97)] = RGFW_F5,-		[RGFW_OS_BASED_VALUE(72, 0x75, 98)] = RGFW_F6,-		[RGFW_OS_BASED_VALUE(73, 0x76, 99)] = RGFW_F7,-		[RGFW_OS_BASED_VALUE(74, 0x77, 101)] = RGFW_F8,-		[RGFW_OS_BASED_VALUE(75, 0x78, 102)] = RGFW_F9,-		[RGFW_OS_BASED_VALUE(76, 0x79, 110)] = RGFW_F10,-		[RGFW_OS_BASED_VALUE(95, 0x7A, 104)] = RGFW_F11,-		[RGFW_OS_BASED_VALUE(96, 0x7B, 112)] = RGFW_F12,-		[RGFW_OS_BASED_VALUE(111, 0x26, 126)] = RGFW_Up,-		[RGFW_OS_BASED_VALUE(116, 0x28, 125)] = RGFW_Down,-		[RGFW_OS_BASED_VALUE(113, 0x25, 123)] = RGFW_Left,-		[RGFW_OS_BASED_VALUE(114, 0x27, 124)] = RGFW_Right,-		[RGFW_OS_BASED_VALUE(118, 0x2D, 115)] = RGFW_Insert,-		[RGFW_OS_BASED_VALUE(115, 0x23, 120)] = RGFW_End,-		[RGFW_OS_BASED_VALUE(112, 336, 117)] = RGFW_PageUp,-		[RGFW_OS_BASED_VALUE(117, 325, 122)] = RGFW_PageDown,-		[RGFW_OS_BASED_VALUE(9, 0x1B, 53)] = RGFW_Escape,-		[RGFW_OS_BASED_VALUE(110, 0x24, 116)] = RGFW_Home,-	};--	typedef struct {-		b8 current  : 1;-		b8 prev  : 1;-	} RGFW_keyState;--	RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} };-	-	RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode);--	u32 RGFW_apiKeyCodeToRGFW(u32 keycode) {-		if (keycode > sizeof(RGFW_keycodes) / sizeof(u8))-			return 0;-		-		return RGFW_keycodes[keycode];-	}--	RGFWDEF void RGFW_resetKey(void);-	void RGFW_resetKey(void) {-		size_t len = final_key;-		-		size_t i; -		for (i = 0; i < len; i++) -			RGFW_keyboard[i].prev = 0;-	}--/*-	this is the end of keycode data-*/---/* -	event callback defines start here-*/---	/*-		These exist to avoid the -		if (func == NULL) check -		for (allegedly) better performance-	*/-	void RGFW_windowmovefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); }-	void RGFW_windowresizefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); }-	void RGFW_windowquitfuncEMPTY(RGFW_window* win) { RGFW_UNUSED(win); }-	void RGFW_focusfuncEMPTY(RGFW_window* win, b8 inFocus) {RGFW_UNUSED(win); RGFW_UNUSED(inFocus);}-	void RGFW_mouseNotifyfuncEMPTY(RGFW_window* win, RGFW_vector point, b8 status) {RGFW_UNUSED(win); RGFW_UNUSED(point); RGFW_UNUSED(status);}-	void RGFW_mouseposfuncEMPTY(RGFW_window* win, RGFW_vector point) {RGFW_UNUSED(win); RGFW_UNUSED(point);}-	void RGFW_dndInitfuncEMPTY(RGFW_window* win, RGFW_vector point) {RGFW_UNUSED(win); RGFW_UNUSED(point);}-	void RGFW_windowrefreshfuncEMPTY(RGFW_window* win) {RGFW_UNUSED(win); }-	void RGFW_keyfuncEMPTY(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(keycode); RGFW_UNUSED(keyName); RGFW_UNUSED(lockState); RGFW_UNUSED(pressed);}-	void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, u8 button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);}-	void RGFW_jsButtonfuncEMPTY(RGFW_window* win, u16 joystick, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(button); RGFW_UNUSED(pressed); }-	void RGFW_jsAxisfuncEMPTY(RGFW_window* win, u16 joystick, RGFW_vector axis[2], u8 axisesCount){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); }--	#ifdef RGFW_ALLOC_DROPFILES-	void RGFW_dndfuncEMPTY(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);}-	#else-	void RGFW_dndfuncEMPTY(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);}-	#endif--	RGFW_windowmovefunc RGFW_windowMoveCallback = RGFW_windowmovefuncEMPTY;-	RGFW_windowresizefunc RGFW_windowResizeCallback = RGFW_windowresizefuncEMPTY;-	RGFW_windowquitfunc RGFW_windowQuitCallback = RGFW_windowquitfuncEMPTY;-	RGFW_mouseposfunc RGFW_mousePosCallback = RGFW_mouseposfuncEMPTY;-	RGFW_windowrefreshfunc RGFW_windowRefreshCallback = RGFW_windowrefreshfuncEMPTY;-	RGFW_focusfunc RGFW_focusCallback = RGFW_focusfuncEMPTY;-	RGFW_mouseNotifyfunc RGFW_mouseNotifyCallBack = RGFW_mouseNotifyfuncEMPTY;-	RGFW_dndfunc RGFW_dndCallback = RGFW_dndfuncEMPTY;-	RGFW_dndInitfunc RGFW_dndInitCallback = RGFW_dndInitfuncEMPTY;-	RGFW_keyfunc RGFW_keyCallback = RGFW_keyfuncEMPTY;-	RGFW_mousebuttonfunc RGFW_mouseButtonCallback = RGFW_mousebuttonfuncEMPTY;-	RGFW_jsButtonfunc RGFW_jsButtonCallback = RGFW_jsButtonfuncEMPTY;-	RGFW_jsAxisfunc RGFW_jsAxisCallback = RGFW_jsAxisfuncEMPTY;--	void RGFW_window_checkEvents(RGFW_window* win) { while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { if (win->event.type == RGFW_quit) return; }}-	-	void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { RGFW_windowMoveCallback = func; }-	void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) { RGFW_windowResizeCallback = func; }-	void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) { RGFW_windowQuitCallback = func; }-	void RGFW_setMousePosCallback(RGFW_mouseposfunc func) { RGFW_mousePosCallback = func; }-	void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) { RGFW_windowRefreshCallback = func; }-	void RGFW_setFocusCallback(RGFW_focusfunc func) { RGFW_focusCallback = func; }-	void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) { RGFW_mouseNotifyCallBack = func; }-	void RGFW_setDndCallback(RGFW_dndfunc func) { RGFW_dndCallback = func; }-	void RGFW_setDndInitCallback(RGFW_dndInitfunc func) { RGFW_dndInitCallback = func; }-	void RGFW_setKeyCallback(RGFW_keyfunc func) { RGFW_keyCallback = func; }-	void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) { RGFW_mouseButtonCallback = func; }-	void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) { RGFW_jsButtonCallback = func; }-	void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) { RGFW_jsAxisCallback = func; }-/* -	no more event call back defines-*/--#define RGFW_ASSERT(check, str) {\-	if (!(check)) { \-		printf(str); \-		assert(check); \-	} \-}--	b8 RGFW_error = 0;-	b8 RGFW_Error() { return RGFW_error; }--#define SET_ATTRIB(a, v) { \-    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \-    attribs[index++] = a; \-    attribs[index++] = v; \-}-	-	RGFW_area RGFW_bufferSize = {0, 0};-	void RGFW_setBufferSize(RGFW_area size) {-		RGFW_bufferSize = size;-	}---	RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args);--	RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {-		RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /* make a new RGFW struct */--#ifdef RGFW_ALLOC_DROPFILES-		win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS);-		u32 i;-		for (i = 0; i < RGFW_MAX_DROPS; i++)-			win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char));-#endif--		#ifndef RGFW_X11 -		RGFW_area screenR = RGFW_getScreenSize();-		#else-		win->src.display = XOpenDisplay(NULL);-		assert(win->src.display != NULL);--		Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display);-		RGFW_area screenR = RGFW_AREA(scrn->width, scrn->height);-		#endif-		-		if (args & RGFW_FULLSCREEN)-			rect = RGFW_RECT(0, 0, screenR.w, screenR.h);--		if (args & RGFW_CENTER)-			rect = RGFW_RECT((screenR.w - rect.w) / 2, (screenR.h - rect.h) / 2, rect.w, rect.h);--		/* set and init the new window's data */-		win->r = rect;-		win->fpsCap = 0;-		win->event.inFocus = 1;-		win->event.droppedFilesCount = 0;-		win->src.joystickCount = 0;-		win->src.winArgs = 0;-		win->event.lockState = 0;--		return win;-	}--	#ifndef RGFW_NO_MONITOR-	void RGFW_window_scaleToMonitor(RGFW_window* win) {-		RGFW_monitor monitor = RGFW_window_getMonitor(win);--		RGFW_window_resize(win, RGFW_AREA(((u32) monitor.scaleX) * win->r.w, ((u32) monitor.scaleX) * win->r.h));-	}-	#endif--RGFW_window* RGFW_root = NULL;---#define RGFW_HOLD_MOUSE			(1L<<2) /*!< hold the moues still */-#define RGFW_MOUSE_LEFT 		(1L<<3) /* if mouse left the window */--	void RGFW_clipboardFree(char* str) { RGFW_FREE(str); }-	-	b8 RGFW_mouseButtons[5] = { 0 };-	b8 RGFW_mouseButtons_prev[5];--	b8 RGFW_isMousePressed(RGFW_window* win, u8 button) {-		assert(win != NULL);-		return RGFW_mouseButtons[button] && (win != NULL) && win->event.inFocus; -	}-	b8 RGFW_wasMousePressed(RGFW_window* win, u8 button) {-		assert(win != NULL); -		return RGFW_mouseButtons_prev[button] && (win != NULL) && win->event.inFocus; -	}-	b8 RGFW_isMouseHeld(RGFW_window* win, u8 button) {-		return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button));-	}-	b8 RGFW_isMouseReleased(RGFW_window* win, u8 button) {-		return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button));	-	}--	b8 RGFW_isPressed(RGFW_window* win, u8 key) {-		assert(win != NULL);-		return RGFW_keyboard[key].current && win->event.inFocus;-	}--	b8 RGFW_wasPressed(RGFW_window* win, u8 key) {-		assert(win != NULL);-		return RGFW_keyboard[key].prev && win->event.inFocus;-	}--	b8 RGFW_isHeld(RGFW_window* win, u8 key) {-		return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key));-	}--	b8 RGFW_isClicked(RGFW_window* win, u8 key) {-		return (RGFW_wasPressed(win, key) && !RGFW_isPressed(win, key));-	}--	b8 RGFW_isReleased(RGFW_window* win, u8 key) {-		return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key));	-	}-	-	void RGFW_window_makeCurrent(RGFW_window* win) {-		assert(win != NULL);--#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)-		RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL);-#endif--#ifdef RGFW_OPENGL-		RGFW_window_makeCurrent_OpenGL(win);-#endif-	}--	void RGFW_window_setGPURender(RGFW_window* win, i8 set) {-		if (!set && !(win->src.winArgs & RGFW_NO_GPU_RENDER))-			win->src.winArgs |= RGFW_NO_GPU_RENDER;--		else if (set && win->src.winArgs & RGFW_NO_GPU_RENDER)-			win->src.winArgs ^= RGFW_NO_GPU_RENDER;-	}--	void RGFW_window_setCPURender(RGFW_window* win, i8 set) {-		if (!set && !(win->src.winArgs & RGFW_NO_CPU_RENDER))-			win->src.winArgs |= RGFW_NO_CPU_RENDER;--		else if (set && win->src.winArgs & RGFW_NO_CPU_RENDER)-			win->src.winArgs ^= RGFW_NO_CPU_RENDER;-	}--	void RGFW_window_maximize(RGFW_window* win) {-		assert(win != NULL);--		RGFW_area screen = RGFW_getScreenSize();--		RGFW_window_move(win, RGFW_VECTOR(0, 0));-		RGFW_window_resize(win, screen);-	}--	b8 RGFW_window_shouldClose(RGFW_window* win) {-		assert(win != NULL);-		return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape));-	}--	void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; RGFW_windowQuitCallback(win); }--	#ifndef RGFW_NO_MONITOR-	void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) {-		RGFW_window_move(win, RGFW_VECTOR(m.rect.x + win->r.x, m.rect.y + win->r.y));-	}-	#endif--	RGFWDEF void RGFW_clipCursor(RGFW_rect);-			-	#if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS)	-	void RGFW_clipCursor(RGFW_rect r) { RGFW_UNUSED(r) }-	#endif--	void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) {-		if (!(win->src.winArgs & RGFW_HOLD_MOUSE)) {-			RGFW_clipCursor(win->r);-			win->src.winArgs |= RGFW_HOLD_MOUSE;-		}-		-		if (!area.w && !area.h)-			area = RGFW_AREA(win->r.w / 2, win->r.h / 2);-		-		#ifndef RGFW_MACOS-		RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (area.w), win->r.y + (area.h)));-		#endif-	}--	void RGFW_window_mouseUnhold(RGFW_window* win) {-		if ((win->src.winArgs & RGFW_HOLD_MOUSE)) {-			win->src.winArgs ^= RGFW_HOLD_MOUSE;--			RGFW_clipCursor(RGFW_RECT(0, 0, 0, 0));-		}-	}--	void RGFW_window_checkFPS(RGFW_window* win) {-		u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime;--		u64 fps = round(1e+9 / deltaTime);-		win->event.fps = fps;--		if (win->fpsCap && fps > win->fpsCap) {-			u64 frameTimeNS = 1e+9 / win->fpsCap;-			u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6;--			if (sleepTimeMS > 0) {-				RGFW_sleep(sleepTimeMS);-				win->event.frameTime = 0;-			}-		}--		win->event.frameTime = RGFW_getTimeNS();-		-		if (win->fpsCap == 0)-			return;-		-		deltaTime = RGFW_getTimeNS() - win->event.frameTime2;-		win->event.fps = round(1e+9 / deltaTime);-		win->event.frameTime2 = RGFW_getTimeNS();-	}-	-	u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { return win->src.jsPressed[c][button]; }-	-	#if defined(RGFW_X11) || defined(RGFW_WINDOWS)-		void RGFW_window_showMouse(RGFW_window* win, i8 show) {-			static u8 RGFW_blk[] = { 0, 0, 0, 0 };-			if (show == 0)-				RGFW_window_setMouse(win, RGFW_blk, RGFW_AREA(1, 1), 4);-			else-				RGFW_window_setMouseDefault(win);-		}-	#endif--	RGFWDEF void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock);	-	void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {-		if (capital && !(win->event.lockState & RGFW_CAPSLOCK))-			win->event.lockState |= RGFW_CAPSLOCK;-		else if (!capital && (win->event.lockState & RGFW_CAPSLOCK))			-			win->event.lockState ^= RGFW_CAPSLOCK;-		-		if (numlock && !(win->event.lockState & RGFW_NUMLOCK))-			win->event.lockState |= RGFW_NUMLOCK;-		else if (!numlock && (win->event.lockState & RGFW_NUMLOCK))-			win->event.lockState ^= RGFW_NUMLOCK;-	}--	#if defined(RGFW_X11) || defined(RGFW_MACOS)-		struct timespec;--		int nanosleep(const struct timespec* duration, struct timespec* rem);-		int clock_gettime(clockid_t clk_id, struct timespec* tp);-		int setenv(const char *name, const char *value, int overwrite);--		void RGFW_window_setDND(RGFW_window* win, b8 allow) {-			if (allow && !(win->src.winArgs & RGFW_ALLOW_DND))-				win->src.winArgs |= RGFW_ALLOW_DND;--			else if (!allow && (win->src.winArgs & RGFW_ALLOW_DND))-				win->src.winArgs ^= RGFW_ALLOW_DND;-		}-	#endif--/*-	graphics API spcific code (end of generic code)-	starts here -*/---/* -	OpenGL defines start here   (Normal, EGL, OSMesa)-*/--#if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA)-#ifndef __APPLE__-#include <GL/gl.h>-#else-#ifndef GL_SILENCE_DEPRECATION-#define GL_SILENCE_DEPRECATION-#endif-#include <OpenGL/gl.h>-#include <OpenGL/OpenGL.h>-#endif--/* EGL, normal OpenGL only */-#if !defined(RGFW_OSMESA) -	i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0;-	-	#ifndef RGFW_EGL-	i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = GL_FALSE, RGFW_AUX_BUFFERS = 0;-	#else-	i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = GL_FALSE, RGFW_AUX_BUFFERS = 0;-	#endif---	void RGFW_setGLStencil(i32 stencil) { RGFW_STENCIL = stencil; }-	void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; }-	void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; }-	void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; }--	void RGFW_setGLVersion(i32 major, i32 minor) {-		RGFW_majorVersion = major;-		RGFW_minorVersion = minor;-	}--	u8* RGFW_getMaxGLVersion(void) {-		RGFW_window* dummy = RGFW_createWindow("dummy", RGFW_RECT(0, 0, 1, 1), 0);--		const char* versionStr = (const char*) glGetString(GL_VERSION);--		static u8 version[2];-		version[0] = versionStr[0] - '0',-			version[1] = versionStr[2] - '0';--		RGFW_window_close(dummy);--		return version;-	}--/* OPENGL normal only (no EGL / OSMesa) */-#ifndef RGFW_EGL--#define RGFW_GL_RENDER_TYPE 		RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE,    	0x2003,		73)-#define RGFW_GL_ALPHA_SIZE 		RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE,       	0x201b,		11)-#define RGFW_GL_DEPTH_SIZE 		RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE,       	0x2022,		12)-#define RGFW_GL_DOUBLEBUFFER 		RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER,     	0x2011, 	5)   -#define RGFW_GL_STENCIL_SIZE 		RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE,	 	0x2023,	13)-#define RGFW_GL_SAMPLES			RGFW_OS_BASED_VALUE(GLX_SAMPLES, 		 	0x2042,	    55)-#define RGFW_GL_STEREO 			RGFW_OS_BASED_VALUE(GLX_STEREO,	 		 	0x2012,			6)-#define RGFW_GL_AUX_BUFFERS		RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS,	    0x2024,	7)--#if defined(RGFW_X11) || defined(RGFW_WINDOWS)-#define RGFW_GL_DRAW 			RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE,	 	0x2001,					0)-#define RGFW_GL_DRAW_TYPE 		RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE,     	0x2013,						0)-#define RGFW_GL_USE_OPENGL		RGFW_OS_BASED_VALUE(GLX_USE_GL,				0x2010,						0)-#define RGFW_GL_FULL_FORMAT		RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR,   	 	0x2027,						0)-#define RGFW_GL_RED_SIZE		RGFW_OS_BASED_VALUE(GLX_RED_SIZE,         	0x2015,						0)-#define RGFW_GL_GREEN_SIZE		RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE,       	0x2017,						0)-#define RGFW_GL_BLUE_SIZE		RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 	 		0x2019,						0)-#define RGFW_GL_USE_RGBA		RGFW_OS_BASED_VALUE(GLX_RGBA_BIT,   	 	0x202B,						0)-#endif--#ifdef RGFW_WINDOWS-#define WGL_COLOR_BITS_ARB                        0x2014-#define WGL_NUMBER_PIXEL_FORMATS_ARB 			0x2000-#define WGL_CONTEXT_MAJOR_VERSION_ARB             0x2091-#define WGL_CONTEXT_MINOR_VERSION_ARB             0x2092-#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126-#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002-#define WGL_SAMPLE_BUFFERS_ARB               0x2041-#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9-#define WGL_PIXEL_TYPE_ARB                        0x2013-#define WGL_TYPE_RGBA_ARB                         0x202B--#define WGL_TRANSPARENT_ARB   					  0x200A-#endif--	static u32* RGFW_initAttribs(u32 useSoftware) {-		RGFW_UNUSED(useSoftware);-		static u32 attribs[] = {-								#ifndef RGFW_MACOS-								RGFW_GL_RENDER_TYPE,-								RGFW_GL_FULL_FORMAT,-								#endif-								RGFW_GL_ALPHA_SIZE      , 8,-								RGFW_GL_DEPTH_SIZE      , 24,-								RGFW_GL_DOUBLEBUFFER    ,-								#ifndef RGFW_MACOS-								1,-								#endif--								#if defined(RGFW_X11) || defined(RGFW_WINDOWS)-								RGFW_GL_USE_OPENGL,		1,-								RGFW_GL_DRAW, 1,-								RGFW_GL_RED_SIZE        , 8,-								RGFW_GL_GREEN_SIZE      , 8,-								RGFW_GL_BLUE_SIZE       , 8,-								RGFW_GL_DRAW_TYPE     , RGFW_GL_USE_RGBA,-								#endif --								#ifdef RGFW_X11-								GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,-								#endif--								#ifdef RGFW_MACOS-								72,-								8, 24,-								#endif--								#ifdef RGFW_WINDOWS-								WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,-								WGL_TRANSPARENT_ARB, TRUE,-								WGL_COLOR_BITS_ARB,	 32,-								#endif--								0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0-		};--		size_t index = (sizeof(attribs) / sizeof(attribs[0])) - 13;--#define RGFW_GL_ADD_ATTRIB(attrib, attVal) \-		if (attVal) { \-			attribs[index] = attrib;\-			attribs[index + 1] = attVal;\-			index += 2;\-		}--		RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL);-		RGFW_GL_ADD_ATTRIB(RGFW_GL_STEREO, RGFW_STEREO);-		RGFW_GL_ADD_ATTRIB(RGFW_GL_AUX_BUFFERS, RGFW_AUX_BUFFERS);--#ifndef RGFW_X11-		RGFW_GL_ADD_ATTRIB(RGFW_GL_SAMPLES, RGFW_SAMPLES);-#endif --#ifdef RGFW_MACOS-		if (useSoftware) {-			RGFW_GL_ADD_ATTRIB(70, kCGLRendererGenericFloatID);-		} else {-			attribs[index] = RGFW_GL_RENDER_TYPE;-			index += 1;-		}-#endif--#ifdef RGFW_MACOS-		attribs[index] = 99;-		attribs[index + 1] = 0x1000;--		if (RGFW_majorVersion >= 4 || RGFW_majorVersion >= 3) {-			attribs[index + 1] = (u32) ((RGFW_majorVersion >= 4) ? 0x4100 : 0x3200);-		}--#endif--		RGFW_GL_ADD_ATTRIB(0, 0);--		return attribs;-	}--/* EGL only (no OSMesa nor normal OPENGL) */-#elif defined(RGFW_EGL)--#include <EGL/egl.h>--#if defined(RGFW_LINK_EGL)-	typedef EGLBoolean(EGLAPIENTRY* PFN_eglInitialize)(EGLDisplay, EGLint*, EGLint*);--	PFNEGLINITIALIZEPROC eglInitializeSource;-	PFNEGLGETCONFIGSPROC eglGetConfigsSource;-	PFNEGLCHOOSECONFIGPROC eglChooseConfigSource;-	PFNEGLCREATEWINDOWSURFACEPROC eglCreateWindowSurfaceSource;-	PFNEGLCREATECONTEXTPROC eglCreateContextSource;-	PFNEGLMAKECURRENTPROC eglMakeCurrentSource;-	PFNEGLGETDISPLAYPROC eglGetDisplaySource;-	PFNEGLSWAPBUFFERSPROC eglSwapBuffersSource;-	PFNEGLSWAPINTERVALPROC eglSwapIntervalSource;-	PFNEGLBINDAPIPROC eglBindAPISource;-	PFNEGLDESTROYCONTEXTPROC eglDestroyContextSource;-	PFNEGLTERMINATEPROC eglTerminateSource;-	PFNEGLDESTROYSURFACEPROC eglDestroySurfaceSource;--#define eglInitialize eglInitializeSource-#define eglGetConfigs eglGetConfigsSource-#define eglChooseConfig eglChooseConfigSource-#define eglCreateWindowSurface eglCreateWindowSurfaceSource-#define eglCreateContext eglCreateContextSource-#define eglMakeCurrent eglMakeCurrentSource-#define eglGetDisplay eglGetDisplaySource-#define eglSwapBuffers eglSwapBuffersSource-#define eglSwapInterval eglSwapIntervalSource-#define eglBindAPI eglBindAPISource-#define eglDestroyContext eglDestroyContextSource-#define eglTerminate eglTerminateSource-#define eglDestroySurface eglDestroySurfaceSource;-#endif---#define EGL_SURFACE_MAJOR_VERSION_KHR 0x3098-#define EGL_SURFACE_MINOR_VERSION_KHR 0x30fb--#ifndef RGFW_GL_ADD_ATTRIB-#define RGFW_GL_ADD_ATTRIB(attrib, attVal) \-	if (attVal) { \-		attribs[index] = attrib;\-		attribs[index + 1] = attVal;\-		index += 2;\-	}-#endif---	void RGFW_createOpenGLContext(RGFW_window* win) {-#if defined(RGFW_LINK_EGL)-		eglInitializeSource = (PFNEGLINITIALIZEPROC) eglGetProcAddress("eglInitialize");-		eglGetConfigsSource = (PFNEGLGETCONFIGSPROC) eglGetProcAddress("eglGetConfigs");-		eglChooseConfigSource = (PFNEGLCHOOSECONFIGPROC) eglGetProcAddress("eglChooseConfig");-		eglCreateWindowSurfaceSource = (PFNEGLCREATEWINDOWSURFACEPROC) eglGetProcAddress("eglCreateWindowSurface");-		eglCreateContextSource = (PFNEGLCREATECONTEXTPROC) eglGetProcAddress("eglCreateContext");-		eglMakeCurrentSource = (PFNEGLMAKECURRENTPROC) eglGetProcAddress("eglMakeCurrent");-		eglGetDisplaySource = (PFNEGLGETDISPLAYPROC) eglGetProcAddress("eglGetDisplay");-		eglSwapBuffersSource = (PFNEGLSWAPBUFFERSPROC) eglGetProcAddress("eglSwapBuffers");-		eglSwapIntervalSource = (PFNEGLSWAPINTERVALPROC) eglGetProcAddress("eglSwapInterval");-		eglBindAPISource = (PFNEGLBINDAPIPROC) eglGetProcAddress("eglBindAPI");-		eglDestroyContextSource = (PFNEGLDESTROYCONTEXTPROC) eglGetProcAddress("eglDestroyContext");-		eglTerminateSource = (PFNEGLTERMINATEPROC) eglGetProcAddress("eglTerminate");-		eglDestroySurfaceSource = (PFNEGLDESTROYSURFACEPROC) eglGetProcAddress("eglDestroySurface");-#endif /* RGFW_LINK_EGL */--		#ifdef RGFW_WINDOWS-		win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc);-		#else-		win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display);-		#endif--		EGLint major, minor;--		eglInitialize(win->src.EGL_display, &major, &minor);--		#ifndef EGL_OPENGL_ES1_BIT-		#define EGL_OPENGL_ES1_BIT 0x1-		#endif--		EGLint egl_config[] = {-			EGL_SURFACE_TYPE, EGL_WINDOW_BIT,-			EGL_RENDERABLE_TYPE,-			#ifdef RGFW_OPENGL_ES1-			EGL_OPENGL_ES1_BIT,-			#elif defined(RGFW_OPENGL_ES3)-			EGL_OPENGL_ES3_BIT,-			#elif defined(RGFW_OPENGL_ES2)-			EGL_OPENGL_ES2_BIT,-			#else-			EGL_OPENGL_BIT,-			#endif-			EGL_NONE, EGL_NONE-		};--		EGLConfig config;-		EGLint numConfigs;-		eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs);---		win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL);--		EGLint attribs[] = {-			EGL_CONTEXT_CLIENT_VERSION,-			#ifdef RGFW_OPENGL_ES1-			1,-			#else-			2,-			#endif-			EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE-		};--		size_t index = 4;-		RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL);-		RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES);--		if (RGFW_majorVersion) {-			attribs[1] = RGFW_majorVersion;-			RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);-			RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion);-			RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion);-		}--		#if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)-		eglBindAPI(EGL_OPENGL_ES_API);-		#else-		eglBindAPI(EGL_OPENGL_API);		-		#endif--      	win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs);--		eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context);-		eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);-	}--	#ifdef RGFW_APPLE-	void* RGFWnsglFramework = NULL;-	#elif defined(RGFW_WINDOWS)-	static HMODULE wglinstance = NULL;-	#endif--	void* RGFW_getProcAddress(const char* procname) { -		#if defined(RGFW_WINDOWS)-			void* proc = (void*) GetProcAddress(wglinstance, procname); --			if (proc)-				return proc;-		#endif--		return (void*) eglGetProcAddress(procname); -	}--	void RGFW_closeEGL(RGFW_window* win) {-		eglDestroySurface(win->src.EGL_display, win->src.EGL_surface);-		eglDestroyContext(win->src.EGL_display, win->src.EGL_context);--		eglTerminate(win->src.EGL_display);-	}--	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {-		assert(win != NULL);-		-		eglSwapInterval(win->src.EGL_display, swapInterval);--		win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;--	}-#endif /* RGFW_EGL */--/* -	end of RGFW_EGL defines-*/--/* OPENGL Normal / EGL defines only (no OS MESA)  Ends here */--#elif defined(RGFW_OSMESA) /* OSmesa only */-RGFWDEF void RGFW_OSMesa_reorganize(void);--/* reorganize buffer for osmesa */-void RGFW_OSMesa_reorganize(void) {-	u8* row = (u8*) RGFW_MALLOC(win->r.w * 3);--	i32 half_height = win->r.h / 2;-	i32 stride = win->r.w * 3;--	i32 y;-	for (y = 0; y < half_height; ++y) {-		i32 top_offset = y * stride;-		i32 bottom_offset = (win->r.h - y - 1) * stride;-		memcpy(row, win->buffer + top_offset, stride);-		memcpy(win->buffer + top_offset, win->buffer + bottom_offset, stride);-		memcpy(win->buffer + bottom_offset, row, stride);-	}--	RGFW_FREE(row);-}-#endif /* RGFW_OSMesa */--#endif /* RGFW_GL (OpenGL, EGL, OSMesa )*/--/*-This is where OS specific stuff starts-*/---/*---Start of Linux / Unix defines---*/--#ifdef RGFW_X11-#ifndef RGFW_NO_X11_CURSOR-#include <X11/Xcursor/Xcursor.h>-#endif-#include <dlfcn.h>--#ifndef RGFW_NO_DPI-#include <X11/extensions/Xrandr.h>-#include <X11/Xresource.h>-#endif--#include <X11/Xutil.h>-#include <X11/Xatom.h>-#include <X11/keysymdef.h>-#include <unistd.h>--#include <X11/XKBlib.h> /* for converting keycode to string */-#include <X11/cursorfont.h> /* for hiding */-#include <X11/extensions/shapeconst.h>-#include <X11/extensions/shape.h>--#include <limits.h> /* for data limits (mainly used in drag and drop functions) */-#include <fcntl.h>--#ifdef __linux__-#include <linux/joystick.h>-#endif--	u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor};  -	/*atoms needed for drag and drop*/-	Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XdndActionMove, XdndActionLink, XdndActionAsk, XdndActionPrivate;--	Atom wm_delete_window = 0;--#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)-	typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int);-	typedef void (*PFN_XcursorImageDestroy)(XcursorImage*);-	typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*);-#endif-#ifdef RGFW_OPENGL-	typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);-#endif--#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)-	PFN_XcursorImageLoadCursor XcursorImageLoadCursorSrc = NULL;-	PFN_XcursorImageCreate XcursorImageCreateSrc = NULL;-	PFN_XcursorImageDestroy XcursorImageDestroySrc = NULL;--#define XcursorImageLoadCursor XcursorImageLoadCursorSrc-#define XcursorImageCreate XcursorImageCreateSrc-#define XcursorImageDestroy XcursorImageDestroySrc--	void* X11Cursorhandle = NULL;-#endif--	u32 RGFW_windowsOpen = 0;--#ifdef RGFW_OPENGL-	void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); }-#endif--	RGFWDEF void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi);-	void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi) {-#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)-		if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)-			RGFW_bufferSize = RGFW_getScreenSize();-		-		win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);--		#ifdef RGFW_OSMESA-				win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL);-				OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);-		#endif--		win->src.bitmap = XCreateImage(-			win->src.display, vi->visual,-			vi->depth,-			ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h,-			32, 0-		);--		win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL);--		#else-		RGFW_UNUSED(win); /* if buffer rendering is not being used */-		RGFW_UNUSED(vi)-		#endif-	}----	void RGFW_window_setBorder(RGFW_window* win, u8 border) {-		static Atom _MOTIF_WM_HINTS = 0;-		if (_MOTIF_WM_HINTS == 0 )-			_MOTIF_WM_HINTS = XInternAtom(win->src.display, "_MOTIF_WM_HINTS", False);-		-		struct __x11WindowHints {-			unsigned long flags, functions, decorations, status;-			long input_mode;-		} hints;-		hints.flags = (1L << 1);-		hints.decorations = !border;--		XChangeProperty(-			win->src.display, win->src.window,-			_MOTIF_WM_HINTS, _MOTIF_WM_HINTS,-			32, PropModeReplace, (u8*)&hints, 5-		);-	}--	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {-#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)-		if (X11Cursorhandle == NULL) {-#if defined(__CYGWIN__)-			X11Cursorhandle = dlopen("libXcursor-1.so", RTLD_LAZY | RTLD_LOCAL);-#elif defined(__OpenBSD__) || defined(__NetBSD__)-			X11Cursorhandle = dlopen("libXcursor.so", RTLD_LAZY | RTLD_LOCAL);-#else-			X11Cursorhandle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_LOCAL);-#endif--			XcursorImageCreateSrc = (PFN_XcursorImageCreate) dlsym(X11Cursorhandle, "XcursorImageCreate");-			XcursorImageDestroySrc = (PFN_XcursorImageDestroy) dlsym(X11Cursorhandle, "XcursorImageDestroy");-			XcursorImageLoadCursorSrc = (PFN_XcursorImageLoadCursor) dlsym(X11Cursorhandle, "XcursorImageLoadCursor");-		}-#endif--		XInitThreads(); /* init X11 threading*/--		if (args & RGFW_OPENGL_SOFTWARE)-			setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);--		RGFW_window* win = RGFW_window_basic_init(rect, args);--		u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /* X11 events accepted*/--#ifdef RGFW_OPENGL-		u32* visual_attribs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);-		i32 fbcount;-		GLXFBConfig* fbc = glXChooseFBConfig((Display*) win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount);--		i32 best_fbc = -1;--		if (fbcount == 0) {-			printf("Failed to find any valid GLX configs\n");-			return NULL;-		}--		u32 i;-		for (i = 0; i < (u32)fbcount; i++) {-			XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, fbc[i]);-			if (vi == NULL)-				continue;--			XFree(vi);--			i32 samp_buf, samples;-			glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);-			glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLES, &samples);-			if ((best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES || best_fbc == -1)) {-				best_fbc = i;-			}-		}--		if (best_fbc == -1) {-			printf("Failed to get a valid GLX visual\n");-			return NULL;-		}--		GLXFBConfig bestFbc = fbc[best_fbc];--		/* Get a visual */-		XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, bestFbc);--		XFree(fbc);--		if (args & RGFW_TRANSPARENT_WINDOW) {-			XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/-		}-#else-		XVisualInfo viNorm;--		viNorm.visual = DefaultVisual((Display*) win->src.display, DefaultScreen((Display*) win->src.display));-		-		viNorm.depth = 0;-		XVisualInfo* vi = &viNorm;-		-		XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/-#endif-		/* make X window attrubutes*/-		XSetWindowAttributes swa;-		Colormap cmap;--		swa.colormap = cmap = XCreateColormap((Display*) win->src.display,-			DefaultRootWindow(win->src.display),-			vi->visual, AllocNone);--		swa.background_pixmap = None;-		swa.border_pixel = 0;-		swa.event_mask = event_mask;-		-		swa.background_pixel = 0;--		/* create the window*/-		win->src.window = XCreateWindow((Display*) win->src.display, DefaultRootWindow((Display*) win->src.display), win->r.x, win->r.y, win->r.w, win->r.h,-			0, vi->depth, InputOutput, vi->visual,-			CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa);--		XFreeColors((Display*) win->src.display, cmap, NULL, 0, 0);--		#ifdef RGFW_OPENGL-		XFree(vi);-		#endif--		// In your .desktop app, if you set the property-		// StartupWMClass=RGFW that will assoicate the launcher icon-		// with your application - robrohan -		XClassHint *hint = XAllocClassHint();-		assert(hint != NULL);-		hint->res_class = "RGFW";-		hint->res_name = (char*)name; // just use the window name as the app name-		XSetClassHint((Display*) win->src.display, win->src.window, hint);-		XFree(hint);--		if ((args & RGFW_NO_INIT_API) == 0) {-#ifdef RGFW_OPENGL-		i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 };-		context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB;-		context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;-		-		if (RGFW_majorVersion || RGFW_minorVersion) {-			context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB;-			context_attribs[3] = RGFW_majorVersion;-			context_attribs[4] = GLX_CONTEXT_MINOR_VERSION_ARB;-			context_attribs[5] = RGFW_minorVersion;-		}--		glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;-		glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)-			glXGetProcAddressARB((GLubyte*) "glXCreateContextAttribsARB");--		GLXContext ctx = NULL;--		if (RGFW_root != NULL)-			ctx = RGFW_root->src.rSurf;--		win->src.rSurf = glXCreateContextAttribsARB((Display*) win->src.display, bestFbc, ctx, True, context_attribs);-#endif-		if (RGFW_root == NULL)-			RGFW_root = win;--		RGFW_init_buffer(win, vi);-		}-		--		#ifndef RGFW_NO_MONITOR-		if (args & RGFW_SCALE_TO_MONITOR)-			RGFW_window_scaleToMonitor(win);-		#endif--		if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/-			XSizeHints* sh = XAllocSizeHints();-			sh->flags = (1L << 4) | (1L << 5);-			sh->min_width = sh->max_width = win->r.w;-			sh->min_height = sh->max_height = win->r.h;--			XSetWMSizeHints((Display*) win->src.display, (Drawable) win->src.window, sh, XA_WM_NORMAL_HINTS);-			XFree(sh);-		}--		if (args & RGFW_NO_BORDER) {-			RGFW_window_setBorder(win, 0);-		}--		XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /* tell X11 what events we want*/--		/* make it so the user can't close the window until the program does*/-		if (wm_delete_window == 0)-			wm_delete_window = XInternAtom((Display*) win->src.display, "WM_DELETE_WINDOW", False);--		XSetWMProtocols((Display*) win->src.display, (Drawable) win->src.window, &wm_delete_window, 1);--		/* connect the context to the window*/-#ifdef RGFW_OPENGL-		if ((args & RGFW_NO_INIT_API) == 0)-			glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf);-#endif--		/* set the background*/-		XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /* set the name*/--		XMapWindow((Display*) win->src.display, (Drawable) win->src.window);						  /* draw the window*/-		XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /* move the window to it's proper cords*/--		if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */-			win->src.winArgs |= RGFW_ALLOW_DND;--			XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False);-			XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False);-			XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False);--			/* client messages */-			XdndEnter = XInternAtom((Display*) win->src.display, "XdndEnter", False);-			XdndPosition = XInternAtom((Display*) win->src.display, "XdndPosition", False);-			XdndStatus = XInternAtom((Display*) win->src.display, "XdndStatus", False);-			XdndLeave = XInternAtom((Display*) win->src.display, "XdndLeave", False);-			XdndDrop = XInternAtom((Display*) win->src.display, "XdndDrop", False);-			XdndFinished = XInternAtom((Display*) win->src.display, "XdndFinished", False);--			/* actions */-			XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False);-			XdndActionMove = XInternAtom((Display*) win->src.display, "XdndActionMove", False);-			XdndActionLink = XInternAtom((Display*) win->src.display, "XdndActionLink", False);-			XdndActionAsk = XInternAtom((Display*) win->src.display, "XdndActionAsk", False);-			XdndActionPrivate = XInternAtom((Display*) win->src.display, "XdndActionPrivate", False);-			const Atom version = 5;--			XChangeProperty((Display*) win->src.display, (Window) win->src.window,-				XdndAware, 4, 32,-				PropModeReplace, (u8*) &version, 1); /* turns on drag and drop */-		}--		#ifdef RGFW_EGL-			if ((args & RGFW_NO_INIT_API) == 0)-				RGFW_createOpenGLContext(win);-		#endif--		RGFW_window_setMouseDefault(win);--		RGFW_windowsOpen++;--		return win; /*return newly created window*/-	}--	RGFW_area RGFW_getScreenSize(void) {-		assert(RGFW_root != NULL);--		Screen* scrn = DefaultScreenOfDisplay((Display*) RGFW_root->src.display);-		return RGFW_AREA(scrn->width, scrn->height);-	}--	RGFW_vector RGFW_getGlobalMousePoint(void) {-		assert(RGFW_root != NULL);--		RGFW_vector RGFWMouse;--		i32 x, y;-		u32 z;-		Window window1, window2;-		XQueryPointer((Display*) RGFW_root->src.display, XDefaultRootWindow((Display*) RGFW_root->src.display), &window1, &window2, &RGFWMouse.x, &RGFWMouse.y, &x, &y, &z);- -		return RGFWMouse;-	}--	RGFW_vector RGFW_window_getMousePoint(RGFW_window* win) {-		assert(win != NULL);--		RGFW_vector RGFWMouse;--		i32 x, y;-		u32 z;-		Window window1, window2;-		XQueryPointer((Display*) win->src.display, win->src.window, &window1, &window2, &x, &y, &RGFWMouse.x, &RGFWMouse.y, &z);--		return RGFWMouse;-	}--	typedef struct XDND {-		long source, version;-		i32 format;-	} XDND; /* data structure for xdnd events */-	XDND xdnd;--	int xAxis = 0, yAxis = 0;--	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {-		assert(win != NULL);--		if (win->event.type == 0) -			RGFW_resetKey();--		if (win->event.type == RGFW_quit) {-			return NULL;-		}--		win->event.type = 0;--#ifdef __linux__-		{-			u8 i;-			for (i = 0; i < win->src.joystickCount; i++) {-				struct js_event e;---				if (win->src.joysticks[i] == 0)-					continue;--				i32 flags = fcntl(win->src.joysticks[i], F_GETFL, 0);-				fcntl(win->src.joysticks[i], F_SETFL, flags | O_NONBLOCK);--				ssize_t bytes;-				while ((bytes = read(win->src.joysticks[i], &e, sizeof(e))) > 0) {-					switch (e.type) {-					case JS_EVENT_BUTTON:-						win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased;-						win->event.button = e.number;-						win->src.jsPressed[i][e.number] = e.value;-						RGFW_jsButtonCallback(win, i, e.number, e.value);-						return &win->event;-					case JS_EVENT_AXIS:-						ioctl(win->src.joysticks[i], JSIOCGAXES, &win->event.axisesCount);--						if ((e.number == 0 || e.number % 2) && e.number != 1)-							xAxis = e.value;-						else-							yAxis = e.value;--						win->event.axis[e.number / 2].x = xAxis;-						win->event.axis[e.number / 2].y = yAxis;-						win->event.type = RGFW_jsAxisMove;-						win->event.joystick = i;-						RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount);-						return &win->event;--					default: break;-					}-				}-			}-		}-#endif--		XEvent E; /* raw X11 event */--		/* if there is no unread qued events, get a new one */-		if (XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading) && win->event.type != RGFW_quit)-			XNextEvent((Display*) win->src.display, &E);-		else {-			return NULL;-		}--		u32 i;-		win->event.type = 0;---		switch (E.type) {-		case KeyPress:-		case KeyRelease:-			/* check if it's a real key release */-			if (E.type == KeyRelease && XEventsQueued((Display*) win->src.display, QueuedAfterReading)) { /* get next event if there is one*/-				XEvent NE;-				XPeekEvent((Display*) win->src.display, &NE);--				if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/-					break;-			}--			/* set event key data */-			KeySym sym = XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0);-			win->event.keyCode = RGFW_apiKeyCodeToRGFW(E.xkey.keycode);-			-			char* str = XKeysymToString(sym);-			if (str != NULL)-				strncpy(win->event.keyName, str, 16);--			win->event.keyName[15] = '\0';		--			RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);-			-			/* get keystate data */-			win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased;--			XKeyboardState keystate;-			XGetKeyboardControl((Display*) win->src.display, &keystate);--			RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2));--			RGFW_keyboard[win->event.keyCode].current = (E.type == KeyPress);-			RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, (E.type == KeyPress));-			break;--		case ButtonPress:-		case ButtonRelease:-			win->event.type = E.type; // the events match -			-			switch(win->event.button) {-				case RGFW_mouseScrollUp:-					win->event.scroll = 1;-					break;-				case RGFW_mouseScrollDown:-					win->event.scroll = -1;-					break;-				default: break;-			}--			win->event.button = E.xbutton.button;-			RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-			RGFW_mouseButtons[win->event.button] = (E.type == ButtonPress);-			RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress));-			break;--		case MotionNotify:-			win->event.point.x = E.xmotion.x;-			win->event.point.y = E.xmotion.y;-			win->event.type = RGFW_mousePosChanged;-			RGFW_mousePosCallback(win, win->event.point);-			break;-		-		case Expose:-			win->event.type = RGFW_windowRefresh;-			RGFW_windowRefreshCallback(win);-			break;--		case ClientMessage:-			/* if the client closed the window*/-			if (E.xclient.data.l[0] == (i64) wm_delete_window) {-				win->event.type = RGFW_quit;-				RGFW_windowQuitCallback(win);-				break;-			}-			-			/* reset DND values */-			if (win->event.droppedFilesCount) {-				for (i = 0; i < win->event.droppedFilesCount; i++)-					win->event.droppedFiles[i][0] = '\0';-			}--			win->event.droppedFilesCount = 0;--			/*-				much of this event (drag and drop code) is source from glfw-			*/--			if ((win->src.winArgs & RGFW_ALLOW_DND) == 0)-				break;--			if (E.xclient.message_type == XdndEnter) {-				u64 count;-				Atom* formats;-				Atom real_formats[6];--				Bool list = E.xclient.data.l[1] & 1;--				xdnd.source = E.xclient.data.l[0];-				xdnd.version = E.xclient.data.l[1] >> 24;-				xdnd.format = None;--				if (xdnd.version > 5)-					break;--				if (list) {-					Atom actualType;-					i32 actualFormat;-					u64 bytesAfter;--					XGetWindowProperty((Display*) win->src.display,-						xdnd.source,-						XdndTypeList,-						0,-						LONG_MAX,-						False,-						4,-						&actualType,-						&actualFormat,-						(unsigned long*) &count,-						(unsigned long*) &bytesAfter,-						(u8**) &formats);-				} else {-					count = 0;--					if (E.xclient.data.l[2] != None)-						real_formats[count++] = E.xclient.data.l[2];-					if (E.xclient.data.l[3] != None)-						real_formats[count++] = E.xclient.data.l[3];-					if (E.xclient.data.l[4] != None)-						real_formats[count++] = E.xclient.data.l[4];-					-					formats = real_formats;-				}--				u32 i;-				for (i = 0; i < count; i++) {-					char* name = XGetAtomName((Display*) win->src.display, formats[i]);--					char* links[2] = { (char*) (const char*) "text/uri-list", (char*) (const char*) "text/plain" };-					for (; 1; name++) {-						u32 j;-						for (j = 0; j < 2; j++) {-							if (*links[j] != *name) {-								links[j] = (char*) (const char*) "\1";-								continue;-							}--							if (*links[j] == '\0' && *name == '\0')-								xdnd.format = formats[i];--							if (*links[j] != '\0' && *links[j] != '\1')-								links[j]++;-						}--						if (*name == '\0')-							break;-					}-				}--				if (list) {-					XFree(formats);-				}--				break;-			}-			if (E.xclient.message_type == XdndPosition) {-				const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff;-				const i32 yabs = (E.xclient.data.l[2]) & 0xffff;-				Window dummy;-				i32 xpos, ypos;--				if (xdnd.version > 5)-					break;--				XTranslateCoordinates((Display*) win->src.display,-					XDefaultRootWindow((Display*) win->src.display),-					(Window) win->src.window,-					xabs, yabs,-					&xpos, &ypos,-					&dummy);--				win->event.point.x = xpos;-				win->event.point.y = ypos;--				XEvent reply = { ClientMessage };-				reply.xclient.window = xdnd.source;-				reply.xclient.message_type = XdndStatus;-				reply.xclient.format = 32;-				reply.xclient.data.l[0] = (long) win->src.window;-				reply.xclient.data.l[2] = 0;-				reply.xclient.data.l[3] = 0;--				if (xdnd.format) {-					reply.xclient.data.l[1] = 1;-					if (xdnd.version >= 2)-						reply.xclient.data.l[4] = XdndActionCopy;-				}--				XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);-				XFlush((Display*) win->src.display);-				break;-			}--			if (E.xclient.message_type != XdndDrop)-				break;--			if (xdnd.version > 5)-				break;--			win->event.type = RGFW_dnd_init;--			if (xdnd.format) {-				Time time = CurrentTime;--				if (xdnd.version >= 1)-					time = E.xclient.data.l[2];--				XConvertSelection((Display*) win->src.display,-					XdndSelection,-					xdnd.format,-					XdndSelection,-					(Window) win->src.window,-					time);-			} else if (xdnd.version >= 2) {-				XEvent reply = { ClientMessage };-				reply.xclient.window = xdnd.source;-				reply.xclient.message_type = XdndFinished;-				reply.xclient.format = 32;-				reply.xclient.data.l[0] = (long) win->src.window;-				reply.xclient.data.l[1] = 0;-				reply.xclient.data.l[2] = None;--				XSendEvent((Display*) win->src.display, xdnd.source,-					False, NoEventMask, &reply);-				XFlush((Display*) win->src.display);-			}--			RGFW_dndInitCallback(win, win->event.point);-			break;-		case SelectionNotify:-			/* this is only for checking for xdnd drops */-			if (E.xselection.property != XdndSelection || !(win->src.winArgs | RGFW_ALLOW_DND))-				break;--			char* data;-			u64 result;--			Atom actualType;-			i32 actualFormat;-			u64 bytesAfter;--			XGetWindowProperty((Display*) win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data);--			if (result == 0)-				break;--			/*-			SOURCED FROM GLFW _glfwParseUriList-			Copyright (c) 2002-2006 Marcus Geelnard-			Copyright (c) 2006-2019 Camilla Löwy-			*/--			const char* prefix = "file://";--			char* line;--			win->event.droppedFilesCount = 0;--			win->event.type = RGFW_dnd;--			while ((line = strtok(data, "\r\n"))) {-				char path[RGFW_MAX_PATH];--				data = NULL;--				if (line[0] == '#')-					continue;--				char* l;-				for (l = line; 1; l++) {-					if ((l - line) > 7)-						break;-					else if (*l != prefix[(l - line)])-						break;-					else if (*l == '\0' && prefix[(l - line)] == '\0') {-						line += 7;-						while (*line != '/')-							line++;-						break;-					} else if (*l == '\0')-						break;-				}--				win->event.droppedFilesCount++;--				size_t index = 0;-				while (*line) {-					if (line[0] == '%' && line[1] && line[2]) {-						const char digits[3] = { line[1], line[2], '\0' };-						path[index] = (char) strtol(digits, NULL, 16);-						line += 2;-					} else-						path[index] = *line;--					index++;-					line++;-				}-				path[index] = '\0';-				strncpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1);-			}--			if (data)-				XFree(data);--			if (xdnd.version >= 2) {-				XEvent reply = { ClientMessage };-				reply.xclient.window = xdnd.source;-				reply.xclient.message_type = XdndFinished;-				reply.xclient.format = 32;-				reply.xclient.data.l[0] = (long) win->src.window;-				reply.xclient.data.l[1] = result;-				reply.xclient.data.l[2] = XdndActionCopy;--				XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);-				XFlush((Display*) win->src.display);-			}--			RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);-			break;--		case FocusIn:-			win->event.inFocus = 1;-			win->event.type = RGFW_focusIn;-			RGFW_focusCallback(win, 1);-			break;--			break;-		case FocusOut:-			win->event.inFocus = 0;-			win->event.type = RGFW_focusOut;-			RGFW_focusCallback(win, 0);-			break;-		-		case EnterNotify: {-			win->event.type = RGFW_mouseEnter;-			win->event.point.x = E.xcrossing.x;-			win->event.point.y = E.xcrossing.y;-			RGFW_mouseNotifyCallBack(win, win->event.point, 1);-			break;-		}--		case LeaveNotify: {-			win->event.type = RGFW_mouseLeave;-			RGFW_mouseNotifyCallBack(win, win->event.point, 0);-			break;-		}--		case ConfigureNotify: {-				/* detect resize */-      			if (E.xconfigure.width != win->r.w || E.xconfigure.height != win->r.h) {-					win->event.type = RGFW_windowResized;-					win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height);-					RGFW_windowResizeCallback(win, win->r);-					break;-      			}  -      -      			/* detect move */-      			if (E.xconfigure.x != win->r.x || E.xconfigure.y != win->r.y) {-					win->event.type = RGFW_windowMoved;-					win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h);-					RGFW_windowMoveCallback(win, win->r);-					break;-				} --				break;-		}-		default: {-			break;-		}-		}--		XFlush((Display*) win->src.display);--		if (win->event.type)-			return &win->event;-		else-			return NULL;-	}--	void RGFW_window_move(RGFW_window* win, RGFW_vector v) {-		assert(win != NULL);-		win->r.x = v.x;-		win->r.y = v.y;--		XMoveWindow((Display*) win->src.display, (Window) win->src.window, v.x, v.y);-	}---	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {-		assert(win != NULL);-		win->r.w = a.w;-		win->r.h = a.h;--		XResizeWindow((Display*) win->src.display, (Window) win->src.window, a.w, a.h);-	}--	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {-		assert(win != NULL);--		if (a.w == 0 && a.h == 0)-			return;--		XSizeHints hints;-		long flags;--		XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);--		hints.flags |= PMinSize;-		-		hints.min_width = a.w;-		hints.min_height = a.h;--		XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);-	}--	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {-		assert(win != NULL);--		if (a.w == 0 && a.h == 0)-			return;--		XSizeHints hints;-		long flags;--		XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);--		hints.flags |= PMaxSize;--		hints.max_width = a.w;-		hints.max_height = a.h;--		XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);-	}---	void RGFW_window_minimize(RGFW_window* win) {-		assert(win != NULL);--		XIconifyWindow(win->src.display, (Window) win->src.window, DefaultScreen(win->src.display));-		XFlush(win->src.display);-	}--	void RGFW_window_restore(RGFW_window* win) {-		assert(win != NULL);--		XMapWindow(win->src.display, (Window) win->src.window);-		XFlush(win->src.display);-	}	--	void RGFW_window_setName(RGFW_window* win, char* name) {-		assert(win != NULL);--		XStoreName((Display*) win->src.display, (Window) win->src.window, name);-	}-	-	void* RGFW_libxshape = NULL;--	#ifndef RGFW_NO_PASSTHROUGH-	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {-		assert(win != NULL);-		-		#if defined(__CYGWIN__)-			RGFW_libxshape = dlopen("libXext-6.so", RTLD_LAZY | RTLD_LOCAL);-		#elif defined(__OpenBSD__) || defined(__NetBSD__)-			RGFW_libxshape = dlopen("libXext.so", RTLD_LAZY | RTLD_LOCAL);-		#else-    		RGFW_libxshape = dlopen("libXext.so.6", RTLD_LAZY | RTLD_LOCAL);-		#endif-		-		typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int);-		static PFN_XShapeCombineMask XShapeCombineMask;-		-		typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int);-		static PFN_XShapeCombineRegion XShapeCombineRegion;-		-		if (XShapeCombineMask != NULL)-			XShapeCombineMask = (PFN_XShapeCombineMask) dlsym(RGFW_libxshape, "XShapeCombineMask");--		if (XShapeCombineRegion != NULL)-			XShapeCombineRegion = (PFN_XShapeCombineRegion) dlsym(RGFW_libxshape, "XShapeCombineMask");--		if (passthrough) {-			Region region = XCreateRegion();-			XShapeCombineRegion(win->src.display, win->src.window, ShapeInput, 0, 0, region, ShapeSet);-			XDestroyRegion(region);--			return;-		}--		XShapeCombineMask(win->src.display, win->src.window, ShapeInput, 0, 0, None, ShapeSet);-	}-	#endif--	/*-		the majority function is sourced from GLFW-	*/--	void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) {-		assert(win != NULL);--		i32 longCount = 2 + a.w * a.h;--		u64* X11Icon = (u64*) RGFW_MALLOC(longCount * sizeof(u64));-		u64* target = X11Icon;--		*target++ = a.w;-		*target++ = a.h;--		u32 i;--		for (i = 0; i < a.w * a.h; i++) {-			if (channels == 3)-				*target++ = ((icon[i * 3 + 0]) << 16) |-				((icon[i * 3 + 1]) << 8) |-				((icon[i * 3 + 2]) << 0) |-				(0xFF << 24);--			else if (channels == 4)-				*target++ = ((icon[i * 4 + 0]) << 16) |-				((icon[i * 4 + 1]) << 8) |-				((icon[i * 4 + 2]) << 0) |-				((icon[i * 4 + 3]) << 24);-		}--		static Atom NET_WM_ICON = 0;-		if (NET_WM_ICON == 0)-			NET_WM_ICON = XInternAtom((Display*) win->src.display, "_NET_WM_ICON", False);--		XChangeProperty((Display*) win->src.display, (Window) win->src.window,-			NET_WM_ICON,-			6, 32,-			PropModeReplace,-			(u8*) X11Icon,-			longCount);--		RGFW_FREE(X11Icon);--		XFlush((Display*) win->src.display);-	}--	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {-		assert(win != NULL);--#ifndef RGFW_NO_X11_CURSOR-		XcursorImage* native = XcursorImageCreate(a.w, a.h);-		native->xhot = 0;-		native->yhot = 0;--		u8* source = (u8*) image;-		XcursorPixel* target = native->pixels;--		u32 i;-		for (i = 0; i < a.w * a.h; i++, target++, source += 4) {-			u8 alpha = 0xFF;-			if (channels == 4)-				alpha = source[3];--			*target = (alpha << 24) | (((source[0] * alpha) / 255) << 16) | (((source[1] * alpha) / 255) << 8) | (((source[2] * alpha) / 255) << 0);-		}--		Cursor cursor = XcursorImageLoadCursor((Display*) win->src.display, native);-		XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor);--		XFreeCursor((Display*) win->src.display, (Cursor) cursor);-		XcursorImageDestroy(native);-#else-	RGFW_UNUSED(image) RGFW_UNUSED(a.w) RGFW_UNUSED(channels)-#endif-	}--	void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v) {-		assert(win != NULL);--		XEvent event;-		XQueryPointer(win->src.display, DefaultRootWindow(win->src.display),-			&event.xbutton.root, &event.xbutton.window,-			&event.xbutton.x_root, &event.xbutton.y_root,-			&event.xbutton.x, &event.xbutton.y,-			&event.xbutton.state);--		if (event.xbutton.x == v.x && event.xbutton.y == v.y)-			return;--		XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) v.x - win->r.x, (int) v.y - win->r.y);-	}--	RGFWDEF void RGFW_window_disableMouse(RGFW_window* win) {-		RGFW_UNUSED(win);-	}--	void RGFW_window_setMouseDefault(RGFW_window* win) {-		RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);-	}--	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {-		assert(win != NULL);--		if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8)))-			return;-		-		mouse = RGFW_mouseIconSrc[mouse];--		Cursor cursor = XCreateFontCursor((Display*) win->src.display, mouse);-		XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor);--		XFreeCursor((Display*) win->src.display, (Cursor) cursor);-	}--	void RGFW_window_hide(RGFW_window* win) {-		XMapWindow(win->src.display, win->src.window);-	}--	void RGFW_window_show(RGFW_window* win) {-		XUnmapWindow(win->src.display, win->src.window);-	}--	/*-		the majority function is sourced from GLFW-	*/-	char* RGFW_readClipboard(size_t* size) {-		static Atom UTF8 = 0;-		if (UTF8 == 0)-			UTF8 = XInternAtom(RGFW_root->src.display, "UTF8_STRING", True);--		XEvent event;-		int format;-		unsigned long N, sizeN;-		char* data, * s = NULL;-		Atom target;-		Atom CLIPBOARD = 0, XSEL_DATA = 0;--		if (CLIPBOARD == 0) {-			CLIPBOARD = XInternAtom(RGFW_root->src.display, "CLIPBOARD", 0);-			XSEL_DATA = XInternAtom(RGFW_root->src.display, "XSEL_DATA", 0);-		}--		XConvertSelection(RGFW_root->src.display, CLIPBOARD, UTF8, XSEL_DATA, RGFW_root->src.window, CurrentTime);-		XSync(RGFW_root->src.display, 0);-		XNextEvent(RGFW_root->src.display, &event);--		if (event.type != SelectionNotify || event.xselection.selection != CLIPBOARD || event.xselection.property == 0)-			return NULL;--		XGetWindowProperty(event.xselection.display, event.xselection.requestor,-			event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target,-			&format, &sizeN, &N, (unsigned char**) &data);--		if (target == UTF8 || target == XA_STRING) {-			s = (char*)RGFW_MALLOC(sizeof(char) * sizeN);-			strncpy(s, data, sizeN);-			s[sizeN] = '\0';-			XFree(data);-		}--		XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);--		if (s != NULL && size != NULL)-			*size = sizeN;--		return s;-	}--	/*-		almost all of this function is sourced from GLFW-	*/-	void RGFW_writeClipboard(const char* text, u32 textLen) {-		static Atom CLIPBOARD = 0,-			UTF8_STRING = 0,-			SAVE_TARGETS = 0,-			TARGETS = 0,-			MULTIPLE = 0,-			ATOM_PAIR = 0,-			CLIPBOARD_MANAGER = 0;--		if (CLIPBOARD == 0) {-			CLIPBOARD = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD", False);-			UTF8_STRING = XInternAtom((Display*) RGFW_root->src.display, "UTF8_STRING", False);-			SAVE_TARGETS = XInternAtom((Display*) RGFW_root->src.display, "SAVE_TARGETS", False);-			TARGETS = XInternAtom((Display*) RGFW_root->src.display, "TARGETS", False);-			MULTIPLE = XInternAtom((Display*) RGFW_root->src.display, "MULTIPLE", False);-			ATOM_PAIR = XInternAtom((Display*) RGFW_root->src.display, "ATOM_PAIR", False);-			CLIPBOARD_MANAGER = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD_MANAGER", False);-		}--		XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime);--		XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime);--		for (;;) {-			XEvent event;--			XNextEvent((Display*) RGFW_root->src.display, &event);-			if (event.type != SelectionRequest)-				return;--			const XSelectionRequestEvent* request = &event.xselectionrequest;--			XEvent reply = { SelectionNotify };--			char* selectionString = NULL;-			const Atom formats[] = { UTF8_STRING, XA_STRING };-			const i32 formatCount = sizeof(formats) / sizeof(formats[0]);--			selectionString = (char*) text;--			if (request->target == TARGETS) {-				const Atom targets[] = { TARGETS,-										MULTIPLE,-										UTF8_STRING,-										XA_STRING };--				XChangeProperty((Display*) RGFW_root->src.display,-					request->requestor,-					request->property,-					4,-					32,-					PropModeReplace,-					(u8*) targets,-					sizeof(targets) / sizeof(targets[0]));--				reply.xselection.property = request->property;-			}--			if (request->target == MULTIPLE) {--				Atom* targets;--				Atom actualType;-				i32 actualFormat;-				u64 count, bytesAfter;--				XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);--				u64 i;-				for (i = 0; i < count; i += 2) {-					i32 j;--					for (j = 0; j < formatCount; j++) {-						if (targets[i] == formats[j])-							break;-					}--					if (j < formatCount)-					{-						XChangeProperty((Display*) RGFW_root->src.display,-							request->requestor,-							targets[i + 1],-							targets[i],-							8,-							PropModeReplace,-							(u8*) selectionString,-							textLen);-					} else-						targets[i + 1] = None;-				}--				XChangeProperty((Display*) RGFW_root->src.display,-					request->requestor,-					request->property,-					ATOM_PAIR,-					32,-					PropModeReplace,-					(u8*) targets,-					count);--				XFree(targets);--				reply.xselection.property = request->property;-			}--			reply.xselection.display = request->display;-			reply.xselection.requestor = request->requestor;-			reply.xselection.selection = request->selection;-			reply.xselection.target = request->target;-			reply.xselection.time = request->time;--			XSendEvent((Display*) RGFW_root->src.display, request->requestor, False, 0, &reply);-		}-	}--	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {-		assert(win != NULL);--#ifdef __linux__-		char file[15];-		sprintf(file, "/dev/input/js%i", jsNumber);--		return RGFW_registerJoystickF(win, file);-#endif-	}--	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {-		assert(win != NULL);--#ifdef __linux__--		i32 js = open(file, O_RDONLY);--		if (js && win->src.joystickCount < 4) {-			win->src.joystickCount++;--			win->src.joysticks[win->src.joystickCount - 1] = open(file, O_RDONLY);--			u8 i;-			for (i = 0; i < 16; i++)-				win->src.jsPressed[win->src.joystickCount - 1][i] = 0;--		}--		else {-#ifdef RGFW_PRINT_ERRORS-			RGFW_error = 1;-			fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file);-#endif-		}--		return win->src.joystickCount - 1;-#endif-	}--	u8 RGFW_window_isFullscreen(RGFW_window* win) {-		assert(win != NULL);--		XWindowAttributes windowAttributes;-		XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);--		/* check if the window is visable */-		if (windowAttributes.map_state != IsViewable)-			return 0;--		/* check if the window covers the full screen */-		return (windowAttributes.x == 0 && windowAttributes.y == 0 &&-			windowAttributes.width == XDisplayWidth(win->src.display, DefaultScreen(win->src.display)) &&-			windowAttributes.height == XDisplayHeight(win->src.display, DefaultScreen(win->src.display)));-	}--	u8 RGFW_window_isHidden(RGFW_window* win) {-		assert(win != NULL);--		XWindowAttributes windowAttributes;-		XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);--		return (windowAttributes.map_state == IsUnmapped && !RGFW_window_isMinimized(win));-	}--	u8 RGFW_window_isMinimized(RGFW_window* win) {-		assert(win != NULL);--		static Atom prop = 0;-		if (prop == 0)-			prop = XInternAtom(win->src.display, "WM_STATE", False);--		Atom actual_type;-		i32 actual_format;-		u64 nitems, bytes_after;-		unsigned char* prop_data;--		i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, prop, 0, 2, False,-			AnyPropertyType, &actual_type, &actual_format,-			&nitems, &bytes_after, &prop_data);--		if (status == Success && nitems >= 1 && *((int*) prop_data) == IconicState) {-			XFree(prop_data);-			return 1;-		}--		if (prop_data != NULL)-			XFree(prop_data);--		return 0;-	}--	u8 RGFW_window_isMaximized(RGFW_window* win) {-		assert(win != NULL);--		static Atom net_wm_state = 0;-		static Atom net_wm_state_maximized_horz = 0;-		static Atom net_wm_state_maximized_vert = 0;--		if (net_wm_state == 0) {-			net_wm_state = XInternAtom(win->src.display, "_NET_WM_STATE", False);-			net_wm_state_maximized_vert = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_VERT", False);-			net_wm_state_maximized_horz = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);-		}--		Atom actual_type;-		i32 actual_format;-		u64 nitems, bytes_after;-		unsigned char* prop_data;--		i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, net_wm_state, 0, 1024, False,-			XA_ATOM, &actual_type, &actual_format,-			&nitems, &bytes_after, &prop_data);--		if (status != Success) {-			if (prop_data != NULL)-				XFree(prop_data);--			return 0;-		}--		Atom* atoms = (Atom*) prop_data;-		u64 i;-		for (i = 0; i < nitems; ++i) {-			if (atoms[i] == net_wm_state_maximized_horz ||-				atoms[i] == net_wm_state_maximized_vert) {-				XFree(prop_data);-				return 1;-			}-		}--		return 0;-	}--	static void XGetSystemContentScale(Display* display, float* xscale, float* yscale) {-		float xdpi = 96.f, ydpi = 96.f;--#ifndef RGFW_NO_DPI-		char* rms = XResourceManagerString(display);-		XrmDatabase db = NULL;--		if (rms && db)-			db = XrmGetStringDatabase(rms);--		if (db == 0) {-			*xscale = xdpi / 96.f;-			*yscale = ydpi / 96.f;-			return;-		}--		XrmValue value;-		char* type = NULL;--		if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strncmp(type, "String", 7) == 0)-			xdpi = ydpi = atof(value.addr);-		XrmDestroyDatabase(db);-#endif--		* xscale = xdpi / 96.f;-		*yscale = ydpi / 96.f;-	}--	RGFW_monitor RGFW_XCreateMonitor(i32 screen) {-		RGFW_monitor monitor;--		Display* display = XOpenDisplay(NULL);--		monitor.rect = RGFW_RECT(0, 0, DisplayWidth(display, screen), DisplayHeight(display, screen));-		monitor.physW = (monitor.rect.w * 25.4f / 96.f);-		monitor.physH = (monitor.rect.h * 25.4f / 96.f);--		strncpy(monitor.name, DisplayString(display), 128);--		XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY);--		XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen));--		XRRCrtcInfo* ci = NULL;-		int crtc = 0;--		if (sr->ncrtc > crtc) {-			ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]);-		}--		if (ci == NULL) {-			XRRFreeScreenResources(sr);-			XCloseDisplay(display);-			return monitor;-		}--		monitor.rect.x = ci->x;-		monitor.rect.y = ci->y;--		XRRFreeCrtcInfo(ci);-		XRRFreeScreenResources(sr);--		XCloseDisplay(display);--		return monitor;-	}--	RGFW_monitor RGFW_monitors[6];-	RGFW_monitor* RGFW_getMonitors(void) {-		size_t i;-		for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++)-			RGFW_monitors[i] = RGFW_XCreateMonitor(i);--		return RGFW_monitors;-	}--	RGFW_monitor RGFW_getPrimaryMonitor(void) {-		assert(RGFW_root != NULL);--		i32 primary = -1;-		Window root = DefaultRootWindow(RGFW_root->src.display);-		XRRScreenResources* res = XRRGetScreenResources(RGFW_root->src.display, root);--		for (int i = 0; i < res->noutput; i++) {-			XRROutputInfo* output_info = XRRGetOutputInfo(RGFW_root->src.display, res, res->outputs[i]);-			if (output_info->connection == RR_Connected && output_info->crtc) {-				XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(RGFW_root->src.display, res, output_info->crtc);-				if (crtc_info->mode != None && crtc_info->x == 0 && crtc_info->y == 0) {-					primary = i;-					XRRFreeCrtcInfo(crtc_info);-					XRRFreeOutputInfo(output_info);-					break;-				}-				XRRFreeCrtcInfo(crtc_info);-			}-			XRRFreeOutputInfo(output_info);-		}--		XRRFreeScreenResources(res);--		return RGFW_XCreateMonitor(primary);-	}--	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {-		return RGFW_XCreateMonitor(DefaultScreen(win->src.display));-	}--	#ifdef RGFW_OPENGL-	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {-		assert(win != NULL);--		glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf);-	}-	#endif---	void RGFW_window_swapBuffers(RGFW_window* win) {-		assert(win != NULL);--		RGFW_window_makeCurrent(win);--		/* clear the window*/-		if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) {-#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)-			#ifdef RGFW_OSMESA-			RGFW_OSMesa_reorganize();-			#endif-			RGFW_area area = RGFW_bufferSize;--#ifndef RGFW_X11_DONT_CONVERT_BGR-			win->src.bitmap->data = (char*) win->buffer;-			u32 x, y;-			for (y = 0; y < (u32)win->r.h; y++) {-				for (x = 0; x < (u32)win->r.w; x++) {-					u32 index = (y * 4 * area.w) + x * 4;--					u8 red = win->src.bitmap->data[index];-					win->src.bitmap->data[index] = win->buffer[index + 2];-					win->src.bitmap->data[index + 2] = red;--				}-			}-#endif	-			XPutImage(win->src.display, (Window) win->src.window, win->src.gc, win->src.bitmap, 0, 0, 0, 0, RGFW_bufferSize.w, RGFW_bufferSize.h);-#endif-		}--		if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) {-			#ifdef RGFW_EGL-					eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);-			#elif defined(RGFW_OPENGL)-					glXSwapBuffers((Display*) win->src.display, (Window) win->src.window);-			#endif-		}--		RGFW_window_checkFPS(win);-	}--	#if !defined(RGFW_EGL)	-	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {-		assert(win != NULL);--		#if defined(RGFW_OPENGL)	-		((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval);-		#endif--		win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;-	}-	#endif---	void RGFW_window_close(RGFW_window* win) {-		assert(win != NULL);-#ifdef RGFW_EGL-		RGFW_closeEGL(win);-#endif--#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)-		if (win->buffer != NULL) {-			XDestroyImage((XImage*) win->src.bitmap);-			XFreeGC(win->src.display, win->src.gc);-		}-#endif--		if ((Display*) win->src.display) {-#ifdef RGFW_OPENGL-			glXDestroyContext((Display*) win->src.display, win->src.rSurf);-#endif--			if (win == RGFW_root)-				RGFW_root = NULL;--			if ((Drawable) win->src.window)-				XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /* close the window*/-			-			XCloseDisplay((Display*) win->src.display); /* kill the display*/-		}--#ifdef RGFW_ALLOC_DROPFILES-		{-			u32 i;-			for (i = 0; i < RGFW_MAX_DROPS; i++)-				RGFW_FREE(win->event.droppedFiles[i]);---			RGFW_FREE(win->event.droppedFiles);-		}-#endif--		RGFW_windowsOpen--;-#if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR)-		if (X11Cursorhandle != NULL && RGFW_windowsOpen <= 0) {-			dlclose(X11Cursorhandle);--			X11Cursorhandle = NULL;-		}-#endif--		if (RGFW_libxshape != NULL && RGFW_windowsOpen <= 0) {-			dlclose(RGFW_libxshape);-			RGFW_libxshape = NULL;-		}--		/* set cleared display / window to NULL for error checking */-		win->src.display = (Display*) 0;-		win->src.window = (Window) 0;--		u8 i;-		for (i = 0; i < win->src.joystickCount; i++)-			close(win->src.joysticks[i]);--		RGFW_FREE(win); /* free collected window data */-	}--	u64 	RGFW_getTimeNS(void) { -		struct timespec ts = { 0 };-		clock_gettime(1, &ts);-		unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;--		return nanoSeconds;-	}--	u64 RGFW_getTime(void) {-		struct timespec ts = { 0 };-		clock_gettime(1, &ts);-		unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;--		return (double)(nanoSeconds) * 1e-9;-	}-/* -	End of linux / unix defines-*/--#endif /* RGFW_X11 */---/*--	Start of Windows defines---*/--#ifdef RGFW_WINDOWS-	#include <processthreadsapi.h>-	#include <wchar.h>-	#include <locale.h>-	#include <windowsx.h>-	#include <shellapi.h>-	#include <shellscalingapi.h>-	#include <windows.h>-	#include <winuser.rh>--	#ifndef RGFW_NO_XINPUT-	typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);-	PFN_XInputGetState XInputGetStateSRC = NULL;-	#define XInputGetState XInputGetStateSRC--	typedef DWORD (WINAPI * PFN_XInputGetKeystroke)(DWORD, DWORD, PXINPUT_KEYSTROKE);-	PFN_XInputGetKeystroke XInputGetKeystrokeSRC = NULL;-	#define XInputGetKeystroke XInputGetKeystrokeSRC--	static HMODULE RGFW_XInput_dll = NULL;-	#endif--	u32 RGFW_mouseIconSrc[] = {OCR_NORMAL, OCR_NORMAL, OCR_IBEAM, OCR_CROSS, OCR_HAND, OCR_SIZEWE, OCR_SIZENS, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEALL, OCR_NO};--	char* createUTF8FromWideStringWin32(const WCHAR* source);--#define GL_FRONT				0x0404-#define GL_BACK					0x0405-#define GL_LEFT					0x0406-#define GL_RIGHT				0x0407--#if defined(RGFW_OSMESA) && defined(RGFW_LINK_OSMESA)--	typedef void (GLAPIENTRY* PFN_OSMesaDestroyContext)(OSMesaContext);-	typedef i32(GLAPIENTRY* PFN_OSMesaMakeCurrent)(OSMesaContext, void*, int, int, int);-	typedef OSMesaContext(GLAPIENTRY* PFN_OSMesaCreateContext)(GLenum, OSMesaContext);--	PFN_OSMesaMakeCurrent OSMesaMakeCurrentSource;-	PFN_OSMesaCreateContext OSMesaCreateContextSource;-	PFN_OSMesaDestroyContext OSMesaDestroyContextSource;--#define OSMesaCreateContext OSMesaCreateContextSource-#define OSMesaMakeCurrent OSMesaMakeCurrentSource-#define OSMesaDestroyContext OSMesaDestroyContextSource-#endif--	typedef int (*PFN_wglGetSwapIntervalEXT)(void);-	PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL;-#define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc----#if defined(RGFW_DIRECTX)-	RGFW_directXinfo RGFW_dxInfo;--	RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; }-#endif--	void* RGFWjoystickApi = NULL;--	/* these two wgl functions need to be preloaded */-	typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList);-	PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;--	/* defines for creating ARB attributes */-#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000-#define WGL_CONTEXT_MAJOR_VERSION_ARB             0x2091-#define WGL_CONTEXT_MINOR_VERSION_ARB             0x2092-#define WGL_DRAW_TO_WINDOW_ARB                    0x2001-#define WGL_ACCELERATION_ARB                      0x2003-#define WGL_NO_ACCELERATION_ARB 0x2025-#define WGL_SUPPORT_OPENGL_ARB                    0x2010-#define WGL_DOUBLE_BUFFER_ARB                     0x2011-#define WGL_COLOR_BITS_ARB                        0x2014-#define WGL_RED_BITS_ARB 0x2015-#define WGL_RED_SHIFT_ARB 0x2016-#define WGL_GREEN_BITS_ARB 0x2017-#define WGL_GREEN_SHIFT_ARB 0x2018-#define WGL_BLUE_BITS_ARB 0x2019-#define WGL_BLUE_SHIFT_ARB 0x201a-#define WGL_ALPHA_BITS_ARB 0x201b-#define WGL_ALPHA_SHIFT_ARB 0x201c-#define WGL_ACCUM_BITS_ARB 0x201d-#define WGL_ACCUM_RED_BITS_ARB 0x201e-#define WGL_ACCUM_GREEN_BITS_ARB 0x201f-#define WGL_ACCUM_BLUE_BITS_ARB 0x2020-#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021-#define WGL_DEPTH_BITS_ARB 0x2022-#define WGL_AUX_BUFFERS_ARB 0x2024-#define WGL_STEREO_ARB 0x2012-#define WGL_DEPTH_BITS_ARB                        0x2022-#define WGL_STENCIL_BITS_ARB 					  0x2023-#define WGL_FULL_ACCELERATION_ARB                 0x2027-#define WGL_CONTEXT_FLAGS_ARB                     0x2094-#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126-#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002-#define WGL_SAMPLE_BUFFERS_ARB               0x2041-#define WGL_SAMPLES_ARB 0x2042-#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9--#ifndef RGFW_EGL-static HMODULE wglinstance = NULL;-#endif--#ifdef RGFW_WGL_LOAD-	typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC);-	typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC);-	typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR);-	typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC);-	typedef HDC(WINAPI* PFN_wglGetCurrentDC)();-	typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)();--	PFN_wglCreateContext wglCreateContextSRC;-	PFN_wglDeleteContext wglDeleteContextSRC;-	PFN_wglGetProcAddress wglGetProcAddressSRC;-	PFN_wglMakeCurrent wglMakeCurrentSRC;-	PFN_wglGetCurrentDC wglGetCurrentDCSRC;-	PFN_wglGetCurrentContext wglGetCurrentContextSRC;--	#define wglCreateContext wglCreateContextSRC-	#define wglDeleteContext wglDeleteContextSRC-	#define wglGetProcAddress wglGetProcAddressSRC-	#define wglMakeCurrent wglMakeCurrentSRC--	#define wglGetCurrentDC wglGetCurrentDCSRC-	#define wglGetCurrentContext wglGetCurrentContextSRC-#endif--#ifdef RGFW_OPENGL-	void* RGFW_getProcAddress(const char* procname) { -		void* proc = (void*) wglGetProcAddress(procname);-		if (proc)-			return proc;--		return (void*) GetProcAddress(wglinstance, procname); -	}--	typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);-	static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;-#endif--	RGFW_window RGFW_eventWindow;--	LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {-		switch (message) {-		case WM_MOVE:-			RGFW_eventWindow.r.x = LOWORD(lParam);-			RGFW_eventWindow.r.y = HIWORD(lParam);-			RGFW_eventWindow.src.window = hWnd;-			return DefWindowProcA(hWnd, message, wParam, lParam);-		case WM_SIZE:-			RGFW_eventWindow.r.w = LOWORD(lParam);-			RGFW_eventWindow.r.h = HIWORD(lParam);-			RGFW_eventWindow.src.window = hWnd;-			return DefWindowProcA(hWnd, message, wParam, lParam); // Call DefWindowProc after handling-		default:-			return DefWindowProcA(hWnd, message, wParam, lParam);-		}-	}-	-	#ifndef RGFW_NO_DPI-	static HMODULE RGFW_Shcore_dll = NULL;-	typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);-	PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL;-	#define GetDpiForMonitor GetDpiForMonitorSRC-	#endif--	__declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod);--	#ifndef RGFW_NO_XINPUT-	void RGFW_loadXInput(void) {-		u32 i;-		static const char* names[] = { -			"xinput1_4.dll",-			"xinput1_3.dll",-			"xinput9_1_0.dll",-			"xinput1_2.dll",-			"xinput1_1.dll"-		};--		for (i = 0; i < sizeof(names) / sizeof(const char*);  i++) {-			RGFW_XInput_dll = LoadLibraryA(names[i]);--			if (RGFW_XInput_dll) {-				XInputGetStateSRC = (PFN_XInputGetState)(void*)GetProcAddress(RGFW_XInput_dll, "XInputGetState");-			-				if (XInputGetStateSRC == NULL)-					printf("Failed to load XInputGetState");-			}-		}-	}-	#endif--	RGFWDEF void RGFW_init_buffer(RGFW_window* win);-	void RGFW_init_buffer(RGFW_window* win) {-#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)-	if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)-		RGFW_bufferSize = RGFW_getScreenSize();-	-	BITMAPV5HEADER bi = { 0 };-	ZeroMemory(&bi, sizeof(bi));-	bi.bV5Size = sizeof(bi);-	bi.bV5Width = RGFW_bufferSize.w;-	bi.bV5Height = -((LONG) RGFW_bufferSize.h);-	bi.bV5Planes = 1;-	bi.bV5BitCount = 32;-	bi.bV5Compression = BI_BITFIELDS;-	bi.bV5BlueMask = 0x00ff0000;-	bi.bV5GreenMask = 0x0000ff00;-	bi.bV5RedMask = 0x000000ff;-	bi.bV5AlphaMask = 0xff000000;--	win->src.bitmap = CreateDIBSection(win->src.hdc,-		(BITMAPINFO*) &bi,-		DIB_RGB_COLORS,-		(void**) &win->buffer,-		NULL,-		(DWORD) 0);-	-	win->src.hdcMem = CreateCompatibleDC(win->src.hdc);--	#if defined(RGFW_OSMESA)-	win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL);-	OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);-	#endif-#else-RGFW_UNUSED(win); /* if buffer rendering is not being used */-#endif-	}--	void RGFW_window_setDND(RGFW_window* win, b8 allow) {-		DragAcceptFiles(win->src.window, allow);-	}--	void RGFW_clipCursor(RGFW_rect rect) {-		if (!rect.x && !rect.y && rect.w && !rect.h) {-			ClipCursor(NULL);-			return;-		}--		RECT r = {rect.x, rect.y, rect.x + rect.w, rect.y + rect.h};-		ClipCursor(&r);-	}--	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {-		#ifndef RGFW_NO_XINPUT-		if (RGFW_XInput_dll == NULL)-			RGFW_loadXInput();-		#endif--		#ifndef RGFW_NO_DPI-		if (RGFW_Shcore_dll == NULL) {-			RGFW_Shcore_dll = LoadLibraryA("shcore.dll");-			GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor");-		}-		#endif--		if (wglinstance == NULL) {-			wglinstance = LoadLibraryA("opengl32.dll");-#ifdef RGFW_WGL_LOAD-			wglCreateContextSRC = (PFN_wglCreateContext) GetProcAddress(wglinstance, "wglCreateContext");-			wglDeleteContextSRC = (PFN_wglDeleteContext) GetProcAddress(wglinstance, "wglDeleteContext");-			wglGetProcAddressSRC = (PFN_wglGetProcAddress) GetProcAddress(wglinstance, "wglGetProcAddress");-			wglMakeCurrentSRC = (PFN_wglMakeCurrent) GetProcAddress(wglinstance, "wglMakeCurrent");-			wglGetCurrentDCSRC = (PFN_wglGetCurrentDC) GetProcAddress(wglinstance, "wglGetCurrentDC");-			wglGetCurrentContextSRC = (PFN_wglGetCurrentContext) GetProcAddress(wglinstance, "wglGetCurrentContext");-#endif-		}--		timeBeginPeriod(1);--		if (name[0] == 0) name = (char*) " ";--		RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);-		RGFW_eventWindow.src.window = NULL;--		RGFW_window* win = RGFW_window_basic_init(rect, args);--		win->src.maxSize = RGFW_AREA(0, 0);-		win->src.minSize = RGFW_AREA(0, 0);---		HINSTANCE inh = GetModuleHandleA(NULL);--		WNDCLASSA Class = { 0 }; /* Setup the Window class. */-		Class.lpszClassName = name;-		Class.hInstance = inh;-		Class.hCursor = LoadCursor(NULL, IDC_ARROW);-		Class.lpfnWndProc = WndProc;--		RegisterClassA(&Class);--		DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;--		RECT windowRect, clientRect;--		if (!(args & RGFW_NO_BORDER)) {-			window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_VISIBLE | WS_MINIMIZEBOX;--			if (!(args & RGFW_NO_RESIZE))-				window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;-		} else-			window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX;--		HWND dummyWin = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h, 0, 0, inh, 0);--		GetWindowRect(dummyWin, &windowRect);-		GetClientRect(dummyWin, &clientRect);--		win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);-		win->src.window = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h + win->src.hOffset, 0, 0, inh, 0);--		if (args & RGFW_ALLOW_DND) {-			win->src.winArgs |= RGFW_ALLOW_DND;-			RGFW_window_setDND(win, 1);-		}-		win->src.hdc = GetDC(win->src.window);--		if ((args & RGFW_NO_INIT_API) == 0) {-#ifdef RGFW_DIRECTX-		assert(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0);--		if (FAILED(RGFW_dxInfo.pFactory->lpVtbl->EnumAdapters(RGFW_dxInfo.pFactory, 0, &RGFW_dxInfo.pAdapter))) {-			fprintf(stderr, "Failed to enumerate DXGI adapters\n");-			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);-			return NULL;-		}--		D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };--		if (FAILED(D3D11CreateDevice(RGFW_dxInfo.pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, featureLevels, 1, D3D11_SDK_VERSION, &RGFW_dxInfo.pDevice, NULL, &RGFW_dxInfo.pDeviceContext))) {-			fprintf(stderr, "Failed to create Direct3D device\n");-			RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);-			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);-			return NULL;-		}--		DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };-		swapChainDesc.BufferCount = 1;-		swapChainDesc.BufferDesc.Width = win->r.w;-		swapChainDesc.BufferDesc.Height = win->r.h;-		swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;-		swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;-		swapChainDesc.OutputWindow = win->src.window;-		swapChainDesc.SampleDesc.Count = 1;-		swapChainDesc.SampleDesc.Quality = 0;-		swapChainDesc.Windowed = TRUE;-		RGFW_dxInfo.pFactory->lpVtbl->CreateSwapChain(RGFW_dxInfo.pFactory, (IUnknown*) RGFW_dxInfo.pDevice, &swapChainDesc, &win->src.swapchain);--		ID3D11Texture2D* pBackBuffer;-		win->src.swapchain->lpVtbl->GetBuffer(win->src.swapchain, 0, &__uuidof(ID3D11Texture2D), (LPVOID*) &pBackBuffer);-		RGFW_dxInfo.pDevice->lpVtbl->CreateRenderTargetView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pBackBuffer, NULL, &win->src.renderTargetView);-		pBackBuffer->lpVtbl->Release(pBackBuffer);--		D3D11_TEXTURE2D_DESC depthStencilDesc = { 0 };-		depthStencilDesc.Width = win->r.w;-		depthStencilDesc.Height = win->r.h;-		depthStencilDesc.MipLevels = 1;-		depthStencilDesc.ArraySize = 1;-		depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;-		depthStencilDesc.SampleDesc.Count = 1;-		depthStencilDesc.SampleDesc.Quality = 0;-		depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;-		depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;--		ID3D11Texture2D* pDepthStencilTexture = NULL;-		RGFW_dxInfo.pDevice->lpVtbl->CreateTexture2D(RGFW_dxInfo.pDevice, &depthStencilDesc, NULL, &pDepthStencilTexture);--		D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = { 0 };-		depthStencilViewDesc.Format = depthStencilDesc.Format;-		depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;-		depthStencilViewDesc.Texture2D.MipSlice = 0;--		RGFW_dxInfo.pDevice->lpVtbl->CreateDepthStencilView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pDepthStencilTexture, &depthStencilViewDesc, &win->src.pDepthStencilView);--		pDepthStencilTexture->lpVtbl->Release(pDepthStencilTexture);--		RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, win->src.pDepthStencilView);-#endif--#ifdef RGFW_OPENGL -		HDC dummy_dc = GetDC(dummyWin);--		PIXELFORMATDESCRIPTOR pfd = {-			.nSize = sizeof(pfd),-			.nVersion = 1,-			.iPixelType = PFD_TYPE_RGBA,-			.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,-			.cColorBits = 24,-			.cAlphaBits = 8,-			.iLayerType = PFD_MAIN_PLANE,-			.cDepthBits = 32,-			.cStencilBits = 8,-		};--		int pixel_format = ChoosePixelFormat(dummy_dc, &pfd);-		SetPixelFormat(dummy_dc, pixel_format, &pfd);--		HGLRC dummy_context = wglCreateContext(dummy_dc);-		wglMakeCurrent(dummy_dc, dummy_context);--		if (wglChoosePixelFormatARB == NULL) {-			wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) (void*) wglGetProcAddress("wglCreateContextAttribsARB");-			wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) (void*)wglGetProcAddress("wglChoosePixelFormatARB");-		}--		wglMakeCurrent(dummy_dc, 0);-		wglDeleteContext(dummy_context);-		ReleaseDC(dummyWin, dummy_dc);--		if (wglCreateContextAttribsARB != NULL) {-			PIXELFORMATDESCRIPTOR pfd = (PIXELFORMATDESCRIPTOR){ sizeof(pfd), 1, PFD_TYPE_RGBA, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};--			if (args & RGFW_OPENGL_SOFTWARE)-				pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED;--			if (wglChoosePixelFormatARB != NULL) {-				i32* pixel_format_attribs = (i32*)RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);--				int pixel_format;-				UINT num_formats;-				wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats);-				if (!num_formats) {-					printf("Failed to set the OpenGL 3.3 pixel format.\n");-				}--				DescribePixelFormat(win->src.hdc, pixel_format, sizeof(pfd), &pfd);-				if (!SetPixelFormat(win->src.hdc, pixel_format, &pfd)) {-					printf("Failed to set the OpenGL 3.3 pixel format.\n");-				}-			}--			u32 index = 0;-			i32 attribs[40];--			SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);--			if (RGFW_majorVersion || RGFW_minorVersion) {-				SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);-				SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);-			}--			SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);--			if (RGFW_majorVersion || RGFW_minorVersion) {-				SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);-				SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);-			}--			SET_ATTRIB(0, 0);--			win->src.rSurf = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs);-		} else {-			fprintf(stderr, "Failed to create an accelerated OpenGL Context\n");--			int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd);-			SetPixelFormat(win->src.hdc, pixel_format, &pfd);--			win->src.rSurf = wglCreateContext(win->src.hdc);-		}-		-		wglMakeCurrent(win->src.hdc, win->src.rSurf);-#endif-	}--#ifdef RGFW_OSMESA-#ifdef RGFW_LINK_OSM ESA-		OSMesaMakeCurrentSource = (PFN_OSMesaMakeCurrent) GetProcAddress(win->src.hdc, "OSMesaMakeCurrent");-		OSMesaCreateContextSource = (PFN_OSMesaCreateContext) GetProcAddress(win->src.hdc, "OSMesaCreateContext");-		OSMesaDestroyContextSource = (PFN_OSMesaDestroyContext) GetProcAddress(win->src.hdc, "OSMesaDestroyContext");-#endif-#endif--#ifdef RGFW_OPENGL-		if ((args & RGFW_NO_INIT_API) == 0) {-			ReleaseDC(win->src.window, win->src.hdc);-			win->src.hdc = GetDC(win->src.window);-			wglMakeCurrent(win->src.hdc, win->src.rSurf);-		}-#endif--		DestroyWindow(dummyWin);-		RGFW_init_buffer(win);---		#ifndef RGFW_NO_MONITOR-		if (args & RGFW_SCALE_TO_MONITOR)-			RGFW_window_scaleToMonitor(win);-		#endif--#ifdef RGFW_EGL-		if ((args & RGFW_NO_INIT_API) == 0)-			RGFW_createOpenGLContext(win);-#endif--		if (args & RGFW_HIDE_MOUSE)-			RGFW_window_showMouse(win, 0);--		if (args & RGFW_TRANSPARENT_WINDOW) {-			SetWindowLong(win->src.window, GWL_EXSTYLE, GetWindowLong(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED);-			SetLayeredWindowAttributes(win->src.window, RGB(255, 255, 255), RGFW_ALPHA, LWA_ALPHA);-		}--		ShowWindow(win->src.window, SW_SHOWNORMAL);-		-		if (RGFW_root == NULL)-			RGFW_root = win;-		-		#ifdef RGFW_OPENGL-		else -			wglShareLists(RGFW_root->src.rSurf, win->src.rSurf);-		#endif--		return win;-	}--	void RGFW_window_setBorder(RGFW_window* win, u8 border) {-		DWORD style = GetWindowLong(win->src.window, GWL_STYLE);--		if (border == 0) {-			SetWindowLong(win->src.window, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW);-			SetWindowPos(-				win->src.window, HWND_TOP, 0, 0, 0, 0,-				SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE-			);-		}-		else {-			SetWindowLong(win->src.window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW);-			SetWindowPos(-				win->src.window, HWND_TOP, 0, 0, 0, 0,-				SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE-			);-		}-	}---	RGFW_area RGFW_getScreenSize(void) {-		return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES));-	}--	RGFW_vector RGFW_getGlobalMousePoint(void) {-		POINT p;-		GetCursorPos(&p);--		return RGFW_VECTOR(p.x, p.y);-	}--	RGFW_vector RGFW_window_getMousePoint(RGFW_window* win) {-		POINT p;-		GetCursorPos(&p);-		ScreenToClient(win->src.window, &p);--		return RGFW_VECTOR(p.x, p.y);-	}--	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {-		assert(win != NULL);-		win->src.minSize = a;-	}--	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {-		assert(win != NULL);-		win->src.maxSize = a;-	}---	void RGFW_window_minimize(RGFW_window* win) {-		assert(win != NULL);--		ShowWindow(win->src.window, SW_MINIMIZE);-	}--	void RGFW_window_restore(RGFW_window* win) {-		assert(win != NULL);--		ShowWindow(win->src.window, SW_RESTORE);-	}---	u8 RGFW_xinput2RGFW[] = {-		RGFW_JS_A, /* or PS X button */-		RGFW_JS_B, /* or PS circle button */-		RGFW_JS_X, /* or PS square button */-		RGFW_JS_Y, /* or PS triangle button */-		RGFW_JS_R1, /* right bumper */-		RGFW_JS_L1, /* left bump */-		RGFW_JS_L2, /* left trigger*/-		RGFW_JS_R2, /* right trigger */-		0, 0, 0, 0, 0, 0, 0, 0,-		RGFW_JS_UP, /* dpad up */-		RGFW_JS_DOWN, /* dpad down*/-		RGFW_JS_LEFT, /* dpad left */-		RGFW_JS_RIGHT, /* dpad right */-		RGFW_JS_START, /* start button */-		RGFW_JS_SELECT/* select button */-	};--	static i32 RGFW_checkXInput(RGFW_window* win, RGFW_Event* e) {-		size_t i;-		for (i = 0; i < 4; i++) {-			XINPUT_KEYSTROKE keystroke;--			if (XInputGetKeystroke == NULL)-				return 0;--			DWORD result = XInputGetKeystroke((DWORD)i, 0, &keystroke);--			if ((keystroke.Flags & XINPUT_KEYSTROKE_REPEAT) == 0 && result != ERROR_EMPTY) {-				if (result != ERROR_SUCCESS)-					return 0;--				if (keystroke.VirtualKey > VK_PAD_BACK)-					continue;--				// RGFW_jsButtonPressed + 1 = RGFW_jsButtonReleased-				e->type = RGFW_jsButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN);-				e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800];-				win->src.jsPressed[i][e->button] = !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN);--				return 1;-			}--			XINPUT_STATE state;-			if (XInputGetState == NULL ||-				XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED-			)-				return 0;-#define INPUT_DEADZONE  ( 0.24f * (float)(0x7FFF) )  // Default to 24% of the +/- 32767 range.   This is a reasonable default value but can be altered if needed.--			if ((state.Gamepad.sThumbLX < INPUT_DEADZONE &&-				state.Gamepad.sThumbLX > -INPUT_DEADZONE) &&-				(state.Gamepad.sThumbLY < INPUT_DEADZONE &&-					state.Gamepad.sThumbLY > -INPUT_DEADZONE))-			{-				state.Gamepad.sThumbLX = 0;-				state.Gamepad.sThumbLY = 0;-			}--			if ((state.Gamepad.sThumbRX < INPUT_DEADZONE &&-				state.Gamepad.sThumbRX > -INPUT_DEADZONE) &&-				(state.Gamepad.sThumbRY < INPUT_DEADZONE &&-					state.Gamepad.sThumbRY > -INPUT_DEADZONE))-			{-				state.Gamepad.sThumbRX = 0;-				state.Gamepad.sThumbRY = 0;-			}--			e->axisesCount = 2;-			RGFW_vector axis1 = RGFW_VECTOR(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY);-			RGFW_vector axis2 = RGFW_VECTOR(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY);--			if (axis1.x != e->axis[0].x || axis1.y != e->axis[0].y || axis2.x != e->axis[1].x || axis2.y != e->axis[1].y) {-				e->type = RGFW_jsAxisMove;--				e->axis[0] = axis1;-				e->axis[1] = axis2;--				return 1;-			}--			e->axis[0] = axis1;-			e->axis[1] = axis2;-		}--		return 0;-	}--	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {-		assert(win != NULL);--		if (win->event.type == RGFW_quit) {-			return NULL;-		}--		MSG msg;--		if (RGFW_eventWindow.src.window == win->src.window) {-			if (RGFW_eventWindow.r.x != -1) {-				win->r.x = RGFW_eventWindow.r.x;-				win->r.y = RGFW_eventWindow.r.y;-				win->event.type = RGFW_windowMoved;-				RGFW_windowMoveCallback(win, win->r);-			}--			if (RGFW_eventWindow.r.w != -1) {-				win->r.w = RGFW_eventWindow.r.w;-				win->r.h = RGFW_eventWindow.r.h;-				win->event.type = RGFW_windowResized;-				RGFW_windowResizeCallback(win, win->r);-			}--			RGFW_eventWindow.src.window = NULL;-			RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);--			return &win->event;-		}---		static HDROP drop;-		-		if (win->event.type == RGFW_dnd_init) {-			if (win->event.droppedFilesCount) {-				u32 i;-				for (i = 0; i < win->event.droppedFilesCount; i++)-					win->event.droppedFiles[i][0] = '\0';-			}--			win->event.droppedFilesCount = 0;-			win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0);-			//win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*));--			u32 i;-			for (i = 0; i < win->event.droppedFilesCount; i++) {-				const UINT length = DragQueryFileW(drop, i, NULL, 0);-				WCHAR* buffer = (WCHAR*) RGFW_CALLOC((size_t) length + 1, sizeof(WCHAR));--				DragQueryFileW(drop, i, buffer, length + 1);-				strncpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer), RGFW_MAX_PATH);-				win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0';-				RGFW_FREE(buffer);-			}--			DragFinish(drop);-			RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);-			-			win->event.type = RGFW_dnd;-			return &win->event;-		}--		win->event.inFocus = (GetForegroundWindow() == win->src.window);--		if (RGFW_checkXInput(win, &win->event))-			return &win->event;--		static BYTE keyboardState[256];--		if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE)) {-			switch (msg.message) {-			case WM_CLOSE:-			case WM_QUIT:-				RGFW_windowQuitCallback(win);-				win->event.type = RGFW_quit;-				break;--			case WM_ACTIVATE:-				win->event.inFocus = (LOWORD(msg.wParam) == WA_INACTIVE);--				if (win->event.inFocus) {-					win->event.type = RGFW_focusIn;-					RGFW_focusCallback(win, 1);-				}-				else {-					win->event.type = RGFW_focusOut;-					RGFW_focusCallback(win, 0);-				}--				break;-			-			case WM_PAINT:-				win->event.type = RGFW_windowRefresh;-				RGFW_windowRefreshCallback(win);-				break;-			-			case WM_MOUSELEAVE:-				win->event.type = RGFW_mouseLeave;-				win->src.winArgs |= RGFW_MOUSE_LEFT;-				RGFW_mouseNotifyCallBack(win, win->event.point, 0);-				break;-			-			case WM_KEYUP: {-				win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam);-								-				RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);--				static char keyName[16];-				-				{-					GetKeyNameTextA((LONG) msg.lParam, keyName, 16);--					if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||-						((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {-						CharLowerBuffA(keyName, 16);-					}-				}--				RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));--				strncpy(win->event.keyName, keyName, 16);--				if (RGFW_isPressed(win, RGFW_ShiftL)) {-					ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),-						keyboardState, (LPWORD) win->event.keyName, 0);-				}--				win->event.type = RGFW_keyReleased;-				RGFW_keyboard[win->event.keyCode].current = 0;-				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0);-				break;-			}-			case WM_KEYDOWN: {-				win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam);--				RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);--				static char keyName[16];-				-				{-					GetKeyNameTextA((LONG) msg.lParam, keyName, 16);--					if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||-						((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {-						CharLowerBuffA(keyName, 16);-					}-				}-								-				RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));--				strncpy(win->event.keyName, keyName, 16);--				if (RGFW_isPressed(win, RGFW_ShiftL) & 0x8000) {-					ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),-						keyboardState, (LPWORD) win->event.keyName, 0);-				}--				win->event.type = RGFW_keyPressed;-				RGFW_keyboard[win->event.keyCode].current = 1;-				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);-				break;-			}--			case WM_MOUSEMOVE:-				win->event.type = RGFW_mousePosChanged;--				win->event.point.x = GET_X_LPARAM(msg.lParam);-				win->event.point.y = GET_Y_LPARAM(msg.lParam);--				RGFW_mousePosCallback(win, win->event.point);--				if (win->src.winArgs & RGFW_MOUSE_LEFT) {-					win->src.winArgs ^= RGFW_MOUSE_LEFT;-					win->event.type = RGFW_mouseEnter;-					RGFW_mouseNotifyCallBack(win, win->event.point, 1);-				}--				break;--			case WM_LBUTTONDOWN:-				win->event.button = RGFW_mouseLeft;-				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 1;-				win->event.type = RGFW_mouseButtonPressed;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);-				break;-			case WM_RBUTTONDOWN:-				win->event.button = RGFW_mouseRight;-				win->event.type = RGFW_mouseButtonPressed;-				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 1;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);-				break;-			case WM_MBUTTONDOWN:-				win->event.button = RGFW_mouseMiddle;-				win->event.type = RGFW_mouseButtonPressed;-				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 1;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);-				break;--			case WM_MOUSEWHEEL:-				if (msg.wParam > 0)-					win->event.button = RGFW_mouseScrollUp;-				else-					win->event.button = RGFW_mouseScrollDown;--				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 1;--				win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA;--				win->event.type = RGFW_mouseButtonPressed;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);-				break;--			case WM_LBUTTONUP:-			-				win->event.button = RGFW_mouseLeft;-				win->event.type = RGFW_mouseButtonReleased;--				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 0;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);-				break;-			case WM_RBUTTONUP:-				win->event.button = RGFW_mouseRight;-				win->event.type = RGFW_mouseButtonReleased;--				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 0;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);-				break;-			case WM_MBUTTONUP:-				win->event.button = RGFW_mouseMiddle;-				win->event.type = RGFW_mouseButtonReleased;--				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 0;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);-				break;--				/*-					much of this event is source from glfw-				*/-			case WM_DROPFILES: {				-				win->event.type = RGFW_dnd_init;--				drop = (HDROP) msg.wParam;-				POINT pt;--				/* Move the mouse to the position of the drop */-				DragQueryPoint(drop, &pt);--				win->event.point.x = pt.x;-				win->event.point.y = pt.y;--				RGFW_dndInitCallback(win, win->event.point);-			}-				break;-			case WM_GETMINMAXINFO:-			{-				if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0)-					break;--				MINMAXINFO* mmi = (MINMAXINFO*) msg.lParam;-				mmi->ptMinTrackSize.x = win->src.minSize.w;-				mmi->ptMinTrackSize.y = win->src.minSize.h;-				mmi->ptMaxTrackSize.x = win->src.maxSize.w;-				mmi->ptMaxTrackSize.y = win->src.maxSize.h;-				return 0;-			}-			default:-				win->event.type = 0;-				break;-			}--			TranslateMessage(&msg);-			DispatchMessageA(&msg);-		}--		else-			win->event.type = 0;--		if (!IsWindow(win->src.window)) {-			win->event.type = RGFW_quit;-			RGFW_windowQuitCallback(win);-		}--		if (win->event.type)-			return &win->event;-		else-			return NULL;-	}--	u8 RGFW_window_isFullscreen(RGFW_window* win) {-		assert(win != NULL);--		WINDOWPLACEMENT placement = { 0 };-		GetWindowPlacement(win->src.window, &placement);-		return placement.showCmd == SW_SHOWMAXIMIZED;-	}--	u8 RGFW_window_isHidden(RGFW_window* win) {-		assert(win != NULL);--		return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win);-	}--	u8 RGFW_window_isMinimized(RGFW_window* win) {-		assert(win != NULL);--		WINDOWPLACEMENT placement = { 0 };-		GetWindowPlacement(win->src.window, &placement);-		return placement.showCmd == SW_SHOWMINIMIZED;-	}--	u8 RGFW_window_isMaximized(RGFW_window* win) {-		assert(win != NULL);--		WINDOWPLACEMENT placement = { 0 };-		GetWindowPlacement(win->src.window, &placement);-		return placement.showCmd == SW_SHOWMAXIMIZED;-	}--	typedef struct { int iIndex; HMONITOR hMonitor; } RGFW_mInfo;-	BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {-		RGFW_UNUSED(hdcMonitor)-		RGFW_UNUSED(lprcMonitor)--		RGFW_mInfo* info = (RGFW_mInfo*) dwData;-		if (info->hMonitor == hMonitor)-			return FALSE;--		info->iIndex++;-		return TRUE;-	}-	-	#ifndef RGFW_NO_MONITOR-	RGFW_monitor win32CreateMonitor(HMONITOR src) {-		RGFW_monitor monitor;-		MONITORINFO monitorInfo;--		monitorInfo.cbSize = sizeof(MONITORINFO);-		GetMonitorInfoA(src, &monitorInfo);--		RGFW_mInfo info;-		info.iIndex = 0;-		info.hMonitor = src;--		/* get the monitor's index */-		if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM) &info)) {-			DISPLAY_DEVICEA dd;-			dd.cb = sizeof(dd);--			/* loop through the devices until you find a device with the monitor's index */-			size_t deviceIndex;-			for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) {-				char* deviceName = dd.DeviceName;-				if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) {-					strncpy(monitor.name, dd.DeviceString, 128); /* copy the monitor's name */-					break;-				}-			}-		}--		monitor.rect.x = monitorInfo.rcWork.left;-		monitor.rect.y = monitorInfo.rcWork.top;-		monitor.rect.w = monitorInfo.rcWork.right - monitorInfo.rcWork.left;-		monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;--#ifndef RGFW_NO_DPI-		if (GetDpiForMonitor != NULL) {-			u32 x, y;-			GetDpiForMonitor(src, MDT_ANGULAR_DPI, &x, &y);-			monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI;-			monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI;-		}-#endif--		HDC hdc = GetDC(NULL);-		/* get pixels per inch */-		i32 ppiX = GetDeviceCaps(hdc, LOGPIXELSX);-		i32 ppiY = GetDeviceCaps(hdc, LOGPIXELSY);-		ReleaseDC(NULL, hdc);--		/* Calculate physical height in inches */-		monitor.physW = GetSystemMetrics(SM_CYSCREEN) / (float) ppiX;-		monitor.physH = GetSystemMetrics(SM_CXSCREEN) / (float) ppiY;--		return monitor;-	}-	#endif /* RGFW_NO_MONITOR */-	--	#ifndef RGFW_NO_MONITOR-	RGFW_monitor RGFW_monitors[6];-	BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {-		RGFW_UNUSED(hdcMonitor)-		RGFW_UNUSED(lprcMonitor)--		RGFW_mInfo* info = (RGFW_mInfo*) dwData;--		if (info->iIndex >= 6)-			return FALSE;--		RGFW_monitors[info->iIndex] = win32CreateMonitor(hMonitor);-		info->iIndex++;--		return TRUE;-	}--	RGFW_monitor RGFW_getPrimaryMonitor(void) {-		return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY));-	}--	RGFW_monitor* RGFW_getMonitors(void) {-		RGFW_mInfo info;-		info.iIndex = 0;-		while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info));--		return RGFW_monitors;-	}--	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {-		HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY);-		return win32CreateMonitor(src);-	}-	#endif--	HICON RGFW_loadHandleImage(RGFW_window* win, u8* src, RGFW_area a, BOOL icon) {-		assert(win != NULL);--		u32 i;-		HDC dc;-		HICON handle;-		HBITMAP color, mask;-		BITMAPV5HEADER bi;-		ICONINFO ii;-		u8* target = NULL;-		u8* source = src;--		ZeroMemory(&bi, sizeof(bi));-		bi.bV5Size = sizeof(bi);-		bi.bV5Width = a.w;-		bi.bV5Height = -((LONG) a.h);-		bi.bV5Planes = 1;-		bi.bV5BitCount = 32;-		bi.bV5Compression = BI_BITFIELDS;-		bi.bV5RedMask = 0x00ff0000;-		bi.bV5GreenMask = 0x0000ff00;-		bi.bV5BlueMask = 0x000000ff;-		bi.bV5AlphaMask = 0xff000000;--		dc = GetDC(NULL);-		color = CreateDIBSection(dc,-			(BITMAPINFO*) &bi,-			DIB_RGB_COLORS,-			(void**) &target,-			NULL,-			(DWORD) 0);-		ReleaseDC(NULL, dc);--		mask = CreateBitmap(a.w, a.h, 1, 1, NULL);--		for (i = 0; i < a.w * a.h; i++) {-			target[0] = source[2];-			target[1] = source[1];-			target[2] = source[0];-			target[3] = source[3];-			target += 4;-			source += 4;-		}--		ZeroMemory(&ii, sizeof(ii));-		ii.fIcon = icon;-		ii.xHotspot = 0;-		ii.yHotspot = 0;-		ii.hbmMask = mask;-		ii.hbmColor = color;--		handle = CreateIconIndirect(&ii);--		DeleteObject(color);-		DeleteObject(mask);--		return handle;-	}--	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {-		assert(win != NULL);-		RGFW_UNUSED(channels)--		HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(win, image, a, FALSE);-		SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) cursor);-		SetCursor(cursor);-		DestroyCursor(cursor);-	}--	void RGFW_window_setMouseDefault(RGFW_window* win) {-		RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);-	}--	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {-		assert(win != NULL);--		if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32)))-			return;--		char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]);--		SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon));-		SetCursor(LoadCursorA(NULL, icon));-	}--	void RGFW_window_hide(RGFW_window* win) {-		ShowWindow(win->src.window, SW_HIDE);-	}--	void RGFW_window_show(RGFW_window* win) {-		ShowWindow(win->src.window, SW_RESTORE);-	}--	void RGFW_window_close(RGFW_window* win) {-		assert(win != NULL);--#ifdef RGFW_EGL-		RGFW_closeEGL(win);-#endif--		if (win == RGFW_root) {-#ifdef RGFW_DIRECTX-			RGFW_dxInfo.pDeviceContext->lpVtbl->Release(RGFW_dxInfo.pDeviceContext);-			RGFW_dxInfo.pDevice->lpVtbl->Release(RGFW_dxInfo.pDevice);-			RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);-			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);-#endif-		-			if (RGFW_XInput_dll != NULL) {-				FreeLibrary(RGFW_XInput_dll);-				RGFW_XInput_dll = NULL;-			}--			#ifndef RGFW_NO_DPI-			if (RGFW_Shcore_dll != NULL) {-				FreeLibrary(RGFW_Shcore_dll);-				RGFW_Shcore_dll = NULL;-			}-			#endif--			if (wglinstance != NULL) {-				FreeLibrary(wglinstance);-				wglinstance = NULL;-			}--			RGFW_root = NULL;-		}--#ifdef RGFW_DIRECTX-		win->src.swapchain->lpVtbl->Release(win->src.swapchain);-		win->src.renderTargetView->lpVtbl->Release(win->src.renderTargetView);-		win->src.pDepthStencilView->lpVtbl->Release(win->src.pDepthStencilView);-#endif--#ifdef RGFW_BUFFER-		DeleteDC(win->src.hdcMem);-		DeleteObject(win->src.bitmap);-#endif--#ifdef RGFW_OPENGL-		wglDeleteContext((HGLRC) win->src.rSurf); /* delete opengl context */-#endif-		DeleteDC(win->src.hdc); /* delete device context */-		DestroyWindow(win->src.window); /* delete window */--#if defined(RGFW_OSMESA)-		if (win->buffer != NULL)-			RGFW_FREE(win->buffer);-#endif--#ifdef RGFW_ALLOC_DROPFILES-		{-			u32 i;-			for (i = 0; i < RGFW_MAX_DROPS; i++)-				RGFW_FREE(win->event.droppedFiles[i]);---			RGFW_FREE(win->event.droppedFiles);-		}-#endif--		RGFW_FREE(win);-	}--	void RGFW_window_move(RGFW_window* win, RGFW_vector v) {-		assert(win != NULL);--		win->r.x = v.x;-		win->r.y = v.y;-		SetWindowPos(win->src.window, HWND_TOP, win->r.x, win->r.y, 0, 0, SWP_NOSIZE);-	}--	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {-		assert(win != NULL);--		win->r.w = a.w;-		win->r.h = a.h;-		SetWindowPos(win->src.window, HWND_TOP, 0, 0, win->r.w, win->r.h + win->src.hOffset, SWP_NOMOVE);-	}---	void RGFW_window_setName(RGFW_window* win, char* name) {-		assert(win != NULL);--		SetWindowTextA(win->src.window, name);-	}--	/* sourced from GLFW */-	#ifndef RGFW_NO_PASSTHROUGH-	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {-		assert(win != NULL);-		-		COLORREF key = 0;-		BYTE alpha = 0;-		DWORD flags = 0;-		DWORD exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE);-		-		if (exStyle & WS_EX_LAYERED)-			GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags);--		if (passthrough)-			exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);-		else-		{-			exStyle &= ~WS_EX_TRANSPARENT;-			// NOTE: Window opacity also needs the layered window style so do not-			//       remove it if the window is alpha blended-			if (exStyle & WS_EX_LAYERED)-			{-				if (!(flags & LWA_ALPHA))-					exStyle &= ~WS_EX_LAYERED;-			}-		}--		SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle);--		if (passthrough) {-			SetLayeredWindowAttributes(win->src.window, key, alpha, flags);-		}-	}-	#endif--	/* much of this function is sourced from GLFW */-	void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) {-		assert(win != NULL);-		#ifndef RGFW_WIN95-		RGFW_UNUSED(channels)--		HICON handle = RGFW_loadHandleImage(win, src, a, TRUE);--		SetClassLongPtrA(win->src.window, GCLP_HICON, (LPARAM) handle);--		DestroyIcon(handle);-		#else-		RGFW_UNUSED(src)-		RGFW_UNUSED(a)-		RGFW_UNUSED(channels)-		#endif-	}--	char* RGFW_readClipboard(size_t* size) {-		/* Open the clipboard */-		if (OpenClipboard(NULL) == 0)-			return (char*) "";--		/* Get the clipboard data as a Unicode string */-		HANDLE hData = GetClipboardData(CF_UNICODETEXT);-		if (hData == NULL) {-			CloseClipboard();-			return (char*) "";-		}--		wchar_t* wstr = (wchar_t*) GlobalLock(hData);--		char* text;--		{-			setlocale(LC_ALL, "en_US.UTF-8");--			size_t textLen = wcstombs(NULL, wstr, 0);-			if (textLen == 0)-				return (char*) "";--			text = (char*) RGFW_MALLOC((textLen * sizeof(char)) + 1);--			wcstombs(text, wstr, (textLen) +1);--			if (size != NULL)-				*size = textLen + 1;--			text[textLen] = '\0';-		}--		/* Release the clipboard data */-		GlobalUnlock(hData);-		CloseClipboard();--		return text;-	}--	void RGFW_writeClipboard(const char* text, u32 textLen) {-		HANDLE object;-		WCHAR* buffer;--		object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR));-		if (!object)-			return;--		buffer = (WCHAR*) GlobalLock(object);-		if (!buffer) {-			GlobalFree(object);-			return;-		}--		MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, textLen);-		GlobalUnlock(object);--		if (!OpenClipboard(RGFW_root->src.window)) {-			GlobalFree(object);-			return;-		}--		EmptyClipboard();-		SetClipboardData(CF_UNICODETEXT, object);-		CloseClipboard();-	}--	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {-		assert(win != NULL);--		RGFW_UNUSED(jsNumber)--		return RGFW_registerJoystickF(win, (char*) "");-	}--	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {-		assert(win != NULL);-		RGFW_UNUSED(file)--		return win->src.joystickCount - 1;-	}--	void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector p) {-		assert(win != NULL);--		SetCursorPos(p.x, p.y);-	}--	#ifdef RGFW_OPENGL-	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {-		assert(win != NULL);-		wglMakeCurrent(win->src.hdc, (HGLRC) win->src.rSurf);-	}-	#endif--	#ifndef RGFW_EGL-	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {-		assert(win != NULL);-		-		#if defined(RGFW_OPENGL)-		typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval);-		static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;-		static void* loadSwapFunc = (void*) 1;--		if (loadSwapFunc == NULL) {-			fprintf(stderr, "wglSwapIntervalEXT not supported\n");-			win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;-			return;-		}--		if (wglSwapIntervalEXT == NULL) {-			loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT");-			wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc;-		}--		if (wglSwapIntervalEXT(swapInterval) == FALSE)-			fprintf(stderr, "Failed to set swap interval\n");-		#endif--		win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;--	}-	#endif--	void RGFW_window_swapBuffers(RGFW_window* win) {-		assert(win != NULL);--		RGFW_window_makeCurrent(win);--		/* clear the window*/--		if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) {-#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)-			#ifdef RGFW_OSMESA-			RGFW_OSMesa_reorganize();-			#endif--			HGDIOBJ oldbmp = SelectObject(win->src.hdcMem, win->src.bitmap);-			BitBlt(win->src.hdc, 0, 0, win->r.w, win->r.h, win->src.hdcMem, 0, 0, SRCCOPY);-			SelectObject(win->src.hdcMem, oldbmp);-#endif-		}--		if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) {-			#ifdef RGFW_EGL-					eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);-			#elif defined(RGFW_OPENGL)-					SwapBuffers(win->src.hdc);-			#endif--			#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)-					win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0);-			#endif-		}--		RGFW_window_checkFPS(win);-	}--	char* createUTF8FromWideStringWin32(const WCHAR* source) {-		char* target;-		i32 size;--		size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);-		if (!size) {-			return NULL;-		}--		target = (char*) RGFW_CALLOC(size, 1);--		if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) {-			RGFW_FREE(target);-			return NULL;-		}--		return target;-	}--	u64 RGFW_getTimeNS(void) {-		LARGE_INTEGER frequency;-		QueryPerformanceFrequency(&frequency);--		LARGE_INTEGER counter;-		QueryPerformanceCounter(&counter);--		return (u64) (counter.QuadPart * 1e9 / frequency.QuadPart);-	}--	u64 RGFW_getTime(void) {-		LARGE_INTEGER frequency;-		QueryPerformanceFrequency(&frequency);--		LARGE_INTEGER counter;-		QueryPerformanceCounter(&counter);-		return (u64) (counter.QuadPart / (double) frequency.QuadPart);-	}-	-	void RGFW_sleep(u64 ms) {-		Sleep(ms);-	}--#ifndef RGFW_NO_THREADS-	RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { return CreateThread(NULL, 0, ptr, args, 0, NULL); }-	void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); }-	void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); }-	void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); }-#endif-#endif /* RGFW_WINDOWS */--/*-	End of Windows defines-*/----/* --	Start of MacOS defines---*/--#if defined(RGFW_MACOS)-	/*-		based on silicon.h-		start of cocoa wrapper-	*/--#include <CoreVideo/CVDisplayLink.h>-#include <ApplicationServices/ApplicationServices.h>-#include <objc/runtime.h>-#include <objc/message.h>-#include <mach/mach_time.h>--	typedef CGRect NSRect;-	typedef CGPoint NSPoint;-	typedef CGSize NSSize;--	typedef void NSBitmapImageRep;-	typedef void NSCursor;-	typedef void NSDraggingInfo;-	typedef void NSWindow;-	typedef void NSApplication;-	typedef void NSScreen;-	typedef void NSEvent;-	typedef void NSString;-	typedef void NSOpenGLContext;-	typedef void NSPasteboard;-	typedef void NSColor;-	typedef void NSArray;-	typedef void NSImageRep;-	typedef void NSImage;-	typedef void NSOpenGLView;---	typedef const char* NSPasteboardType;-	typedef unsigned long NSUInteger;-	typedef long NSInteger;-	typedef NSInteger NSModalResponse;--#ifdef __arm64__-	/* ARM just uses objc_msgSend */-#define abi_objc_msgSend_stret objc_msgSend-#define abi_objc_msgSend_fpret objc_msgSend-#else /* __i386__ */ -	/* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */-#define abi_objc_msgSend_stret objc_msgSend_stret-#define abi_objc_msgSend_fpret objc_msgSend_fpret-#endif--#define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc"))-#define objc_msgSend_bool			((BOOL (*)(id, SEL))objc_msgSend)-#define objc_msgSend_void			((void (*)(id, SEL))objc_msgSend)-#define objc_msgSend_void_id		((void (*)(id, SEL, id))objc_msgSend)-#define objc_msgSend_uint			((NSUInteger (*)(id, SEL))objc_msgSend)-#define objc_msgSend_void_bool		((void (*)(id, SEL, BOOL))objc_msgSend)-#define objc_msgSend_void_SEL		((void (*)(id, SEL, SEL))objc_msgSend)-#define objc_msgSend_id				((id (*)(id, SEL))objc_msgSend)--	void NSRelease(id obj) {-		objc_msgSend_void(obj, sel_registerName("release"));-	}--	#define release NSRelease--	NSString* NSString_stringWithUTF8String(const char* str) {	-		return ((id(*)(id, SEL, const char*))objc_msgSend)-			((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str);-	}--	const char* NSString_to_char(NSString* str) {-		return ((const char* (*)(id, SEL)) objc_msgSend) (str, sel_registerName("UTF8String"));-	}--	void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) {-		Class selected_class;--		if (strcmp(class_name, "NSView") == 0) {-			selected_class = objc_getClass("ViewClass");-		} else if (strcmp(class_name, "NSWindow") == 0) {-			selected_class = objc_getClass("WindowClass");-		} else {-			selected_class = objc_getClass(class_name);-		}--		class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0);-	}--	/* Header for the array. */-	typedef struct siArrayHeader {-		size_t count;-		/* TODO(EimaMei): Add a `type_width` later on. */-	} siArrayHeader;--	/* Gets the header of the siArray. */-#define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1)--	void* si_array_init_reserve(size_t sizeof_element, size_t count) {-		siArrayHeader* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count));-		void* array = ptr + sizeof(siArrayHeader);--		siArrayHeader* header = SI_ARRAY_HEADER(array);-		header->count = count;--		return array;-	}--#define si_array_len(array) (SI_ARRAY_HEADER(array)->count)-#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", function)-	/* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/-#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", function)-	-	unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) {-		return ((unsigned char* (*)(id, SEL))objc_msgSend)-			(imageRep, sel_registerName("bitmapData"));-	}--#define NS_ENUM(type, name) type name; enum--	typedef NS_ENUM(NSUInteger, NSBitmapFormat) {-		NSBitmapFormatAlphaFirst = 1 << 0,       // 0 means is alpha last (RGBA, CMYKA, etc.)-			NSBitmapFormatAlphaNonpremultiplied = 1 << 1,       // 0 means is premultiplied-			NSBitmapFormatFloatingPointSamples = 1 << 2,  // 0 is integer--			NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8),-			NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9),-			NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10),-			NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11)-	};--	NSBitmapImageRep* NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) {-		void* func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:");--		return (NSBitmapImageRep*) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend)-			(NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits);-	}--	NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) {-		void* nsclass = objc_getClass("NSColor");-		void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:");-		return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)-			(nsclass, func, red, green, blue, alpha);-	}--	NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) {-		void* func = sel_registerName("initWithImage:hotSpot:");-		void* nsclass = objc_getClass("NSCursor");--		return (NSCursor*) ((id(*)(id, SEL, id, NSPoint))objc_msgSend)-			(NSAlloc(nsclass), func, newImage, aPoint);-	}--	void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep) {-		void* func = sel_registerName("addRepresentation:");-		objc_msgSend_void_id(image, func, imageRep);-	}--	NSImage* NSImage_initWithSize(NSSize size) {-		void* func = sel_registerName("initWithSize:");-		return ((id(*)(id, SEL, NSSize))objc_msgSend)-			(NSAlloc((id)objc_getClass("NSImage")), func, size);-	}-#define NS_OPENGL_ENUM_DEPRECATED(minVers, maxVers) API_AVAILABLE(macos(minVers))-	typedef NS_ENUM(NSInteger, NSOpenGLContextParameter) {-		NSOpenGLContextParameterSwapInterval           NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param.  0 -> Don't sync, 1 -> Sync to vertical retrace     */-			NSOpenGLContextParameterSurfaceOrder           NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param.  1 -> Above Window (default), -1 -> Below Window    */-			NSOpenGLContextParameterSurfaceOpacity         NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param.  1-> Surface is opaque (default), 0 -> non-opaque   */-			NSOpenGLContextParameterSurfaceBackingSize     NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params.  Width/height of surface backing size              */-			NSOpenGLContextParameterReclaimResources       NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params.                                                    */-			NSOpenGLContextParameterCurrentRendererID      NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param.   Retrieves the current renderer ID                 */-			NSOpenGLContextParameterGPUVertexProcessing    NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param.   Currently processing vertices with GPU (get)      */-			NSOpenGLContextParameterGPUFragmentProcessing  NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param.   Currently processing fragments with GPU (get)     */-			NSOpenGLContextParameterHasDrawable            NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param.   Boolean returned if drawable is attached          */-			NSOpenGLContextParameterMPSwapsInFlight        NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param.   Max number of swaps queued by the MP GL engine    */--			NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params.  Set or get the swap rectangle {x, y, w, h} */-			NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */-			NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */-			NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */-			NSOpenGLContextParameterSurfaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param.   Surface volatile state */-	};---	void NSOpenGLContext_setValues(NSOpenGLContext* context, const int* vals, NSOpenGLContextParameter param) {-		void* func = sel_registerName("setValues:forParameter:");-		((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend)-			(context, func, vals, param);-	}--	void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) {-		void* func = sel_registerName("initWithAttributes:");-		return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend)-			(NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs);-	}--	NSOpenGLView* NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) {-		void* func = sel_registerName("initWithFrame:pixelFormat:");-		return (NSOpenGLView*) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend)-			(NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format);-	}--	void NSCursor_performSelector(NSCursor* cursor, void* selector) {-		void* func = sel_registerName("performSelector:");-		objc_msgSend_void_SEL(cursor, func, selector);-	}--	NSPasteboard* NSPasteboard_generalPasteboard(void) {-		return (NSPasteboard*) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard"));-	}--	NSString** cstrToNSStringArray(char** strs, size_t len) {-		static NSString* nstrs[6];-		size_t i;-		for (i = 0; i < len; i++)-			nstrs[i] = NSString_stringWithUTF8String(strs[i]);--		return nstrs;-	}--	const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType) {-		void* func = sel_registerName("stringForType:");-		return (const char*) NSString_to_char(((id(*)(id, SEL, const char*))objc_msgSend)(pasteboard, func, NSString_stringWithUTF8String(dataType)));-	}--	NSArray* c_array_to_NSArray(void* array, size_t len) {-		SEL func = sel_registerName("initWithObjects:count:");-		void* nsclass = objc_getClass("NSArray");-		return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend)-					(NSAlloc(nsclass), func, array, len);-	}- -	void NSregisterForDraggedTypes(void* view, NSPasteboardType* newTypes, size_t len) {-		NSString** ntypes = cstrToNSStringArray((char**)newTypes, len);--		NSArray* array = c_array_to_NSArray(ntypes, len);-		objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array);-		NSRelease(array);-	}--	NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) {-		NSString** ntypes = cstrToNSStringArray((char**)newTypes, len);--		void* func = sel_registerName("declareTypes:owner:");--		NSArray* array = c_array_to_NSArray(ntypes, len);--		NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend)-			(pasteboard, func, array, owner);-		NSRelease(array);--		return output;-	}--	bool NSPasteBoard_setString(NSPasteboard* pasteboard, const char* stringToWrite, NSPasteboardType dataType) {-		void* func = sel_registerName("setString:forType:");-		return ((bool (*)(id, SEL, id, NSPasteboardType))objc_msgSend)-			(pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType));-	}--	void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); }--	typedef enum NSApplicationActivationPolicy {-		NSApplicationActivationPolicyRegular,-		NSApplicationActivationPolicyAccessory,-		NSApplicationActivationPolicyProhibited-	} NSApplicationActivationPolicy;--	typedef NS_ENUM(u32, NSBackingStoreType) {-		NSBackingStoreRetained = 0,-			NSBackingStoreNonretained = 1,-			NSBackingStoreBuffered = 2-	};--	typedef NS_ENUM(u32, NSWindowStyleMask) {-		NSWindowStyleMaskBorderless = 0,-			NSWindowStyleMaskTitled = 1 << 0,-			NSWindowStyleMaskClosable = 1 << 1,-			NSWindowStyleMaskMiniaturizable = 1 << 2,-			NSWindowStyleMaskResizable = 1 << 3,-			NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */-			NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12,-			NSWindowStyleMaskFullScreen = 1 << 14,-			NSWindowStyleMaskFullSizeContentView = 1 << 15,-			NSWindowStyleMaskUtilityWindow = 1 << 4,-			NSWindowStyleMaskDocModalWindow = 1 << 6,-			NSWindowStyleMaskNonactivatingPanel = 1 << 7,-			NSWindowStyleMaskHUDWindow = 1 << 13-	};--	typedef const char* NSPasteboardType;-	NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType----	typedef NS_ENUM(i32, NSDragOperation) {-		NSDragOperationNone = 0,-			NSDragOperationCopy = 1,-			NSDragOperationLink = 2,-			NSDragOperationGeneric = 4,-			NSDragOperationPrivate = 8,-			NSDragOperationMove = 16,-			NSDragOperationDelete = 32,-			NSDragOperationEvery = ULONG_MAX,--			//NSDragOperationAll_Obsolete	API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery-			//NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery-	};--	void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) {-		void* func = sel_registerName("objectAtIndex:");-		return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index);-	}--	const char** NSPasteboard_readObjectsForClasses(NSPasteboard* pasteboard, Class* classArray, size_t len, void* options) {-		void* func = sel_registerName("readObjectsForClasses:options:");--		NSArray* array = c_array_to_NSArray(classArray, len);--		NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend)-			(pasteboard, func, array, options);--		NSRelease(array);-		NSUInteger count = ((NSUInteger(*)(id, SEL))objc_msgSend)(output, sel_registerName("count"));--		const char** res = si_array_init_reserve(sizeof(const char*), count);--		void* path_func = sel_registerName("path");--		for (NSUInteger i = 0; i < count; i++) {-			void* url = NSArray_objectAtIndex(output, i);-			NSString* url_str = ((id(*)(id, SEL))objc_msgSend)(url, path_func);-			res[i] = NSString_to_char(url_str);-		}--		return res;-	}--	void* NSWindow_contentView(NSWindow* window) {-		void* func = sel_registerName("contentView");-		return objc_msgSend_id(window, func);-	}--	/*-		End of cocoa wrapper-	*/--	char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"};--	void* RGFWnsglFramework = NULL;--#ifdef RGFW_OPENGL-	void* RGFW_getProcAddress(const char* procname) {-		if (RGFWnsglFramework == NULL)-			RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));--		CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII);--		void* symbol = CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName);--		CFRelease(symbolName);--		return symbol;-	}-#endif--	CVReturn displayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) { -		RGFW_UNUSED(displayLink) RGFW_UNUSED(inNow) RGFW_UNUSED(inOutputTime) RGFW_UNUSED(flagsIn) RGFW_UNUSED(flagsOut) RGFW_UNUSED(displayLinkContext)-		return kCVReturnSuccess; -	}--	id NSWindow_delegate(RGFW_window* win) {-		return (id) objc_msgSend_id(win->src.window, sel_registerName("delegate"));-	}--	u32 RGFW_OnClose(void* self) {-		RGFW_window* win = NULL;-		object_getInstanceVariable(self, "RGFW_window", (void*)&win);-		if (win == NULL)-			return true;--		win->event.type = RGFW_quit;-		RGFW_windowQuitCallback(win);--		return true;-	}--	/* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */-	bool acceptsFirstResponder(void) { return true; }-	bool performKeyEquivalent(NSEvent* event) { RGFW_UNUSED(event); return true; }--	NSDragOperation draggingEntered(id self, SEL sel, id sender) { -		RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);  --		printf("hi\n");-		return NSDragOperationCopy; -	}-	NSDragOperation draggingUpdated(id self, SEL sel, id sender) { -		RGFW_UNUSED(sel); --		RGFW_window* win = NULL;-		object_getInstanceVariable(self, "RGFW_window", (void*)&win);-		if (win == NULL)-			return true;-		-		if (!(win->src.winArgs & RGFW_ALLOW_DND)) {-			return false;-		}--		win->event.type = RGFW_dnd_init;-		win->src.dndPassed = 0;--		NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));--		win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));-		RGFW_dndInitCallback(win, win->event.point);--		return NSDragOperationCopy; -	}-	bool prepareForDragOperation(id self) {-		RGFW_window* win = NULL;-		object_getInstanceVariable(self, "RGFW_window", (void*)&win);-		if (win == NULL)-			return true;-		-		if (!(win->src.winArgs & RGFW_ALLOW_DND)) {-			return false;-		}--		return true;-	}--	void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);  return; }--	/* NOTE(EimaMei): Usually, you never need 'id self, SEL cmd' for C -> Obj-C methods. This isn't the case. */-	bool performDragOperation(id self, SEL sel, id sender) {-		RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); --		RGFW_window* win = NULL;-		object_getInstanceVariable(self, "RGFW_window", (void*)&win);-		if (win == NULL)-			return true;--		//NSWindow* window = objc_msgSend_id(sender, sel_registerName("draggingDestinationWindow"));-		u32 i;-		bool found = 0;--		if (!found)-			i = 0;--		Class array[] = { objc_getClass("NSURL"), NULL };-		NSPasteboard* pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard"));-		-		char** droppedFiles = (char**) NSPasteboard_readObjectsForClasses(pasteBoard, array, 1, NULL);--		win->event.droppedFilesCount = si_array_len(droppedFiles);--		u32 y;--		for (y = 0; y < win->event.droppedFilesCount; y++) {-			strncpy(win->event.droppedFiles[y], droppedFiles[y], RGFW_MAX_PATH);--			win->event.droppedFiles[y][RGFW_MAX_PATH - 1] = '\0';-		}--		win->event.type = RGFW_dnd;-		win->src.dndPassed = 0;--		NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));-		win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));--		RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);-		return true;-	}---	NSApplication* NSApp = NULL;--	static void NSMoveToResourceDir(void) {-		/* sourced from glfw */-		char resourcesPath[255];--		CFBundleRef bundle = CFBundleGetMainBundle();-		if (!bundle)-			return;--		CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);-		CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);--		if (-			CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo ||-			CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0-			) {-			CFRelease(last);-			CFRelease(resourcesURL);-			return;-		}--		CFRelease(last);-		CFRelease(resourcesURL);--		chdir(resourcesPath);-	}---	NSSize RGFW__osxWindowResize(void* self, SEL sel, NSSize frameSize) {-		RGFW_UNUSED(sel); --		RGFW_window* win = NULL;-		object_getInstanceVariable(self, "RGFW_window", (void*)&win);-		if (win == NULL)-			return frameSize;-		-		win->r.w = frameSize.width;-		win->r.h = frameSize.height;-		win->event.type = RGFW_windowResized;-		RGFW_windowResizeCallback(win, win->r);-		return frameSize;-	}--	void RGFW__osxWindowMove(void* self, SEL sel) {-		RGFW_UNUSED(sel); --		RGFW_window* win = NULL;-		object_getInstanceVariable(self, "RGFW_window", (void*)&win);-		if (win == NULL)-			return;-		-		NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(win->src.window, sel_registerName("frame"));-		win->r.x = (i32) frame.origin.x;-		win->r.y = (i32) frame.origin.y;--		win->event.type = RGFW_windowMoved;-		RGFW_windowMoveCallback(win, win->r);-	}--	void RGFW__osxUpdateLayer(void* self, SEL sel) {-		RGFW_UNUSED(sel);--		RGFW_window* win = NULL;-		object_getInstanceVariable(self, "RGFW_window", (void*)&win);-		if (win == NULL)-			return;-		-		win->event.type = RGFW_windowRefresh;-		RGFW_windowRefreshCallback(win);-	}--	RGFWDEF void RGFW_init_buffer(RGFW_window* win);-	void RGFW_init_buffer(RGFW_window* win) {-		#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)-			if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)-				RGFW_bufferSize = RGFW_getScreenSize();-				-			win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);--		#ifdef RGFW_OSMESA-				win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL);-				OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);-		#endif-		#else-		RGFW_UNUSED(win); /* if buffer rendering is not being used */-		#endif-	}--	NSPasteboardType const NSPasteboardTypeURL = "public.url";-	NSPasteboardType const NSPasteboardTypeFileURL  = "public.file-url";--	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {-		static u8 RGFW_loaded = 0;--		/* NOTE(EimaMei): Why does Apple hate good code? Like wtf, who thought of methods being a great idea???-		Imagine a universe, where MacOS had a proper system API (we would probably have like 20% better performance).-		*/-		si_func_to_SEL_with_name("NSObject", "windowShouldClose", RGFW_OnClose);--		/* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */-		si_func_to_SEL("NSWindow", acceptsFirstResponder);-		si_func_to_SEL("NSWindow", performKeyEquivalent);--		if (NSApp == NULL) {-			NSApp = objc_msgSend_id((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));--			((void (*)(id, SEL, NSUInteger))objc_msgSend)-				(NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular);-		}--		RGFW_window* win = RGFW_window_basic_init(rect, args);-		-		RGFW_window_setMouseDefault(win);--		NSRect windowRect;-		windowRect.origin.x = win->r.x;-		windowRect.origin.y = win->r.y;-		windowRect.size.width = win->r.w;-		windowRect.size.height = win->r.h;--		NSBackingStoreType macArgs = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled;--		if (!(args & RGFW_NO_RESIZE))-			macArgs |= NSWindowStyleMaskResizable;-		if (!(args & RGFW_NO_BORDER))-			macArgs |= NSWindowStyleMaskTitled;-		else-			macArgs = NSWindowStyleMaskBorderless;-		{-			void* nsclass = objc_getClass("NSWindow");-			void* func = sel_registerName("initWithContentRect:styleMask:backing:defer:");--			win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend)-				(NSAlloc(nsclass), func, windowRect, macArgs, macArgs, false);-		}--		NSString* str = NSString_stringWithUTF8String(name);-		objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);--#ifdef RGFW_OPENGL-	if ((args & RGFW_NO_INIT_API) == 0) {-		void* attrs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);-		void* format = NSOpenGLPixelFormat_initWithAttributes(attrs);--		if (format == NULL) {-			printf("Failed to load pixel format ");--			void* attrs = RGFW_initAttribs(1);-			format = NSOpenGLPixelFormat_initWithAttributes(attrs);-			if (format == NULL)-				printf("and loading software rendering OpenGL failed\n");-			else-				printf("Switching to software rendering\n");-		}--		win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format);-		objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL"));-		win->src.rSurf = objc_msgSend_id(win->src.view, sel_registerName("openGLContext"));-	} else-#endif-	{-		NSRect contentRect = (NSRect){{0, 0}, {win->r.w, win->r.h}};-		win->src.view = ((id(*)(id, SEL, NSRect))objc_msgSend)-			(NSAlloc((id)objc_getClass("NSView")), sel_registerName("initWithFrame:"),-				contentRect);-	}--		void* contentView = NSWindow_contentView(win->src.window);-		objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true);--		objc_msgSend_void_id(win->src.window, sel_registerName("setContentView:"), win->src.view);--#ifdef RGFW_OPENGL-		if ((args & RGFW_NO_INIT_API) == 0)-			objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext"));-#endif-		if (args & RGFW_TRANSPARENT_WINDOW) {-#ifdef RGFW_OPENGL-		if ((args & RGFW_NO_INIT_API) == 0) {-			i32 opacity = 0;-			#define NSOpenGLCPSurfaceOpacity 236-			NSOpenGLContext_setValues(win->src.rSurf, &opacity, NSOpenGLCPSurfaceOpacity);-		}-#endif--			objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false);--			objc_msgSend_void_id(win->src.window, sel_registerName("setBackgroundColor:"),-				NSColor_colorWithSRGB(0, 0, 0, 0));-		}--		win->src.display = CGMainDisplayID();-		CVDisplayLinkCreateWithCGDisplay(win->src.display, (CVDisplayLinkRef*)&win->src.displayLink);-		CVDisplayLinkSetOutputCallback(win->src.displayLink, displayCallback, win);-		CVDisplayLinkStart(win->src.displayLink);--		RGFW_init_buffer(win);--		#ifndef RGFW_NO_MONITOR-		if (args & RGFW_SCALE_TO_MONITOR)-			RGFW_window_scaleToMonitor(win);-		#endif--		if (args & RGFW_HIDE_MOUSE)-			RGFW_window_showMouse(win, 0);--		if (args & RGFW_COCOA_MOVE_TO_RESOURCE_DIR)-			NSMoveToResourceDir();--		Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0);--		class_addIvar(-			delegateClass, "RGFW_window",-			sizeof(RGFW_window*), rint(log2(sizeof(RGFW_window*))),-			"L"-		);--		class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}");-		class_addMethod(delegateClass, sel_registerName("updateLayer:"), (IMP) RGFW__osxUpdateLayer, "");-		class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, "");-		class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, "");-		class_addMethod(delegateClass, sel_registerName("draggingEntered:"), (IMP)draggingEntered, "l@:@");-		class_addMethod(delegateClass, sel_registerName("draggingUpdated:"), (IMP)draggingUpdated, "l@:@");-		class_addMethod(delegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@");-		class_addMethod(delegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@");-		class_addMethod(delegateClass, sel_registerName("prepareForDragOperation:"), (IMP)prepareForDragOperation, "B@:@");-		class_addMethod(delegateClass, sel_registerName("performDragOperation:"), (IMP)performDragOperation, "B@:@");--		id delegate = objc_msgSend_id(NSAlloc(delegateClass), sel_registerName("init"));--		object_setInstanceVariable(delegate, "RGFW_window", win);--		objc_msgSend_void_id(win->src.window, sel_registerName("setDelegate:"), delegate);--		if (args & RGFW_ALLOW_DND) {-			win->src.winArgs |= RGFW_ALLOW_DND;--			NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString};-			NSregisterForDraggedTypes(win->src.window, types, 3);-		}--		// Show the window-		((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);-		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);--		if (!RGFW_loaded) {-			objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow"));--			RGFW_loaded = 1;-		}--		objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow"));--		objc_msgSend_void(NSApp, sel_registerName("finishLaunching"));--		if (RGFW_root == NULL)-			RGFW_root = win;--		NSRetain(win->src.window);-		NSRetain(NSApp);--		return win;-	}--	void RGFW_window_setBorder(RGFW_window* win, u8 border) {-		NSBackingStoreType storeType = NSWindowStyleMaskBorderless;-		if (!border) {-			storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;-		}-		if (!(win->src.winArgs & RGFW_NO_RESIZE)) {-			storeType |= NSWindowStyleMaskResizable;-		}-		-		((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)(win->src.window, sel_registerName("setStyleMask:"), storeType);--		objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border);-	}--	RGFW_area RGFW_getScreenSize(void) {-		static CGDirectDisplayID display = 0;--		if (display == 0)-			display = CGMainDisplayID();--		return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display));-	}--	RGFW_vector RGFW_getGlobalMousePoint(void) {-		assert(RGFW_root != NULL);--		CGEventRef e = CGEventCreate(NULL);-		CGPoint point = CGEventGetLocation(e);-		CFRelease(e);--		return RGFW_VECTOR((u32) point.x, (u32) point.y); /* the point is loaded during event checks */-	}--	RGFW_vector RGFW_window_getMousePoint(RGFW_window* win) {-		NSPoint p =  ((NSPoint(*)(id, SEL)) objc_msgSend)(win->src.window, sel_registerName("mouseLocationOutsideOfEventStream"));--		return RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));-	}--	u32 RGFW_keysPressed[10]; /*10 keys at a time*/-	typedef NS_ENUM(u32, NSEventType) {        /* various types of events */-		NSEventTypeLeftMouseDown = 1,-			NSEventTypeLeftMouseUp = 2,-			NSEventTypeRightMouseDown = 3,-			NSEventTypeRightMouseUp = 4,-			NSEventTypeMouseMoved = 5,-			NSEventTypeLeftMouseDragged = 6,-			NSEventTypeRightMouseDragged = 7,-			NSEventTypeMouseEntered = 8,-			NSEventTypeMouseExited = 9,-			NSEventTypeKeyDown = 10,-			NSEventTypeKeyUp = 11,-			NSEventTypeFlagsChanged = 12,-			NSEventTypeAppKitDefined = 13,-			NSEventTypeSystemDefined = 14,-			NSEventTypeApplicationDefined = 15,-			NSEventTypePeriodic = 16,-			NSEventTypeCursorUpdate = 17,-			NSEventTypeScrollWheel = 22,-			NSEventTypeTabletPoint = 23,-			NSEventTypeTabletProximity = 24,-			NSEventTypeOtherMouseDown = 25,-			NSEventTypeOtherMouseUp = 26,-			NSEventTypeOtherMouseDragged = 27,-			/* The following event types are available on some hardware on 10.5.2 and later */-			NSEventTypeGesture API_AVAILABLE(macos(10.5)) = 29,-			NSEventTypeMagnify API_AVAILABLE(macos(10.5)) = 30,-			NSEventTypeSwipe   API_AVAILABLE(macos(10.5)) = 31,-			NSEventTypeRotate  API_AVAILABLE(macos(10.5)) = 18,-			NSEventTypeBeginGesture API_AVAILABLE(macos(10.5)) = 19,-			NSEventTypeEndGesture API_AVAILABLE(macos(10.5)) = 20,--			NSEventTypeSmartMagnify API_AVAILABLE(macos(10.8)) = 32,-			NSEventTypeQuickLook API_AVAILABLE(macos(10.8)) = 33,--			NSEventTypePressure API_AVAILABLE(macos(10.10.3)) = 34,-			NSEventTypeDirectTouch API_AVAILABLE(macos(10.10)) = 37,--			NSEventTypeChangeMode API_AVAILABLE(macos(10.15)) = 38,-	};--	typedef NS_ENUM(unsigned long long, NSEventMask) { /* masks for the types of events */-		NSEventMaskLeftMouseDown = 1ULL << NSEventTypeLeftMouseDown,-			NSEventMaskLeftMouseUp = 1ULL << NSEventTypeLeftMouseUp,-			NSEventMaskRightMouseDown = 1ULL << NSEventTypeRightMouseDown,-			NSEventMaskRightMouseUp = 1ULL << NSEventTypeRightMouseUp,-			NSEventMaskMouseMoved = 1ULL << NSEventTypeMouseMoved,-			NSEventMaskLeftMouseDragged = 1ULL << NSEventTypeLeftMouseDragged,-			NSEventMaskRightMouseDragged = 1ULL << NSEventTypeRightMouseDragged,-			NSEventMaskMouseEntered = 1ULL << NSEventTypeMouseEntered,-			NSEventMaskMouseExited = 1ULL << NSEventTypeMouseExited,-			NSEventMaskKeyDown = 1ULL << NSEventTypeKeyDown,-			NSEventMaskKeyUp = 1ULL << NSEventTypeKeyUp,-			NSEventMaskFlagsChanged = 1ULL << NSEventTypeFlagsChanged,-			NSEventMaskAppKitDefined = 1ULL << NSEventTypeAppKitDefined,-			NSEventMaskSystemDefined = 1ULL << NSEventTypeSystemDefined,-			NSEventMaskApplicationDefined = 1ULL << NSEventTypeApplicationDefined,-			NSEventMaskPeriodic = 1ULL << NSEventTypePeriodic,-			NSEventMaskCursorUpdate = 1ULL << NSEventTypeCursorUpdate,-			NSEventMaskScrollWheel = 1ULL << NSEventTypeScrollWheel,-			NSEventMaskTabletPoint = 1ULL << NSEventTypeTabletPoint,-			NSEventMaskTabletProximity = 1ULL << NSEventTypeTabletProximity,-			NSEventMaskOtherMouseDown = 1ULL << NSEventTypeOtherMouseDown,-			NSEventMaskOtherMouseUp = 1ULL << NSEventTypeOtherMouseUp,-			NSEventMaskOtherMouseDragged = 1ULL << NSEventTypeOtherMouseDragged,-			/* The following event masks are available on some hardware on 10.5.2 and later */-			NSEventMaskGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeGesture,-			NSEventMaskMagnify API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeMagnify,-			NSEventMaskSwipe API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeSwipe,-			NSEventMaskRotate API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeRotate,-			NSEventMaskBeginGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeBeginGesture,-			NSEventMaskEndGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeEndGesture,--			/* Note: You can only use these event masks on 64 bit. In other words, you cannot setup a local, nor global, event monitor for these event types on 32 bit. Also, you cannot search the event queue for them (nextEventMatchingMask:...) on 32 bit.-			 */-			NSEventMaskSmartMagnify API_AVAILABLE(macos(10.8)) = 1ULL << NSEventTypeSmartMagnify,-			NSEventMaskPressure API_AVAILABLE(macos(10.10.3)) = 1ULL << NSEventTypePressure,-			NSEventMaskDirectTouch API_AVAILABLE(macos(10.12.2)) = 1ULL << NSEventTypeDirectTouch,--			NSEventMaskChangeMode API_AVAILABLE(macos(10.15)) = 1ULL << NSEventTypeChangeMode,--			NSEventMaskAny = ULONG_MAX,--	};--	typedef enum NSEventModifierFlags {-		NSEventModifierFlagCapsLock = 1 << 16,-		NSEventModifierFlagShift = 1 << 17,-		NSEventModifierFlagControl = 1 << 18,-		NSEventModifierFlagOption = 1 << 19,-		NSEventModifierFlagCommand = 1 << 20,-		NSEventModifierFlagNumericPad = 1 << 21-	} NSEventModifierFlags;--	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {-		assert(win != NULL);-		-		if (win->event.type == RGFW_quit)-			return NULL;--		if ((win->event.type == RGFW_dnd || win->event.type == RGFW_dnd_init) && win->src.dndPassed == 0) {-			win->src.dndPassed = 1;-			return &win->event;-		}--		static void* eventFunc = NULL;-		if (eventFunc == NULL)-			eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");-		-		if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.keyCode != 120) {-			win->event.keyCode = 120;-			return &win->event;-		}--		NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend)-			(NSApp, eventFunc, ULONG_MAX, NULL, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);--		if (e == NULL)-			return NULL;--		if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) {-			((void (*)(id, SEL, id, bool))objc_msgSend)-				(NSApp, sel_registerName("postEvent:atStart:"), e, 0);--			return NULL;-		}--		if (win->event.droppedFilesCount) {-			u32 i;-			for (i = 0; i < win->event.droppedFilesCount; i++)-				win->event.droppedFiles[i][0] = '\0';-		}--		win->event.droppedFilesCount = 0;-		win->event.type = 0;--		switch (objc_msgSend_uint(e, sel_registerName("type"))) {-			case NSEventTypeMouseEntered: {-				win->event.type = RGFW_mouseEnter;-				NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));--				win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));-				RGFW_mouseNotifyCallBack(win, win->event.point, 1);-				break;-			}-			-			case NSEventTypeMouseExited:-				win->event.type = RGFW_mouseLeave;-				RGFW_mouseNotifyCallBack(win, win->event.point, 0);-				break;--			case NSEventTypeKeyDown: {-				u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));-				win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);-				RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current;--				win->event.type = RGFW_keyPressed;-				char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));-				strncpy(win->event.keyName, str, 16);-				RGFW_keyboard[win->event.keyCode].current = 1;--				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);-				break;-			}--			case NSEventTypeKeyUp: {-				u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));-				win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);;--				RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current;--				win->event.type = RGFW_keyReleased;-				char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));-				strncpy(win->event.keyName, str, 16);--				RGFW_keyboard[win->event.keyCode].current = 0;-				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0);-				break;-			}--			case NSEventTypeFlagsChanged: {-				u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags"));-				RGFW_updateLockState(win, ((u32)(flags & NSEventModifierFlagCapsLock) % 255), ((flags & NSEventModifierFlagNumericPad) % 255));-				-				u8 i;-				for (i = 0; i < 9; i++)-					RGFW_keyboard[i + RGFW_CapsLock].prev = 0;-				-				for (i = 0; i < 5; i++) {-					u32 shift = (1 << (i + 16));-					u32 key = i + RGFW_CapsLock;--					if ((flags & shift) && !RGFW_wasPressed(win, key)) {-						RGFW_keyboard[key].current = 1;--						if (key != RGFW_CapsLock)-							RGFW_keyboard[key+ 4].current = 1;-						-						win->event.type = RGFW_keyPressed;-						win->event.keyCode = key;-						break;-					} -					-					if (!(flags & shift) && RGFW_wasPressed(win, key)) {-						RGFW_keyboard[key].current = 0;-						-						if (key != RGFW_CapsLock)-							RGFW_keyboard[key + 4].current = 0;--						win->event.type = RGFW_keyReleased;-						win->event.keyCode = key;-						break;-					}-				}--				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, win->event.type == RGFW_keyPressed);--				break;-			}-			case NSEventTypeLeftMouseDragged:-			case NSEventTypeOtherMouseDragged:-			case NSEventTypeRightMouseDragged:-			case NSEventTypeMouseMoved:-				win->event.type = RGFW_mousePosChanged;-				NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));-				win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));--				if ((win->src.winArgs & RGFW_HOLD_MOUSE)) {-					p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX"));-					p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));-					-					p.x = ((win->r.w / 2)) + p.x;-					p.y = ((win->r.h / 2)) + p.y;-					win->event.point = RGFW_VECTOR((u32) p.x, (u32) (p.y));-				}--				RGFW_mousePosCallback(win, win->event.point);-				break;--			case NSEventTypeLeftMouseDown:-				win->event.button = RGFW_mouseLeft;-				win->event.type = RGFW_mouseButtonPressed;-				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 1;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);-				break;--			case NSEventTypeOtherMouseDown:-				win->event.button = RGFW_mouseMiddle;-				win->event.type = RGFW_mouseButtonPressed;-				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 1;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);-				break;--			case NSEventTypeRightMouseDown:-				win->event.button = RGFW_mouseRight;-				win->event.type = RGFW_mouseButtonPressed;-				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 1;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);-				break;--			case NSEventTypeLeftMouseUp:-				win->event.button = RGFW_mouseLeft;-				win->event.type = RGFW_mouseButtonReleased;-				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 0;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);-				break;--			case NSEventTypeOtherMouseUp:-				win->event.button = RGFW_mouseMiddle;-				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 0;-				win->event.type = RGFW_mouseButtonReleased;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);-				break;--			case NSEventTypeRightMouseUp:-				win->event.button = RGFW_mouseRight;-				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 0;-				win->event.type = RGFW_mouseButtonReleased;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);-				break;--			case NSEventTypeScrollWheel: {-				double deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));--				if (deltaY > 0) {-					win->event.button = RGFW_mouseScrollUp;-				}-				else if (deltaY < 0) {-					win->event.button = RGFW_mouseScrollDown;-				}--				RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];-				RGFW_mouseButtons[win->event.button] = 1;--				win->event.scroll = deltaY;--				win->event.type = RGFW_mouseButtonPressed;-				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);-				break;-			}--			default:-				break;-		}--		objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e);--		return &win->event;-	}---	void RGFW_window_move(RGFW_window* win, RGFW_vector v) {-		assert(win != NULL);--		win->r.x = v.x;-		win->r.y = v.y;-		((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)-			(win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true);-	}--	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {-		assert(win != NULL);--		win->r.w = a.w;-		win->r.h = a.h;-		((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)-			(win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true);-	}--	void RGFW_window_minimize(RGFW_window* win) {-		assert(win != NULL);--		objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL);-	}--	void RGFW_window_restore(RGFW_window* win) {-		assert(win != NULL);--		objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL);-	}--	void RGFW_window_setName(RGFW_window* win, char* name) {-		assert(win != NULL);--		NSString* str = NSString_stringWithUTF8String(name);-		objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);-	}--	#ifndef RGFW_NO_PASSTHROUGH-	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {-		objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough);-	}-	#endif--	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {-		if (a.w == 0 && a.h == 0)-			return;--		((void (*)(id, SEL, NSSize))objc_msgSend)-			(win->src.window, sel_registerName("setMinSize:"), (NSSize){a.w, a.h});-	}--	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {-		if (a.w == 0 && a.h == 0)-			return;--		((void (*)(id, SEL, NSSize))objc_msgSend)-			(win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h});-	}--	void RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) {-		assert(win != NULL);--		/* code by EimaMei  */-		// Make a bitmap representation, then copy the loaded image into it.-		void* representation = NSBitmapImageRep_initWithBitmapData(NULL, area.w, area.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, area.w * channels, 8 * channels);-		memcpy(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels);--		// Add ze representation.-		void* dock_image = NSImage_initWithSize((NSSize){area.w, area.h});-		NSImage_addRepresentation(dock_image, (void*) representation);--		// Finally, set the dock image to it.-		objc_msgSend_void_id(NSApp, sel_registerName("setApplicationIconImage:"), dock_image);-		// Free the garbage.-		release(dock_image);-		release(representation);-	}--	NSCursor* NSCursor_arrowStr(char* str) {-		void* nclass = objc_getClass("NSCursor");-		void* func = sel_registerName(str);-		return (NSCursor*) objc_msgSend_id(nclass, func);-	}--	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {-		assert(win != NULL);--		if (image == NULL) {-			objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set"));-			return;-		}--		/* NOTE(EimaMei): Code by yours truly. */-		// Make a bitmap representation, then copy the loaded image into it.-		void* representation = NSBitmapImageRep_initWithBitmapData(NULL, a.w, a.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, a.w * channels, 8 * channels);-		memcpy(NSBitmapImageRep_bitmapData(representation), image, a.w * a.h * channels);--		// Add ze representation.-		void* cursor_image = NSImage_initWithSize((NSSize){a.w, a.h});-		NSImage_addRepresentation(cursor_image, representation);--		// Finally, set the cursor image.-		void* cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0});--		objc_msgSend_void(cursor, sel_registerName("set"));--		// Free the garbage.-		release(cursor_image);-		release(representation);-	}--	void RGFW_window_setMouseDefault(RGFW_window* win) {-		RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);-	}--	void RGFW_window_showMouse(RGFW_window* win, i8 show) {-		RGFW_UNUSED(win);--		if (show) {-			CGDisplayShowCursor(kCGDirectMainDisplay);-		}-		else {-			CGDisplayHideCursor(kCGDirectMainDisplay);-		}-	}--	void RGFW_window_setMouseStandard(RGFW_window* win, u8 stdMouses) {-		if (stdMouses > ((sizeof(RGFW_mouseIconSrc)) / (sizeof(char*))))-			return;-		-		char* mouseStr = RGFW_mouseIconSrc[stdMouses];-		void* mouse = NSCursor_arrowStr(mouseStr);--		if (mouse == NULL)-			return;--		RGFW_UNUSED(win);-		CGDisplayShowCursor(kCGDirectMainDisplay);-		objc_msgSend_void(mouse, sel_registerName("set"));-	}--	void RGFW_clipCursor(RGFW_rect r) { -		CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2)));-		CGAssociateMouseAndMouseCursorPosition((!r.x && !r.y && r.w && !r.h));-	}--	void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v) {-		RGFW_UNUSED(win);--		CGWarpMouseCursorPosition(CGPointMake(v.x, v.y));		-	}---	void RGFW_window_hide(RGFW_window* win) {-		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false);-	}--	void RGFW_window_show(RGFW_window* win) {-		((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);-		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);-	}--	u8 RGFW_window_isFullscreen(RGFW_window* win) {-		assert(win != NULL);--		NSWindowStyleMask mask = (NSWindowStyleMask) objc_msgSend_uint(win->src.window, sel_registerName("styleMask"));-		return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;-	}--	u8 RGFW_window_isHidden(RGFW_window* win) {-		assert(win != NULL);--		bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible"));-		return visible == NO && !RGFW_window_isMinimized(win);-	}--	u8 RGFW_window_isMinimized(RGFW_window* win) {-		assert(win != NULL);--		return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES;-	}--	u8 RGFW_window_isMaximized(RGFW_window* win) {-		assert(win != NULL);--		return objc_msgSend_bool(win->src.window, sel_registerName("isZoomed"));-	}--	static RGFW_monitor RGFW_NSCreateMonitor(CGDirectDisplayID display) {-		RGFW_monitor monitor;--		CGRect bounds = CGDisplayBounds(display);-		monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height);--		CGSize screenSizeMM = CGDisplayScreenSize(display);-		monitor.physW = screenSizeMM.width / 25.4;-		monitor.physH = screenSizeMM.height / 25.4;--		monitor.scaleX = (monitor.rect.w / (screenSizeMM.width)) / 2.6;-		monitor.scaleY = (monitor.rect.h / (screenSizeMM.height)) / 2.6;--		snprintf(monitor.name, 128, "%i %i %i", CGDisplayModelNumber(display), CGDisplayVendorNumber(display), CGDisplaySerialNumber(display));--		return monitor;-	}---	static RGFW_monitor RGFW_monitors[7];--	RGFW_monitor* RGFW_getMonitors(void) {-		static CGDirectDisplayID displays[7];-		u32 count;--		if (CGGetActiveDisplayList(6, displays, &count) != kCGErrorSuccess)-			return NULL;--		for (u32 i = 0; i < count; i++)-			RGFW_monitors[i] = RGFW_NSCreateMonitor(displays[i]);--		return RGFW_monitors;-	}--	RGFW_monitor RGFW_getPrimaryMonitor(void) {-		CGDirectDisplayID primary = CGMainDisplayID();-		return RGFW_NSCreateMonitor(primary);-	}--	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {-		return RGFW_NSCreateMonitor(win->src.display);-	}--	char* RGFW_readClipboard(size_t* size) {-		char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString);-		-		size_t clip_len = 1;--		if (clip != NULL) {-			clip_len = strlen(clip) + 1; -		}--		char* str = (char*)RGFW_MALLOC(sizeof(char) * clip_len);-		-		if (clip != NULL) {-			strncpy(str, clip, clip_len);-		}--		str[clip_len] = '\0';-		-		if (size != NULL)-			*size = clip_len;-		return str;-	}--	void RGFW_writeClipboard(const char* text, u32 textLen) {-		RGFW_UNUSED(textLen);--		NSPasteboardType array[] = { NSPasteboardTypeString, NULL };-		NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL);--		NSPasteBoard_setString(NSPasteboard_generalPasteboard(), text, NSPasteboardTypeString);-	}--	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {-		RGFW_UNUSED(jsNumber);--		assert(win != NULL);--		return RGFW_registerJoystickF(win, (char*) "");-	}--	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {-		RGFW_UNUSED(file);--		assert(win != NULL);--		return win->src.joystickCount - 1;-	}--	#ifdef RGFW_OPENGL-	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {-		assert(win != NULL);-		objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext"));-	}-	#endif--	#if !defined(RGFW_EGL)-	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {-		assert(win != NULL);-		#if defined(RGFW_OPENGL)-		-		NSOpenGLContext_setValues(win->src.rSurf, &swapInterval, 222);-		#endif--		win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;-	}-	#endif-	-	void RGFW_window_swapBuffers(RGFW_window* win) {-		assert(win != NULL);--		RGFW_window_makeCurrent(win);--		/* clear the window*/--		if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) {-#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)-			#ifdef RGFW_OSMESA-			RGFW_OSMesa_reorganize();-			#endif--			RGFW_area area = RGFW_bufferSize;-			void* view = NSWindow_contentView(win->src.window);-			void* layer = objc_msgSend_id(view, sel_registerName("layer"));--			((void(*)(id, SEL, NSRect))objc_msgSend)(layer,-				sel_registerName("setFrame:"),-				(NSRect){{0, 0}, {win->r.w, win->r.h}});--			NSBitmapImageRep* rep = NSBitmapImageRep_initWithBitmapData(-				&win->buffer, win->r.w, win->r.h, 8, 4, true, false,-				"NSDeviceRGBColorSpace", 0,-				area.w * 4, 32-			);-			id image = NSAlloc((id)objc_getClass("NSImage"));-			NSImage_addRepresentation(image, rep);-			objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id) image);--			release(image);-			release(rep);-#endif-		}--		if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) {-			#ifdef RGFW_EGL-					eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);-			#elif defined(RGFW_OPENGL)-					objc_msgSend_void(win->src.rSurf, sel_registerName("flushBuffer"));-			#endif-		}--		RGFW_window_checkFPS(win);-	}--	void RGFW_window_close(RGFW_window* win) {-		assert(win != NULL);-		release(win->src.view);--#ifdef RGFW_ALLOC_DROPFILES-		{-			u32 i;-			for (i = 0; i < RGFW_MAX_DROPS; i++)-				RGFW_FREE(win->event.droppedFiles[i]);---			RGFW_FREE(win->event.droppedFiles);-		}-#endif--		if (RGFW_root == win) {-			objc_msgSend_void_id(NSApp, sel_registerName("terminate:"), (id) win->src.window);-			NSApp = NULL;-		}--#ifdef RGFW_BUFFER-		release(win->src.bitmap);-		release(win->src.image);-#endif--		CVDisplayLinkStop(win->src.displayLink);-		CVDisplayLinkRelease(win->src.displayLink);--		RGFW_FREE(win);-	}--	u64 RGFW_getTimeNS(void) {-		static mach_timebase_info_data_t timebase_info;-		if (timebase_info.denom == 0) {-			mach_timebase_info(&timebase_info);-		}-		return mach_absolute_time() * timebase_info.numer / timebase_info.denom;-	}--	u64 RGFW_getTime(void) {-		static mach_timebase_info_data_t timebase_info;-		if (timebase_info.denom == 0) {-			mach_timebase_info(&timebase_info);-		}-		return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9);-	}-#endif /* RGFW_MACOS */--/*-	End of MaOS defines-*/--/* unix (macOS, linux) only stuff */-#if defined(RGFW_X11) || defined(RGFW_MACOS)-/* unix threading */-#ifndef RGFW_NO_THREADS-#include <pthread.h>--	RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) {-		RGFW_UNUSED(args);-		-		RGFW_thread t;-		pthread_create((pthread_t*) &t, NULL, *ptr, NULL);-		return t;-	}-	void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); }-	void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); }-#ifdef __linux__-	void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio(thread, priority); }-#endif-#endif-/* unix sleep */-	void RGFW_sleep(u64 ms) {-		struct timespec time;-		time.tv_sec = 0;-		time.tv_nsec = ms * 1e+6;--		nanosleep(&time, NULL);-	}--#endif /* end of unix / mac stuff*/-#endif /*RGFW_IMPLEMENTATION*/--#ifdef __cplusplus++ 	#define RGFW_EXPORT - Use when building RGFW +    #define RGFW_IMPORT - Use when linking with RGFW (not as a single-header)+	+	#define RGFW_STD_INT - force the use stdint.h (for systems that might not have stdint.h (msvc)) +*/++/*+	Credits :+		EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support, siliapp.h -> referencing ++		stb - This project is heavily inspired by the stb single header files++		GLFW:+			certain parts of winapi and X11 are very poorly documented,+			GLFW's source code was referenced and used throughout the project (used code is marked in some way),+			this mainly includes, code for drag and drops, code for setting the icon to a bitmap and the code for managing the clipboard for X11 (as these parts are not documented very well)++			GLFW Copyright, https::/github.com/GLFW/GLFW++			Copyright (c) 2002-2006 Marcus Geelnard+			Copyright (c) 2006-2019 Camilla Löwy++		contributors : (feel free to put yourself here if you contribute)+		krisvers -> code review+		EimaMei (SaCode) -> code review+		Code-Nycticebus -> bug fixes+		Rob Rohan -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs +		AICDG (@THISISAGOODNAME) -> vulkan support (example)+		@Easymode -> support, testing/debugging, bug fixes and reviews+*/++#if _MSC_VER+	#pragma comment(lib, "gdi32")+	#pragma comment(lib, "shell32")+	#pragma comment(lib, "opengl32")+	#pragma comment(lib, "winmm")+	#pragma comment(lib, "user32")+#endif++#ifndef RGFW_MALLOC+	#include <stdlib.h>++	#ifndef __USE_POSIX199309+	#define __USE_POSIX199309+	#endif++	#include <time.h>+	#define RGFW_MALLOC malloc+	#define RGFW_CALLOC calloc+	#define RGFW_FREE free+#endif++#if !_MSC_VER+	#ifndef inline+		#ifndef __APPLE__+			#define inline __inline+		#endif+	#endif+#endif++#ifdef RGFW_WIN95 /* for windows 95 testing (not that it really works) */+	#define RGFW_NO_MONITOR+	#define RGFW_NO_PASSTHROUGH+#endif++#if defined(RGFW_EXPORT) ||  defined(RGFW_IMPORT)+	#if defined(_WIN32)+		#if defined(__TINYC__) && (defined(RGFW_EXPORT) ||  defined(RGFW_IMPORT))+			#define __declspec(x) __attribute__((x))+		#endif++		#if defined(RGFW_EXPORT)+			#define RGFWDEF __declspec(dllexport)+		#else +			#define RGFWDEF __declspec(dllimport)+		#endif+	#else+		#if defined(RGFW_EXPORT)+			#define RGFWDEF __attribute__((visibility("default")))+		#endif+	#endif+#endif ++#ifndef RGFWDEF+	#ifdef __clang__+		#define RGFWDEF static inline+	#else+		#define RGFWDEF inline+	#endif+#endif++#ifndef RGFW_ENUM+	#define RGFW_ENUM(type, name) type name; enum+#endif++#ifndef RGFW_UNUSED+	#define RGFW_UNUSED(x) (void)(x);+#endif++#if defined(__cplusplus) && !defined(__EMSCRIPTEN__)+	extern "C" {+#endif++	/* makes sure the header file part is only defined once by default */+#ifndef RGFW_HEADER++#define RGFW_HEADER++#if !defined(u8)+	#if ((defined(_MSC_VER) || defined(__SYMBIAN32__)) && !defined(RGFW_STD_INT)) /* MSVC might not have stdint.h */+		typedef unsigned char 	u8;+		typedef signed char		i8;+		typedef unsigned short  u16;+		typedef signed short 	i16;+		typedef unsigned int 	u32;+		typedef signed int		i32;+		typedef unsigned long	u64;+		typedef signed long		i64;+	#else /* use stdint standard types instead of c ""standard"" types */+		#include <stdint.h>++		typedef uint8_t     u8;+		typedef int8_t      i8;+		typedef uint16_t   u16;+		typedef int16_t    i16;+		typedef uint32_t   u32;+		typedef int32_t    i32;+		typedef uint64_t   u64;+		typedef int64_t    i64;+	#endif+#endif++#if !defined(b8) /* RGFW bool type */+	typedef u8 b8;+	typedef u32 b32;+#endif++#define RGFW_TRUE (!(0))+#define RGFW_FALSE 0++/* thse OS macros looks better & are standardized */+/* plus it helps with cross-compiling */++#ifdef __EMSCRIPTEN__+	#define RGFW_WEBASM++	#ifndef RGFW_NO_API+		#define RGFW_OPENGL+	#endif++	#ifdef RGFW_EGL+		#undef RGFW_EGL+	#endif++	#include <emscripten/html5.h>+	#include <emscripten/key_codes.h>+#endif++#if defined(RGFW_X11) && defined(__APPLE__)+	#define RGFW_MACOS_X11+	#undef __APPLE__+#endif++#if defined(_WIN32) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) /* (if you're using X11 on windows some how) */+	#define RGFW_WINDOWS++	/* make sure the correct architecture is defined */+	#if defined(_WIN64)+		#define _AMD64_+		#undef _X86_+	#else+		#undef _AMD64_+		#ifndef _X86_+			#define _X86_+		#endif+	#endif++	#ifndef RGFW_NO_XINPUT+		#ifdef __MINGW32__ /* try to find the right header */+			#include <xinput.h>+		#else+			#include <XInput.h>+		#endif+	#endif++	#if defined(RGFW_DIRECTX)+		#include <d3d11.h>+		#include <dxgi.h>+		#include <dxgi.h>+		#include <d3dcompiler.h>++		#ifndef __cplusplus+			#define __uuidof(T) IID_##T+		#endif+	#endif++#elif defined(RGFW_WAYLAND)+    #if !defined(RGFW_NO_API) && (!defined(RGFW_BUFFER) || defined(RGFW_OPENGL))+		#define RGFW_EGL+		#define RGFW_OPENGL+		#include <wayland-egl.h>+	#endif++	#include <wayland-client.h>+#elif (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11))  && !defined(RGFW_WEBASM)+	#define RGFW_MACOS_X11+	#define RGFW_X11+	#include <X11/Xlib.h>+#elif defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11)  && !defined(RGFW_WEBASM)+	#define RGFW_MACOS+#endif++#if (defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)) && !defined(RGFW_EGL)+	#define RGFW_EGL+#endif++#if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API)+	#define RGFW_OPENGL+#endif++#ifdef RGFW_EGL+	#include <EGL/egl.h>+#elif defined(RGFW_OSMESA)+	#ifndef __APPLE__+		#include <GL/osmesa.h>+	#else+		#include <OpenGL/osmesa.h>+	#endif+#endif++#if defined(RGFW_OPENGL) && defined(RGFW_X11)+	#ifndef GLX_MESA_swap_control+		#define  GLX_MESA_swap_control+	#endif+	#include <GL/glx.h> /* GLX defs, xlib.h, gl.h */+#endif++#ifndef RGFW_ALPHA+	#define RGFW_ALPHA 128 /* alpha value for RGFW_TRANSPARENT_WINDOW (WINAPI ONLY, macOS + linux don't need this) */+#endif++/*! Optional arguments for making a windows */+#define RGFW_TRANSPARENT_WINDOW		(1L<<9) /*!< the window is transparent (only properly works on X11 and MacOS, although it's although for windows) */+#define RGFW_NO_BORDER		(1L<<3) /*!< the window doesn't have border */+#define RGFW_NO_RESIZE		(1L<<4) /*!< the window cannot be resized  by the user */+#define RGFW_ALLOW_DND     (1L<<5) /*!< the window supports drag and drop*/+#define RGFW_HIDE_MOUSE (1L<<6) /*! the window should hide the mouse or not (can be toggled later on) using `RGFW_window_mouseShow*/+#define RGFW_FULLSCREEN (1L<<8) /* the window is fullscreen by default or not */+#define RGFW_CENTER (1L<<10) /*! center the window on the screen */+#define RGFW_OPENGL_SOFTWARE (1L<<11) /*! use OpenGL software rendering */+#define RGFW_COCOA_MOVE_TO_RESOURCE_DIR (1L << 12) /* (cocoa only), move to resource folder */+#define RGFW_SCALE_TO_MONITOR (1L << 13) /* scale the window to the screen */+#define RGFW_NO_INIT_API (1L << 2) /* DO not init an API (mostly for bindings, you should use `#define RGFW_NO_API` in C */++#define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/+#define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/+#define RGFW_WINDOW_HIDE (1L <<  16)/* the window is hidden */++typedef RGFW_ENUM(u8, RGFW_event_types) {+	/*! event codes */+ 	RGFW_keyPressed = 1, /* a key has been pressed */+	RGFW_keyReleased, /*!< a key has been released*/+	/*! key event note+		the code of the key pressed is stored in+		RGFW_Event.keyCode+		!!Keycodes defined at the bottom of the RGFW_HEADER part of this file!!++		while a string version is stored in+		RGFW_Event.KeyString++		RGFW_Event.lockState holds the current lockState+		this means if CapsLock, NumLock are active or not+	*/+	RGFW_mouseButtonPressed, /*!< a mouse button has been pressed (left,middle,right)*/+	RGFW_mouseButtonReleased, /*!< a mouse button has been released (left,middle,right)*/+	RGFW_mousePosChanged, /*!< the position of the mouse has been changed*/+	/*! mouse event note+		the x and y of the mouse can be found in the vector, RGFW_Event.point++		RGFW_Event.button holds which mouse button was pressed+	*/+	RGFW_jsButtonPressed, /*!< a joystick button was pressed */+	RGFW_jsButtonReleased, /*!< a joystick button was released */+	RGFW_jsAxisMove, /*!< an axis of a joystick was moved*/+	/*! joystick event note+		RGFW_Event.joystick holds which joystick was altered, if any+		RGFW_Event.button holds which joystick button was pressed++		RGFW_Event.axis holds the data of all the axis+		RGFW_Event.axisCount says how many axis there are+	*/+	RGFW_windowMoved, /*!< the window was moved (by the user) */+	RGFW_windowResized, /*!< the window was resized (by the user), [on webASM this means the browser was resized] */+	RGFW_focusIn, /*!< window is in focus now */+	RGFW_focusOut, /*!< window is out of focus now */+	RGFW_mouseEnter, /* mouse entered the window */+	RGFW_mouseLeave, /* mouse left the window */+	RGFW_windowRefresh, /* The window content needs to be refreshed */++	/* attribs change event note+		The event data is sent straight to the window structure+		with win->r.x, win->r.y, win->r.w and win->r.h+	*/+	RGFW_quit, /*!< the user clicked the quit button*/ +	RGFW_dnd, /*!< a file has been dropped into the window*/+	RGFW_dnd_init /*!< the start of a dnd event, when the place where the file drop is known */+	/* dnd data note+		The x and y coords of the drop are stored in the vector RGFW_Event.point++		RGFW_Event.droppedFilesCount holds how many files were dropped++		This is also the size of the array which stores all the dropped file string,+		RGFW_Event.droppedFiles+	*/+};++/*! mouse button codes (RGFW_Event.button) */+#define RGFW_mouseLeft  1 /*!< left mouse button is pressed*/+#define RGFW_mouseMiddle  2 /*!< mouse-wheel-button is pressed*/+#define RGFW_mouseRight  3 /*!< right mouse button is pressed*/+#define RGFW_mouseScrollUp  4 /*!< mouse wheel is scrolling up*/+#define RGFW_mouseScrollDown  5 /*!< mouse wheel is scrolling down*/++#ifndef RGFW_MAX_PATH+#define RGFW_MAX_PATH 260 /* max length of a path (for dnd) */+#endif+#ifndef RGFW_MAX_DROPS+#define RGFW_MAX_DROPS 260 /* max items you can drop at once */+#endif+++/* for RGFW_Event.lockstate */+#define RGFW_CAPSLOCK (1L << 1)+#define RGFW_NUMLOCK (1L << 2)++/*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */+#ifndef RGFW_joystick_codes+	typedef RGFW_ENUM(u8, RGFW_joystick_codes) {+		RGFW_JS_A = 0, /*!< or PS X button */+		RGFW_JS_B = 1, /*!< or PS circle button */+		RGFW_JS_Y = 2, /*!< or PS triangle button */+		RGFW_JS_X = 3, /*!< or PS square button */+		RGFW_JS_START = 9, /*!< start button */+		RGFW_JS_SELECT = 8, /*!< select button */+		RGFW_JS_HOME = 10, /*!< home button */+		RGFW_JS_UP = 13, /*!< dpad up */+		RGFW_JS_DOWN = 14, /*!< dpad down*/+		RGFW_JS_LEFT = 15, /*!< dpad left */+		RGFW_JS_RIGHT = 16, /*!< dpad right */+		RGFW_JS_L1 = 4, /*!< left bump */+		RGFW_JS_L2 = 5, /*!< left trigger*/+		RGFW_JS_R1 = 6, /*!< right bumper */+		RGFW_JS_R2 = 7, /*!< right trigger */+	};+#endif++/*! basic vector type, if there's not already a point/vector type of choice */+#ifndef RGFW_point+	typedef struct { i32 x, y; } RGFW_point;+#endif++/*! basic rect type, if there's not already a rect type of choice */+#ifndef RGFW_rect+	typedef struct { i32 x, y, w, h; } RGFW_rect;+#endif++/*! basic area type, if there's not already a area type of choice */+#ifndef RGFW_area+	typedef struct { u32 w, h; } RGFW_area;+#endif++#ifndef __cplusplus+#define RGFW_POINT(x, y) (RGFW_point){(i32)(x), (i32)(y)}+#define RGFW_RECT(x, y, w, h) (RGFW_rect){(i32)(x), (i32)(y), (i32)(w), (i32)(h)}+#define RGFW_AREA(w, h) (RGFW_area){(u32)(w), (u32)(h)}+#else+#define RGFW_POINT(x, y) {(i32)(x), (i32)(y)}+#define RGFW_RECT(x, y, w, h) {(i32)(x), (i32)(y), (i32)(w), (i32)(h)}+#define RGFW_AREA(w, h) {(u32)(w), (u32)(h)}+#endif++#ifndef RGFW_NO_MONITOR+	/*! structure for monitor data */+	typedef struct RGFW_monitor {+		char name[128]; /*!< monitor name */+		RGFW_rect rect; /*!< monitor Workarea */+		float scaleX, scaleY; /*!< monitor content scale*/+		float physW, physH; /*!< monitor physical size */+	} RGFW_monitor;++	/*+		NOTE : Monitor functions should be ran only as many times as needed (not in a loop)+	*/++	/*! get an array of all the monitors (max 6) */+	RGFWDEF RGFW_monitor* RGFW_getMonitors(void);+	/*! get the primary monitor */+	RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void);+#endif++/* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */+/*! Event structure for checking/getting events */+typedef struct RGFW_Event {+	char keyName[16]; /*!< key name of event*/++	/*! drag and drop data */+	/* 260 max paths with a max length of 260 */+#ifdef RGFW_ALLOC_DROPFILES+	char** droppedFiles;+#else+	char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH]; /*!< dropped files*/+#endif+	u32 droppedFilesCount; /*!< house many files were dropped */++	u32 type; /*!< which event has been sent?*/+	RGFW_point point; /*!< mouse x, y of event (or drop point) */+	+	u8 keyCode; /*!< keycode of event 	!!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */	+	+	b8 repeat; /*!< key press event repeated (the key is being held) */+	b8 inFocus;  /*!< if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */++	u8 lockState;+	+	u8 button; /* !< which mouse button was pressed */+	double scroll; /*!< the raw mouse scroll value */++	u16 joystick; /*! which joystick this event applies to (if applicable to any) */+	u8 axisesCount; /*!< number of axises */+	RGFW_point axis[2]; /*!< x, y of axises (-100 to 100) */++	u64 frameTime, frameTime2; /*!< this is used for counting the fps */+} RGFW_Event;++/*! source data for the window (used by the APIs) */+typedef struct RGFW_window_src {+#ifdef RGFW_WINDOWS+	HWND window; /*!< source window */+	HDC hdc; /*!< source HDC */+	u32 hOffset; /*!< height offset for window */+	#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)+		HGLRC ctx; /*!< source graphics context */+	#elif defined(RGFW_OSMESA)+		OSMesaContext ctx;+	#elif defined(RGFW_DIRECTX)+		IDXGISwapChain* swapchain;+		ID3D11RenderTargetView* renderTargetView;+		ID3D11DepthStencilView* pDepthStencilView;+	#elif defined(RGFW_EGL)+		EGLSurface EGL_surface;+		EGLDisplay EGL_display;+		EGLContext EGL_context;+	#endif++	#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) +		HDC hdcMem;+		HBITMAP bitmap;+	#endif+	RGFW_area maxSize, minSize; /*!< for setting max/min resize (RGFW_WINDOWS) */+#elif defined(RGFW_X11)+	Display* display; /*!< source display */+	Window window; /*!< source window */+	#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)+		GLXContext ctx; /*!< source graphics context */+	#elif defined(RGFW_OSMESA)+		OSMesaContext ctx;+	#elif defined(RGFW_EGL)+		EGLSurface EGL_surface;+		EGLDisplay EGL_display;+		EGLContext EGL_context;+	#endif++#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) +		XImage* bitmap;+		GC gc;+#endif+#elif defined(RGFW_WAYLAND)+	struct wl_display* display;+	struct wl_surface* surface;+	struct wl_buffer* wl_buffer;+	struct wl_keyboard* keyboard;++	struct xdg_surface* xdg_surface;+	struct xdg_toplevel* xdg_toplevel;+	struct zxdg_toplevel_decoration_v1* decoration;+	RGFW_Event events[20];+		i32 eventLen;+		size_t eventIndex;+	#if defined(RGFW_EGL)+			struct wl_egl_window* window;+			EGLSurface EGL_surface;+			EGLDisplay EGL_display;+			EGLContext EGL_context;+	#elif defined(RGFW_OSMESA)+		OSMesaContext ctx;+	#endif+#elif defined(RGFW_MACOS)+	u32 display;+	void* displayLink;+	void* window;+	b8 dndPassed;+#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)+		void* ctx; /*!< source graphics context */+#elif defined(RGFW_OSMESA)+		OSMesaContext ctx;+#elif defined(RGFW_EGL)+		EGLSurface EGL_surface;+		EGLDisplay EGL_display;+		EGLContext EGL_context;+#endif++	void* view; /*apple viewpoint thingy*/++#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) +		void* bitmap; /*!< API's bitmap for storing or managing */+		void* image;+#endif+#elif defined(RGFW_WEBASM)+	EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx;+#endif+} RGFW_window_src;++++typedef struct RGFW_window {+	RGFW_window_src src; /*!< src window data */++#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) +	u8* buffer; /*!< buffer for non-GPU systems (OSMesa, basic software rendering) */+	/* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */+#endif+	void* userPtr; /* ptr for usr data */+	+	RGFW_Event event; /*!< current event */++	RGFW_rect r; /*!< the x, y, w and h of the struct */+	+	RGFW_point _lastMousePoint; /*!< last cusor point (for raw mouse data) */+	+	u32 _winArgs; /*!< windows args (for RGFW to check) */+} RGFW_window; /*!< Window structure for managing the window */++#if defined(RGFW_X11) || defined(RGFW_MACOS)+	typedef u64 RGFW_thread; /*!< thread type unix */+#else+	typedef void* RGFW_thread; /*!< thread type for window */+#endif++/** * @defgroup Window_management+* @{ */ +++/*! + * the class name for X11 and WinAPI. apps with the same class will be grouped by the WM+ * by default the class name will == the root window's name+*/+RGFWDEF void RGFW_setClassName(char* name);++/*! this has to be set before createWindow is called, else the fulscreen size is used */+RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resized (by RGFW) */++RGFWDEF RGFW_window* RGFW_createWindow(+	const char* name, /* name of the window */+	RGFW_rect rect, /* rect of window */+	u16 args /* extra arguments (NULL / (u16)0 means no args used)*/+); /*!< function to create a window struct */++/*! get the size of the screen to an area struct */+RGFWDEF RGFW_area RGFW_getScreenSize(void);++/*!+	this function checks an *individual* event (and updates window structure attributes)+	this means, using this function without a while loop may cause event lag++	ex.++	while (RGFW_window_checkEvent(win) != NULL) [this keeps checking events until it reaches the last one]++	this function is optional if you choose to use event callbacks, +	although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents`+*/++RGFWDEF RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/++/*!+	for RGFW_window_eventWait and RGFW_window_checkEvents+	waitMS -> Allows th	e function to keep checking for events even after `RGFW_window_checkEvent == NULL`+			  if waitMS == 0, the loop will not wait for events+			  if waitMS == a positive integer, the loop will wait that many miliseconds after there are no more events until it returns+			  if waitMS == a negative integer, the loop will not return until it gets another event+*/+typedef RGFW_ENUM(i32, RGFW_eventWait) {+	RGFW_NEXT = -1,+	RGFW_NO_WAIT = 0+};++/*! sleep until RGFW gets an event or the timer ends (defined by OS) */+RGFWDEF void RGFW_window_eventWait(RGFW_window* win, i32 waitMS);++/*!+	check all the events until there are none left, +	this should only be used if you're using callbacks only+*/+RGFWDEF void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS);++/*! +	Tell RGFW_window_eventWait to stop waiting, to be ran from another thread+*/+RGFWDEF void RGFW_stopCheckEvents(void);++/*! window managment functions*/+RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */++/*! moves window to a given point */+RGFWDEF void RGFW_window_move(RGFW_window* win,+	RGFW_point v/*!< new pos*/+);++#ifndef RGFW_NO_MONITOR+	/*! move to a specific monitor */+	RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m /* monitor */);+#endif++/*! resize window to a current size/area */+RGFWDEF void RGFW_window_resize(RGFW_window* win, /*!< source window */+	RGFW_area a/*!< new size*/+);++/*! set the minimum size a user can shrink a window to a given size/area */+RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a);+/*! set the minimum size a user can extend a window to a given size/area */+RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a);++RGFWDEF void RGFW_window_maximize(RGFW_window* win); /*!< maximize the window size */+RGFWDEF void RGFW_window_minimize(RGFW_window* win); /*!< minimize the window (in taskbar (per OS))*/+RGFWDEF void RGFW_window_restore(RGFW_window* win); /*!< restore the window from minimized (per OS)*/++/*! if the window should have a border or not (borderless) based on bool value of `border` */+RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border);++/*! turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/+RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow);++#ifndef RGFW_NO_PASSTHROUGH+	/*!! turn on / off mouse passthrough */+	RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough);+#endif ++/*! rename window to a given string */+RGFWDEF void RGFW_window_setName(RGFW_window* win,+	char* name+);++RGFWDEF void RGFW_window_setIcon(RGFW_window* win, /*!< source window */+	u8* icon /*!< icon bitmap */,+	RGFW_area a /*!< width and height of the bitmap*/,+	i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */+); /*!< image resized by default */++/*!< sets mouse to bitmap (very simular to RGFW_window_setIcon), image NOT resized by default*/+RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels);++/*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */+RGFWDEF	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse);++RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /*!< sets the mouse to the default mouse icon */+/*+	Locks cursor at the center of the window+	win->event.point become raw mouse movement data ++	this is useful for a 3D camera+*/+RGFWDEF void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area);+/*! stop holding the mouse and let it move freely */+RGFWDEF void RGFW_window_mouseUnhold(RGFW_window* win);++/*! hide the window */+RGFWDEF void RGFW_window_hide(RGFW_window* win);+/*! show the window */+RGFWDEF void RGFW_window_show(RGFW_window* win);++/*+	makes it so `RGFW_window_shouldClose` returns true+	by setting the window event.type to RGFW_quit+*/+RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win);++/*! where the mouse is on the screen */+RGFWDEF RGFW_point RGFW_getGlobalMousePoint(void);++/*! where the mouse is on the window */+RGFWDEF RGFW_point RGFW_window_getMousePoint(RGFW_window* win);++/*! show the mouse or hide the mouse*/+RGFWDEF void RGFW_window_showMouse(RGFW_window* win, i8 show);+/*! move the mouse to a set x, y pos*/+RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v);++/*! if the window should close (RGFW_close was sent or escape was pressed) */+RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win);+/*! if window is fullscreen'd */+RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win);+/*! if window is hidden */+RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win);+/*! if window is minimized */+RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win);+/*! if window is maximized */+RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win);++/** @} */ ++/** * @defgroup Monitor+* @{ */ ++#ifndef RGFW_NO_MONITOR+/*+scale the window to the monitor,+this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation+*/+RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win);+/*! get the struct of the window's monitor  */+RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win);+#endif++/** @} */ ++/** * @defgroup Input+* @{ */ ++/*error handling*/+RGFWDEF b8 RGFW_Error(void); /*!< returns true if an error has occurred (doesn't print errors itself) */++/*! returns true if the key should be shifted */+RGFWDEF b8 RGFW_shouldShift(u32 keycode, u8 lockState);++/*! get char from RGFW keycode (using a LUT), uses shift'd version if shift = true */+RGFWDEF char RGFW_keyCodeToChar(u32 keycode, b8 shift);+/*! get char from RGFW keycode (using a LUT), uses lockState for shouldShift) */+RGFWDEF char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState);++/*! if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/+RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/++RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks previous state only) (key code)*/++RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code)*/+RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/++/* if a key is pressed and then released, pretty much the same as RGFW_isReleased */+RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key /*!< key code*/);++/*! if a mouse button is pressed */+RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ );+/*! if a mouse button is held */+RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button /*!< mouse button code */ );+/*! if a mouse button was released */+RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button /*!< mouse button code */ );+/*! if a mouse button was pressed (checks previous state only) */+RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ );+/** @} */ ++/** * @defgroup Clipboard+* @{ */ +RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */+RGFWDEF void RGFW_clipboardFree(char* str); /*!< the string returned from RGFW_readClipboard must be freed */++RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */+/** @} */ ++/**+	+	+	Event callbacks, +	these are completely optional, you can use the normal +	RGFW_checkEvent() method if you prefer that++* @defgroup Callbacks+* @{ +*/++/*! RGFW_windowMoved, the window and its new rect value  */+typedef void (* RGFW_windowmovefunc)(RGFW_window* win, RGFW_rect r);+/*! RGFW_windowResized, the window and its new rect value  */+typedef void (* RGFW_windowresizefunc)(RGFW_window* win, RGFW_rect r);+/*! RGFW_quit, the window that was closed */+typedef void (* RGFW_windowquitfunc)(RGFW_window* win);+/*! RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */+typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus);+/*! RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */+typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_point point, b8 status);+/*! RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse  */+typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_point point);+/*! RGFW_dnd_init, the window, the point of the drop on the windows */+typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_point point);+/*! RGFW_windowRefresh, the window that needs to be refreshed */+typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win);+/*! RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */+typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed);+/*! RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release)  */+typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed);+/*! RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */+typedef void (* RGFW_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed);+/*! RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */+typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount);+++/*!  RGFW_dnd, the window that had the drop, the drop data and the amount files dropped returns previous callback function (if it was set) */+#ifdef RGFW_ALLOC_DROPFILES+	typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount);+#else+	typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount);+#endif+/*! set callback for a window move event returns previous callback function (if it was set)  */+RGFWDEF RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func);+/*! set callback for a window resize event returns previous callback function (if it was set)  */+RGFWDEF RGFW_windowresizefunc RGFW_setWindowResizeCallback(RGFW_windowresizefunc func);+/*! set callback for a window quit event returns previous callback function (if it was set)  */+RGFWDEF RGFW_windowquitfunc RGFW_setWindowQuitCallback(RGFW_windowquitfunc func);+/*! set callback for a mouse move event returns previous callback function (if it was set)  */+RGFWDEF RGFW_mouseposfunc RGFW_setMousePosCallback(RGFW_mouseposfunc func);+/*! set callback for a window refresh event returns previous callback function (if it was set)  */+RGFWDEF RGFW_windowrefreshfunc RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func);+/*! set callback for a window focus change event returns previous callback function (if it was set)  */+RGFWDEF RGFW_focusfunc RGFW_setFocusCallback(RGFW_focusfunc func);+/*! set callback for a mouse notify event returns previous callback function (if it was set)  */+RGFWDEF RGFW_mouseNotifyfunc RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func);+/*! set callback for a drop event event returns previous callback function (if it was set)  */+RGFWDEF RGFW_dndfunc RGFW_setDndCallback(RGFW_dndfunc func);+/*! set callback for a start of a drop event returns previous callback function (if it was set)  */+RGFWDEF RGFW_dndInitfunc RGFW_setDndInitCallback(RGFW_dndInitfunc func);+/*! set callback for a key (press / release ) event returns previous callback function (if it was set)  */+RGFWDEF RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func);+/*! set callback for a mouse button (press / release ) event returns previous callback function (if it was set)  */+RGFWDEF RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func);+/*! set callback for a controller button (press / release ) event returns previous callback function (if it was set)  */+RGFWDEF RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func);+/*! set callback for a joystick axis mov event returns previous callback function (if it was set)  */+RGFWDEF RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func);++/** @} */ ++/** * @defgroup Threads+* @{ */ ++#ifndef RGFW_NO_THREADS+	/*! threading functions*/++	/*! NOTE! (for X11/linux) : if you define a window in a thread, it must be run after the original thread's window is created or else there will be a memory error */+	/*+		I'd suggest you use sili's threading functions instead+		if you're going to use sili+		which is a good idea generally+	*/++	#if defined(__unix__) || defined(__APPLE__) || defined(RGFW_WEBASM) +		typedef void* (* RGFW_threadFunc_ptr)(void*);+	#else+		typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter);  +	#endif++	RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/+	RGFWDEF void RGFW_cancelThread(RGFW_thread thread); /*!< cancels a thread*/+	RGFWDEF void RGFW_joinThread(RGFW_thread thread); /*!< join thread to current thread */+	RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority  */+#endif++/** @} */ ++/** * @defgroup joystick+* @{ */ ++/*! joystick count starts at 0*/+/*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/+RGFWDEF u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber);+RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file);++RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button);++/** @} */ ++/** * @defgroup graphics_API+* @{ */ ++/*!< make the window the current opengl drawing context++	NOTE:+ 	if you want to switch the graphics context's thread, +	you have to run RGFW_window_makeCurrent(NULL); on the old thread+	then RGFW_window_makeCurrent(valid_window) on the new thread+*/+RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win);++/*< updates fps / sets fps to cap (must by ran manually by the user at the end of a frame), returns current fps */+RGFWDEF u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap);++/* supports openGL, directX, OSMesa, EGL and software rendering */+RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /*!< swap the rendering buffer */+RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval);++RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set);+RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set);++/*! native API functions */+#if defined(RGFW_OPENGL) || defined(RGFW_EGL)+	/*! OpenGL init hints */+	RGFWDEF void RGFW_setGLStencil(i32 stencil); /*!< set stencil buffer bit size (8 by default) */+	RGFWDEF void RGFW_setGLSamples(i32 samples); /*!< set number of sampiling buffers (4 by default) */+	RGFWDEF void RGFW_setGLStereo(i32 stereo); /*!< use GL_STEREO (GL_FALSE by default) */+	RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /*!< number of aux buffers (0 by default) */++	/*! which profile to use for the opengl verion */+	typedef RGFW_ENUM(u8, RGFW_GL_profile)  { RGFW_GL_CORE = 0,  RGFW_GL_COMPATIBILITY  };+	/*! Set OpenGL version hint (core or compatibility profile)*/+	RGFWDEF void RGFW_setGLVersion(RGFW_GL_profile profile, i32 major, i32 minor);+	RGFWDEF void RGFW_setDoubleBuffer(b8 useDoubleBuffer); +    RGFWDEF void* RGFW_getProcAddress(const char* procname); /*!< get native opengl proc address */+    RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /*!< to be called by RGFW_window_makeCurrent */+#elif defined(RGFW_DIRECTX)+	typedef struct {+		IDXGIFactory* pFactory;+		IDXGIAdapter* pAdapter;+		ID3D11Device* pDevice;+		ID3D11DeviceContext* pDeviceContext;+	} RGFW_directXinfo;++	/*+		RGFW stores a global instance of RGFW_directXinfo,+		you can use this function to get a pointer the instance+	*/+	RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void);+#endif++/** @} */ ++/** * @defgroup Supporting+* @{ */ +RGFWDEF u64 RGFW_getTime(void); /*!< get time in seconds */+RGFWDEF u64 RGFW_getTimeNS(void); /*!< get time in nanoseconds */+RGFWDEF void RGFW_sleep(u64 milisecond); /*!< sleep for a set time */++/*!+	key codes and mouse icon enums+*/++typedef RGFW_ENUM(u8, RGFW_Key) {+	RGFW_KEY_NULL = 0,+	RGFW_Escape,+	RGFW_F1,+	RGFW_F2,+	RGFW_F3,+	RGFW_F4,+	RGFW_F5,+	RGFW_F6,+	RGFW_F7,+	RGFW_F8,+	RGFW_F9,+	RGFW_F10,+	RGFW_F11,+	RGFW_F12,++	RGFW_Backtick,++	RGFW_0,+	RGFW_1,+	RGFW_2,+	RGFW_3,+	RGFW_4,+	RGFW_5,+	RGFW_6,+	RGFW_7,+	RGFW_8,+	RGFW_9,++	RGFW_Minus,+	RGFW_Equals,+	RGFW_BackSpace,+	RGFW_Tab,+	RGFW_CapsLock,+	RGFW_ShiftL,+	RGFW_ControlL,+	RGFW_AltL,+	RGFW_SuperL,+	RGFW_ShiftR,+	RGFW_ControlR,+	RGFW_AltR,+	RGFW_SuperR,+	RGFW_Space,++	RGFW_a,+	RGFW_b,+	RGFW_c,+	RGFW_d,+	RGFW_e,+	RGFW_f,+	RGFW_g,+	RGFW_h,+	RGFW_i,+	RGFW_j,+	RGFW_k,+	RGFW_l,+	RGFW_m,+	RGFW_n,+	RGFW_o,+	RGFW_p,+	RGFW_q,+	RGFW_r,+	RGFW_s,+	RGFW_t,+	RGFW_u,+	RGFW_v,+	RGFW_w,+	RGFW_x,+	RGFW_y,+	RGFW_z,++	RGFW_Period,+	RGFW_Comma,+	RGFW_Slash,+	RGFW_Bracket,+	RGFW_CloseBracket,+	RGFW_Semicolon,+	RGFW_Return,+	RGFW_Quote,+	RGFW_BackSlash,++	RGFW_Up,+	RGFW_Down,+	RGFW_Left,+	RGFW_Right,++	RGFW_Delete,+	RGFW_Insert,+	RGFW_End,+	RGFW_Home,+	RGFW_PageUp,+	RGFW_PageDown,++	RGFW_Numlock,+	RGFW_KP_Slash,+	RGFW_Multiply,+	RGFW_KP_Minus,+	RGFW_KP_1,+	RGFW_KP_2,+	RGFW_KP_3,+	RGFW_KP_4,+	RGFW_KP_5,+	RGFW_KP_6,+	RGFW_KP_7,+	RGFW_KP_8,+	RGFW_KP_9,+	RGFW_KP_0,+	RGFW_KP_Period,+	RGFW_KP_Return,++	final_key,+};+++typedef RGFW_ENUM(u8, RGFW_mouseIcons) {+	RGFW_MOUSE_NORMAL = 0,+	RGFW_MOUSE_ARROW,+	RGFW_MOUSE_IBEAM,+	RGFW_MOUSE_CROSSHAIR,+	RGFW_MOUSE_POINTING_HAND,+	RGFW_MOUSE_RESIZE_EW,+	RGFW_MOUSE_RESIZE_NS,+	RGFW_MOUSE_RESIZE_NWSE,+	RGFW_MOUSE_RESIZE_NESW,+	RGFW_MOUSE_RESIZE_ALL,+	RGFW_MOUSE_NOT_ALLOWED,+};++/** @} */ ++#endif /* RGFW_HEADER */++/*+Example to get you started :++linux : gcc main.c -lX11 -lXcursor -lGL+windows : gcc main.c -lopengl32 -lshell32 -lgdi32+macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo++#define RGFW_IMPLEMENTATION+#include "RGFW.h"++u8 icon[4 * 3 * 3] = {0xFF, 0x00, 0x00, 0xFF,    0xFF, 0x00, 0x00, 0xFF,     0xFF, 0x00, 0x00, 0xFF,   0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF,     0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF};++int main() {+	RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0);++	RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4);++	for (;;) {+		RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag+		if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape))+			break;++		RGFW_window_swapBuffers(win);++		glClearColor(0xFF, 0XFF, 0xFF, 0xFF);+		glClear(GL_COLOR_BUFFER_BIT);+	}++	RGFW_window_close(win);+}++	compiling :++	if you wish to compile the library all you have to do is create a new file with this in it++	rgfw.c+	#define RGFW_IMPLEMENTATION+	#include "RGFW.h"++	then you can use gcc (or whatever compile you wish to use) to compile the library into object file++	ex. gcc -c RGFW.c -fPIC++	after you compile the library into an object file, you can also turn the object file into an static or shared library++	(commands ar and gcc can be replaced with whatever equivalent your system uses)+	static : ar rcs RGFW.a RGFW.o+	shared :+		windows:+			gcc -shared RGFW.o -lopengl32 -lshell32 -lgdi32 -o RGFW.dll+		linux:+			gcc -shared RGFW.o -lX11 -lXcursor -lGL -o RGFW.so+		macos:+			gcc -shared RGFW.o -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo+*/++#ifdef RGFW_X11+	#define RGFW_OS_BASED_VALUE(l, w, m, h, ww) l+#elif defined(RGFW_WINDOWS)+	#define RGFW_OS_BASED_VALUE(l, w, m, h, ww) w+#elif defined(RGFW_MACOS)+	#define RGFW_OS_BASED_VALUE(l, w, m, h, ww) m+#elif defined(RGFW_WEBASM)+	#define RGFW_OS_BASED_VALUE(l, w, m, h, ww) h+#elif defined(RGFW_WAYLAND)+    #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) ww  +#endif+++#ifdef RGFW_IMPLEMENTATION++#include <stdio.h>+#include <string.h>+#include <math.h>+#include <assert.h>++/*+RGFW_IMPLEMENTATION starts with generic RGFW defines++This is the start of keycode data++	Why not use macros instead of the numbers itself?+	Windows -> Not all virtual keys are macros (VK_0 - VK_1, VK_a - VK_z)+	Linux -> Only symcodes are values, (XK_0 - XK_1, XK_a - XK_z) are larger than 0xFF00, I can't find any way to work with them without making the array an unreasonable size+	MacOS -> windows and linux already don't have keycodes as macros, so there's no point+*/++++/* +	the c++ compiler doesn't support setting up an array like, +	we'll have to do it during runtime using a function & this messy setup+*/+#ifndef __cplusplus+#define RGFW_NEXT ,+#define RGFW_MAP+#else +#define RGFW_NEXT ;+#define RGFW_MAP RGFW_keycodes+#endif++#ifdef RGFW_WAYLAND+#include <linux/input-event-codes.h>+#endif++u8 RGFW_keycodes [RGFW_OS_BASED_VALUE(136, 337, 128, DOM_VK_WIN_OEM_CLEAR + 1, 130)] = {+#ifdef __cplusplus+	0+};+void RGFW_init_keys(void) {+#endif+	RGFW_MAP [RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE)] = RGFW_Backtick 		RGFW_NEXT++	RGFW_MAP [RGFW_OS_BASED_VALUE(19, 0x30, 29, DOM_VK_0, KEY_0)] = RGFW_0 					RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(10, 0x31, 18, DOM_VK_1, KEY_1)] = RGFW_1						RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(11, 0x32, 19, DOM_VK_2, KEY_2)] = RGFW_2						RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(12, 0x33, 20, DOM_VK_3, KEY_3)] = RGFW_3						RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(13, 0x34, 21, DOM_VK_4, KEY_4)] = RGFW_4						RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(14, 0x35, 23, DOM_VK_5, KEY_5)] = RGFW_5                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(15, 0x36, 22, DOM_VK_6, KEY_6)] = RGFW_6                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(16, 0x37, 26, DOM_VK_7, KEY_7)] = RGFW_7                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(17, 0x38, 28, DOM_VK_8, KEY_8)] = RGFW_8                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(18, 0x39, 25, DOM_VK_9, KEY_9)] = RGFW_9,++	RGFW_MAP [RGFW_OS_BASED_VALUE(65, 0x20, 49, DOM_VK_SPACE, KEY_SPACE)] = RGFW_Space,++	RGFW_MAP [RGFW_OS_BASED_VALUE(38, 0x41, 0, DOM_VK_A, KEY_A)] = RGFW_a                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(56, 0x42, 11, DOM_VK_B, KEY_B)] = RGFW_b                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(54, 0x43, 8, DOM_VK_C, KEY_C)] = RGFW_c                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(40, 0x44, 2, DOM_VK_D, KEY_D)] = RGFW_d                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(26, 0x45, 14, DOM_VK_E, KEY_E)] = RGFW_e                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(41, 0x46, 3, DOM_VK_F, KEY_F)] = RGFW_f                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(42, 0x47, 5, DOM_VK_G, KEY_G)] = RGFW_g                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(43, 0x48, 4, DOM_VK_H, KEY_H)] = RGFW_h                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(31, 0x49, 34, DOM_VK_I, KEY_I)] = RGFW_i                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(44, 0x4A, 38, DOM_VK_J, KEY_J)] = RGFW_j                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(45, 0x4B, 40, DOM_VK_K, KEY_K)] = RGFW_k                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(46, 0x4C, 37, DOM_VK_L, KEY_L)] = RGFW_l                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(58, 0x4D, 46, DOM_VK_M, KEY_M)] = RGFW_m                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(57, 0x4E, 45, DOM_VK_N, KEY_N)] = RGFW_n                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(32, 0x4F, 31, DOM_VK_O, KEY_O)] = RGFW_o                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(33, 0x50, 35, DOM_VK_P, KEY_P)] = RGFW_p                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(24, 0x51, 12, DOM_VK_Q, KEY_Q)] = RGFW_q                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(27, 0x52, 15, DOM_VK_R, KEY_R)] = RGFW_r                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(39, 0x53, 1, DOM_VK_S, KEY_S)] = RGFW_s                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(28, 0x54, 17, DOM_VK_T, KEY_T)] = RGFW_t                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(30, 0x55, 32, DOM_VK_U, KEY_U)] = RGFW_u                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(55, 0x56, 9, DOM_VK_V, KEY_V)] = RGFW_v                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(25, 0x57, 13, DOM_VK_W, KEY_W)] = RGFW_w                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(53, 0x58, 7, DOM_VK_X, KEY_X)] = RGFW_x                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(29, 0x59, 16, DOM_VK_Y, KEY_Y)] = RGFW_y                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(52, 0x5A, 6, DOM_VK_Z, KEY_Z)] = RGFW_z,++	RGFW_MAP [RGFW_OS_BASED_VALUE(60, 190, 47, DOM_VK_PERIOD, KEY_DOT)] = RGFW_Period             			RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(59, 188, 43, DOM_VK_COMMA, KEY_COMMA)] = RGFW_Comma               			RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(61, 191, 44, DOM_VK_SLASH, KEY_SLASH)] = RGFW_Slash               			RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(34, 219, 33, DOM_VK_OPEN_BRACKET, KEY_LEFTBRACE)] = RGFW_Bracket      			RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(35, 221, 30, DOM_VK_CLOSE_BRACKET, KEY_RIGHTBRACE)] = RGFW_CloseBracket             RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(47, 186, 41, DOM_VK_SEMICOLON, KEY_SEMICOLON)] = RGFW_Semicolon                 RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(48, 222, 39, DOM_VK_QUOTE, KEY_APOSTROPHE)] = RGFW_Quote                 			RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(51, 322, 42, DOM_VK_BACK_SLASH, KEY_BACKSLASH)] = RGFW_BackSlash,+	+	RGFW_MAP [RGFW_OS_BASED_VALUE(36, 0x0D, 36, DOM_VK_RETURN, KEY_ENTER)] = RGFW_Return              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(119, 0x2E, 118, DOM_VK_DELETE, KEY_DELETE)] = RGFW_Delete                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(77, 0x90, 72, DOM_VK_NUM_LOCK, KEY_NUMLOCK)] = RGFW_Numlock               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(106, 0x6F, 82, DOM_VK_DIVIDE, KEY_KPSLASH)] = RGFW_KP_Slash               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(63, 0x6A, 76, DOM_VK_MULTIPLY, KEY_KPASTERISK)] = RGFW_Multiply              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(82, 0x6D, 67, DOM_VK_SUBTRACT, KEY_KPMINUS)] = RGFW_KP_Minus              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(87, 0x61, 84, DOM_VK_NUMPAD1, KEY_KP1)] = RGFW_KP_1               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(88, 0x62, 85, DOM_VK_NUMPAD2, KEY_KP2)] = RGFW_KP_2               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(89, 0x63, 86, DOM_VK_NUMPAD3, KEY_KP3)] = RGFW_KP_3               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(83, 0x64, 87, DOM_VK_NUMPAD4, KEY_KP4)] = RGFW_KP_4               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(84, 0x65, 88, DOM_VK_NUMPAD5, KEY_KP5)] = RGFW_KP_5               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(85, 0x66, 89, DOM_VK_NUMPAD6, KEY_KP6)] = RGFW_KP_6               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(79, 0x67, 90, DOM_VK_NUMPAD7, KEY_KP7)] = RGFW_KP_7               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(80, 0x68, 92, DOM_VK_NUMPAD8, KEY_KP8)] = RGFW_KP_8               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(81, 0x69, 93, DOM_VK_NUMPAD9, KEY_KP9)] = RGFW_KP_9               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(90, 0x60, 83, DOM_VK_NUMPAD0, KEY_KP0)] = RGFW_KP_0               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(91, 0x6E, 65, DOM_VK_DECIMAL, KEY_KPDOT)] = RGFW_KP_Period              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(104, 0x92, 77, 0, KEY_KPENTER)] = RGFW_KP_Return,+	+	RGFW_MAP [RGFW_OS_BASED_VALUE(20, 189, 27, DOM_VK_HYPHEN_MINUS, KEY_MINUS)] = RGFW_Minus              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(21, 187, 24, DOM_VK_EQUALS, KEY_EQUAL)] = RGFW_Equals               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(22, 8, 51, DOM_VK_BACK_SPACE, KEY_BACKSPACE)] = RGFW_BackSpace              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(23, 0x09, 48, DOM_VK_TAB, KEY_TAB)] = RGFW_Tab                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(66, 20, 57, DOM_VK_CAPS_LOCK, KEY_CAPSLOCK)] = RGFW_CapsLock               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(50, 0x10, 56, DOM_VK_SHIFT, KEY_LEFTSHIFT)] = RGFW_ShiftL               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(37, 0x11, 59, DOM_VK_CONTROL, KEY_LEFTCTRL)] = RGFW_ControlL               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(64,0x12, 58, DOM_VK_ALT, KEY_LEFTALT)] = RGFW_AltL                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(133, 0x5B, 55, DOM_VK_WIN, KEY_LEFTMETA)] = RGFW_SuperL,+	+	#if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) && !defined(RGFW_WEBASM)+	RGFW_MAP [RGFW_OS_BASED_VALUE(105, 0x11, 59, 0, KEY_RIGHTCTRL)] = RGFW_ControlR               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(135, 0xA4, 55, 0, KEY_RIGHTMETA)] = RGFW_SuperR,+	RGFW_MAP [RGFW_OS_BASED_VALUE(62, 0x5C, 56, 0, KEY_RIGHTSHIFT)] = RGFW_ShiftR              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(108, 165, 58, 0, KEY_RIGHTALT)] = RGFW_AltR,+	#endif++	RGFW_MAP [RGFW_OS_BASED_VALUE(67, 0x70, 127, DOM_VK_F1, KEY_F1)] = RGFW_F1                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(68, 0x71, 121, DOM_VK_F2, KEY_F2)] = RGFW_F2                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(69, 0x72, 100, DOM_VK_F3, KEY_F3)] = RGFW_F3                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(70, 0x73, 119, DOM_VK_F4, KEY_F4)] = RGFW_F4                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(71, 0x74, 97, DOM_VK_F5, KEY_F5)] = RGFW_F5              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(72, 0x75, 98, DOM_VK_F6, KEY_F6)] = RGFW_F6              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(73, 0x76, 99, DOM_VK_F7, KEY_F7)] = RGFW_F7              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(74, 0x77, 101, DOM_VK_F8, KEY_F8)] = RGFW_F8                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(75, 0x78, 102, DOM_VK_F9, KEY_F9)] = RGFW_F9                 		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(76, 0x79, 110, DOM_VK_F10, KEY_F10)] = RGFW_F10               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(95, 0x7A, 104, DOM_VK_F11, KEY_F11)] = RGFW_F11               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(96, 0x7B, 112, DOM_VK_F12, KEY_F12)] = RGFW_F12               RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(111, 0x26, 126, DOM_VK_UP, KEY_UP)] = RGFW_Up                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(116, 0x28, 125, DOM_VK_DOWN, KEY_DOWN)] = RGFW_Down                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(113, 0x25, 123, DOM_VK_LEFT, KEY_LEFT)] = RGFW_Left                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(114, 0x27, 124, DOM_VK_RIGHT, KEY_RIGHT)] = RGFW_Right              RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(118, 0x2D, 115, DOM_VK_INSERT, KEY_INSERT)] = RGFW_Insert                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(115, 0x23, 120, DOM_VK_END, KEY_END)] = RGFW_End                  		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(112, 336, 117, DOM_VK_PAGE_UP, KEY_PAGEUP)] = RGFW_PageUp                		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(117, 325, 122, DOM_VK_PAGE_DOWN, KEY_PAGEDOWN)] = RGFW_PageDown            RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(9, 0x1B, 53, DOM_VK_ESCAPE, KEY_ESC)] = RGFW_Escape                   		RGFW_NEXT+	RGFW_MAP [RGFW_OS_BASED_VALUE(110, 0x24, 116, DOM_VK_HOME, KEY_HOME)] = RGFW_Home                    		RGFW_NEXT+#ifndef __cplusplus+};+#else +}+#endif++#undef RGFW_NEXT+#undef RGFW_MAP++typedef struct {+	b8 current  : 1;+	b8 prev  : 1;+} RGFW_keyState;++RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} };++RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode);++u32 RGFW_apiKeyCodeToRGFW(u32 keycode) {+	#ifdef __cplusplus+	if (RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE) != RGFW_Backtick) {+		RGFW_init_keys();+	}+	#endif++	/* make sure the key isn't out of bounds */+	if (keycode > sizeof(RGFW_keycodes) / sizeof(u8))+		return 0;+	+	return RGFW_keycodes[keycode];+}++RGFWDEF void RGFW_resetKey(void);+void RGFW_resetKey(void) {+	size_t len = final_key; /*!< last_key == length */+	+	size_t i; /*!< reset each previous state  */+	for (i = 0; i < len; i++)+		RGFW_keyboard[i].prev = 0;+}++b8 RGFW_shouldShift(u32 keycode, u8 lockState) {+    #define RGFW_xor(x, y) (( (x) && (!(y)) ) ||  ((y) && (!(x)) ))+    b8 caps4caps = (lockState & RGFW_CAPSLOCK) && ((keycode >= RGFW_a) && (keycode <= RGFW_z));+    b8 shouldShift = RGFW_xor((RGFW_isPressed(NULL, RGFW_ShiftL) || RGFW_isPressed(NULL, RGFW_ShiftR)), caps4caps);+    #undef RGFW_xor++	return shouldShift;+}	++char RGFW_keyCodeToChar(u32 keycode, b8 shift) {+    static const char map[] = {+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '`', '0', '1', '2', '3', '4', '5', '6', '7', '8', +        '9', '-', '=', 0, '\t',  0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',+        'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '.', ',', '/', '[', ']',  ';', '\n', '\'', '\\', +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  '/', '*', '-', '1', '2', '3',  '3', '5', '6', '7', '8',  '9', '0', '\n'+    };++    static const char mapCaps[] = {+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', ')', '!', '@', '#', '$', '%', '^', '&', '*', +        '(', '_', '+', 0, '0',  0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G',+        'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',+        'X', 'Y', 'Z', '>', '<', '?', '{', '}',  ':', '\n', '"', '|', +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '?', '*', '-', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0+    };++    if (shift == RGFW_FALSE)+        return map[keycode]; +    return mapCaps[keycode];+}++char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState) { return RGFW_keyCodeToChar(keycode, RGFW_shouldShift(keycode, lockState)); }++/*+	this is the end of keycode data+*/++/* joystick data */+u8 RGFW_jsPressed[4][16]; /*!< if a key is currently pressed or not (per joystick) */++i32 RGFW_joysticks[4]; /*!< limit of 4 joysticks at a time */+u16 RGFW_joystickCount; /*!< the actual amount of joysticks */++/* +	event callback defines start here+*/+++/*+	These exist to avoid the +	if (func == NULL) check +	for (allegedly) better performance+*/+void RGFW_windowmovefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); }+void RGFW_windowresizefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); }+void RGFW_windowquitfuncEMPTY(RGFW_window* win) { RGFW_UNUSED(win); }+void RGFW_focusfuncEMPTY(RGFW_window* win, b8 inFocus) {RGFW_UNUSED(win); RGFW_UNUSED(inFocus);}+void RGFW_mouseNotifyfuncEMPTY(RGFW_window* win, RGFW_point point, b8 status) {RGFW_UNUSED(win); RGFW_UNUSED(point); RGFW_UNUSED(status);}+void RGFW_mouseposfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);}+void RGFW_dndInitfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);}+void RGFW_windowrefreshfuncEMPTY(RGFW_window* win) {RGFW_UNUSED(win); }+void RGFW_keyfuncEMPTY(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(keycode); RGFW_UNUSED(keyName); RGFW_UNUSED(lockState); RGFW_UNUSED(pressed);}+void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, u8 button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);}+void RGFW_jsButtonfuncEMPTY(RGFW_window* win, u16 joystick, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(button); RGFW_UNUSED(pressed); }+void RGFW_jsAxisfuncEMPTY(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); }++#ifdef RGFW_ALLOC_DROPFILES+void RGFW_dndfuncEMPTY(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);}+#else+void RGFW_dndfuncEMPTY(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);}+#endif++RGFW_windowmovefunc RGFW_windowMoveCallback = RGFW_windowmovefuncEMPTY;+RGFW_windowresizefunc RGFW_windowResizeCallback = RGFW_windowresizefuncEMPTY;+RGFW_windowquitfunc RGFW_windowQuitCallback = RGFW_windowquitfuncEMPTY;+RGFW_mouseposfunc RGFW_mousePosCallback = RGFW_mouseposfuncEMPTY;+RGFW_windowrefreshfunc RGFW_windowRefreshCallback = RGFW_windowrefreshfuncEMPTY;+RGFW_focusfunc RGFW_focusCallback = RGFW_focusfuncEMPTY;+RGFW_mouseNotifyfunc RGFW_mouseNotifyCallBack = RGFW_mouseNotifyfuncEMPTY;+RGFW_dndfunc RGFW_dndCallback = RGFW_dndfuncEMPTY;+RGFW_dndInitfunc RGFW_dndInitCallback = RGFW_dndInitfuncEMPTY;+RGFW_keyfunc RGFW_keyCallback = RGFW_keyfuncEMPTY;+RGFW_mousebuttonfunc RGFW_mouseButtonCallback = RGFW_mousebuttonfuncEMPTY;+RGFW_jsButtonfunc RGFW_jsButtonCallback = RGFW_jsButtonfuncEMPTY;+RGFW_jsAxisfunc RGFW_jsAxisCallback = RGFW_jsAxisfuncEMPTY;++void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) { +	RGFW_window_eventWait(win, waitMS);++	while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { +		if (win->event.type == RGFW_quit) return; +	}+	+	#ifdef RGFW_WEBASM /* webasm needs to run the sleep function for asyncify */+		RGFW_sleep(0);+	#endif+}++RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { +	RGFW_windowmovefunc	prev =  (RGFW_windowMoveCallback == RGFW_windowmovefuncEMPTY) ? NULL : RGFW_windowMoveCallback;+	RGFW_windowMoveCallback = func;+	return prev;+}+RGFW_windowresizefunc RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) {+    RGFW_windowresizefunc prev = (RGFW_windowResizeCallback == RGFW_windowresizefuncEMPTY) ? NULL : RGFW_windowResizeCallback;+    RGFW_windowResizeCallback = func;+    return prev;+}+RGFW_windowquitfunc RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) {+    RGFW_windowquitfunc prev = (RGFW_windowQuitCallback == RGFW_windowquitfuncEMPTY) ? NULL : RGFW_windowQuitCallback;+    RGFW_windowQuitCallback = func;+    return prev;+}++RGFW_mouseposfunc RGFW_setMousePosCallback(RGFW_mouseposfunc func) {+    RGFW_mouseposfunc prev = (RGFW_mousePosCallback == RGFW_mouseposfuncEMPTY) ? NULL : RGFW_mousePosCallback;+    RGFW_mousePosCallback = func;+    return prev;+}+RGFW_windowrefreshfunc RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) {+    RGFW_windowrefreshfunc prev = (RGFW_windowRefreshCallback == RGFW_windowrefreshfuncEMPTY) ? NULL : RGFW_windowRefreshCallback;+    RGFW_windowRefreshCallback = func;+    return prev;+}+RGFW_focusfunc RGFW_setFocusCallback(RGFW_focusfunc func) {+    RGFW_focusfunc prev = (RGFW_focusCallback == RGFW_focusfuncEMPTY) ? NULL : RGFW_focusCallback;+    RGFW_focusCallback = func;+    return prev;+}++RGFW_mouseNotifyfunc RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) {+    RGFW_mouseNotifyfunc prev = (RGFW_mouseNotifyCallBack == RGFW_mouseNotifyfuncEMPTY) ? NULL : RGFW_mouseNotifyCallBack;+    RGFW_mouseNotifyCallBack = func;+    return prev;+}+RGFW_dndfunc RGFW_setDndCallback(RGFW_dndfunc func) {+    RGFW_dndfunc prev = (RGFW_dndCallback == RGFW_dndfuncEMPTY) ? NULL : RGFW_dndCallback;+    RGFW_dndCallback = func;+    return prev;+}+RGFW_dndInitfunc RGFW_setDndInitCallback(RGFW_dndInitfunc func) {+    RGFW_dndInitfunc prev = (RGFW_dndInitCallback == RGFW_dndInitfuncEMPTY) ? NULL : RGFW_dndInitCallback;+    RGFW_dndInitCallback = func;+    return prev;+}+RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func) {+    RGFW_keyfunc prev = (RGFW_keyCallback == RGFW_keyfuncEMPTY) ? NULL : RGFW_keyCallback;+    RGFW_keyCallback = func;+    return prev;+}+RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) {+    RGFW_mousebuttonfunc prev = (RGFW_mouseButtonCallback == RGFW_mousebuttonfuncEMPTY) ? NULL : RGFW_mouseButtonCallback;+    RGFW_mouseButtonCallback = func;+    return prev;+}+RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) {+    RGFW_jsButtonfunc prev = (RGFW_jsButtonCallback == RGFW_jsButtonfuncEMPTY) ? NULL : RGFW_jsButtonCallback;+    RGFW_jsButtonCallback = func;+    return prev;+}+RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) {+    RGFW_jsAxisfunc prev = (RGFW_jsAxisCallback == RGFW_jsAxisfuncEMPTY) ? NULL : RGFW_jsAxisCallback;+    RGFW_jsAxisCallback = func;+    return prev;+}+/* +no more event call back defines+*/++#define RGFW_ASSERT(check, str) {\+	if (!(check)) { \+		printf(str); \+		assert(check); \+	} \+}++b8 RGFW_error = 0;+b8 RGFW_Error(void) { return RGFW_error; }++#define SET_ATTRIB(a, v) { \+    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \+    attribs[index++] = a; \+    attribs[index++] = v; \+}+	+RGFW_area RGFW_bufferSize = {0, 0};+void RGFW_setBufferSize(RGFW_area size) {+	RGFW_bufferSize = size;+}+++RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args);++/* do a basic initialization for RGFW_window, this is to standard it for each OS */+RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {+	RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /*!< make a new RGFW struct */++	/* clear out dnd info */+#ifdef RGFW_ALLOC_DROPFILES+	win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS);+	u32 i;+	for (i = 0; i < RGFW_MAX_DROPS; i++)+		win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char));+#endif++	/* X11 requires us to have a display to get the screen size */+	#ifndef RGFW_X11 +	RGFW_area screenR = RGFW_getScreenSize();+	#else+	win->src.display = XOpenDisplay(NULL);+	assert(win->src.display != NULL);++	Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display);+	RGFW_area screenR = RGFW_AREA((u32)scrn->width, (u32)scrn->height);+	#endif+	+	/* rect based the requested args */+	if (args & RGFW_FULLSCREEN)+		rect = RGFW_RECT(0, 0, screenR.w, screenR.h);++	/* set and init the new window's data */+	win->r = rect;+	win->event.inFocus = 1;+	win->event.droppedFilesCount = 0;+	RGFW_joystickCount = 0;+	win->_winArgs = 0;+	win->event.lockState = 0;++	return win;+}++#ifndef RGFW_NO_MONITOR+void RGFW_window_scaleToMonitor(RGFW_window* win) {+	RGFW_monitor monitor = RGFW_window_getMonitor(win);+	+	RGFW_window_resize(win, RGFW_AREA((u32)(monitor.scaleX * (float)win->r.w), (u32)(monitor.scaleX * (float)win->r.h)));+}+#endif++RGFW_window* RGFW_root = NULL;+++#define RGFW_HOLD_MOUSE			(1L<<2) /*!< hold the moues still */+#define RGFW_MOUSE_LEFT 		(1L<<3) /* if mouse left the window */++#ifdef RGFW_MACOS+RGFWDEF void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer);+RGFWDEF void* RGFW_cocoaGetLayer(void);+#endif++char* RGFW_className = NULL;+void RGFW_setClassName(char* name) {+	RGFW_className = name;+}++void RGFW_clipboardFree(char* str) { RGFW_FREE(str); }++RGFW_keyState RGFW_mouseButtons[5] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} };++b8 RGFW_isMousePressed(RGFW_window* win, u8 button) {+	assert(win != NULL);+	return RGFW_mouseButtons[button].current && (win != NULL) && win->event.inFocus; +}+b8 RGFW_wasMousePressed(RGFW_window* win, u8 button) {+	assert(win != NULL); +	return RGFW_mouseButtons[button].prev && (win != NULL) && win->event.inFocus; +}+b8 RGFW_isMouseHeld(RGFW_window* win, u8 button) {+	return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button));+}+b8 RGFW_isMouseReleased(RGFW_window* win, u8 button) {+	return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button));	+}++b8 RGFW_isPressed(RGFW_window* win, u8 key) {+	return RGFW_keyboard[key].current && (win == NULL || win->event.inFocus);+}++b8 RGFW_wasPressed(RGFW_window* win, u8 key) {+	return RGFW_keyboard[key].prev && (win == NULL || win->event.inFocus);+}++b8 RGFW_isHeld(RGFW_window* win, u8 key) {+	return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key));+}++b8 RGFW_isClicked(RGFW_window* win, u8 key) {+	return (RGFW_wasPressed(win, key) && !RGFW_isPressed(win, key));+}++b8 RGFW_isReleased(RGFW_window* win, u8 key) {+	return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key));	+}++#if defined(RGFW_WINDOWS)  && defined(RGFW_DIRECTX) /* defines for directX context*/+	RGFW_directXinfo RGFW_dxInfo;+	RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; }+#endif++void RGFW_window_makeCurrent(RGFW_window* win) {+#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)+	if (win == NULL)+		RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, NULL, NULL);+	else+		RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL);+#elif defined(RGFW_OPENGL)+	RGFW_window_makeCurrent_OpenGL(win);+#else+	RGFW_UNUSED(win)+#endif+}++void RGFW_window_setGPURender(RGFW_window* win, i8 set) {+	if (!set && !(win->_winArgs & RGFW_NO_GPU_RENDER))+		win->_winArgs |= RGFW_NO_GPU_RENDER;+		+	else if (set && win->_winArgs & RGFW_NO_GPU_RENDER)+		win->_winArgs ^= RGFW_NO_GPU_RENDER;+}++void RGFW_window_setCPURender(RGFW_window* win, i8 set) {+	if (!set && !(win->_winArgs & RGFW_NO_CPU_RENDER))+		win->_winArgs |= RGFW_NO_CPU_RENDER;++	else if (set && win->_winArgs & RGFW_NO_CPU_RENDER)+		win->_winArgs ^= RGFW_NO_CPU_RENDER;+}++void RGFW_window_maximize(RGFW_window* win) {+	assert(win != NULL);++	RGFW_area screen = RGFW_getScreenSize();++	RGFW_window_move(win, RGFW_POINT(0, 0));+	RGFW_window_resize(win, screen);+}++b8 RGFW_window_shouldClose(RGFW_window* win) {+	assert(win != NULL);+	return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape));+}++void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; RGFW_windowQuitCallback(win); }++#ifndef RGFW_NO_MONITOR+	void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) {+		RGFW_window_move(win, RGFW_POINT(m.rect.x + win->r.x, m.rect.y + win->r.y));+	}+#endif++RGFWDEF void RGFW_captureCursor(RGFW_window* win, RGFW_rect);+RGFWDEF void RGFW_releaseCursor(RGFW_window* win);++void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) {+	if ((win->_winArgs & RGFW_HOLD_MOUSE))+		return;+	++	if (!area.w && !area.h)+		area = RGFW_AREA(win->r.w / 2, win->r.h / 2);+		+	win->_winArgs |= RGFW_HOLD_MOUSE;+	RGFW_captureCursor(win, win->r);+	RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));+}++void RGFW_window_mouseUnhold(RGFW_window* win) {+	if ((win->_winArgs & RGFW_HOLD_MOUSE)) {+		win->_winArgs ^= RGFW_HOLD_MOUSE;++		RGFW_releaseCursor(win);+	}+}++u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap) {+	u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime;++	u32 output_fps = 0;+	u64 fps = round(1e+9 / deltaTime);+	output_fps= fps;++	if (fpsCap && fps > fpsCap) {+		u64 frameTimeNS = 1e+9 / fpsCap;+		u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6;++		if (sleepTimeMS > 0) {+			RGFW_sleep(sleepTimeMS);+			win->event.frameTime = 0;+		}+	}++	win->event.frameTime = RGFW_getTimeNS();+	+	if (fpsCap == 0) +		return (u32) output_fps;+	+	deltaTime = RGFW_getTimeNS() - win->event.frameTime2;+	output_fps = round(1e+9 / deltaTime);+	win->event.frameTime2 = RGFW_getTimeNS();++	return output_fps;+}++u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { +	RGFW_UNUSED(win);+	return RGFW_jsPressed[c][button]; +}++#if defined(RGFW_X11) || defined(RGFW_WINDOWS)+	void RGFW_window_showMouse(RGFW_window* win, i8 show) {+		static u8 RGFW_blk[] = { 0, 0, 0, 0 };+		if (show == 0)+			RGFW_window_setMouse(win, RGFW_blk, RGFW_AREA(1, 1), 4);+		else+			RGFW_window_setMouseDefault(win);+	}+#endif++RGFWDEF void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock);	+void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {+	if (capital && !(win->event.lockState & RGFW_CAPSLOCK))+		win->event.lockState |= RGFW_CAPSLOCK;+	else if (!capital && (win->event.lockState & RGFW_CAPSLOCK))			+		win->event.lockState ^= RGFW_CAPSLOCK;+	+	if (numlock && !(win->event.lockState & RGFW_NUMLOCK))+		win->event.lockState |= RGFW_NUMLOCK;+	else if (!numlock && (win->event.lockState & RGFW_NUMLOCK))+		win->event.lockState ^= RGFW_NUMLOCK;+}++#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND)+	struct timespec;++	int nanosleep(const struct timespec* duration, struct timespec* rem);+	int clock_gettime(clockid_t clk_id, struct timespec* tp);+	int setenv(const char *name, const char *value, int overwrite);++	void RGFW_window_setDND(RGFW_window* win, b8 allow) {+		if (allow && !(win->_winArgs & RGFW_ALLOW_DND))+			win->_winArgs |= RGFW_ALLOW_DND;++		else if (!allow && (win->_winArgs & RGFW_ALLOW_DND))+			win->_winArgs ^= RGFW_ALLOW_DND;+	}+#endif++/*+	graphics API specific code (end of generic code)+	starts here +*/+++/* +	OpenGL defines start here   (Normal, EGL, OSMesa)+*/++#if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA)+	#ifdef RGFW_WINDOWS+		#define WIN32_LEAN_AND_MEAN+		#define OEMRESOURCE+		#include <windows.h>+	#endif++	#if !defined(__APPLE__) && !defined(RGFW_NO_GL_HEADER)+		#include <GL/gl.h>+	#elif defined(__APPLE__)+		#ifndef GL_SILENCE_DEPRECATION+			#define GL_SILENCE_DEPRECATION+		#endif+		#include <OpenGL/gl.h>+		#include <OpenGL/OpenGL.h>+	#endif++/* EGL, normal OpenGL only */+#if !defined(RGFW_OSMESA) +	i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0;+	b8 RGFW_profile = RGFW_GL_CORE;+	+	#ifndef RGFW_EGL+	i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1;+	#else+	i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1;+	#endif+++	void RGFW_setGLStencil(i32 stencil) { RGFW_STENCIL = stencil; }+	void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; }+	void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; }+	void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; }+	void RGFW_setDoubleBuffer(b8 useDoubleBuffer) { RGFW_DOUBLE_BUFFER = useDoubleBuffer; }++	void RGFW_setGLVersion(b8 profile, i32 major, i32 minor) {+        RGFW_profile = profile;+		RGFW_majorVersion = major;+		RGFW_minorVersion = minor;+	}++/* OPENGL normal only (no EGL / OSMesa) */+#ifndef RGFW_EGL++#define RGFW_GL_RENDER_TYPE 		RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE,    	0x2003,		73, 0, 0)+	#define RGFW_GL_ALPHA_SIZE 		RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE,       	0x201b,		11,     0, 0)+	#define RGFW_GL_DEPTH_SIZE 		RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE,       	0x2022,		12,     0, 0)+	#define RGFW_GL_DOUBLEBUFFER 		RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER,     	0x2011, 	5,  0, 0)   +	#define RGFW_GL_STENCIL_SIZE 		RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE,	 	0x2023,	13,     0, 0)+	#define RGFW_GL_SAMPLES			RGFW_OS_BASED_VALUE(GLX_SAMPLES, 		 	0x2042,	    55,     0, 0)+	#define RGFW_GL_STEREO 			RGFW_OS_BASED_VALUE(GLX_STEREO,	 		 	0x2012,			6,  0, 0)+	#define RGFW_GL_AUX_BUFFERS		RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS,	    0x2024,	7, 		    0, 0)++#if defined(RGFW_X11) || defined(RGFW_WINDOWS)+	#define RGFW_GL_DRAW 			RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE,	 	0x2001,					0, 0, 0)+	#define RGFW_GL_DRAW_TYPE 		RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE,     	0x2013,						0, 0, 0)+	#define RGFW_GL_FULL_FORMAT		RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR,   	 	0x2027,						0, 0, 0)+	#define RGFW_GL_RED_SIZE		RGFW_OS_BASED_VALUE(GLX_RED_SIZE,         	0x2015,						0, 0, 0)+	#define RGFW_GL_GREEN_SIZE		RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE,       	0x2017,						0, 0, 0)+	#define RGFW_GL_BLUE_SIZE		RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 	 		0x2019,						0, 0, 0)+	#define RGFW_GL_USE_RGBA		RGFW_OS_BASED_VALUE(GLX_RGBA_BIT,   	 	0x202B,						0, 0, 0)+#endif++#ifdef RGFW_WINDOWS+	#define WGL_SUPPORT_OPENGL_ARB                    0x2010+	#define WGL_COLOR_BITS_ARB                        0x2014+	#define WGL_NUMBER_PIXEL_FORMATS_ARB 			0x2000+	#define WGL_CONTEXT_MAJOR_VERSION_ARB             0x2091+	#define WGL_CONTEXT_MINOR_VERSION_ARB             0x2092+	#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126+	#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001+	#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002+	#define WGL_SAMPLE_BUFFERS_ARB               0x2041+	#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9+	#define WGL_PIXEL_TYPE_ARB                        0x2013+	#define WGL_TYPE_RGBA_ARB                         0x202B++	#define WGL_TRANSPARENT_ARB   					  0x200A+#endif+	+/*  The window'ing api needs to know how to render the data we (or opengl) give it +	MacOS and Windows do this using a structure called a "pixel format" +	X11 calls it a "Visual"+	This function returns the attributes for the format we want */+	static u32* RGFW_initFormatAttribs(u32 useSoftware) {+		RGFW_UNUSED(useSoftware);+		static u32 attribs[] = {+								#if defined(RGFW_X11) || defined(RGFW_WINDOWS)+								RGFW_GL_RENDER_TYPE,+								RGFW_GL_FULL_FORMAT,+								#endif+								RGFW_GL_ALPHA_SIZE      , 8,+								RGFW_GL_DEPTH_SIZE      , 24,+								#if defined(RGFW_X11) || defined(RGFW_WINDOWS)+								RGFW_GL_DRAW, 1,+								RGFW_GL_RED_SIZE        , 8,+								RGFW_GL_GREEN_SIZE      , 8,+								RGFW_GL_BLUE_SIZE       , 8,+								RGFW_GL_DRAW_TYPE     , RGFW_GL_USE_RGBA,+								#endif ++								#ifdef RGFW_X11+								GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,+								#endif	++								#ifdef RGFW_MACOS+								72,+								8, 24,+								#endif++								#ifdef RGFW_WINDOWS+								WGL_SUPPORT_OPENGL_ARB,		1,+								WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,+								WGL_COLOR_BITS_ARB,	 32,+								#endif++								0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0+		};++		size_t index = (sizeof(attribs) / sizeof(attribs[0])) - 13;++#define RGFW_GL_ADD_ATTRIB(attrib, attVal) \+		if (attVal) { \+			attribs[index] = attrib;\+			attribs[index + 1] = attVal;\+			index += 2;\+		}+         +        RGFW_GL_ADD_ATTRIB(RGFW_GL_DOUBLEBUFFER, 1);+        +        RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL);+		RGFW_GL_ADD_ATTRIB(RGFW_GL_STEREO, RGFW_STEREO);+		RGFW_GL_ADD_ATTRIB(RGFW_GL_AUX_BUFFERS, RGFW_AUX_BUFFERS);++#ifndef RGFW_X11+		RGFW_GL_ADD_ATTRIB(RGFW_GL_SAMPLES, RGFW_SAMPLES);+#endif ++#ifdef RGFW_MACOS+		if (useSoftware) {+			RGFW_GL_ADD_ATTRIB(70, kCGLRendererGenericFloatID);+		} else {+			attribs[index] = RGFW_GL_RENDER_TYPE;+			index += 1;+		}+#endif++#ifdef RGFW_MACOS+		/* macOS has the surface attribs and the opengl attribs connected for some reason+			maybe this is to give macOS more control to limit openGL/the opengl version? */++		attribs[index] = 99;+		attribs[index + 1] = 0x1000;++		if (RGFW_majorVersion >= 4 || RGFW_majorVersion >= 3) {+			attribs[index + 1] = (u32) ((RGFW_majorVersion >= 4) ? 0x4100 : 0x3200);+		}+#endif++		RGFW_GL_ADD_ATTRIB(0, 0);++		return attribs;+	}++/* EGL only (no OSMesa nor normal OPENGL) */+#elif defined(RGFW_EGL)++#include <EGL/egl.h>++#if defined(RGFW_LINK_EGL)+	typedef EGLBoolean(EGLAPIENTRY* PFN_eglInitialize)(EGLDisplay, EGLint*, EGLint*);++	PFNEGLINITIALIZEPROC eglInitializeSource;+	PFNEGLGETCONFIGSPROC eglGetConfigsSource;+	PFNEGLCHOOSECONFIGPROC eglChooseConfigSource;+	PFNEGLCREATEWINDOWSURFACEPROC eglCreateWindowSurfaceSource;+	PFNEGLCREATECONTEXTPROC eglCreateContextSource;+	PFNEGLMAKECURRENTPROC eglMakeCurrentSource;+	PFNEGLGETDISPLAYPROC eglGetDisplaySource;+	PFNEGLSWAPBUFFERSPROC eglSwapBuffersSource;+	PFNEGLSWAPINTERVALPROC eglSwapIntervalSource;+	PFNEGLBINDAPIPROC eglBindAPISource;+	PFNEGLDESTROYCONTEXTPROC eglDestroyContextSource;+	PFNEGLTERMINATEPROC eglTerminateSource;+	PFNEGLDESTROYSURFACEPROC eglDestroySurfaceSource;++#define eglInitialize eglInitializeSource+#define eglGetConfigs eglGetConfigsSource+#define eglChooseConfig eglChooseConfigSource+#define eglCreateWindowSurface eglCreateWindowSurfaceSource+#define eglCreateContext eglCreateContextSource+#define eglMakeCurrent eglMakeCurrentSource+#define eglGetDisplay eglGetDisplaySource+#define eglSwapBuffers eglSwapBuffersSource+#define eglSwapInterval eglSwapIntervalSource+#define eglBindAPI eglBindAPISource+#define eglDestroyContext eglDestroyContextSource+#define eglTerminate eglTerminateSource+#define eglDestroySurface eglDestroySurfaceSource;+#endif+++#define EGL_SURFACE_MAJOR_VERSION_KHR 0x3098+#define EGL_SURFACE_MINOR_VERSION_KHR 0x30fb++#ifndef RGFW_GL_ADD_ATTRIB+#define RGFW_GL_ADD_ATTRIB(attrib, attVal) \+	if (attVal) { \+		attribs[index] = attrib;\+		attribs[index + 1] = attVal;\+		index += 2;\+	}+#endif+++	void RGFW_createOpenGLContext(RGFW_window* win) {+#if defined(RGFW_LINK_EGL)+		eglInitializeSource = (PFNEGLINITIALIZEPROC) eglGetProcAddress("eglInitialize");+		eglGetConfigsSource = (PFNEGLGETCONFIGSPROC) eglGetProcAddress("eglGetConfigs");+		eglChooseConfigSource = (PFNEGLCHOOSECONFIGPROC) eglGetProcAddress("eglChooseConfig");+		eglCreateWindowSurfaceSource = (PFNEGLCREATEWINDOWSURFACEPROC) eglGetProcAddress("eglCreateWindowSurface");+		eglCreateContextSource = (PFNEGLCREATECONTEXTPROC) eglGetProcAddress("eglCreateContext");+		eglMakeCurrentSource = (PFNEGLMAKECURRENTPROC) eglGetProcAddress("eglMakeCurrent");+		eglGetDisplaySource = (PFNEGLGETDISPLAYPROC) eglGetProcAddress("eglGetDisplay");+		eglSwapBuffersSource = (PFNEGLSWAPBUFFERSPROC) eglGetProcAddress("eglSwapBuffers");+		eglSwapIntervalSource = (PFNEGLSWAPINTERVALPROC) eglGetProcAddress("eglSwapInterval");+		eglBindAPISource = (PFNEGLBINDAPIPROC) eglGetProcAddress("eglBindAPI");+		eglDestroyContextSource = (PFNEGLDESTROYCONTEXTPROC) eglGetProcAddress("eglDestroyContext");+		eglTerminateSource = (PFNEGLTERMINATEPROC) eglGetProcAddress("eglTerminate");+		eglDestroySurfaceSource = (PFNEGLDESTROYSURFACEPROC) eglGetProcAddress("eglDestroySurface");+#endif /* RGFW_LINK_EGL */++		#ifdef RGFW_WINDOWS+		win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc);+		#elif defined(RGFW_MACOS)+		win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType)0);+		#else+		win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display);+		#endif++		EGLint major, minor;++		eglInitialize(win->src.EGL_display, &major, &minor);++		#ifndef EGL_OPENGL_ES1_BIT+		#define EGL_OPENGL_ES1_BIT 0x1+		#endif++		EGLint egl_config[] = {+			EGL_SURFACE_TYPE, EGL_WINDOW_BIT,+			EGL_RENDERABLE_TYPE,+			#ifdef RGFW_OPENGL_ES1+			EGL_OPENGL_ES1_BIT,+			#elif defined(RGFW_OPENGL_ES3)+			EGL_OPENGL_ES3_BIT,+			#elif defined(RGFW_OPENGL_ES2)+			EGL_OPENGL_ES2_BIT,+			#else+			EGL_OPENGL_BIT,+			#endif+			EGL_NONE, EGL_NONE+		};++		EGLConfig config;+		EGLint numConfigs;+		eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs);++		#if defined(RGFW_MACOS)+		    void* layer = RGFW_cocoaGetLayer(); +		+			RGFW_window_cocoaSetLayer(win, layer);+			+			win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) layer, NULL);+		#else+			win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL);+		#endif++		EGLint attribs[] = {+			EGL_CONTEXT_CLIENT_VERSION,+			#ifdef RGFW_OPENGL_ES1+			1,+			#else+			2,+			#endif+			EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE+		};++		size_t index = 4;+		RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL);+		RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES);++        if (RGFW_DOUBLE_BUFFER)+            RGFW_GL_ADD_ATTRIB(EGL_RENDER_BUFFER, EGL_BACK_BUFFER);++		if (RGFW_majorVersion) {+			attribs[1] = RGFW_majorVersion;+	+			RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion);+			RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion);++			if (RGFW_profile == RGFW_GL_CORE) {+				RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);+			}+			else {+				RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);+			}++		}++		#if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)+		eglBindAPI(EGL_OPENGL_ES_API);+		#else+		eglBindAPI(EGL_OPENGL_API);		+		#endif+      		+		win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs);+		+		if (win->src.EGL_context == NULL)+			fprintf(stderr, "failed to create an EGL opengl context\n");++		eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context);+		eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);+	}++	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {+		eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context);+	}++	#ifdef RGFW_APPLE+	void* RGFWnsglFramework = NULL;+	#elif defined(RGFW_WINDOWS)+	static HMODULE wglinstance = NULL;+	#endif++	void* RGFW_getProcAddress(const char* procname) { +		#if defined(RGFW_WINDOWS)+			void* proc = (void*) GetProcAddress(wglinstance, procname); ++			if (proc)+				return proc;+		#endif++		return (void*) eglGetProcAddress(procname); +	}++	void RGFW_closeEGL(RGFW_window* win) {+		eglDestroySurface(win->src.EGL_display, win->src.EGL_surface);+		eglDestroyContext(win->src.EGL_display, win->src.EGL_context);++		eglTerminate(win->src.EGL_display);+	}+	+	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {+		assert(win != NULL);+		+		eglSwapInterval(win->src.EGL_display, swapInterval);++	}+#endif /* RGFW_EGL */++/* +	end of RGFW_EGL defines+*/++/* OPENGL Normal / EGL defines only (no OS MESA)  Ends here */++#elif defined(RGFW_OSMESA) /* OSmesa only */+RGFWDEF void RGFW_OSMesa_reorganize(void);++/* reorganize buffer for osmesa */+void RGFW_OSMesa_reorganize(void) {+	u8* row = (u8*) RGFW_MALLOC(win->r.w * 3);++	i32 half_height = win->r.h / 2;+	i32 stride = win->r.w * 3;++	i32 y;+	for (y = 0; y < half_height; ++y) {+		i32 top_offset = y * stride;+		i32 bottom_offset = (win->r.h - y - 1) * stride;+		memcpy(row, win->buffer + top_offset, stride);+		memcpy(win->buffer + top_offset, win->buffer + bottom_offset, stride);+		memcpy(win->buffer + bottom_offset, row, stride);+	}++	RGFW_FREE(row);+}+#endif /* RGFW_OSMesa */++#endif /* RGFW_GL (OpenGL, EGL, OSMesa )*/++/*+This is where OS specific stuff starts+*/+++#if defined(RGFW_WAYLAND) || defined(RGFW_X11)+	int RGFW_eventWait_forceStop[] = {0, 0, 0}; /* for wait events */++	#ifdef __linux__+		#include <linux/joystick.h>+		#include <fcntl.h>+		#include <unistd.h>+		+		RGFW_Event* RGFW_linux_updateJoystick(RGFW_window* win) {+			static int xAxis = 0, yAxis = 0;+			u8 i;+			for (i = 0; i < RGFW_joystickCount; i++) {+				struct js_event e;+++				if (RGFW_joysticks[i] == 0)+					continue;++				i32 flags = fcntl(RGFW_joysticks[i], F_GETFL, 0);+				fcntl(RGFW_joysticks[i], F_SETFL, flags | O_NONBLOCK);++				ssize_t bytes;+				while ((bytes = read(RGFW_joysticks[i], &e, sizeof(e))) > 0) {+					switch (e.type) {+					case JS_EVENT_BUTTON:+						win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased;+						win->event.button = e.number;+						RGFW_jsPressed[i][e.number] = e.value;+						RGFW_jsButtonCallback(win, i, e.number, e.value);+						return &win->event;+					case JS_EVENT_AXIS:+						ioctl(RGFW_joysticks[i], JSIOCGAXES, &win->event.axisesCount);++						if ((e.number == 0 || e.number % 2) && e.number != 1)+							xAxis = e.value;+						else+							yAxis = e.value;++						win->event.axis[e.number / 2].x = xAxis;+						win->event.axis[e.number / 2].y = yAxis;+						win->event.type = RGFW_jsAxisMove;+						win->event.joystick = i;+						RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount);+						return &win->event;++						default: break;+					}+				}+			}++			return NULL;+		}++	#endif+#endif++/*+++Start of Linux / Unix defines+++*/++#ifdef RGFW_X11+#ifndef RGFW_NO_X11_CURSOR+#include <X11/Xcursor/Xcursor.h>+#endif+#include <dlfcn.h>++#ifndef RGFW_NO_DPI+#include <X11/extensions/Xrandr.h>+#include <X11/Xresource.h>+#endif++#include <X11/Xutil.h>+#include <X11/Xatom.h>+#include <X11/keysymdef.h>+#include <unistd.h>++#include <X11/XKBlib.h> /* for converting keycode to string */+#include <X11/cursorfont.h> /* for hiding */+#include <X11/extensions/shapeconst.h>+#include <X11/extensions/shape.h>+#include <X11/extensions/XInput2.h>++#include <limits.h> /* for data limits (mainly used in drag and drop functions) */+#include <poll.h>+++#ifdef __linux__+#include <linux/joystick.h>+#endif++	u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor};  +	/*atoms needed for drag and drop*/+	Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XtextPlain, XtextUriList;++	Atom wm_delete_window = 0;++#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)+	typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int);+	typedef void (*PFN_XcursorImageDestroy)(XcursorImage*);+	typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*);+#endif+#ifdef RGFW_OPENGL+	typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);+#endif++#if !defined(RGFW_NO_X11_XI_PRELOAD)+	typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);+	PFN_XISelectEvents XISelectEventsSrc = NULL;+	#define XISelectEvents XISelectEventsSrc++	void* X11Xihandle = NULL;+#endif++#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)+	PFN_XcursorImageLoadCursor XcursorImageLoadCursorSrc = NULL;+	PFN_XcursorImageCreate XcursorImageCreateSrc = NULL;+	PFN_XcursorImageDestroy XcursorImageDestroySrc = NULL;++#define XcursorImageLoadCursor XcursorImageLoadCursorSrc+#define XcursorImageCreate XcursorImageCreateSrc+#define XcursorImageDestroy XcursorImageDestroySrc++	void* X11Cursorhandle = NULL;+#endif++	u32 RGFW_windowsOpen = 0;++#ifdef RGFW_OPENGL+	void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); }+#endif++	RGFWDEF void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi);+	void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi) {+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+		if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)+			RGFW_bufferSize = RGFW_getScreenSize();+		+		win->buffer = (u8*)RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);++		#ifdef RGFW_OSMESA+				win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);+				OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);+		#endif++		win->src.bitmap = XCreateImage(+			win->src.display, XDefaultVisual(win->src.display, vi->screen),+			vi->depth,+			ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h,+			32, 0+		);++		win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL);++		#else+		RGFW_UNUSED(win); /*!< if buffer rendering is not being used */+		RGFW_UNUSED(vi)+		#endif+	}++++	void RGFW_window_setBorder(RGFW_window* win, u8 border) {+		static Atom _MOTIF_WM_HINTS = 0;+		if (_MOTIF_WM_HINTS == 0 )+			_MOTIF_WM_HINTS = XInternAtom(win->src.display, "_MOTIF_WM_HINTS", False);+		+		struct __x11WindowHints {+			unsigned long flags, functions, decorations, status;+			long input_mode;+		} hints;+		hints.flags = (1L << 1);+		hints.decorations = border;++		XChangeProperty(+			win->src.display, win->src.window,+			_MOTIF_WM_HINTS, _MOTIF_WM_HINTS,+			32, PropModeReplace, (u8*)&hints, 5+		);+	}+	+	void RGFW_releaseCursor(RGFW_window* win) {+		XUngrabPointer(win->src.display, CurrentTime);++		/* disable raw input */+		unsigned char mask[] = { 0 };+		XIEventMask em;+		em.deviceid = XIAllMasterDevices;+		em.mask_len = sizeof(mask);+		em.mask = mask;++		XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1);+	}+	+	void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { +		/* enable raw input */+		unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };+		XISetMask(mask, XI_RawMotion);++		XIEventMask em;+		em.deviceid = XIAllMasterDevices;+		em.mask_len = sizeof(mask);+		em.mask = mask;+		+		XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1);++		XGrabPointer(win->src.display, win->src.window, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);++		RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (i32)(r.w / 2), win->r.y + (i32)(r.h / 2)));+	}++	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {+#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)+		if (X11Cursorhandle == NULL) {+#if defined(__CYGWIN__)+			X11Cursorhandle = dlopen("libXcursor-1.so", RTLD_LAZY | RTLD_LOCAL);+#elif defined(__OpenBSD__) || defined(__NetBSD__)+			X11Cursorhandle = dlopen("libXcursor.so", RTLD_LAZY | RTLD_LOCAL);+#else+			X11Cursorhandle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_LOCAL);+#endif++			XcursorImageCreateSrc = (PFN_XcursorImageCreate) dlsym(X11Cursorhandle, "XcursorImageCreate");+			XcursorImageDestroySrc = (PFN_XcursorImageDestroy) dlsym(X11Cursorhandle, "XcursorImageDestroy");+			XcursorImageLoadCursorSrc = (PFN_XcursorImageLoadCursor) dlsym(X11Cursorhandle, "XcursorImageLoadCursor");+		}+#endif++#if !defined(RGFW_NO_X11_XI_PRELOAD)+		if (X11Xihandle == NULL) {+#if defined(__CYGWIN__)+			X11Xihandle = dlopen("libXi-6.so", RTLD_LAZY | RTLD_LOCAL);+#elif defined(__OpenBSD__) || defined(__NetBSD__)+			X11Xihandle = dlopen("libXi.so", RTLD_LAZY | RTLD_LOCAL);+#else+			X11Xihandle = dlopen("libXi.so.6", RTLD_LAZY | RTLD_LOCAL);+#endif++			XISelectEventsSrc = (PFN_XISelectEvents) dlsym(X11Xihandle, "XISelectEvents");+		}+#endif++		XInitThreads(); /*!< init X11 threading*/++		if (args & RGFW_OPENGL_SOFTWARE)+			setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);++		RGFW_window* win = RGFW_window_basic_init(rect, args);++		u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /*!< X11 events accepted*/++#ifdef RGFW_OPENGL+		u32* visual_attribs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);+		i32 fbcount;+		GLXFBConfig* fbc = glXChooseFBConfig((Display*) win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount);++		i32 best_fbc = -1;++		if (fbcount == 0) {+			printf("Failed to find any valid GLX visual configs\n");+			return NULL;+		}++		u32 i;+		for (i = 0; i < (u32)fbcount; i++) {+			XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, fbc[i]);+                        if (vi == NULL)+				continue;+                        +			XFree(vi);++			i32 samp_buf, samples;+			glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);+			glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLES, &samples);+			+			if ((best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES || best_fbc == -1)) {+				best_fbc = i;+			}+		}++		if (best_fbc == -1) {+			printf("Failed to get a valid GLX visual\n");+			return NULL;+		}++		GLXFBConfig bestFbc = fbc[best_fbc];++		/* Get a visual */+		XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, bestFbc);+		+		XFree(fbc);+		+		if (args & RGFW_TRANSPARENT_WINDOW) {+			XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/+		}+		+#else+		XVisualInfo viNorm;++		viNorm.visual = DefaultVisual((Display*) win->src.display, DefaultScreen((Display*) win->src.display));+		+		viNorm.depth = 0;+		XVisualInfo* vi = &viNorm;+		+		XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/+#endif+		/* make X window attrubutes*/+		XSetWindowAttributes swa;+		Colormap cmap;++		swa.colormap = cmap = XCreateColormap((Display*) win->src.display,+			DefaultRootWindow(win->src.display),+			vi->visual, AllocNone);++		swa.background_pixmap = None;+		swa.border_pixel = 0;+		swa.event_mask = event_mask;+		+		swa.background_pixel = 0;++		/* create the window*/+		win->src.window = XCreateWindow((Display*) win->src.display, DefaultRootWindow((Display*) win->src.display), win->r.x, win->r.y, win->r.w, win->r.h,+			0, vi->depth, InputOutput, vi->visual,+			CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa);++		XFreeColors((Display*) win->src.display, cmap, NULL, 0, 0);++		#ifdef RGFW_OPENGL+		XFree(vi);+		#endif++		// In your .desktop app, if you set the property+		// StartupWMClass=RGFW that will assoicate the launcher icon+		// with your application - robrohan +		+		if (RGFW_className == NULL)+			RGFW_className = (char*)name;++		XClassHint *hint = XAllocClassHint();+		assert(hint != NULL);+		hint->res_class = (char*)RGFW_className;+		hint->res_name = (char*)name; // just use the window name as the app name+		XSetClassHint((Display*) win->src.display, win->src.window, hint);+		XFree(hint);++		if ((args & RGFW_NO_INIT_API) == 0) {+#ifdef RGFW_OPENGL /* This is the second part of setting up opengl. This is where we ask OpenGL for a specific version. */ +		i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 };+		context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB;+		if (RGFW_profile == RGFW_GL_CORE) +			context_attribs[1] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;+		else +			context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;+		+		if (RGFW_majorVersion || RGFW_minorVersion) {+			context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB;+			context_attribs[3] = RGFW_majorVersion;+			context_attribs[4] = GLX_CONTEXT_MINOR_VERSION_ARB;+			context_attribs[5] = RGFW_minorVersion;+		}++		glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;+		glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)+			glXGetProcAddressARB((GLubyte*) "glXCreateContextAttribsARB");++		GLXContext ctx = NULL;++		if (RGFW_root != NULL)+			ctx = RGFW_root->src.ctx;++		win->src.ctx = glXCreateContextAttribsARB((Display*) win->src.display, bestFbc, ctx, True, context_attribs);+#endif+		if (RGFW_root == NULL)+			RGFW_root = win;++		RGFW_init_buffer(win, vi);+		}+		++		#ifndef RGFW_NO_MONITOR+		if (args & RGFW_SCALE_TO_MONITOR)+			RGFW_window_scaleToMonitor(win);+		#endif++		if (args & RGFW_CENTER) {+			RGFW_area screenR = RGFW_getScreenSize();+			RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));+		}++		if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/+			XSizeHints* sh = XAllocSizeHints();+			sh->flags = (1L << 4) | (1L << 5);+			sh->min_width = sh->max_width = win->r.w;+			sh->min_height = sh->max_height = win->r.h;++			XSetWMSizeHints((Display*) win->src.display, (Drawable) win->src.window, sh, XA_WM_NORMAL_HINTS);+			XFree(sh);+		}++		if (args & RGFW_NO_BORDER) {+			RGFW_window_setBorder(win, 0);+		}++		XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want*/++		/* make it so the user can't close the window until the program does*/+		if (wm_delete_window == 0)+			wm_delete_window = XInternAtom((Display*) win->src.display, "WM_DELETE_WINDOW", False);++		XSetWMProtocols((Display*) win->src.display, (Drawable) win->src.window, &wm_delete_window, 1);++		/* connect the context to the window*/+#ifdef RGFW_OPENGL+		if ((args & RGFW_NO_INIT_API) == 0)+			glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx);+#endif++		/* set the background*/+		XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /*!< set the name*/++		XMapWindow((Display*) win->src.display, (Drawable) win->src.window);						  /* draw the window*/+		XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /*!< move the window to it's proper cords*/++		if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */+			win->_winArgs |= RGFW_ALLOW_DND;++			XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False);+			XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False);++			/* client messages */+			XdndEnter = XInternAtom((Display*) win->src.display, "XdndEnter", False);+			XdndPosition = XInternAtom((Display*) win->src.display, "XdndPosition", False);+			XdndStatus = XInternAtom((Display*) win->src.display, "XdndStatus", False);+			XdndLeave = XInternAtom((Display*) win->src.display, "XdndLeave", False);+			XdndDrop = XInternAtom((Display*) win->src.display, "XdndDrop", False);+			XdndFinished = XInternAtom((Display*) win->src.display, "XdndFinished", False);++			/* actions */+			XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False);++			XtextUriList = XInternAtom((Display*) win->src.display, "text/uri-list", False); +			XtextPlain = XInternAtom((Display*) win->src.display, "text/plain", False);++			XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False);+			const u8 version = 5;++			XChangeProperty((Display*) win->src.display, (Window) win->src.window,+				XdndAware, 4, 32,+				PropModeReplace, &version, 1); /*!< turns on drag and drop */+		}++		#ifdef RGFW_EGL+			if ((args & RGFW_NO_INIT_API) == 0)+				RGFW_createOpenGLContext(win);+		#endif++		RGFW_window_setMouseDefault(win);++		RGFW_windowsOpen++;++		return win; /*return newly created window*/+	}++	RGFW_area RGFW_getScreenSize(void) {+		assert(RGFW_root != NULL);++		Screen* scrn = DefaultScreenOfDisplay((Display*) RGFW_root->src.display);+		return RGFW_AREA(scrn->width, scrn->height);+	}++	RGFW_point RGFW_getGlobalMousePoint(void) {+		assert(RGFW_root != NULL);++		RGFW_point RGFWMouse;++		i32 x, y;+		u32 z;+		Window window1, window2;+		XQueryPointer((Display*) RGFW_root->src.display, XDefaultRootWindow((Display*) RGFW_root->src.display), &window1, &window2, &RGFWMouse.x, &RGFWMouse.y, &x, &y, &z);+ +		return RGFWMouse;+	}++	RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {+		assert(win != NULL);++		RGFW_point RGFWMouse;++		i32 x, y;+		u32 z;+		Window window1, window2;+		XQueryPointer((Display*) win->src.display, win->src.window, &window1, &window2, &x, &y, &RGFWMouse.x, &RGFWMouse.y, &z);++		return RGFWMouse;+	}++	int xAxis = 0, yAxis = 0;++	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {+		assert(win != NULL);++		static struct {+			long source, version;+			i32 format;+		} xdnd;++		if (win->event.type == 0) +			RGFW_resetKey();++		if (win->event.type == RGFW_quit) {+			return NULL;+		}++		win->event.type = 0;++#ifdef __linux__+	RGFW_Event* event = RGFW_linux_updateJoystick(win);+	if (event != NULL)+		return event;+#endif++		XPending(win->src.display);++		XEvent E; /*!< raw X11 event */++		/* if there is no unread qued events, get a new one */+		if ((QLength(win->src.display) || XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading)) +			&& win->event.type != RGFW_quit+		)+			XNextEvent((Display*) win->src.display, &E);+		else {+			return NULL;+		}++		u32 i;+		win->event.type = 0;+++		switch (E.type) {+		case KeyPress:+		case KeyRelease: {+			win->event.repeat = RGFW_FALSE;+			/* check if it's a real key release */+			if (E.type == KeyRelease && XEventsQueued((Display*) win->src.display, QueuedAfterReading)) { /* get next event if there is one*/+				XEvent NE;+				XPeekEvent((Display*) win->src.display, &NE);++				if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/+					win->event.repeat = RGFW_TRUE;+			}++			/* set event key data */+			KeySym sym = (KeySym)XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0);+			win->event.keyCode = RGFW_apiKeyCodeToRGFW(E.xkey.keycode);+			+			char* str = (char*)XKeysymToString(sym);+			if (str != NULL)+				strncpy(win->event.keyName, str, 16);++			win->event.keyName[15] = '\0';		++			RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);+			+			/* get keystate data */+			win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased;++			XKeyboardState keystate;+			XGetKeyboardControl((Display*) win->src.display, &keystate);++			RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2));+			RGFW_keyboard[win->event.keyCode].current = (E.type == KeyPress);+			RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, (E.type == KeyPress));+			break;+		}+		case ButtonPress:+		case ButtonRelease:+			win->event.type = RGFW_mouseButtonPressed + (E.type == ButtonRelease); // the events match +			+			switch(win->event.button) {+				case RGFW_mouseScrollUp:+					win->event.scroll = 1;+					break;+				case RGFW_mouseScrollDown:+					win->event.scroll = -1;+					break;+				default: break;+			}++			win->event.button = E.xbutton.button;+			RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;++			if (win->event.repeat == RGFW_FALSE)+				win->event.repeat = RGFW_isPressed(win, win->event.keyCode);++			RGFW_mouseButtons[win->event.button].current = (E.type == ButtonPress);+			RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress));+			break;++		case MotionNotify:	+			win->event.point.x = E.xmotion.x;+			win->event.point.y = E.xmotion.y;+			+			if ((win->_winArgs & RGFW_HOLD_MOUSE)) {+				win->event.point.y = E.xmotion.y;++				win->event.point.x = win->_lastMousePoint.x - abs(win->event.point.x);+				win->event.point.y = win->_lastMousePoint.y - abs(win->event.point.y);+			}++			win->_lastMousePoint = RGFW_POINT(E.xmotion.x, E.xmotion.y);++			win->event.type = RGFW_mousePosChanged;+			RGFW_mousePosCallback(win, win->event.point);+			break;++		case GenericEvent: {+			/* MotionNotify is used for mouse events if the mouse isn't held */                +			if (!(win->_winArgs & RGFW_HOLD_MOUSE)) {+            	XFreeEventData(win->src.display, &E.xcookie);+				break;+			}+			+            XGetEventData(win->src.display, &E.xcookie);+            if (E.xcookie.evtype == XI_RawMotion) {+				XIRawEvent *raw = (XIRawEvent *)E.xcookie.data;+				if (raw->valuators.mask_len == 0) {+					XFreeEventData(win->src.display, &E.xcookie);+					break;+				}++                double deltaX = 0.0f; +				double deltaY = 0.0f;++                /* check if relative motion data exists where we think it does */+				if (XIMaskIsSet(raw->valuators.mask, 0) != 0)+					deltaX += raw->raw_values[0];+				if (XIMaskIsSet(raw->valuators.mask, 1) != 0)+					deltaY += raw->raw_values[1];++				win->event.point = RGFW_POINT((i32)deltaX, (i32)deltaY);+				+				RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));++				win->event.type = RGFW_mousePosChanged;+				RGFW_mousePosCallback(win, win->event.point);+            }++            XFreeEventData(win->src.display, &E.xcookie);+			break;+		}+		+		case Expose:+			win->event.type = RGFW_windowRefresh;+			RGFW_windowRefreshCallback(win);+			break;++		case ClientMessage:+			/* if the client closed the window*/+			if (E.xclient.data.l[0] == (i64) wm_delete_window) {+				win->event.type = RGFW_quit;+				RGFW_windowQuitCallback(win);+				break;+			}+			+			/* reset DND values */+			if (win->event.droppedFilesCount) {+				for (i = 0; i < win->event.droppedFilesCount; i++)+					win->event.droppedFiles[i][0] = '\0';+			}++			win->event.droppedFilesCount = 0;++			if ((win->_winArgs & RGFW_ALLOW_DND) == 0)+				break;++			XEvent reply = { ClientMessage };+			reply.xclient.window = xdnd.source;+			reply.xclient.format = 32;+			reply.xclient.data.l[0] = (long) win->src.window;+			reply.xclient.data.l[1] = 0;+			reply.xclient.data.l[2] = None;++			if (E.xclient.message_type == XdndEnter) {+				unsigned long count;+				Atom* formats;+				Atom real_formats[6];++				Bool list = E.xclient.data.l[1] & 1;++				xdnd.source = E.xclient.data.l[0];+				xdnd.version = E.xclient.data.l[1] >> 24;+				xdnd.format = None;++				if (xdnd.version > 5)+					break;++				if (list) {+					Atom actualType;+					i32 actualFormat;+					unsigned long bytesAfter;++					XGetWindowProperty((Display*) win->src.display,+						xdnd.source,+						XdndTypeList,+						0,+						LONG_MAX,+						False,+						4,+						&actualType,+						&actualFormat,+						&count,+						&bytesAfter,+						(u8**) &formats);+				} else {+					count = 0;++					if (E.xclient.data.l[2] != None)+						real_formats[count++] = E.xclient.data.l[2];+					if (E.xclient.data.l[3] != None)+						real_formats[count++] = E.xclient.data.l[3];+					if (E.xclient.data.l[4] != None)+						real_formats[count++] = E.xclient.data.l[4];+					+					formats = real_formats;+				}++				unsigned long i;+				for (i = 0; i < count; i++) {+				    if (formats[i] == XtextUriList || formats[i] == XtextPlain) {+						xdnd.format = formats[i];+						break;+					}+				}++				if (list) {+					XFree(formats);+				}++				break;+			}+			if (E.xclient.message_type == XdndPosition) {+				const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff;+				const i32 yabs = (E.xclient.data.l[2]) & 0xffff;+				Window dummy;+				i32 xpos, ypos;++				if (xdnd.version > 5)+					break;++				XTranslateCoordinates((Display*) win->src.display,+					XDefaultRootWindow((Display*) win->src.display),+					(Window) win->src.window,+					xabs, yabs,+					&xpos, &ypos,+					&dummy);++				win->event.point.x = xpos;+				win->event.point.y = ypos;++				reply.xclient.window = xdnd.source;+				reply.xclient.message_type = XdndStatus;++				if (xdnd.format) {+					reply.xclient.data.l[1] = 1;+					if (xdnd.version >= 2)+						reply.xclient.data.l[4] = XdndActionCopy;+				}++				XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);+				XFlush((Display*) win->src.display);+				break;+			}++			if (E.xclient.message_type != XdndDrop)+				break;++			if (xdnd.version > 5)+				break;++			win->event.type = RGFW_dnd_init;++			if (xdnd.format) {+				Time time = CurrentTime;++				if (xdnd.version >= 1)+					time = E.xclient.data.l[2];++				XConvertSelection((Display*) win->src.display,+					XdndSelection,+					xdnd.format,+					XdndSelection,+					(Window) win->src.window,+					time);+			} else if (xdnd.version >= 2) {+				XEvent reply = { ClientMessage };++				XSendEvent((Display*) win->src.display, xdnd.source,+					False, NoEventMask, &reply);+				XFlush((Display*) win->src.display);+			}++			RGFW_dndInitCallback(win, win->event.point);+			break;+		case SelectionNotify: {+			/* this is only for checking for xdnd drops */+			if (E.xselection.property != XdndSelection || !(win->_winArgs | RGFW_ALLOW_DND))+				break;++			char* data;+			unsigned long result;++			Atom actualType;+			i32 actualFormat;+			unsigned long bytesAfter;++			XGetWindowProperty((Display*) win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data);++			if (result == 0)+				break;++			/*+			SOURCED FROM GLFW _glfwParseUriList+			Copyright (c) 2002-2006 Marcus Geelnard+			Copyright (c) 2006-2019 Camilla Löwy+			*/++			const char* prefix = (const char*)"file://";++			char* line;++			win->event.droppedFilesCount = 0;++			win->event.type = RGFW_dnd;++			while ((line = strtok(data, "\r\n"))) {+				char path[RGFW_MAX_PATH];++				data = NULL;++				if (line[0] == '#')+					continue;++				char* l;+				for (l = line; 1; l++) {+					if ((l - line) > 7)+						break;+					else if (*l != prefix[(l - line)])+						break;+					else if (*l == '\0' && prefix[(l - line)] == '\0') {+						line += 7;+						while (*line != '/')+							line++;+						break;+					} else if (*l == '\0')+						break;+				}++				win->event.droppedFilesCount++;++				size_t index = 0;+				while (*line) {+					if (line[0] == '%' && line[1] && line[2]) {+						const char digits[3] = { line[1], line[2], '\0' };+						path[index] = (char) strtol(digits, NULL, 16);+						line += 2;+					} else+						path[index] = *line;++					index++;+					line++;+				}+				path[index] = '\0';+				strncpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1);+			}++			if (data)+				XFree(data);++			if (xdnd.version >= 2) {+				reply.xclient.message_type = XdndFinished;+				reply.xclient.data.l[1] = result;+				reply.xclient.data.l[2] = XdndActionCopy;++				XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);+				XFlush((Display*) win->src.display);+			}++			RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);+			break;+		}+		case FocusIn:+			win->event.inFocus = 1;+			win->event.type = RGFW_focusIn;+			RGFW_focusCallback(win, 1);+			break;++			break;+		case FocusOut:+			win->event.inFocus = 0;+			win->event.type = RGFW_focusOut;+			RGFW_focusCallback(win, 0);+			break;+		+		case EnterNotify: {+			win->event.type = RGFW_mouseEnter;+			win->event.point.x = E.xcrossing.x;+			win->event.point.y = E.xcrossing.y;+			RGFW_mouseNotifyCallBack(win, win->event.point, 1);+			break;+		}++		case LeaveNotify: {+			win->event.type = RGFW_mouseLeave;+			RGFW_mouseNotifyCallBack(win, win->event.point, 0);+			break;+		}++		case ConfigureNotify: {+				/* detect resize */+      			if (E.xconfigure.width != win->r.w || E.xconfigure.height != win->r.h) {+					win->event.type = RGFW_windowResized;+					win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height);+					RGFW_windowResizeCallback(win, win->r);+					break;+      			}  +      +      			/* detect move */+      			if (E.xconfigure.x != win->r.x || E.xconfigure.y != win->r.y) {+					win->event.type = RGFW_windowMoved;+					win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h);+					RGFW_windowMoveCallback(win, win->r);+					break;+				} ++				break;+		}+		default: {+			break;+		}+		}++		XFlush((Display*) win->src.display);++		if (win->event.type)+			return &win->event;+		else+			return NULL;+	}++	void RGFW_window_move(RGFW_window* win, RGFW_point v) {+		assert(win != NULL);+		win->r.x = v.x;+		win->r.y = v.y;++		XMoveWindow((Display*) win->src.display, (Window) win->src.window, v.x, v.y);+	}+++	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {+		assert(win != NULL);+		win->r.w = a.w;+		win->r.h = a.h;++		XResizeWindow((Display*) win->src.display, (Window) win->src.window, a.w, a.h);+	}++	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {+		assert(win != NULL);++		if (a.w == 0 && a.h == 0)+			return;++		XSizeHints hints;+		long flags;++		XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);++		hints.flags |= PMinSize;+		+		hints.min_width = a.w;+		hints.min_height = a.h;++		XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);+	}++	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {+		assert(win != NULL);++		if (a.w == 0 && a.h == 0)+			return;++		XSizeHints hints;+		long flags;++		XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);++		hints.flags |= PMaxSize;++		hints.max_width = a.w;+		hints.max_height = a.h;++		XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);+	}+++	void RGFW_window_minimize(RGFW_window* win) {+		assert(win != NULL);++		XIconifyWindow(win->src.display, (Window) win->src.window, DefaultScreen(win->src.display));+		XFlush(win->src.display);+	}++	void RGFW_window_restore(RGFW_window* win) {+		assert(win != NULL);++		XMapWindow(win->src.display, (Window) win->src.window);+		XFlush(win->src.display);+	}	++	void RGFW_window_setName(RGFW_window* win, char* name) {+		assert(win != NULL);++		XStoreName((Display*) win->src.display, (Window) win->src.window, name);+	}+	+	void* RGFW_libxshape = NULL;++	#ifndef RGFW_NO_PASSTHROUGH+	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {+		assert(win != NULL);+		+		#if defined(__CYGWIN__)+			RGFW_libxshape = dlopen("libXext-6.so", RTLD_LAZY | RTLD_LOCAL);+		#elif defined(__OpenBSD__) || defined(__NetBSD__)+			RGFW_libxshape = dlopen("libXext.so", RTLD_LAZY | RTLD_LOCAL);+		#else+    		RGFW_libxshape = dlopen("libXext.so.6", RTLD_LAZY | RTLD_LOCAL);+		#endif+		+		typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int);+		static PFN_XShapeCombineMask XShapeCombineMask;+		+		typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int);+		static PFN_XShapeCombineRegion XShapeCombineRegion;+		+		if (XShapeCombineMask != NULL)+			XShapeCombineMask = (PFN_XShapeCombineMask) dlsym(RGFW_libxshape, "XShapeCombineMask");++		if (XShapeCombineRegion != NULL)+			XShapeCombineRegion = (PFN_XShapeCombineRegion) dlsym(RGFW_libxshape, "XShapeCombineMask");++		if (passthrough) {+			Region region = XCreateRegion();+			XShapeCombineRegion(win->src.display, win->src.window, ShapeInput, 0, 0, region, ShapeSet);+			XDestroyRegion(region);++			return;+		}++		XShapeCombineMask(win->src.display, win->src.window, ShapeInput, 0, 0, None, ShapeSet);+	}+	#endif++	/*+		the majority function is sourced from GLFW+	*/++	void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) {+		assert(win != NULL);++		i32 longCount = 2 + a.w * a.h;++		u64* X11Icon = (u64*) RGFW_MALLOC(longCount * sizeof(u64));+		u64* target = X11Icon;++		*target++ = a.w;+		*target++ = a.h;++		u32 i;++		for (i = 0; i < a.w * a.h; i++) {+			if (channels == 3)+				*target++ = ((icon[i * 3 + 0]) << 16) |+				((icon[i * 3 + 1]) << 8) |+				((icon[i * 3 + 2]) << 0) |+				(0xFF << 24);++			else if (channels == 4)+				*target++ = ((icon[i * 4 + 0]) << 16) |+				((icon[i * 4 + 1]) << 8) |+				((icon[i * 4 + 2]) << 0) |+				((icon[i * 4 + 3]) << 24);+		}++		static Atom NET_WM_ICON = 0;+		if (NET_WM_ICON == 0)+			NET_WM_ICON = XInternAtom((Display*) win->src.display, "_NET_WM_ICON", False);++		XChangeProperty((Display*) win->src.display, (Window) win->src.window,+			NET_WM_ICON,+			6, 32,+			PropModeReplace,+			(u8*) X11Icon,+			longCount);++		RGFW_FREE(X11Icon);++		XFlush((Display*) win->src.display);+	}++	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {+		assert(win != NULL);++#ifndef RGFW_NO_X11_CURSOR+		XcursorImage* native = XcursorImageCreate(a.w, a.h);+		native->xhot = 0;+		native->yhot = 0;++		u8* source = (u8*) image;+		XcursorPixel* target = native->pixels;++		u32 i;+		for (i = 0; i < a.w * a.h; i++, target++, source += 4) {+			u8 alpha = 0xFF;+			if (channels == 4)+				alpha = source[3];++			*target = (alpha << 24) | (((source[0] * alpha) / 255) << 16) | (((source[1] * alpha) / 255) << 8) | (((source[2] * alpha) / 255) << 0);+		}++		Cursor cursor = XcursorImageLoadCursor((Display*) win->src.display, native);+		XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor);++		XFreeCursor((Display*) win->src.display, (Cursor) cursor);+		XcursorImageDestroy(native);+#else+	RGFW_UNUSED(image) RGFW_UNUSED(a.w) RGFW_UNUSED(channels)+#endif+	}++	void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {+		assert(win != NULL);++		XEvent event;+		XQueryPointer(win->src.display, DefaultRootWindow(win->src.display),+			&event.xbutton.root, &event.xbutton.window,+			&event.xbutton.x_root, &event.xbutton.y_root,+			&event.xbutton.x, &event.xbutton.y,+			&event.xbutton.state);++		if (event.xbutton.x == v.x && event.xbutton.y == v.y)+			return;++		XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) v.x - win->r.x, (int) v.y - win->r.y);+	}++	RGFWDEF void RGFW_window_disableMouse(RGFW_window* win) {+		RGFW_UNUSED(win);+	}++	void RGFW_window_setMouseDefault(RGFW_window* win) {+		RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);+	}++	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {+		assert(win != NULL);+		 +		if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8)))+			return;+		+		mouse = RGFW_mouseIconSrc[mouse];++		Cursor cursor = XCreateFontCursor((Display*) win->src.display, mouse);+		XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor);++		XFreeCursor((Display*) win->src.display, (Cursor) cursor);+	}++	void RGFW_window_hide(RGFW_window* win) {+		XMapWindow(win->src.display, win->src.window);+	}++	void RGFW_window_show(RGFW_window* win) {+		XUnmapWindow(win->src.display, win->src.window);+	}++	/*+		the majority function is sourced from GLFW+	*/+	char* RGFW_readClipboard(size_t* size) {+		static Atom UTF8 = 0;+		if (UTF8 == 0)+			UTF8 = XInternAtom(RGFW_root->src.display, "UTF8_STRING", True);++		XEvent event;+		int format;+		unsigned long N, sizeN;+		char* data, * s = NULL;+		Atom target;+		Atom CLIPBOARD = 0, XSEL_DATA = 0;++		if (CLIPBOARD == 0) {+			CLIPBOARD = XInternAtom(RGFW_root->src.display, "CLIPBOARD", 0);+			XSEL_DATA = XInternAtom(RGFW_root->src.display, "XSEL_DATA", 0);+		}++		XConvertSelection(RGFW_root->src.display, CLIPBOARD, UTF8, XSEL_DATA, RGFW_root->src.window, CurrentTime);+		XSync(RGFW_root->src.display, 0);+		XNextEvent(RGFW_root->src.display, &event);++		if (event.type != SelectionNotify || event.xselection.selection != CLIPBOARD || event.xselection.property == 0)+			return NULL;++		XGetWindowProperty(event.xselection.display, event.xselection.requestor,+			event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target,+			&format, &sizeN, &N, (unsigned char**) &data);++		if (target == UTF8 || target == XA_STRING) {+			s = (char*)RGFW_MALLOC(sizeof(char) * sizeN);+			strncpy(s, data, sizeN);+			s[sizeN] = '\0';+			XFree(data);+		}++		XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);++		if (s != NULL && size != NULL)+			*size = sizeN;++		return s;+	}++	/*+		almost all of this function is sourced from GLFW+	*/+	void RGFW_writeClipboard(const char* text, u32 textLen) {+		static Atom CLIPBOARD = 0,+			UTF8_STRING = 0,+			SAVE_TARGETS = 0,+			TARGETS = 0,+			MULTIPLE = 0,+			ATOM_PAIR = 0,+			CLIPBOARD_MANAGER = 0;++		if (CLIPBOARD == 0) {+			CLIPBOARD = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD", False);+			UTF8_STRING = XInternAtom((Display*) RGFW_root->src.display, "UTF8_STRING", False);+			SAVE_TARGETS = XInternAtom((Display*) RGFW_root->src.display, "SAVE_TARGETS", False);+			TARGETS = XInternAtom((Display*) RGFW_root->src.display, "TARGETS", False);+			MULTIPLE = XInternAtom((Display*) RGFW_root->src.display, "MULTIPLE", False);+			ATOM_PAIR = XInternAtom((Display*) RGFW_root->src.display, "ATOM_PAIR", False);+			CLIPBOARD_MANAGER = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD_MANAGER", False);+		}+		+		XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime);++		XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime);+		for (;;) {+			XEvent event;++			XNextEvent((Display*) RGFW_root->src.display, &event);+			if (event.type != SelectionRequest) {+				break;+			}++			const XSelectionRequestEvent* request = &event.xselectionrequest;++			XEvent reply = { SelectionNotify };+			reply.xselection.property = 0;++			if (request->target == TARGETS) {+				const Atom targets[] = { TARGETS,+										MULTIPLE,+										UTF8_STRING,+										XA_STRING };++				XChangeProperty((Display*) RGFW_root->src.display,+					request->requestor,+					request->property,+					4,+					32,+					PropModeReplace,+					(u8*) targets,+					sizeof(targets) / sizeof(targets[0]));++				reply.xselection.property = request->property;+			}++			if (request->target == MULTIPLE) {+				Atom* targets = NULL;++				Atom actualType = 0;+				int actualFormat = 0;+				unsigned long count = 0, bytesAfter = 0;++				XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);++				unsigned long i;+				for (i = 0; i < (u32)count; i += 2) {+					if (targets[i] == UTF8_STRING || targets[i] == XA_STRING) {+						XChangeProperty((Display*) RGFW_root->src.display,+							request->requestor,+							targets[i + 1],+							targets[i],+							8,+							PropModeReplace,+							(u8*) text,+							textLen);+						XFlush(RGFW_root->src.display);+					} else {+						targets[i + 1] = None;+					}+				}++				XChangeProperty((Display*) RGFW_root->src.display,+					request->requestor,+					request->property,+					ATOM_PAIR,+					32,+					PropModeReplace,+					(u8*) targets,+					count);++				XFlush(RGFW_root->src.display);+				XFree(targets);++				reply.xselection.property = request->property;+			}++			reply.xselection.display = request->display;+			reply.xselection.requestor = request->requestor;+			reply.xselection.selection = request->selection;+			reply.xselection.target = request->target;+			reply.xselection.time = request->time;++			XSendEvent((Display*) RGFW_root->src.display, request->requestor, False, 0, &reply);+			XFlush(RGFW_root->src.display);+		}+	}++	u8 RGFW_window_isFullscreen(RGFW_window* win) {+		assert(win != NULL);++		XWindowAttributes windowAttributes;+		XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);++		/* check if the window is visable */+		if (windowAttributes.map_state != IsViewable)+			return 0;++		/* check if the window covers the full screen */+		return (windowAttributes.x == 0 && windowAttributes.y == 0 &&+			windowAttributes.width == XDisplayWidth(win->src.display, DefaultScreen(win->src.display)) &&+			windowAttributes.height == XDisplayHeight(win->src.display, DefaultScreen(win->src.display)));+	}++	u8 RGFW_window_isHidden(RGFW_window* win) {+		assert(win != NULL);++		XWindowAttributes windowAttributes;+		XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);++		return (windowAttributes.map_state == IsUnmapped && !RGFW_window_isMinimized(win));+	}++	u8 RGFW_window_isMinimized(RGFW_window* win) {+		assert(win != NULL);++		static Atom prop = 0;+		if (prop == 0)+			prop = XInternAtom(win->src.display, "WM_STATE", False);++		Atom actual_type;+		i32 actual_format;+		unsigned long nitems, bytes_after;+		unsigned char* prop_data;++		i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, prop, 0, 2, False,+			AnyPropertyType, &actual_type, &actual_format,+			&nitems, &bytes_after, &prop_data);++		if (status == Success && nitems >= 1 && *((int*) prop_data) == IconicState) {+			XFree(prop_data);+			return 1;+		}++		if (prop_data != NULL)+			XFree(prop_data);++		return 0;+	}++	u8 RGFW_window_isMaximized(RGFW_window* win) {+		assert(win != NULL);++		static Atom net_wm_state = 0;+		static Atom net_wm_state_maximized_horz = 0;+		static Atom net_wm_state_maximized_vert = 0;++		if (net_wm_state == 0) {+			net_wm_state = XInternAtom(win->src.display, "_NET_WM_STATE", False);+			net_wm_state_maximized_vert = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_VERT", False);+			net_wm_state_maximized_horz = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);+		}++		Atom actual_type;+		i32 actual_format;+		unsigned long nitems, bytes_after;+		unsigned char* prop_data;++		i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, net_wm_state, 0, 1024, False,+			XA_ATOM, &actual_type, &actual_format,+			&nitems, &bytes_after, &prop_data);++		if (status != Success) {+			if (prop_data != NULL)+				XFree(prop_data);++			return 0;+		}++		Atom* atoms = (Atom*) prop_data;+		u64 i;+		for (i = 0; i < nitems; ++i) {+			if (atoms[i] == net_wm_state_maximized_horz ||+				atoms[i] == net_wm_state_maximized_vert) {+				XFree(prop_data);+				return 1;+			}+		}++		return 0;+	}++	static void XGetSystemContentScale(Display* display, float* xscale, float* yscale) {+		float xdpi = 96.f, ydpi = 96.f;++#ifndef RGFW_NO_DPI+		char* rms = XResourceManagerString(display);+		XrmDatabase db = NULL;++		if (rms && db)+			db = XrmGetStringDatabase(rms);++		if (db == 0) {+			*xscale = xdpi / 96.f;+			*yscale = ydpi / 96.f;+			return;+		}++		XrmValue value;+		char* type = NULL;++		if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strncmp(type, "String", 7) == 0)+			xdpi = ydpi = atof(value.addr);+		XrmDestroyDatabase(db);+#endif++		* xscale = xdpi / 96.f;+		*yscale = ydpi / 96.f;+	}++	RGFW_monitor RGFW_XCreateMonitor(i32 screen) {+		RGFW_monitor monitor;++		Display* display = XOpenDisplay(NULL);+		+		RGFW_area size = RGFW_getScreenSize();++		monitor.rect = RGFW_RECT(0, 0, size.w, size.h);+		monitor.physW = DisplayWidthMM(display, screen);+		monitor.physH = DisplayHeightMM(display, screen);+		+		XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY);+		XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen));++		XRRCrtcInfo* ci = NULL;+		int crtc = screen;++		if (sr->ncrtc > crtc) {+			ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]);+		}+		+		if (ci == NULL) {+			float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4));+			float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4));+		+			monitor.scaleX = (float) (dpi_width) / (float) 96;+			monitor.scaleY = (float) (dpi_height) / (float) 96;+			XRRFreeScreenResources(sr);+			XCloseDisplay(display);+			return monitor;+		}+	    +		XRROutputInfo* info = XRRGetOutputInfo (display, sr, sr->outputs[screen]);+		monitor.physW = info->mm_width;+		monitor.physH = info->mm_height;++		monitor.rect.x = ci->x;+		monitor.rect.y = ci->y;+		monitor.rect.w = ci->width;+		monitor.rect.h = ci->height;+		+		float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4));+		float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4));++		monitor.scaleX = (float) (dpi_width) / (float) 96;+		monitor.scaleY = (float) (dpi_height) / (float) 96;		++		if (monitor.scaleX > 1 && monitor.scaleX < 1.1)+			monitor.scaleX = 1;++		if (monitor.scaleY > 1 && monitor.scaleY < 1.1)+			monitor.scaleY = 1;++		XRRFreeCrtcInfo(ci);+		XRRFreeScreenResources(sr);++		XCloseDisplay(display);++		return monitor;+	}++	RGFW_monitor RGFW_monitors[6];+	RGFW_monitor* RGFW_getMonitors(void) {+		size_t i;+		for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++)+			RGFW_monitors[i] = RGFW_XCreateMonitor(i);++		return RGFW_monitors;+	}++	RGFW_monitor RGFW_getPrimaryMonitor(void) {+		assert(RGFW_root != NULL);++		i32 primary = -1;+		Window root = DefaultRootWindow(RGFW_root->src.display);+		XRRScreenResources* res = XRRGetScreenResources(RGFW_root->src.display, root);++		for (int i = 0; i < res->noutput; i++) {+			XRROutputInfo* output_info = XRRGetOutputInfo(RGFW_root->src.display, res, res->outputs[i]);+			if (output_info->connection == RR_Connected && output_info->crtc) {+				XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(RGFW_root->src.display, res, output_info->crtc);+				if (crtc_info->mode != None && crtc_info->x == 0 && crtc_info->y == 0) {+					primary = i;+					XRRFreeCrtcInfo(crtc_info);+					XRRFreeOutputInfo(output_info);+					break;+				}+				XRRFreeCrtcInfo(crtc_info);+			}+			XRRFreeOutputInfo(output_info);+		}++		XRRFreeScreenResources(res);++		return RGFW_XCreateMonitor(primary);+	}++	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {+		return RGFW_XCreateMonitor(DefaultScreen(win->src.display));+	}++	#ifdef RGFW_OPENGL+	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {+		if (win == NULL)+			glXMakeCurrent((Display*) NULL, (Drawable)NULL, (GLXContext) NULL);+		else+			glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx);+	}+	#endif+++	void RGFW_window_swapBuffers(RGFW_window* win) {+		assert(win != NULL);++		/* clear the window*/+		if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+			#ifdef RGFW_OSMESA+			RGFW_OSMesa_reorganize();+			#endif+			RGFW_area area = RGFW_bufferSize;++#ifndef RGFW_X11_DONT_CONVERT_BGR+			win->src.bitmap->data = (char*) win->buffer;+			u32 x, y;+			for (y = 0; y < (u32)win->r.h; y++) {+				for (x = 0; x < (u32)win->r.w; x++) {+					u32 index = (y * 4 * area.w) + x * 4;++					u8 red = win->src.bitmap->data[index];+					win->src.bitmap->data[index] = win->buffer[index + 2];+					win->src.bitmap->data[index + 2] = red;++				}+			}+#endif	+			XPutImage(win->src.display, (Window) win->src.window, win->src.gc, win->src.bitmap, 0, 0, 0, 0, RGFW_bufferSize.w, RGFW_bufferSize.h);+#endif+		}++		if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) {+			#ifdef RGFW_EGL+					eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);+			#elif defined(RGFW_OPENGL)+					glXSwapBuffers((Display*) win->src.display, (Window) win->src.window);+			#endif+		}+	}++	#if !defined(RGFW_EGL)	+	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {+		assert(win != NULL);++		#if defined(RGFW_OPENGL)	+		((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval);+		#else+		RGFW_UNUSED(swapInterval);+		#endif+	}+	#endif+++	void RGFW_window_close(RGFW_window* win) {+		/* ungrab pointer if it was grabbed */+		if (win->_winArgs & RGFW_HOLD_MOUSE) +			XUngrabPointer(win->src.display, CurrentTime);+			+		assert(win != NULL);+#ifdef RGFW_EGL+		RGFW_closeEGL(win);+#endif++#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+		if (win->buffer != NULL) {+			XDestroyImage((XImage*) win->src.bitmap);+			XFreeGC(win->src.display, win->src.gc);+		}+#endif++		if ((Display*) win->src.display) {+#ifdef RGFW_OPENGL+			glXDestroyContext((Display*) win->src.display, win->src.ctx);+#endif++			if (win == RGFW_root)+				RGFW_root = NULL;++			if ((Drawable) win->src.window)+				XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /*!< close the window*/+			+			XCloseDisplay((Display*) win->src.display); /*!< kill the display*/+		}++#ifdef RGFW_ALLOC_DROPFILES+		{+			u32 i;+			for (i = 0; i < RGFW_MAX_DROPS; i++)+				RGFW_FREE(win->event.droppedFiles[i]);+++			RGFW_FREE(win->event.droppedFiles);+		}+#endif++		RGFW_windowsOpen--;+#if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR)+		if (X11Cursorhandle != NULL && RGFW_windowsOpen <= 0) {+			dlclose(X11Cursorhandle);++			X11Cursorhandle = NULL;+		}+#endif+#if !defined(RGFW_NO_X11_XI_PRELOAD)+		if (X11Xihandle != NULL && RGFW_windowsOpen <= 0) {+			dlclose(X11Xihandle);++			X11Xihandle = NULL;+		}+#endif++		if (RGFW_libxshape != NULL && RGFW_windowsOpen <= 0) {+			dlclose(RGFW_libxshape);+			RGFW_libxshape = NULL;+		}++		if (RGFW_windowsOpen <= 0) {+			if (RGFW_eventWait_forceStop[0] || RGFW_eventWait_forceStop[1]){+				close(RGFW_eventWait_forceStop[0]);+				close(RGFW_eventWait_forceStop[1]);+			}++			u8 i;+			for (i = 0; i < RGFW_joystickCount; i++)+				close(RGFW_joysticks[i]);+		}++		/* set cleared display / window to NULL for error checking */+		win->src.display = (Display*) 0;+		win->src.window = (Window) 0;++		RGFW_FREE(win); /*!< free collected window data */+	}+	++/* +	End of X11 linux / unix defines+*/++#endif /* RGFW_X11 */+++/* wayland or X11 defines*/+#if defined(RGFW_WAYLAND) || defined(RGFW_X11)+#include <fcntl.h>+#include <poll.h>+#include <unistd.h>+	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {+		assert(win != NULL);++#ifdef __linux__++		i32 js = open(file, O_RDONLY);++		if (js && RGFW_joystickCount < 4) {+			RGFW_joystickCount++;++			RGFW_joysticks[RGFW_joystickCount - 1] = open(file, O_RDONLY);++			u8 i;+			for (i = 0; i < 16; i++)+				RGFW_jsPressed[RGFW_joystickCount - 1][i] = 0;++		}++		else {+#ifdef RGFW_PRINT_ERRORS+			RGFW_error = 1;+			fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file);+#endif+		}++		return RGFW_joystickCount - 1;+#endif+	}+	+	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {+		assert(win != NULL);++#ifdef __linux__+		char file[15];+		sprintf(file, "/dev/input/js%i", jsNumber);++		return RGFW_registerJoystickF(win, file);+#endif+	}+	+	void RGFW_stopCheckEvents(void) { +		RGFW_eventWait_forceStop[2] = 1;+		while (1) {+			const char byte = 0;+			const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1);+			if (result == 1 || result == -1)+				break;+		}+	}++	void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {+		if (waitMS == 0)+			return;+		+		u8 i;++		if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) {+			if (pipe(RGFW_eventWait_forceStop) != -1) {+				fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0);+				fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0);+				fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0);+				fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0);+			}+		}++		struct pollfd fds[] = {+			#ifdef RGFW_WAYLAND+			{ wl_display_get_fd(win->src.display), POLLIN, 0 },+			#else+			{ ConnectionNumber(win->src.display), POLLIN, 0 },+			#endif+			{ RGFW_eventWait_forceStop[0], POLLIN, 0 },+			#ifdef __linux__ /* blank space for 4 joystick files*/+			{ -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 },  {-1, POLLIN, 0} +			#endif+		};++		u8 index = 2;+		+		#if defined(__linux__)+			for (i = 0; i < RGFW_joystickCount; i++) {+				if (RGFW_joysticks[i] == 0)+					continue;++				fds[index].fd = RGFW_joysticks[i];+				index++;+			}+		#endif+++		u64 start = RGFW_getTimeNS();++		#ifdef RGFW_WAYLAND+		while (wl_display_dispatch(win->src.display) <= 0 && waitMS >= -1) {+		#else+		while (XPending(win->src.display) == 0 && waitMS >= -1) {+		#endif+			if (poll(fds, index, waitMS) <= 0)+				break;++			if (waitMS > 0) {+				waitMS -= (RGFW_getTimeNS() - start) / 1e+6;+			}+		}++		/* drain any data in the stop request */+		if (RGFW_eventWait_forceStop[2]) {	+			char data[64];+			(void)!read(RGFW_eventWait_forceStop[0], data, sizeof(data));+			+			RGFW_eventWait_forceStop[2] = 0;+		}+	}++	u64 RGFW_getTimeNS(void) { +		struct timespec ts = { 0 };+		clock_gettime(1, &ts);+		unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;++		return nanoSeconds;+	}++	u64 RGFW_getTime(void) {+		struct timespec ts = { 0 };+		clock_gettime(1, &ts);+		unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;++		return (double)(nanoSeconds) * 1e-9;+	}+#endif /* end of wayland or X11 time defines*/+++/*++	Start of Wayland defines+++*/++#ifdef RGFW_WAYLAND+/*+Wayland TODO:+- fix RGFW_keyPressed lock state++	RGFW_windowMoved, 		the window was moved (by the user)+	RGFW_windowResized  	the window was resized (by the user), [on webASM this means the browser was resized]+	RGFW_windowRefresh	 	The window content needs to be refreshed++	RGFW_dnd 				a file has been dropped into the window+	RGFW_dnd_init++- window args:+	#define RGFW_NO_RESIZE	 			the window cannot be resized  by the user+	#define RGFW_ALLOW_DND     			the window supports drag and drop+	#define RGFW_SCALE_TO_MONITOR 			scale the window to the screen ++- other missing functions functions ("TODO wayland") (~30 functions)+- fix buffer rendering weird behavior+*/+	#include <errno.h>+	#include <unistd.h>+	#include <sys/mman.h>+	#include <xkbcommon/xkbcommon.h>+	#include <xkbcommon/xkbcommon-keysyms.h>+	#include <dirent.h>+	#include <linux/kd.h> +	#include <wayland-cursor.h>++RGFW_window* RGFW_key_win = NULL;++void RGFW_eventPipe_push(RGFW_window* win, RGFW_Event event) {+	if (win == NULL) {+		win = RGFW_key_win;++		if (win == NULL) return;+	}+	+	if (win->src.eventLen >= (i32)(sizeof(win->src.events) / sizeof(win->src.events[0])))+		return;++	win->src.events[win->src.eventLen] = event;+	win->src.eventLen += 1;+}++RGFW_Event RGFW_eventPipe_pop(RGFW_window* win) {+	RGFW_Event ev;+	ev.type = 0;+	+	if (win->src.eventLen > -1)+		win->src.eventLen -= 1;+	+	if (win->src.eventLen >= 0)  +		ev = win->src.events[win->src.eventLen];++	return ev;	+}++/* wayland global garbage (wayland bad, X11 is fine (ish) (not really)) */+#include "xdg-shell.h"+#include "xdg-decoration-unstable-v1.h"++struct xdg_wm_base *xdg_wm_base;+struct wl_compositor* RGFW_compositor = NULL;+struct wl_shm* shm = NULL;+struct wl_shell* RGFW_shell = NULL;+static struct wl_seat *seat = NULL;+static struct xkb_context *xkb_context;+static struct xkb_keymap *keymap = NULL;+static struct xkb_state *xkb_state = NULL;+enum zxdg_toplevel_decoration_v1_mode client_preferred_mode, RGFW_current_mode;+static struct zxdg_decoration_manager_v1 *decoration_manager = NULL;++struct wl_cursor_theme* RGFW_wl_cursor_theme = NULL;+struct wl_surface* RGFW_cursor_surface = NULL;+struct wl_cursor_image* RGFW_cursor_image = NULL;++static void xdg_wm_base_ping_handler(void *data,+        struct xdg_wm_base *wm_base, uint32_t serial)+{+	RGFW_UNUSED(data);+    xdg_wm_base_pong(wm_base, serial);+}++static const struct xdg_wm_base_listener xdg_wm_base_listener = {+    .ping = xdg_wm_base_ping_handler,+};++b8 RGFW_wl_configured = 0;++static void xdg_surface_configure_handler(void *data,+        struct xdg_surface *xdg_surface, uint32_t serial)+{	+	RGFW_UNUSED(data);+    xdg_surface_ack_configure(xdg_surface, serial);+	#ifdef RGFW_DEBUG+	printf("Surface configured\n");+	#endif+	RGFW_wl_configured = 1;+}++static const struct xdg_surface_listener xdg_surface_listener = {+    .configure = xdg_surface_configure_handler,+};++static void xdg_toplevel_configure_handler(void *data,+        struct xdg_toplevel *toplevel, int32_t width, int32_t height,+        struct wl_array *states)+{+	RGFW_UNUSED(data); RGFW_UNUSED(toplevel); RGFW_UNUSED(states)+    fprintf(stderr, "XDG toplevel configure: %dx%d\n", width, height);+}++static void xdg_toplevel_close_handler(void *data,+        struct xdg_toplevel *toplevel)+{+	RGFW_UNUSED(data);+	RGFW_window* win = (RGFW_window*)xdg_toplevel_get_user_data(toplevel);+	if (win == NULL)+		win = RGFW_key_win;+	+	RGFW_Event ev;+	ev.type = RGFW_quit;++	RGFW_eventPipe_push(win, ev); 	++	RGFW_windowQuitCallback(win);+}++static void shm_format_handler(void *data,+        struct wl_shm *shm, uint32_t format)+{+	RGFW_UNUSED(data); RGFW_UNUSED(shm);+    fprintf(stderr, "Format %d\n", format);+}++static const struct wl_shm_listener shm_listener = {+    .format = shm_format_handler,+};++static const struct xdg_toplevel_listener xdg_toplevel_listener = {+    .configure = xdg_toplevel_configure_handler,+    .close = xdg_toplevel_close_handler,+};++RGFW_window* RGFW_mouse_win = NULL;++static void pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {+	RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(serial); RGFW_UNUSED(surface_x); RGFW_UNUSED(surface_y);+	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);+	RGFW_mouse_win = win;++	RGFW_Event ev;+	ev.type = RGFW_mouseEnter;+	ev.point = win->event.point;++	RGFW_eventPipe_push(win, ev); 	++	RGFW_mouseNotifyCallBack(win, win->event.point, RGFW_TRUE);+}+static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) {+	RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(serial); RGFW_UNUSED(surface);+	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);+	if (RGFW_mouse_win == win)+		RGFW_mouse_win = NULL;+	+	RGFW_Event ev;+	ev.type = RGFW_mouseLeave;+	ev.point = win->event.point;+	RGFW_eventPipe_push(win, ev);++	RGFW_mouseNotifyCallBack(win,  win->event.point, RGFW_FALSE);+}+static void pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) {+	RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(x); RGFW_UNUSED(y);++	assert(RGFW_mouse_win != NULL);+	+	RGFW_Event ev;+	ev.type = RGFW_mousePosChanged;+	ev.point = RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y));+	RGFW_eventPipe_push(RGFW_mouse_win, ev);+	+	RGFW_mousePosCallback(RGFW_mouse_win, RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y)));+}+static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) {+	RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(serial);+	assert(RGFW_mouse_win != NULL);++	u32 b = (button - 0x110) + 1;++	/* flip right and middle button codes */+	if (b == 2) b = 3;+	else if (b == 3) b = 2;+	+	RGFW_mouseButtons[b].prev = RGFW_mouseButtons[b].current;+	RGFW_mouseButtons[b].current = state;++	RGFW_Event ev;+	ev.type = RGFW_mouseButtonPressed + state;+	ev.button = b;+	RGFW_eventPipe_push(RGFW_mouse_win, ev);++	RGFW_mouseButtonCallback(RGFW_mouse_win, b, 0, state);+}+static void pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) {+	RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time);  RGFW_UNUSED(axis);+	assert(RGFW_mouse_win != NULL); ++	double scroll = wl_fixed_to_double(value);++	RGFW_Event ev;+	ev.type = RGFW_mouseButtonPressed;+	ev.button = RGFW_mouseScrollUp + (scroll < 0);+	RGFW_eventPipe_push(RGFW_mouse_win, ev);++	RGFW_mouseButtonCallback(RGFW_mouse_win, RGFW_mouseScrollUp + (scroll < 0), scroll, 1);+}++void RGFW_doNothing(void) { }+static struct wl_pointer_listener pointer_listener = (struct wl_pointer_listener){&pointer_enter, &pointer_leave, &pointer_motion, &pointer_button, &pointer_axis, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing};++static void keyboard_keymap (void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size) {+	RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(format);++	char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);+	xkb_keymap_unref (keymap);+	keymap = xkb_keymap_new_from_string (xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);+	+	munmap (keymap_string, size);+	close (fd);+	xkb_state_unref (xkb_state);+	xkb_state = xkb_state_new (keymap);+}+static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { +	RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(keys);++	RGFW_key_win = (RGFW_window*)wl_surface_get_user_data(surface);++	RGFW_Event ev;+	ev.type = RGFW_focusIn;+	ev.inFocus = RGFW_TRUE;+	RGFW_key_win->event.inFocus = RGFW_TRUE;++	RGFW_eventPipe_push((RGFW_window*)RGFW_mouse_win, ev);++	RGFW_focusCallback(RGFW_key_win, RGFW_TRUE);+}+static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { +	RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial);++	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);+	if (RGFW_key_win == win)+		RGFW_key_win = NULL;	++	RGFW_Event ev;+	ev.type = RGFW_focusOut;+	ev.inFocus = RGFW_FALSE;+	win->event.inFocus = RGFW_FALSE;+	RGFW_eventPipe_push(win, ev);++	RGFW_focusCallback(win, RGFW_FALSE);+}+static void keyboard_key (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {+	RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); ++	assert(RGFW_key_win != NULL);++	xkb_keysym_t keysym = xkb_state_key_get_one_sym (xkb_state, key+8);+	char name[16];+	xkb_keysym_get_name(keysym, name, 16);++	u32 RGFW_key = RGFW_apiKeyCodeToRGFW(key);+	RGFW_keyboard[RGFW_key].prev = RGFW_keyboard[RGFW_key].current;+	RGFW_keyboard[RGFW_key].current = state;+	RGFW_Event ev;+	ev.type = RGFW_keyPressed + state;+	ev.keyCode = RGFW_key;+	strcpy(ev.keyName, name);+	ev.repeat = RGFW_isHeld(RGFW_key_win, RGFW_key);+	RGFW_eventPipe_push(RGFW_key_win, ev);+	+	RGFW_updateLockState(RGFW_key_win, xkb_keymap_mod_get_index(keymap, "Lock"), xkb_keymap_mod_get_index(keymap, "Mod2"));++	RGFW_keyCallback(RGFW_key_win, RGFW_key, name, RGFW_key_win->event.lockState, state);+}+static void keyboard_modifiers (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {+	RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); +	xkb_state_update_mask (xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);+}+static struct wl_keyboard_listener keyboard_listener = {&keyboard_keymap, &keyboard_enter, &keyboard_leave, &keyboard_key, &keyboard_modifiers, (void*)&RGFW_doNothing};++static void seat_capabilities (void *data, struct wl_seat *seat, uint32_t capabilities) {+	RGFW_UNUSED(data);++	if (capabilities & WL_SEAT_CAPABILITY_POINTER) {+		struct wl_pointer *pointer = wl_seat_get_pointer (seat);+		wl_pointer_add_listener (pointer, &pointer_listener, NULL);+	}+	if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {+		struct wl_keyboard *keyboard = wl_seat_get_keyboard (seat);+		wl_keyboard_add_listener (keyboard, &keyboard_listener, NULL);+	}+}+static struct wl_seat_listener seat_listener = {&seat_capabilities, (void*)&RGFW_doNothing};++static void wl_global_registry_handler(void *data,+		struct wl_registry *registry, uint32_t id, const char *interface,+		uint32_t version)+{+	RGFW_UNUSED(data); RGFW_UNUSED(version);++    if (strcmp(interface, "wl_compositor") == 0) {+		RGFW_compositor = wl_registry_bind(registry,+			id, &wl_compositor_interface, 4);+	} else if (strcmp(interface, "xdg_wm_base") == 0) {+	xdg_wm_base = wl_registry_bind(registry,+		id, &xdg_wm_base_interface, 1);+	} else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) {+		decoration_manager = wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1);+    } else if (strcmp(interface, "wl_shm") == 0) {+        shm = wl_registry_bind(registry,+            id, &wl_shm_interface, 1);+        wl_shm_add_listener(shm, &shm_listener, NULL);+	} else if (strcmp(interface,"wl_seat") == 0) {+		seat = wl_registry_bind(registry, id, &wl_seat_interface, 1);+		wl_seat_add_listener(seat, &seat_listener, NULL);+	}++	else {+		#ifdef RGFW_DEBUG+		printf("did not register %s\n", interface);+		return;+		#endif+	}++		#ifdef RGFW_DEBUG+		printf("registered %s\n", interface);+		#endif+}++static void wl_global_registry_remove(void *data, struct wl_registry *registry, uint32_t name) { RGFW_UNUSED(data); RGFW_UNUSED(registry); RGFW_UNUSED(name); }+static const struct wl_registry_listener registry_listener = {+	.global = wl_global_registry_handler,+	.global_remove = wl_global_registry_remove,+};++static const char *get_mode_name(enum zxdg_toplevel_decoration_v1_mode mode) {+	switch (mode) {+	case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE:+		return "client-side decorations";+	case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE:+		return "server-side decorations";+	}+	abort();+}+++static void decoration_handle_configure(void *data,+		struct zxdg_toplevel_decoration_v1 *decoration,+		enum zxdg_toplevel_decoration_v1_mode mode) {+	RGFW_UNUSED(data); RGFW_UNUSED(decoration);+	printf("Using %s\n", get_mode_name(mode));+	RGFW_current_mode = mode;+}++static const struct zxdg_toplevel_decoration_v1_listener decoration_listener = {+	.configure = decoration_handle_configure,+};++static void randname(char *buf) {+	struct timespec ts;+	clock_gettime(CLOCK_REALTIME, &ts);+	long r = ts.tv_nsec;+	for (int i = 0; i < 6; ++i) {+		buf[i] = 'A'+(r&15)+(r&16)*2;+		r >>= 5;+	}+}++static int anonymous_shm_open(void) {+	char name[] = "/RGFW-wayland-XXXXXX";+	int retries = 100;++	do {+		randname(name + strlen(name) - 6);++		--retries;+		// shm_open guarantees that O_CLOEXEC is set+		int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);+		if (fd >= 0) {+			shm_unlink(name);+			return fd;+		}+	} while (retries > 0 && errno == EEXIST);++	return -1;+}++int create_shm_file(off_t size) {+	int fd = anonymous_shm_open();+	if (fd < 0) {+		return fd;+	}++	if (ftruncate(fd, size) < 0) {+		close(fd);+		return -1;+	}++	return fd;+}++static void wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) {+	#ifdef RGFW_BUFFER+		RGFW_window* win = (RGFW_window*)data;+		if ((win->_winArgs & RGFW_NO_CPU_RENDER))+			return;	+		+		#ifndef RGFW_X11_DONT_CONVERT_BGR+			u32 x, y;+			for (y = 0; y < (u32)win->r.h; y++) {+				for (x = 0; x < (u32)win->r.w; x++) {+					u32 index = (y * 4 * win->r.w) + x * 4;++					u8 red = win->buffer[index];+					win->buffer[index] = win->buffer[index + 2];+					win->buffer[index + 2] = red;++				}+			}+		#endif	+	+		wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0);+		wl_surface_damage_buffer(win->src.surface, 0, 0, win->r.w, win->r.h);+		wl_surface_commit(win->src.surface);+	#endif+}++static const struct wl_callback_listener wl_surface_frame_listener = {+	.done = wl_surface_frame_done,+};+++	/* normal wayland RGFW stuff */+	+	RGFW_area RGFW_getScreenSize(void) {+		RGFW_area area = {};++		if (RGFW_root != NULL)+			/* this isn't right but it's here for buffers */+			area = RGFW_AREA(RGFW_root->r.w, RGFW_root->r.h);+		+		/* TODO wayland */+		return area;+	}+	+	void RGFW_releaseCursor(RGFW_window* win) {+		RGFW_UNUSED(win);+	}++	void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {+		RGFW_UNUSED(win); RGFW_UNUSED(r);++		/* TODO wayland */+	}+++	RGFWDEF void RGFW_init_buffer(RGFW_window* win);+	void RGFW_init_buffer(RGFW_window* win) {+		#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)	+			size_t size = win->r.w * win->r.h * 4;+			int fd = create_shm_file(size);+			if (fd < 0) {+				fprintf(stderr, "Failed to create a buffer. size: %ld\n", size);+				exit(1);+			}++			win->buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);+			if (win->buffer == MAP_FAILED) {+				fprintf(stderr, "mmap failed!\n");+				close(fd);+				exit(1);+			}++			struct wl_shm_pool* pool = wl_shm_create_pool(shm, fd, size);+			win->src.wl_buffer = wl_shm_pool_create_buffer(pool, 0, win->r.w, win->r.h, win->r.w * 4,+				WL_SHM_FORMAT_ARGB8888);+			wl_shm_pool_destroy(pool);++			close(fd);+			+			wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0);+			wl_surface_commit(win->src.surface);++			u8 color[] = {0x00, 0x00, 0x00, 0xFF};++			size_t i;+			for (i = 0; i < size; i += 4) {+				memcpy(&win->buffer[i], color, 4);+			}+	+			#if defined(RGFW_OSMESA)+					win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);+					OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);+			#endif+		#else+		RGFW_UNUSED(win);+		#endif+	}+   ++	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {+		RGFW_window* win = RGFW_window_basic_init(rect, args);+		+		fprintf(stderr, "Warning: RGFW Wayland support is experimental\n");+		+		win->src.display = wl_display_connect(NULL);+		if (win->src.display == NULL) {+			#ifdef RGFW_DEBUG+				fprintf(stderr, "Failed to load Wayland display\n");+			#endif+			return NULL;+		}+		+		struct wl_registry *registry = wl_display_get_registry(win->src.display);+		wl_registry_add_listener(registry, &registry_listener, NULL);+			+		wl_display_dispatch(win->src.display);+		wl_display_roundtrip(win->src.display);++		if (RGFW_compositor == NULL) {+			#ifdef RGFW_DEBUG+				fprintf(stderr, "Can't find compositor.\n");+			#endif+			+			return NULL;+		}+		+		if (RGFW_wl_cursor_theme == NULL) {+			RGFW_wl_cursor_theme = wl_cursor_theme_load(NULL, 24, shm);+			RGFW_cursor_surface = wl_compositor_create_surface(RGFW_compositor); +			+			struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, "left_ptr");+			RGFW_cursor_image = cursor->images[0];+			struct wl_buffer* cursor_buffer	= wl_cursor_image_get_buffer(RGFW_cursor_image);++			wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);+			wl_surface_commit(RGFW_cursor_surface); +		}++		if (RGFW_root == NULL)+			xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL);+		+		xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);++		win->src.surface = wl_compositor_create_surface(RGFW_compositor);+		wl_surface_set_user_data(win->src.surface, win);++		win->src.xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, win->src.surface);+		xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, NULL);+	+		xdg_wm_base_set_user_data(xdg_wm_base, win);++		win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface);+		xdg_toplevel_set_user_data(win->src.xdg_toplevel, win);+		xdg_toplevel_set_title(win->src.xdg_toplevel, name);+		xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, NULL);++		xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h);+		+		if (!(args & RGFW_NO_BORDER)) {+			win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(+						decoration_manager, win->src.xdg_toplevel);+		}++		if (args & RGFW_CENTER) {+			RGFW_area screenR = RGFW_getScreenSize();+			RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));+		}++		if (args & RGFW_OPENGL_SOFTWARE)+			setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);++		wl_display_roundtrip(win->src.display);++		wl_surface_commit(win->src.surface);+		+		/* wait for the surface to be configured */+		while (wl_display_dispatch(win->src.display) != -1 && !RGFW_wl_configured) { }+		+		+		#ifdef RGFW_OPENGL+			if ((args & RGFW_NO_INIT_API) == 0) {+				win->src.window = wl_egl_window_create(win->src.surface, win->r.w, win->r.h);+				RGFW_createOpenGLContext(win);+			}+		#endif	++		RGFW_init_buffer(win);++		struct wl_callback* callback = wl_surface_frame(win->src.surface);+   		wl_callback_add_listener(callback, &wl_surface_frame_listener, win);	+		wl_surface_commit(win->src.surface);++		if (args & RGFW_HIDE_MOUSE) {+			RGFW_window_showMouse(win, 0);+		}+		+		if (RGFW_root == NULL) {+			RGFW_root = win;+		}+		+		win->src.eventIndex = 0;+		win->src.eventLen = 0;+		+		return win;+	}++	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {+		if (win->_winArgs & RGFW_WINDOW_HIDE)+			return NULL;++		if (win->src.eventIndex == 0) {+			if (wl_display_roundtrip(win->src.display) == -1) {+				return NULL;+			}+			RGFW_resetKey();+		}++		#ifdef __linux__+			RGFW_Event* event = RGFW_linux_updateJoystick(win);+			if (event != NULL)+				return event;+		#endif+		+		if (win->src.eventLen == 0) {+				return NULL;+		}++		RGFW_Event ev = RGFW_eventPipe_pop(win);+		+		if (ev.type ==  0 || win->event.type == RGFW_quit) {+			return NULL;+		}+        +		ev.frameTime = win->event.frameTime;+        ev.frameTime2 = win->event.frameTime2;+        ev.inFocus = win->event.inFocus;+        win->event = ev;+		+		return &win->event;+	}+++	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {+		RGFW_UNUSED(win); RGFW_UNUSED(a);++		/* TODO wayland */+	}++	void RGFW_window_move(RGFW_window* win, RGFW_point v) {+		RGFW_UNUSED(win); RGFW_UNUSED(v);++		/* TODO wayland */+	}++	void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) {+		RGFW_UNUSED(win); RGFW_UNUSED(src); RGFW_UNUSED(a); RGFW_UNUSED(channels)+		/* TODO wayland */+	}++	void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {+		RGFW_UNUSED(win); RGFW_UNUSED(v);++		/* TODO wayland */+	}++	void RGFW_window_showMouse(RGFW_window* win, i8 show) {+		RGFW_UNUSED(win);++		if (show) {++		}+		else {+			+		}++		/* TODO wayland */+	}++	b8 RGFW_window_isMaximized(RGFW_window* win) {+		RGFW_UNUSED(win);+		/* TODO wayland */+		return 0;+	}++	b8 RGFW_window_isMinimized(RGFW_window* win) {+		RGFW_UNUSED(win);+		/* TODO wayland */+		return 0;+	}++	b8 RGFW_window_isHidden(RGFW_window* win) {+		RGFW_UNUSED(win);+		/* TODO wayland */+		return 0;+	}++	b8 RGFW_window_isFullscreen(RGFW_window* win) {+		RGFW_UNUSED(win);+		/* TODO wayland */+		return 0;+	}++	RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {+		RGFW_UNUSED(win);+		/* TODO wayland */+		return RGFW_POINT(0, 0);+	}+			+	RGFW_point RGFW_getGlobalMousePoint(void) {+		/* TODO wayland */+		return RGFW_POINT(0, 0);+	}+			+	void RGFW_window_show(RGFW_window* win) {+		//wl_surface_attach(win->src.surface, win->rc., 0, 0);+        wl_surface_commit(win->src.surface);+		+		if (win->_winArgs & RGFW_WINDOW_HIDE)+			win->_winArgs ^= RGFW_WINDOW_HIDE;+	}+		+	void RGFW_window_hide(RGFW_window* win) {+		wl_surface_attach(win->src.surface, NULL, 0, 0);+        wl_surface_commit(win->src.surface);+		win->_winArgs |= RGFW_WINDOW_HIDE;+	}+		+	void RGFW_window_setMouseDefault(RGFW_window* win) {+		RGFW_UNUSED(win);+	+		RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL);+	}+		+	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {+		RGFW_UNUSED(win);+		+		static const char* iconStrings[] = { "left_ptr", "left_ptr", "text", "cross", "pointer", "e-resize", "n-resize", "nw-resize", "ne-resize", "all-resize", "not-allowed" };++		struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]);+		RGFW_cursor_image = cursor->images[0];+		struct wl_buffer* cursor_buffer	= wl_cursor_image_get_buffer(RGFW_cursor_image);++		wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);+		wl_surface_commit(RGFW_cursor_surface); +	}+		+	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {+		RGFW_UNUSED(win); RGFW_UNUSED(image); RGFW_UNUSED(a); RGFW_UNUSED(channels)+		//struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]);+		//RGFW_cursor_image = image;+		struct wl_buffer* cursor_buffer	= wl_cursor_image_get_buffer(RGFW_cursor_image);++		wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);+		wl_surface_commit(RGFW_cursor_surface); +	}+		+	void RGFW_window_setName(RGFW_window* win, char* name) {+		xdg_toplevel_set_title(win->src.xdg_toplevel, name);+	}+		+	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {+		RGFW_UNUSED(win); RGFW_UNUSED(passthrough);++	/* TODO wayland */+	}+		+	void RGFW_window_setBorder(RGFW_window* win, b8 border) {+		RGFW_UNUSED(win); RGFW_UNUSED(border);++	/* TODO wayland */+	}+		+	void RGFW_window_restore(RGFW_window* win) {+		RGFW_UNUSED(win);++	/* TODO wayland */+	}+		+	void RGFW_window_minimize(RGFW_window* win) {+		RGFW_UNUSED(win);++	/* TODO wayland */+	}+		+	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {+		RGFW_UNUSED(win); RGFW_UNUSED(a);++	/* TODO wayland */+	}+		+	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {+		RGFW_UNUSED(win); RGFW_UNUSED(a);++	/* TODO wayland */+	}++	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {+		RGFW_monitor m = {};+		RGFW_UNUSED(win);+		RGFW_UNUSED(m);+		/* TODO wayland */++		return m;+	}+++	#ifndef RGFW_EGL+	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); }+	#endif++	void RGFW_window_swapBuffers(RGFW_window* win) {+		assert(win != NULL);++		/* clear the window*/+		#ifdef RGFW_BUFFER	+			wl_surface_frame_done(win, NULL, 0);+			if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) +		#endif+		{+		#ifdef RGFW_OPENGL+			eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);+		#endif+		}+		+		wl_display_flush(win->src.display);+	}++	void RGFW_window_close(RGFW_window* win) {+		#ifdef RGFW_EGL+			RGFW_closeEGL(win);+		#endif++		if (RGFW_root == win) {+			RGFW_root = NULL;+		}++		xdg_toplevel_destroy(win->src.xdg_toplevel);+		xdg_surface_destroy(win->src.xdg_surface);+		wl_surface_destroy(win->src.surface);++		#ifdef RGFW_BUFFER+		wl_buffer_destroy(win->src.wl_buffer);+		#endif+		+		wl_display_disconnect(win->src.display);+		RGFW_FREE(win);+	}++	RGFW_monitor RGFW_getPrimaryMonitor(void) {+		/* TODO wayland */++		return (RGFW_monitor){};+	}+						+	RGFW_monitor* RGFW_getMonitors(void) {+		/* TODO wayland */++		return NULL;+	}++	void RGFW_writeClipboard(const char* text, u32 textLen) {+		RGFW_UNUSED(text); RGFW_UNUSED(textLen);++		/* TODO wayland */+	}++	char* RGFW_readClipboard(size_t* size) {+		RGFW_UNUSED(size);++		/* TODO wayland */++		return NULL;+	}+#endif /* RGFW_WAYLAND */++/* +	End of Wayland defines+*/+++/*++	Start of Windows defines+++*/++#ifdef RGFW_WINDOWS+	#define WIN32_LEAN_AND_MEAN+	#define OEMRESOURCE+	#include <windows.h>+	+	#include <processthreadsapi.h>+	#include <wchar.h>+	#include <locale.h>+	#include <windowsx.h>+	#include <shellapi.h>+	#include <shellscalingapi.h>++	#include <winuser.h>++	__declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar,  LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar);+	+	#ifndef RGFW_NO_XINPUT+	typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);+	PFN_XInputGetState XInputGetStateSRC = NULL;+	#define XInputGetState XInputGetStateSRC++	typedef DWORD (WINAPI * PFN_XInputGetKeystroke)(DWORD, DWORD, PXINPUT_KEYSTROKE);+	PFN_XInputGetKeystroke XInputGetKeystrokeSRC = NULL;+	#define XInputGetKeystroke XInputGetKeystrokeSRC++	static HMODULE RGFW_XInput_dll = NULL;+	#endif++	u32 RGFW_mouseIconSrc[] = {OCR_NORMAL, OCR_NORMAL, OCR_IBEAM, OCR_CROSS, OCR_HAND, OCR_SIZEWE, OCR_SIZENS, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEALL, OCR_NO};++	char* createUTF8FromWideStringWin32(const WCHAR* source);++#define GL_FRONT				0x0404+#define GL_BACK					0x0405+#define GL_LEFT					0x0406+#define GL_RIGHT				0x0407++#if defined(RGFW_OSMESA) && defined(RGFW_LINK_OSMESA)++	typedef void (GLAPIENTRY* PFN_OSMesaDestroyContext)(OSMesaContext);+	typedef i32(GLAPIENTRY* PFN_OSMesaMakeCurrent)(OSMesaContext, void*, int, int, int);+	typedef OSMesaContext(GLAPIENTRY* PFN_OSMesaCreateContext)(GLenum, OSMesaContext);++	PFN_OSMesaMakeCurrent OSMesaMakeCurrentSource;+	PFN_OSMesaCreateContext OSMesaCreateContextSource;+	PFN_OSMesaDestroyContext OSMesaDestroyContextSource;++#define OSMesaCreateContext OSMesaCreateContextSource+#define OSMesaMakeCurrent OSMesaMakeCurrentSource+#define OSMesaDestroyContext OSMesaDestroyContextSource+#endif++	typedef int (*PFN_wglGetSwapIntervalEXT)(void);+	PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL;+#define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc+++	void* RGFWjoystickApi = NULL;++	/* these two wgl functions need to be preloaded */+	typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList);+	PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;++	/* defines for creating ARB attributes */+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000+#define WGL_CONTEXT_MAJOR_VERSION_ARB             0x2091+#define WGL_CONTEXT_MINOR_VERSION_ARB             0x2092+#define WGL_DRAW_TO_WINDOW_ARB                    0x2001+#define WGL_ACCELERATION_ARB                      0x2003+#define WGL_NO_ACCELERATION_ARB 0x2025+#define WGL_DOUBLE_BUFFER_ARB                     0x2011+#define WGL_COLOR_BITS_ARB                        0x2014+#define WGL_RED_BITS_ARB 0x2015+#define WGL_RED_SHIFT_ARB 0x2016+#define WGL_GREEN_BITS_ARB 0x2017+#define WGL_GREEN_SHIFT_ARB 0x2018+#define WGL_BLUE_BITS_ARB 0x2019+#define WGL_BLUE_SHIFT_ARB 0x201a+#define WGL_ALPHA_BITS_ARB 0x201b+#define WGL_ALPHA_SHIFT_ARB 0x201c+#define WGL_ACCUM_BITS_ARB 0x201d+#define WGL_ACCUM_RED_BITS_ARB 0x201e+#define WGL_ACCUM_GREEN_BITS_ARB 0x201f+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021+#define WGL_DEPTH_BITS_ARB 0x2022+#define WGL_AUX_BUFFERS_ARB 0x2024+#define WGL_STEREO_ARB 0x2012+#define WGL_DEPTH_BITS_ARB                        0x2022+#define WGL_STENCIL_BITS_ARB 					  0x2023+#define WGL_FULL_ACCELERATION_ARB                 0x2027+#define WGL_CONTEXT_FLAGS_ARB                     0x2094+#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002+#define WGL_SAMPLE_BUFFERS_ARB               0x2041+#define WGL_SAMPLES_ARB 0x2042+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9++#ifndef RGFW_EGL+static HMODULE wglinstance = NULL;+#endif++#ifdef RGFW_WGL_LOAD+	typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC);+	typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC);+	typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR);+	typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC);+	typedef HDC(WINAPI* PFN_wglGetCurrentDC)();+	typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)();++	PFN_wglCreateContext wglCreateContextSRC;+	PFN_wglDeleteContext wglDeleteContextSRC;+	PFN_wglGetProcAddress wglGetProcAddressSRC;+	PFN_wglMakeCurrent wglMakeCurrentSRC;+	PFN_wglGetCurrentDC wglGetCurrentDCSRC;+	PFN_wglGetCurrentContext wglGetCurrentContextSRC;++	#define wglCreateContext wglCreateContextSRC+	#define wglDeleteContext wglDeleteContextSRC+	#define wglGetProcAddress wglGetProcAddressSRC+	#define wglMakeCurrent wglMakeCurrentSRC++	#define wglGetCurrentDC wglGetCurrentDCSRC+	#define wglGetCurrentContext wglGetCurrentContextSRC+#endif++#ifdef RGFW_OPENGL+	void* RGFW_getProcAddress(const char* procname) { +		void* proc = (void*) wglGetProcAddress(procname);+		if (proc)+			return proc;++		return (void*) GetProcAddress(wglinstance, procname); +	}++	typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);+	static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;+#endif++	RGFW_window RGFW_eventWindow;++	LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {+		switch (message) {+		case WM_MOVE:+			RGFW_eventWindow.r.x = LOWORD(lParam);+			RGFW_eventWindow.r.y = HIWORD(lParam);+			RGFW_eventWindow.src.window = hWnd;+			return DefWindowProcA(hWnd, message, wParam, lParam);+		case WM_SIZE:+			RGFW_eventWindow.r.w = LOWORD(lParam);+			RGFW_eventWindow.r.h = HIWORD(lParam);+			RGFW_eventWindow.src.window = hWnd;+			return DefWindowProcA(hWnd, message, wParam, lParam); // Call DefWindowProc after handling+		default:+			return DefWindowProcA(hWnd, message, wParam, lParam);+		}+	}+	+	#ifndef RGFW_NO_DPI+	static HMODULE RGFW_Shcore_dll = NULL;+	typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);+	PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL;+	#define GetDpiForMonitor GetDpiForMonitorSRC+	#endif++	__declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod);+	+	#ifndef RGFW_NO_XINPUT+	void RGFW_loadXInput(void) {+		u32 i;+		static const char* names[] = { +			"xinput1_4.dll",+			"xinput1_3.dll",+			"xinput9_1_0.dll",+			"xinput1_2.dll",+			"xinput1_1.dll"+		};++		for (i = 0; i < sizeof(names) / sizeof(const char*);  i++) {+			RGFW_XInput_dll = LoadLibraryA(names[i]);++			if (RGFW_XInput_dll) {+				XInputGetStateSRC = (PFN_XInputGetState)(void*)GetProcAddress(RGFW_XInput_dll, "XInputGetState");+			+				if (XInputGetStateSRC == NULL)+					printf("Failed to load XInputGetState");+			}+		}+	}+	#endif++	RGFWDEF void RGFW_init_buffer(RGFW_window* win);+	void RGFW_init_buffer(RGFW_window* win) {+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+	if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)+		RGFW_bufferSize = RGFW_getScreenSize();+	+	BITMAPV5HEADER bi = { 0 };+	ZeroMemory(&bi, sizeof(bi));+	bi.bV5Size = sizeof(bi);+	bi.bV5Width = RGFW_bufferSize.w;+	bi.bV5Height = -((LONG) RGFW_bufferSize.h);+	bi.bV5Planes = 1;+	bi.bV5BitCount = 32;+	bi.bV5Compression = BI_BITFIELDS;+	bi.bV5BlueMask = 0x00ff0000;+	bi.bV5GreenMask = 0x0000ff00;+	bi.bV5RedMask = 0x000000ff;+	bi.bV5AlphaMask = 0xff000000;++	win->src.bitmap = CreateDIBSection(win->src.hdc,+		(BITMAPINFO*) &bi,+		DIB_RGB_COLORS,+		(void**) &win->buffer,+		NULL,+		(DWORD) 0);+	+	win->src.hdcMem = CreateCompatibleDC(win->src.hdc);++	#if defined(RGFW_OSMESA)+	win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);+	OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);+	#endif+#else+RGFW_UNUSED(win); /*!< if buffer rendering is not being used */+#endif+	}++	void RGFW_window_setDND(RGFW_window* win, b8 allow) {+		DragAcceptFiles(win->src.window, allow);+	}++	void RGFW_releaseCursor(RGFW_window* win) {+		RGFW_UNUSED(win);+		ClipCursor(NULL);+    	const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL };+    	RegisterRawInputDevices(&id, 1, sizeof(id));	+	}++	void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) {+		RGFW_UNUSED(win); RGFW_UNUSED(rect);++		RECT clipRect;+		GetClientRect(win->src.window, &clipRect);+		ClientToScreen(win->src.window, (POINT*) &clipRect.left);+		ClientToScreen(win->src.window, (POINT*) &clipRect.right);+		ClipCursor(&clipRect);++	    const RAWINPUTDEVICE id = { 0x01, 0x02, 0, win->src.window };+		RegisterRawInputDevices(&id, 1, sizeof(id));+	}++	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {+		#ifndef RGFW_NO_XINPUT+		if (RGFW_XInput_dll == NULL)+			RGFW_loadXInput();+		#endif++		#ifndef RGFW_NO_DPI+		if (RGFW_Shcore_dll == NULL) {+			RGFW_Shcore_dll = LoadLibraryA("shcore.dll");+			GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor");+			SetProcessDPIAware();+		}+		#endif++		if (wglinstance == NULL) {+			wglinstance = LoadLibraryA("opengl32.dll");+#ifdef RGFW_WGL_LOAD+			wglCreateContextSRC = (PFN_wglCreateContext) GetProcAddress(wglinstance, "wglCreateContext");+			wglDeleteContextSRC = (PFN_wglDeleteContext) GetProcAddress(wglinstance, "wglDeleteContext");+			wglGetProcAddressSRC = (PFN_wglGetProcAddress) GetProcAddress(wglinstance, "wglGetProcAddress");+			wglMakeCurrentSRC = (PFN_wglMakeCurrent) GetProcAddress(wglinstance, "wglMakeCurrent");+			wglGetCurrentDCSRC = (PFN_wglGetCurrentDC) GetProcAddress(wglinstance, "wglGetCurrentDC");+			wglGetCurrentContextSRC = (PFN_wglGetCurrentContext) GetProcAddress(wglinstance, "wglGetCurrentContext");+#endif+		}+	+		if (name[0] == 0) name = (char*) " ";++		RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);+		RGFW_eventWindow.src.window = NULL;++		RGFW_window* win = RGFW_window_basic_init(rect, args);++		win->src.maxSize = RGFW_AREA(0, 0);+		win->src.minSize = RGFW_AREA(0, 0);+++		HINSTANCE inh = GetModuleHandleA(NULL);++		#ifndef __cplusplus+		WNDCLASSA Class = { 0 }; /*!< Setup the Window class. */+		#else+		WNDCLASSA Class = { };+		#endif++		if (RGFW_className == NULL)+			RGFW_className = (char*)name;++		Class.lpszClassName = RGFW_className;+		Class.hInstance = inh;+		Class.hCursor = LoadCursor(NULL, IDC_ARROW);+		Class.lpfnWndProc = WndProc;++		RegisterClassA(&Class);++		DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;++		RECT windowRect, clientRect;++		if (!(args & RGFW_NO_BORDER)) {+			window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX;++			if (!(args & RGFW_NO_RESIZE))+				window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;+		} else+			window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX;++		HWND dummyWin = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h, 0, 0, inh, 0);++		GetWindowRect(dummyWin, &windowRect);+		GetClientRect(dummyWin, &clientRect);++		win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);+		win->src.window = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h + win->src.hOffset, 0, 0, inh, 0);++		if (args & RGFW_ALLOW_DND) {+			win->_winArgs |= RGFW_ALLOW_DND;+			RGFW_window_setDND(win, 1);+		}+		win->src.hdc = GetDC(win->src.window);++		if ((args & RGFW_NO_INIT_API) == 0) {+#ifdef RGFW_DIRECTX+		assert(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0);++		if (FAILED(RGFW_dxInfo.pFactory->lpVtbl->EnumAdapters(RGFW_dxInfo.pFactory, 0, &RGFW_dxInfo.pAdapter))) {+			fprintf(stderr, "Failed to enumerate DXGI adapters\n");+			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);+			return NULL;+		}++		D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };++		if (FAILED(D3D11CreateDevice(RGFW_dxInfo.pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, featureLevels, 1, D3D11_SDK_VERSION, &RGFW_dxInfo.pDevice, NULL, &RGFW_dxInfo.pDeviceContext))) {+			fprintf(stderr, "Failed to create Direct3D device\n");+			RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);+			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);+			return NULL;+		}++		DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };+		swapChainDesc.BufferCount = 1;+		swapChainDesc.BufferDesc.Width = win->r.w;+		swapChainDesc.BufferDesc.Height = win->r.h;+		swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;+		swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;+		swapChainDesc.OutputWindow = win->src.window;+		swapChainDesc.SampleDesc.Count = 1;+		swapChainDesc.SampleDesc.Quality = 0;+		swapChainDesc.Windowed = TRUE;+		RGFW_dxInfo.pFactory->lpVtbl->CreateSwapChain(RGFW_dxInfo.pFactory, (IUnknown*) RGFW_dxInfo.pDevice, &swapChainDesc, &win->src.swapchain);++		ID3D11Texture2D* pBackBuffer;+		win->src.swapchain->lpVtbl->GetBuffer(win->src.swapchain, 0, &__uuidof(ID3D11Texture2D), (LPVOID*) &pBackBuffer);+		RGFW_dxInfo.pDevice->lpVtbl->CreateRenderTargetView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pBackBuffer, NULL, &win->src.renderTargetView);+		pBackBuffer->lpVtbl->Release(pBackBuffer);++		D3D11_TEXTURE2D_DESC depthStencilDesc = { 0 };+		depthStencilDesc.Width = win->r.w;+		depthStencilDesc.Height = win->r.h;+		depthStencilDesc.MipLevels = 1;+		depthStencilDesc.ArraySize = 1;+		depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;+		depthStencilDesc.SampleDesc.Count = 1;+		depthStencilDesc.SampleDesc.Quality = 0;+		depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;+		depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;++		ID3D11Texture2D* pDepthStencilTexture = NULL;+		RGFW_dxInfo.pDevice->lpVtbl->CreateTexture2D(RGFW_dxInfo.pDevice, &depthStencilDesc, NULL, &pDepthStencilTexture);++		D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = { 0 };+		depthStencilViewDesc.Format = depthStencilDesc.Format;+		depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;+		depthStencilViewDesc.Texture2D.MipSlice = 0;++		RGFW_dxInfo.pDevice->lpVtbl->CreateDepthStencilView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pDepthStencilTexture, &depthStencilViewDesc, &win->src.pDepthStencilView);++		pDepthStencilTexture->lpVtbl->Release(pDepthStencilTexture);++		RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, win->src.pDepthStencilView);+#endif++#ifdef RGFW_OPENGL +		HDC dummy_dc = GetDC(dummyWin);+        +        u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; +        +        //if (RGFW_DOUBLE_BUFFER)    +             pfd_flags |= PFD_DOUBLEBUFFER;+		+        PIXELFORMATDESCRIPTOR pfd = {+			sizeof(pfd),+			1, /* version */+			pfd_flags,+		    PFD_TYPE_RGBA, /* ipixel type */+			24, /* color bits */+			0, 0, 0, 0, 0, 0,+			8, /* alpha bits */+			0, 0, 0, 0, 0, 0,+			32, /* depth bits */+			8, /* stencil bits */ +			0,+			PFD_MAIN_PLANE, /* Layer type */+			0, 0, 0, 0+		};++		int pixel_format = ChoosePixelFormat(dummy_dc, &pfd);+		SetPixelFormat(dummy_dc, pixel_format, &pfd);++		HGLRC dummy_context = wglCreateContext(dummy_dc);+		wglMakeCurrent(dummy_dc, dummy_context);++		if (wglChoosePixelFormatARB == NULL) {+			wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) (void*) wglGetProcAddress("wglCreateContextAttribsARB");+			wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) (void*)wglGetProcAddress("wglChoosePixelFormatARB");+		}++		wglMakeCurrent(dummy_dc, 0);+		wglDeleteContext(dummy_context);+		ReleaseDC(dummyWin, dummy_dc);+		+		/* try to create the pixel format we want for opengl and then try to create an opengl context for the specified version */ +		if (wglCreateContextAttribsARB != NULL) {+			PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};++			if (args & RGFW_OPENGL_SOFTWARE)+				pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED;++			if (wglChoosePixelFormatARB != NULL) {+				i32* pixel_format_attribs = (i32*)RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);++				int pixel_format;+				UINT num_formats;+				wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats);+				if (!num_formats) {+					printf("Failed to create a pixel format for WGL.\n");+				}++				DescribePixelFormat(win->src.hdc, pixel_format, sizeof(pfd), &pfd);+				if (!SetPixelFormat(win->src.hdc, pixel_format, &pfd)) {+					printf("Failed to set the WGL pixel format.\n");+				}+			}+			+			/* create opengl/WGL context for the specified version */ +			u32 index = 0;+			i32 attribs[40];++			if (RGFW_profile == RGFW_GL_CORE) {+				SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB);+			}+			else {+				SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);+			}+			+			if (RGFW_majorVersion || RGFW_minorVersion) {+				SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);+				SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);+			}++			SET_ATTRIB(0, 0);++			win->src.ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs);+		} else { /* fall back to a default context (probably opengl 2 or something) */+			fprintf(stderr, "Failed to create an accelerated OpenGL Context\n");++			int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd);+			SetPixelFormat(win->src.hdc, pixel_format, &pfd);++			win->src.ctx = wglCreateContext(win->src.hdc);+		}+		+		wglMakeCurrent(win->src.hdc, win->src.ctx);+#endif+	}++#ifdef RGFW_OSMESA+#ifdef RGFW_LINK_OSM ESA+		OSMesaMakeCurrentSource = (PFN_OSMesaMakeCurrent) GetProcAddress(win->src.hdc, "OSMesaMakeCurrent");+		OSMesaCreateContextSource = (PFN_OSMesaCreateContext) GetProcAddress(win->src.hdc, "OSMesaCreateContext");+		OSMesaDestroyContextSource = (PFN_OSMesaDestroyContext) GetProcAddress(win->src.hdc, "OSMesaDestroyContext");+#endif+#endif++#ifdef RGFW_OPENGL+		if ((args & RGFW_NO_INIT_API) == 0) {+			ReleaseDC(win->src.window, win->src.hdc);+			win->src.hdc = GetDC(win->src.window);+			wglMakeCurrent(win->src.hdc, win->src.ctx);+		}+#endif++		DestroyWindow(dummyWin);+		RGFW_init_buffer(win);+++		#ifndef RGFW_NO_MONITOR+		if (args & RGFW_SCALE_TO_MONITOR)+			RGFW_window_scaleToMonitor(win);+		#endif+	+		if (args & RGFW_CENTER) {+			RGFW_area screenR = RGFW_getScreenSize();+			RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));+		}++#ifdef RGFW_EGL+		if ((args & RGFW_NO_INIT_API) == 0)+			RGFW_createOpenGLContext(win);+#endif++		if (args & RGFW_HIDE_MOUSE)+			RGFW_window_showMouse(win, 0);++		if (args & RGFW_TRANSPARENT_WINDOW) {+			SetWindowLong(win->src.window, GWL_EXSTYLE, GetWindowLong(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED);+			SetLayeredWindowAttributes(win->src.window, RGB(255, 255, 255), RGFW_ALPHA, LWA_ALPHA);+		}++		ShowWindow(win->src.window, SW_SHOWNORMAL);+		+		if (RGFW_root == NULL)+			RGFW_root = win;+		+		#ifdef RGFW_OPENGL+		else +			wglShareLists(RGFW_root->src.ctx, win->src.ctx);+		#endif++		return win;+	}++	void RGFW_window_setBorder(RGFW_window* win, u8 border) {+		DWORD style = GetWindowLong(win->src.window, GWL_STYLE);++		if (border == 0) {+			SetWindowLong(win->src.window, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW);+			SetWindowPos(+				win->src.window, HWND_TOP, 0, 0, 0, 0,+				SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE+			);+		}+		else {+			SetWindowLong(win->src.window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW);+			SetWindowPos(+				win->src.window, HWND_TOP, 0, 0, 0, 0,+				SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE+			);+		}+	}+++	RGFW_area RGFW_getScreenSize(void) {+		return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES));+	}++	RGFW_point RGFW_getGlobalMousePoint(void) {+		POINT p;+		GetCursorPos(&p);++		return RGFW_POINT(p.x, p.y);+	}++	RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {+		POINT p;+		GetCursorPos(&p);+		ScreenToClient(win->src.window, &p);++		return RGFW_POINT(p.x, p.y);+	}++	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {+		assert(win != NULL);+		win->src.minSize = a;+	}++	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {+		assert(win != NULL);+		win->src.maxSize = a;+	}+++	void RGFW_window_minimize(RGFW_window* win) {+		assert(win != NULL);++		ShowWindow(win->src.window, SW_MINIMIZE);+	}++	void RGFW_window_restore(RGFW_window* win) {+		assert(win != NULL);++		ShowWindow(win->src.window, SW_RESTORE);+	}+++	u8 RGFW_xinput2RGFW[] = {+		RGFW_JS_A, /* or PS X button */+		RGFW_JS_B, /* or PS circle button */+		RGFW_JS_X, /* or PS square button */+		RGFW_JS_Y, /* or PS triangle button */+		RGFW_JS_R1, /* right bumper */+		RGFW_JS_L1, /* left bump */+		RGFW_JS_L2, /* left trigger*/+		RGFW_JS_R2, /* right trigger */+		0, 0, 0, 0, 0, 0, 0, 0,+		RGFW_JS_UP, /* dpad up */+		RGFW_JS_DOWN, /* dpad down*/+		RGFW_JS_LEFT, /* dpad left */+		RGFW_JS_RIGHT, /* dpad right */+		RGFW_JS_START, /* start button */+		RGFW_JS_SELECT/* select button */+	};++	static i32 RGFW_checkXInput(RGFW_window* win, RGFW_Event* e) {+		RGFW_UNUSED(win)+		+		size_t i;+		for (i = 0; i < 4; i++) {+			XINPUT_KEYSTROKE keystroke;++			if (XInputGetKeystroke == NULL)+				return 0;++			DWORD result = XInputGetKeystroke((DWORD)i, 0, &keystroke);++			if ((keystroke.Flags & XINPUT_KEYSTROKE_REPEAT) == 0 && result != ERROR_EMPTY) {+				if (result != ERROR_SUCCESS)+					return 0;++				if (keystroke.VirtualKey > VK_PAD_BACK)+					continue;++				// RGFW_jsButtonPressed + 1 = RGFW_jsButtonReleased+				e->type = RGFW_jsButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN);+				e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800];+				RGFW_jsPressed[i][e->button] = !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN);++				return 1;+			}++			XINPUT_STATE state;+			if (XInputGetState == NULL ||+				XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED+			)+				return 0;+#define INPUT_DEADZONE  ( 0.24f * (float)(0x7FFF) )  // Default to 24% of the +/- 32767 range.   This is a reasonable default value but can be altered if needed.++			if ((state.Gamepad.sThumbLX < INPUT_DEADZONE &&+				state.Gamepad.sThumbLX > -INPUT_DEADZONE) &&+				(state.Gamepad.sThumbLY < INPUT_DEADZONE &&+					state.Gamepad.sThumbLY > -INPUT_DEADZONE))+			{+				state.Gamepad.sThumbLX = 0;+				state.Gamepad.sThumbLY = 0;+			}++			if ((state.Gamepad.sThumbRX < INPUT_DEADZONE &&+				state.Gamepad.sThumbRX > -INPUT_DEADZONE) &&+				(state.Gamepad.sThumbRY < INPUT_DEADZONE &&+					state.Gamepad.sThumbRY > -INPUT_DEADZONE))+			{+				state.Gamepad.sThumbRX = 0;+				state.Gamepad.sThumbRY = 0;+			}++			e->axisesCount = 2;+			RGFW_point axis1 = RGFW_POINT(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY);+			RGFW_point axis2 = RGFW_POINT(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY);++			if (axis1.x != e->axis[0].x || axis1.y != e->axis[0].y || axis2.x != e->axis[1].x || axis2.y != e->axis[1].y) {+				e->type = RGFW_jsAxisMove;++				e->axis[0] = axis1;+				e->axis[1] = axis2;++				return 1;+			}++			e->axis[0] = axis1;+			e->axis[1] = axis2;+		}++		return 0;+	}++	void RGFW_stopCheckEvents(void) { +		PostMessageW(RGFW_root->src.window, WM_NULL, 0, 0);+	}++	void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {+		RGFW_UNUSED(win);++		MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (waitMS * 1e3), QS_ALLINPUT);+	}++	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {+		assert(win != NULL);++		if (win->event.type == RGFW_quit) {+			return NULL;+		}++		MSG msg;++		if (RGFW_eventWindow.src.window == win->src.window) {+			if (RGFW_eventWindow.r.x != -1) {+				win->r.x = RGFW_eventWindow.r.x;+				win->r.y = RGFW_eventWindow.r.y;+				win->event.type = RGFW_windowMoved;+				RGFW_windowMoveCallback(win, win->r);+			}++			if (RGFW_eventWindow.r.w != -1) {+				win->r.w = RGFW_eventWindow.r.w;+				win->r.h = RGFW_eventWindow.r.h;+				win->event.type = RGFW_windowResized;+				RGFW_windowResizeCallback(win, win->r);+			}++			RGFW_eventWindow.src.window = NULL;+			RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);++			return &win->event;+		}+++		static HDROP drop;+		+		if (win->event.type == RGFW_dnd_init) {+			if (win->event.droppedFilesCount) {+				u32 i;+				for (i = 0; i < win->event.droppedFilesCount; i++)+					win->event.droppedFiles[i][0] = '\0';+			}++			win->event.droppedFilesCount = 0;+			win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0);+			//win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*));++			u32 i;+			for (i = 0; i < win->event.droppedFilesCount; i++) {+				const UINT length = DragQueryFileW(drop, i, NULL, 0);+				WCHAR* buffer = (WCHAR*) RGFW_CALLOC((size_t) length + 1, sizeof(WCHAR));++				DragQueryFileW(drop, i, buffer, length + 1);+				strncpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer), RGFW_MAX_PATH);+				win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0';+				RGFW_FREE(buffer);+			}++			DragFinish(drop);+			RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);+			+			win->event.type = RGFW_dnd;+			return &win->event;+		}++		win->event.inFocus = (GetForegroundWindow() == win->src.window);++		if (RGFW_checkXInput(win, &win->event))+			return &win->event;++		static BYTE keyboardState[256];++		if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE)) {+			switch (msg.message) {+			case WM_CLOSE:+			case WM_QUIT:+				RGFW_windowQuitCallback(win);+				win->event.type = RGFW_quit;+				break;++			case WM_ACTIVATE:+				win->event.inFocus = (LOWORD(msg.wParam) == WA_INACTIVE);++				if (win->event.inFocus) {+					win->event.type = RGFW_focusIn;+					RGFW_focusCallback(win, 1);+				}+				else {+					win->event.type = RGFW_focusOut;+					RGFW_focusCallback(win, 0);+				}++				break;+			+			case WM_PAINT:+				win->event.type = RGFW_windowRefresh;+				RGFW_windowRefreshCallback(win);+				break;+			+			case WM_MOUSELEAVE:+				win->event.type = RGFW_mouseLeave;+				win->_winArgs |= RGFW_MOUSE_LEFT;+				RGFW_mouseNotifyCallBack(win, win->event.point, 0);+				break;+			+			case WM_KEYUP: {+				win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam);+								+				RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);++				static char keyName[16];+				+				{+					GetKeyNameTextA((LONG) msg.lParam, keyName, 16);++					if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||+						((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {+						CharLowerBuffA(keyName, 16);+					}+				}++				RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));++				strncpy(win->event.keyName, keyName, 16);++				if (RGFW_isPressed(win, RGFW_ShiftL)) {+					ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),+						keyboardState, (LPWORD) win->event.keyName, 0);+				}++				win->event.type = RGFW_keyReleased;+				RGFW_keyboard[win->event.keyCode].current = 0;+				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0);+				break;+			}+			case WM_KEYDOWN: {+				win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam);++				RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);++				static char keyName[16];+				+				{+					GetKeyNameTextA((LONG) msg.lParam, keyName, 16);++					if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||+						((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {+						CharLowerBuffA(keyName, 16);+					}+				}+				+				RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));++				strncpy(win->event.keyName, keyName, 16);++				if (RGFW_isPressed(win, RGFW_ShiftL) & 0x8000) {+					ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),+						keyboardState, (LPWORD) win->event.keyName, 0);+				}++				win->event.type = RGFW_keyPressed;+				win->event.repeat = RGFW_isPressed(win, win->event.keyCode);+				RGFW_keyboard[win->event.keyCode].current = 1;+				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);+				break;+			}++			case WM_MOUSEMOVE:+				if ((win->_winArgs & RGFW_HOLD_MOUSE))+					break;++				win->event.type = RGFW_mousePosChanged;++				win->event.point.x = GET_X_LPARAM(msg.lParam);+				win->event.point.y = GET_Y_LPARAM(msg.lParam);+				+				RGFW_mousePosCallback(win, win->event.point);++				if (win->_winArgs & RGFW_MOUSE_LEFT) {+					win->_winArgs ^= RGFW_MOUSE_LEFT;+					win->event.type = RGFW_mouseEnter;+					RGFW_mouseNotifyCallBack(win, win->event.point, 1);+				}++				break;++			case WM_INPUT: {+				if (!(win->_winArgs & RGFW_HOLD_MOUSE))+					break;+				+				unsigned size = sizeof(RAWINPUT);+				static RAWINPUT raw[sizeof(RAWINPUT)];+				GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER));++				if (raw->header.dwType != RIM_TYPEMOUSE || (raw->data.mouse.lLastX == 0 && raw->data.mouse.lLastY == 0) )+					break;+				+				win->event.type = RGFW_mousePosChanged;+				win->event.point.x = raw->data.mouse.lLastX;+				win->event.point.y = raw->data.mouse.lLastY;+				break;+			}++			case WM_LBUTTONDOWN:+				win->event.button = RGFW_mouseLeft;+				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 1;+				win->event.type = RGFW_mouseButtonPressed;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+				break;+			case WM_RBUTTONDOWN:+				win->event.button = RGFW_mouseRight;+				win->event.type = RGFW_mouseButtonPressed;+				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 1;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+				break;+			case WM_MBUTTONDOWN:+				win->event.button = RGFW_mouseMiddle;+				win->event.type = RGFW_mouseButtonPressed;+				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 1;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+				break;++			case WM_MOUSEWHEEL:+				if (msg.wParam > 0)+					win->event.button = RGFW_mouseScrollUp;+				else+					win->event.button = RGFW_mouseScrollDown;++				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 1;++				win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA;++				win->event.type = RGFW_mouseButtonPressed;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+				break;++			case WM_LBUTTONUP:+			+				win->event.button = RGFW_mouseLeft;+				win->event.type = RGFW_mouseButtonReleased;++				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 0;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+				break;+			case WM_RBUTTONUP:+				win->event.button = RGFW_mouseRight;+				win->event.type = RGFW_mouseButtonReleased;++				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 0;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+				break;+			case WM_MBUTTONUP:+				win->event.button = RGFW_mouseMiddle;+				win->event.type = RGFW_mouseButtonReleased;++				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 0;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+				break;++				/*+					much of this event is source from glfw+				*/+			case WM_DROPFILES: {				+				win->event.type = RGFW_dnd_init;++				drop = (HDROP) msg.wParam;+				POINT pt;++				/* Move the mouse to the position of the drop */+				DragQueryPoint(drop, &pt);++				win->event.point.x = pt.x;+				win->event.point.y = pt.y;++				RGFW_dndInitCallback(win, win->event.point);+			}+				break;+			case WM_GETMINMAXINFO:+			{+				if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0)+					break;++				MINMAXINFO* mmi = (MINMAXINFO*) msg.lParam;+				mmi->ptMinTrackSize.x = win->src.minSize.w;+				mmi->ptMinTrackSize.y = win->src.minSize.h;+				mmi->ptMaxTrackSize.x = win->src.maxSize.w;+				mmi->ptMaxTrackSize.y = win->src.maxSize.h;+				return 0;+			}+			default:+				win->event.type = 0;+				break;+			}++			TranslateMessage(&msg);+			DispatchMessageA(&msg);+		}++		else+			win->event.type = 0;++		if (!IsWindow(win->src.window)) {+			win->event.type = RGFW_quit;+			RGFW_windowQuitCallback(win);+		}++		if (win->event.type)+			return &win->event;+		else+			return NULL;+	}++	u8 RGFW_window_isFullscreen(RGFW_window* win) {+		assert(win != NULL);++		#ifndef __cplusplus+		WINDOWPLACEMENT placement = { 0 };+		#else+		WINDOWPLACEMENT placement = {  };+		#endif+		GetWindowPlacement(win->src.window, &placement);+		return placement.showCmd == SW_SHOWMAXIMIZED;+	}++	u8 RGFW_window_isHidden(RGFW_window* win) {+		assert(win != NULL);++		return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win);+	}++	u8 RGFW_window_isMinimized(RGFW_window* win) {+		assert(win != NULL);++		#ifndef __cplusplus+		WINDOWPLACEMENT placement = { 0 };+		#else+		WINDOWPLACEMENT placement = {  };+		#endif+		GetWindowPlacement(win->src.window, &placement);+		return placement.showCmd == SW_SHOWMINIMIZED;+	}++	u8 RGFW_window_isMaximized(RGFW_window* win) {+		assert(win != NULL);++		#ifndef __cplusplus+		WINDOWPLACEMENT placement = { 0 };+		#else+		WINDOWPLACEMENT placement = {  };+		#endif+		GetWindowPlacement(win->src.window, &placement);+		return placement.showCmd == SW_SHOWMAXIMIZED;+	}++	typedef struct { int iIndex; HMONITOR hMonitor; } RGFW_mInfo;+	BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {+		RGFW_UNUSED(hdcMonitor)+		RGFW_UNUSED(lprcMonitor)++		RGFW_mInfo* info = (RGFW_mInfo*) dwData;+		if (info->hMonitor == hMonitor)+			return FALSE;++		info->iIndex++;+		return TRUE;+	}+	+	#ifndef RGFW_NO_MONITOR+	RGFW_monitor win32CreateMonitor(HMONITOR src) {+		RGFW_monitor monitor;+		MONITORINFO monitorInfo;++		monitorInfo.cbSize = sizeof(MONITORINFO);+		GetMonitorInfoA(src, &monitorInfo);++		RGFW_mInfo info;+		info.iIndex = 0;+		info.hMonitor = src;++		/* get the monitor's index */+		if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM) &info)) {+			DISPLAY_DEVICEA dd;+			dd.cb = sizeof(dd);++			/* loop through the devices until you find a device with the monitor's index */+			size_t deviceIndex;+			for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) {+				char* deviceName = dd.DeviceName;+				if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) {+					strncpy(monitor.name, dd.DeviceString, 128); /*!< copy the monitor's name */+					break;+				}+			}+		}++		monitor.rect.x = monitorInfo.rcWork.left;+		monitor.rect.y = monitorInfo.rcWork.top;+		monitor.rect.w = monitorInfo.rcWork.right - monitorInfo.rcWork.left;+		monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;++#ifndef RGFW_NO_DPI+		#ifndef USER_DEFAULT_SCREEN_DPI+		#define USER_DEFAULT_SCREEN_DPI 96+		#endif++		if (GetDpiForMonitor != NULL) {+			u32 x, y;+			GetDpiForMonitor(src, MDT_EFFECTIVE_DPI, &x, &y);+			+			monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI;+			monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI;+		}+#endif++		HDC hdc = GetDC(NULL);+		/* get pixels per inch */+		i32 ppiX = GetDeviceCaps(hdc, LOGPIXELSX);+		i32 ppiY = GetDeviceCaps(hdc, LOGPIXELSY);+		ReleaseDC(NULL, hdc);++		/* Calculate physical height in inches */+		monitor.physW = GetSystemMetrics(SM_CYSCREEN) / (float) ppiX;+		monitor.physH = GetSystemMetrics(SM_CXSCREEN) / (float) ppiY;+		+		return monitor;+	}+	#endif /* RGFW_NO_MONITOR */+	++	#ifndef RGFW_NO_MONITOR+	RGFW_monitor RGFW_monitors[6];+	BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {+		RGFW_UNUSED(hdcMonitor)+		RGFW_UNUSED(lprcMonitor)++		RGFW_mInfo* info = (RGFW_mInfo*) dwData;++		if (info->iIndex >= 6)+			return FALSE;++		RGFW_monitors[info->iIndex] = win32CreateMonitor(hMonitor);+		info->iIndex++;++		return TRUE;+	}++	RGFW_monitor RGFW_getPrimaryMonitor(void) {+        #ifdef __cplusplus+        return win32CreateMonitor(MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY));+        #else+		return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY));+	    #endif+    }++	RGFW_monitor* RGFW_getMonitors(void) {+		RGFW_mInfo info;+		info.iIndex = 0;+		while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info));+			+		return RGFW_monitors;+	}++	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {+		HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY);+		return win32CreateMonitor(src);+	}+	#endif++	HICON RGFW_loadHandleImage(RGFW_window* win, u8* src, RGFW_area a, BOOL icon) {+		assert(win != NULL);++		u32 i;+		HDC dc;+		HICON handle;+		HBITMAP color, mask;+		BITMAPV5HEADER bi;+		ICONINFO ii;+		u8* target = NULL;+		u8* source = src;++		ZeroMemory(&bi, sizeof(bi));+		bi.bV5Size = sizeof(bi);+		bi.bV5Width = a.w;+		bi.bV5Height = -((LONG) a.h);+		bi.bV5Planes = 1;+		bi.bV5BitCount = 32;+		bi.bV5Compression = BI_BITFIELDS;+		bi.bV5RedMask = 0x00ff0000;+		bi.bV5GreenMask = 0x0000ff00;+		bi.bV5BlueMask = 0x000000ff;+		bi.bV5AlphaMask = 0xff000000;++		dc = GetDC(NULL);+		color = CreateDIBSection(dc,+			(BITMAPINFO*) &bi,+			DIB_RGB_COLORS,+			(void**) &target,+			NULL,+			(DWORD) 0);+		ReleaseDC(NULL, dc);++		mask = CreateBitmap(a.w, a.h, 1, 1, NULL);++		for (i = 0; i < a.w * a.h; i++) {+			target[0] = source[2];+			target[1] = source[1];+			target[2] = source[0];+			target[3] = source[3];+			target += 4;+			source += 4;+		}++		ZeroMemory(&ii, sizeof(ii));+		ii.fIcon = icon;+		ii.xHotspot = 0;+		ii.yHotspot = 0;+		ii.hbmMask = mask;+		ii.hbmColor = color;++		handle = CreateIconIndirect(&ii);++		DeleteObject(color);+		DeleteObject(mask);++		return handle;+	}++	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {+		assert(win != NULL);+		RGFW_UNUSED(channels)++		HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(win, image, a, FALSE);+		SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) cursor);+		SetCursor(cursor);+		DestroyCursor(cursor);+	}++	void RGFW_window_setMouseDefault(RGFW_window* win) {+		RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);+	}++	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {+		assert(win != NULL);++		if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32)))+			return;++		char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]);++		SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon));+		SetCursor(LoadCursorA(NULL, icon));+	}++	void RGFW_window_hide(RGFW_window* win) {+		ShowWindow(win->src.window, SW_HIDE);+	}++	void RGFW_window_show(RGFW_window* win) {+		ShowWindow(win->src.window, SW_RESTORE);+	}++	void RGFW_window_close(RGFW_window* win) {+		assert(win != NULL);++#ifdef RGFW_EGL+		RGFW_closeEGL(win);+#endif++		if (win == RGFW_root) {+#ifdef RGFW_DIRECTX+			RGFW_dxInfo.pDeviceContext->lpVtbl->Release(RGFW_dxInfo.pDeviceContext);+			RGFW_dxInfo.pDevice->lpVtbl->Release(RGFW_dxInfo.pDevice);+			RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);+			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);+#endif+		+			if (RGFW_XInput_dll != NULL) {+				FreeLibrary(RGFW_XInput_dll);+				RGFW_XInput_dll = NULL;+			}++			#ifndef RGFW_NO_DPI+			if (RGFW_Shcore_dll != NULL) {+				FreeLibrary(RGFW_Shcore_dll);+				RGFW_Shcore_dll = NULL;+			}+			#endif++			if (wglinstance != NULL) {+				FreeLibrary(wglinstance);+				wglinstance = NULL;+			}++			RGFW_root = NULL;+		}++#ifdef RGFW_DIRECTX+		win->src.swapchain->lpVtbl->Release(win->src.swapchain);+		win->src.renderTargetView->lpVtbl->Release(win->src.renderTargetView);+		win->src.pDepthStencilView->lpVtbl->Release(win->src.pDepthStencilView);+#endif++#ifdef RGFW_BUFFER+		DeleteDC(win->src.hdcMem);+		DeleteObject(win->src.bitmap);+#endif++#ifdef RGFW_OPENGL+		wglDeleteContext((HGLRC) win->src.ctx); /*!< delete opengl context */+#endif+		DeleteDC(win->src.hdc); /*!< delete device context */+		DestroyWindow(win->src.window); /*!< delete window */++#if defined(RGFW_OSMESA)+		if (win->buffer != NULL)+			RGFW_FREE(win->buffer);+#endif++#ifdef RGFW_ALLOC_DROPFILES+		{+			u32 i;+			for (i = 0; i < RGFW_MAX_DROPS; i++)+				RGFW_FREE(win->event.droppedFiles[i]);+++			RGFW_FREE(win->event.droppedFiles);+		}+#endif++		RGFW_FREE(win);+	}++	void RGFW_window_move(RGFW_window* win, RGFW_point v) {+		assert(win != NULL);++		win->r.x = v.x;+		win->r.y = v.y;+		SetWindowPos(win->src.window, HWND_TOP, win->r.x, win->r.y, 0, 0, SWP_NOSIZE);+	}++	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {+		assert(win != NULL);++		win->r.w = a.w;+		win->r.h = a.h;+		SetWindowPos(win->src.window, HWND_TOP, 0, 0, win->r.w, win->r.h + win->src.hOffset, SWP_NOMOVE);+	}+++	void RGFW_window_setName(RGFW_window* win, char* name) {+		assert(win != NULL);++		SetWindowTextA(win->src.window, name);+	}++	/* sourced from GLFW */+	#ifndef RGFW_NO_PASSTHROUGH+	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {+		assert(win != NULL);+		+		COLORREF key = 0;+		BYTE alpha = 0;+		DWORD flags = 0;+		DWORD exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE);+		+		if (exStyle & WS_EX_LAYERED)+			GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags);++		if (passthrough)+			exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);+		else+		{+			exStyle &= ~WS_EX_TRANSPARENT;+			// NOTE: Window opacity also needs the layered window style so do not+			//       remove it if the window is alpha blended+			if (exStyle & WS_EX_LAYERED)+			{+				if (!(flags & LWA_ALPHA))+					exStyle &= ~WS_EX_LAYERED;+			}+		}++		SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle);++		if (passthrough) {+			SetLayeredWindowAttributes(win->src.window, key, alpha, flags);+		}+	}+	#endif++	/* much of this function is sourced from GLFW */+	void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) {+		assert(win != NULL);+		#ifndef RGFW_WIN95+		RGFW_UNUSED(channels)++		HICON handle = RGFW_loadHandleImage(win, src, a, TRUE);++		SetClassLongPtrA(win->src.window, GCLP_HICON, (LPARAM) handle);++		DestroyIcon(handle);+		#else+		RGFW_UNUSED(src)+		RGFW_UNUSED(a)+		RGFW_UNUSED(channels)+		#endif+	}++	char* RGFW_readClipboard(size_t* size) {+		/* Open the clipboard */+		if (OpenClipboard(NULL) == 0)+			return (char*) "";++		/* Get the clipboard data as a Unicode string */+		HANDLE hData = GetClipboardData(CF_UNICODETEXT);+		if (hData == NULL) {+			CloseClipboard();+			return (char*) "";+		}++		wchar_t* wstr = (wchar_t*) GlobalLock(hData);++		char* text;++		{+			setlocale(LC_ALL, "en_US.UTF-8");++			size_t textLen = wcstombs(NULL, wstr, 0);+			if (textLen == 0)+				return (char*) "";++			text = (char*) RGFW_MALLOC((textLen * sizeof(char)) + 1);++			wcstombs(text, wstr, (textLen) +1);++			if (size != NULL)+				*size = textLen + 1;++			text[textLen] = '\0';+		}++		/* Release the clipboard data */+		GlobalUnlock(hData);+		CloseClipboard();++		return text;+	}++	void RGFW_writeClipboard(const char* text, u32 textLen) {+		HANDLE object;+		WCHAR* buffer;++		object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR));+		if (!object)+			return;++		buffer = (WCHAR*) GlobalLock(object);+		if (!buffer) {+			GlobalFree(object);+			return;+		}++		MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, textLen);+		GlobalUnlock(object);++		if (!OpenClipboard(RGFW_root->src.window)) {+			GlobalFree(object);+			return;+		}++		EmptyClipboard();+		SetClipboardData(CF_UNICODETEXT, object);+		CloseClipboard();+	}++	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {+		assert(win != NULL);++		RGFW_UNUSED(jsNumber)++		return RGFW_registerJoystickF(win, (char*) "");+	}++	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {+		assert(win != NULL);+		RGFW_UNUSED(file)++		return RGFW_joystickCount - 1;+	}++	void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) {+		assert(win != NULL);++		SetCursorPos(p.x, p.y);+	}++	#ifdef RGFW_OPENGL+	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {+		if (win == NULL)+			wglMakeCurrent(NULL, NULL);+		else+			wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx);+	}+	#endif++	#ifndef RGFW_EGL+	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {+		assert(win != NULL);+		+		#if defined(RGFW_OPENGL)+		typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval);+		static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;+		static void* loadSwapFunc = (void*) 1;++		if (loadSwapFunc == NULL) {+			fprintf(stderr, "wglSwapIntervalEXT not supported\n");+			return;+		}++		if (wglSwapIntervalEXT == NULL) {+			loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT");+			wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc;+		}++		if (wglSwapIntervalEXT(swapInterval) == FALSE)+			fprintf(stderr, "Failed to set swap interval\n");+		#else+        RGFW_UNUSED(swapInterval);+        #endif++	}+	#endif++	void RGFW_window_swapBuffers(RGFW_window* win) {+		//assert(win != NULL);+		/* clear the window*/++		if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+			#ifdef RGFW_OSMESA+			RGFW_OSMesa_reorganize();+			#endif++			HGDIOBJ oldbmp = SelectObject(win->src.hdcMem, win->src.bitmap);+			BitBlt(win->src.hdc, 0, 0, win->r.w, win->r.h, win->src.hdcMem, 0, 0, SRCCOPY);+			SelectObject(win->src.hdcMem, oldbmp);+#endif+		}++		if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) {+			#ifdef RGFW_EGL+					eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);+			#elif defined(RGFW_OPENGL)+					SwapBuffers(win->src.hdc);+			#endif++			#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)+					win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0);+			#endif+		}+	}++	char* createUTF8FromWideStringWin32(const WCHAR* source) {+		char* target;+		i32 size;++		size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);+		if (!size) {+			return NULL;+		}++		target = (char*) RGFW_CALLOC(size, 1);++		if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) {+			RGFW_FREE(target);+			return NULL;+		}++		return target;+	}+	+    static inline LARGE_INTEGER RGFW_win32_initTimer(void) {+		static LARGE_INTEGER frequency = {{0, 0}};+		if (frequency.QuadPart == 0) {+			timeBeginPeriod(1);+			QueryPerformanceFrequency(&frequency);+		}++		return frequency;+	}++	u64 RGFW_getTimeNS(void) {+		LARGE_INTEGER frequency = RGFW_win32_initTimer();++		LARGE_INTEGER counter;+		QueryPerformanceCounter(&counter);++		return (u64) ((counter.QuadPart * 1e9) / frequency.QuadPart);+	}++	u64 RGFW_getTime(void) {+		LARGE_INTEGER frequency = RGFW_win32_initTimer();++		LARGE_INTEGER counter;+		QueryPerformanceCounter(&counter);+		return (u64) (counter.QuadPart / (double) frequency.QuadPart);+	}+	+	void RGFW_sleep(u64 ms) {+		Sleep(ms);+	}++#ifndef RGFW_NO_THREADS+	RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { return CreateThread(NULL, 0, ptr, args, 0, NULL); }+	void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); }+	void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); }+	void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); }+#endif+#endif /* RGFW_WINDOWS */++/*+	End of Windows defines+*/++++/* ++	Start of MacOS defines+++*/++#if defined(RGFW_MACOS)+	/*+		based on silicon.h+		start of cocoa wrapper+	*/++#include <CoreVideo/CVDisplayLink.h>+#include <ApplicationServices/ApplicationServices.h>+#include <objc/runtime.h>+#include <objc/message.h>+#include <mach/mach_time.h>++	typedef CGRect NSRect;+	typedef CGPoint NSPoint;+	typedef CGSize NSSize;++	typedef void NSBitmapImageRep;+	typedef void NSCursor;+	typedef void NSDraggingInfo;+	typedef void NSWindow;+	typedef void NSApplication;+	typedef void NSScreen;+	typedef void NSEvent;+	typedef void NSString;+	typedef void NSOpenGLContext;+	typedef void NSPasteboard;+	typedef void NSColor;+	typedef void NSArray;+	typedef void NSImageRep;+	typedef void NSImage;+	typedef void NSOpenGLView;+++	typedef const char* NSPasteboardType;+	typedef unsigned long NSUInteger;+	typedef long NSInteger;+	typedef NSInteger NSModalResponse;++#ifdef __arm64__+	/* ARM just uses objc_msgSend */+#define abi_objc_msgSend_stret objc_msgSend+#define abi_objc_msgSend_fpret objc_msgSend+#else /* __i386__ */ +	/* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */+#define abi_objc_msgSend_stret objc_msgSend_stret+#define abi_objc_msgSend_fpret objc_msgSend_fpret+#endif++#define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc"))+#define objc_msgSend_bool			((BOOL (*)(id, SEL))objc_msgSend)+#define objc_msgSend_void			((void (*)(id, SEL))objc_msgSend)+#define objc_msgSend_void_id		((void (*)(id, SEL, id))objc_msgSend)+#define objc_msgSend_uint			((NSUInteger (*)(id, SEL))objc_msgSend)+#define objc_msgSend_void_bool		((void (*)(id, SEL, BOOL))objc_msgSend)+#define objc_msgSend_bool_void		((BOOL (*)(id, SEL))objc_msgSend)+#define objc_msgSend_void_SEL		((void (*)(id, SEL, SEL))objc_msgSend)+#define objc_msgSend_id				((id (*)(id, SEL))objc_msgSend)+#define objc_msgSend_id_id				((id (*)(id, SEL, id))objc_msgSend)+#define objc_msgSend_id_bool			((BOOL (*)(id, SEL, id))objc_msgSend)+#define objc_msgSend_int ((id (*)(id, SEL, int))objc_msgSend)+#define objc_msgSend_arr ((id (*)(id, SEL, int))objc_msgSend)+#define objc_msgSend_ptr ((id (*)(id, SEL, void*))objc_msgSend)+#define objc_msgSend_class ((id (*)(Class, SEL))objc_msgSend)+#define objc_msgSend_class_char ((id (*)(Class, SEL, char*))objc_msgSend)++	NSApplication* NSApp = NULL;++	void NSRelease(id obj) {+		objc_msgSend_void(obj, sel_registerName("release"));+	}++	#define release NSRelease++	NSString* NSString_stringWithUTF8String(const char* str) {	+		return ((id(*)(id, SEL, const char*))objc_msgSend)+			((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str);+	}++	const char* NSString_to_char(NSString* str) {+		return ((const char* (*)(id, SEL)) objc_msgSend) (str, sel_registerName("UTF8String"));+	}++	void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) {+		Class selected_class;++		if (strcmp(class_name, "NSView") == 0) {+			selected_class = objc_getClass("ViewClass");+		} else if (strcmp(class_name, "NSWindow") == 0) {+			selected_class = objc_getClass("WindowClass");+		} else {+			selected_class = objc_getClass(class_name);+		}++		class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0);+	}++	/* Header for the array. */+	typedef struct siArrayHeader {+		size_t count;+		/* TODO(EimaMei): Add a `type_width` later on. */+	} siArrayHeader;++	/* Gets the header of the siArray. */+#define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1)++	void* si_array_init_reserve(size_t sizeof_element, size_t count) {+		siArrayHeader* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count));+		void* array = ptr + sizeof(siArrayHeader);++		siArrayHeader* header = SI_ARRAY_HEADER(array);+		header->count = count;++		return array;+	}++#define si_array_len(array) (SI_ARRAY_HEADER(array)->count)+#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", function)+	/* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/+#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", function)+	+	unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) {+		return ((unsigned char* (*)(id, SEL))objc_msgSend)+			(imageRep, sel_registerName("bitmapData"));+	}++#define NS_ENUM(type, name) type name; enum++	typedef NS_ENUM(NSUInteger, NSBitmapFormat) {+		NSBitmapFormatAlphaFirst = 1 << 0,       // 0 means is alpha last (RGBA, CMYKA, etc.)+			NSBitmapFormatAlphaNonpremultiplied = 1 << 1,       // 0 means is premultiplied+			NSBitmapFormatFloatingPointSamples = 1 << 2,  // 0 is integer++			NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8),+			NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9),+			NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10),+			NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11)+	};++	NSBitmapImageRep* NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) {+		void* func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:");++		return (NSBitmapImageRep*) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend)+			(NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits);+	}++	NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) {+		void* nsclass = objc_getClass("NSColor");+		void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:");+		return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)+			(nsclass, func, red, green, blue, alpha);+	}++	NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) {+		void* func = sel_registerName("initWithImage:hotSpot:");+		void* nsclass = objc_getClass("NSCursor");++		return (NSCursor*) ((id(*)(id, SEL, id, NSPoint))objc_msgSend)+			(NSAlloc(nsclass), func, newImage, aPoint);+	}++	void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep) {+		void* func = sel_registerName("addRepresentation:");+		objc_msgSend_void_id(image, func, imageRep);+	}++	NSImage* NSImage_initWithSize(NSSize size) {+		void* func = sel_registerName("initWithSize:");+		return ((id(*)(id, SEL, NSSize))objc_msgSend)+			(NSAlloc((id)objc_getClass("NSImage")), func, size);+	}+#define NS_OPENGL_ENUM_DEPRECATED(minVers, maxVers) API_AVAILABLE(macos(minVers))+	typedef NS_ENUM(NSInteger, NSOpenGLContextParameter) {+		NSOpenGLContextParameterSwapInterval           NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param.  0 -> Don't sync, 1 -> Sync to vertical retrace     */+			NSOpenGLContextParametectxaceOrder           NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param.  1 -> Above Window (default), -1 -> Below Window    */+			NSOpenGLContextParametectxaceOpacity         NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param.  1-> Surface is opaque (default), 0 -> non-opaque   */+			NSOpenGLContextParametectxaceBackingSize     NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params.  Width/height of surface backing size              */+			NSOpenGLContextParameterReclaimResources       NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params.                                                    */+			NSOpenGLContextParameterCurrentRendererID      NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param.   Retrieves the current renderer ID                 */+			NSOpenGLContextParameterGPUVertexProcessing    NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param.   Currently processing vertices with GPU (get)      */+			NSOpenGLContextParameterGPUFragmentProcessing  NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param.   Currently processing fragments with GPU (get)     */+			NSOpenGLContextParameterHasDrawable            NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param.   Boolean returned if drawable is attached          */+			NSOpenGLContextParameterMPSwapsInFlight        NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param.   Max number of swaps queued by the MP GL engine    */++			NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params.  Set or get the swap rectangle {x, y, w, h} */+			NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */+			NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */+			NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */+			NSOpenGLContextParametectxaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param.   Surface volatile state */+	};+++	void NSOpenGLContext_setValues(NSOpenGLContext* context, const int* vals, NSOpenGLContextParameter param) {+		void* func = sel_registerName("setValues:forParameter:");+		((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend)+			(context, func, vals, param);+	}++	void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) {+		void* func = sel_registerName("initWithAttributes:");+		return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend)+			(NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs);+	}++	NSOpenGLView* NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) {+		void* func = sel_registerName("initWithFrame:pixelFormat:");+		return (NSOpenGLView*) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend)+			(NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format);+	}++	void NSCursor_performSelector(NSCursor* cursor, void* selector) {+		void* func = sel_registerName("performSelector:");+		objc_msgSend_void_SEL(cursor, func, selector);+	}++	NSPasteboard* NSPasteboard_generalPasteboard(void) {+		return (NSPasteboard*) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard"));+	}++	NSString** cstrToNSStringArray(char** strs, size_t len) {+		static NSString* nstrs[6];+		size_t i;+		for (i = 0; i < len; i++)+			nstrs[i] = NSString_stringWithUTF8String(strs[i]);++		return nstrs;+	}++	const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType) {+		void* func = sel_registerName("stringForType:");+		return (const char*) NSString_to_char(((id(*)(id, SEL, const char*))objc_msgSend)(pasteboard, func, NSString_stringWithUTF8String(dataType)));+	}++	NSArray* c_array_to_NSArray(void* array, size_t len) {+		SEL func = sel_registerName("initWithObjects:count:");+		void* nsclass = objc_getClass("NSArray");+		return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend)+					(NSAlloc(nsclass), func, array, len);+	}+ +	void NSregisterForDraggedTypes(void* view, NSPasteboardType* newTypes, size_t len) {+		NSString** ntypes = cstrToNSStringArray((char**)newTypes, len);++		NSArray* array = c_array_to_NSArray(ntypes, len);+		objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array);+		NSRelease(array);+	}++	NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) {+		NSString** ntypes = cstrToNSStringArray((char**)newTypes, len);++		void* func = sel_registerName("declareTypes:owner:");++		NSArray* array = c_array_to_NSArray(ntypes, len);++		NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend)+			(pasteboard, func, array, owner);+		NSRelease(array);++		return output;+	}++	bool NSPasteBoard_setString(NSPasteboard* pasteboard, const char* stringToWrite, NSPasteboardType dataType) {+		void* func = sel_registerName("setString:forType:");+		return ((bool (*)(id, SEL, id, NSPasteboardType))objc_msgSend)+			(pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType));+	}++	void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); }++	typedef enum NSApplicationActivationPolicy {+		NSApplicationActivationPolicyRegular,+		NSApplicationActivationPolicyAccessory,+		NSApplicationActivationPolicyProhibited+	} NSApplicationActivationPolicy;++	typedef NS_ENUM(u32, NSBackingStoreType) {+		NSBackingStoreRetained = 0,+			NSBackingStoreNonretained = 1,+			NSBackingStoreBuffered = 2+	};++	typedef NS_ENUM(u32, NSWindowStyleMask) {+		NSWindowStyleMaskBorderless = 0,+			NSWindowStyleMaskTitled = 1 << 0,+			NSWindowStyleMaskClosable = 1 << 1,+			NSWindowStyleMaskMiniaturizable = 1 << 2,+			NSWindowStyleMaskResizable = 1 << 3,+			NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */+			NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12,+			NSWindowStyleMaskFullScreen = 1 << 14,+			NSWindowStyleMaskFullSizeContentView = 1 << 15,+			NSWindowStyleMaskUtilityWindow = 1 << 4,+			NSWindowStyleMaskDocModalWindow = 1 << 6,+			NSWindowStyleMaskNonactivatingPanel = 1 << 7,+			NSWindowStyleMaskHUDWindow = 1 << 13+	};++	NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType+++	typedef NS_ENUM(i32, NSDragOperation) {+		NSDragOperationNone = 0,+			NSDragOperationCopy = 1,+			NSDragOperationLink = 2,+			NSDragOperationGeneric = 4,+			NSDragOperationPrivate = 8,+			NSDragOperationMove = 16,+			NSDragOperationDelete = 32,+			NSDragOperationEvery = ULONG_MAX,++			//NSDragOperationAll_Obsolete	API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery+			//NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery+	};++	void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) {+		void* func = sel_registerName("objectAtIndex:");+		return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index);+	}++	const char** NSPasteboard_readObjectsForClasses(NSPasteboard* pasteboard, Class* classArray, size_t len, void* options) {+		void* func = sel_registerName("readObjectsForClasses:options:");++		NSArray* array = c_array_to_NSArray(classArray, len);++		NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend)+			(pasteboard, func, array, options);++		NSRelease(array);+		NSUInteger count = ((NSUInteger(*)(id, SEL))objc_msgSend)(output, sel_registerName("count"));++		const char** res = si_array_init_reserve(sizeof(const char*), count);++		void* path_func = sel_registerName("path");++		for (NSUInteger i = 0; i < count; i++) {+			void* url = NSArray_objectAtIndex(output, i);+			NSString* url_str = ((id(*)(id, SEL))objc_msgSend)(url, path_func);+			res[i] = NSString_to_char(url_str);+		}++		return res;+	}++	void* NSWindow_contentView(NSWindow* window) {+		void* func = sel_registerName("contentView");+		return objc_msgSend_id(window, func);+	}++	/*+		End of cocoa wrapper+	*/++	char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"};++	void* RGFWnsglFramework = NULL;++#ifdef RGFW_OPENGL+	void* RGFW_getProcAddress(const char* procname) {+		if (RGFWnsglFramework == NULL)+			RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));++		CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII);++		void* symbol = CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName);++		CFRelease(symbolName);++		return symbol;+	}+#endif++	CVReturn displayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) { +		RGFW_UNUSED(displayLink) RGFW_UNUSED(inNow) RGFW_UNUSED(inOutputTime) RGFW_UNUSED(flagsIn) RGFW_UNUSED(flagsOut) RGFW_UNUSED(displayLinkContext)+		return kCVReturnSuccess; +	}++	id NSWindow_delegate(RGFW_window* win) {+		return (id) objc_msgSend_id(win->src.window, sel_registerName("delegate"));+	}++	u32 RGFW_OnClose(void* self) {+		RGFW_window* win = NULL;+		object_getInstanceVariable(self, "RGFW_window", (void*)&win);+		if (win == NULL)+			return true;++		win->event.type = RGFW_quit;+		RGFW_windowQuitCallback(win);++		return true;+	}++	/* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */+	bool acceptsFirstResponder(void) { return true; }+	bool performKeyEquivalent(NSEvent* event) { RGFW_UNUSED(event); return true; }++	NSDragOperation draggingEntered(id self, SEL sel, id sender) { +		RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);  ++		return NSDragOperationCopy; +	}+	NSDragOperation draggingUpdated(id self, SEL sel, id sender) { +		RGFW_UNUSED(sel); ++		RGFW_window* win = NULL;+		object_getInstanceVariable(self, "RGFW_window", (void*)&win);+		if (win == NULL)+			return 0;+		+		if (!(win->_winArgs & RGFW_ALLOW_DND)) {+			return 0;+		}++		win->event.type = RGFW_dnd_init;+		win->src.dndPassed = 0;++		NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));++		win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));+		RGFW_dndInitCallback(win, win->event.point);++		return NSDragOperationCopy; +	}+	bool prepareForDragOperation(id self) {+		RGFW_window* win = NULL;+		object_getInstanceVariable(self, "RGFW_window", (void*)&win);+		if (win == NULL)+			return true;+		+		if (!(win->_winArgs & RGFW_ALLOW_DND)) {+			return false;+		}++		return true;+	}++	void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);  return; }++	/* NOTE(EimaMei): Usually, you never need 'id self, SEL cmd' for C -> Obj-C methods. This isn't the case. */+	bool performDragOperation(id self, SEL sel, id sender) {+		RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); ++		RGFW_window* win = NULL;+		object_getInstanceVariable(self, "RGFW_window", (void*)&win);++        if (win == NULL)+			return false;++		// NSPasteboard* pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard"));++        /////////////////////////////+        id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard"));++        // Get the types of data available on the pasteboard+        id types = objc_msgSend_id(pasteBoard, sel_registerName("types"));++        // Get the string type for file URLs+        id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType");++        // Check if the pasteboard contains file URLs+        if (objc_msgSend_id_bool(types, sel_registerName("containsObject:"), fileURLsType) == 0) {+		    #ifdef RGFW_DEBUG+            printf("No files found on the pasteboard.\n");+			#endif++			return 0;+		}++		id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType);+		int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count"));++		if (count == 0)+			return 0;++		for (int i = 0; i < count; i++) {+			id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i);+			const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String"));+			strncpy(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH);+			win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0';+		}+		win->event.droppedFilesCount = count;++		win->event.type = RGFW_dnd;+		win->src.dndPassed = 0;+		+		NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));+		win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));+		+		RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);+	+    	return false;+	}++	static void NSMoveToResourceDir(void) {+		/* sourced from glfw */+		char resourcesPath[255];++		CFBundleRef bundle = CFBundleGetMainBundle();+		if (!bundle)+			return;++		CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);+		CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);++		if (+			CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo ||+			CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0+			) {+			CFRelease(last);+			CFRelease(resourcesURL);+			return;+		}++		CFRelease(last);+		CFRelease(resourcesURL);++		chdir(resourcesPath);+	}+++	NSSize RGFW__osxWindowResize(void* self, SEL sel, NSSize frameSize) {+		RGFW_UNUSED(sel); ++		RGFW_window* win = NULL;+		object_getInstanceVariable(self, "RGFW_window", (void*)&win);+		if (win == NULL)+			return frameSize;+		+		win->r.w = frameSize.width;+		win->r.h = frameSize.height;+		win->event.type = RGFW_windowResized;+		RGFW_windowResizeCallback(win, win->r);+		return frameSize;+	}++	void RGFW__osxWindowMove(void* self, SEL sel) {+		RGFW_UNUSED(sel); ++		RGFW_window* win = NULL;+		object_getInstanceVariable(self, "RGFW_window", (void*)&win);+		if (win == NULL)+			return;+		+		NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(win->src.window, sel_registerName("frame"));+		win->r.x = (i32) frame.origin.x;+		win->r.y = (i32) frame.origin.y;++		win->event.type = RGFW_windowMoved;+		RGFW_windowMoveCallback(win, win->r);+	}++	void RGFW__osxUpdateLayer(void* self, SEL sel) {+		RGFW_UNUSED(sel);++		RGFW_window* win = NULL;+		object_getInstanceVariable(self, "RGFW_window", (void*)&win);+		if (win == NULL)+			return;+		+		win->event.type = RGFW_windowRefresh;+		RGFW_windowRefreshCallback(win);+	}++	RGFWDEF void RGFW_init_buffer(RGFW_window* win);+	void RGFW_init_buffer(RGFW_window* win) {+		#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+			if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)+				RGFW_bufferSize = RGFW_getScreenSize();+				+			win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);++		#ifdef RGFW_OSMESA+				win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);+				OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);+		#endif+		#else+		RGFW_UNUSED(win); /*!< if buffer rendering is not being used */+		#endif+	}+++	void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer) {+		objc_msgSend_void_id(win->src.view, sel_registerName("setLayer"), layer);+	}++	void* RGFW_cocoaGetLayer(void) {+		return objc_msgSend_class(objc_getClass("CAMetalLayer"), sel_registerName("layer"));+	}+++	NSPasteboardType const NSPasteboardTypeURL = "public.url";+	NSPasteboardType const NSPasteboardTypeFileURL  = "public.file-url";++	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {+		static u8 RGFW_loaded = 0;++		/* NOTE(EimaMei): Why does Apple hate good code? Like wtf, who thought of methods being a great idea???+		Imagine a universe, where MacOS had a proper system API (we would probably have like 20% better performance).+		*/+		si_func_to_SEL_with_name("NSObject", "windowShouldClose", RGFW_OnClose);++		/* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */+		si_func_to_SEL("NSWindow", acceptsFirstResponder);+		si_func_to_SEL("NSWindow", performKeyEquivalent);++		// RR Create an autorelease pool+		id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));+		pool = objc_msgSend_id(pool, sel_registerName("init"));++		if (NSApp == NULL) {+			NSApp = objc_msgSend_id((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));++			((void (*)(id, SEL, NSUInteger))objc_msgSend)+				(NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular);+		}++		RGFW_window* win = RGFW_window_basic_init(rect, args);+		+		RGFW_window_setMouseDefault(win);++		NSRect windowRect;+		windowRect.origin.x = win->r.x;+		windowRect.origin.y = win->r.y;+		windowRect.size.width = win->r.w;+		windowRect.size.height = win->r.h;++		NSBackingStoreType macArgs = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled;++		if (!(args & RGFW_NO_RESIZE))+			macArgs |= NSWindowStyleMaskResizable;+		if (!(args & RGFW_NO_BORDER))+			macArgs |= NSWindowStyleMaskTitled;+		else+			macArgs = NSWindowStyleMaskBorderless;+		{+			void* nsclass = objc_getClass("NSWindow");+			void* func = sel_registerName("initWithContentRect:styleMask:backing:defer:");++			win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend)+				(NSAlloc(nsclass), func, windowRect, macArgs, macArgs, false);+		}++		NSString* str = NSString_stringWithUTF8String(name);+		objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);++#ifdef RGFW_EGL+		if ((args & RGFW_NO_INIT_API) == 0)+			RGFW_createOpenGLContext(win);+#endif++#ifdef RGFW_OPENGL+	if ((args & RGFW_NO_INIT_API) == 0) {+		void* attrs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);+		void* format = NSOpenGLPixelFormat_initWithAttributes(attrs);++		if (format == NULL) {+			printf("Failed to load pixel format for OpenGL\n");++			void* attrs = RGFW_initFormatAttribs(1);+			format = NSOpenGLPixelFormat_initWithAttributes(attrs);+			if (format == NULL)+				printf("and loading software rendering OpenGL failed\n");+			else+				printf("Switching to software rendering\n");+		}+		+		/* the pixel format can be passed directly to opengl context creation to create a context +			this is because the format also includes information about the opengl version (which may be a bad thing) */+		win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format);+		objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL"));+		win->src.ctx = objc_msgSend_id(win->src.view, sel_registerName("openGLContext"));+	} else+#endif+	{+		NSRect contentRect = (NSRect){{0, 0}, {win->r.w, win->r.h}};+		win->src.view = ((id(*)(id, SEL, NSRect))objc_msgSend)+			(NSAlloc((id)objc_getClass("NSView")), sel_registerName("initWithFrame:"),+				contentRect);+	}++		void* contentView = NSWindow_contentView(win->src.window);+		objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true);++		objc_msgSend_void_id(win->src.window, sel_registerName("setContentView:"), win->src.view);++#ifdef RGFW_OPENGL+		if ((args & RGFW_NO_INIT_API) == 0)+			objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext"));+#endif+		if (args & RGFW_TRANSPARENT_WINDOW) {+#ifdef RGFW_OPENGL+		if ((args & RGFW_NO_INIT_API) == 0) {+			i32 opacity = 0;+			#define NSOpenGLCPSurfaceOpacity 236+			NSOpenGLContext_setValues(win->src.ctx, &opacity, NSOpenGLCPSurfaceOpacity);+		}+#endif++			objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false);++			objc_msgSend_void_id(win->src.window, sel_registerName("setBackgroundColor:"),+				NSColor_colorWithSRGB(0, 0, 0, 0));+		}++		win->src.display = CGMainDisplayID();+		CVDisplayLinkCreateWithCGDisplay(win->src.display, (CVDisplayLinkRef*)&win->src.displayLink);+		CVDisplayLinkSetOutputCallback(win->src.displayLink, displayCallback, win);+		CVDisplayLinkStart(win->src.displayLink);++		RGFW_init_buffer(win);++		#ifndef RGFW_NO_MONITOR+		if (args & RGFW_SCALE_TO_MONITOR)+			RGFW_window_scaleToMonitor(win);+		#endif++		if (args & RGFW_CENTER) {+			RGFW_area screenR = RGFW_getScreenSize();+			RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));+		}++		if (args & RGFW_HIDE_MOUSE)+			RGFW_window_showMouse(win, 0);++		if (args & RGFW_COCOA_MOVE_TO_RESOURCE_DIR)+			NSMoveToResourceDir();++		Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0);++		class_addIvar(+			delegateClass, "RGFW_window",+			sizeof(RGFW_window*), rint(log2(sizeof(RGFW_window*))),+			"L"+		);++		class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}");+		class_addMethod(delegateClass, sel_registerName("updateLayer:"), (IMP) RGFW__osxUpdateLayer, "");+		class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, "");+		class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, "");+		class_addMethod(delegateClass, sel_registerName("draggingEntered:"), (IMP)draggingEntered, "l@:@");+		class_addMethod(delegateClass, sel_registerName("draggingUpdated:"), (IMP)draggingUpdated, "l@:@");+		class_addMethod(delegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@");+		class_addMethod(delegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@");+		class_addMethod(delegateClass, sel_registerName("prepareForDragOperation:"), (IMP)prepareForDragOperation, "B@:@");+		class_addMethod(delegateClass, sel_registerName("performDragOperation:"), (IMP)performDragOperation, "B@:@");++		id delegate = objc_msgSend_id(NSAlloc(delegateClass), sel_registerName("init"));++		object_setInstanceVariable(delegate, "RGFW_window", win);++		objc_msgSend_void_id(win->src.window, sel_registerName("setDelegate:"), delegate);++		if (args & RGFW_ALLOW_DND) {+			win->_winArgs |= RGFW_ALLOW_DND;++			NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString};+			NSregisterForDraggedTypes(win->src.window, types, 3);+		}++		// Show the window+		objc_msgSend_void_bool(NSApp, sel_registerName("activateIgnoringOtherApps:"), true);+		((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);+		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);++		if (!RGFW_loaded) {+			objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow"));++			RGFW_loaded = 1;+		}++		objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow"));++		objc_msgSend_void(NSApp, sel_registerName("finishLaunching"));++		if (RGFW_root == NULL)+			RGFW_root = win;++		NSRetain(win->src.window);+		NSRetain(NSApp);++		return win;+	}++	void RGFW_window_setBorder(RGFW_window* win, u8 border) {+		NSBackingStoreType storeType = NSWindowStyleMaskBorderless;+		if (!border) {+			storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;+		}+		if (!(win->_winArgs & RGFW_NO_RESIZE)) {+			storeType |= NSWindowStyleMaskResizable;+		}+		+		((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)(win->src.window, sel_registerName("setStyleMask:"), storeType);++		objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border);+	}++	RGFW_area RGFW_getScreenSize(void) {+		static CGDirectDisplayID display = 0;++		if (display == 0)+			display = CGMainDisplayID();++		return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display));+	}++	RGFW_point RGFW_getGlobalMousePoint(void) {+		assert(RGFW_root != NULL);++		CGEventRef e = CGEventCreate(NULL);+		CGPoint point = CGEventGetLocation(e);+		CFRelease(e);++		return RGFW_POINT((u32) point.x, (u32) point.y); /*!< the point is loaded during event checks */+	}++	RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {+		NSPoint p =  ((NSPoint(*)(id, SEL)) objc_msgSend)(win->src.window, sel_registerName("mouseLocationOutsideOfEventStream"));++		return RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));+	}++	u32 RGFW_keysPressed[10]; /*10 keys at a time*/+	typedef NS_ENUM(u32, NSEventType) {        /* various types of events */+		NSEventTypeLeftMouseDown = 1,+			NSEventTypeLeftMouseUp = 2,+			NSEventTypeRightMouseDown = 3,+			NSEventTypeRightMouseUp = 4,+			NSEventTypeMouseMoved = 5,+			NSEventTypeLeftMouseDragged = 6,+			NSEventTypeRightMouseDragged = 7,+			NSEventTypeMouseEntered = 8,+			NSEventTypeMouseExited = 9,+			NSEventTypeKeyDown = 10,+			NSEventTypeKeyUp = 11,+			NSEventTypeFlagsChanged = 12,+			NSEventTypeAppKitDefined = 13,+			NSEventTypeSystemDefined = 14,+			NSEventTypeApplicationDefined = 15,+			NSEventTypePeriodic = 16,+			NSEventTypeCursorUpdate = 17,+			NSEventTypeScrollWheel = 22,+			NSEventTypeTabletPoint = 23,+			NSEventTypeTabletProximity = 24,+			NSEventTypeOtherMouseDown = 25,+			NSEventTypeOtherMouseUp = 26,+			NSEventTypeOtherMouseDragged = 27,+			/* The following event types are available on some hardware on 10.5.2 and later */+			NSEventTypeGesture API_AVAILABLE(macos(10.5)) = 29,+			NSEventTypeMagnify API_AVAILABLE(macos(10.5)) = 30,+			NSEventTypeSwipe   API_AVAILABLE(macos(10.5)) = 31,+			NSEventTypeRotate  API_AVAILABLE(macos(10.5)) = 18,+			NSEventTypeBeginGesture API_AVAILABLE(macos(10.5)) = 19,+			NSEventTypeEndGesture API_AVAILABLE(macos(10.5)) = 20,++			NSEventTypeSmartMagnify API_AVAILABLE(macos(10.8)) = 32,+			NSEventTypeQuickLook API_AVAILABLE(macos(10.8)) = 33,++			NSEventTypePressure API_AVAILABLE(macos(10.10.3)) = 34,+			NSEventTypeDirectTouch API_AVAILABLE(macos(10.10)) = 37,++			NSEventTypeChangeMode API_AVAILABLE(macos(10.15)) = 38,+	};++	typedef NS_ENUM(unsigned long long, NSEventMask) { /* masks for the types of events */+		NSEventMaskLeftMouseDown = 1ULL << NSEventTypeLeftMouseDown,+			NSEventMaskLeftMouseUp = 1ULL << NSEventTypeLeftMouseUp,+			NSEventMaskRightMouseDown = 1ULL << NSEventTypeRightMouseDown,+			NSEventMaskRightMouseUp = 1ULL << NSEventTypeRightMouseUp,+			NSEventMaskMouseMoved = 1ULL << NSEventTypeMouseMoved,+			NSEventMaskLeftMouseDragged = 1ULL << NSEventTypeLeftMouseDragged,+			NSEventMaskRightMouseDragged = 1ULL << NSEventTypeRightMouseDragged,+			NSEventMaskMouseEntered = 1ULL << NSEventTypeMouseEntered,+			NSEventMaskMouseExited = 1ULL << NSEventTypeMouseExited,+			NSEventMaskKeyDown = 1ULL << NSEventTypeKeyDown,+			NSEventMaskKeyUp = 1ULL << NSEventTypeKeyUp,+			NSEventMaskFlagsChanged = 1ULL << NSEventTypeFlagsChanged,+			NSEventMaskAppKitDefined = 1ULL << NSEventTypeAppKitDefined,+			NSEventMaskSystemDefined = 1ULL << NSEventTypeSystemDefined,+			NSEventMaskApplicationDefined = 1ULL << NSEventTypeApplicationDefined,+			NSEventMaskPeriodic = 1ULL << NSEventTypePeriodic,+			NSEventMaskCursorUpdate = 1ULL << NSEventTypeCursorUpdate,+			NSEventMaskScrollWheel = 1ULL << NSEventTypeScrollWheel,+			NSEventMaskTabletPoint = 1ULL << NSEventTypeTabletPoint,+			NSEventMaskTabletProximity = 1ULL << NSEventTypeTabletProximity,+			NSEventMaskOtherMouseDown = 1ULL << NSEventTypeOtherMouseDown,+			NSEventMaskOtherMouseUp = 1ULL << NSEventTypeOtherMouseUp,+			NSEventMaskOtherMouseDragged = 1ULL << NSEventTypeOtherMouseDragged,+			/* The following event masks are available on some hardware on 10.5.2 and later */+			NSEventMaskGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeGesture,+			NSEventMaskMagnify API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeMagnify,+			NSEventMaskSwipe API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeSwipe,+			NSEventMaskRotate API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeRotate,+			NSEventMaskBeginGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeBeginGesture,+			NSEventMaskEndGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeEndGesture,++			/* Note: You can only use these event masks on 64 bit. In other words, you cannot setup a local, nor global, event monitor for these event types on 32 bit. Also, you cannot search the event queue for them (nextEventMatchingMask:...) on 32 bit.+			 */+			NSEventMaskSmartMagnify API_AVAILABLE(macos(10.8)) = 1ULL << NSEventTypeSmartMagnify,+			NSEventMaskPressure API_AVAILABLE(macos(10.10.3)) = 1ULL << NSEventTypePressure,+			NSEventMaskDirectTouch API_AVAILABLE(macos(10.12.2)) = 1ULL << NSEventTypeDirectTouch,++			NSEventMaskChangeMode API_AVAILABLE(macos(10.15)) = 1ULL << NSEventTypeChangeMode,++			NSEventMaskAny = ULONG_MAX,++	};++	typedef enum NSEventModifierFlags {+		NSEventModifierFlagCapsLock = 1 << 16,+		NSEventModifierFlagShift = 1 << 17,+		NSEventModifierFlagControl = 1 << 18,+		NSEventModifierFlagOption = 1 << 19,+		NSEventModifierFlagCommand = 1 << 20,+		NSEventModifierFlagNumericPad = 1 << 21+	} NSEventModifierFlags;++	void RGFW_stopCheckEvents(void) { +		id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));+        eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));++		NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventType, NSPoint, NSEventModifierFlags, void*, NSInteger, void**, short, NSInteger, NSInteger))objc_msgSend)+			(NSApp, sel_registerName("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"), +				NSEventTypeApplicationDefined, (NSPoint){0, 0}, 0, 0, 0, NULL, 0, 0, 0);++		((void (*)(id, SEL, id, bool))objc_msgSend)+			(NSApp, sel_registerName("postEvent:atStart:"), e, 1);++		objc_msgSend_bool_void(eventPool, sel_registerName("drain"));+	}++	void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {+		RGFW_UNUSED(win);+		+		id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));+        eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));++		void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend)+					(objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS);++		NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend)+			(NSApp, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"), +				ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);+++		if (e) {+			objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e);+		}++		objc_msgSend_bool_void(eventPool, sel_registerName("drain"));+	}++	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {+		assert(win != NULL);+		+		if (win->event.type == RGFW_quit)+			return NULL;+		+		if ((win->event.type == RGFW_dnd || win->event.type == RGFW_dnd_init) && win->src.dndPassed == 0) {+			win->src.dndPassed = 1;+			return &win->event;+		}++		id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));+        eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));++		static void* eventFunc = NULL;+		if (eventFunc == NULL) +			eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");++		if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.keyCode != 120) {+			win->event.keyCode = 120;+			objc_msgSend_bool_void(eventPool, sel_registerName("drain"));+			return &win->event;+		}++		void* date = NULL;++		NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend)+			(NSApp, eventFunc, ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);++		if (e == NULL) {+			objc_msgSend_bool_void(eventPool, sel_registerName("drain"));+			return NULL;+		}+		+		if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) {+			((void (*)(id, SEL, id, bool))objc_msgSend)+				(NSApp, sel_registerName("postEvent:atStart:"), e, 0);+						+			objc_msgSend_bool_void(eventPool, sel_registerName("drain"));+			return NULL;+		}++		if (win->event.droppedFilesCount) {+			u32 i;+			for (i = 0; i < win->event.droppedFilesCount; i++)+				win->event.droppedFiles[i][0] = '\0';+		}++		win->event.droppedFilesCount = 0;+		win->event.type = 0;+		+		switch (objc_msgSend_uint(e, sel_registerName("type"))) {+			case NSEventTypeMouseEntered: {+				win->event.type = RGFW_mouseEnter;+				NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));++				win->event.point = RGFW_POINT((i32) p.x, (i32) (win->r.h - p.y));+				RGFW_mouseNotifyCallBack(win, win->event.point, 1);+				break;+			}+			+			case NSEventTypeMouseExited:+				win->event.type = RGFW_mouseLeave;+				RGFW_mouseNotifyCallBack(win, win->event.point, 0);+				break;++			case NSEventTypeKeyDown: {+				u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));+				win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);+				RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current;++				win->event.type = RGFW_keyPressed;+				char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));+				strncpy(win->event.keyName, str, 16);+				win->event.repeat = RGFW_isPressed(win, win->event.keyCode);+				RGFW_keyboard[win->event.keyCode].current = 1;++				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);+				break;+			}++			case NSEventTypeKeyUp: {+				u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));+				win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);;++				RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current;++				win->event.type = RGFW_keyReleased;+				char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));+				strncpy(win->event.keyName, str, 16);++				RGFW_keyboard[win->event.keyCode].current = 0;+				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0);+				break;+			}++			case NSEventTypeFlagsChanged: {+				u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags"));+				RGFW_updateLockState(win, ((u32)(flags & NSEventModifierFlagCapsLock) % 255), ((flags & NSEventModifierFlagNumericPad) % 255));+				+				u8 i;+				for (i = 0; i < 9; i++)+					RGFW_keyboard[i + RGFW_CapsLock].prev = 0;+				+				for (i = 0; i < 5; i++) {+					u32 shift = (1 << (i + 16));+					u32 key = i + RGFW_CapsLock;++					if ((flags & shift) && !RGFW_wasPressed(win, key)) {+						RGFW_keyboard[key].current = 1;++						if (key != RGFW_CapsLock)+							RGFW_keyboard[key+ 4].current = 1;+						+						win->event.type = RGFW_keyPressed;+						win->event.keyCode = key;+						break;+					} +					+					if (!(flags & shift) && RGFW_wasPressed(win, key)) {+						RGFW_keyboard[key].current = 0;+						+						if (key != RGFW_CapsLock)+							RGFW_keyboard[key + 4].current = 0;++						win->event.type = RGFW_keyReleased;+						win->event.keyCode = key;+						break;+					}+				}++				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, win->event.type == RGFW_keyPressed);++				break;+			}+			case NSEventTypeLeftMouseDragged:+			case NSEventTypeOtherMouseDragged:+			case NSEventTypeRightMouseDragged:+			case NSEventTypeMouseMoved:+				win->event.type = RGFW_mousePosChanged;+				NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));+				win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));++				if ((win->_winArgs & RGFW_HOLD_MOUSE)) {+					p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX"));+					p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));+					+					win->event.point = RGFW_POINT((i32)p.x, (i32)p.y);+				}++				RGFW_mousePosCallback(win, win->event.point);+				break;++			case NSEventTypeLeftMouseDown:+				win->event.button = RGFW_mouseLeft;+				win->event.type = RGFW_mouseButtonPressed;+				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 1;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+				break;++			case NSEventTypeOtherMouseDown:+				win->event.button = RGFW_mouseMiddle;+				win->event.type = RGFW_mouseButtonPressed;+				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 1;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+				break;++			case NSEventTypeRightMouseDown:+				win->event.button = RGFW_mouseRight;+				win->event.type = RGFW_mouseButtonPressed;+				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 1;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+				break;++			case NSEventTypeLeftMouseUp:+				win->event.button = RGFW_mouseLeft;+				win->event.type = RGFW_mouseButtonReleased;+				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 0;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+				break;++			case NSEventTypeOtherMouseUp:+				win->event.button = RGFW_mouseMiddle;+				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 0;+				win->event.type = RGFW_mouseButtonReleased;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+				break;++			case NSEventTypeRightMouseUp:+				win->event.button = RGFW_mouseRight;+				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 0;+				win->event.type = RGFW_mouseButtonReleased;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+				break;++			case NSEventTypeScrollWheel: {+				double deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));++				if (deltaY > 0) {+					win->event.button = RGFW_mouseScrollUp;+				}+				else if (deltaY < 0) {+					win->event.button = RGFW_mouseScrollDown;+				}++				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;+				RGFW_mouseButtons[win->event.button].current = 1;++				win->event.scroll = deltaY;++				win->event.type = RGFW_mouseButtonPressed;+				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+				break;+			}++			default:+				break;+		}++		objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e);+		((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows"));+				+		objc_msgSend_bool_void(eventPool, sel_registerName("drain"));+		return &win->event;+	}+++	void RGFW_window_move(RGFW_window* win, RGFW_point v) {+		assert(win != NULL);++		win->r.x = v.x;+		win->r.y = v.y;+		((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)+			(win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true);+	}++	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {+		assert(win != NULL);++		win->r.w = a.w;+		win->r.h = a.h;+		((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)+			(win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true);+	}++	void RGFW_window_minimize(RGFW_window* win) {+		assert(win != NULL);++		objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL);+	}++	void RGFW_window_restore(RGFW_window* win) {+		assert(win != NULL);++		objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL);+	}++	void RGFW_window_setName(RGFW_window* win, char* name) {+		assert(win != NULL);++		NSString* str = NSString_stringWithUTF8String(name);+		objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);+	}++	#ifndef RGFW_NO_PASSTHROUGH+	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {+		objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough);+	}+	#endif++	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {+		if (a.w == 0 && a.h == 0)+			return;++		((void (*)(id, SEL, NSSize))objc_msgSend)+			(win->src.window, sel_registerName("setMinSize:"), (NSSize){a.w, a.h});+	}++	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {+		if (a.w == 0 && a.h == 0)+			return;++		((void (*)(id, SEL, NSSize))objc_msgSend)+			(win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h});+	}++	void RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) {+		assert(win != NULL);++		/* code by EimaMei  */+		// Make a bitmap representation, then copy the loaded image into it.+		void* representation = NSBitmapImageRep_initWithBitmapData(NULL, area.w, area.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, area.w * channels, 8 * channels);+		memcpy(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels);++		// Add ze representation.+		void* dock_image = NSImage_initWithSize((NSSize){area.w, area.h});+		NSImage_addRepresentation(dock_image, (void*) representation);++		// Finally, set the dock image to it.+		objc_msgSend_void_id(NSApp, sel_registerName("setApplicationIconImage:"), dock_image);+		// Free the garbage.+		release(dock_image);+		release(representation);+	}++	NSCursor* NSCursor_arrowStr(char* str) {+		void* nclass = objc_getClass("NSCursor");+		void* func = sel_registerName(str);+		return (NSCursor*) objc_msgSend_id(nclass, func);+	}++	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {+		assert(win != NULL);++		if (image == NULL) {+			objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set"));+			return;+		}++		/* NOTE(EimaMei): Code by yours truly. */+		// Make a bitmap representation, then copy the loaded image into it.+		void* representation = NSBitmapImageRep_initWithBitmapData(NULL, a.w, a.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, a.w * channels, 8 * channels);+		memcpy(NSBitmapImageRep_bitmapData(representation), image, a.w * a.h * channels);++		// Add ze representation.+		void* cursor_image = NSImage_initWithSize((NSSize){a.w, a.h});+		NSImage_addRepresentation(cursor_image, representation);++		// Finally, set the cursor image.+		void* cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0});++		objc_msgSend_void(cursor, sel_registerName("set"));++		// Free the garbage.+		release(cursor_image);+		release(representation);+	}++	void RGFW_window_setMouseDefault(RGFW_window* win) {+		RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);+	}++	void RGFW_window_showMouse(RGFW_window* win, i8 show) {+		RGFW_UNUSED(win);++		if (show) {+			CGDisplayShowCursor(kCGDirectMainDisplay);+		}+		else {+			CGDisplayHideCursor(kCGDirectMainDisplay);+		}+	}++	void RGFW_window_setMouseStandard(RGFW_window* win, u8 stdMouses) {+		if (stdMouses > ((sizeof(RGFW_mouseIconSrc)) / (sizeof(char*))))+			return;+		+		char* mouseStr = RGFW_mouseIconSrc[stdMouses];+		void* mouse = NSCursor_arrowStr(mouseStr);++		if (mouse == NULL)+			return;++		RGFW_UNUSED(win);+		CGDisplayShowCursor(kCGDirectMainDisplay);+		objc_msgSend_void(mouse, sel_registerName("set"));+	}+	+	void RGFW_releaseCursor(RGFW_window* win) {+		RGFW_UNUSED(win);+		CGAssociateMouseAndMouseCursorPosition(1);	+	}++	void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { +		RGFW_UNUSED(win)++		CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2)));+		CGAssociateMouseAndMouseCursorPosition(0);+	}++	void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {+		RGFW_UNUSED(win);+		+		CGWarpMouseCursorPosition(CGPointMake(v.x, v.y));		+	}+++	void RGFW_window_hide(RGFW_window* win) {+		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false);+	}++	void RGFW_window_show(RGFW_window* win) {+		((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);+		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);+	}++	u8 RGFW_window_isFullscreen(RGFW_window* win) {+		assert(win != NULL);++		NSWindowStyleMask mask = (NSWindowStyleMask) objc_msgSend_uint(win->src.window, sel_registerName("styleMask"));+		return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;+	}++	u8 RGFW_window_isHidden(RGFW_window* win) {+		assert(win != NULL);++		bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible"));+		return visible == NO && !RGFW_window_isMinimized(win);+	}++	u8 RGFW_window_isMinimized(RGFW_window* win) {+		assert(win != NULL);++		return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES;+	}++	u8 RGFW_window_isMaximized(RGFW_window* win) {+		assert(win != NULL);++		return objc_msgSend_bool(win->src.window, sel_registerName("isZoomed"));+	}++	static RGFW_monitor RGFW_NSCreateMonitor(CGDirectDisplayID display) {+		RGFW_monitor monitor;++		CGRect bounds = CGDisplayBounds(display);+		monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height);++		CGSize screenSizeMM = CGDisplayScreenSize(display);+		monitor.physW = screenSizeMM.width;+		monitor.physH = screenSizeMM.height;++		monitor.scaleX = ((monitor.rect.w / (screenSizeMM.width / 25.4)) / 96) + 0.25;+		monitor.scaleY = ((monitor.rect.h / (screenSizeMM.height / 25.4)) / 96) + 0.25;++		return monitor;+	}+++	static RGFW_monitor RGFW_monitors[7];++	RGFW_monitor* RGFW_getMonitors(void) {+		static CGDirectDisplayID displays[7];+		u32 count;++		if (CGGetActiveDisplayList(6, displays, &count) != kCGErrorSuccess)+			return NULL;++		for (u32 i = 0; i < count; i++)+			RGFW_monitors[i] = RGFW_NSCreateMonitor(displays[i]);++		return RGFW_monitors;+	}++	RGFW_monitor RGFW_getPrimaryMonitor(void) {+		CGDirectDisplayID primary = CGMainDisplayID();+		return RGFW_NSCreateMonitor(primary);+	}++	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {+		return RGFW_NSCreateMonitor(win->src.display);+	}++	char* RGFW_readClipboard(size_t* size) {+		char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString);+		+		size_t clip_len = 1;++		if (clip != NULL) {+			clip_len = strlen(clip) + 1; +		}++		char* str = (char*)RGFW_MALLOC(sizeof(char) * clip_len);+		+		if (clip != NULL) {+			strncpy(str, clip, clip_len);+		}++		str[clip_len] = '\0';+		+		if (size != NULL)+			*size = clip_len;+		return str;+	}++	void RGFW_writeClipboard(const char* text, u32 textLen) {+		RGFW_UNUSED(textLen);++		NSPasteboardType array[] = { NSPasteboardTypeString, NULL };+		NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL);++		NSPasteBoard_setString(NSPasteboard_generalPasteboard(), text, NSPasteboardTypeString);+	}++	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {+		RGFW_UNUSED(jsNumber);++		assert(win != NULL);++		return RGFW_registerJoystickF(win, (char*) "");+	}++	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {+		RGFW_UNUSED(file);++		assert(win != NULL);++		return RGFW_joystickCount - 1;+	}++	#ifdef RGFW_OPENGL+	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {+		assert(win != NULL);+		objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext"));+	}+	#endif++	#if !defined(RGFW_EGL)+	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {+		assert(win != NULL);+		#if defined(RGFW_OPENGL)+		+		NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222);+		#else+		RGFW_UNUSED(swapInterval);+		#endif+	}+	#endif+	+	// Function to create a CGImageRef from an array of bytes+	CGImageRef createImageFromBytes(unsigned char *buffer, int width, int height)+	{+		// Define color space+        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();+        // Create bitmap context+        CGContextRef context = CGBitmapContextCreate(+        		buffer, +        		width, height,+        		8,+        		RGFW_bufferSize.w * 4, +        		colorSpace,+        		kCGImageAlphaPremultipliedLast);+        // Create image from bitmap context+        CGImageRef image = CGBitmapContextCreateImage(context);+        // Release the color space and context+        CGColorSpaceRelease(colorSpace);+        CGContextRelease(context);+                         +        return image;+    }++	void RGFW_window_swapBuffers(RGFW_window* win) {+		assert(win != NULL);+		/* clear the window*/++		if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+			#ifdef RGFW_OSMESA+			RGFW_OSMesa_reorganize();+			#endif++			void* view = NSWindow_contentView(win->src.window);+			void* layer = objc_msgSend_id(view, sel_registerName("layer"));++			((void(*)(id, SEL, NSRect))objc_msgSend)(layer,+				sel_registerName("setFrame:"),+				(NSRect){{0, 0}, {win->r.w, win->r.h}});++            CGImageRef image = createImageFromBytes(win->buffer, win->r.w, win->r.h);+            // Get the current graphics context+            id graphicsContext = objc_msgSend_class(objc_getClass("NSGraphicsContext"), sel_registerName("currentContext"));+            // Get the CGContext from the current NSGraphicsContext+            id cgContext = objc_msgSend_id(graphicsContext, sel_registerName("graphicsPort"));+			// Draw the image in the context+			NSRect bounds = (NSRect){{0,0}, {win->r.w, win->r.h}};+		    CGContextDrawImage((void*)cgContext, *(CGRect*)&bounds, image);+          	// Flush the graphics context to ensure the drawing is displayed+            objc_msgSend_id(graphicsContext, sel_registerName("flushGraphics"));+            +            objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id)image);+            objc_msgSend_id(layer, sel_registerName("setNeedsDisplay"));+            +            CGImageRelease(image);+#endif+		}++		if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) {+			#ifdef RGFW_EGL+					eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);+			#elif defined(RGFW_OPENGL)+					objc_msgSend_void(win->src.ctx, sel_registerName("flushBuffer"));+			#endif+		}+	}++	void RGFW_window_close(RGFW_window* win) {+		assert(win != NULL);+		release(win->src.view);++#ifdef RGFW_ALLOC_DROPFILES+		{+			u32 i;+			for (i = 0; i < RGFW_MAX_DROPS; i++)+				RGFW_FREE(win->event.droppedFiles[i]);+++			RGFW_FREE(win->event.droppedFiles);+		}+#endif+	+#ifdef RGFW_BUFFER+		release(win->src.bitmap);+		release(win->src.image);+#endif++		CVDisplayLinkStop(win->src.displayLink);+		CVDisplayLinkRelease(win->src.displayLink);++		RGFW_FREE(win);+	}++	u64 RGFW_getTimeNS(void) {+		static mach_timebase_info_data_t timebase_info;+		if (timebase_info.denom == 0) {+			mach_timebase_info(&timebase_info);+		}+		return mach_absolute_time() * timebase_info.numer / timebase_info.denom;+	}++	u64 RGFW_getTime(void) {+		static mach_timebase_info_data_t timebase_info;+		if (timebase_info.denom == 0) {+			mach_timebase_info(&timebase_info);+		}+		return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9);+	}+#endif /* RGFW_MACOS */++/*+	End of MaOS defines+*/++/*+	WEBASM defines+*/++#ifdef RGFW_WEBASM+RGFW_Event RGFW_events[20];+size_t RGFW_eventLen = 0;++EM_BOOL Emscripten_on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);+	+	RGFW_events[RGFW_eventLen].type = RGFW_keyPressed;+	memcpy(RGFW_events[RGFW_eventLen].keyName, e->key, 16);+	RGFW_events[RGFW_eventLen].keyCode = RGFW_apiKeyCodeToRGFW(e->keyCode);+	RGFW_events[RGFW_eventLen].lockState = 0;+	RGFW_eventLen++;++	RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current;+	RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 1;+	RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 1);+	+    return EM_TRUE;+}++EM_BOOL Emscripten_on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);++	RGFW_events[RGFW_eventLen].type = RGFW_keyReleased;+	memcpy(RGFW_events[RGFW_eventLen].keyName, e->key, 16);+	RGFW_events[RGFW_eventLen].keyCode = RGFW_apiKeyCodeToRGFW(e->keyCode);+	RGFW_events[RGFW_eventLen].lockState = 0;+	RGFW_eventLen++;++	RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current;+	RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 0;++	RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 0);++    return EM_TRUE;+}++EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);++	RGFW_events[RGFW_eventLen].type = RGFW_windowResized;+	RGFW_eventLen++;++	RGFW_windowResizeCallback(RGFW_root, RGFW_RECT(0, 0, e->windowInnerWidth, e->windowInnerHeight));+    return EM_TRUE;+}++EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);++	RGFW_events[RGFW_eventLen].type = RGFW_windowResized;+	RGFW_eventLen++;++	RGFW_root->r = RGFW_RECT(0, 0, e->elementWidth, e->elementHeight);+	RGFW_windowResizeCallback(RGFW_root, RGFW_root->r);+    return EM_TRUE;+}++EM_BOOL Emscripten_on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e);++	RGFW_events[RGFW_eventLen].type = RGFW_focusIn;+	RGFW_eventLen++;++	RGFW_root->event.inFocus = 1;+	RGFW_focusCallback(RGFW_root, 1);+    return EM_TRUE;+}++EM_BOOL Emscripten_on_focusout(int eventType, const EmscriptenFocusEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e);++	RGFW_events[RGFW_eventLen].type = RGFW_focusOut;+	RGFW_eventLen++;++	RGFW_root->event.inFocus = 0;+	RGFW_focusCallback(RGFW_root, 0);+    return EM_TRUE;+}++EM_BOOL Emscripten_on_mousemove(int eventType, const EmscriptenMouseEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);++	RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged;++	if ((RGFW_root->_winArgs & RGFW_HOLD_MOUSE)) {+		RGFW_point p = RGFW_POINT(e->movementX, e->movementY);+		RGFW_events[RGFW_eventLen].point = p;+	}+	else+		RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY);+	RGFW_eventLen++;+	+	RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);+    return EM_TRUE;+}++EM_BOOL Emscripten_on_mousedown(int eventType, const EmscriptenMouseEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);++	RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;+	RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY);+	RGFW_events[RGFW_eventLen].button = e->button + 1; +	RGFW_events[RGFW_eventLen].scroll = 0;++	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;	+	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;++	RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);+	RGFW_eventLen++;+	+    return EM_TRUE;+}++EM_BOOL Emscripten_on_mouseup(int eventType, const EmscriptenMouseEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);++	RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased;+	RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY);+	RGFW_events[RGFW_eventLen].button = e->button + 1; +	RGFW_events[RGFW_eventLen].scroll = 0;++	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;	+	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0;++	RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0);+	RGFW_eventLen++;+    return EM_TRUE;+}++EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);++	RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;+	RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->mouse.targetX, e->mouse.targetY);+	RGFW_events[RGFW_eventLen].button = RGFW_mouseScrollUp + (e->deltaY < 0); +	RGFW_events[RGFW_eventLen].scroll = e->deltaY;++	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;	+	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;++	RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);+	RGFW_eventLen++;++    return EM_TRUE;+}++EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) { +	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);++    size_t i; +    for (i = 0; i < (size_t)e->numTouches; i++) { +	    RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;+	    RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);+	    RGFW_events[RGFW_eventLen].button = 1; +	    RGFW_events[RGFW_eventLen].scroll = 0;+++	    RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;	+	    RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;++        RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);++	    RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);+    	RGFW_eventLen++;+    }++	return EM_TRUE;+}+EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) { +	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);+    +    size_t i; +    for (i = 0; i < (size_t)e->numTouches; i++) { +   	    RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged;+	    RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);++        RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);+	    RGFW_eventLen++;+    }+    return EM_TRUE;+}++EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* e, void* userData) {+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);+	+    size_t i; +    for (i = 0; i < (size_t)e->numTouches; i++) { +	    RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased;+	    RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);+	    RGFW_events[RGFW_eventLen].button = 1; +	    RGFW_events[RGFW_eventLen].scroll = 0;++	    RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;	+	    RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0;+        +	    RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0);+	    RGFW_eventLen++;+    }+	return EM_TRUE;+}++EM_BOOL Emscripten_on_touchcancel(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); return EM_TRUE; }++EM_BOOL Emscripten_on_gamepad(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) {	+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);++	if (gamepadEvent->index >= 4)+		return 0;++	RGFW_joysticks[gamepadEvent->index] = gamepadEvent->connected;++    return 1; // The event was consumed by the callback handler+}++void EMSCRIPTEN_KEEPALIVE Emscripten_onDrop(size_t count) {+	if (!(RGFW_root->_winArgs & RGFW_ALLOW_DND))+		return;++	RGFW_events[RGFW_eventLen].droppedFilesCount = count;	+	RGFW_dndCallback(RGFW_root, RGFW_events[RGFW_eventLen].droppedFiles, count);+	RGFW_eventLen++;+}++b8 RGFW_stopCheckEvents_bool = RGFW_FALSE;+void RGFW_stopCheckEvents(void) { +	RGFW_stopCheckEvents_bool = RGFW_TRUE;+}++void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {+	RGFW_UNUSED(win);++	if (waitMS == 0)+		return;+	+	u32 start = (u32)(((u64)RGFW_getTimeNS()) / 1e+6);++	while ((RGFW_eventLen == 0) && RGFW_stopCheckEvents_bool == RGFW_FALSE && +		(waitMS < 0 || (RGFW_getTimeNS() / 1e+6) - start < waitMS)+	) {+		emscripten_sleep(0);+	}+	+	RGFW_stopCheckEvents_bool = RGFW_FALSE;+}++RGFWDEF void RGFW_init_buffer(RGFW_window* win);+void RGFW_init_buffer(RGFW_window* win) {+	#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+		if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)+			RGFW_bufferSize = RGFW_getScreenSize();+		+		win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);+	#ifdef RGFW_OSMESA+			win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);+			OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);+	#endif+	#else+	RGFW_UNUSED(win); /*!< if buffer rendering is not being used */+	#endif+}++void EMSCRIPTEN_KEEPALIVE RGFW_makeSetValue(size_t index, char* file) { +	/* This seems like a terrible idea, don't replicate this unless you hate yourself or the OS */+	/* TODO: find a better way to do this, +		strcpy doesn't seem to work, maybe because of asyncio+	*/++	RGFW_events[RGFW_eventLen].type = RGFW_dnd;+	char** arr = (char**)&RGFW_events[RGFW_eventLen].droppedFiles[index];+	*arr = file;+}++#include <sys/stat.h>+#include <sys/types.h>+#include <errno.h>++void EMSCRIPTEN_KEEPALIVE RGFW_mkdir(char* name) { mkdir(name, 0755); }++void EMSCRIPTEN_KEEPALIVE RGFW_writeFile(const char *path, const char *data, size_t len) {+    FILE* file = fopen(path, "w+");+	if (file == NULL)+		return;++    fwrite(data, sizeof(char), len, file);+    fclose(file);+}++RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {+	RGFW_UNUSED(name) ++	RGFW_UNUSED(RGFW_initFormatAttribs);+	+    RGFW_window* win = RGFW_window_basic_init(rect, args);++    EmscriptenWebGLContextAttributes attrs;+    attrs.alpha = EM_TRUE;+    attrs.depth = EM_TRUE;+	attrs.alpha = EM_TRUE;+    attrs.stencil = RGFW_STENCIL;+    attrs.antialias = RGFW_SAMPLES;+    attrs.premultipliedAlpha = EM_TRUE;+    attrs.preserveDrawingBuffer = EM_FALSE;+	+    if (RGFW_DOUBLE_BUFFER == 0)+        attrs.renderViaOffscreenBackBuffer = 0;+    else+        attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS;+    +    attrs.failIfMajorPerformanceCaveat = EM_FALSE;+	attrs.majorVersion = (RGFW_majorVersion == 0) ? 1 : RGFW_majorVersion;+	attrs.minorVersion = RGFW_minorVersion;+	+    attrs.enableExtensionsByDefault = EM_TRUE;+    attrs.explicitSwapControl = EM_TRUE;++    emscripten_webgl_init_context_attributes(&attrs);+    win->src.ctx = emscripten_webgl_create_context("#canvas", &attrs);+    emscripten_webgl_make_context_current(win->src.ctx);++	#ifdef LEGACY_GL_EMULATION+	EM_ASM("Module.useWebGL = true; GLImmediate.init();");	+	#endif++	emscripten_set_canvas_element_size("#canvas", rect.w, rect.h);+	emscripten_set_window_title(name);++	/* load callbacks */+    emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keydown);+    emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keyup);+    emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_resize);+    emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, Emscripten_on_fullscreenchange);+    emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousemove);+    emscripten_set_touchstart_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchstart);+    emscripten_set_touchend_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchend);+    emscripten_set_touchmove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchmove);+    emscripten_set_touchcancel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchcancel);+    emscripten_set_mousedown_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousedown);+    emscripten_set_mouseup_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mouseup);+    emscripten_set_wheel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_wheel);+    emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusin);+    emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusout);+	emscripten_set_gamepadconnected_callback(NULL, 1, Emscripten_on_gamepad);+	emscripten_set_gamepaddisconnected_callback(NULL, 1, Emscripten_on_gamepad);+	+	if (args & RGFW_ALLOW_DND)  {+		win->_winArgs |= RGFW_ALLOW_DND;+	}++    EM_ASM({+		var canvas = document.getElementById('canvas');+        canvas.addEventListener('drop', function(e) {+            e.preventDefault();+            if (e.dataTransfer.file < 0)+				return;++			var filenamesArray = [];+			var count = e.dataTransfer.files.length;++			/* Read and save the files to emscripten's files */+			var drop_dir = '.rgfw_dropped_files';+			Module._RGFW_mkdir(drop_dir);++			for (var i = 0; i < count; i++) {+				var file = e.dataTransfer.files[i];++				var path = '/' + drop_dir + '/' + file.name.replace("//", '_');+				var reader = new FileReader();+				+				reader.onloadend = (e) => {+					if (reader.readyState != 2) {+						out('failed to read dropped file: '+file.name+': '+reader.error);+					}+					else {+						var data = e.target.result;+						+						_RGFW_writeFile(path, new Uint8Array(data), file.size);+					}+				};++				reader.readAsArrayBuffer(file);		+				// This works weird on modern opengl+				var filename = stringToNewUTF8(path);++				filenamesArray.push(filename);+				+				Module._RGFW_makeSetValue(i, filename);+			}+			+			Module._Emscripten_onDrop(count);+			+			for (var i = 0; i < count; ++i) {+				_free(filenamesArray[i]);+			}+        }, true);++        canvas.addEventListener('dragover', function(e) { e.preventDefault(); return false; }, true);+    });++	RGFW_init_buffer(win);+	glViewport(0, 0, rect.w, rect.h);+	+	RGFW_root = win; ++	if (args & RGFW_HIDE_MOUSE) {+		RGFW_window_showMouse(win, 0);+	}++	if (args & RGFW_FULLSCREEN) {+		RGFW_window_resize(win, RGFW_getScreenSize());+	}++    return win;+}++RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {+	static u8 index = 0;+	+	if (index == 0) +		RGFW_resetKey();++	/* check gamepads */+    for (int i = 0; (i < emscripten_get_num_gamepads()) && (i < 4); i++) {+		if (RGFW_joysticks[i] == 0)+			continue;;+		+        EmscriptenGamepadEvent gamepadState;++        if (emscripten_get_gamepad_status(i, &gamepadState) != EMSCRIPTEN_RESULT_SUCCESS)+			break;++		// Register buttons data for every connected gamepad+		for (int j = 0; (j < gamepadState.numButtons) && (j < 16); j++) {+			u32 map[] = {+				RGFW_JS_A, RGFW_JS_X, RGFW_JS_B, RGFW_JS_Y,+				RGFW_JS_L1, RGFW_JS_R1, RGFW_JS_L2, RGFW_JS_R2,+				RGFW_JS_SELECT, RGFW_JS_START,+				0, 0,+				RGFW_JS_UP, RGFW_JS_DOWN, RGFW_JS_LEFT, RGFW_JS_RIGHT+			};++			u32 button = map[j]; +			if (RGFW_jsPressed[i][button] != gamepadState.digitalButton[j]) {+				win->event.type = RGFW_jsButtonPressed;+				win->event.joystick = i;+				win->event.button = map[j];+				return &win->event;+			}++			RGFW_jsPressed[i][button] = gamepadState.digitalButton[j];+		}++		for (int j = 0; (j < gamepadState.numAxes) && (j < 4); j += 2) {+			win->event.axisesCount = gamepadState.numAxes;+			if (win->event.axis[j].x != gamepadState.axis[j] || +				win->event.axis[j].y != gamepadState.axis[j + 1]+			) {+				win->event.axis[j].x = gamepadState.axis[j];+				win->event.axis[j].y = gamepadState.axis[j + 1];+				win->event.type = RGFW_jsAxisMove;+				win->event.joystick = i;+				return &win->event;+			}+		}+    }++	/* check queued events */+	if (RGFW_eventLen == 0)+		return NULL;+	+	RGFW_events[index].frameTime = win->event.frameTime;+	RGFW_events[index].frameTime2 = win->event.frameTime2;+	RGFW_events[index].inFocus = win->event.inFocus;++	win->event = RGFW_events[index];++	RGFW_eventLen--;++	if (RGFW_eventLen)+		index++;+	else+		index = 0;++	return &win->event;+}++void RGFW_window_resize(RGFW_window* win, RGFW_area a) {+	RGFW_UNUSED(win)+	emscripten_set_canvas_element_size("#canvas", a.w, a.h);+}++/* NOTE: I don't know if this is possible */+void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win); RGFW_UNUSED(v); }+/* this one might be possible but it looks iffy */+void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { RGFW_UNUSED(win); RGFW_UNUSED(channels) RGFW_UNUSED(a) RGFW_UNUSED(image) }++const char RGFW_CURSORS[11][12] = {+    "default",+    "default",+    "text",+    "crosshair",+    "pointer",+    "ew-resize",+    "ns-resize",+    "nwse-resize",+    "nesw-resize",+    "move",+    "not-allowed"+};++void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {+	RGFW_UNUSED(win)+	EM_ASM( { document.getElementById("canvas").style.cursor = UTF8ToString($0); }, RGFW_CURSORS[mouse]);+}++void RGFW_window_setMouseDefault(RGFW_window* win) {+	RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL);+}++void RGFW_window_showMouse(RGFW_window* win, i8 show) {+	if (show)+		RGFW_window_setMouseDefault(win);+	else+		EM_ASM(document.getElementById('canvas').style.cursor = 'none';);+}++RGFW_point RGFW_getGlobalMousePoint(void) {+    RGFW_point point;+    point.x = EM_ASM_INT({+        return window.mouseX || 0;+    });+    point.y = EM_ASM_INT({+        return window.mouseY || 0;+    });+    return point;+}++RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {+	RGFW_UNUSED(win);+	+	EmscriptenMouseEvent mouseEvent;+    emscripten_get_mouse_status(&mouseEvent);+	return RGFW_POINT( mouseEvent.targetX,  mouseEvent.targetY);+}++void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {+	RGFW_UNUSED(win);++    EM_ASM_({+        var canvas = document.getElementById('canvas');+        if ($0) {+            canvas.style.pointerEvents = 'none';+        } else {+            canvas.style.pointerEvents = 'auto';+        }+    }, passthrough);+}++void RGFW_writeClipboard(const char* text, u32 textLen) {+	RGFW_UNUSED(textLen)+	EM_ASM({ navigator.clipboard.writeText(UTF8ToString($0)); }, text);+}+++char* RGFW_readClipboard(size_t* size) {+	/*+		placeholder code for later+		I'm not sure if this is possible do the the async stuff+	*/+	+	if (size != NULL)+		*size = 0;+	+	char* str = (char*)malloc(1);+	str[0] = '\0';++	return str;+}++void RGFW_window_swapBuffers(RGFW_window* win) {+	RGFW_UNUSED(win);+	+	#ifdef RGFW_BUFFER+	if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {		+		glEnable(GL_TEXTURE_2D);++		GLuint texture;+		glGenTextures(1,&texture);++		glBindTexture(GL_TEXTURE_2D,texture);+		+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);++		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RGFW_bufferSize.w, RGFW_bufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, win->buffer);+		+		float ratioX = ((float)win->r.w / (float)RGFW_bufferSize.w);+		float ratioY = ((float)win->r.h / (float)RGFW_bufferSize.h);++		// Set up the viewport+		glClear(GL_COLOR_BUFFER_BIT);++		glBegin(GL_TRIANGLES);+			glTexCoord2f(0, ratioY); glColor3f(1, 1, 1); glVertex2f(-1, -1);+			glTexCoord2f(0, 0); glColor3f(1, 1, 1); glVertex2f(-1, 1);+			glTexCoord2f(ratioX, ratioY); glColor3f(1, 1, 1); glVertex2f(1, -1);++			glTexCoord2f(ratioX, 0); glColor3f(1, 1, 1); glVertex2f(1, 1);+			glTexCoord2f(ratioX, ratioY); glColor3f(1, 1, 1); glVertex2f(1, -1);+			glTexCoord2f(0, 0); glColor3f(1, 1, 1); glVertex2f(-1, 1);+		glEnd();++		glDeleteTextures(1, &texture);+	}+	#endif++	emscripten_webgl_commit_frame();+	emscripten_sleep(0);+}+++void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {+	if (win == NULL)+	    emscripten_webgl_make_context_current(0);+	else+	    emscripten_webgl_make_context_current(win->src.ctx);+}++#ifndef RGFW_EGL+void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); }+#endif++void RGFW_window_close(RGFW_window* win) {+    emscripten_webgl_destroy_context(win->src.ctx);++    free(win);+}++int RGFW_innerWidth(void) {   return EM_ASM_INT({ return window.innerWidth; });  }+int RGFW_innerHeight(void) {  return EM_ASM_INT({ return window.innerHeight; });  }++RGFW_area RGFW_getScreenSize(void) {+	return RGFW_AREA(RGFW_innerWidth(), RGFW_innerHeight());+}++void* RGFW_getProcAddress(const char* procname) { +	return emscripten_webgl_get_proc_address(procname);+}++void RGFW_sleep(u64 milisecond) {+	emscripten_sleep(milisecond);+}++u64 RGFW_getTimeNS(void) {+	return emscripten_get_now() * 1e+6;+}++u64 RGFW_getTime(void) {+	return emscripten_get_now() * 1000;+}++void RGFW_releaseCursor(RGFW_window* win) {+	RGFW_UNUSED(win);+	emscripten_exit_pointerlock();+}++void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { +	RGFW_UNUSED(win); RGFW_UNUSED(r);++	emscripten_request_pointerlock("#canvas", 1);+}+++void RGFW_window_setName(RGFW_window* win, char* name) {+	RGFW_UNUSED(win);+	emscripten_set_window_title(name);+}++/* unsupported functions */+RGFW_monitor* RGFW_getMonitors(void) { return NULL; }+RGFW_monitor RGFW_getPrimaryMonitor(void) { return (RGFW_monitor){}; }+void RGFW_window_move(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win) RGFW_UNUSED(v) }+void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a)  }+void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a)  }+void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win)}+void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win) }+void RGFW_window_setBorder(RGFW_window* win, b8 border) { RGFW_UNUSED(win) RGFW_UNUSED(border)  }+void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(win) RGFW_UNUSED(icon) RGFW_UNUSED(a) RGFW_UNUSED(channels)  }+void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win) }+void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win) }+b8 RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win) return 0; }+b8 RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win) return 0; }+b8 RGFW_window_isMaximized(RGFW_window* win) { RGFW_UNUSED(win) return 0; }+RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return (RGFW_monitor){}; }++#endif++/* end of web asm defines */++/* unix (macOS, linux, web asm) only stuff */+#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM)  || defined(RGFW_WAYLAND)+/* unix threading */+#ifndef RGFW_NO_THREADS+#include <pthread.h>++	RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) {+		RGFW_UNUSED(args);+		+		RGFW_thread t;+		pthread_create((pthread_t*) &t, NULL, *ptr, NULL);+		return t;+	}+	void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); }+	void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); }+#ifdef __linux__+	void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio((pthread_t)thread, priority); }+#endif+#endif++#ifndef RGFW_WEBASM+/* unix sleep */+	void RGFW_sleep(u64 ms) {+		struct timespec time;+		time.tv_sec = 0;+		time.tv_nsec = ms * 1e+6;++		nanosleep(&time, NULL);+	}+#endif++#endif /* end of unix / mac stuff*/+#endif /*RGFW_IMPLEMENTATION*/++#if defined(__cplusplus) && !defined(__EMSCRIPTEN__) } #endif
raylib/src/external/glfw/src/mappings.h view
@@ -996,6 +996,7 @@ "03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,", "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux,", #endif // GLFW_BUILD_LINUX_JOYSTICK }; 
raylib/src/external/jar_xm.h view
@@ -1204,7 +1204,7 @@ }  static void jar_xm_pitch_slide(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch, float period_offset) {-    /* Don't ask about the 4.f coefficient. I found mention of it nowhere. Found by ear™. */+    /* Don't ask about the 4.f coefficient. I found mention of it nowhere. Found by ear. */     if(ctx->module.frequency_type == jar_xm_LINEAR_FREQUENCIES) {period_offset *= 4.f; }     ch->period += period_offset;     jar_xm_CLAMP_DOWN(ch->period);@@ -1507,7 +1507,7 @@             jar_xm_volume_slide(ch, ch->fine_volume_slide_param);             break;         case 0xD: /* EDy: Note delay */-            /* XXX: figure this out better. EDx triggers the note even when there no note and no instrument. But ED0 acts like like a ghost note, EDx (x ≠ 0) does not. */+            /* XXX: figure this out better. EDx triggers the note even when there no note and no instrument. But ED0 acts like like a ghost note, EDx (x != 0) does not. */             if(s->note == 0 && s->instrument == 0) {                 unsigned int flags = jar_xm_TRIGGER_KEEP_VOLUME;                 if(ch->current->effect_param & 0x0F) {@@ -1795,7 +1795,7 @@             if(ch->current->effect_param > 0) {                 char arp_offset = ctx->tempo % 3;                 switch(arp_offset) {-                case 2: /* 0 -> x -> 0 -> y -> x -> … */+                case 2: /* 0 -> x -> 0 -> y -> x -> ... */                     if(ctx->current_tick == 1) {                         ch->arp_in_progress = true;                         ch->arp_note_offset = ch->current->effect_param >> 4;@@ -1803,7 +1803,7 @@                         break;                     }                     /* No break here, this is intended */-                case 1: /* 0 -> 0 -> y -> x -> … */+                case 1: /* 0 -> 0 -> y -> x -> ... */                     if(ctx->current_tick == 0) {                         ch->arp_in_progress = false;                         ch->arp_note_offset = 0;@@ -1811,7 +1811,7 @@                         break;                     }                     /* No break here, this is intended */-                case 0: /* 0 -> y -> x -> … */+                case 0: /* 0 -> y -> x -> ... */                     jar_xm_arpeggio(ctx, ch, ch->current->effect_param, ctx->current_tick - arp_offset);                 default:                     break;
raylib/src/external/miniaudio.h view

file too large to diff

− raylib/src/external/nanosvg.h
@@ -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 <string.h>-#include <stdlib.h>-#include <stdio.h>-#include <math.h>--#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
− raylib/src/external/nanosvgrast.h
@@ -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 <math.h>-#include <stdlib.h>-#include <string.h>--#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, "<svg viewBox=\"%f %f %f %f\" xmlns=\"http://www.w3.org/2000/svg\">", xmin, ymin, (xmax - xmin), (ymax - ymin));--	for (i = 0; i < r->nedges; i++) {-		e = &r->edges[i];-		fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#000;\" />", e->x0,e->y0, e->x1,e->y1);-	}--	for (i = 0; i < r->npoints; i++) {-		if (i+1 < r->npoints)-			fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#f00;\" />", r->points[i].x, r->points[i].y, r->points[i+1].x, r->points[i+1].y);-		fprintf(fp ,"<circle cx=\"%f\" cy=\"%f\" r=\"1\" style=\"fill:%s;\" />", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : "#0f0");-	}--	fprintf(fp, "</svg>");-	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
raylib/src/external/par_shapes.h view
@@ -1130,7 +1130,7 @@             total += rule->weight;         }     }-    float r = (float) rand() / RAND_MAX;+    float r = (float) rand() / (float) RAND_MAX;     float t = 0;     for (int i = 0; i < nrules; i++) {         rule = rules + i;
raylib/src/external/stb_image_resize2.h view
@@ -1,10303 +1,10572 @@-/* stb_image_resize2 - v2.01 - public domain image resizing-   -   by Jeff Roberts (v2) and Jorge L Rodriguez -   http://github.com/nothings/stb--   Can be threaded with the extended API. SSE2, AVX, Neon and WASM SIMD support. Only -   scaling and translation is supported, no rotations or shears.--   COMPILING & LINKING-      In one C/C++ file that #includes this file, do this:-         #define STB_IMAGE_RESIZE_IMPLEMENTATION-      before the #include. That will create the implementation in that file.--   PORTING FROM VERSION 1--      The API has changed. You can continue to use the old version of stb_image_resize.h,-      which is available in the "deprecated/" directory.--      If you're using the old simple-to-use API, porting is straightforward.-      (For more advanced APIs, read the documentation.)--        stbir_resize_uint8():-          - call `stbir_resize_uint8_linear`, cast channel count to `stbir_pixel_layout`--        stbir_resize_float():-          - call `stbir_resize_float_linear`, cast channel count to `stbir_pixel_layout`--        stbir_resize_uint8_srgb():-          - function name is unchanged-          - cast channel count to `stbir_pixel_layout`-          - above is sufficient unless your image has alpha and it's not RGBA/BGRA-            - in that case, follow the below instructions for stbir_resize_uint8_srgb_edgemode--        stbir_resize_uint8_srgb_edgemode()-          - switch to the "medium complexity" API-          - stbir_resize(), very similar API but a few more parameters:-            - pixel_layout: cast channel count to `stbir_pixel_layout`-            - data_type:    STBIR_TYPE_UINT8_SRGB-            - edge:         unchanged (STBIR_EDGE_WRAP, etc.)-            - filter:       STBIR_FILTER_DEFAULT-          - which channel is alpha is specified in stbir_pixel_layout, see enum for details--   EASY API CALLS:-     Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation, clamps to edge.--     stbir_resize_uint8_srgb( input_pixels,  input_w,  input_h,  input_stride_in_bytes,-                              output_pixels, output_w, output_h, output_stride_in_bytes,-                              pixel_layout_enum )--     stbir_resize_uint8_linear( input_pixels,  input_w,  input_h,  input_stride_in_bytes,-                                output_pixels, output_w, output_h, output_stride_in_bytes,-                                pixel_layout_enum )--     stbir_resize_float_linear( input_pixels,  input_w,  input_h,  input_stride_in_bytes,-                                output_pixels, output_w, output_h, output_stride_in_bytes,-                                pixel_layout_enum )--     If you pass NULL or zero for the output_pixels, we will allocate the output buffer-     for you and return it from the function (free with free() or STBIR_FREE).-     As a special case, XX_stride_in_bytes of 0 means packed continuously in memory.--   API LEVELS-      There are three levels of API - easy-to-use, medium-complexity and extended-complexity.--      See the "header file" section of the source for API documentation.--   ADDITIONAL DOCUMENTATION--      MEMORY ALLOCATION-         By default, we use malloc and free for memory allocation.  To override the -         memory allocation, before the implementation #include, add a:--            #define STBIR_MALLOC(size,user_data) ...-            #define STBIR_FREE(ptr,user_data)   ...--         Each resize makes exactly one call to malloc/free (unless you use the -         extended API where you can do one allocation for many resizes). Under-         address sanitizer, we do separate allocations to find overread/writes.--      PERFORMANCE-         This library was written with an emphasis on performance. When testing-         stb_image_resize with RGBA, the fastest mode is STBIR_4CHANNEL with -         STBIR_TYPE_UINT8 pixels and CLAMPed edges (which is what many other resize-         libs do by default). Also, make sure SIMD is turned on of course (default -         for 64-bit targets). Avoid WRAP edge mode if you want the fastest speed.--         This library also comes with profiling built-in. If you define STBIR_PROFILE,-         you can use the advanced API and get low-level profiling information by -         calling stbir_resize_extended_profile_info() or stbir_resize_split_profile_info()-         after a resize.--      SIMD-         Most of the routines have optimized SSE2, AVX, NEON and WASM versions. --         On Microsoft compilers, we automatically turn on SIMD for 64-bit x64 and -         ARM; for 32-bit x86 and ARM, you select SIMD mode by defining STBIR_SSE2 or -         STBIR_NEON. For AVX and AVX2, we auto-select it by detecting the /arch:AVX-         or /arch:AVX2 switches. You can also always manually turn SSE2, AVX or AVX2 -         support on by defining STBIR_SSE2, STBIR_AVX or STBIR_AVX2.--         On Linux, SSE2 and Neon is on by default for 64-bit x64 or ARM64. For 32-bit,-         we select x86 SIMD mode by whether you have -msse2, -mavx or -mavx2 enabled-         on the command line. For 32-bit ARM, you must pass -mfpu=neon-vfpv4 for both-         clang and GCC, but GCC also requires an additional -mfp16-format=ieee to -         automatically enable NEON.--         On x86 platforms, you can also define STBIR_FP16C to turn on FP16C instructions-         for converting back and forth to half-floats. This is autoselected when we-         are using AVX2. Clang and GCC also require the -mf16c switch. ARM always uses -         the built-in half float hardware NEON instructions. --         You can also tell us to use multiply-add instructions with STBIR_USE_FMA. -         Because x86 doesn't always have fma, we turn it off by default to maintain-         determinism across all platforms. If you don't care about non-FMA determinism-         and are willing to restrict yourself to more recent x86 CPUs (around the AVX -         timeframe), then fma will give you around a 15% speedup.--         You can force off SIMD in all cases by defining STBIR_NO_SIMD. You can turn-         off AVX or AVX2 specifically with STBIR_NO_AVX or STBIR_NO_AVX2. AVX is 10%-         to 40% faster, and AVX2 is generally another 12%.-        -      ALPHA CHANNEL-         Most of the resizing functions provide the ability to control how the alpha -         channel of an image is processed.--         When alpha represents transparency, it is important that when combining-         colors with filtering, the pixels should not be treated equally; they-         should use a weighted average based on their alpha values. For example,-         if a pixel is 1% opaque bright green and another pixel is 99% opaque-         black and you average them, the average will be 50% opaque, but the-         unweighted average and will be a middling green color, while the weighted-         average will be nearly black. This means the unweighted version introduced-         green energy that didn't exist in the source image.--         (If you want to know why this makes sense, you can work out the math for-         the following: consider what happens if you alpha composite a source image-         over a fixed color and then average the output, vs. if you average the-         source image pixels and then composite that over the same fixed color.-         Only the weighted average produces the same result as the ground truth-         composite-then-average result.)--         Therefore, it is in general best to "alpha weight" the pixels when applying-         filters to them. This essentially means multiplying the colors by the alpha-         values before combining them, and then dividing by the alpha value at the-         end.--         The computer graphics industry introduced a technique called "premultiplied-         alpha" or "associated alpha" in which image colors are stored in image files-         already multiplied by their alpha. This saves some math when compositing,-         and also avoids the need to divide by the alpha at the end (which is quite-         inefficient). However, while premultiplied alpha is common in the movie CGI-         industry, it is not commonplace in other industries like videogames, and most-         consumer file formats are generally expected to contain not-premultiplied-         colors. For example, Photoshop saves PNG files "unpremultiplied", and web-         browsers like Chrome and Firefox expect PNG images to be unpremultiplied.--         Note that there are three possibilities that might describe your image-         and resize expectation:--             1. images are not premultiplied, alpha weighting is desired-             2. images are not premultiplied, alpha weighting is not desired-             3. images are premultiplied--         Both case #2 and case #3 require the exact same math: no alpha weighting-         should be applied or removed. Only case 1 requires extra math operations;-         the other two cases can be handled identically.--         stb_image_resize expects case #1 by default, applying alpha weighting to-         images, expecting the input images to be unpremultiplied. This is what the-         COLOR+ALPHA buffer types tell the resizer to do. --         When you use the pixel layouts STBIR_RGBA, STBIR_BGRA, STBIR_ARGB, -         STBIR_ABGR, STBIR_RX, or STBIR_XR you are telling us that the pixels are -         non-premultiplied. In these cases, the resizer will alpha weight the colors -         (effectively creating the premultiplied image), do the filtering, and then -         convert back to non-premult on exit.--         When you use the pixel layouts STBIR_RGBA_PM, STBIR_RGBA_PM, STBIR_RGBA_PM,-         STBIR_RGBA_PM, STBIR_RX_PM or STBIR_XR_PM, you are telling that the pixels -         ARE premultiplied. In this case, the resizer doesn't have to do the -         premultipling - it can filter directly on the input. This about twice as -         fast as the non-premultiplied case, so it's the right option if your data is -         already setup correctly.--         When you use the pixel layout STBIR_4CHANNEL or STBIR_2CHANNEL, you are -         telling us that there is no channel that represents transparency; it may be -         RGB and some unrelated fourth channel that has been stored in the alpha -         channel, but it is actually not alpha. No special processing will be -         performed. --         The difference between the generic 4 or 2 channel layouts, and the -         specialized _PM versions is with the _PM versions you are telling us that-         the data *is* alpha, just don't premultiply it. That's important when-         using SRGB pixel formats, we need to know where the alpha is, because-         it is converted linearly (rather than with the SRGB converters).-   -         Because alpha weighting produces the same effect as premultiplying, you-         even have the option with non-premultiplied inputs to let the resizer-         produce a premultiplied output. Because the intially computed alpha-weighted-         output image is effectively premultiplied, this is actually more performant-         than the normal path which un-premultiplies the output image as a final step.--         Finally, when converting both in and out of non-premulitplied space (for-         example, when using STBIR_RGBA), we go to somewhat heroic measures to -         ensure that areas with zero alpha value pixels get something reasonable -         in the RGB values. If you don't care about the RGB values of zero alpha -         pixels, you can call the stbir_set_non_pm_alpha_speed_over_quality() -         function - this runs a premultiplied resize about 25% faster. That said,-         when you really care about speed, using premultiplied pixels for both in-         and out (STBIR_RGBA_PM, etc) much faster than both of these premultiplied-         options.--      PIXEL LAYOUT CONVERSION-         The resizer can convert from some pixel layouts to others. When using the-         stbir_set_pixel_layouts(), you can, for example, specify STBIR_RGBA-         on input, and STBIR_ARGB on output, and it will re-organize the channels-         during the resize. Currently, you can only convert between two pixel-         layouts with the same number of channels.--      DETERMINISM-         We commit to being deterministic (from x64 to ARM to scalar to SIMD, etc). -         This requires compiling with fast-math off (using at least /fp:precise). -         Also, you must turn off fp-contracting (which turns mult+adds into fmas)!-         We attempt to do this with pragmas, but with Clang, you usually want to add -         -ffp-contract=off to the command line as well.--         For 32-bit x86, you must use SSE and SSE2 codegen for determinism. That is, -         if the scalar x87 unit gets used at all, we immediately lose determinism. -         On Microsoft Visual Studio 2008 and earlier, from what we can tell there is-         no way to be deterministic in 32-bit x86 (some x87 always leaks in, even -         with fp:strict). On 32-bit x86 GCC, determinism requires both -msse2 and -         -fpmath=sse.--         Note that we will not be deterministic with float data containing NaNs --         the NaNs will propagate differently on different SIMD and platforms. --         If you turn on STBIR_USE_FMA, then we will be deterministic with other -         fma targets, but we will differ from non-fma targets (this is unavoidable, -         because a fma isn't simply an add with a mult - it also introduces a -         rounding difference compared to non-fma instruction sequences. --      FLOAT PIXEL FORMAT RANGE-         Any range of values can be used for the non-alpha float data that you pass -         in (0 to 1, -1 to 1, whatever). However, if you are inputting float values -         but *outputting* bytes or shorts, you must use a range of 0 to 1 so that we -         scale back properly. The alpha channel must also be 0 to 1 for any format -         that does premultiplication prior to resizing. --         Note also that with float output, using filters with negative lobes, the -         output filtered values might go slightly out of range. You can define -         STBIR_FLOAT_LOW_CLAMP and/or STBIR_FLOAT_HIGH_CLAMP to specify the range -         to clamp to on output, if that's important. --      MAX/MIN SCALE FACTORS-         The input pixel resolutions are in integers, and we do the internal pointer-         resolution in size_t sized integers. However, the scale ratio from input-         resolution to output resolution is calculated in float form. This means-         the effective possible scale ratio is limited to 24 bits (or 16 million-         to 1). As you get close to the size of the float resolution (again, 16-         million pixels wide or high), you might start seeing float inaccuracy-         issues in general in the pipeline. If you have to do extreme resizes,-         you can usually do this is multiple stages (using float intermediate-         buffers).--      FLIPPED IMAGES-         Stride is just the delta from one scanline to the next. This means you can -         use a negative stride to handle inverted images (point to the final -         scanline and use a negative stride). You can invert the input or output,-         using negative strides.--      DEFAULT FILTERS-         For functions which don't provide explicit control over what filters to -         use, you can change the compile-time defaults with:--            #define STBIR_DEFAULT_FILTER_UPSAMPLE     STBIR_FILTER_something-            #define STBIR_DEFAULT_FILTER_DOWNSAMPLE   STBIR_FILTER_something--         See stbir_filter in the header-file section for the list of filters.--      NEW FILTERS-         A number of 1D filter kernels are supplied. For a list of supported -         filters, see the stbir_filter enum. You can install your own filters by -         using the stbir_set_filter_callbacks function.--      PROGRESS-         For interactive use with slow resize operations, you can use the the -         scanline callbacks in the extended API. It would have to be a *very* large -         image resample to need progress though - we're very fast.--      CEIL and FLOOR-         In scalar mode, the only functions we use from math.h are ceilf and floorf, -         but if you have your own versions, you can define the STBIR_CEILF(v) and -         STBIR_FLOORF(v) macros and we'll use them instead. In SIMD, we just use-         our own versions.--      ASSERT-         Define STBIR_ASSERT(boolval) to override assert() and not use assert.h--      FUTURE TODOS-        *  For polyphase integral filters, we just memcpy the coeffs to dupe-           them, but we should indirect and use the same coeff memory.-        *  Add pixel layout conversions for sensible different channel counts-           (maybe, 1->3/4, 3->4, 4->1, 3->1).-         * For SIMD encode and decode scanline routines, do any pre-aligning-           for bad input/output buffer alignments and pitch?-         * For very wide scanlines, we should we do vertical strips to stay within-           L2 cache. Maybe do chunks of 1K pixels at a time. There would be -           some pixel reconversion, but probably dwarfed by things falling out-           of cache. Probably also something possible with alternating between-           scattering and gathering at high resize scales?-         * Rewrite the coefficient generator to do many at once.-         * AVX-512 vertical kernels - worried about downclocking here.-         * Convert the reincludes to macros when we know they aren't changing.-         * Experiment with pivoting the horizontal and always using the-           vertical filters (which are faster, but perhaps not enough to overcome-           the pivot cost and the extra memory touches). Need to buffer the whole-           image so have to balance memory use.-         * Most of our code is internally function pointers, should we compile-           all the SIMD stuff always and dynamically dispatch? --   CONTRIBUTORS-      Jeff Roberts: 2.0 implementation, optimizations, SIMD-      Martins Mozeiko: NEON simd, WASM simd, clang and GCC whisperer.-      Fabian Giesen: half float and srgb converters-      Sean Barrett: API design, optimizations-      Jorge L Rodriguez: Original 1.0 implementation-      Aras Pranckevicius: bugfixes for 1.0-      Nathan Reed: warning fixes for 1.0--   REVISIONS-      2.00 (2022-02-20) mostly new source: new api, optimizations, simd, vertical-first, etc -                       (2x-5x faster without simd, 4x-12x faster with simd)-                       (in some cases, 20x to 40x faster - resizing to very small for example)-      0.96 (2019-03-04) fixed warnings-      0.95 (2017-07-23) fixed warnings-      0.94 (2017-03-18) fixed warnings-      0.93 (2017-03-03) fixed bug with certain combinations of heights-      0.92 (2017-01-02) fix integer overflow on large (>2GB) images-      0.91 (2016-04-02) fix warnings; fix handling of subpixel regions-      0.90 (2014-09-17) first released version--   LICENSE-     See end of file for license information.-*/--#if !defined(STB_IMAGE_RESIZE_DO_HORIZONTALS) && !defined(STB_IMAGE_RESIZE_DO_VERTICALS) && !defined(STB_IMAGE_RESIZE_DO_CODERS)   // for internal re-includes--#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE2_H-#define STBIR_INCLUDE_STB_IMAGE_RESIZE2_H--#include <stddef.h>-#ifdef _MSC_VER-typedef unsigned char    stbir_uint8;-typedef unsigned short   stbir_uint16;-typedef unsigned int     stbir_uint32;-typedef unsigned __int64 stbir_uint64;-#else-#include <stdint.h>-typedef uint8_t  stbir_uint8;-typedef uint16_t stbir_uint16;-typedef uint32_t stbir_uint32;-typedef uint64_t stbir_uint64;-#endif--#ifdef _M_IX86_FP-#if ( _M_IX86_FP >= 1 )-#ifndef STBIR_SSE-#define STBIR_SSE-#endif-#endif-#endif --#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(_M_AMD64) || defined(__SSE2__) || defined(STBIR_SSE) || defined(STBIR_SSE2)-  #ifndef STBIR_SSE2-    #define STBIR_SSE2-  #endif-  #if defined(__AVX__) || defined(STBIR_AVX2)-    #ifndef STBIR_AVX-      #ifndef STBIR_NO_AVX-        #define STBIR_AVX-      #endif-    #endif-  #endif-  #if defined(__AVX2__) || defined(STBIR_AVX2)-    #ifndef STBIR_NO_AVX2-      #ifndef STBIR_AVX2  -        #define STBIR_AVX2-      #endif-      #if defined( _MSC_VER ) && !defined(__clang__)-        #ifndef STBIR_FP16C  // FP16C instructions are on all AVX2 cpus, so we can autoselect it here on microsoft - clang needs -m16c-          #define STBIR_FP16C-        #endif-      #endif-    #endif-  #endif-  #ifdef __F16C__-    #ifndef STBIR_FP16C  // turn on FP16C instructions if the define is set (for clang and gcc)-      #define STBIR_FP16C-    #endif-  #endif-#endif--#if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(_M_ARM) || (__ARM_NEON_FP & 4) != 0 &&  __ARM_FP16_FORMAT_IEEE != 0-#ifndef STBIR_NEON-#define STBIR_NEON-#endif-#endif--#if defined(_M_ARM)-#ifdef STBIR_USE_FMA-#undef STBIR_USE_FMA // no FMA for 32-bit arm on MSVC -#endif-#endif--#if defined(__wasm__) && defined(__wasm_simd128__)-#ifndef STBIR_WASM-#define STBIR_WASM-#endif-#endif--#ifndef STBIRDEF-#ifdef STB_IMAGE_RESIZE_STATIC-#define STBIRDEF static-#else-#ifdef __cplusplus-#define STBIRDEF extern "C"-#else-#define STBIRDEF extern-#endif-#endif-#endif--//////////////////////////////////////////////////////////////////////////////-////   start "header file" ///////////////////////////////////////////////////-//-// Easy-to-use API:-//-//     * stride is the offset between successive rows of image data -//        in memory, in bytes. specify 0 for packed continuously in memory-//     * colorspace is linear or sRGB as specified by function name-//     * Uses the default filters-//     * Uses edge mode clamped-//     * returned result is 1 for success or 0 in case of an error.---// stbir_pixel_layout specifies:-//   number of channels-//   order of channels-//   whether color is premultiplied by alpha-// for back compatibility, you can cast the old channel count to an stbir_pixel_layout-typedef enum -{-  STBIR_BGR      = 0,               // 3-chan, with order specified (for channel flipping)-  STBIR_1CHANNEL = 1,              -  STBIR_2CHANNEL = 2,-  STBIR_RGB      = 3,               // 3-chan, with order specified (for channel flipping) -  STBIR_RGBA     = 4,               // alpha formats, alpha is NOT premultiplied into color channels--  STBIR_4CHANNEL = 5,-  STBIR_BGRA = 6,-  STBIR_ARGB = 7,-  STBIR_ABGR = 8,-  STBIR_RA   = 9,-  STBIR_AR   = 10,--  STBIR_RGBA_PM = 11,               // alpha formats, alpha is premultiplied into color channels-  STBIR_BGRA_PM = 12,-  STBIR_ARGB_PM = 13,-  STBIR_ABGR_PM = 14,-  STBIR_RA_PM   = 15,-  STBIR_AR_PM   = 16,-} stbir_pixel_layout;--//===============================================================-//  Simple-complexity API-//-//    If output_pixels is NULL (0), then we will allocate the buffer and return it to you.-//----------------------------------STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes,-                                                        unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,-                                                        stbir_pixel_layout pixel_type );--STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes,-                                                          unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,-                                                          stbir_pixel_layout pixel_type );--STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes,-                                                  float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,-                                                  stbir_pixel_layout pixel_type );-//===============================================================--//===============================================================-// Medium-complexity API-//-// This extends the easy-to-use API as follows:-//-//     * Can specify the datatype - U8, U8_SRGB, U16, FLOAT, HALF_FLOAT-//     * Edge wrap can selected explicitly-//     * Filter can be selected explicitly-//----------------------------------typedef enum-{-  STBIR_EDGE_CLAMP   = 0,-  STBIR_EDGE_REFLECT = 1,-  STBIR_EDGE_WRAP    = 2,  // this edge mode is slower and uses more memory-  STBIR_EDGE_ZERO    = 3,-} stbir_edge;--typedef enum-{-  STBIR_FILTER_DEFAULT      = 0,  // use same filter type that easy-to-use API chooses-  STBIR_FILTER_BOX          = 1,  // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios-  STBIR_FILTER_TRIANGLE     = 2,  // On upsampling, produces same results as bilinear texture filtering-  STBIR_FILTER_CUBICBSPLINE = 3,  // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque-  STBIR_FILTER_CATMULLROM   = 4,  // An interpolating cubic spline-  STBIR_FILTER_MITCHELL     = 5,  // Mitchell-Netrevalli filter with B=1/3, C=1/3-  STBIR_FILTER_POINT_SAMPLE = 6,  // Simple point sampling-  STBIR_FILTER_OTHER        = 7,  // User callback specified-} stbir_filter;--typedef enum-{-  STBIR_TYPE_UINT8            = 0,-  STBIR_TYPE_UINT8_SRGB       = 1,-  STBIR_TYPE_UINT8_SRGB_ALPHA = 2,  // alpha channel, when present, should also be SRGB (this is very unusual)-  STBIR_TYPE_UINT16           = 3,-  STBIR_TYPE_FLOAT            = 4,-  STBIR_TYPE_HALF_FLOAT       = 5-} stbir_datatype;--// medium api-STBIRDEF void *  stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes,-                                     void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,-                               stbir_pixel_layout pixel_layout, stbir_datatype data_type,-                               stbir_edge edge, stbir_filter filter );-//===============================================================----//===============================================================-// Extended-complexity API-//-// This API exposes all resize functionality.-//-//     * Separate filter types for each axis-//     * Separate edge modes for each axis-//     * Separate input and output data types-//     * Can specify regions with subpixel correctness-//     * Can specify alpha flags-//     * Can specify a memory callback -//     * Can specify a callback data type for pixel input and output -//     * Can be threaded for a single resize-//     * Can be used to resize many frames without recalculating the sampler info-//-//  Use this API as follows:-//     1) Call the stbir_resize_init function on a local STBIR_RESIZE structure-//     2) Call any of the stbir_set functions-//     3) Optionally call stbir_build_samplers() if you are going to resample multiple times-//        with the same input and output dimensions (like resizing video frames)-//     4) Resample by calling stbir_resize_extended().-//     5) Call stbir_free_samplers() if you called stbir_build_samplers()-//-----------------------------------// Types:--// INPUT CALLBACK: this callback is used for input scanlines-typedef void const * stbir_input_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context );--// OUTPUT CALLBACK: this callback is used for output scanlines-typedef void stbir_output_callback( void const * output_ptr, int num_pixels, int y, void * context );--// callbacks for user installed filters-typedef float stbir__kernel_callback( float x, float scale, void * user_data ); // centered at zero-typedef float stbir__support_callback( float scale, void * user_data );--// internal structure with precomputed scaling-typedef struct stbir__info stbir__info; --typedef struct STBIR_RESIZE  // use the stbir_resize_init and stbir_override functions to set these values for future compatibility-{-  void * user_data;-  void const * input_pixels;-  int input_w, input_h;-  double input_s0, input_t0, input_s1, input_t1;-  stbir_input_callback * input_cb;-  void * output_pixels;-  int output_w, output_h;-  int output_subx, output_suby, output_subw, output_subh;-  stbir_output_callback * output_cb;-  int input_stride_in_bytes;-  int output_stride_in_bytes;-  int splits;-  int fast_alpha;-  int needs_rebuild;-  int called_alloc;-  stbir_pixel_layout input_pixel_layout_public;-  stbir_pixel_layout output_pixel_layout_public;-  stbir_datatype input_data_type;-  stbir_datatype output_data_type;-  stbir_filter horizontal_filter, vertical_filter;-  stbir_edge horizontal_edge, vertical_edge;-  stbir__kernel_callback * horizontal_filter_kernel; stbir__support_callback * horizontal_filter_support;-  stbir__kernel_callback * vertical_filter_kernel; stbir__support_callback * vertical_filter_support;-  stbir__info * samplers;      -} STBIR_RESIZE;--// extended complexity api---// First off, you must ALWAYS call stbir_resize_init on your resize structure before any of the other calls!-STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize,-                                 const void *input_pixels,  int input_w,  int input_h, int input_stride_in_bytes, // stride can be zero-                                       void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero-                                 stbir_pixel_layout pixel_layout, stbir_datatype data_type );--//===============================================================-// You can update these parameters any time after resize_init and there is no cost-//----------------------------------STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type );         -STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb );   // no callbacks by default-STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data );                                               // pass back STBIR_RESIZE* by default-STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes );--//===============================================================---//===============================================================-// If you call any of these functions, you will trigger a sampler rebuild!-//----------------------------------STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout input_pixel_layout, stbir_pixel_layout output_pixel_layout );  // sets new buffer layouts-STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge );       // CLAMP by default--STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ); // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default-STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support ); --STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh );        // sets both sub-regions (full regions by default)-STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 );    // sets input sub-region (full region by default)-STBIRDEF int stbir_set_output_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ); // sets output sub-region (full region by default)--// when inputting AND outputting non-premultiplied alpha pixels, we use a slower but higher quality technique-//   that fills the zero alpha pixel's RGB values with something plausible.  If you don't care about areas of-//   zero alpha, you can call this function to get about a 25% speed improvement for STBIR_RGBA to STBIR_RGBA-//   types of resizes.-STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, int non_pma_alpha_speed_over_quality );-//===============================================================---//===============================================================-// You can call build_samplers to prebuild all the internal data we need to resample.-//   Then, if you call resize_extended many times with the same resize, you only pay the-//   cost once.-// If you do call build_samplers, you MUST call free_samplers eventually.-//----------------------------------// This builds the samplers and does one allocation-STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize ); --// You MUST call this, if you call stbir_build_samplers or stbir_build_samplers_with_splits-STBIRDEF void stbir_free_samplers( STBIR_RESIZE * resize );-//===============================================================---// And this is the main function to perform the resize synchronously on one thread.-STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize );---//===============================================================-// Use these functions for multithreading.-//   1) You call stbir_build_samplers_with_splits first on the main thread-//   2) Then stbir_resize_with_split on each thread-//   3) stbir_free_samplers when done on the main thread-//----------------------------------// This will build samplers for threading.-//   You can pass in the number of threads you'd like to use (try_splits).-//   It returns the number of splits (threads) that you can call it with.-///  It might be less if the image resize can't be split up that many ways.--STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int try_splits );             --// This function does a split of the resizing (you call this fuction for each-// split, on multiple threads). A split is a piece of the output resize pixel space.--// Note that you MUST call stbir_build_samplers_with_splits before stbir_resize_extended_split!--// Usually, you will always call stbir_resize_split with split_start as the thread_index-//   and "1" for the split_count.-// But, if you have a weird situation where you MIGHT want 8 threads, but sometimes-//   only 4 threads, you can use 0,2,4,6 for the split_start's and use "2" for the -//   split_count each time to turn in into a 4 thread resize. (This is unusual).--STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count );         -//===============================================================---//===============================================================-// Pixel Callbacks info:-//----------------------------------//   The input callback is super flexible - it calls you with the input address-//   (based on the stride and base pointer), it gives you an optional_output-//   pointer that you can fill, or you can just return your own pointer into-//   your own data. -//-//   You can also do conversion from non-supported data types if necessary - in -//   this case, you ignore the input_ptr and just use the x and y parameters to -//   calculate your own input_ptr based on the size of each non-supported pixel.-//   (Something like the third example below.)-//-//   You can also install just an input or just an output callback by setting the-//   callback that you don't want to zero.-//-//     First example, progress: (getting a callback that you can monitor the progress):-//        void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context )-//        {-//           percentage_done = y / input_height;-//           return input_ptr;  // use buffer from call-//        }-//-//     Next example, copying: (copy from some other buffer or stream):  -//        void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context )-//        {-//           CopyOrStreamData( optional_output, other_data_src, num_pixels * pixel_width_in_bytes );-//           return optional_output;  // return the optional buffer that we filled-//        }-//-//     Third example, input another buffer without copying: (zero-copy from other buffer):  -//        void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context )-//        {-//           void * pixels = ( (char*) other_image_base ) + ( y * other_image_stride ) + ( x * other_pixel_width_in_bytes );-//           return pixels;       // return pointer to your data without copying-//        }-//-//-//   The output callback is considerably simpler - it just calls you so that you can dump-//   out each scanline. You could even directly copy out to disk if you have a simple format-//   like TGA or BMP. You can also convert to other output types here if you want.-//-//   Simple example:-//        void const * my_output( void * output_ptr, int num_pixels, int y, void * context )-//        {-//           percentage_done = y / output_height;-//           fwrite( output_ptr, pixel_width_in_bytes, num_pixels, output_file );-//        }-//===============================================================-----//===============================================================-// optional built-in profiling API-//----------------------------------#ifdef STBIR_PROFILE--typedef struct STBIR_PROFILE_INFO -{-  stbir_uint64 total_clocks;--  // how many clocks spent (of total_clocks) in the various resize routines, along with a string description-  //    there are "resize_count" number of zones-  stbir_uint64 clocks[ 8 ];-  char const ** descriptions;-  -  // count of clocks and descriptions-  stbir_uint32 count;-} STBIR_PROFILE_INFO;--// use after calling stbir_resize_extended (or stbir_build_samplers or stbir_build_samplers_with_splits)-STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize );--// use after calling stbir_resize_extended-STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize );--// use after calling stbir_resize_extended_split-STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize, int split_start, int split_num );--//===============================================================--#endif---////   end header file   /////////////////////////////////////////////////////-#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE2_H--#if defined(STB_IMAGE_RESIZE_IMPLEMENTATION) || defined(STB_IMAGE_RESIZE2_IMPLEMENTATION)--#ifndef STBIR_ASSERT-#include <assert.h>-#define STBIR_ASSERT(x) assert(x)-#endif--#ifndef STBIR_MALLOC-#include <stdlib.h>-#define STBIR_MALLOC(size,user_data) ((void)(user_data), malloc(size))-#define STBIR_FREE(ptr,user_data)    ((void)(user_data), free(ptr))-// (we used the comma operator to evaluate user_data, to avoid "unused parameter" warnings)-#endif--#ifdef _MSC_VER--#define stbir__inline __forceinline--#else--#define stbir__inline __inline__--// Clang address sanitizer-#if defined(__has_feature)-  #if __has_feature(address_sanitizer) || __has_feature(memory_sanitizer)-    #ifndef STBIR__SEPARATE_ALLOCATIONS-      #define STBIR__SEPARATE_ALLOCATIONS-    #endif-  #endif-#endif--#endif--// GCC and MSVC-#if defined(__SANITIZE_ADDRESS__)-  #ifndef STBIR__SEPARATE_ALLOCATIONS-    #define STBIR__SEPARATE_ALLOCATIONS-  #endif-#endif--// Always turn off automatic FMA use - use STBIR_USE_FMA if you want.-// Otherwise, this is a determinism disaster.-#ifndef STBIR_DONT_CHANGE_FP_CONTRACT  // override in case you don't want this behavior-#if defined(_MSC_VER) && !defined(__clang__)-#if _MSC_VER > 1200-#pragma fp_contract(off)-#endif-#elif defined(__GNUC__) &&  !defined(__clang__)-#pragma GCC optimize("fp-contract=off")-#else-#pragma STDC FP_CONTRACT OFF-#endif-#endif--#ifdef _MSC_VER-#define STBIR__UNUSED(v)  (void)(v)-#else-#define STBIR__UNUSED(v)  (void)sizeof(v)-#endif--#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0]))---#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE-#define STBIR_DEFAULT_FILTER_UPSAMPLE    STBIR_FILTER_CATMULLROM-#endif--#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE-#define STBIR_DEFAULT_FILTER_DOWNSAMPLE  STBIR_FILTER_MITCHELL-#endif---#ifndef STBIR__HEADER_FILENAME-#define STBIR__HEADER_FILENAME "stb_image_resize2.h"-#endif--// the internal pixel layout enums are in a different order, so we can easily do range comparisons of types-//   the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible -typedef enum -{-  STBIRI_1CHANNEL = 0,-  STBIRI_2CHANNEL = 1,-  STBIRI_RGB      = 2,-  STBIRI_BGR      = 3,-  STBIRI_4CHANNEL = 4,-  -  STBIRI_RGBA = 5,-  STBIRI_BGRA = 6,-  STBIRI_ARGB = 7,-  STBIRI_ABGR = 8,-  STBIRI_RA   = 9,-  STBIRI_AR   = 10,--  STBIRI_RGBA_PM = 11,-  STBIRI_BGRA_PM = 12,-  STBIRI_ARGB_PM = 13,-  STBIRI_ABGR_PM = 14,-  STBIRI_RA_PM   = 15,-  STBIRI_AR_PM   = 16,-} stbir_internal_pixel_layout;--// define the public pixel layouts to not compile inside the implementation (to avoid accidental use)-#define STBIR_BGR bad_dont_use_in_implementation-#define STBIR_1CHANNEL STBIR_BGR-#define STBIR_2CHANNEL STBIR_BGR-#define STBIR_RGB STBIR_BGR-#define STBIR_RGBA STBIR_BGR-#define STBIR_4CHANNEL STBIR_BGR-#define STBIR_BGRA STBIR_BGR-#define STBIR_ARGB STBIR_BGR-#define STBIR_ABGR STBIR_BGR-#define STBIR_RA STBIR_BGR-#define STBIR_AR STBIR_BGR-#define STBIR_RGBA_PM STBIR_BGR-#define STBIR_BGRA_PM STBIR_BGR-#define STBIR_ARGB_PM STBIR_BGR-#define STBIR_ABGR_PM STBIR_BGR-#define STBIR_RA_PM STBIR_BGR-#define STBIR_AR_PM STBIR_BGR--// must match stbir_datatype-static unsigned char stbir__type_size[] = {-  1,1,1,2,4,2 // STBIR_TYPE_UINT8,STBIR_TYPE_UINT8_SRGB,STBIR_TYPE_UINT8_SRGB_ALPHA,STBIR_TYPE_UINT16,STBIR_TYPE_FLOAT,STBIR_TYPE_HALF_FLOAT-};--// When gathering, the contributors are which source pixels contribute.-// When scattering, the contributors are which destination pixels are contributed to.-typedef struct-{-  int n0; // First contributing pixel-  int n1; // Last contributing pixel-} stbir__contributors;--typedef struct-{-  int lowest;    // First sample index for whole filter-  int highest;   // Last sample index for whole filter-  int widest;    // widest single set of samples for an output-} stbir__filter_extent_info;--typedef struct-{-  int n0; // First pixel of decode buffer to write to-  int n1; // Last pixel of decode that will be written to-  int pixel_offset_for_input;  // Pixel offset into input_scanline-} stbir__span;--typedef struct stbir__scale_info-{-  int input_full_size;-  int output_sub_size;-  float scale;-  float inv_scale;-  float pixel_shift; // starting shift in output pixel space (in pixels)-  int scale_is_rational;-  stbir_uint32 scale_numerator, scale_denominator;-} stbir__scale_info;--typedef struct-{-  stbir__contributors * contributors;-  float* coefficients;-  stbir__contributors * gather_prescatter_contributors;-  float * gather_prescatter_coefficients;-  stbir__scale_info scale_info;-  float support;-  stbir_filter filter_enum;-  stbir__kernel_callback * filter_kernel;-  stbir__support_callback * filter_support;-  stbir_edge edge;-  int coefficient_width;-  int filter_pixel_width;-  int filter_pixel_margin;-  int num_contributors;-  int contributors_size;-  int coefficients_size;-  stbir__filter_extent_info extent_info;-  int is_gather;  // 0 = scatter, 1 = gather with scale >= 1, 2 = gather with scale < 1-  int gather_prescatter_num_contributors;-  int gather_prescatter_coefficient_width;-  int gather_prescatter_contributors_size;-  int gather_prescatter_coefficients_size;-} stbir__sampler;--typedef struct-{-  stbir__contributors conservative;-  int edge_sizes[2];    // this can be less than filter_pixel_margin, if the filter and scaling falls off-  stbir__span spans[2]; // can be two spans, if doing input subrect with clamp mode WRAP-} stbir__extents;--typedef struct -{-#ifdef STBIR_PROFILE-  union-  {-    struct { stbir_uint64 total, looping, vertical, horizontal, decode, encode, alpha, unalpha; } named;-    stbir_uint64 array[8];-  } profile;-  stbir_uint64 * current_zone_excluded_ptr;-#endif-  float* decode_buffer;--  int ring_buffer_first_scanline;-  int ring_buffer_last_scanline;-  int ring_buffer_begin_index;    // first_scanline is at this index in the ring buffer-  int start_output_y, end_output_y;-  int start_input_y, end_input_y;  // used in scatter only--  #ifdef STBIR__SEPARATE_ALLOCATIONS-    float** ring_buffers; // one pointer for each ring buffer-  #else-    float* ring_buffer;  // one big buffer that we index into-  #endif--  float* vertical_buffer;--  char no_cache_straddle[64];-} stbir__per_split_info;--typedef void stbir__decode_pixels_func( float * decode, int width_times_channels, void const * input );-typedef void stbir__alpha_weight_func( float * decode_buffer, int width_times_channels );-typedef void stbir__horizontal_gather_channels_func( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, -  stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width );-typedef void stbir__alpha_unweight_func(float * encode_buffer, int width_times_channels );-typedef void stbir__encode_pixels_func( void * output, int width_times_channels, float const * encode );--struct stbir__info-{-#ifdef STBIR_PROFILE-  union-  {-    struct { stbir_uint64 total, build, alloc, horizontal, vertical, cleanup, pivot; } named;-    stbir_uint64 array[7];-  } profile;-  stbir_uint64 * current_zone_excluded_ptr;-#endif-  stbir__sampler horizontal;-  stbir__sampler vertical;--  void const * input_data;-  void * output_data;--  int input_stride_bytes;-  int output_stride_bytes;-  int ring_buffer_length_bytes;   // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter)-  int ring_buffer_num_entries;    // Total number of entries in the ring buffer.--  stbir_datatype input_type;-  stbir_datatype output_type;--  stbir_input_callback * in_pixels_cb;-  void * user_data;-  stbir_output_callback * out_pixels_cb;--  stbir__extents scanline_extents;--  void * alloced_mem;-  stbir__per_split_info * split_info;  // by default 1, but there will be N of these allocated based on the thread init you did--  stbir__decode_pixels_func * decode_pixels;-  stbir__alpha_weight_func * alpha_weight;-  stbir__horizontal_gather_channels_func * horizontal_gather_channels;-  stbir__alpha_unweight_func * alpha_unweight;-  stbir__encode_pixels_func * encode_pixels;-  -  int alloced_total;-  int splits; // count of splits-  -  stbir_internal_pixel_layout input_pixel_layout_internal;-  stbir_internal_pixel_layout output_pixel_layout_internal;--  int input_color_and_type;-  int offset_x, offset_y; // offset within output_data-  int vertical_first;-  int channels;-  int effective_channels; // same as channels, except on RGBA/ARGB (7), or XA/AX (3)-  int alloc_ring_buffer_num_entries;    // Number of entries in the ring buffer that will be allocated-};---#define stbir__max_uint8_as_float             255.0f-#define stbir__max_uint16_as_float            65535.0f-#define stbir__max_uint8_as_float_inverted    (1.0f/255.0f)-#define stbir__max_uint16_as_float_inverted   (1.0f/65535.0f)-#define stbir__small_float ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20))--// min/max friendly-#define STBIR_CLAMP(x, xmin, xmax) do { \-  if ( (x) < (xmin) ) (x) = (xmin);     \-  if ( (x) > (xmax) ) (x) = (xmax);     \-} while (0)--static stbir__inline int stbir__min(int a, int b)-{-  return a < b ? a : b;-}--static stbir__inline int stbir__max(int a, int b)-{-  return a > b ? a : b;-}--static float stbir__srgb_uchar_to_linear_float[256] = {-  0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,-  0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f,-  0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f,-  0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f,-  0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f,-  0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f,-  0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f,-  0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,-  0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f,-  0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f,-  0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f,-  0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f,-  0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f,-  0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f,-  0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,-  0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f,-  0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f,-  0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f,-  0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f,-  0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f,-  0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f,-  0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,-  0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f,-  0.982251f, 0.991102f, 1.0f-};--typedef union-{-  unsigned int u;-  float f;-} stbir__FP32;--// From https://gist.github.com/rygorous/2203834--static const stbir_uint32 fp32_to_srgb8_tab4[104] = {-  0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d,-  0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a,-  0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033,-  0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067,-  0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5,-  0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2,-  0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143,-  0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af,-  0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240,-  0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300,-  0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401,-  0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559,-  0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723,-};- -static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in)-{-  static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps-  static const stbir__FP32 minval = { (127-13) << 23 };-  stbir_uint32 tab,bias,scale,t;-  stbir__FP32 f;--  // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively.-  // The tests are carefully written so that NaNs map to 0, same as in the reference-  // implementation.-  if (!(in > minval.f)) // written this way to catch NaNs-      return 0;-  if (in > almostone.f)-      return 255;--  // Do the table lookup and unpack bias, scale-  f.f = in;-  tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20];-  bias = (tab >> 16) << 9;-  scale = tab & 0xffff;--  // Grab next-highest mantissa bits and perform linear interpolation-  t = (f.u >> 12) & 0xff;-  return (unsigned char) ((bias + scale*t) >> 16);-}--#ifndef STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT-#define STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT 32 // when downsampling and <= 32 scanlines of buffering, use gather. gather used down to 1/8th scaling for 25% win.-#endif--// restrict pointers for the output pointers-#if defined( _MSC_VER ) && !defined(__clang__)-  #define STBIR_STREAMOUT_PTR( star ) star __restrict-  #define STBIR_NO_UNROLL( ptr ) __assume(ptr) // this oddly keeps msvc from unrolling a loop-#elif defined(  __clang__ )-  #define STBIR_STREAMOUT_PTR( star ) star __restrict__-  #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr))-#elif defined(  __GNUC__ )-  #define STBIR_STREAMOUT_PTR( star ) star __restrict__-  #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr))-#else-  #define STBIR_STREAMOUT_PTR( star ) star-  #define STBIR_NO_UNROLL( ptr )-#endif--#ifdef STBIR_NO_SIMD // force simd off for whatever reason--// force simd off overrides everything else, so clear it all--#ifdef STBIR_SSE2-#undef STBIR_SSE2-#endif--#ifdef STBIR_AVX-#undef STBIR_AVX-#endif--#ifdef STBIR_NEON-#undef STBIR_NEON-#endif--#ifdef STBIR_AVX2-#undef STBIR_AVX2-#endif--#ifdef STBIR_FP16C-#undef STBIR_FP16C-#endif--#ifdef STBIR_WASM-#undef STBIR_WASM-#endif--#ifdef STBIR_SIMD-#undef STBIR_SIMD-#endif--#else // STBIR_SIMD--#ifdef STBIR_SSE2-  #include <emmintrin.h>-  -  #define stbir__simdf __m128-  #define stbir__simdi __m128i--  #define stbir_simdi_castf( reg ) _mm_castps_si128(reg)-  #define stbir_simdf_casti( reg ) _mm_castsi128_ps(reg)--  #define stbir__simdf_load( reg, ptr ) (reg) = _mm_loadu_ps( (float const*)(ptr) )-  #define stbir__simdi_load( reg, ptr ) (reg) = _mm_loadu_si128 ( (stbir__simdi const*)(ptr) )-  #define stbir__simdf_load1( out, ptr ) (out) = _mm_load_ss( (float const*)(ptr) )  // top values can be random (not denormal or nan for perf)-  #define stbir__simdi_load1( out, ptr ) (out) = _mm_castps_si128( _mm_load_ss( (float const*)(ptr) ))-  #define stbir__simdf_load1z( out, ptr ) (out) = _mm_load_ss( (float const*)(ptr) )  // top values must be zero-  #define stbir__simdf_frep4( fvar ) _mm_set_ps1( fvar )-  #define stbir__simdf_load1frep4( out, fvar ) (out) = _mm_set_ps1( fvar )-  #define stbir__simdf_load2( out, ptr ) (out) = _mm_castsi128_ps( _mm_loadl_epi64( (__m128i*)(ptr)) ) // top values can be random (not denormal or nan for perf)-  #define stbir__simdf_load2z( out, ptr ) (out) = _mm_castsi128_ps( _mm_loadl_epi64( (__m128i*)(ptr)) ) // top values must be zero-  #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = _mm_castpd_ps(_mm_loadh_pd( _mm_castps_pd(reg), (double*)(ptr) ))--  #define stbir__simdf_zeroP() _mm_setzero_ps()-  #define stbir__simdf_zero( reg ) (reg) = _mm_setzero_ps()--  #define stbir__simdf_store( ptr, reg )  _mm_storeu_ps( (float*)(ptr), reg )-  #define stbir__simdf_store1( ptr, reg ) _mm_store_ss( (float*)(ptr), reg )-  #define stbir__simdf_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), _mm_castps_si128(reg) )-  #define stbir__simdf_store2h( ptr, reg ) _mm_storeh_pd( (double*)(ptr), _mm_castps_pd(reg) )--  #define stbir__simdi_store( ptr, reg )  _mm_storeu_si128( (__m128i*)(ptr), reg )-  #define stbir__simdi_store1( ptr, reg ) _mm_store_ss( (float*)(ptr), _mm_castsi128_ps(reg) )-  #define stbir__simdi_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), (reg) )--  #define stbir__prefetch( ptr ) _mm_prefetch((char*)(ptr), _MM_HINT_T0 )- -  #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \-  { \-    stbir__simdi zero = _mm_setzero_si128(); \-    out2 = _mm_unpacklo_epi8( ireg, zero ); \-    out3 = _mm_unpackhi_epi8( ireg, zero ); \-    out0 = _mm_unpacklo_epi16( out2, zero ); \-    out1 = _mm_unpackhi_epi16( out2, zero ); \-    out2 = _mm_unpacklo_epi16( out3, zero ); \-    out3 = _mm_unpackhi_epi16( out3, zero ); \-  }--#define stbir__simdi_expand_u8_to_1u32(out,ireg) \-  { \-    stbir__simdi zero = _mm_setzero_si128(); \-    out = _mm_unpacklo_epi8( ireg, zero ); \-    out = _mm_unpacklo_epi16( out, zero ); \-  }--  #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \-  { \-    stbir__simdi zero = _mm_setzero_si128(); \-    out0 = _mm_unpacklo_epi16( ireg, zero ); \-    out1 = _mm_unpackhi_epi16( ireg, zero ); \-  }--  #define stbir__simdf_convert_float_to_i32( i, f ) (i) = _mm_cvttps_epi32(f)-  #define stbir__simdf_convert_float_to_int( f ) _mm_cvtt_ss2si(f)-  #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),_mm_setzero_ps()))))-  #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps()))))--  #define stbir__simdi_to_int( i ) _mm_cvtsi128_si32(i) -  #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = _mm_cvtepi32_ps( ireg )-  #define stbir__simdf_add( out, reg0, reg1 ) (out) = _mm_add_ps( reg0, reg1 )-  #define stbir__simdf_mult( out, reg0, reg1 ) (out) = _mm_mul_ps( reg0, reg1 )-  #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = _mm_mul_ps( reg, _mm_loadu_ps( (float const*)(ptr) ) )-  #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = _mm_mul_ss( reg, _mm_load_ss( (float const*)(ptr) ) )-  #define stbir__simdf_add_mem( out, reg, ptr ) (out) = _mm_add_ps( reg, _mm_loadu_ps( (float const*)(ptr) ) )-  #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = _mm_add_ss( reg, _mm_load_ss( (float const*)(ptr) ) )--  #ifdef STBIR_USE_FMA           // not on by default to maintain bit identical simd to non-simd-  #include <immintrin.h>-  #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = _mm_fmadd_ps( mul1, mul2, add )-  #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = _mm_fmadd_ss( mul1, mul2, add )-  #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = _mm_fmadd_ps( mul, _mm_loadu_ps( (float const*)(ptr) ), add )-  #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = _mm_fmadd_ss( mul, _mm_load_ss( (float const*)(ptr) ), add )-  #else-  #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = _mm_add_ps( add, _mm_mul_ps( mul1, mul2 ) )-  #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = _mm_add_ss( add, _mm_mul_ss( mul1, mul2 ) )-  #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = _mm_add_ps( add, _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ) )-  #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = _mm_add_ss( add, _mm_mul_ss( mul, _mm_load_ss( (float const*)(ptr) ) ) )-  #endif--  #define stbir__simdf_add1( out, reg0, reg1 ) (out) = _mm_add_ss( reg0, reg1 )-  #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = _mm_mul_ss( reg0, reg1 )--  #define stbir__simdf_and( out, reg0, reg1 ) (out) = _mm_and_ps( reg0, reg1 )-  #define stbir__simdf_or( out, reg0, reg1 ) (out) = _mm_or_ps( reg0, reg1 )--  #define stbir__simdf_min( out, reg0, reg1 ) (out) = _mm_min_ps( reg0, reg1 )-  #define stbir__simdf_max( out, reg0, reg1 ) (out) = _mm_max_ps( reg0, reg1 )-  #define stbir__simdf_min1( out, reg0, reg1 ) (out) = _mm_min_ss( reg0, reg1 )-  #define stbir__simdf_max1( out, reg0, reg1 ) (out) = _mm_max_ss( reg0, reg1 )--  #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_shuffle_ps( reg1,reg0, (0<<0) + (1<<2) + (2<<4) + (3<<6) )), (3<<0) + (0<<2) + (1<<4) + (2<<6) ) )-  #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_shuffle_ps( reg1,reg0, (0<<0) + (1<<2) + (2<<4) + (3<<6) )), (2<<0) + (3<<2) + (0<<4) + (1<<6) ) )--  static const stbir__simdf STBIR_zeroones = { 0.0f,1.0f,0.0f,1.0f };-  static const stbir__simdf STBIR_onezeros = { 1.0f,0.0f,1.0f,0.0f };-  #define stbir__simdf_aaa1( out, alp, ones ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_movehl_ps( ones, alp ) ), (1<<0) + (1<<2) + (1<<4) + (2<<6) ) )-  #define stbir__simdf_1aaa( out, alp, ones ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_movelh_ps( ones, alp ) ), (0<<0) + (2<<2) + (2<<4) + (2<<6) ) )-  #define stbir__simdf_a1a1( out, alp, ones) (out) = _mm_or_ps( _mm_castsi128_ps( _mm_srli_epi64( _mm_castps_si128(alp), 32 ) ), STBIR_zeroones )-  #define stbir__simdf_1a1a( out, alp, ones) (out) = _mm_or_ps( _mm_castsi128_ps( _mm_slli_epi64( _mm_castps_si128(alp), 32 ) ), STBIR_onezeros )--  #define stbir__simdf_swiz( reg, one, two, three, four ) _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( reg ), (one<<0) + (two<<2) + (three<<4) + (four<<6) ) )--  #define stbir__simdi_and( out, reg0, reg1 ) (out) = _mm_and_si128( reg0, reg1 )-  #define stbir__simdi_or( out, reg0, reg1 ) (out) = _mm_or_si128( reg0, reg1 )-  #define stbir__simdi_16madd( out, reg0, reg1 ) (out) = _mm_madd_epi16( reg0, reg1 )--  #define stbir__simdf_pack_to_8bytes(out,aa,bb) \-  { \-    stbir__simdf af,bf; \-    stbir__simdi a,b; \-    af = _mm_min_ps( aa, STBIR_max_uint8_as_float ); \-    bf = _mm_min_ps( bb, STBIR_max_uint8_as_float ); \-    af = _mm_max_ps( af, _mm_setzero_ps() ); \-    bf = _mm_max_ps( bf, _mm_setzero_ps() ); \-    a = _mm_cvttps_epi32( af ); \-    b = _mm_cvttps_epi32( bf ); \-    a = _mm_packs_epi32( a, b ); \-    out = _mm_packus_epi16( a, a ); \-  }--  #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \-      stbir__simdf_load( o0, (ptr) );    \-      stbir__simdf_load( o1, (ptr)+4 );  \-      stbir__simdf_load( o2, (ptr)+8 );  \-      stbir__simdf_load( o3, (ptr)+12 ); \-      {                                  \-        __m128 tmp0, tmp1, tmp2, tmp3;   \-        tmp0 = _mm_unpacklo_ps(o0, o1);  \-        tmp2 = _mm_unpacklo_ps(o2, o3);  \-        tmp1 = _mm_unpackhi_ps(o0, o1);  \-        tmp3 = _mm_unpackhi_ps(o2, o3);  \-        o0 = _mm_movelh_ps(tmp0, tmp2);  \-        o1 = _mm_movehl_ps(tmp2, tmp0);  \-        o2 = _mm_movelh_ps(tmp1, tmp3);  \-        o3 = _mm_movehl_ps(tmp3, tmp1);  \-      }--  #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \-      r0 = _mm_packs_epi32( r0, r1 ); \-      r2 = _mm_packs_epi32( r2, r3 ); \-      r1 = _mm_unpacklo_epi16( r0, r2 ); \-      r3 = _mm_unpackhi_epi16( r0, r2 ); \-      r0 = _mm_unpacklo_epi16( r1, r3 ); \-      r2 = _mm_unpackhi_epi16( r1, r3 ); \-      r0 = _mm_packus_epi16( r0, r2 ); \-      stbir__simdi_store( ptr, r0 ); \--  #define stbir__simdi_32shr( out, reg, imm ) out = _mm_srli_epi32( reg, imm )--  #if defined(_MSC_VER) && !defined(__clang__)-    // msvc inits with 8 bytes-    #define STBIR__CONST_32_TO_8( v ) (char)(unsigned char)((v)&255),(char)(unsigned char)(((v)>>8)&255),(char)(unsigned char)(((v)>>16)&255),(char)(unsigned char)(((v)>>24)&255)-    #define STBIR__CONST_4_32i( v ) STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v )-    #define STBIR__CONST_4d_32i( v0, v1, v2, v3 ) STBIR__CONST_32_TO_8( v0 ), STBIR__CONST_32_TO_8( v1 ), STBIR__CONST_32_TO_8( v2 ), STBIR__CONST_32_TO_8( v3 )-  #else-    // everything else inits with long long's-    #define STBIR__CONST_4_32i( v ) (long long)((((stbir_uint64)(stbir_uint32)(v))<<32)|((stbir_uint64)(stbir_uint32)(v))),(long long)((((stbir_uint64)(stbir_uint32)(v))<<32)|((stbir_uint64)(stbir_uint32)(v)))-    #define STBIR__CONST_4d_32i( v0, v1, v2, v3 ) (long long)((((stbir_uint64)(stbir_uint32)(v1))<<32)|((stbir_uint64)(stbir_uint32)(v0))),(long long)((((stbir_uint64)(stbir_uint32)(v3))<<32)|((stbir_uint64)(stbir_uint32)(v2)))-  #endif--  #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = { x, x, x, x }-  #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { STBIR__CONST_4_32i(x) }-  #define STBIR__CONSTF(var) (var)-  #define STBIR__CONSTI(var) (var)--  #if defined(STBIR_AVX) || defined(__SSE4_1__)-    #include <smmintrin.h>-    #define stbir__simdf_pack_to_8words(out,reg0,reg1) out = _mm_packus_epi32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())), _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())))-  #else-    STBIR__SIMDI_CONST(stbir__s32_32768, 32768);-    STBIR__SIMDI_CONST(stbir__s16_32768, ((32768<<16)|32768));--    #define stbir__simdf_pack_to_8words(out,reg0,reg1) \-      { \-        stbir__simdi tmp0,tmp1; \-        tmp0 = _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())); \-        tmp1 = _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())); \-        tmp0 = _mm_sub_epi32( tmp0, stbir__s32_32768 ); \-        tmp1 = _mm_sub_epi32( tmp1, stbir__s32_32768 ); \-        out = _mm_packs_epi32( tmp0, tmp1 ); \-        out = _mm_sub_epi16( out, stbir__s16_32768 ); \-      }--  #endif--  #define STBIR_SIMD--  // if we detect AVX, set the simd8 defines-  #ifdef STBIR_AVX-    #include <immintrin.h>-    #define STBIR_SIMD8-    #define stbir__simdf8 __m256-    #define stbir__simdi8 __m256i-    #define stbir__simdf8_load( out, ptr ) (out) = _mm256_loadu_ps( (float const *)(ptr) )-    #define stbir__simdi8_load( out, ptr ) (out) = _mm256_loadu_si256( (__m256i const *)(ptr) )-    #define stbir__simdf8_mult( out, a, b ) (out) = _mm256_mul_ps( (a), (b) )-    #define stbir__simdf8_store( ptr, out ) _mm256_storeu_ps( (float*)(ptr), out )-    #define stbir__simdi8_store( ptr, reg )  _mm256_storeu_si256( (__m256i*)(ptr), reg )-    #define stbir__simdf8_frep8( fval ) _mm256_set1_ps( fval )--    #define stbir__simdf8_min( out, reg0, reg1 ) (out) = _mm256_min_ps( reg0, reg1 )-    #define stbir__simdf8_max( out, reg0, reg1 ) (out) = _mm256_max_ps( reg0, reg1 )--    #define stbir__simdf8_add4halves( out, bot4, top8 ) (out) = _mm_add_ps( bot4, _mm256_extractf128_ps( top8, 1 ) )-    #define stbir__simdf8_mult_mem( out, reg, ptr ) (out) = _mm256_mul_ps( reg, _mm256_loadu_ps( (float const*)(ptr) ) )-    #define stbir__simdf8_add_mem( out, reg, ptr ) (out) = _mm256_add_ps( reg, _mm256_loadu_ps( (float const*)(ptr) ) )-    #define stbir__simdf8_add( out, a, b ) (out) = _mm256_add_ps( a, b )-    #define stbir__simdf8_load1b( out, ptr ) (out) = _mm256_broadcast_ss( ptr )-    #define stbir__simdf_load1rep4( out, ptr ) (out) = _mm_broadcast_ss( ptr )  // avx load instruction--    #define stbir__simdi8_convert_i32_to_float(out, ireg) (out) = _mm256_cvtepi32_ps( ireg )-    #define stbir__simdf8_convert_float_to_i32( i, f ) (i) = _mm256_cvttps_epi32(f)-  -    #define stbir__simdf8_bot4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (0<<0)+(2<<4) )-    #define stbir__simdf8_top4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (1<<0)+(3<<4) )-    -    #define stbir__simdf8_gettop4( reg ) _mm256_extractf128_ps(reg,1)--    #ifdef STBIR_AVX2--    #define stbir__simdi8_expand_u8_to_u32(out0,out1,ireg) \-    { \-      stbir__simdi8 a, zero  =_mm256_setzero_si256();\-      a = _mm256_permute4x64_epi64( _mm256_unpacklo_epi8( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), zero ),(0<<0)+(2<<2)+(1<<4)+(3<<6)); \-      out0 = _mm256_unpacklo_epi16( a, zero ); \-      out1 = _mm256_unpackhi_epi16( a, zero ); \-    }--    #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \-    { \-      stbir__simdi8 t; \-      stbir__simdf8 af,bf; \-      stbir__simdi8 a,b; \-      af = _mm256_min_ps( aa, STBIR_max_uint8_as_floatX ); \-      bf = _mm256_min_ps( bb, STBIR_max_uint8_as_floatX ); \-      af = _mm256_max_ps( af, _mm256_setzero_ps() ); \-      bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \-      a = _mm256_cvttps_epi32( af ); \-      b = _mm256_cvttps_epi32( bf ); \-      t = _mm256_permute4x64_epi64( _mm256_packs_epi32( a, b ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ); \-      out = _mm256_castsi256_si128( _mm256_permute4x64_epi64( _mm256_packus_epi16( t, t ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ) ); \-    }--    #define stbir__simdi8_expand_u16_to_u32(out,ireg) out = _mm256_unpacklo_epi16( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), _mm256_setzero_si256() ); -  -    #define stbir__simdf8_pack_to_16words(out,aa,bb) \-      { \-        stbir__simdf8 af,bf; \-        stbir__simdi8 a,b; \-        af = _mm256_min_ps( aa, STBIR_max_uint16_as_floatX ); \-        bf = _mm256_min_ps( bb, STBIR_max_uint16_as_floatX ); \-        af = _mm256_max_ps( af, _mm256_setzero_ps() ); \-        bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \-        a = _mm256_cvttps_epi32( af ); \-        b = _mm256_cvttps_epi32( bf ); \-        (out) = _mm256_permute4x64_epi64( _mm256_packus_epi32(a, b), (0<<0)+(2<<2)+(1<<4)+(3<<6) ); \-      }--    #else--    #define stbir__simdi8_expand_u8_to_u32(out0,out1,ireg) \-    { \-      stbir__simdi a,zero = _mm_setzero_si128(); \-      a = _mm_unpacklo_epi8( ireg, zero ); \-      out0 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \-      a = _mm_unpackhi_epi8( ireg, zero ); \-      out1 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \-    }-  -    #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \-    { \-      stbir__simdi t; \-      stbir__simdf8 af,bf; \-      stbir__simdi8 a,b; \-      af = _mm256_min_ps( aa, STBIR_max_uint8_as_floatX ); \-      bf = _mm256_min_ps( bb, STBIR_max_uint8_as_floatX ); \-      af = _mm256_max_ps( af, _mm256_setzero_ps() ); \-      bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \-      a = _mm256_cvttps_epi32( af ); \-      b = _mm256_cvttps_epi32( bf ); \-      out = _mm_packs_epi32( _mm256_castsi256_si128(a), _mm256_extractf128_si256( a, 1 ) ); \-      out = _mm_packus_epi16( out, out ); \-      t = _mm_packs_epi32( _mm256_castsi256_si128(b), _mm256_extractf128_si256( b, 1 ) ); \-      t = _mm_packus_epi16( t, t ); \-      out = _mm_castps_si128( _mm_shuffle_ps( _mm_castsi128_ps(out), _mm_castsi128_ps(t), (0<<0)+(1<<2)+(0<<4)+(1<<6) ) ); \-    }-  -    #define stbir__simdi8_expand_u16_to_u32(out,ireg) \-    { \-      stbir__simdi a,b,zero = _mm_setzero_si128(); \-      a = _mm_unpacklo_epi16( ireg, zero ); \-      b = _mm_unpackhi_epi16( ireg, zero ); \-      out = _mm256_insertf128_si256( _mm256_castsi128_si256( a ), b, 1 ); \-    }--    #define stbir__simdf8_pack_to_16words(out,aa,bb) \-      { \-        stbir__simdi t0,t1; \-        stbir__simdf8 af,bf; \-        stbir__simdi8 a,b; \-        af = _mm256_min_ps( aa, STBIR_max_uint16_as_floatX ); \-        bf = _mm256_min_ps( bb, STBIR_max_uint16_as_floatX ); \-        af = _mm256_max_ps( af, _mm256_setzero_ps() ); \-        bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \-        a = _mm256_cvttps_epi32( af ); \-        b = _mm256_cvttps_epi32( bf ); \-        t0 = _mm_packus_epi32( _mm256_castsi256_si128(a), _mm256_extractf128_si256( a, 1 ) ); \-        t1 = _mm_packus_epi32( _mm256_castsi256_si128(b), _mm256_extractf128_si256( b, 1 ) ); \-        out = _mm256_setr_m128i( t0, t1 ); \-      }--    #endif--    static __m256i stbir_00001111 = { STBIR__CONST_4d_32i( 0, 0, 0, 0 ), STBIR__CONST_4d_32i( 1, 1, 1, 1 ) };-    #define stbir__simdf8_0123to00001111( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_00001111 )--    static __m256i stbir_22223333 = { STBIR__CONST_4d_32i( 2, 2, 2, 2 ), STBIR__CONST_4d_32i( 3, 3, 3, 3 ) };-    #define stbir__simdf8_0123to22223333( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_22223333 )--    #define stbir__simdf8_0123to2222( out, in ) (out) = stbir__simdf_swiz(_mm256_castps256_ps128(in), 2,2,2,2 )--    #define stbir__simdf8_load2( out, ptr ) (out) = _mm256_castsi256_ps(_mm256_castsi128_si256( _mm_loadl_epi64( (__m128i*)(ptr)) )) // top values can be random (not denormal or nan for perf)-    #define stbir__simdf8_load4b( out, ptr ) (out) = _mm256_broadcast_ps( (__m128 const *)(ptr) )--    static __m256i stbir_00112233 = { STBIR__CONST_4d_32i( 0, 0, 1, 1 ), STBIR__CONST_4d_32i( 2, 2, 3, 3 ) };-    #define stbir__simdf8_0123to00112233( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_00112233 )-    #define stbir__simdf8_add4( out, a8, b ) (out) = _mm256_add_ps( a8,  _mm256_castps128_ps256( b ) )--    static __m256i stbir_load6 = { STBIR__CONST_4_32i( 0x80000000 ), STBIR__CONST_4d_32i(  0x80000000,  0x80000000, 0, 0 ) };-    #define stbir__simdf8_load6z( out, ptr ) (out) = _mm256_maskload_ps( ptr, stbir_load6 )--    #define stbir__simdf8_0123to00000000( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (0<<0)+(0<<2)+(0<<4)+(0<<6) )-    #define stbir__simdf8_0123to11111111( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (1<<0)+(1<<2)+(1<<4)+(1<<6) )-    #define stbir__simdf8_0123to22222222( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (2<<0)+(2<<2)+(2<<4)+(2<<6) )-    #define stbir__simdf8_0123to33333333( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (3<<0)+(3<<2)+(3<<4)+(3<<6) )-    #define stbir__simdf8_0123to21032103( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (2<<0)+(1<<2)+(0<<4)+(3<<6) )-    #define stbir__simdf8_0123to32103210( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (3<<0)+(2<<2)+(1<<4)+(0<<6) )-    #define stbir__simdf8_0123to12301230( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (1<<0)+(2<<2)+(3<<4)+(0<<6) )-    #define stbir__simdf8_0123to10321032( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (1<<0)+(0<<2)+(3<<4)+(2<<6) )-    #define stbir__simdf8_0123to30123012( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (3<<0)+(0<<2)+(1<<4)+(2<<6) )--    #define stbir__simdf8_0123to11331133( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (1<<0)+(1<<2)+(3<<4)+(3<<6) )-    #define stbir__simdf8_0123to00220022( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (0<<0)+(0<<2)+(2<<4)+(2<<6) )--    #define stbir__simdf8_aaa1( out, alp, ones ) (out) = _mm256_blend_ps( alp, ones, (1<<0)+(1<<1)+(1<<2)+(0<<3)+(1<<4)+(1<<5)+(1<<6)+(0<<7)); (out)=_mm256_shuffle_ps( out,out, (3<<0) + (3<<2) + (3<<4) + (0<<6) )-    #define stbir__simdf8_1aaa( out, alp, ones ) (out) = _mm256_blend_ps( alp, ones, (0<<0)+(1<<1)+(1<<2)+(1<<3)+(0<<4)+(1<<5)+(1<<6)+(1<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (0<<4) + (0<<6) )-    #define stbir__simdf8_a1a1( out, alp, ones) (out) = _mm256_blend_ps( alp, ones, (1<<0)+(0<<1)+(1<<2)+(0<<3)+(1<<4)+(0<<5)+(1<<6)+(0<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (3<<4) + (2<<6) )-    #define stbir__simdf8_1a1a( out, alp, ones) (out) = _mm256_blend_ps( alp, ones, (0<<0)+(1<<1)+(0<<2)+(1<<3)+(0<<4)+(1<<5)+(0<<6)+(1<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (3<<4) + (2<<6) )--    #define stbir__simdf8_zero( reg ) (reg) = _mm256_setzero_ps()--    #ifdef STBIR_USE_FMA           // not on by default to maintain bit identical simd to non-simd-    #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_fmadd_ps( mul1, mul2, add )-    #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_fmadd_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ), add )-    #define stbir__simdf8_madd_mem4( out, add, mul, ptr ) (out) = _mm256_fmadd_ps( _mm256_castps128_ps256( mul ), _mm256_castps128_ps256( _mm_loadu_ps( (float const*)(ptr) ) ), add )-    #else-    #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul1, mul2 ) )-    #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ) ) )-    #define stbir__simdf8_madd_mem4( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_castps128_ps256( _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ) ) )-    #endif-    #define stbir__if_simdf8_cast_to_simdf4( val ) _mm256_castps256_ps128( val )--  #endif--  #ifdef STBIR_FLOORF-  #undef STBIR_FLOORF-  #endif-  #define STBIR_FLOORF stbir_simd_floorf-  static stbir__inline float stbir_simd_floorf(float x)  // martins floorf-  {-    #if defined(STBIR_AVX) || defined(__SSE4_1__) || defined(STBIR_SSE41)-    __m128 t = _mm_set_ss(x);-    return _mm_cvtss_f32( _mm_floor_ss(t, t) );-    #else-    __m128 f = _mm_set_ss(x);-    __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f));-    __m128 r = _mm_add_ss(t, _mm_and_ps(_mm_cmplt_ss(f, t), _mm_set_ss(-1.0f)));-    return _mm_cvtss_f32(r);-    #endif-  }--  #ifdef STBIR_CEILF-  #undef STBIR_CEILF-  #endif-  #define STBIR_CEILF stbir_simd_ceilf-  static stbir__inline float stbir_simd_ceilf(float x)  // martins ceilf-  {-    #if defined(STBIR_AVX) || defined(__SSE4_1__) || defined(STBIR_SSE41)-    __m128 t = _mm_set_ss(x);-    return _mm_cvtss_f32( _mm_ceil_ss(t, t) );-    #else-    __m128 f = _mm_set_ss(x);-    __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f));-    __m128 r = _mm_add_ss(t, _mm_and_ps(_mm_cmplt_ss(t, f), _mm_set_ss(1.0f)));-    return _mm_cvtss_f32(r);-    #endif-  }--#elif defined(STBIR_NEON)-  -  #include <arm_neon.h>--  #define stbir__simdf float32x4_t-  #define stbir__simdi uint32x4_t--  #define stbir_simdi_castf( reg ) vreinterpretq_u32_f32(reg)-  #define stbir_simdf_casti( reg ) vreinterpretq_f32_u32(reg)--  #define stbir__simdf_load( reg, ptr ) (reg) = vld1q_f32( (float const*)(ptr) )-  #define stbir__simdi_load( reg, ptr ) (reg) = vld1q_u32( (uint32_t const*)(ptr) )-  #define stbir__simdf_load1( out, ptr ) (out) = vld1q_dup_f32( (float const*)(ptr) ) // top values can be random (not denormal or nan for perf)-  #define stbir__simdi_load1( out, ptr ) (out) = vld1q_dup_u32( (uint32_t const*)(ptr) )-  #define stbir__simdf_load1z( out, ptr ) (out) = vld1q_lane_f32( (float const*)(ptr), vdupq_n_f32(0), 0 ) // top values must be zero-  #define stbir__simdf_frep4( fvar ) vdupq_n_f32( fvar )-  #define stbir__simdf_load1frep4( out, fvar ) (out) = vdupq_n_f32( fvar )-  #define stbir__simdf_load2( out, ptr ) (out) = vcombine_f32( vld1_f32( (float const*)(ptr) ), vcreate_f32(0) ) // top values can be random (not denormal or nan for perf)-  #define stbir__simdf_load2z( out, ptr ) (out) = vcombine_f32( vld1_f32( (float const*)(ptr) ), vcreate_f32(0) )  // top values must be zero-  #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = vcombine_f32( vget_low_f32(reg), vld1_f32( (float const*)(ptr) ) )--  #define stbir__simdf_zeroP() vdupq_n_f32(0)-  #define stbir__simdf_zero( reg ) (reg) = vdupq_n_f32(0)--  #define stbir__simdf_store( ptr, reg )  vst1q_f32( (float*)(ptr), reg )-  #define stbir__simdf_store1( ptr, reg ) vst1q_lane_f32( (float*)(ptr), reg, 0)-  #define stbir__simdf_store2( ptr, reg ) vst1_f32( (float*)(ptr), vget_low_f32(reg) )-  #define stbir__simdf_store2h( ptr, reg ) vst1_f32( (float*)(ptr), vget_high_f32(reg) )--  #define stbir__simdi_store( ptr, reg )  vst1q_u32( (uint32_t*)(ptr), reg )-  #define stbir__simdi_store1( ptr, reg ) vst1q_lane_u32( (uint32_t*)(ptr), reg, 0 )-  #define stbir__simdi_store2( ptr, reg ) vst1_u32( (uint32_t*)(ptr), vget_low_u32(reg) )--  #define stbir__prefetch( ptr )--  #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \-  { \-    uint16x8_t l = vmovl_u8( vget_low_u8 ( vreinterpretq_u8_u32(ireg) ) ); \-    uint16x8_t h = vmovl_u8( vget_high_u8( vreinterpretq_u8_u32(ireg) ) ); \-    out0 = vmovl_u16( vget_low_u16 ( l ) ); \-    out1 = vmovl_u16( vget_high_u16( l ) ); \-    out2 = vmovl_u16( vget_low_u16 ( h ) ); \-    out3 = vmovl_u16( vget_high_u16( h ) ); \-  }--  #define stbir__simdi_expand_u8_to_1u32(out,ireg) \-  { \-    uint16x8_t tmp = vmovl_u8( vget_low_u8( vreinterpretq_u8_u32(ireg) ) ); \-    out = vmovl_u16( vget_low_u16( tmp ) ); \-  }--  #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \-  { \-    uint16x8_t tmp = vreinterpretq_u16_u32(ireg); \-    out0 = vmovl_u16( vget_low_u16 ( tmp ) ); \-    out1 = vmovl_u16( vget_high_u16( tmp ) ); \-  }--  #define stbir__simdf_convert_float_to_i32( i, f ) (i) = vreinterpretq_u32_s32( vcvtq_s32_f32(f) )-  #define stbir__simdf_convert_float_to_int( f ) vgetq_lane_s32(vcvtq_s32_f32(f), 0)-  #define stbir__simdi_to_int( i ) (int)vgetq_lane_u32(i, 0) -  #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),vdupq_n_f32(0))), 0))-  #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),vdupq_n_f32(0))), 0))-  #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = vcvtq_f32_s32( vreinterpretq_s32_u32(ireg) )-  #define stbir__simdf_add( out, reg0, reg1 ) (out) = vaddq_f32( reg0, reg1 )-  #define stbir__simdf_mult( out, reg0, reg1 ) (out) = vmulq_f32( reg0, reg1 )-  #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = vmulq_f32( reg, vld1q_f32( (float const*)(ptr) ) )-  #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = vmulq_f32( reg, vld1q_dup_f32( (float const*)(ptr) ) )-  #define stbir__simdf_add_mem( out, reg, ptr ) (out) = vaddq_f32( reg, vld1q_f32( (float const*)(ptr) ) )-  #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = vaddq_f32( reg, vld1q_dup_f32( (float const*)(ptr) ) )--  #ifdef STBIR_USE_FMA           // not on by default to maintain bit identical simd to non-simd (and also x64 no madd to arm madd)-  #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = vfmaq_f32( add, mul1, mul2 )-  #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = vfmaq_f32( add, mul1, mul2 )-  #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = vfmaq_f32( add, mul, vld1q_f32( (float const*)(ptr) ) )-  #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = vfmaq_f32( add, mul, vld1q_dup_f32( (float const*)(ptr) ) )-  #else-  #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = vaddq_f32( add, vmulq_f32( mul1, mul2 ) )-  #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = vaddq_f32( add, vmulq_f32( mul1, mul2 ) )-  #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = vaddq_f32( add, vmulq_f32( mul, vld1q_f32( (float const*)(ptr) ) ) )-  #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = vaddq_f32( add, vmulq_f32( mul, vld1q_dup_f32( (float const*)(ptr) ) ) )-  #endif--  #define stbir__simdf_add1( out, reg0, reg1 ) (out) = vaddq_f32( reg0, reg1 )-  #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = vmulq_f32( reg0, reg1 )--  #define stbir__simdf_and( out, reg0, reg1 ) (out) = vreinterpretq_f32_u32( vandq_u32( vreinterpretq_u32_f32(reg0), vreinterpretq_u32_f32(reg1) ) )-  #define stbir__simdf_or( out, reg0, reg1 ) (out) = vreinterpretq_f32_u32( vorrq_u32( vreinterpretq_u32_f32(reg0), vreinterpretq_u32_f32(reg1) ) )--  #define stbir__simdf_min( out, reg0, reg1 ) (out) = vminq_f32( reg0, reg1 )-  #define stbir__simdf_max( out, reg0, reg1 ) (out) = vmaxq_f32( reg0, reg1 )-  #define stbir__simdf_min1( out, reg0, reg1 ) (out) = vminq_f32( reg0, reg1 )-  #define stbir__simdf_max1( out, reg0, reg1 ) (out) = vmaxq_f32( reg0, reg1 )--  #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out) = vextq_f32( reg0, reg1, 3 )-  #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out) = vextq_f32( reg0, reg1, 2 )--  #define stbir__simdf_a1a1( out, alp, ones ) (out) = vzipq_f32(vuzpq_f32(alp, alp).val[1], ones).val[0]-  #define stbir__simdf_1a1a( out, alp, ones ) (out) = vzipq_f32(ones, vuzpq_f32(alp, alp).val[0]).val[0]--  #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ )--    #define stbir__simdf_aaa1( out, alp, ones ) (out) = vcopyq_laneq_f32(vdupq_n_f32(vgetq_lane_f32(alp, 3)), 3, ones, 3)-    #define stbir__simdf_1aaa( out, alp, ones ) (out) = vcopyq_laneq_f32(vdupq_n_f32(vgetq_lane_f32(alp, 0)), 0, ones, 0)--    #if defined( _MSC_VER ) && !defined(__clang__)-      #define stbir_make16(a,b,c,d) vcombine_u8( \-        vcreate_u8( (4*a+0) | ((4*a+1)<<8) | ((4*a+2)<<16) | ((4*a+3)<<24) | \-          ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56)), \-        vcreate_u8( (4*c+0) | ((4*c+1)<<8) | ((4*c+2)<<16) | ((4*c+3)<<24) | \-          ((stbir_uint64)(4*d+0)<<32) | ((stbir_uint64)(4*d+1)<<40) | ((stbir_uint64)(4*d+2)<<48) | ((stbir_uint64)(4*d+3)<<56) ) )-    #else-      #define stbir_make16(a,b,c,d) (uint8x16_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3,4*c+0,4*c+1,4*c+2,4*c+3,4*d+0,4*d+1,4*d+2,4*d+3}-    #endif--    #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vqtbl1q_u8( vreinterpretq_u8_f32(reg), stbir_make16(one, two, three, four) ) )-  -    #define stbir__simdi_16madd( out, reg0, reg1 ) \-    { \-      int16x8_t r0 = vreinterpretq_s16_u32(reg0); \-      int16x8_t r1 = vreinterpretq_s16_u32(reg1); \-      int32x4_t tmp0 = vmull_s16( vget_low_s16(r0), vget_low_s16(r1) ); \-      int32x4_t tmp1 = vmull_s16( vget_high_s16(r0), vget_high_s16(r1) ); \-      (out) = vreinterpretq_u32_s32( vpaddq_s32(tmp0, tmp1) ); \-    }--  #else--    #define stbir__simdf_aaa1( out, alp, ones ) (out) = vsetq_lane_f32(1.0f, vdupq_n_f32(vgetq_lane_f32(alp, 3)), 3)-    #define stbir__simdf_1aaa( out, alp, ones ) (out) = vsetq_lane_f32(1.0f, vdupq_n_f32(vgetq_lane_f32(alp, 0)), 0)--    #if defined( _MSC_VER ) && !defined(__clang__)-      static stbir__inline uint8x8x2_t stbir_make8x2(float32x4_t reg)-      {-        uint8x8x2_t r = { { vget_low_u8(vreinterpretq_u8_f32(reg)), vget_high_u8(vreinterpretq_u8_f32(reg)) } };-        return r;-      }-      #define stbir_make8(a,b) vcreate_u8( \-        (4*a+0) | ((4*a+1)<<8) | ((4*a+2)<<16) | ((4*a+3)<<24) | \-        ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56) )-    #else-      #define stbir_make8x2(reg) (uint8x8x2_t){ { vget_low_u8(vreinterpretq_u8_f32(reg)), vget_high_u8(vreinterpretq_u8_f32(reg)) } }-      #define stbir_make8(a,b) (uint8x8_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3}-    #endif--    #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vcombine_u8( \-        vtbl2_u8( stbir_make8x2( reg ), stbir_make8( one, two ) ), \-        vtbl2_u8( stbir_make8x2( reg ), stbir_make8( three, four ) ) ) )--    #define stbir__simdi_16madd( out, reg0, reg1 ) \-    { \-      int16x8_t r0 = vreinterpretq_s16_u32(reg0); \-      int16x8_t r1 = vreinterpretq_s16_u32(reg1); \-      int32x4_t tmp0 = vmull_s16( vget_low_s16(r0), vget_low_s16(r1) ); \-      int32x4_t tmp1 = vmull_s16( vget_high_s16(r0), vget_high_s16(r1) ); \-      int32x2_t out0 = vpadd_s32( vget_low_s32(tmp0), vget_high_s32(tmp0) ); \-      int32x2_t out1 = vpadd_s32( vget_low_s32(tmp1), vget_high_s32(tmp1) ); \-      (out) = vreinterpretq_u32_s32( vcombine_s32(out0, out1) ); \-    }--  #endif--  #define stbir__simdi_and( out, reg0, reg1 ) (out) = vandq_u32( reg0, reg1 )-  #define stbir__simdi_or( out, reg0, reg1 ) (out) = vorrq_u32( reg0, reg1 )--  #define stbir__simdf_pack_to_8bytes(out,aa,bb) \-  { \-    float32x4_t af = vmaxq_f32( vminq_f32(aa,STBIR__CONSTF(STBIR_max_uint8_as_float) ), vdupq_n_f32(0) ); \-    float32x4_t bf = vmaxq_f32( vminq_f32(bb,STBIR__CONSTF(STBIR_max_uint8_as_float) ), vdupq_n_f32(0) ); \-    int16x4_t ai = vqmovn_s32( vcvtq_s32_f32( af ) ); \-    int16x4_t bi = vqmovn_s32( vcvtq_s32_f32( bf ) ); \-    uint8x8_t out8 = vqmovun_s16( vcombine_s16(ai, bi) ); \-    out = vreinterpretq_u32_u8( vcombine_u8(out8, out8) ); \-  }--  #define stbir__simdf_pack_to_8words(out,aa,bb) \-  { \-    float32x4_t af = vmaxq_f32( vminq_f32(aa,STBIR__CONSTF(STBIR_max_uint16_as_float) ), vdupq_n_f32(0) ); \-    float32x4_t bf = vmaxq_f32( vminq_f32(bb,STBIR__CONSTF(STBIR_max_uint16_as_float) ), vdupq_n_f32(0) ); \-    int32x4_t ai = vcvtq_s32_f32( af ); \-    int32x4_t bi = vcvtq_s32_f32( bf ); \-    out = vreinterpretq_u32_u16( vcombine_u16(vqmovun_s32(ai), vqmovun_s32(bi)) ); \-  }--  #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \-  { \-    int16x4x2_t tmp0 = vzip_s16( vqmovn_s32(vreinterpretq_s32_u32(r0)), vqmovn_s32(vreinterpretq_s32_u32(r2)) ); \-    int16x4x2_t tmp1 = vzip_s16( vqmovn_s32(vreinterpretq_s32_u32(r1)), vqmovn_s32(vreinterpretq_s32_u32(r3)) ); \-    uint8x8x2_t out = \-    { { \-      vqmovun_s16( vcombine_s16(tmp0.val[0], tmp0.val[1]) ), \-      vqmovun_s16( vcombine_s16(tmp1.val[0], tmp1.val[1]) ), \-    } }; \-    vst2_u8(ptr, out); \-  }--  #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \-  { \-    float32x4x4_t tmp = vld4q_f32(ptr); \-    o0 = tmp.val[0]; \-    o1 = tmp.val[1]; \-    o2 = tmp.val[2]; \-    o3 = tmp.val[3]; \-  }--  #define stbir__simdi_32shr( out, reg, imm ) out = vshrq_n_u32( reg, imm )--  #if defined( _MSC_VER ) && !defined(__clang__)-    #define STBIR__SIMDF_CONST(var, x) __declspec(align(8)) float var[] = { x, x, x, x }-    #define STBIR__SIMDI_CONST(var, x) __declspec(align(8)) uint32_t var[] = { x, x, x, x }-    #define STBIR__CONSTF(var) (*(const float32x4_t*)var)-    #define STBIR__CONSTI(var) (*(const uint32x4_t*)var)-  #else-    #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = { x, x, x, x }-    #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { x, x, x, x }-    #define STBIR__CONSTF(var) (var)-    #define STBIR__CONSTI(var) (var)-  #endif--  #ifdef STBIR_FLOORF-  #undef STBIR_FLOORF-  #endif-  #define STBIR_FLOORF stbir_simd_floorf-  static stbir__inline float stbir_simd_floorf(float x)-  {-    #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ )-    return vget_lane_f32( vrndm_f32( vdup_n_f32(x) ), 0);-    #else-    float32x2_t f = vdup_n_f32(x);-    float32x2_t t = vcvt_f32_s32(vcvt_s32_f32(f));-    uint32x2_t a = vclt_f32(f, t);-    uint32x2_t b = vreinterpret_u32_f32(vdup_n_f32(-1.0f));-    float32x2_t r = vadd_f32(t, vreinterpret_f32_u32(vand_u32(a, b)));-    return vget_lane_f32(r, 0);-    #endif-  }--  #ifdef STBIR_CEILF-  #undef STBIR_CEILF-  #endif-  #define STBIR_CEILF stbir_simd_ceilf-  static stbir__inline float stbir_simd_ceilf(float x)-  {-    #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ )-    return vget_lane_f32( vrndp_f32( vdup_n_f32(x) ), 0);-    #else-    float32x2_t f = vdup_n_f32(x);-    float32x2_t t = vcvt_f32_s32(vcvt_s32_f32(f));-    uint32x2_t a = vclt_f32(t, f);-    uint32x2_t b = vreinterpret_u32_f32(vdup_n_f32(1.0f));-    float32x2_t r = vadd_f32(t, vreinterpret_f32_u32(vand_u32(a, b)));-    return vget_lane_f32(r, 0);-    #endif-  }--  #define STBIR_SIMD--#elif defined(STBIR_WASM)--  #include <wasm_simd128.h>--  #define stbir__simdf v128_t-  #define stbir__simdi v128_t--  #define stbir_simdi_castf( reg ) (reg)-  #define stbir_simdf_casti( reg ) (reg)--  #define stbir__simdf_load( reg, ptr )             (reg) = wasm_v128_load( (void const*)(ptr) )-  #define stbir__simdi_load( reg, ptr )             (reg) = wasm_v128_load( (void const*)(ptr) )-  #define stbir__simdf_load1( out, ptr )            (out) = wasm_v128_load32_splat( (void const*)(ptr) ) // top values can be random (not denormal or nan for perf)-  #define stbir__simdi_load1( out, ptr )            (out) = wasm_v128_load32_splat( (void const*)(ptr) )-  #define stbir__simdf_load1z( out, ptr )           (out) = wasm_v128_load32_zero( (void const*)(ptr) ) // top values must be zero-  #define stbir__simdf_frep4( fvar )                wasm_f32x4_splat( fvar )-  #define stbir__simdf_load1frep4( out, fvar )      (out) = wasm_f32x4_splat( fvar )-  #define stbir__simdf_load2( out, ptr )            (out) = wasm_v128_load64_splat( (void const*)(ptr) ) // top values can be random (not denormal or nan for perf)-  #define stbir__simdf_load2z( out, ptr )           (out) = wasm_v128_load64_zero( (void const*)(ptr) ) // top values must be zero-  #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = wasm_v128_load64_lane( (void const*)(ptr), reg, 1 )--  #define stbir__simdf_zeroP() wasm_f32x4_const_splat(0)-  #define stbir__simdf_zero( reg ) (reg) = wasm_f32x4_const_splat(0)--  #define stbir__simdf_store( ptr, reg )   wasm_v128_store( (void*)(ptr), reg )-  #define stbir__simdf_store1( ptr, reg )  wasm_v128_store32_lane( (void*)(ptr), reg, 0 )-  #define stbir__simdf_store2( ptr, reg )  wasm_v128_store64_lane( (void*)(ptr), reg, 0 )-  #define stbir__simdf_store2h( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 1 )--  #define stbir__simdi_store( ptr, reg )  wasm_v128_store( (void*)(ptr), reg )-  #define stbir__simdi_store1( ptr, reg ) wasm_v128_store32_lane( (void*)(ptr), reg, 0 )-  #define stbir__simdi_store2( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 0 )--  #define stbir__prefetch( ptr )--  #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \-  { \-    v128_t l = wasm_u16x8_extend_low_u8x16 ( ireg ); \-    v128_t h = wasm_u16x8_extend_high_u8x16( ireg ); \-    out0 = wasm_u32x4_extend_low_u16x8 ( l ); \-    out1 = wasm_u32x4_extend_high_u16x8( l ); \-    out2 = wasm_u32x4_extend_low_u16x8 ( h ); \-    out3 = wasm_u32x4_extend_high_u16x8( h ); \-  }--  #define stbir__simdi_expand_u8_to_1u32(out,ireg) \-  { \-    v128_t tmp = wasm_u16x8_extend_low_u8x16(ireg); \-    out = wasm_u32x4_extend_low_u16x8(tmp); \-  }--  #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \-  { \-    out0 = wasm_u32x4_extend_low_u16x8 ( ireg ); \-    out1 = wasm_u32x4_extend_high_u16x8( ireg ); \-  }--  #define stbir__simdf_convert_float_to_i32( i, f )    (i) = wasm_i32x4_trunc_sat_f32x4(f)-  #define stbir__simdf_convert_float_to_int( f )       wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(f), 0)-  #define stbir__simdi_to_int( i )                     wasm_i32x4_extract_lane(i, 0) -  #define stbir__simdf_convert_float_to_uint8( f )     ((unsigned char)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint8_as_float),wasm_f32x4_const_splat(0))), 0))-  #define stbir__simdf_convert_float_to_short( f )     ((unsigned short)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint16_as_float),wasm_f32x4_const_splat(0))), 0))-  #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = wasm_f32x4_convert_i32x4(ireg)-  #define stbir__simdf_add( out, reg0, reg1 )          (out) = wasm_f32x4_add( reg0, reg1 )-  #define stbir__simdf_mult( out, reg0, reg1 )         (out) = wasm_f32x4_mul( reg0, reg1 )-  #define stbir__simdf_mult_mem( out, reg, ptr )       (out) = wasm_f32x4_mul( reg, wasm_v128_load( (void const*)(ptr) ) )-  #define stbir__simdf_mult1_mem( out, reg, ptr )      (out) = wasm_f32x4_mul( reg, wasm_v128_load32_splat( (void const*)(ptr) ) )-  #define stbir__simdf_add_mem( out, reg, ptr )        (out) = wasm_f32x4_add( reg, wasm_v128_load( (void const*)(ptr) ) )-  #define stbir__simdf_add1_mem( out, reg, ptr )       (out) = wasm_f32x4_add( reg, wasm_v128_load32_splat( (void const*)(ptr) ) )--  #define stbir__simdf_madd( out, add, mul1, mul2 )    (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul1, mul2 ) )-  #define stbir__simdf_madd1( out, add, mul1, mul2 )   (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul1, mul2 ) )-  #define stbir__simdf_madd_mem( out, add, mul, ptr )  (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul, wasm_v128_load( (void const*)(ptr) ) ) )-  #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul, wasm_v128_load32_splat( (void const*)(ptr) ) ) )--  #define stbir__simdf_add1( out, reg0, reg1 )  (out) = wasm_f32x4_add( reg0, reg1 )-  #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = wasm_f32x4_mul( reg0, reg1 )--  #define stbir__simdf_and( out, reg0, reg1 ) (out) = wasm_v128_and( reg0, reg1 )-  #define stbir__simdf_or( out, reg0, reg1 )  (out) = wasm_v128_or( reg0, reg1 )--  #define stbir__simdf_min( out, reg0, reg1 ) (out) = wasm_f32x4_min( reg0, reg1 )-  #define stbir__simdf_max( out, reg0, reg1 ) (out) = wasm_f32x4_max( reg0, reg1 )-  #define stbir__simdf_min1( out, reg0, reg1 ) (out) = wasm_f32x4_min( reg0, reg1 )-  #define stbir__simdf_max1( out, reg0, reg1 ) (out) = wasm_f32x4_max( reg0, reg1 )--  #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out) = wasm_i32x4_shuffle( reg0, reg1, 3, 4, 5, -1 )-  #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out) = wasm_i32x4_shuffle( reg0, reg1, 2, 3, 4, -1 )--  #define stbir__simdf_aaa1(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 3, 3, 3, 4)-  #define stbir__simdf_1aaa(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 4, 0, 0, 0)-  #define stbir__simdf_a1a1(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 1, 4, 3, 4)-  #define stbir__simdf_1a1a(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 4, 0, 4, 2)--  #define stbir__simdf_swiz( reg, one, two, three, four ) wasm_i32x4_shuffle(reg, reg, one, two, three, four)--  #define stbir__simdi_and( out, reg0, reg1 )    (out) = wasm_v128_and( reg0, reg1 )-  #define stbir__simdi_or( out, reg0, reg1 )     (out) = wasm_v128_or( reg0, reg1 )-  #define stbir__simdi_16madd( out, reg0, reg1 ) (out) = wasm_i32x4_dot_i16x8( reg0, reg1 )--  #define stbir__simdf_pack_to_8bytes(out,aa,bb) \-  { \-    v128_t af = wasm_f32x4_max( wasm_f32x4_min(aa, STBIR_max_uint8_as_float), wasm_f32x4_const_splat(0) ); \-    v128_t bf = wasm_f32x4_max( wasm_f32x4_min(bb, STBIR_max_uint8_as_float), wasm_f32x4_const_splat(0) ); \-    v128_t ai = wasm_i32x4_trunc_sat_f32x4( af ); \-    v128_t bi = wasm_i32x4_trunc_sat_f32x4( bf ); \-    v128_t out16 = wasm_i16x8_narrow_i32x4( ai, bi ); \-    out = wasm_u8x16_narrow_i16x8( out16, out16 ); \-  }--  #define stbir__simdf_pack_to_8words(out,aa,bb) \-  { \-    v128_t af = wasm_f32x4_max( wasm_f32x4_min(aa, STBIR_max_uint16_as_float), wasm_f32x4_const_splat(0)); \-    v128_t bf = wasm_f32x4_max( wasm_f32x4_min(bb, STBIR_max_uint16_as_float), wasm_f32x4_const_splat(0)); \-    v128_t ai = wasm_i32x4_trunc_sat_f32x4( af ); \-    v128_t bi = wasm_i32x4_trunc_sat_f32x4( bf ); \-    out = wasm_u16x8_narrow_i32x4( ai, bi ); \-  }--  #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \-  { \-    v128_t tmp0 = wasm_i16x8_narrow_i32x4(r0, r1); \-    v128_t tmp1 = wasm_i16x8_narrow_i32x4(r2, r3); \-    v128_t tmp = wasm_u8x16_narrow_i16x8(tmp0, tmp1); \-    tmp = wasm_i8x16_shuffle(tmp, tmp, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15); \-    wasm_v128_store( (void*)(ptr), tmp); \-  }--  #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \-  { \-    v128_t t0 = wasm_v128_load( ptr    ); \-    v128_t t1 = wasm_v128_load( ptr+4  ); \-    v128_t t2 = wasm_v128_load( ptr+8  ); \-    v128_t t3 = wasm_v128_load( ptr+12 ); \-    v128_t s0 = wasm_i32x4_shuffle(t0, t1, 0, 4, 2, 6); \-    v128_t s1 = wasm_i32x4_shuffle(t0, t1, 1, 5, 3, 7); \-    v128_t s2 = wasm_i32x4_shuffle(t2, t3, 0, 4, 2, 6); \-    v128_t s3 = wasm_i32x4_shuffle(t2, t3, 1, 5, 3, 7); \-    o0 = wasm_i32x4_shuffle(s0, s2, 0, 1, 4, 5); \-    o1 = wasm_i32x4_shuffle(s1, s3, 0, 1, 4, 5); \-    o2 = wasm_i32x4_shuffle(s0, s2, 2, 3, 6, 7); \-    o3 = wasm_i32x4_shuffle(s1, s3, 2, 3, 6, 7); \-  }--  #define stbir__simdi_32shr( out, reg, imm ) out = wasm_u32x4_shr( reg, imm )--  typedef float stbir__f32x4 __attribute__((__vector_size__(16), __aligned__(16)));-  #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = (v128_t)(stbir__f32x4){ x, x, x, x }-  #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { x, x, x, x }-  #define STBIR__CONSTF(var) (var)-  #define STBIR__CONSTI(var) (var)--  #ifdef STBIR_FLOORF-  #undef STBIR_FLOORF-  #endif-  #define STBIR_FLOORF stbir_simd_floorf-  static stbir__inline float stbir_simd_floorf(float x)-  {-    return wasm_f32x4_extract_lane( wasm_f32x4_floor( wasm_f32x4_splat(x) ), 0);-  }--  #ifdef STBIR_CEILF-  #undef STBIR_CEILF-  #endif-  #define STBIR_CEILF stbir_simd_ceilf-  static stbir__inline float stbir_simd_ceilf(float x)-  {-    return wasm_f32x4_extract_lane( wasm_f32x4_ceil( wasm_f32x4_splat(x) ), 0);-  }--  #define STBIR_SIMD--#endif  // SSE2/NEON/WASM--#endif // NO SIMD--#ifdef STBIR_SIMD8-  #define stbir__simdfX stbir__simdf8-  #define stbir__simdiX stbir__simdi8-  #define stbir__simdfX_load stbir__simdf8_load-  #define stbir__simdiX_load stbir__simdi8_load-  #define stbir__simdfX_mult stbir__simdf8_mult-  #define stbir__simdfX_add_mem stbir__simdf8_add_mem-  #define stbir__simdfX_madd_mem stbir__simdf8_madd_mem-  #define stbir__simdfX_store stbir__simdf8_store-  #define stbir__simdiX_store stbir__simdi8_store-  #define stbir__simdf_frepX  stbir__simdf8_frep8-  #define stbir__simdfX_madd stbir__simdf8_madd-  #define stbir__simdfX_min stbir__simdf8_min-  #define stbir__simdfX_max stbir__simdf8_max-  #define stbir__simdfX_aaa1 stbir__simdf8_aaa1-  #define stbir__simdfX_1aaa stbir__simdf8_1aaa-  #define stbir__simdfX_a1a1 stbir__simdf8_a1a1-  #define stbir__simdfX_1a1a stbir__simdf8_1a1a-  #define stbir__simdfX_convert_float_to_i32 stbir__simdf8_convert_float_to_i32-  #define stbir__simdfX_pack_to_words stbir__simdf8_pack_to_16words-  #define stbir__simdfX_zero stbir__simdf8_zero-  #define STBIR_onesX STBIR_ones8-  #define STBIR_max_uint8_as_floatX STBIR_max_uint8_as_float8-  #define STBIR_max_uint16_as_floatX STBIR_max_uint16_as_float8-  #define STBIR_simd_point5X STBIR_simd_point58-  #define stbir__simdfX_float_count 8-  #define stbir__simdfX_0123to1230 stbir__simdf8_0123to12301230-  #define stbir__simdfX_0123to2103 stbir__simdf8_0123to21032103-  static const stbir__simdf8 STBIR_max_uint16_as_float_inverted8 = { stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted };-  static const stbir__simdf8 STBIR_max_uint8_as_float_inverted8 = { stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted };-  static const stbir__simdf8 STBIR_ones8 = { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 };-  static const stbir__simdf8 STBIR_simd_point58 = { 0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5 };-  static const stbir__simdf8 STBIR_max_uint8_as_float8 = { stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float, stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float };-  static const stbir__simdf8 STBIR_max_uint16_as_float8 = { stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float, stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float };-#else-  #define stbir__simdfX stbir__simdf-  #define stbir__simdiX stbir__simdi-  #define stbir__simdfX_load stbir__simdf_load-  #define stbir__simdiX_load stbir__simdi_load-  #define stbir__simdfX_mult stbir__simdf_mult-  #define stbir__simdfX_add_mem stbir__simdf_add_mem-  #define stbir__simdfX_madd_mem stbir__simdf_madd_mem-  #define stbir__simdfX_store stbir__simdf_store-  #define stbir__simdiX_store stbir__simdi_store-  #define stbir__simdf_frepX  stbir__simdf_frep4-  #define stbir__simdfX_madd stbir__simdf_madd-  #define stbir__simdfX_min stbir__simdf_min-  #define stbir__simdfX_max stbir__simdf_max-  #define stbir__simdfX_aaa1 stbir__simdf_aaa1-  #define stbir__simdfX_1aaa stbir__simdf_1aaa-  #define stbir__simdfX_a1a1 stbir__simdf_a1a1-  #define stbir__simdfX_1a1a stbir__simdf_1a1a-  #define stbir__simdfX_convert_float_to_i32 stbir__simdf_convert_float_to_i32-  #define stbir__simdfX_pack_to_words stbir__simdf_pack_to_8words-  #define stbir__simdfX_zero stbir__simdf_zero-  #define STBIR_onesX STBIR__CONSTF(STBIR_ones)-  #define STBIR_simd_point5X STBIR__CONSTF(STBIR_simd_point5)-  #define STBIR_max_uint8_as_floatX STBIR__CONSTF(STBIR_max_uint8_as_float)-  #define STBIR_max_uint16_as_floatX STBIR__CONSTF(STBIR_max_uint16_as_float)-  #define stbir__simdfX_float_count 4-  #define stbir__if_simdf8_cast_to_simdf4( val ) ( val )-  #define stbir__simdfX_0123to1230 stbir__simdf_0123to1230-  #define stbir__simdfX_0123to2103 stbir__simdf_0123to2103-#endif---#if defined(STBIR_NEON) && !defined(_M_ARM)--  #if defined( _MSC_VER ) && !defined(__clang__)-  typedef __int16 stbir__FP16;-  #else-  typedef float16_t stbir__FP16;-  #endif--#else // no NEON, or 32-bit ARM for MSVC--  typedef union stbir__FP16-  {-    unsigned short u;-  } stbir__FP16;--#endif--#if !defined(STBIR_NEON) && !defined(STBIR_FP16C) || defined(STBIR_NEON) && defined(_M_ARM)--  // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668--  static stbir__inline float stbir__half_to_float( stbir__FP16 h )-  {-    static const stbir__FP32 magic = { (254 - 15) << 23 };-    static const stbir__FP32 was_infnan = { (127 + 16) << 23 };-    stbir__FP32 o;--    o.u = (h.u & 0x7fff) << 13;     // exponent/mantissa bits-    o.f *= magic.f;                 // exponent adjust-    if (o.f >= was_infnan.f)        // make sure Inf/NaN survive-      o.u |= 255 << 23;-    o.u |= (h.u & 0x8000) << 16;    // sign bit-    return o.f;-  }--  static stbir__inline stbir__FP16 stbir__float_to_half(float val)-  {-    stbir__FP32 f32infty = { 255 << 23 };-    stbir__FP32 f16max   = { (127 + 16) << 23 };-    stbir__FP32 denorm_magic = { ((127 - 15) + (23 - 10) + 1) << 23 };-    unsigned int sign_mask = 0x80000000u;-    stbir__FP16 o = { 0 };-    stbir__FP32 f;-    unsigned int sign; --    f.f = val;-    sign = f.u & sign_mask;-    f.u ^= sign;--    if (f.u >= f16max.u) // result is Inf or NaN (all exponent bits set)-      o.u = (f.u > f32infty.u) ? 0x7e00 : 0x7c00; // NaN->qNaN and Inf->Inf-    else // (De)normalized number or zero-    {-      if (f.u < (113 << 23)) // resulting FP16 is subnormal or zero-      {-        // use a magic value to align our 10 mantissa bits at the bottom of-        // the float. as long as FP addition is round-to-nearest-even this-        // just works.-        f.f += denorm_magic.f;-        // and one integer subtract of the bias later, we have our final float!-        o.u = (unsigned short) ( f.u - denorm_magic.u );-      }-      else-      {-        unsigned int mant_odd = (f.u >> 13) & 1; // resulting mantissa is odd-        // update exponent, rounding bias part 1-        f.u = f.u + ((15u - 127) << 23) + 0xfff;-        // rounding bias part 2-        f.u += mant_odd;-        // take the bits!-        o.u = (unsigned short) ( f.u >> 13 );-      }-    }--    o.u |= sign >> 16;-    return o;-  }--#endif---#if defined(STBIR_FP16C)--  #include <immintrin.h>--  static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input)-  {-    _mm256_storeu_ps( (float*)output, _mm256_cvtph_ps( _mm_loadu_si128( (__m128i const* )input ) ) );-  }--  static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input)-  {-    _mm_storeu_si128( (__m128i*)output, _mm256_cvtps_ph( _mm256_loadu_ps( input ), 0 ) );-  }--  static stbir__inline float stbir__half_to_float( stbir__FP16 h )-  {-    return _mm_cvtss_f32( _mm_cvtph_ps( _mm_cvtsi32_si128( (int)h.u ) ) );-  }--  static stbir__inline stbir__FP16 stbir__float_to_half( float f )-  {-    stbir__FP16 h;-    h.u = (unsigned short) _mm_cvtsi128_si32( _mm_cvtps_ph( _mm_set_ss( f ), 0 ) );-    return h;-  }--#elif defined(STBIR_SSE2)--  // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668-  stbir__inline static void stbir__half_to_float_SIMD(float * output, void const * input)-  {-    static const STBIR__SIMDI_CONST(mask_nosign,      0x7fff);-    static const STBIR__SIMDI_CONST(smallest_normal,  0x0400);-    static const STBIR__SIMDI_CONST(infinity,         0x7c00);-    static const STBIR__SIMDI_CONST(expadjust_normal, (127 - 15) << 23);-    static const STBIR__SIMDI_CONST(magic_denorm,     113 << 23);--    __m128i i = _mm_loadu_si128 ( (__m128i const*)(input) );-    __m128i h = _mm_unpacklo_epi16 ( i, _mm_setzero_si128() );-    __m128i mnosign     = STBIR__CONSTI(mask_nosign);-    __m128i eadjust     = STBIR__CONSTI(expadjust_normal);-    __m128i smallest    = STBIR__CONSTI(smallest_normal);-    __m128i infty       = STBIR__CONSTI(infinity);-    __m128i expmant     = _mm_and_si128(mnosign, h);-    __m128i justsign    = _mm_xor_si128(h, expmant);-    __m128i b_notinfnan = _mm_cmpgt_epi32(infty, expmant);-    __m128i b_isdenorm  = _mm_cmpgt_epi32(smallest, expmant);-    __m128i shifted     = _mm_slli_epi32(expmant, 13);-    __m128i adj_infnan  = _mm_andnot_si128(b_notinfnan, eadjust);-    __m128i adjusted    = _mm_add_epi32(eadjust, shifted);-    __m128i den1        = _mm_add_epi32(shifted, STBIR__CONSTI(magic_denorm));-    __m128i adjusted2   = _mm_add_epi32(adjusted, adj_infnan);-    __m128  den2        = _mm_sub_ps(_mm_castsi128_ps(den1), *(const __m128 *)&magic_denorm);-    __m128  adjusted3   = _mm_and_ps(den2, _mm_castsi128_ps(b_isdenorm));-    __m128  adjusted4   = _mm_andnot_ps(_mm_castsi128_ps(b_isdenorm), _mm_castsi128_ps(adjusted2));-    __m128  adjusted5   = _mm_or_ps(adjusted3, adjusted4);-    __m128i sign        = _mm_slli_epi32(justsign, 16);-    __m128  final       = _mm_or_ps(adjusted5, _mm_castsi128_ps(sign));-    stbir__simdf_store( output + 0,  final );--    h = _mm_unpackhi_epi16 ( i, _mm_setzero_si128() );-    expmant     = _mm_and_si128(mnosign, h);-    justsign    = _mm_xor_si128(h, expmant);-    b_notinfnan = _mm_cmpgt_epi32(infty, expmant);-    b_isdenorm  = _mm_cmpgt_epi32(smallest, expmant);-    shifted     = _mm_slli_epi32(expmant, 13);-    adj_infnan  = _mm_andnot_si128(b_notinfnan, eadjust);-    adjusted    = _mm_add_epi32(eadjust, shifted);-    den1        = _mm_add_epi32(shifted, STBIR__CONSTI(magic_denorm));-    adjusted2   = _mm_add_epi32(adjusted, adj_infnan);-    den2        = _mm_sub_ps(_mm_castsi128_ps(den1), *(const __m128 *)&magic_denorm);-    adjusted3   = _mm_and_ps(den2, _mm_castsi128_ps(b_isdenorm));-    adjusted4   = _mm_andnot_ps(_mm_castsi128_ps(b_isdenorm), _mm_castsi128_ps(adjusted2));-    adjusted5   = _mm_or_ps(adjusted3, adjusted4);-    sign        = _mm_slli_epi32(justsign, 16);-    final       = _mm_or_ps(adjusted5, _mm_castsi128_ps(sign));-    stbir__simdf_store( output + 4,  final );--    // ~38 SSE2 ops for 8 values-  }--  // Fabian's round-to-nearest-even float to half-  // ~48 SSE2 ops for 8 output-  stbir__inline static void stbir__float_to_half_SIMD(void * output, float const * input)-  {-    static const STBIR__SIMDI_CONST(mask_sign,      0x80000000u);-    static const STBIR__SIMDI_CONST(c_f16max,       (127 + 16) << 23); // all FP32 values >=this round to +inf-    static const STBIR__SIMDI_CONST(c_nanbit,        0x200);-    static const STBIR__SIMDI_CONST(c_infty_as_fp16, 0x7c00);-    static const STBIR__SIMDI_CONST(c_min_normal,    (127 - 14) << 23); // smallest FP32 that yields a normalized FP16-    static const STBIR__SIMDI_CONST(c_subnorm_magic, ((127 - 15) + (23 - 10) + 1) << 23);-    static const STBIR__SIMDI_CONST(c_normal_bias,    0xfff - ((127 - 15) << 23)); // adjust exponent and add mantissa rounding--    __m128  f           =  _mm_loadu_ps(input);-    __m128  msign       = _mm_castsi128_ps(STBIR__CONSTI(mask_sign));-    __m128  justsign    = _mm_and_ps(msign, f);-    __m128  absf        = _mm_xor_ps(f, justsign);-    __m128i absf_int    = _mm_castps_si128(absf); // the cast is "free" (extra bypass latency, but no thruput hit)-    __m128i f16max      = STBIR__CONSTI(c_f16max);-    __m128  b_isnan     = _mm_cmpunord_ps(absf, absf); // is this a NaN?-    __m128i b_isregular = _mm_cmpgt_epi32(f16max, absf_int); // (sub)normalized or special?-    __m128i nanbit      = _mm_and_si128(_mm_castps_si128(b_isnan), STBIR__CONSTI(c_nanbit));-    __m128i inf_or_nan  = _mm_or_si128(nanbit, STBIR__CONSTI(c_infty_as_fp16)); // output for specials--    __m128i min_normal  = STBIR__CONSTI(c_min_normal);-    __m128i b_issub     = _mm_cmpgt_epi32(min_normal, absf_int);--    // "result is subnormal" path-    __m128  subnorm1    = _mm_add_ps(absf, _mm_castsi128_ps(STBIR__CONSTI(c_subnorm_magic))); // magic value to round output mantissa-    __m128i subnorm2    = _mm_sub_epi32(_mm_castps_si128(subnorm1), STBIR__CONSTI(c_subnorm_magic)); // subtract out bias--    // "result is normal" path-    __m128i mantoddbit  = _mm_slli_epi32(absf_int, 31 - 13); // shift bit 13 (mantissa LSB) to sign-    __m128i mantodd     = _mm_srai_epi32(mantoddbit, 31); // -1 if FP16 mantissa odd, else 0--    __m128i round1      = _mm_add_epi32(absf_int, STBIR__CONSTI(c_normal_bias));-    __m128i round2      = _mm_sub_epi32(round1, mantodd); // if mantissa LSB odd, bias towards rounding up (RTNE)-    __m128i normal      = _mm_srli_epi32(round2, 13); // rounded result--    // combine the two non-specials-    __m128i nonspecial  = _mm_or_si128(_mm_and_si128(subnorm2, b_issub), _mm_andnot_si128(b_issub, normal));--    // merge in specials as well-    __m128i joined      = _mm_or_si128(_mm_and_si128(nonspecial, b_isregular), _mm_andnot_si128(b_isregular, inf_or_nan));--    __m128i sign_shift  = _mm_srai_epi32(_mm_castps_si128(justsign), 16);-    __m128i final2, final= _mm_or_si128(joined, sign_shift);--    f           =  _mm_loadu_ps(input+4);-    justsign    = _mm_and_ps(msign, f);-    absf        = _mm_xor_ps(f, justsign);-    absf_int    = _mm_castps_si128(absf); // the cast is "free" (extra bypass latency, but no thruput hit)-    b_isnan     = _mm_cmpunord_ps(absf, absf); // is this a NaN?-    b_isregular = _mm_cmpgt_epi32(f16max, absf_int); // (sub)normalized or special?-    nanbit      = _mm_and_si128(_mm_castps_si128(b_isnan), c_nanbit);-    inf_or_nan  = _mm_or_si128(nanbit, STBIR__CONSTI(c_infty_as_fp16)); // output for specials--    b_issub     = _mm_cmpgt_epi32(min_normal, absf_int);--    // "result is subnormal" path-    subnorm1    = _mm_add_ps(absf, _mm_castsi128_ps(STBIR__CONSTI(c_subnorm_magic))); // magic value to round output mantissa-    subnorm2    = _mm_sub_epi32(_mm_castps_si128(subnorm1), STBIR__CONSTI(c_subnorm_magic)); // subtract out bias--    // "result is normal" path-    mantoddbit  = _mm_slli_epi32(absf_int, 31 - 13); // shift bit 13 (mantissa LSB) to sign-    mantodd     = _mm_srai_epi32(mantoddbit, 31); // -1 if FP16 mantissa odd, else 0--    round1      = _mm_add_epi32(absf_int, STBIR__CONSTI(c_normal_bias));-    round2      = _mm_sub_epi32(round1, mantodd); // if mantissa LSB odd, bias towards rounding up (RTNE)-    normal      = _mm_srli_epi32(round2, 13); // rounded result--    // combine the two non-specials-    nonspecial  = _mm_or_si128(_mm_and_si128(subnorm2, b_issub), _mm_andnot_si128(b_issub, normal));--    // merge in specials as well-    joined      = _mm_or_si128(_mm_and_si128(nonspecial, b_isregular), _mm_andnot_si128(b_isregular, inf_or_nan));--    sign_shift  = _mm_srai_epi32(_mm_castps_si128(justsign), 16);-    final2      = _mm_or_si128(joined, sign_shift);-    final       = _mm_packs_epi32(final, final2);-    stbir__simdi_store( output,final );-  }--#elif defined(STBIR_WASM) || (defined(STBIR_NEON) && defined(_MSC_VER) && defined(_M_ARM)) // WASM or 32-bit ARM on MSVC/clang--  static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input)-  {-    for (int i=0; i<8; i++)-    {-      output[i] = stbir__half_to_float(input[i]);-    }-  }--  static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input)-  {-    for (int i=0; i<8; i++)-    {-      output[i] = stbir__float_to_half(input[i]);-    }-  }--#elif defined(STBIR_NEON) && defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__) // 64-bit ARM on MSVC (not clang)--  static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input)-  {-    float16x4_t in0 = vld1_f16(input + 0);-    float16x4_t in1 = vld1_f16(input + 4);-    vst1q_f32(output + 0, vcvt_f32_f16(in0));-    vst1q_f32(output + 4, vcvt_f32_f16(in1));-  }--  static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input)-  {-    float16x4_t out0 = vcvt_f16_f32(vld1q_f32(input + 0));-    float16x4_t out1 = vcvt_f16_f32(vld1q_f32(input + 4));-    vst1_f16(output+0, out0);-    vst1_f16(output+4, out1);-  }--  static stbir__inline float stbir__half_to_float( stbir__FP16 h )-  {-    return vgetq_lane_f32(vcvt_f32_f16(vld1_dup_f16(&h)), 0);-  }--  static stbir__inline stbir__FP16 stbir__float_to_half( float f )-  {-    return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0).n16_u16[0];-  }--#elif defined(STBIR_NEON) // 64-bit ARM--  static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input)-  {-    float16x8_t in = vld1q_f16(input);-    vst1q_f32(output + 0, vcvt_f32_f16(vget_low_f16(in)));-    vst1q_f32(output + 4, vcvt_f32_f16(vget_high_f16(in)));-  }--  static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input)-  {-    float16x4_t out0 = vcvt_f16_f32(vld1q_f32(input + 0));-    float16x4_t out1 = vcvt_f16_f32(vld1q_f32(input + 4));-    vst1q_f16(output, vcombine_f16(out0, out1));-  }--  static stbir__inline float stbir__half_to_float( stbir__FP16 h )-  {-    return vgetq_lane_f32(vcvt_f32_f16(vdup_n_f16(h)), 0);-  }--  static stbir__inline stbir__FP16 stbir__float_to_half( float f )-  {-    return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0);-  }--#endif---#ifdef STBIR_SIMD--#define stbir__simdf_0123to3333( out, reg ) (out) = stbir__simdf_swiz( reg, 3,3,3,3 )-#define stbir__simdf_0123to2222( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,2,2 )-#define stbir__simdf_0123to1111( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,1,1 )-#define stbir__simdf_0123to0000( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,0 )-#define stbir__simdf_0123to0003( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,3 )-#define stbir__simdf_0123to0001( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,1 )-#define stbir__simdf_0123to1122( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,2,2 )-#define stbir__simdf_0123to2333( out, reg ) (out) = stbir__simdf_swiz( reg, 2,3,3,3 )-#define stbir__simdf_0123to0023( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,3 )-#define stbir__simdf_0123to1230( out, reg ) (out) = stbir__simdf_swiz( reg, 1,2,3,0 )-#define stbir__simdf_0123to2103( out, reg ) (out) = stbir__simdf_swiz( reg, 2,1,0,3 )-#define stbir__simdf_0123to3210( out, reg ) (out) = stbir__simdf_swiz( reg, 3,2,1,0 )-#define stbir__simdf_0123to2301( out, reg ) (out) = stbir__simdf_swiz( reg, 2,3,0,1 )-#define stbir__simdf_0123to3012( out, reg ) (out) = stbir__simdf_swiz( reg, 3,0,1,2 )-#define stbir__simdf_0123to0011( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,1,1 )-#define stbir__simdf_0123to1100( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,0,0 )-#define stbir__simdf_0123to2233( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,3,3 ) -#define stbir__simdf_0123to1133( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,3,3 ) -#define stbir__simdf_0123to0022( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,2 ) -#define stbir__simdf_0123to1032( out, reg ) (out) = stbir__simdf_swiz( reg, 1,0,3,2 ) --typedef union stbir__simdi_u32-{-  stbir_uint32 m128i_u32[4];-  int m128i_i32[4];-  stbir__simdi m128i_i128;-} stbir__simdi_u32;--static const int STBIR_mask[9] = { 0,0,0,-1,-1,-1,0,0,0 };--static const STBIR__SIMDF_CONST(STBIR_max_uint8_as_float,           stbir__max_uint8_as_float);-static const STBIR__SIMDF_CONST(STBIR_max_uint16_as_float,          stbir__max_uint16_as_float);-static const STBIR__SIMDF_CONST(STBIR_max_uint8_as_float_inverted,  stbir__max_uint8_as_float_inverted);-static const STBIR__SIMDF_CONST(STBIR_max_uint16_as_float_inverted, stbir__max_uint16_as_float_inverted);--static const STBIR__SIMDF_CONST(STBIR_simd_point5,   0.5f);-static const STBIR__SIMDF_CONST(STBIR_ones,          1.0f);-static const STBIR__SIMDI_CONST(STBIR_almost_zero,   (127 - 13) << 23);-static const STBIR__SIMDI_CONST(STBIR_almost_one,    0x3f7fffff);-static const STBIR__SIMDI_CONST(STBIR_mastissa_mask, 0xff);-static const STBIR__SIMDI_CONST(STBIR_topscale,      0x02000000);--//   Basically, in simd mode, we unroll the proper amount, and we don't want-//   the non-simd remnant loops to be unroll because they only run a few times-//   Adding this switch saves about 5K on clang which is Captain Unroll the 3rd.-#define STBIR_SIMD_STREAMOUT_PTR( star )  STBIR_STREAMOUT_PTR( star )-#define STBIR_SIMD_NO_UNROLL(ptr) STBIR_NO_UNROLL(ptr)--#ifdef STBIR_MEMCPY-#undef STBIR_MEMCPY-#define STBIR_MEMCPY stbir_simd_memcpy-#endif--// override normal use of memcpy with much simpler copy (faster and smaller with our sized copies)-static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes ) -{-  char STBIR_SIMD_STREAMOUT_PTR (*) d = (char*) dest;-  char STBIR_SIMD_STREAMOUT_PTR( * ) d_end = ((char*) dest) + bytes;-  ptrdiff_t ofs_to_src = (char*)src - (char*)dest;--  // check overlaps-  STBIR_ASSERT( ( ( d >= ( (char*)src) + bytes ) ) || ( ( d + bytes ) <= (char*)src ) );--  if ( bytes < (16*stbir__simdfX_float_count) )-  {-    if ( bytes < 16 )-    {-      if ( bytes ) -      {-        do-        {-          STBIR_SIMD_NO_UNROLL(d);-          d[ 0 ] = d[ ofs_to_src ];-          ++d;-        } while ( d < d_end );-      }-    }-    else-    {-      stbir__simdf x;-      // do one unaligned to get us aligned for the stream out below-      stbir__simdf_load( x, ( d + ofs_to_src ) );-      stbir__simdf_store( d, x );-      d = (char*)( ( ( (ptrdiff_t)d ) + 16 ) & ~15 );--      for(;;)-      {-        STBIR_SIMD_NO_UNROLL(d);--        if ( d > ( d_end - 16 ) )-        {-          if ( d == d_end )-            return;-          d = d_end - 16;-        }--        stbir__simdf_load( x, ( d + ofs_to_src ) );-        stbir__simdf_store( d, x );-        d += 16;-      }-    }-  }-  else-  {-    stbir__simdfX x0,x1,x2,x3;--    // do one unaligned to get us aligned for the stream out below-    stbir__simdfX_load( x0, ( d + ofs_to_src ) +  0*stbir__simdfX_float_count );-    stbir__simdfX_load( x1, ( d + ofs_to_src ) +  4*stbir__simdfX_float_count );-    stbir__simdfX_load( x2, ( d + ofs_to_src ) +  8*stbir__simdfX_float_count );-    stbir__simdfX_load( x3, ( d + ofs_to_src ) + 12*stbir__simdfX_float_count );-    stbir__simdfX_store( d +  0*stbir__simdfX_float_count, x0 );-    stbir__simdfX_store( d +  4*stbir__simdfX_float_count, x1 );-    stbir__simdfX_store( d +  8*stbir__simdfX_float_count, x2 );-    stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 );-    d = (char*)( ( ( (ptrdiff_t)d ) + (16*stbir__simdfX_float_count) ) & ~((16*stbir__simdfX_float_count)-1) );--    for(;;)-    {-      STBIR_SIMD_NO_UNROLL(d);-  -      if ( d > ( d_end - (16*stbir__simdfX_float_count) ) )-      {-        if ( d == d_end )-          return;-        d = d_end - (16*stbir__simdfX_float_count);-      }--      stbir__simdfX_load( x0, ( d + ofs_to_src ) +  0*stbir__simdfX_float_count );-      stbir__simdfX_load( x1, ( d + ofs_to_src ) +  4*stbir__simdfX_float_count );-      stbir__simdfX_load( x2, ( d + ofs_to_src ) +  8*stbir__simdfX_float_count );-      stbir__simdfX_load( x3, ( d + ofs_to_src ) + 12*stbir__simdfX_float_count );-      stbir__simdfX_store( d +  0*stbir__simdfX_float_count, x0 );-      stbir__simdfX_store( d +  4*stbir__simdfX_float_count, x1 );-      stbir__simdfX_store( d +  8*stbir__simdfX_float_count, x2 );-      stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 );-      d += (16*stbir__simdfX_float_count);-    }-  }-}--// memcpy that is specically intentionally overlapping (src is smaller then dest, so can be-//   a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to-//   the diff between dest and src)-static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) -{-  char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src;-  char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes;-  ptrdiff_t ofs_to_dest = (char*)dest - (char*)src;--  if ( ofs_to_dest >= 16 ) // is the overlap more than 16 away?-  {-    char STBIR_SIMD_STREAMOUT_PTR( * ) s_end16 = ((char*) src) + (bytes&~15);-    do-    {-      stbir__simdf x;-      STBIR_SIMD_NO_UNROLL(sd);-      stbir__simdf_load( x, sd );-      stbir__simdf_store(  ( sd + ofs_to_dest ), x );-      sd += 16;-    } while ( sd < s_end16 );--    if ( sd == s_end )-      return;-  }--  do-  {-    STBIR_SIMD_NO_UNROLL(sd);-    *(int*)( sd + ofs_to_dest ) = *(int*) sd; -    sd += 4;-  } while ( sd < s_end );-}--#else // no SSE2--// when in scalar mode, we let unrolling happen, so this macro just does the __restrict-#define STBIR_SIMD_STREAMOUT_PTR( star ) STBIR_STREAMOUT_PTR( star )-#define STBIR_SIMD_NO_UNROLL(ptr) --#endif // SSE2---#ifdef STBIR_PROFILE--#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined(STBIR_SSE) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ )--#ifdef _MSC_VER--  STBIRDEF stbir_uint64 __rdtsc();-  #define STBIR_PROFILE_FUNC() __rdtsc()--#else // non msvc--  static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() -  {-    stbir_uint32 lo, hi;-    asm volatile ("rdtsc" : "=a" (lo), "=d" (hi) );-    return ( ( (stbir_uint64) hi ) << 32 ) | ( (stbir_uint64) lo );-  }--#endif  // msvc--#elif defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) --#if defined( _MSC_VER ) && !defined(__clang__)--  #define STBIR_PROFILE_FUNC() _ReadStatusReg(ARM64_CNTVCT)--#else--  static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC()-  {-    stbir_uint64 tsc;-    asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));-    return tsc;-  }--#endif--#else // x64, arm--#error Unknown platform for profiling.--#endif  //x64 and   ---#define STBIR_ONLY_PROFILE_GET_SPLIT_INFO ,stbir__per_split_info * split_info-#define STBIR_ONLY_PROFILE_SET_SPLIT_INFO ,split_info--#define STBIR_ONLY_PROFILE_BUILD_GET_INFO ,stbir__info * profile_info-#define STBIR_ONLY_PROFILE_BUILD_SET_INFO ,profile_info--// super light-weight micro profiler-#define STBIR_PROFILE_START_ll( info, wh ) { stbir_uint64 wh##thiszonetime = STBIR_PROFILE_FUNC(); stbir_uint64 * wh##save_parent_excluded_ptr = info->current_zone_excluded_ptr; stbir_uint64 wh##current_zone_excluded = 0; info->current_zone_excluded_ptr = &wh##current_zone_excluded; -#define STBIR_PROFILE_END_ll( info, wh ) wh##thiszonetime = STBIR_PROFILE_FUNC() - wh##thiszonetime; info->profile.named.wh += wh##thiszonetime - wh##current_zone_excluded; *wh##save_parent_excluded_ptr += wh##thiszonetime; info->current_zone_excluded_ptr = wh##save_parent_excluded_ptr; }-#define STBIR_PROFILE_FIRST_START_ll( info, wh ) { int i; info->current_zone_excluded_ptr = &info->profile.named.total; for(i=0;i<STBIR__ARRAY_SIZE(info->profile.array);i++) info->profile.array[i]=0; } STBIR_PROFILE_START_ll( info, wh );-#define STBIR_PROFILE_CLEAR_EXTRAS_ll( info, num ) { int extra; for(extra=1;extra<(num);extra++) { int i; for(i=0;i<STBIR__ARRAY_SIZE((info)->profile.array);i++) (info)[extra].profile.array[i]=0; } }--// for thread data-#define STBIR_PROFILE_START( wh ) STBIR_PROFILE_START_ll( split_info, wh )-#define STBIR_PROFILE_END( wh ) STBIR_PROFILE_END_ll( split_info, wh )-#define STBIR_PROFILE_FIRST_START( wh ) STBIR_PROFILE_FIRST_START_ll( split_info, wh )-#define STBIR_PROFILE_CLEAR_EXTRAS() STBIR_PROFILE_CLEAR_EXTRAS_ll( split_info, split_count )--// for build data-#define STBIR_PROFILE_BUILD_START( wh ) STBIR_PROFILE_START_ll( profile_info, wh )-#define STBIR_PROFILE_BUILD_END( wh ) STBIR_PROFILE_END_ll( profile_info, wh )-#define STBIR_PROFILE_BUILD_FIRST_START( wh ) STBIR_PROFILE_FIRST_START_ll( profile_info, wh )-#define STBIR_PROFILE_BUILD_CLEAR( info ) { int i; for(i=0;i<STBIR__ARRAY_SIZE(info->profile.array);i++) info->profile.array[i]=0; }--#else  // no profile--#define STBIR_ONLY_PROFILE_GET_SPLIT_INFO-#define STBIR_ONLY_PROFILE_SET_SPLIT_INFO--#define STBIR_ONLY_PROFILE_BUILD_GET_INFO-#define STBIR_ONLY_PROFILE_BUILD_SET_INFO--#define STBIR_PROFILE_START( wh )-#define STBIR_PROFILE_END( wh )-#define STBIR_PROFILE_FIRST_START( wh )-#define STBIR_PROFILE_CLEAR_EXTRAS( )--#define STBIR_PROFILE_BUILD_START( wh ) -#define STBIR_PROFILE_BUILD_END( wh ) -#define STBIR_PROFILE_BUILD_FIRST_START( wh )-#define STBIR_PROFILE_BUILD_CLEAR( info )--#endif  // stbir_profile--#ifndef STBIR_CEILF-#include <math.h>-#if _MSC_VER <= 1200 // support VC6 for Sean-#define STBIR_CEILF(x) ((float)ceil((float)(x)))-#define STBIR_FLOORF(x) ((float)floor((float)(x)))-#else-#define STBIR_CEILF(x) ceilf(x)-#define STBIR_FLOORF(x) floorf(x)-#endif-#endif--#ifndef STBIR_MEMCPY-// For memcpy-#include <string.h>-#define STBIR_MEMCPY( dest, src, len ) memcpy( dest, src, len )-#endif--#ifndef STBIR_SIMD--// memcpy that is specically intentionally overlapping (src is smaller then dest, so can be-//   a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to-//   the diff between dest and src)-static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) -{-  char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src;-  char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes;-  ptrdiff_t ofs_to_dest = (char*)dest - (char*)src;--  if ( ofs_to_dest >= 8 ) // is the overlap more than 8 away?-  {-    char STBIR_SIMD_STREAMOUT_PTR( * ) s_end8 = ((char*) src) + (bytes&~7);-    do-    {-      STBIR_NO_UNROLL(sd);-      *(stbir_uint64*)( sd + ofs_to_dest ) = *(stbir_uint64*) sd; -      sd += 8;-    } while ( sd < s_end8 );--    if ( sd == s_end )-      return;-  }--  do-  {-    STBIR_NO_UNROLL(sd);-    *(int*)( sd + ofs_to_dest ) = *(int*) sd; -    sd += 4;-  } while ( sd < s_end );-}--#endif--static float stbir__filter_trapezoid(float x, float scale, void * user_data)-{-  float halfscale = scale / 2;-  float t = 0.5f + halfscale;-  STBIR_ASSERT(scale <= 1);-  STBIR__UNUSED(user_data);--  if ( x < 0.0f ) x = -x;--  if (x >= t)-    return 0.0f;-  else-  {-    float r = 0.5f - halfscale;-    if (x <= r)-      return 1.0f;-    else-      return (t - x) / scale;-  }-}--static float stbir__support_trapezoid(float scale, void * user_data)-{-  STBIR__UNUSED(user_data);-  return 0.5f + scale / 2.0f;-}--static float stbir__filter_triangle(float x, float s, void * user_data)-{-  STBIR__UNUSED(s);-  STBIR__UNUSED(user_data);--  if ( x < 0.0f ) x = -x;--  if (x <= 1.0f)-    return 1.0f - x;-  else-    return 0.0f;-}--static float stbir__filter_point(float x, float s, void * user_data)-{-  STBIR__UNUSED(x);-  STBIR__UNUSED(s);-  STBIR__UNUSED(user_data);--  return 1.0f;-}--static float stbir__filter_cubic(float x, float s, void * user_data)-{-  STBIR__UNUSED(s);-  STBIR__UNUSED(user_data);--  if ( x < 0.0f ) x = -x;--  if (x < 1.0f)-    return (4.0f + x*x*(3.0f*x - 6.0f))/6.0f;-  else if (x < 2.0f)-    return (8.0f + x*(-12.0f + x*(6.0f - x)))/6.0f;--  return (0.0f);-}--static float stbir__filter_catmullrom(float x, float s, void * user_data)-{-  STBIR__UNUSED(s);-  STBIR__UNUSED(user_data);--  if ( x < 0.0f ) x = -x;--  if (x < 1.0f)-    return 1.0f - x*x*(2.5f - 1.5f*x);-  else if (x < 2.0f)-    return 2.0f - x*(4.0f + x*(0.5f*x - 2.5f));--  return (0.0f);-}--static float stbir__filter_mitchell(float x, float s, void * user_data)-{-  STBIR__UNUSED(s);-  STBIR__UNUSED(user_data);--  if ( x < 0.0f ) x = -x;--  if (x < 1.0f)-    return (16.0f + x*x*(21.0f * x - 36.0f))/18.0f;-  else if (x < 2.0f)-    return (32.0f + x*(-60.0f + x*(36.0f - 7.0f*x)))/18.0f;--  return (0.0f);-}--static float stbir__support_zero(float s, void * user_data)-{-  STBIR__UNUSED(s);-  STBIR__UNUSED(user_data);-  return 0;-}--static float stbir__support_zeropoint5(float s, void * user_data)-{-  STBIR__UNUSED(s);-  STBIR__UNUSED(user_data);-  return 0.5f;-}--static float stbir__support_one(float s, void * user_data)-{-  STBIR__UNUSED(s);-  STBIR__UNUSED(user_data);-  return 1;-}--static float stbir__support_two(float s, void * user_data) -{-  STBIR__UNUSED(s);-  STBIR__UNUSED(user_data);-  return 2;-}--// This is the maximum number of input samples that can affect an output sample-// with the given filter from the output pixel's perspective-static int stbir__get_filter_pixel_width(stbir__support_callback * support, float scale, void * user_data)-{-  STBIR_ASSERT(support != 0);--  if ( scale >= ( 1.0f-stbir__small_float ) ) // upscale-    return (int)STBIR_CEILF(support(1.0f/scale,user_data) * 2.0f);-  else-    return (int)STBIR_CEILF(support(scale,user_data) * 2.0f / scale);-}--// this is how many coefficents per run of the filter (which is different -//   from the filter_pixel_width depending on if we are scattering or gathering)-static int stbir__get_coefficient_width(stbir__sampler * samp, int is_gather, void * user_data)-{-  float scale = samp->scale_info.scale;-  stbir__support_callback * support = samp->filter_support;--  switch( is_gather )-  {-    case 1:-      return (int)STBIR_CEILF(support(1.0f / scale, user_data) * 2.0f);-    case 2:-      return (int)STBIR_CEILF(support(scale, user_data) * 2.0f / scale);-    case 0:-      return (int)STBIR_CEILF(support(scale, user_data) * 2.0f);-    default:-      STBIR_ASSERT( (is_gather >= 0 ) && (is_gather <= 2 ) );-      return 0;-  }-}--static int stbir__get_contributors(stbir__sampler * samp, int is_gather)  -{-  if (is_gather)-      return samp->scale_info.output_sub_size;-  else-      return (samp->scale_info.input_full_size + samp->filter_pixel_margin * 2);-}--static int stbir__edge_zero_full( int n, int max )-{-  STBIR__UNUSED(n);-  STBIR__UNUSED(max);-  return 0; // NOTREACHED-}--static int stbir__edge_clamp_full( int n, int max )-{-  if (n < 0)-    return 0;--  if (n >= max)-    return max - 1;--  return n; // NOTREACHED-}--static int stbir__edge_reflect_full( int n, int max )-{-  if (n < 0)-  {-    if (n > -max)    -      return -n;-    else-      return max - 1;-  }--  if (n >= max)-  {-    int max2 = max * 2;-    if (n >= max2)-      return 0;-    else-      return max2 - n - 1;-  }--  return n; // NOTREACHED-}--static int stbir__edge_wrap_full( int n, int max )-{-  if (n >= 0)-    return (n % max);-  else-  {-    int m = (-n) % max;--    if (m != 0)-      m = max - m;--    return (m);-  }-}--typedef int stbir__edge_wrap_func( int n, int max );-static stbir__edge_wrap_func * stbir__edge_wrap_slow[] =-{-  stbir__edge_clamp_full,    // STBIR_EDGE_CLAMP-  stbir__edge_reflect_full,  // STBIR_EDGE_REFLECT-  stbir__edge_wrap_full,     // STBIR_EDGE_WRAP-  stbir__edge_zero_full,     // STBIR_EDGE_ZERO-};--stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max)-{-  // avoid per-pixel switch-  if (n >= 0 && n < max)-      return n;-  return stbir__edge_wrap_slow[edge]( n, max );-}--#define STBIR__MERGE_RUNS_PIXEL_THRESHOLD 16--// get information on the extents of a sampler-static void stbir__get_extents( stbir__sampler * samp, stbir__extents * scanline_extents )-{-  int j, stop;-  int left_margin, right_margin;-  int min_n = 0x7fffffff, max_n = -0x7fffffff;-  int min_left = 0x7fffffff, max_left = -0x7fffffff;-  int min_right = 0x7fffffff, max_right = -0x7fffffff;-  stbir_edge edge = samp->edge;-  stbir__contributors* contributors = samp->contributors;-  int output_sub_size = samp->scale_info.output_sub_size;-  int input_full_size = samp->scale_info.input_full_size;-  int filter_pixel_margin = samp->filter_pixel_margin;--  STBIR_ASSERT( samp->is_gather );--  stop = output_sub_size;-  for (j = 0; j < stop; j++ )-  {-    STBIR_ASSERT( contributors[j].n1 >= contributors[j].n0 );-    if ( contributors[j].n0 < min_n )-    {-      min_n = contributors[j].n0;-      stop = j + filter_pixel_margin;  // if we find a new min, only scan another filter width-      if ( stop > output_sub_size ) stop = output_sub_size;-    }-  }--  stop = 0;-  for (j = output_sub_size - 1; j >= stop; j-- )-  {-    STBIR_ASSERT( contributors[j].n1 >= contributors[j].n0 );-    if ( contributors[j].n1 > max_n )-    {-      max_n = contributors[j].n1;-      stop = j - filter_pixel_margin;  // if we find a new max, only scan another filter width-      if (stop<0) stop = 0;-    }-  }--  STBIR_ASSERT( scanline_extents->conservative.n0 <= min_n );-  STBIR_ASSERT( scanline_extents->conservative.n1 >= max_n );--  // now calculate how much into the margins we really read-  left_margin = 0;-  if ( min_n < 0 )-  {-    left_margin = -min_n;-    min_n = 0;-  }-  -  right_margin = 0;-  if ( max_n >= input_full_size )-  {-    right_margin = max_n - input_full_size + 1;-    max_n = input_full_size - 1;-  }--  // index 1 is margin pixel extents (how many pixels we hang over the edge)-  scanline_extents->edge_sizes[0] = left_margin;-  scanline_extents->edge_sizes[1] = right_margin;--  // index 2 is pixels read from the input-  scanline_extents->spans[0].n0 = min_n;-  scanline_extents->spans[0].n1 = max_n;-  scanline_extents->spans[0].pixel_offset_for_input = min_n;--  // default to no other input range-  scanline_extents->spans[1].n0 = 0;-  scanline_extents->spans[1].n1 = -1;-  scanline_extents->spans[1].pixel_offset_for_input = 0;--  // don't have to do edge calc for zero clamp-  if ( edge == STBIR_EDGE_ZERO )-    return;-  -  // convert margin pixels to the pixels within the input (min and max)-  for( j = -left_margin ; j < 0 ; j++ )-  {-      int p = stbir__edge_wrap( edge, j, input_full_size );-      if ( p < min_left )-        min_left = p;-      if ( p > max_left )-        max_left = p;-  }--  for( j = input_full_size ; j < (input_full_size + right_margin) ; j++ )-  {-      int p = stbir__edge_wrap( edge, j, input_full_size );-      if ( p < min_right )-        min_right = p;-      if ( p > max_right )-        max_right = p;-  }--  // merge the left margin pixel region if it connects within 4 pixels of main pixel region-  if ( min_left != 0x7fffffff )-  {-    if ( ( ( min_left <= min_n ) && ( ( max_left  + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= min_n ) ) ||-         ( ( min_n <= min_left ) && ( ( max_n  + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= max_left ) ) )-    {-      scanline_extents->spans[0].n0 = min_n = stbir__min( min_n, min_left );-      scanline_extents->spans[0].n1 = max_n = stbir__max( max_n, max_left );-      scanline_extents->spans[0].pixel_offset_for_input = min_n;-      left_margin = 0;-    }-  }--  // merge the right margin pixel region if it connects within 4 pixels of main pixel region-  if ( min_right != 0x7fffffff )-  {-    if ( ( ( min_right <= min_n ) && ( ( max_right  + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= min_n ) ) ||-         ( ( min_n <= min_right ) && ( ( max_n  + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= max_right ) ) )-    {-      scanline_extents->spans[0].n0 = min_n = stbir__min( min_n, min_right );-      scanline_extents->spans[0].n1 = max_n = stbir__max( max_n, max_right );-      scanline_extents->spans[0].pixel_offset_for_input = min_n;-      right_margin = 0;-    }-  }--  STBIR_ASSERT( scanline_extents->conservative.n0 <= min_n );-  STBIR_ASSERT( scanline_extents->conservative.n1 >= max_n );--  // you get two ranges when you have the WRAP edge mode and you are doing just the a piece of the resize-  //   so you need to get a second run of pixels from the opposite side of the scanline (which you-  //   wouldn't need except for WRAP)---  // if we can't merge the min_left range, add it as a second range-  if ( ( left_margin ) && ( min_left != 0x7fffffff ) )-  {-    stbir__span * newspan = scanline_extents->spans + 1;-    STBIR_ASSERT( right_margin == 0 );-    if ( min_left < scanline_extents->spans[0].n0 )-    {-      scanline_extents->spans[1].pixel_offset_for_input = scanline_extents->spans[0].n0;-      scanline_extents->spans[1].n0 = scanline_extents->spans[0].n0;-      scanline_extents->spans[1].n1 = scanline_extents->spans[0].n1;-      --newspan;-    }-    newspan->pixel_offset_for_input = min_left;-    newspan->n0 = -left_margin;-    newspan->n1 = ( max_left - min_left ) - left_margin;-    scanline_extents->edge_sizes[0] = 0;  // don't need to copy the left margin, since we are directly decoding into the margin-    return;-  }--  // if we can't merge the min_left range, add it as a second range-  if ( ( right_margin ) && ( min_right != 0x7fffffff ) )-  {-    stbir__span * newspan = scanline_extents->spans + 1;-    if ( min_right < scanline_extents->spans[0].n0 )-    {-      scanline_extents->spans[1].pixel_offset_for_input = scanline_extents->spans[0].n0;-      scanline_extents->spans[1].n0 = scanline_extents->spans[0].n0;-      scanline_extents->spans[1].n1 = scanline_extents->spans[0].n1;-      --newspan;-    }-    newspan->pixel_offset_for_input = min_right;-    newspan->n0 = scanline_extents->spans[1].n1 + 1;-    newspan->n1 = scanline_extents->spans[1].n1 + 1 + ( max_right - min_right );-    scanline_extents->edge_sizes[1] = 0;  // don't need to copy the right margin, since we are directly decoding into the margin-    return;-  }-}--static void stbir__calculate_in_pixel_range( int * first_pixel, int * last_pixel, float out_pixel_center, float out_filter_radius, float inv_scale, float out_shift, int input_size, stbir_edge edge )-{-  int first, last;-  float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius;-  float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius;--  float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) * inv_scale; -  float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) * inv_scale; --  first = (int)(STBIR_FLOORF(in_pixel_influence_lowerbound + 0.5f));-  last = (int)(STBIR_FLOORF(in_pixel_influence_upperbound - 0.5f));--  if ( edge == STBIR_EDGE_WRAP )-  {-    if ( first <= -input_size )-      first = -(input_size-1);-    if ( last >= (input_size*2))-      last = (input_size*2) - 1;-  }-  -  *first_pixel = first;-  *last_pixel = last;-}--static void stbir__calculate_coefficients_for_gather_upsample( float out_filter_radius, stbir__kernel_callback * kernel, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float* coefficient_group, int coefficient_width, stbir_edge edge, void * user_data )-{-  int n, end;-  float inv_scale = scale_info->inv_scale;-  float out_shift = scale_info->pixel_shift;-  int input_size  = scale_info->input_full_size;-  int numerator = scale_info->scale_numerator;-  int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < num_contributors ) );--  // Looping through out pixels-  end = num_contributors; if ( polyphase ) end = numerator;-  for (n = 0; n < end; n++)-  {-    int i;-    int last_non_zero;-    float out_pixel_center = (float)n + 0.5f;-    float in_center_of_out = (out_pixel_center + out_shift) * inv_scale;  --    int in_first_pixel, in_last_pixel;-    -    stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, out_pixel_center, out_filter_radius, inv_scale, out_shift, input_size, edge );--    last_non_zero = -1;-    for (i = 0; i <= in_last_pixel - in_first_pixel; i++)-    {-      float in_pixel_center = (float)(i + in_first_pixel) + 0.5f;-      float coeff = kernel(in_center_of_out - in_pixel_center, inv_scale, user_data);--      // kill denormals-      if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) )-      {-        if ( i == 0 )  // if we're at the front, just eat zero contributors-        { -          STBIR_ASSERT ( ( in_last_pixel - in_first_pixel ) != 0 ); // there should be at least one contrib-          ++in_first_pixel;-          i--;-          continue;-        }-        coeff = 0;  // make sure is fully zero (should keep denormals away)-      }-      else-        last_non_zero = i;-      -      coefficient_group[i] = coeff;-    }-    -    in_last_pixel = last_non_zero+in_first_pixel; // kills trailing zeros-    contributors->n0 = in_first_pixel;-    contributors->n1 = in_last_pixel;--    STBIR_ASSERT(contributors->n1 >= contributors->n0);--    ++contributors;-    coefficient_group += coefficient_width;-  }-}--static void stbir__insert_coeff( stbir__contributors * contribs, float * coeffs, int new_pixel, float new_coeff )-{-  if ( new_pixel <= contribs->n1 )  // before the end-  {-    if ( new_pixel < contribs->n0 ) // before the front?-    {-      int j, o = contribs->n0 - new_pixel;-      for ( j = contribs->n1 - contribs->n0 ; j <= 0 ; j-- )-        coeffs[ j + o ] = coeffs[ j ];-      for ( j = 1 ; j < o ; j-- )-        coeffs[ j ] = coeffs[ 0 ];-      coeffs[ 0 ] = new_coeff;-      contribs->n0 = new_pixel;-    }-    else-    {-      coeffs[ new_pixel - contribs->n0 ] += new_coeff;-    }-  }-  else-  {-    int j, e = new_pixel - contribs->n0;-    for( j = ( contribs->n1 - contribs->n0 ) + 1 ; j < e ; j++ ) // clear in-betweens coeffs if there are any-      coeffs[j] = 0;--    coeffs[ e ] = new_coeff;-    contribs->n1 = new_pixel;-  }-}--static void stbir__calculate_out_pixel_range( int * first_pixel, int * last_pixel, float in_pixel_center, float in_pixels_radius, float scale, float out_shift, int out_size )-{-  float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius;-  float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius;-  float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale - out_shift;-  float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale - out_shift;-  int out_first_pixel = (int)(STBIR_FLOORF(out_pixel_influence_lowerbound + 0.5f));-  int out_last_pixel = (int)(STBIR_FLOORF(out_pixel_influence_upperbound - 0.5f));--  if ( out_first_pixel < 0 )-    out_first_pixel = 0;-  if ( out_last_pixel >= out_size )-    out_last_pixel = out_size - 1;-  *first_pixel = out_first_pixel;-  *last_pixel = out_last_pixel;-}--static void stbir__calculate_coefficients_for_gather_downsample( int start, int end, float in_pixels_radius, stbir__kernel_callback * kernel, stbir__scale_info * scale_info, int coefficient_width, int num_contributors, stbir__contributors * contributors, float * coefficient_group, void * user_data )-{-  int in_pixel;-  int i;-  int first_out_inited = -1;-  float scale = scale_info->scale;-  float out_shift = scale_info->pixel_shift;-  int out_size = scale_info->output_sub_size;-  int numerator = scale_info->scale_numerator;-  int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < out_size ) );--  STBIR__UNUSED(num_contributors);--  // Loop through the input pixels-  for (in_pixel = start; in_pixel < end; in_pixel++)-  {-    float in_pixel_center = (float)in_pixel + 0.5f;-    float out_center_of_in = in_pixel_center * scale - out_shift;-    int out_first_pixel, out_last_pixel;--    stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, in_pixel_center, in_pixels_radius, scale, out_shift, out_size );--    if ( out_first_pixel > out_last_pixel )-      continue;--    // clamp or exit if we are using polyphase filtering, and the limit is up-    if ( polyphase )-    {-      // when polyphase, you only have to do coeffs up to the numerator count-      if ( out_first_pixel == numerator )-        break;--      // don't do any extra work, clamp last pixel at numerator too-      if ( out_last_pixel >= numerator )-        out_last_pixel = numerator - 1;-    }--    for (i = 0; i <= out_last_pixel - out_first_pixel; i++)-    {-      float out_pixel_center = (float)(i + out_first_pixel) + 0.5f;-      float x = out_pixel_center - out_center_of_in;-      float coeff = kernel(x, scale, user_data) * scale;--      // kill the coeff if it's too small (avoid denormals)-      if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) )-        coeff = 0.0f;--      {-        int out = i + out_first_pixel;-        float * coeffs = coefficient_group + out * coefficient_width;-        stbir__contributors * contribs = contributors + out;--        // is this the first time this output pixel has been seen?  Init it.-        if ( out > first_out_inited ) -        {-          STBIR_ASSERT( out == ( first_out_inited + 1 ) ); // ensure we have only advanced one at time-          first_out_inited = out;-          contribs->n0 = in_pixel;-          contribs->n1 = in_pixel;-          coeffs[0]  = coeff;-        }-        else -        {-          // insert on end (always in order)-          if ( coeffs[0] == 0.0f )  // if the first coefficent is zero, then zap it for this coeffs-          {-            STBIR_ASSERT( ( in_pixel - contribs->n0 ) == 1 ); // ensure that when we zap, we're at the 2nd pos-            contribs->n0 = in_pixel;-          }-          contribs->n1 = in_pixel;-          STBIR_ASSERT( ( in_pixel - contribs->n0 ) < coefficient_width );-          coeffs[in_pixel - contribs->n0]  = coeff;-        }-      }-    }-  }-}--static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter_extent_info* filter_info, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float * coefficient_group, int coefficient_width )-{-  int input_size = scale_info->input_full_size;-  int input_last_n1 = input_size - 1; -  int n, end;-  int lowest = 0x7fffffff;-  int highest = -0x7fffffff;-  int widest = -1;-  int numerator = scale_info->scale_numerator;-  int denominator = scale_info->scale_denominator;-  int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < num_contributors ) );-  float * coeffs;-  stbir__contributors * contribs;--  // weight all the coeffs for each sample-  coeffs = coefficient_group;-  contribs = contributors;-  end = num_contributors; if ( polyphase ) end = numerator;-  for (n = 0; n < end; n++)-  {-    int i;-    float filter_scale, total_filter = 0;-    int e;--    // add all contribs-    e = contribs->n1 - contribs->n0;-    for( i = 0 ; i <= e ; i++ )-    {-      total_filter += coeffs[i];-      STBIR_ASSERT( ( coeffs[i] >= -2.0f ) && ( coeffs[i] <= 2.0f )  ); // check for wonky weights-    }--    // rescale-    if ( ( total_filter < stbir__small_float ) && ( total_filter > -stbir__small_float ) )-    {-      // all coeffs are extremely small, just zero it-      contribs->n1 = contribs->n0;-      coeffs[0] = 0.0f;-    }-    else-    {-      // if the total isn't 1.0, rescale everything-      if ( ( total_filter < (1.0f-stbir__small_float) ) || ( total_filter > (1.0f+stbir__small_float) ) )-      {-        filter_scale = 1.0f / total_filter;-        // scale them all-        for (i = 0; i <= e; i++)-          coeffs[i] *= filter_scale;-      }-    }-    ++contribs;-    coeffs += coefficient_width;-  }--  // if we have a rational for the scale, we can exploit the polyphaseness to not calculate-  //   most of the coefficients, so we copy them here-  if ( polyphase )-  {-    stbir__contributors * prev_contribs = contributors;-    stbir__contributors * cur_contribs = contributors + numerator;--    for( n = numerator ; n < num_contributors ; n++ )-    {-      cur_contribs->n0 = prev_contribs->n0 + denominator;-      cur_contribs->n1 = prev_contribs->n1 + denominator;-      ++cur_contribs;-      ++prev_contribs;-    }-    stbir_overlapping_memcpy( coefficient_group + numerator * coefficient_width, coefficient_group, ( num_contributors - numerator ) * coefficient_width * sizeof( coeffs[ 0 ] ) );-  }--  coeffs = coefficient_group;-  contribs = contributors;-  for (n = 0; n < num_contributors; n++)-  {-    int i;--    // in zero edge mode, just remove out of bounds contribs completely (since their weights are accounted for now)-    if ( edge == STBIR_EDGE_ZERO )-    {-      // shrink the right side if necessary-      if ( contribs->n1 > input_last_n1 )-        contribs->n1 = input_last_n1;--      // shrink the left side-      if ( contribs->n0 < 0 )-      {-        int j, left, skips = 0;--        skips = -contribs->n0;-        contribs->n0 = 0;--        // now move down the weights-        left = contribs->n1 - contribs->n0 + 1;-        if ( left > 0 )-        {-          for( j = 0 ; j < left ; j++ )-            coeffs[ j ] = coeffs[ j + skips ];-        }-      }-    }-    else if ( ( edge == STBIR_EDGE_CLAMP ) || ( edge == STBIR_EDGE_REFLECT ) )-    {-      // for clamp and reflect, calculate the true inbounds position (based on edge type) and just add that to the existing weight-      -      // right hand side first-      if ( contribs->n1 > input_last_n1 )-      {-        int start = contribs->n0;-        int endi = contribs->n1;-        contribs->n1 = input_last_n1;  -        for( i = input_size; i <= endi; i++ )-          stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), coeffs[i-start] );-      }--      // now check left hand edge-      if ( contribs->n0 < 0 )-      {-        int save_n0;-        float save_n0_coeff;-        float * c = coeffs - ( contribs->n0 + 1 );-        -        // reinsert the coeffs with it reflected or clamped (insert accumulates, if the coeffs exist)-        for( i = -1 ; i > contribs->n0 ; i-- ) -          stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), *c-- );-        save_n0 = contribs->n0;-        save_n0_coeff = c[0]; // save it, since we didn't do the final one (i==n0), because there might be too many coeffs to hold (before we resize)!--        // now slide all the coeffs down (since we have accumulated them in the positive contribs) and reset the first contrib-        contribs->n0 = 0;  -        for(i = 0 ; i <= contribs->n1 ; i++ )-          coeffs[i] = coeffs[i-save_n0];-        -        // now that we have shrunk down the contribs, we insert the first one safely-        stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( save_n0, input_size ), save_n0_coeff );-      }-    }--    if ( contribs->n0 <= contribs->n1 )-    {-      int diff = contribs->n1 - contribs->n0 + 1;-      while ( diff && ( coeffs[ diff-1 ] == 0.0f ) )-        --diff;-      contribs->n1 = contribs->n0 + diff - 1;--      if ( contribs->n0 <= contribs->n1 )-      {-        if ( contribs->n0 < lowest )-          lowest = contribs->n0;-        if ( contribs->n1 > highest )-          highest = contribs->n1;-        if ( diff > widest )-          widest = diff;-      }--      // re-zero out unused coefficients (if any)-      for( i = diff ; i < coefficient_width ; i++ )-        coeffs[i] = 0.0f;-    }--    ++contribs;-    coeffs += coefficient_width;-  }-  filter_info->lowest = lowest;-  filter_info->highest = highest;-  filter_info->widest = widest;-}--static int stbir__pack_coefficients( int num_contributors, stbir__contributors* contributors, float * coefficents, int coefficient_width, int widest, int row_width )-{-  #define STBIR_MOVE_1( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint32*)(dest))[0] = ((stbir_uint32*)(src))[0]; }-  #define STBIR_MOVE_2( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; }-  #ifdef STBIR_SIMD-  #define STBIR_MOVE_4( dest, src ) { stbir__simdf t; STBIR_NO_UNROLL(dest); stbir__simdf_load( t, src ); stbir__simdf_store( dest, t ); }-  #else-  #define STBIR_MOVE_4( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; ((stbir_uint64*)(dest))[1] = ((stbir_uint64*)(src))[1]; }-  #endif-  if ( coefficient_width != widest )-  {-    float * pc = coefficents;-    float * coeffs = coefficents;-    float * pc_end = coefficents + num_contributors * widest;-    switch( widest )-    {-      case 1:-        do {-          STBIR_MOVE_1( pc, coeffs );-          ++pc;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 2:-        do {-          STBIR_MOVE_2( pc, coeffs );-          pc += 2;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 3:-        do {-          STBIR_MOVE_2( pc, coeffs );-          STBIR_MOVE_1( pc+2, coeffs+2 );-          pc += 3;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 4:-        do {-          STBIR_MOVE_4( pc, coeffs );-          pc += 4;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 5:-        do {-          STBIR_MOVE_4( pc, coeffs );-          STBIR_MOVE_1( pc+4, coeffs+4 );-          pc += 5;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 6:-        do {-          STBIR_MOVE_4( pc, coeffs );-          STBIR_MOVE_2( pc+4, coeffs+4 );-          pc += 6;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 7:-        do {-          STBIR_MOVE_4( pc, coeffs );-          STBIR_MOVE_2( pc+4, coeffs+4 );-          STBIR_MOVE_1( pc+6, coeffs+6 );-          pc += 7;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 8:-        do {-          STBIR_MOVE_4( pc, coeffs );-          STBIR_MOVE_4( pc+4, coeffs+4 );-          pc += 8;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 9:-        do {-          STBIR_MOVE_4( pc, coeffs );-          STBIR_MOVE_4( pc+4, coeffs+4 );-          STBIR_MOVE_1( pc+8, coeffs+8 );-          pc += 9;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 10:-        do {-          STBIR_MOVE_4( pc, coeffs );-          STBIR_MOVE_4( pc+4, coeffs+4 );-          STBIR_MOVE_2( pc+8, coeffs+8 );-          pc += 10;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 11:-        do {-          STBIR_MOVE_4( pc, coeffs );-          STBIR_MOVE_4( pc+4, coeffs+4 );-          STBIR_MOVE_2( pc+8, coeffs+8 );-          STBIR_MOVE_1( pc+10, coeffs+10 );-          pc += 11;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      case 12:-        do {-          STBIR_MOVE_4( pc, coeffs );-          STBIR_MOVE_4( pc+4, coeffs+4 );-          STBIR_MOVE_4( pc+8, coeffs+8 );-          pc += 12;-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-      default:-        do {-          float * copy_end = pc + widest - 4;-          float * c = coeffs;-          do {-            STBIR_NO_UNROLL( pc );-            STBIR_MOVE_4( pc, c );-            pc += 4;-            c += 4;-          } while ( pc <= copy_end );-          copy_end += 4;-          while ( pc < copy_end )-          {-            STBIR_MOVE_1( pc, c );-            ++pc; ++c;-          }-          coeffs += coefficient_width;-        } while ( pc < pc_end );-        break;-    }-  }--  // some horizontal routines read one float off the end (which is then masked off), so put in a sentinal so we don't read an snan or denormal-  coefficents[ widest * num_contributors ] = 8888.0f;--  // the minimum we might read for unrolled filters widths is 12. So, we need to-  //   make sure we never read outside the decode buffer, by possibly moving -  //   the sample area back into the scanline, and putting zeros weights first.-  // we start on the right edge and check until we're well past the possible-  //   clip area (2*widest).-  {-    stbir__contributors * contribs = contributors + num_contributors - 1;-    float * coeffs = coefficents + widest * ( num_contributors - 1 );--    // go until no chance of clipping (this is usually less than 8 lops)-    while ( ( ( contribs->n0 + widest*2 ) >= row_width ) && ( contribs >= contributors ) )-    {-      // might we clip??-      if ( ( contribs->n0 + widest ) > row_width )-      {-        int stop_range = widest;-      -        // if range is larger than 12, it will be handled by generic loops that can terminate on the exact length-        //   of this contrib n1, instead of a fixed widest amount - so calculate this-        if ( widest > 12 )-        {-          int mod;--          // how far will be read in the n_coeff loop (which depends on the widest count mod4);-          mod = widest & 3;-          stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; --          // the n_coeff loops do a minimum amount of coeffs, so factor that in!-          if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod;-        }--        // now see if we still clip with the refined range-        if ( ( contribs->n0 + stop_range ) > row_width )-        {-          int new_n0 = row_width - stop_range;-          int num = contribs->n1 - contribs->n0 + 1;-          int backup = contribs->n0 - new_n0;-          float * from_co = coeffs + num - 1;-          float * to_co = from_co + backup;--          STBIR_ASSERT( ( new_n0 >= 0 ) && ( new_n0 < contribs->n0 ) );--          // move the coeffs over-          while( num )-          {-            *to_co-- = *from_co--;-            --num;-          }-          // zero new positions-          while ( to_co >= coeffs )-            *to_co-- = 0;-          // set new start point-          contribs->n0 = new_n0;-          if ( widest > 12 )-          {-            int mod;--            // how far will be read in the n_coeff loop (which depends on the widest count mod4);-            mod = widest & 3;-            stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; --            // the n_coeff loops do a minimum amount of coeffs, so factor that in!-            if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod;-          }-        }-      }-      --contribs;-      coeffs -= widest;-    }-  }--  return widest;-  #undef STBIR_MOVE_1-  #undef STBIR_MOVE_2-  #undef STBIR_MOVE_4-}--static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * other_axis_for_pivot, void * user_data STBIR_ONLY_PROFILE_BUILD_GET_INFO )-{-  int n;-  float scale = samp->scale_info.scale;-  stbir__kernel_callback * kernel = samp->filter_kernel;-  stbir__support_callback * support = samp->filter_support;-  float inv_scale = samp->scale_info.inv_scale;-  int input_full_size = samp->scale_info.input_full_size;-  int gather_num_contributors = samp->num_contributors;-  stbir__contributors* gather_contributors = samp->contributors;-  float * gather_coeffs = samp->coefficients; -  int gather_coefficient_width = samp->coefficient_width;--  switch ( samp->is_gather )-  {-    case 1: // gather upsample-    {-      float out_pixels_radius = support(inv_scale,user_data) * scale;--      stbir__calculate_coefficients_for_gather_upsample( out_pixels_radius, kernel, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width, samp->edge, user_data );--      STBIR_PROFILE_BUILD_START( cleanup );-      stbir__cleanup_gathered_coefficients( samp->edge, &samp->extent_info, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width );-      STBIR_PROFILE_BUILD_END( cleanup );-    }-    break;--    case 0: // scatter downsample (only on vertical)-    case 2: // gather downsample  -    {-      float in_pixels_radius = support(scale,user_data) * inv_scale;-      int filter_pixel_margin = samp->filter_pixel_margin;-      int input_end = input_full_size + filter_pixel_margin;-      -      // if this is a scatter, we do a downsample gather to get the coeffs, and then pivot after-      if ( !samp->is_gather )-      {-        // check if we are using the same gather downsample on the horizontal as this vertical, -        //   if so, then we don't have to generate them, we can just pivot from the horizontal.-        if ( other_axis_for_pivot )-        {-          gather_contributors = other_axis_for_pivot->contributors;-          gather_coeffs = other_axis_for_pivot->coefficients;-          gather_coefficient_width = other_axis_for_pivot->coefficient_width;-          gather_num_contributors = other_axis_for_pivot->num_contributors;-          samp->extent_info.lowest = other_axis_for_pivot->extent_info.lowest;-          samp->extent_info.highest = other_axis_for_pivot->extent_info.highest;-          samp->extent_info.widest = other_axis_for_pivot->extent_info.widest;-          goto jump_right_to_pivot;-        }--        gather_contributors = samp->gather_prescatter_contributors;-        gather_coeffs = samp->gather_prescatter_coefficients;-        gather_coefficient_width = samp->gather_prescatter_coefficient_width;-        gather_num_contributors = samp->gather_prescatter_num_contributors;-      }--      stbir__calculate_coefficients_for_gather_downsample( -filter_pixel_margin, input_end, in_pixels_radius, kernel, &samp->scale_info, gather_coefficient_width, gather_num_contributors, gather_contributors, gather_coeffs, user_data );--      STBIR_PROFILE_BUILD_START( cleanup );-      stbir__cleanup_gathered_coefficients( samp->edge, &samp->extent_info, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width );-      STBIR_PROFILE_BUILD_END( cleanup );--      if ( !samp->is_gather )-      {-        // if this is a scatter (vertical only), then we need to pivot the coeffs-        stbir__contributors * scatter_contributors;-        int highest_set;--        jump_right_to_pivot:--        STBIR_PROFILE_BUILD_START( pivot );--        highest_set = (-filter_pixel_margin) - 1;-        for (n = 0; n < gather_num_contributors; n++)-        {-          int k;-          int gn0 = gather_contributors->n0, gn1 = gather_contributors->n1;-          int scatter_coefficient_width = samp->coefficient_width;-          float * scatter_coeffs = samp->coefficients + ( gn0 + filter_pixel_margin ) * scatter_coefficient_width;-          float * g_coeffs = gather_coeffs;-          scatter_contributors = samp->contributors + ( gn0 + filter_pixel_margin );-          -          for (k = gn0 ; k <= gn1 ; k++ )-          {-            float gc = *g_coeffs++;-            if ( ( k > highest_set ) || ( scatter_contributors->n0 > scatter_contributors->n1 ) )-            {-              {-                // if we are skipping over several contributors, we need to clear the skipped ones-                stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1);-                while ( clear_contributors < scatter_contributors )-                {-                  clear_contributors->n0 = 0; -                  clear_contributors->n1 = -1;-                  ++clear_contributors;-                }-              }-              scatter_contributors->n0 = n;-              scatter_contributors->n1 = n;-              scatter_coeffs[0]  = gc;-              highest_set = k;-            }-            else-            {-              stbir__insert_coeff( scatter_contributors, scatter_coeffs, n, gc );-            }-            ++scatter_contributors;-            scatter_coeffs += scatter_coefficient_width;-          }--          ++gather_contributors;-          gather_coeffs += gather_coefficient_width;-        }--        // now clear any unset contribs-        {-          stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1);-          stbir__contributors * end_contributors = samp->contributors + samp->num_contributors;-          while ( clear_contributors < end_contributors )-          {-            clear_contributors->n0 = 0;-            clear_contributors->n1 = -1;-            ++clear_contributors;-          }-        }--        STBIR_PROFILE_BUILD_END( pivot );-      }-    }-    break;-  }-}---//========================================================================================================-// scanline decoders and encoders--#define stbir__coder_min_num 1-#define STB_IMAGE_RESIZE_DO_CODERS-#include STBIR__HEADER_FILENAME--#define stbir__decode_suffix BGRA-#define stbir__decode_swizzle-#define stbir__decode_order0  2 -#define stbir__decode_order1  1-#define stbir__decode_order2  0-#define stbir__decode_order3  3-#define stbir__encode_order0  2 -#define stbir__encode_order1  1-#define stbir__encode_order2  0-#define stbir__encode_order3  3-#define stbir__coder_min_num 4-#define STB_IMAGE_RESIZE_DO_CODERS-#include STBIR__HEADER_FILENAME--#define stbir__decode_suffix ARGB-#define stbir__decode_swizzle-#define stbir__decode_order0  1 -#define stbir__decode_order1  2-#define stbir__decode_order2  3-#define stbir__decode_order3  0-#define stbir__encode_order0  3 -#define stbir__encode_order1  0-#define stbir__encode_order2  1-#define stbir__encode_order3  2-#define stbir__coder_min_num 4-#define STB_IMAGE_RESIZE_DO_CODERS-#include STBIR__HEADER_FILENAME--#define stbir__decode_suffix ABGR-#define stbir__decode_swizzle-#define stbir__decode_order0  3 -#define stbir__decode_order1  2-#define stbir__decode_order2  1-#define stbir__decode_order3  0-#define stbir__encode_order0  3 -#define stbir__encode_order1  2-#define stbir__encode_order2  1-#define stbir__encode_order3  0-#define stbir__coder_min_num 4-#define STB_IMAGE_RESIZE_DO_CODERS-#include STBIR__HEADER_FILENAME--#define stbir__decode_suffix AR-#define stbir__decode_swizzle-#define stbir__decode_order0  1 -#define stbir__decode_order1  0 -#define stbir__decode_order2  3-#define stbir__decode_order3  2-#define stbir__encode_order0  1 -#define stbir__encode_order1  0 -#define stbir__encode_order2  3-#define stbir__encode_order3  2-#define stbir__coder_min_num 2-#define STB_IMAGE_RESIZE_DO_CODERS-#include STBIR__HEADER_FILENAME---// fancy alpha means we expand to keep both premultipied and non-premultiplied color channels-static void stbir__fancy_alpha_weight_4ch( float * out_buffer, int width_times_channels )-{-  float STBIR_STREAMOUT_PTR(*) out = out_buffer;-  float const * end_decode = out_buffer + ( width_times_channels / 4 ) * 7;  // decode buffer aligned to end of out_buffer-  float STBIR_STREAMOUT_PTR(*) decode = (float*)end_decode - width_times_channels;--  // fancy alpha is stored internally as R G B A Rpm Gpm Bpm--  #ifdef STBIR_SIMD-  -  #ifdef STBIR_SIMD8-  decode += 16;-  while ( decode <= end_decode )-  {-    stbir__simdf8 d0,d1,a0,a1,p0,p1;-    STBIR_NO_UNROLL(decode);-    stbir__simdf8_load( d0, decode-16 );-    stbir__simdf8_load( d1, decode-16+8 );-    stbir__simdf8_0123to33333333( a0, d0 );-    stbir__simdf8_0123to33333333( a1, d1 );-    stbir__simdf8_mult( p0, a0, d0 );-    stbir__simdf8_mult( p1, a1, d1 );-    stbir__simdf8_bot4s( a0, d0, p0 );-    stbir__simdf8_bot4s( a1, d1, p1 );-    stbir__simdf8_top4s( d0, d0, p0 );-    stbir__simdf8_top4s( d1, d1, p1 );-    stbir__simdf8_store ( out, a0 );-    stbir__simdf8_store ( out+7, d0 );-    stbir__simdf8_store ( out+14, a1 );-    stbir__simdf8_store ( out+21, d1 );-    decode += 16;-    out += 28;-  }-  decode -= 16;-  #else  -  decode += 8;-  while ( decode <= end_decode )-  {-    stbir__simdf d0,a0,d1,a1,p0,p1;-    STBIR_NO_UNROLL(decode);-    stbir__simdf_load( d0, decode-8 );-    stbir__simdf_load( d1, decode-8+4 );-    stbir__simdf_0123to3333( a0, d0 );-    stbir__simdf_0123to3333( a1, d1 );-    stbir__simdf_mult( p0, a0, d0 );-    stbir__simdf_mult( p1, a1, d1 );-    stbir__simdf_store ( out, d0 );-    stbir__simdf_store ( out+4, p0 );-    stbir__simdf_store ( out+7, d1 );-    stbir__simdf_store ( out+7+4, p1 );-    decode += 8;-    out += 14;-  }-  decode -= 8;-  #endif--  // might be one last odd pixel-  #ifdef STBIR_SIMD8-  while ( decode < end_decode )-  #else-  if ( decode < end_decode )-  #endif-  {-    stbir__simdf d,a,p;-    stbir__simdf_load( d, decode );-    stbir__simdf_0123to3333( a, d );-    stbir__simdf_mult( p, a, d );-    stbir__simdf_store ( out, d );-    stbir__simdf_store ( out+4, p );-    decode += 4;-    out += 7;-  }--  #else--  while( decode < end_decode )-  {-    float r = decode[0], g = decode[1], b = decode[2], alpha = decode[3];-    out[0] = r;-    out[1] = g;-    out[2] = b;-    out[3] = alpha;-    out[4] = r * alpha;-    out[5] = g * alpha;-    out[6] = b * alpha;-    out += 7;-    decode += 4;-  }--  #endif-}--static void stbir__fancy_alpha_weight_2ch( float * out_buffer, int width_times_channels )-{-  float STBIR_STREAMOUT_PTR(*) out = out_buffer;-  float const * end_decode = out_buffer + ( width_times_channels / 2 ) * 3;-  float STBIR_STREAMOUT_PTR(*) decode = (float*)end_decode - width_times_channels;--  //  for fancy alpha, turns into: [X A Xpm][X A Xpm],etc--  #ifdef STBIR_SIMD--  decode += 8;-  if ( decode <= end_decode )-  {-    do {-      #ifdef STBIR_SIMD8-      stbir__simdf8 d0,a0,p0;-      STBIR_NO_UNROLL(decode);-      stbir__simdf8_load( d0, decode-8 );-      stbir__simdf8_0123to11331133( p0, d0 );-      stbir__simdf8_0123to00220022( a0, d0 );-      stbir__simdf8_mult( p0, p0, a0 );- -      stbir__simdf_store2( out, stbir__if_simdf8_cast_to_simdf4( d0 ) );-      stbir__simdf_store( out+2, stbir__if_simdf8_cast_to_simdf4( p0 ) );-      stbir__simdf_store2h( out+3, stbir__if_simdf8_cast_to_simdf4( d0 ) );-      -      stbir__simdf_store2( out+6, stbir__simdf8_gettop4( d0 ) );-      stbir__simdf_store( out+8, stbir__simdf8_gettop4( p0 ) );-      stbir__simdf_store2h( out+9, stbir__simdf8_gettop4( d0 ) );-      #else-      stbir__simdf d0,a0,d1,a1,p0,p1;-      STBIR_NO_UNROLL(decode);-      stbir__simdf_load( d0, decode-8 );-      stbir__simdf_load( d1, decode-8+4 );-      stbir__simdf_0123to1133( p0, d0 );-      stbir__simdf_0123to1133( p1, d1 );-      stbir__simdf_0123to0022( a0, d0 );-      stbir__simdf_0123to0022( a1, d1 );-      stbir__simdf_mult( p0, p0, a0 );-      stbir__simdf_mult( p1, p1, a1 );--      stbir__simdf_store2( out, d0 );-      stbir__simdf_store( out+2, p0 );-      stbir__simdf_store2h( out+3, d0 );--      stbir__simdf_store2( out+6, d1 );-      stbir__simdf_store( out+8, p1 );-      stbir__simdf_store2h( out+9, d1 );-      #endif-      decode += 8;-      out += 12;-    } while ( decode <= end_decode );-  }-  decode -= 8;-  #endif--  while( decode < end_decode )-  {-    float x = decode[0], y = decode[1];-    STBIR_SIMD_NO_UNROLL(decode);-    out[0] = x;-    out[1] = y;-    out[2] = x * y;-    out += 3;-    decode += 2;-  }-}--static void stbir__fancy_alpha_unweight_4ch( float * encode_buffer, int width_times_channels )-{-  float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer;-  float STBIR_SIMD_STREAMOUT_PTR(*) input = encode_buffer;-  float const * end_output = encode_buffer + width_times_channels;--  // fancy RGBA is stored internally as R G B A Rpm Gpm Bpm--  do {-    float alpha = input[3];-#ifdef STBIR_SIMD-    stbir__simdf i,ia;-    STBIR_SIMD_NO_UNROLL(encode);-    if ( alpha < stbir__small_float )-    {-      stbir__simdf_load( i, input );-      stbir__simdf_store( encode, i );-    }-    else-    {-      stbir__simdf_load1frep4( ia, 1.0f / alpha );-      stbir__simdf_load( i, input+4 );-      stbir__simdf_mult( i, i, ia );-      stbir__simdf_store( encode, i );-      encode[3] = alpha;-    }-#else-    if ( alpha < stbir__small_float )-    {-      encode[0] = input[0];-      encode[1] = input[1];-      encode[2] = input[2];-    }-    else-    {-      float ialpha = 1.0f / alpha;-      encode[0] = input[4] * ialpha;-      encode[1] = input[5] * ialpha;-      encode[2] = input[6] * ialpha;-    }-    encode[3] = alpha;-#endif--    input += 7;-    encode += 4;-  } while ( encode < end_output );-}--//  format: [X A Xpm][X A Xpm] etc-static void stbir__fancy_alpha_unweight_2ch( float * encode_buffer, int width_times_channels )-{-  float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer;-  float STBIR_SIMD_STREAMOUT_PTR(*) input = encode_buffer;-  float const * end_output = encode_buffer + width_times_channels;--  do {-    float alpha = input[1];-    encode[0] = input[0];-    if ( alpha >= stbir__small_float )-      encode[0] = input[2] / alpha;-    encode[1] = alpha;--    input += 3;-    encode += 2;-  } while ( encode < end_output );-}--static void stbir__simple_alpha_weight_4ch( float * decode_buffer, int width_times_channels )-{-  float STBIR_STREAMOUT_PTR(*) decode = decode_buffer;-  float const * end_decode = decode_buffer + width_times_channels;--  #ifdef STBIR_SIMD-  {-    decode += 2 * stbir__simdfX_float_count;-    while ( decode <= end_decode )-    {-      stbir__simdfX d0,a0,d1,a1;-      STBIR_NO_UNROLL(decode);-      stbir__simdfX_load( d0, decode-2*stbir__simdfX_float_count );-      stbir__simdfX_load( d1, decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count );-      stbir__simdfX_aaa1( a0, d0, STBIR_onesX );-      stbir__simdfX_aaa1( a1, d1, STBIR_onesX );-      stbir__simdfX_mult( d0, d0, a0 );-      stbir__simdfX_mult( d1, d1, a1 );-      stbir__simdfX_store ( decode-2*stbir__simdfX_float_count, d0 );-      stbir__simdfX_store ( decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count, d1 );-      decode += 2 * stbir__simdfX_float_count;-    }-    decode -= 2 * stbir__simdfX_float_count;--    // few last pixels remnants-    #ifdef STBIR_SIMD8-    while ( decode < end_decode )-    #else-    if ( decode < end_decode )-    #endif-    {-      stbir__simdf d,a;-      stbir__simdf_load( d, decode );-      stbir__simdf_aaa1( a, d, STBIR__CONSTF(STBIR_ones) );-      stbir__simdf_mult( d, d, a );-      stbir__simdf_store ( decode, d );-      decode += 4;-    }-  }--  #else--  while( decode < end_decode )-  {-    float alpha = decode[3];-    decode[0] *= alpha;-    decode[1] *= alpha;-    decode[2] *= alpha;-    decode += 4;-  }--  #endif-}--static void stbir__simple_alpha_weight_2ch( float * decode_buffer, int width_times_channels )-{-  float STBIR_STREAMOUT_PTR(*) decode = decode_buffer;-  float const * end_decode = decode_buffer + width_times_channels;--  #ifdef STBIR_SIMD-  decode += 2 * stbir__simdfX_float_count;-  while ( decode <= end_decode )-  {-    stbir__simdfX d0,a0,d1,a1;-    STBIR_NO_UNROLL(decode);-    stbir__simdfX_load( d0, decode-2*stbir__simdfX_float_count );-    stbir__simdfX_load( d1, decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count );-    stbir__simdfX_a1a1( a0, d0, STBIR_onesX );-    stbir__simdfX_a1a1( a1, d1, STBIR_onesX );-    stbir__simdfX_mult( d0, d0, a0 );-    stbir__simdfX_mult( d1, d1, a1 );-    stbir__simdfX_store ( decode-2*stbir__simdfX_float_count, d0 );-    stbir__simdfX_store ( decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count, d1 );-    decode += 2 * stbir__simdfX_float_count;-  }-  decode -= 2 * stbir__simdfX_float_count;-  #endif--  while( decode < end_decode )-  {-    float alpha = decode[1];-    STBIR_SIMD_NO_UNROLL(decode);-    decode[0] *= alpha;-    decode += 2;-  }-}--static void stbir__simple_alpha_unweight_4ch( float * encode_buffer, int width_times_channels )-{-  float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer;-  float const * end_output = encode_buffer + width_times_channels;--  do {-    float alpha = encode[3];--#ifdef STBIR_SIMD-    stbir__simdf i,ia;-    STBIR_SIMD_NO_UNROLL(encode);-    if ( alpha >= stbir__small_float )-    {-      stbir__simdf_load1frep4( ia, 1.0f / alpha );-      stbir__simdf_load( i, encode );-      stbir__simdf_mult( i, i, ia );-      stbir__simdf_store( encode, i );-      encode[3] = alpha;-    }-#else-    if ( alpha >= stbir__small_float )-    {-      float ialpha = 1.0f / alpha;-      encode[0] *= ialpha;-      encode[1] *= ialpha;-      encode[2] *= ialpha;-    }-#endif-    encode += 4;-  } while ( encode < end_output );-}--static void stbir__simple_alpha_unweight_2ch( float * encode_buffer, int width_times_channels )-{-  float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer;-  float const * end_output = encode_buffer + width_times_channels;--  do {-    float alpha = encode[1];-    if ( alpha >= stbir__small_float )-      encode[0] /= alpha;-    encode += 2;-  } while ( encode < end_output );-}---// only used in RGB->BGR or BGR->RGB-static void stbir__simple_flip_3ch( float * decode_buffer, int width_times_channels )-{-  float STBIR_STREAMOUT_PTR(*) decode = decode_buffer;-  float const * end_decode = decode_buffer + width_times_channels;--  decode += 12;-  while( decode <= end_decode )-  {-    float t0,t1,t2,t3;-    STBIR_NO_UNROLL(decode);-    t0 = decode[0]; t1 = decode[3]; t2 = decode[6]; t3 = decode[9];-    decode[0] = decode[2]; decode[3] = decode[5]; decode[6] = decode[8]; decode[9] = decode[11];-    decode[2] = t0; decode[5] = t1; decode[8] = t2; decode[11] = t3;-    decode += 12;-  }-  decode -= 12;--  while( decode < end_decode )-  {-    float t = decode[0];-    STBIR_NO_UNROLL(decode);-    decode[0] = decode[2];-    decode[2] = t;-    decode += 3;-  }-}----static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float * output_buffer STBIR_ONLY_PROFILE_GET_SPLIT_INFO )-{-  int channels = stbir_info->channels;-  int effective_channels = stbir_info->effective_channels;-  int input_sample_in_bytes = stbir__type_size[stbir_info->input_type] * channels;-  stbir_edge edge_horizontal = stbir_info->horizontal.edge;-  stbir_edge edge_vertical = stbir_info->vertical.edge;-  int row = stbir__edge_wrap(edge_vertical, n, stbir_info->vertical.scale_info.input_full_size);-  const void* input_plane_data = ( (char *) stbir_info->input_data ) + (ptrdiff_t)row * (ptrdiff_t) stbir_info->input_stride_bytes;-  stbir__span const * spans = stbir_info->scanline_extents.spans;-  float* full_decode_buffer = output_buffer - stbir_info->scanline_extents.conservative.n0 * effective_channels;--  // if we are on edge_zero, and we get in here with an out of bounds n, then the calculate filters has failed-  STBIR_ASSERT( !(edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->vertical.scale_info.input_full_size)) );--  do -  {-    float * decode_buffer;-    void const * input_data;-    float * end_decode;-    int width_times_channels;-    int width;--    if ( spans->n1 < spans->n0 )    -      break;--    width = spans->n1 + 1 - spans->n0;-    decode_buffer = full_decode_buffer + spans->n0 * effective_channels;-    end_decode = full_decode_buffer + ( spans->n1 + 1 ) * effective_channels;-    width_times_channels = width * channels;--    // read directly out of input plane by default-    input_data = ( (char*)input_plane_data ) + spans->pixel_offset_for_input * input_sample_in_bytes;--    // if we have an input callback, call it to get the input data-    if ( stbir_info->in_pixels_cb )-    {-      // call the callback with a temp buffer (that they can choose to use or not).  the temp is just right aligned memory in the decode_buffer itself-      input_data = stbir_info->in_pixels_cb( ( (char*) end_decode ) - ( width * input_sample_in_bytes ), input_plane_data, width, spans->pixel_offset_for_input, row, stbir_info->user_data );-    }-    -    STBIR_PROFILE_START( decode );-    // convert the pixels info the float decode_buffer, (we index from end_decode, so that when channels<effective_channels, we are right justified in the buffer)-    stbir_info->decode_pixels( (float*)end_decode - width_times_channels, width_times_channels, input_data );-    STBIR_PROFILE_END( decode );--    if (stbir_info->alpha_weight)-    {-      STBIR_PROFILE_START( alpha );-      stbir_info->alpha_weight( decode_buffer, width_times_channels );-      STBIR_PROFILE_END( alpha );-    }--    ++spans;-  } while ( spans <= ( &stbir_info->scanline_extents.spans[1] ) );--  // handle the edge_wrap filter (all other types are handled back out at the calculate_filter stage)-  // basically the idea here is that if we have the whole scanline in memory, we don't redecode the-  //   wrapped edge pixels, and instead just memcpy them from the scanline into the edge positions-  if ( ( edge_horizontal == STBIR_EDGE_WRAP ) && ( stbir_info->scanline_extents.edge_sizes[0] | stbir_info->scanline_extents.edge_sizes[1] ) )-  {-    // this code only runs if we're in edge_wrap, and we're doing the entire scanline-    int e, start_x[2];-    int input_full_size = stbir_info->horizontal.scale_info.input_full_size;-    -    start_x[0] = -stbir_info->scanline_extents.edge_sizes[0];  // left edge start x-    start_x[1] =  input_full_size;                             // right edge--    for( e = 0; e < 2 ; e++ )-    {-      // do each margin-      int margin = stbir_info->scanline_extents.edge_sizes[e];-      if ( margin )-      {-        int x = start_x[e];-        float * marg = full_decode_buffer + x * effective_channels;-        float const * src = full_decode_buffer + stbir__edge_wrap(edge_horizontal, x, input_full_size) * effective_channels;-        STBIR_MEMCPY( marg, src, margin * effective_channels * sizeof(float) );-      }-    }-  }-}---//=================-// Do 1 channel horizontal routines--#ifdef STBIR_SIMD--#define stbir__1_coeff_only()          \-    stbir__simdf tot,c;                \-    STBIR_SIMD_NO_UNROLL(decode);      \-    stbir__simdf_load1( c, hc );       \-    stbir__simdf_mult1_mem( tot, c, decode ); --#define stbir__2_coeff_only()          \-    stbir__simdf tot,c,d;              \-    STBIR_SIMD_NO_UNROLL(decode);      \-    stbir__simdf_load2z( c, hc );      \-    stbir__simdf_load2( d, decode );   \-    stbir__simdf_mult( tot, c, d );    \-    stbir__simdf_0123to1230( c, tot ); \-    stbir__simdf_add1( tot, tot, c );          --#define stbir__3_coeff_only()                  \-    stbir__simdf tot,c,t;                      \-    STBIR_SIMD_NO_UNROLL(decode);              \-    stbir__simdf_load( c, hc );                \-    stbir__simdf_mult_mem( tot, c, decode );   \-    stbir__simdf_0123to1230( c, tot );         \-    stbir__simdf_0123to2301( t, tot );         \-    stbir__simdf_add1( tot, tot, c );          \-    stbir__simdf_add1( tot, tot, t );    --#define stbir__store_output_tiny()                \-    stbir__simdf_store1( output, tot );           \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 1;--#define stbir__4_coeff_start()                 \-    stbir__simdf tot,c;                        \-    STBIR_SIMD_NO_UNROLL(decode);              \-    stbir__simdf_load( c, hc );                \-    stbir__simdf_mult_mem( tot, c, decode );   \--#define stbir__4_coeff_continue_from_4( ofs )  \-    STBIR_SIMD_NO_UNROLL(decode);              \-    stbir__simdf_load( c, hc + (ofs) );        \-    stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) ); --#define stbir__1_coeff_remnant( ofs )          \-    { stbir__simdf d;                          \-    stbir__simdf_load1z( c, hc + (ofs) );      \-    stbir__simdf_load1( d, decode + (ofs) );   \-    stbir__simdf_madd( tot, tot, d, c ); }--#define stbir__2_coeff_remnant( ofs )          \-    { stbir__simdf d;                          \-    stbir__simdf_load2z( c, hc+(ofs) );        \-    stbir__simdf_load2( d, decode+(ofs) );     \-    stbir__simdf_madd( tot, tot, d, c ); }   --#define stbir__3_coeff_setup()                 \-    stbir__simdf mask;                         \-    stbir__simdf_load( mask, STBIR_mask + 3 );--#define stbir__3_coeff_remnant( ofs )                  \-    stbir__simdf_load( c, hc+(ofs) );                  \-    stbir__simdf_and( c, c, mask );                    \-    stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) );--#define stbir__store_output()                     \-    stbir__simdf_0123to2301( c, tot );            \-    stbir__simdf_add( tot, tot, c );              \-    stbir__simdf_0123to1230( c, tot );            \-    stbir__simdf_add1( tot, tot, c );             \-    stbir__simdf_store1( output, tot );           \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 1;--#else--#define stbir__1_coeff_only()  \-    float tot;                 \-    tot = decode[0]*hc[0];     --#define stbir__2_coeff_only()  \-    float tot;                 \-    tot = decode[0] * hc[0];   \-    tot += decode[1] * hc[1];    --#define stbir__3_coeff_only()  \-    float tot;                 \-    tot = decode[0] * hc[0];   \-    tot += decode[1] * hc[1];  \-    tot += decode[2] * hc[2];    --#define stbir__store_output_tiny()                \-    output[0] = tot;                              \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 1;--#define stbir__4_coeff_start()  \-    float tot0,tot1,tot2,tot3;  \-    tot0 = decode[0] * hc[0];   \-    tot1 = decode[1] * hc[1];   \-    tot2 = decode[2] * hc[2];   \-    tot3 = decode[3] * hc[3];     --#define stbir__4_coeff_continue_from_4( ofs )  \-    tot0 += decode[0+(ofs)] * hc[0+(ofs)];     \-    tot1 += decode[1+(ofs)] * hc[1+(ofs)];     \-    tot2 += decode[2+(ofs)] * hc[2+(ofs)];     \-    tot3 += decode[3+(ofs)] * hc[3+(ofs)];     --#define stbir__1_coeff_remnant( ofs )        \-    tot0 += decode[0+(ofs)] * hc[0+(ofs)];   --#define stbir__2_coeff_remnant( ofs )        \-    tot0 += decode[0+(ofs)] * hc[0+(ofs)];   \-    tot1 += decode[1+(ofs)] * hc[1+(ofs)];   \--#define stbir__3_coeff_remnant( ofs )        \-    tot0 += decode[0+(ofs)] * hc[0+(ofs)];   \-    tot1 += decode[1+(ofs)] * hc[1+(ofs)];   \-    tot2 += decode[2+(ofs)] * hc[2+(ofs)];   --#define stbir__store_output()                     \-    output[0] = (tot0+tot2)+(tot1+tot3);          \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 1;--#endif  --#define STBIR__horizontal_channels 1-#define STB_IMAGE_RESIZE_DO_HORIZONTALS-#include STBIR__HEADER_FILENAME---//=================-// Do 2 channel horizontal routines--#ifdef STBIR_SIMD--#define stbir__1_coeff_only()         \-    stbir__simdf tot,c,d;             \-    STBIR_SIMD_NO_UNROLL(decode);     \-    stbir__simdf_load1z( c, hc );     \-    stbir__simdf_0123to0011( c, c );  \-    stbir__simdf_load2( d, decode );  \-    stbir__simdf_mult( tot, d, c ); --#define stbir__2_coeff_only()         \-    stbir__simdf tot,c;               \-    STBIR_SIMD_NO_UNROLL(decode);     \-    stbir__simdf_load2( c, hc );      \-    stbir__simdf_0123to0011( c, c );  \-    stbir__simdf_mult_mem( tot, c, decode ); --#define stbir__3_coeff_only()                \-    stbir__simdf tot,c,cs,d;                 \-    STBIR_SIMD_NO_UNROLL(decode);            \-    stbir__simdf_load( cs, hc );             \-    stbir__simdf_0123to0011( c, cs );        \-    stbir__simdf_mult_mem( tot, c, decode ); \-    stbir__simdf_0123to2222( c, cs );        \-    stbir__simdf_load2z( d, decode+4 );      \-    stbir__simdf_madd( tot, tot, d, c );   --#define stbir__store_output_tiny()                \-    stbir__simdf_0123to2301( c, tot );            \-    stbir__simdf_add( tot, tot, c );              \-    stbir__simdf_store2( output, tot );           \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 2;--#ifdef STBIR_SIMD8--#define stbir__4_coeff_start()                    \-    stbir__simdf8 tot0,c,cs;                      \-    STBIR_SIMD_NO_UNROLL(decode);                 \-    stbir__simdf8_load4b( cs, hc );               \-    stbir__simdf8_0123to00112233( c, cs );        \-    stbir__simdf8_mult_mem( tot0, c, decode );--#define stbir__4_coeff_continue_from_4( ofs )        \-    STBIR_SIMD_NO_UNROLL(decode);                    \-    stbir__simdf8_load4b( cs, hc + (ofs) );          \-    stbir__simdf8_0123to00112233( c, cs );           \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); --#define stbir__1_coeff_remnant( ofs )                \-    { stbir__simdf t;                                \-    stbir__simdf_load1z( t, hc + (ofs) );            \-    stbir__simdf_0123to0011( t, t );                 \-    stbir__simdf_mult_mem( t, t, decode+(ofs)*2 );   \-    stbir__simdf8_add4( tot0, tot0, t ); }--#define stbir__2_coeff_remnant( ofs )                \-    { stbir__simdf t;                                \-    stbir__simdf_load2( t, hc + (ofs) );             \-    stbir__simdf_0123to0011( t, t );                 \-    stbir__simdf_mult_mem( t, t, decode+(ofs)*2 );   \-    stbir__simdf8_add4( tot0, tot0, t ); }--#define stbir__3_coeff_remnant( ofs )                \-    { stbir__simdf8 d;                               \-    stbir__simdf8_load4b( cs, hc + (ofs) );          \-    stbir__simdf8_0123to00112233( c, cs );           \-    stbir__simdf8_load6z( d, decode+(ofs)*2 );       \-    stbir__simdf8_madd( tot0, tot0, c, d ); }               --#define stbir__store_output()                     \-    { stbir__simdf t,c;                           \-    stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 );    \-    stbir__simdf_0123to2301( c, t );              \-    stbir__simdf_add( t, t, c );                  \-    stbir__simdf_store2( output, t );             \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 2; }--#else--#define stbir__4_coeff_start()                   \-    stbir__simdf tot0,tot1,c,cs;                 \-    STBIR_SIMD_NO_UNROLL(decode);                \-    stbir__simdf_load( cs, hc );                 \-    stbir__simdf_0123to0011( c, cs );            \-    stbir__simdf_mult_mem( tot0, c, decode );    \-    stbir__simdf_0123to2233( c, cs );            \-    stbir__simdf_mult_mem( tot1, c, decode+4 );   --#define stbir__4_coeff_continue_from_4( ofs )                \-    STBIR_SIMD_NO_UNROLL(decode);                            \-    stbir__simdf_load( cs, hc + (ofs) );                     \-    stbir__simdf_0123to0011( c, cs );                        \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 );  \-    stbir__simdf_0123to2233( c, cs );                        \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*2+4 );   --#define stbir__1_coeff_remnant( ofs )            \-    { stbir__simdf d;                            \-    stbir__simdf_load1z( cs, hc + (ofs) );       \-    stbir__simdf_0123to0011( c, cs );            \-    stbir__simdf_load2( d, decode + (ofs) * 2 ); \-    stbir__simdf_madd( tot0, tot0, d, c ); }--#define stbir__2_coeff_remnant( ofs )                      \-    stbir__simdf_load2( cs, hc + (ofs) );                  \-    stbir__simdf_0123to0011( c, cs );                      \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 );       --#define stbir__3_coeff_remnant( ofs )                       \-    { stbir__simdf d;                                       \-    stbir__simdf_load( cs, hc + (ofs) );                    \-    stbir__simdf_0123to0011( c, cs );                       \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); \-    stbir__simdf_0123to2222( c, cs );                       \-    stbir__simdf_load2z( d, decode + (ofs) * 2 + 4 );       \-    stbir__simdf_madd( tot1, tot1, d, c ); }  --#define stbir__store_output()                     \-    stbir__simdf_add( tot0, tot0, tot1 );         \-    stbir__simdf_0123to2301( c, tot0 );           \-    stbir__simdf_add( tot0, tot0, c );            \-    stbir__simdf_store2( output, tot0 );          \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 2;--#endif--#else--#define stbir__1_coeff_only()  \-    float tota,totb,c;         \-    c = hc[0];                 \-    tota = decode[0]*c;        \-    totb = decode[1]*c;     --#define stbir__2_coeff_only()  \-    float tota,totb,c;         \-    c = hc[0];                 \-    tota = decode[0]*c;        \-    totb = decode[1]*c;        \-    c = hc[1];                 \-    tota += decode[2]*c;       \-    totb += decode[3]*c;     --// this weird order of add matches the simd-#define stbir__3_coeff_only()  \-    float tota,totb,c;         \-    c = hc[0];                 \-    tota = decode[0]*c;        \-    totb = decode[1]*c;        \-    c = hc[2];                 \-    tota += decode[4]*c;       \-    totb += decode[5]*c;       \-    c = hc[1];                 \-    tota += decode[2]*c;       \-    totb += decode[3]*c;     --#define stbir__store_output_tiny()                \-    output[0] = tota;                             \-    output[1] = totb;                             \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 2;--#define stbir__4_coeff_start()      \-    float tota0,tota1,tota2,tota3,totb0,totb1,totb2,totb3,c;  \-    c = hc[0];                      \-    tota0 = decode[0]*c;            \-    totb0 = decode[1]*c;            \-    c = hc[1];                      \-    tota1 = decode[2]*c;            \-    totb1 = decode[3]*c;            \-    c = hc[2];                      \-    tota2 = decode[4]*c;            \-    totb2 = decode[5]*c;            \-    c = hc[3];                      \-    tota3 = decode[6]*c;            \-    totb3 = decode[7]*c;     --#define stbir__4_coeff_continue_from_4( ofs )  \-    c = hc[0+(ofs)];                           \-    tota0 += decode[0+(ofs)*2]*c;              \-    totb0 += decode[1+(ofs)*2]*c;              \-    c = hc[1+(ofs)];                           \-    tota1 += decode[2+(ofs)*2]*c;              \-    totb1 += decode[3+(ofs)*2]*c;              \-    c = hc[2+(ofs)];                           \-    tota2 += decode[4+(ofs)*2]*c;              \-    totb2 += decode[5+(ofs)*2]*c;              \-    c = hc[3+(ofs)];                           \-    tota3 += decode[6+(ofs)*2]*c;              \-    totb3 += decode[7+(ofs)*2]*c;     --#define stbir__1_coeff_remnant( ofs )  \-    c = hc[0+(ofs)];                   \-    tota0 += decode[0+(ofs)*2] * c;    \-    totb0 += decode[1+(ofs)*2] * c;   --#define stbir__2_coeff_remnant( ofs )  \-    c = hc[0+(ofs)];                   \-    tota0 += decode[0+(ofs)*2] * c;    \-    totb0 += decode[1+(ofs)*2] * c;    \-    c = hc[1+(ofs)];                   \-    tota1 += decode[2+(ofs)*2] * c;    \-    totb1 += decode[3+(ofs)*2] * c;   --#define stbir__3_coeff_remnant( ofs )  \-    c = hc[0+(ofs)];                   \-    tota0 += decode[0+(ofs)*2] * c;    \-    totb0 += decode[1+(ofs)*2] * c;    \-    c = hc[1+(ofs)];                   \-    tota1 += decode[2+(ofs)*2] * c;    \-    totb1 += decode[3+(ofs)*2] * c;    \-    c = hc[2+(ofs)];                   \-    tota2 += decode[4+(ofs)*2] * c;    \-    totb2 += decode[5+(ofs)*2] * c;    --#define stbir__store_output()                     \-    output[0] = (tota0+tota2)+(tota1+tota3);      \-    output[1] = (totb0+totb2)+(totb1+totb3);      \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 2;--#endif  --#define STBIR__horizontal_channels 2-#define STB_IMAGE_RESIZE_DO_HORIZONTALS-#include STBIR__HEADER_FILENAME---//=================-// Do 3 channel horizontal routines--#ifdef STBIR_SIMD--#define stbir__1_coeff_only()         \-    stbir__simdf tot,c,d;             \-    STBIR_SIMD_NO_UNROLL(decode);     \-    stbir__simdf_load1z( c, hc );     \-    stbir__simdf_0123to0001( c, c );  \-    stbir__simdf_load( d, decode );   \-    stbir__simdf_mult( tot, d, c ); --#define stbir__2_coeff_only()         \-    stbir__simdf tot,c,cs,d;          \-    STBIR_SIMD_NO_UNROLL(decode);     \-    stbir__simdf_load2( cs, hc );     \-    stbir__simdf_0123to0000( c, cs ); \-    stbir__simdf_load( d, decode );   \-    stbir__simdf_mult( tot, d, c );   \-    stbir__simdf_0123to1111( c, cs ); \-    stbir__simdf_load( d, decode+3 ); \-    stbir__simdf_madd( tot, tot, d, c ); --#define stbir__3_coeff_only()            \-    stbir__simdf tot,c,d,cs;             \-    STBIR_SIMD_NO_UNROLL(decode);        \-    stbir__simdf_load( cs, hc );         \-    stbir__simdf_0123to0000( c, cs );    \-    stbir__simdf_load( d, decode );      \-    stbir__simdf_mult( tot, d, c );      \-    stbir__simdf_0123to1111( c, cs );    \-    stbir__simdf_load( d, decode+3 );    \-    stbir__simdf_madd( tot, tot, d, c ); \-    stbir__simdf_0123to2222( c, cs );    \-    stbir__simdf_load( d, decode+6 );    \-    stbir__simdf_madd( tot, tot, d, c ); --#define stbir__store_output_tiny()                \-    stbir__simdf_store2( output, tot );           \-    stbir__simdf_0123to2301( tot, tot );          \-    stbir__simdf_store1( output+2, tot );         \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 3;--#ifdef STBIR_SIMD8--// we're loading from the XXXYYY decode by -1 to get the XXXYYY into different halves of the AVX reg fyi-#define stbir__4_coeff_start()                     \-    stbir__simdf8 tot0,tot1,c,cs; stbir__simdf t;  \-    STBIR_SIMD_NO_UNROLL(decode);                  \-    stbir__simdf8_load4b( cs, hc );                \-    stbir__simdf8_0123to00001111( c, cs );         \-    stbir__simdf8_mult_mem( tot0, c, decode - 1 ); \-    stbir__simdf8_0123to22223333( c, cs );         \-    stbir__simdf8_mult_mem( tot1, c, decode+6 - 1 );    --#define stbir__4_coeff_continue_from_4( ofs )      \-    STBIR_SIMD_NO_UNROLL(decode);                  \-    stbir__simdf8_load4b( cs, hc + (ofs) );        \-    stbir__simdf8_0123to00001111( c, cs );         \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \-    stbir__simdf8_0123to22223333( c, cs );         \-    stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*3 + 6 - 1 );    --#define stbir__1_coeff_remnant( ofs )                          \-    STBIR_SIMD_NO_UNROLL(decode);                              \-    stbir__simdf_load1rep4( t, hc + (ofs) );                   \-    stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*3 - 1 ); --#define stbir__2_coeff_remnant( ofs )                          \-    STBIR_SIMD_NO_UNROLL(decode);                              \-    stbir__simdf8_load4b( cs, hc + (ofs) - 2 );                \-    stbir__simdf8_0123to22223333( c, cs );                     \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 );   - - #define stbir__3_coeff_remnant( ofs )                           \-    STBIR_SIMD_NO_UNROLL(decode);                                \-    stbir__simdf8_load4b( cs, hc + (ofs) );                      \-    stbir__simdf8_0123to00001111( c, cs );                       \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \-    stbir__simdf8_0123to2222( t, cs );                           \-    stbir__simdf8_madd_mem4( tot1, tot1, t, decode+(ofs)*3 + 6 - 1 ); --#define stbir__store_output()                       \-    stbir__simdf8_add( tot0, tot0, tot1 );          \-    stbir__simdf_0123to1230( t, stbir__if_simdf8_cast_to_simdf4( tot0 ) ); \-    stbir__simdf8_add4halves( t, t, tot0 );         \-    horizontal_coefficients += coefficient_width;   \-    ++horizontal_contributors;                      \-    output += 3;                                    \-    if ( output < output_end )                      \-    {                                               \-      stbir__simdf_store( output-3, t );            \-      continue;                                     \-    }                                               \-    { stbir__simdf tt; stbir__simdf_0123to2301( tt, t ); \-    stbir__simdf_store2( output-3, t );             \-    stbir__simdf_store1( output+2-3, tt ); }        \-    break;---#else--#define stbir__4_coeff_start()                  \-    stbir__simdf tot0,tot1,tot2,c,cs;           \-    STBIR_SIMD_NO_UNROLL(decode);               \-    stbir__simdf_load( cs, hc );                \-    stbir__simdf_0123to0001( c, cs );           \-    stbir__simdf_mult_mem( tot0, c, decode );   \-    stbir__simdf_0123to1122( c, cs );           \-    stbir__simdf_mult_mem( tot1, c, decode+4 ); \-    stbir__simdf_0123to2333( c, cs );           \-    stbir__simdf_mult_mem( tot2, c, decode+8 ); --#define stbir__4_coeff_continue_from_4( ofs )                 \-    STBIR_SIMD_NO_UNROLL(decode);                             \-    stbir__simdf_load( cs, hc + (ofs) );                      \-    stbir__simdf_0123to0001( c, cs );                         \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 );   \-    stbir__simdf_0123to1122( c, cs );                         \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \-    stbir__simdf_0123to2333( c, cs );                         \-    stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*3+8 );   --#define stbir__1_coeff_remnant( ofs )         \-    STBIR_SIMD_NO_UNROLL(decode);             \-    stbir__simdf_load1z( c, hc + (ofs) );     \-    stbir__simdf_0123to0001( c, c );          \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 );   --#define stbir__2_coeff_remnant( ofs )                       \-    { stbir__simdf d;                                       \-    STBIR_SIMD_NO_UNROLL(decode);                           \-    stbir__simdf_load2z( cs, hc + (ofs) );                  \-    stbir__simdf_0123to0001( c, cs );                       \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \-    stbir__simdf_0123to1122( c, cs );                       \-    stbir__simdf_load2z( d, decode+(ofs)*3+4 );             \-    stbir__simdf_madd( tot1, tot1, c, d ); }                 --#define stbir__3_coeff_remnant( ofs )                         \-    { stbir__simdf d;                                         \-    STBIR_SIMD_NO_UNROLL(decode);                             \-    stbir__simdf_load( cs, hc + (ofs) );                      \-    stbir__simdf_0123to0001( c, cs );                         \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 );   \-    stbir__simdf_0123to1122( c, cs );                         \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \-    stbir__simdf_0123to2222( c, cs );                         \-    stbir__simdf_load1z( d, decode+(ofs)*3+8 );               \-    stbir__simdf_madd( tot2, tot2, c, d );  }                --#define stbir__store_output()                       \-    stbir__simdf_0123ABCDto3ABx( c, tot0, tot1 );   \-    stbir__simdf_0123ABCDto23Ax( cs, tot1, tot2 );  \-    stbir__simdf_0123to1230( tot2, tot2 );          \-    stbir__simdf_add( tot0, tot0, cs );             \-    stbir__simdf_add( c, c, tot2 );                 \-    stbir__simdf_add( tot0, tot0, c );              \-    horizontal_coefficients += coefficient_width;   \-    ++horizontal_contributors;                      \-    output += 3;                                    \-    if ( output < output_end )                      \-    {                                               \-      stbir__simdf_store( output-3, tot0 );         \-      continue;                                     \-    }                                               \-    stbir__simdf_0123to2301( tot1, tot0 );          \-    stbir__simdf_store2( output-3, tot0 );          \-    stbir__simdf_store1( output+2-3, tot1 );        \-    break;--#endif--#else--#define stbir__1_coeff_only()  \-    float tot0, tot1, tot2, c; \-    c = hc[0];                 \-    tot0 = decode[0]*c;        \-    tot1 = decode[1]*c;        \-    tot2 = decode[2]*c;              --#define stbir__2_coeff_only()  \-    float tot0, tot1, tot2, c; \-    c = hc[0];                 \-    tot0 = decode[0]*c;        \-    tot1 = decode[1]*c;        \-    tot2 = decode[2]*c;        \-    c = hc[1];                 \-    tot0 += decode[3]*c;       \-    tot1 += decode[4]*c;       \-    tot2 += decode[5]*c;              --#define stbir__3_coeff_only()  \-    float tot0, tot1, tot2, c; \-    c = hc[0];                 \-    tot0 = decode[0]*c;        \-    tot1 = decode[1]*c;        \-    tot2 = decode[2]*c;        \-    c = hc[1];                 \-    tot0 += decode[3]*c;       \-    tot1 += decode[4]*c;       \-    tot2 += decode[5]*c;       \-    c = hc[2];                 \-    tot0 += decode[6]*c;       \-    tot1 += decode[7]*c;       \-    tot2 += decode[8]*c;              --#define stbir__store_output_tiny()                \-    output[0] = tot0;                             \-    output[1] = tot1;                             \-    output[2] = tot2;                             \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 3;--#define stbir__4_coeff_start()      \-    float tota0,tota1,tota2,totb0,totb1,totb2,totc0,totc1,totc2,totd0,totd1,totd2,c;  \-    c = hc[0];                      \-    tota0 = decode[0]*c;            \-    tota1 = decode[1]*c;            \-    tota2 = decode[2]*c;            \-    c = hc[1];                      \-    totb0 = decode[3]*c;            \-    totb1 = decode[4]*c;            \-    totb2 = decode[5]*c;            \-    c = hc[2];                      \-    totc0 = decode[6]*c;            \-    totc1 = decode[7]*c;            \-    totc2 = decode[8]*c;            \-    c = hc[3];                      \-    totd0 = decode[9]*c;            \-    totd1 = decode[10]*c;           \-    totd2 = decode[11]*c;            --#define stbir__4_coeff_continue_from_4( ofs )  \-    c = hc[0+(ofs)];                           \-    tota0 += decode[0+(ofs)*3]*c;              \-    tota1 += decode[1+(ofs)*3]*c;              \-    tota2 += decode[2+(ofs)*3]*c;              \-    c = hc[1+(ofs)];                           \-    totb0 += decode[3+(ofs)*3]*c;              \-    totb1 += decode[4+(ofs)*3]*c;              \-    totb2 += decode[5+(ofs)*3]*c;              \-    c = hc[2+(ofs)];                           \-    totc0 += decode[6+(ofs)*3]*c;              \-    totc1 += decode[7+(ofs)*3]*c;              \-    totc2 += decode[8+(ofs)*3]*c;              \-    c = hc[3+(ofs)];                           \-    totd0 += decode[9+(ofs)*3]*c;              \-    totd1 += decode[10+(ofs)*3]*c;             \-    totd2 += decode[11+(ofs)*3]*c;              --#define stbir__1_coeff_remnant( ofs )  \-    c = hc[0+(ofs)];                   \-    tota0 += decode[0+(ofs)*3]*c;      \-    tota1 += decode[1+(ofs)*3]*c;      \-    tota2 += decode[2+(ofs)*3]*c;--#define stbir__2_coeff_remnant( ofs )  \-    c = hc[0+(ofs)];                   \-    tota0 += decode[0+(ofs)*3]*c;      \-    tota1 += decode[1+(ofs)*3]*c;      \-    tota2 += decode[2+(ofs)*3]*c;      \-    c = hc[1+(ofs)];                   \-    totb0 += decode[3+(ofs)*3]*c;      \-    totb1 += decode[4+(ofs)*3]*c;      \-    totb2 += decode[5+(ofs)*3]*c;      \--#define stbir__3_coeff_remnant( ofs )  \-    c = hc[0+(ofs)];                   \-    tota0 += decode[0+(ofs)*3]*c;      \-    tota1 += decode[1+(ofs)*3]*c;      \-    tota2 += decode[2+(ofs)*3]*c;      \-    c = hc[1+(ofs)];                   \-    totb0 += decode[3+(ofs)*3]*c;      \-    totb1 += decode[4+(ofs)*3]*c;      \-    totb2 += decode[5+(ofs)*3]*c;      \-    c = hc[2+(ofs)];                   \-    totc0 += decode[6+(ofs)*3]*c;      \-    totc1 += decode[7+(ofs)*3]*c;      \-    totc2 += decode[8+(ofs)*3]*c;              --#define stbir__store_output()                     \-    output[0] = (tota0+totc0)+(totb0+totd0);      \-    output[1] = (tota1+totc1)+(totb1+totd1);      \-    output[2] = (tota2+totc2)+(totb2+totd2);      \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 3;--#endif  --#define STBIR__horizontal_channels 3-#define STB_IMAGE_RESIZE_DO_HORIZONTALS-#include STBIR__HEADER_FILENAME--//=================-// Do 4 channel horizontal routines--#ifdef STBIR_SIMD--#define stbir__1_coeff_only()             \-    stbir__simdf tot,c;                   \-    STBIR_SIMD_NO_UNROLL(decode);         \-    stbir__simdf_load1( c, hc );          \-    stbir__simdf_0123to0000( c, c );      \-    stbir__simdf_mult_mem( tot, c, decode ); --#define stbir__2_coeff_only()                       \-    stbir__simdf tot,c,cs;                          \-    STBIR_SIMD_NO_UNROLL(decode);                   \-    stbir__simdf_load2( cs, hc );                   \-    stbir__simdf_0123to0000( c, cs );               \-    stbir__simdf_mult_mem( tot, c, decode );        \-    stbir__simdf_0123to1111( c, cs );               \-    stbir__simdf_madd_mem( tot, tot, c, decode+4 ); --#define stbir__3_coeff_only()                       \-    stbir__simdf tot,c,cs;                          \-    STBIR_SIMD_NO_UNROLL(decode);                   \-    stbir__simdf_load( cs, hc );                    \-    stbir__simdf_0123to0000( c, cs );               \-    stbir__simdf_mult_mem( tot, c, decode );        \-    stbir__simdf_0123to1111( c, cs );               \-    stbir__simdf_madd_mem( tot, tot, c, decode+4 ); \-    stbir__simdf_0123to2222( c, cs );               \-    stbir__simdf_madd_mem( tot, tot, c, decode+8 ); --#define stbir__store_output_tiny()                \-    stbir__simdf_store( output, tot );            \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 4;--#ifdef STBIR_SIMD8--#define stbir__4_coeff_start()                     \-    stbir__simdf8 tot0,c,cs; stbir__simdf t;  \-    STBIR_SIMD_NO_UNROLL(decode);                  \-    stbir__simdf8_load4b( cs, hc );                \-    stbir__simdf8_0123to00001111( c, cs );         \-    stbir__simdf8_mult_mem( tot0, c, decode );     \-    stbir__simdf8_0123to22223333( c, cs );         \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+8 );    --#define stbir__4_coeff_continue_from_4( ofs )                  \-    STBIR_SIMD_NO_UNROLL(decode);                              \-    stbir__simdf8_load4b( cs, hc + (ofs) );                    \-    stbir__simdf8_0123to00001111( c, cs );                     \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 );   \-    stbir__simdf8_0123to22223333( c, cs );                     \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 );    --#define stbir__1_coeff_remnant( ofs )                          \-    STBIR_SIMD_NO_UNROLL(decode);                              \-    stbir__simdf_load1rep4( t, hc + (ofs) );                   \-    stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4 ); --#define stbir__2_coeff_remnant( ofs )                          \-    STBIR_SIMD_NO_UNROLL(decode);                              \-    stbir__simdf8_load4b( cs, hc + (ofs) - 2 );                \-    stbir__simdf8_0123to22223333( c, cs );                     \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 );   - - #define stbir__3_coeff_remnant( ofs )                         \-    STBIR_SIMD_NO_UNROLL(decode);                              \-    stbir__simdf8_load4b( cs, hc + (ofs) );                    \-    stbir__simdf8_0123to00001111( c, cs );                     \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 );   \-    stbir__simdf8_0123to2222( t, cs );                         \-    stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4+8 ); --#define stbir__store_output()                      \-    stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 );     \-    stbir__simdf_store( output, t );               \-    horizontal_coefficients += coefficient_width;  \-    ++horizontal_contributors;                     \-    output += 4;--#else    --#define stbir__4_coeff_start()                        \-    stbir__simdf tot0,tot1,c,cs;                      \-    STBIR_SIMD_NO_UNROLL(decode);                     \-    stbir__simdf_load( cs, hc );                      \-    stbir__simdf_0123to0000( c, cs );                 \-    stbir__simdf_mult_mem( tot0, c, decode );         \-    stbir__simdf_0123to1111( c, cs );                 \-    stbir__simdf_mult_mem( tot1, c, decode+4 );       \-    stbir__simdf_0123to2222( c, cs );                 \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+8 ); \-    stbir__simdf_0123to3333( c, cs );                 \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+12 ); --#define stbir__4_coeff_continue_from_4( ofs )                  \-    STBIR_SIMD_NO_UNROLL(decode);                              \-    stbir__simdf_load( cs, hc + (ofs) );                       \-    stbir__simdf_0123to0000( c, cs );                          \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 );    \-    stbir__simdf_0123to1111( c, cs );                          \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 );  \-    stbir__simdf_0123to2222( c, cs );                          \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 );  \-    stbir__simdf_0123to3333( c, cs );                          \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+12 ); --#define stbir__1_coeff_remnant( ofs )                       \-    STBIR_SIMD_NO_UNROLL(decode);                           \-    stbir__simdf_load1( c, hc + (ofs) );                    \-    stbir__simdf_0123to0000( c, c );                        \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); --#define stbir__2_coeff_remnant( ofs )                         \-    STBIR_SIMD_NO_UNROLL(decode);                             \-    stbir__simdf_load2( cs, hc + (ofs) );                     \-    stbir__simdf_0123to0000( c, cs );                         \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 );   \-    stbir__simdf_0123to1111( c, cs );                         \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); -  -#define stbir__3_coeff_remnant( ofs )                          \-    STBIR_SIMD_NO_UNROLL(decode);                              \-    stbir__simdf_load( cs, hc + (ofs) );                       \-    stbir__simdf_0123to0000( c, cs );                          \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 );    \-    stbir__simdf_0123to1111( c, cs );                          \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 );  \-    stbir__simdf_0123to2222( c, cs );                          \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 );--#define stbir__store_output()                     \-    stbir__simdf_add( tot0, tot0, tot1 );         \-    stbir__simdf_store( output, tot0 );           \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 4;--#endif--#else--#define stbir__1_coeff_only()         \-    float p0,p1,p2,p3,c;              \-    STBIR_SIMD_NO_UNROLL(decode);     \-    c = hc[0];                        \-    p0 = decode[0] * c;               \-    p1 = decode[1] * c;               \-    p2 = decode[2] * c;               \-    p3 = decode[3] * c;--#define stbir__2_coeff_only()         \-    float p0,p1,p2,p3,c;              \-    STBIR_SIMD_NO_UNROLL(decode);     \-    c = hc[0];                        \-    p0 = decode[0] * c;               \-    p1 = decode[1] * c;               \-    p2 = decode[2] * c;               \-    p3 = decode[3] * c;               \-    c = hc[1];                        \-    p0 += decode[4] * c;              \-    p1 += decode[5] * c;              \-    p2 += decode[6] * c;              \-    p3 += decode[7] * c;--#define stbir__3_coeff_only()         \-    float p0,p1,p2,p3,c;              \-    STBIR_SIMD_NO_UNROLL(decode);     \-    c = hc[0];                        \-    p0 = decode[0] * c;               \-    p1 = decode[1] * c;               \-    p2 = decode[2] * c;               \-    p3 = decode[3] * c;               \-    c = hc[1];                        \-    p0 += decode[4] * c;              \-    p1 += decode[5] * c;              \-    p2 += decode[6] * c;              \-    p3 += decode[7] * c;              \-    c = hc[2];                        \-    p0 += decode[8] * c;              \-    p1 += decode[9] * c;              \-    p2 += decode[10] * c;             \-    p3 += decode[11] * c;--#define stbir__store_output_tiny()                \-    output[0] = p0;                               \-    output[1] = p1;                               \-    output[2] = p2;                               \-    output[3] = p3;                               \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 4;--#define stbir__4_coeff_start()        \-    float x0,x1,x2,x3,y0,y1,y2,y3,c;  \-    STBIR_SIMD_NO_UNROLL(decode);     \-    c = hc[0];                        \-    x0 = decode[0] * c;               \-    x1 = decode[1] * c;               \-    x2 = decode[2] * c;               \-    x3 = decode[3] * c;               \-    c = hc[1];                        \-    y0 = decode[4] * c;               \-    y1 = decode[5] * c;               \-    y2 = decode[6] * c;               \-    y3 = decode[7] * c;               \-    c = hc[2];                        \-    x0 += decode[8] * c;              \-    x1 += decode[9] * c;              \-    x2 += decode[10] * c;             \-    x3 += decode[11] * c;             \-    c = hc[3];                        \-    y0 += decode[12] * c;             \-    y1 += decode[13] * c;             \-    y2 += decode[14] * c;             \-    y3 += decode[15] * c;--#define stbir__4_coeff_continue_from_4( ofs ) \-    STBIR_SIMD_NO_UNROLL(decode);     \-    c = hc[0+(ofs)];                  \-    x0 += decode[0+(ofs)*4] * c;      \-    x1 += decode[1+(ofs)*4] * c;      \-    x2 += decode[2+(ofs)*4] * c;      \-    x3 += decode[3+(ofs)*4] * c;      \-    c = hc[1+(ofs)];                  \-    y0 += decode[4+(ofs)*4] * c;      \-    y1 += decode[5+(ofs)*4] * c;      \-    y2 += decode[6+(ofs)*4] * c;      \-    y3 += decode[7+(ofs)*4] * c;      \-    c = hc[2+(ofs)];                  \-    x0 += decode[8+(ofs)*4] * c;      \-    x1 += decode[9+(ofs)*4] * c;      \-    x2 += decode[10+(ofs)*4] * c;     \-    x3 += decode[11+(ofs)*4] * c;     \-    c = hc[3+(ofs)];                  \-    y0 += decode[12+(ofs)*4] * c;     \-    y1 += decode[13+(ofs)*4] * c;     \-    y2 += decode[14+(ofs)*4] * c;     \-    y3 += decode[15+(ofs)*4] * c;--#define stbir__1_coeff_remnant( ofs ) \-    STBIR_SIMD_NO_UNROLL(decode);     \-    c = hc[0+(ofs)];                  \-    x0 += decode[0+(ofs)*4] * c;      \-    x1 += decode[1+(ofs)*4] * c;      \-    x2 += decode[2+(ofs)*4] * c;      \-    x3 += decode[3+(ofs)*4] * c;      --#define stbir__2_coeff_remnant( ofs ) \-    STBIR_SIMD_NO_UNROLL(decode);     \-    c = hc[0+(ofs)];                  \-    x0 += decode[0+(ofs)*4] * c;      \-    x1 += decode[1+(ofs)*4] * c;      \-    x2 += decode[2+(ofs)*4] * c;      \-    x3 += decode[3+(ofs)*4] * c;      \-    c = hc[1+(ofs)];                  \-    y0 += decode[4+(ofs)*4] * c;      \-    y1 += decode[5+(ofs)*4] * c;      \-    y2 += decode[6+(ofs)*4] * c;      \-    y3 += decode[7+(ofs)*4] * c;    -  -#define stbir__3_coeff_remnant( ofs ) \-    STBIR_SIMD_NO_UNROLL(decode);     \-    c = hc[0+(ofs)];                  \-    x0 += decode[0+(ofs)*4] * c;      \-    x1 += decode[1+(ofs)*4] * c;      \-    x2 += decode[2+(ofs)*4] * c;      \-    x3 += decode[3+(ofs)*4] * c;      \-    c = hc[1+(ofs)];                  \-    y0 += decode[4+(ofs)*4] * c;      \-    y1 += decode[5+(ofs)*4] * c;      \-    y2 += decode[6+(ofs)*4] * c;      \-    y3 += decode[7+(ofs)*4] * c;      \-    c = hc[2+(ofs)];                  \-    x0 += decode[8+(ofs)*4] * c;      \-    x1 += decode[9+(ofs)*4] * c;      \-    x2 += decode[10+(ofs)*4] * c;     \-    x3 += decode[11+(ofs)*4] * c;     --#define stbir__store_output()                     \-    output[0] = x0 + y0;                          \-    output[1] = x1 + y1;                          \-    output[2] = x2 + y2;                          \-    output[3] = x3 + y3;                          \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 4;--#endif  --#define STBIR__horizontal_channels 4-#define STB_IMAGE_RESIZE_DO_HORIZONTALS-#include STBIR__HEADER_FILENAME----//=================-// Do 7 channel horizontal routines--#ifdef STBIR_SIMD--#define stbir__1_coeff_only()                   \-    stbir__simdf tot0,tot1,c;                   \-    STBIR_SIMD_NO_UNROLL(decode);               \-    stbir__simdf_load1( c, hc );                \-    stbir__simdf_0123to0000( c, c );            \-    stbir__simdf_mult_mem( tot0, c, decode );   \-    stbir__simdf_mult_mem( tot1, c, decode+3 ); --#define stbir__2_coeff_only()                         \-    stbir__simdf tot0,tot1,c,cs;                      \-    STBIR_SIMD_NO_UNROLL(decode);                     \-    stbir__simdf_load2( cs, hc );                     \-    stbir__simdf_0123to0000( c, cs );                 \-    stbir__simdf_mult_mem( tot0, c, decode );         \-    stbir__simdf_mult_mem( tot1, c, decode+3 );       \-    stbir__simdf_0123to1111( c, cs );                 \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+7 ); \-    stbir__simdf_madd_mem( tot1, tot1, c,decode+10 ); --#define stbir__3_coeff_only()                           \-    stbir__simdf tot0,tot1,c,cs;                        \-    STBIR_SIMD_NO_UNROLL(decode);                       \-    stbir__simdf_load( cs, hc );                        \-    stbir__simdf_0123to0000( c, cs );                   \-    stbir__simdf_mult_mem( tot0, c, decode );           \-    stbir__simdf_mult_mem( tot1, c, decode+3 );         \-    stbir__simdf_0123to1111( c, cs );                   \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+7 );   \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+10 );  \-    stbir__simdf_0123to2222( c, cs );                   \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+14 );  \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+17 );  --#define stbir__store_output_tiny()                \-    stbir__simdf_store( output+3, tot1 );         \-    stbir__simdf_store( output, tot0 );           \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 7;--#ifdef STBIR_SIMD8--#define stbir__4_coeff_start()                     \-    stbir__simdf8 tot0,tot1,c,cs;                  \-    STBIR_SIMD_NO_UNROLL(decode);                  \-    stbir__simdf8_load4b( cs, hc );                \-    stbir__simdf8_0123to00000000( c, cs );         \-    stbir__simdf8_mult_mem( tot0, c, decode );     \-    stbir__simdf8_0123to11111111( c, cs );         \-    stbir__simdf8_mult_mem( tot1, c, decode+7 );   \-    stbir__simdf8_0123to22222222( c, cs );         \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+14 );  \-    stbir__simdf8_0123to33333333( c, cs );         \-    stbir__simdf8_madd_mem( tot1, tot1, c, decode+21 );  --#define stbir__4_coeff_continue_from_4( ofs )                   \-    STBIR_SIMD_NO_UNROLL(decode);                               \-    stbir__simdf8_load4b( cs, hc + (ofs) );                     \-    stbir__simdf8_0123to00000000( c, cs );                      \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 );    \-    stbir__simdf8_0123to11111111( c, cs );                      \-    stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 );  \-    stbir__simdf8_0123to22222222( c, cs );                      \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \-    stbir__simdf8_0123to33333333( c, cs );                      \-    stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+21 ); --#define stbir__1_coeff_remnant( ofs )                           \-    STBIR_SIMD_NO_UNROLL(decode);                               \-    stbir__simdf8_load1b( c, hc + (ofs) );                      \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 );    --#define stbir__2_coeff_remnant( ofs )                           \-    STBIR_SIMD_NO_UNROLL(decode);                               \-    stbir__simdf8_load1b( c, hc + (ofs) );                      \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 );    \-    stbir__simdf8_load1b( c, hc + (ofs)+1 );                    \-    stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 );   --#define stbir__3_coeff_remnant( ofs )                           \-    STBIR_SIMD_NO_UNROLL(decode);                               \-    stbir__simdf8_load4b( cs, hc + (ofs) );                     \-    stbir__simdf8_0123to00000000( c, cs );                      \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 );    \-    stbir__simdf8_0123to11111111( c, cs );                      \-    stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 );  \-    stbir__simdf8_0123to22222222( c, cs );                      \-    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); --#define stbir__store_output()                     \-    stbir__simdf8_add( tot0, tot0, tot1 );        \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 7;                                  \-    if ( output < output_end )                    \-    {                                             \-      stbir__simdf8_store( output-7, tot0 );      \-      continue;                                   \-    }                                             \-    stbir__simdf_store( output-7+3, stbir__simdf_swiz(stbir__simdf8_gettop4(tot0),0,0,1,2) ); \-    stbir__simdf_store( output-7, stbir__if_simdf8_cast_to_simdf4(tot0) );           \-    break;--#else--#define stbir__4_coeff_start()                    \-    stbir__simdf tot0,tot1,tot2,tot3,c,cs;        \-    STBIR_SIMD_NO_UNROLL(decode);                 \-    stbir__simdf_load( cs, hc );                  \-    stbir__simdf_0123to0000( c, cs );             \-    stbir__simdf_mult_mem( tot0, c, decode );     \-    stbir__simdf_mult_mem( tot1, c, decode+3 );   \-    stbir__simdf_0123to1111( c, cs );             \-    stbir__simdf_mult_mem( tot2, c, decode+7 );   \-    stbir__simdf_mult_mem( tot3, c, decode+10 );  \-    stbir__simdf_0123to2222( c, cs );             \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+14 );  \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+17 );  \-    stbir__simdf_0123to3333( c, cs );                   \-    stbir__simdf_madd_mem( tot2, tot2, c, decode+21 );  \-    stbir__simdf_madd_mem( tot3, tot3, c, decode+24 );         --#define stbir__4_coeff_continue_from_4( ofs )                   \-    STBIR_SIMD_NO_UNROLL(decode);                               \-    stbir__simdf_load( cs, hc + (ofs) );                        \-    stbir__simdf_0123to0000( c, cs );                           \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 );     \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 );   \-    stbir__simdf_0123to1111( c, cs );                           \-    stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 );   \-    stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 );  \-    stbir__simdf_0123to2222( c, cs );                           \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 );  \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 );  \-    stbir__simdf_0123to3333( c, cs );                           \-    stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+21 );  \-    stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+24 );   --#define stbir__1_coeff_remnant( ofs )                           \-    STBIR_SIMD_NO_UNROLL(decode);                               \-    stbir__simdf_load1( c, hc + (ofs) );                        \-    stbir__simdf_0123to0000( c, c );                            \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 );     \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 );   \--#define stbir__2_coeff_remnant( ofs )                           \-    STBIR_SIMD_NO_UNROLL(decode);                               \-    stbir__simdf_load2( cs, hc + (ofs) );                       \-    stbir__simdf_0123to0000( c, cs );                           \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 );     \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 );   \-    stbir__simdf_0123to1111( c, cs );                           \-    stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 );   \-    stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 );  -  -#define stbir__3_coeff_remnant( ofs )                           \-    STBIR_SIMD_NO_UNROLL(decode);                               \-    stbir__simdf_load( cs, hc + (ofs) );                        \-    stbir__simdf_0123to0000( c, cs );                           \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 );     \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 );   \-    stbir__simdf_0123to1111( c, cs );                           \-    stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 );   \-    stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 );  \-    stbir__simdf_0123to2222( c, cs );                           \-    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 );  \-    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 );  --#define stbir__store_output()                     \-    stbir__simdf_add( tot0, tot0, tot2 );         \-    stbir__simdf_add( tot1, tot1, tot3 );         \-    stbir__simdf_store( output+3, tot1 );         \-    stbir__simdf_store( output, tot0 );           \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 7;--#endif--#else--#define stbir__1_coeff_only()        \-    float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \-    c = hc[0];                       \-    tot0 = decode[0]*c;              \-    tot1 = decode[1]*c;              \-    tot2 = decode[2]*c;              \-    tot3 = decode[3]*c;              \-    tot4 = decode[4]*c;              \-    tot5 = decode[5]*c;              \-    tot6 = decode[6]*c;              --#define stbir__2_coeff_only()        \-    float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \-    c = hc[0];                       \-    tot0 = decode[0]*c;              \-    tot1 = decode[1]*c;              \-    tot2 = decode[2]*c;              \-    tot3 = decode[3]*c;              \-    tot4 = decode[4]*c;              \-    tot5 = decode[5]*c;              \-    tot6 = decode[6]*c;              \-    c = hc[1];                       \-    tot0 += decode[7]*c;             \-    tot1 += decode[8]*c;             \-    tot2 += decode[9]*c;             \-    tot3 += decode[10]*c;            \-    tot4 += decode[11]*c;            \-    tot5 += decode[12]*c;            \-    tot6 += decode[13]*c;            \--#define stbir__3_coeff_only()        \-    float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \-    c = hc[0];                       \-    tot0 = decode[0]*c;              \-    tot1 = decode[1]*c;              \-    tot2 = decode[2]*c;              \-    tot3 = decode[3]*c;              \-    tot4 = decode[4]*c;              \-    tot5 = decode[5]*c;              \-    tot6 = decode[6]*c;              \-    c = hc[1];                       \-    tot0 += decode[7]*c;             \-    tot1 += decode[8]*c;             \-    tot2 += decode[9]*c;             \-    tot3 += decode[10]*c;            \-    tot4 += decode[11]*c;            \-    tot5 += decode[12]*c;            \-    tot6 += decode[13]*c;            \-    c = hc[2];                       \-    tot0 += decode[14]*c;            \-    tot1 += decode[15]*c;            \-    tot2 += decode[16]*c;            \-    tot3 += decode[17]*c;            \-    tot4 += decode[18]*c;            \-    tot5 += decode[19]*c;            \-    tot6 += decode[20]*c;            \--#define stbir__store_output_tiny()                \-    output[0] = tot0;                             \-    output[1] = tot1;                             \-    output[2] = tot2;                             \-    output[3] = tot3;                             \-    output[4] = tot4;                             \-    output[5] = tot5;                             \-    output[6] = tot6;                             \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 7;--#define stbir__4_coeff_start()    \-    float x0,x1,x2,x3,x4,x5,x6,y0,y1,y2,y3,y4,y5,y6,c; \-    STBIR_SIMD_NO_UNROLL(decode); \-    c = hc[0];                    \-    x0 = decode[0] * c;           \-    x1 = decode[1] * c;           \-    x2 = decode[2] * c;           \-    x3 = decode[3] * c;           \-    x4 = decode[4] * c;           \-    x5 = decode[5] * c;           \-    x6 = decode[6] * c;           \-    c = hc[1];                    \-    y0 = decode[7] * c;           \-    y1 = decode[8] * c;           \-    y2 = decode[9] * c;           \-    y3 = decode[10] * c;          \-    y4 = decode[11] * c;          \-    y5 = decode[12] * c;          \-    y6 = decode[13] * c;          \-    c = hc[2];                    \-    x0 += decode[14] * c;         \-    x1 += decode[15] * c;         \-    x2 += decode[16] * c;         \-    x3 += decode[17] * c;         \-    x4 += decode[18] * c;         \-    x5 += decode[19] * c;         \-    x6 += decode[20] * c;         \-    c = hc[3];                    \-    y0 += decode[21] * c;         \-    y1 += decode[22] * c;         \-    y2 += decode[23] * c;         \-    y3 += decode[24] * c;         \-    y4 += decode[25] * c;         \-    y5 += decode[26] * c;         \-    y6 += decode[27] * c; --#define stbir__4_coeff_continue_from_4( ofs ) \-    STBIR_SIMD_NO_UNROLL(decode);  \-    c = hc[0+(ofs)];               \-    x0 += decode[0+(ofs)*7] * c;   \-    x1 += decode[1+(ofs)*7] * c;   \-    x2 += decode[2+(ofs)*7] * c;   \-    x3 += decode[3+(ofs)*7] * c;   \-    x4 += decode[4+(ofs)*7] * c;   \-    x5 += decode[5+(ofs)*7] * c;   \-    x6 += decode[6+(ofs)*7] * c;   \-    c = hc[1+(ofs)];               \-    y0 += decode[7+(ofs)*7] * c;   \-    y1 += decode[8+(ofs)*7] * c;   \-    y2 += decode[9+(ofs)*7] * c;   \-    y3 += decode[10+(ofs)*7] * c;  \-    y4 += decode[11+(ofs)*7] * c;  \-    y5 += decode[12+(ofs)*7] * c;  \-    y6 += decode[13+(ofs)*7] * c;  \-    c = hc[2+(ofs)];               \-    x0 += decode[14+(ofs)*7] * c;  \-    x1 += decode[15+(ofs)*7] * c;  \-    x2 += decode[16+(ofs)*7] * c;  \-    x3 += decode[17+(ofs)*7] * c;  \-    x4 += decode[18+(ofs)*7] * c;  \-    x5 += decode[19+(ofs)*7] * c;  \-    x6 += decode[20+(ofs)*7] * c;  \-    c = hc[3+(ofs)];               \-    y0 += decode[21+(ofs)*7] * c;  \-    y1 += decode[22+(ofs)*7] * c;  \-    y2 += decode[23+(ofs)*7] * c;  \-    y3 += decode[24+(ofs)*7] * c;  \-    y4 += decode[25+(ofs)*7] * c;  \-    y5 += decode[26+(ofs)*7] * c;  \-    y6 += decode[27+(ofs)*7] * c; --#define stbir__1_coeff_remnant( ofs ) \-    STBIR_SIMD_NO_UNROLL(decode);  \-    c = hc[0+(ofs)];               \-    x0 += decode[0+(ofs)*7] * c;   \-    x1 += decode[1+(ofs)*7] * c;   \-    x2 += decode[2+(ofs)*7] * c;   \-    x3 += decode[3+(ofs)*7] * c;   \-    x4 += decode[4+(ofs)*7] * c;   \-    x5 += decode[5+(ofs)*7] * c;   \-    x6 += decode[6+(ofs)*7] * c;   \--#define stbir__2_coeff_remnant( ofs ) \-    STBIR_SIMD_NO_UNROLL(decode);  \-    c = hc[0+(ofs)];               \-    x0 += decode[0+(ofs)*7] * c;   \-    x1 += decode[1+(ofs)*7] * c;   \-    x2 += decode[2+(ofs)*7] * c;   \-    x3 += decode[3+(ofs)*7] * c;   \-    x4 += decode[4+(ofs)*7] * c;   \-    x5 += decode[5+(ofs)*7] * c;   \-    x6 += decode[6+(ofs)*7] * c;   \-    c = hc[1+(ofs)];               \-    y0 += decode[7+(ofs)*7] * c;   \-    y1 += decode[8+(ofs)*7] * c;   \-    y2 += decode[9+(ofs)*7] * c;   \-    y3 += decode[10+(ofs)*7] * c;  \-    y4 += decode[11+(ofs)*7] * c;  \-    y5 += decode[12+(ofs)*7] * c;  \-    y6 += decode[13+(ofs)*7] * c;  \-  -#define stbir__3_coeff_remnant( ofs ) \-    STBIR_SIMD_NO_UNROLL(decode);  \-    c = hc[0+(ofs)];               \-    x0 += decode[0+(ofs)*7] * c;   \-    x1 += decode[1+(ofs)*7] * c;   \-    x2 += decode[2+(ofs)*7] * c;   \-    x3 += decode[3+(ofs)*7] * c;   \-    x4 += decode[4+(ofs)*7] * c;   \-    x5 += decode[5+(ofs)*7] * c;   \-    x6 += decode[6+(ofs)*7] * c;   \-    c = hc[1+(ofs)];               \-    y0 += decode[7+(ofs)*7] * c;   \-    y1 += decode[8+(ofs)*7] * c;   \-    y2 += decode[9+(ofs)*7] * c;   \-    y3 += decode[10+(ofs)*7] * c;  \-    y4 += decode[11+(ofs)*7] * c;  \-    y5 += decode[12+(ofs)*7] * c;  \-    y6 += decode[13+(ofs)*7] * c;  \-    c = hc[2+(ofs)];               \-    x0 += decode[14+(ofs)*7] * c;  \-    x1 += decode[15+(ofs)*7] * c;  \-    x2 += decode[16+(ofs)*7] * c;  \-    x3 += decode[17+(ofs)*7] * c;  \-    x4 += decode[18+(ofs)*7] * c;  \-    x5 += decode[19+(ofs)*7] * c;  \-    x6 += decode[20+(ofs)*7] * c;  \--#define stbir__store_output()                     \-    output[0] = x0 + y0;                          \-    output[1] = x1 + y1;                          \-    output[2] = x2 + y2;                          \-    output[3] = x3 + y3;                          \-    output[4] = x4 + y4;                          \-    output[5] = x5 + y5;                          \-    output[6] = x6 + y6;                          \-    horizontal_coefficients += coefficient_width; \-    ++horizontal_contributors;                    \-    output += 7;--#endif  --#define STBIR__horizontal_channels 7-#define STB_IMAGE_RESIZE_DO_HORIZONTALS-#include STBIR__HEADER_FILENAME---// include all of the vertical resamplers (both scatter and gather versions)--#define STBIR__vertical_channels 1-#define STB_IMAGE_RESIZE_DO_VERTICALS-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 1-#define STB_IMAGE_RESIZE_DO_VERTICALS-#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 2-#define STB_IMAGE_RESIZE_DO_VERTICALS-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 2-#define STB_IMAGE_RESIZE_DO_VERTICALS-#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 3-#define STB_IMAGE_RESIZE_DO_VERTICALS-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 3-#define STB_IMAGE_RESIZE_DO_VERTICALS-#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 4-#define STB_IMAGE_RESIZE_DO_VERTICALS-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 4-#define STB_IMAGE_RESIZE_DO_VERTICALS-#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 5-#define STB_IMAGE_RESIZE_DO_VERTICALS-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 5-#define STB_IMAGE_RESIZE_DO_VERTICALS-#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 6-#define STB_IMAGE_RESIZE_DO_VERTICALS-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 6-#define STB_IMAGE_RESIZE_DO_VERTICALS-#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 7-#define STB_IMAGE_RESIZE_DO_VERTICALS-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 7-#define STB_IMAGE_RESIZE_DO_VERTICALS-#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 8-#define STB_IMAGE_RESIZE_DO_VERTICALS-#include STBIR__HEADER_FILENAME--#define STBIR__vertical_channels 8-#define STB_IMAGE_RESIZE_DO_VERTICALS-#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#include STBIR__HEADER_FILENAME--typedef void STBIR_VERTICAL_GATHERFUNC( float * output, float const * coeffs, float const ** inputs, float const * input0_end );--static STBIR_VERTICAL_GATHERFUNC * stbir__vertical_gathers[ 8 ] =-{-  stbir__vertical_gather_with_1_coeffs,stbir__vertical_gather_with_2_coeffs,stbir__vertical_gather_with_3_coeffs,stbir__vertical_gather_with_4_coeffs,stbir__vertical_gather_with_5_coeffs,stbir__vertical_gather_with_6_coeffs,stbir__vertical_gather_with_7_coeffs,stbir__vertical_gather_with_8_coeffs-};--static STBIR_VERTICAL_GATHERFUNC * stbir__vertical_gathers_continues[ 8 ] =-{-  stbir__vertical_gather_with_1_coeffs_cont,stbir__vertical_gather_with_2_coeffs_cont,stbir__vertical_gather_with_3_coeffs_cont,stbir__vertical_gather_with_4_coeffs_cont,stbir__vertical_gather_with_5_coeffs_cont,stbir__vertical_gather_with_6_coeffs_cont,stbir__vertical_gather_with_7_coeffs_cont,stbir__vertical_gather_with_8_coeffs_cont-};--typedef void STBIR_VERTICAL_SCATTERFUNC( float ** outputs, float const * coeffs, float const * input, float const * input_end );--static STBIR_VERTICAL_SCATTERFUNC * stbir__vertical_scatter_sets[ 8 ] =-{-  stbir__vertical_scatter_with_1_coeffs,stbir__vertical_scatter_with_2_coeffs,stbir__vertical_scatter_with_3_coeffs,stbir__vertical_scatter_with_4_coeffs,stbir__vertical_scatter_with_5_coeffs,stbir__vertical_scatter_with_6_coeffs,stbir__vertical_scatter_with_7_coeffs,stbir__vertical_scatter_with_8_coeffs-};--static STBIR_VERTICAL_SCATTERFUNC * stbir__vertical_scatter_blends[ 8 ] =-{-  stbir__vertical_scatter_with_1_coeffs_cont,stbir__vertical_scatter_with_2_coeffs_cont,stbir__vertical_scatter_with_3_coeffs_cont,stbir__vertical_scatter_with_4_coeffs_cont,stbir__vertical_scatter_with_5_coeffs_cont,stbir__vertical_scatter_with_6_coeffs_cont,stbir__vertical_scatter_with_7_coeffs_cont,stbir__vertical_scatter_with_8_coeffs_cont-};---static void stbir__encode_scanline( stbir__info const * stbir_info, void *output_buffer_data, float * encode_buffer, int row  STBIR_ONLY_PROFILE_GET_SPLIT_INFO )-{-  int num_pixels = stbir_info->horizontal.scale_info.output_sub_size;-  int channels = stbir_info->channels;-  int width_times_channels = num_pixels * channels;-  void * output_buffer;--  // un-alpha weight if we need to-  if ( stbir_info->alpha_unweight )-  {-    STBIR_PROFILE_START( unalpha );-    stbir_info->alpha_unweight( encode_buffer, width_times_channels );-    STBIR_PROFILE_END( unalpha );-  }--  // write directly into output by default-  output_buffer = output_buffer_data;--  // if we have an output callback, we first convert the decode buffer in place (and then hand that to the callback)-  if ( stbir_info->out_pixels_cb )-    output_buffer = encode_buffer;-  -  STBIR_PROFILE_START( encode );-  // convert into the output buffer-  stbir_info->encode_pixels( output_buffer, width_times_channels, encode_buffer );-  STBIR_PROFILE_END( encode );--  // if we have an output callback, call it to send the data-  if ( stbir_info->out_pixels_cb )-    stbir_info->out_pixels_cb( output_buffer_data, num_pixels, row, stbir_info->user_data );-}---// Get the ring buffer pointer for an index-static float* stbir__get_ring_buffer_entry(stbir__info const * stbir_info, stbir__per_split_info const * split_info, int index )-{-  STBIR_ASSERT( index < stbir_info->ring_buffer_num_entries );--  #ifdef STBIR__SEPARATE_ALLOCATIONS-    return split_info->ring_buffers[ index ];-  #else-    return (float*) ( ( (char*) split_info->ring_buffer ) + ( index * stbir_info->ring_buffer_length_bytes ) );-  #endif-}--// Get the specified scan line from the ring buffer-static float* stbir__get_ring_buffer_scanline(stbir__info const * stbir_info, stbir__per_split_info const * split_info, int get_scanline)-{-  int ring_buffer_index = (split_info->ring_buffer_begin_index + (get_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries;-  return stbir__get_ring_buffer_entry( stbir_info, split_info, ring_buffer_index );-}--static void stbir__resample_horizontal_gather(stbir__info const * stbir_info, float* output_buffer, float const * input_buffer STBIR_ONLY_PROFILE_GET_SPLIT_INFO )-{-  float const * decode_buffer = input_buffer - ( stbir_info->scanline_extents.conservative.n0 * stbir_info->effective_channels );--  STBIR_PROFILE_START( horizontal );-  if ( ( stbir_info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( stbir_info->horizontal.scale_info.scale == 1.0f ) )-    STBIR_MEMCPY( output_buffer, input_buffer, stbir_info->horizontal.scale_info.output_sub_size * sizeof( float ) * stbir_info->effective_channels );-  else-    stbir_info->horizontal_gather_channels( output_buffer, stbir_info->horizontal.scale_info.output_sub_size, decode_buffer, stbir_info->horizontal.contributors, stbir_info->horizontal.coefficients, stbir_info->horizontal.coefficient_width );-  STBIR_PROFILE_END( horizontal );-}--static void stbir__resample_vertical_gather(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n, int contrib_n0, int contrib_n1, float const * vertical_coefficients )-{-  float* encode_buffer = split_info->vertical_buffer;-  float* decode_buffer = split_info->decode_buffer;-  int vertical_first = stbir_info->vertical_first;-  int width = (vertical_first) ? ( stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1 ) : stbir_info->horizontal.scale_info.output_sub_size;-  int width_times_channels = stbir_info->effective_channels * width;--  STBIR_ASSERT( stbir_info->vertical.is_gather );--  // loop over the contributing scanlines and scale into the buffer-  STBIR_PROFILE_START( vertical );-  {-    int k = 0, total = contrib_n1 - contrib_n0 + 1;-    STBIR_ASSERT( total > 0 );-    do {-      float const * inputs[8];-      int i, cnt = total; if ( cnt > 8 ) cnt = 8;-      for( i = 0 ; i < cnt ; i++ )-        inputs[ i ] = stbir__get_ring_buffer_scanline(stbir_info, split_info, k+i+contrib_n0 );--      // call the N scanlines at a time function (up to 8 scanlines of blending at once)-      ((k==0)?stbir__vertical_gathers:stbir__vertical_gathers_continues)[cnt-1]( (vertical_first) ? decode_buffer : encode_buffer, vertical_coefficients + k, inputs, inputs[0] + width_times_channels );-      k += cnt;-      total -= cnt;-    } while ( total );-  }-  STBIR_PROFILE_END( vertical );--  if ( vertical_first )-  {-    // Now resample the gathered vertical data in the horizontal axis into the encode buffer-    stbir__resample_horizontal_gather(stbir_info, encode_buffer, decode_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );-  }--  stbir__encode_scanline( stbir_info, ( (char *) stbir_info->output_data ) + ((ptrdiff_t)n * (ptrdiff_t)stbir_info->output_stride_bytes), -                          encode_buffer, n  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );-}--static void stbir__decode_and_resample_for_vertical_gather_loop(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n)-{-  int ring_buffer_index;-  float* ring_buffer;--  // Decode the nth scanline from the source image into the decode buffer.-  stbir__decode_scanline( stbir_info, n, split_info->decode_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );--  // update new end scanline-  split_info->ring_buffer_last_scanline = n;--  // get ring buffer -  ring_buffer_index = (split_info->ring_buffer_begin_index + (split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries;-  ring_buffer = stbir__get_ring_buffer_entry(stbir_info, split_info, ring_buffer_index);--  // Now resample it into the ring buffer.-  stbir__resample_horizontal_gather( stbir_info, ring_buffer, split_info->decode_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );--  // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling.-}--static void stbir__vertical_gather_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count )-{-  int y, start_output_y, end_output_y;-  stbir__contributors* vertical_contributors = stbir_info->vertical.contributors;-  float const * vertical_coefficients = stbir_info->vertical.coefficients;--  STBIR_ASSERT( stbir_info->vertical.is_gather );--  start_output_y = split_info->start_output_y;-  end_output_y = split_info[split_count-1].end_output_y;--  vertical_contributors += start_output_y;-  vertical_coefficients += start_output_y * stbir_info->vertical.coefficient_width;--  // initialize the ring buffer for gathering-  split_info->ring_buffer_begin_index = 0;-  split_info->ring_buffer_first_scanline = stbir_info->vertical.extent_info.lowest;  -  split_info->ring_buffer_last_scanline = split_info->ring_buffer_first_scanline - 1; // means "empty"--  for (y = start_output_y; y < end_output_y; y++)-  {-    int in_first_scanline, in_last_scanline;--    in_first_scanline = vertical_contributors->n0;-    in_last_scanline = vertical_contributors->n1;--    // make sure the indexing hasn't broken-    STBIR_ASSERT( in_first_scanline >= split_info->ring_buffer_first_scanline );--    // Load in new scanlines-    while (in_last_scanline > split_info->ring_buffer_last_scanline)-    {-      STBIR_ASSERT( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) <= stbir_info->ring_buffer_num_entries );--      // make sure there was room in the ring buffer when we add new scanlines-      if ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries )-      {-        split_info->ring_buffer_first_scanline++;-        split_info->ring_buffer_begin_index++;-      }-      -      if ( stbir_info->vertical_first )-      {-        float * ring_buffer = stbir__get_ring_buffer_scanline( stbir_info, split_info, ++split_info->ring_buffer_last_scanline );-        // Decode the nth scanline from the source image into the decode buffer.-        stbir__decode_scanline( stbir_info, split_info->ring_buffer_last_scanline, ring_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); -      }-      else-      {-        stbir__decode_and_resample_for_vertical_gather_loop(stbir_info, split_info, split_info->ring_buffer_last_scanline + 1);-      }-    }--    // Now all buffers should be ready to write a row of vertical sampling, so do it.-    stbir__resample_vertical_gather(stbir_info, split_info, y, in_first_scanline, in_last_scanline, vertical_coefficients );--    ++vertical_contributors;-    vertical_coefficients += stbir_info->vertical.coefficient_width;-  }-}--#define STBIR__FLOAT_EMPTY_MARKER 3.0e+38F-#define STBIR__FLOAT_BUFFER_IS_EMPTY(ptr) ((ptr)[0]==STBIR__FLOAT_EMPTY_MARKER)--static void stbir__encode_first_scanline_from_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info)-{-  // evict a scanline out into the output buffer-  float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index );-  -  // dump the scanline out-  stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (ptrdiff_t)split_info->ring_buffer_first_scanline * (ptrdiff_t)stbir_info->output_stride_bytes ), ring_buffer_entry, split_info->ring_buffer_first_scanline  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );-  -  // mark it as empty-  ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER;--  // advance the first scanline-  split_info->ring_buffer_first_scanline++;-  if ( ++split_info->ring_buffer_begin_index == stbir_info->ring_buffer_num_entries )-    split_info->ring_buffer_begin_index = 0;-}--static void stbir__horizontal_resample_and_encode_first_scanline_from_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info)-{-  // evict a scanline out into the output buffer--  float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index );--  // Now resample it into the buffer.-  stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, ring_buffer_entry  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );-  -  // dump the scanline out-  stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (ptrdiff_t)split_info->ring_buffer_first_scanline * (ptrdiff_t)stbir_info->output_stride_bytes ), split_info->vertical_buffer, split_info->ring_buffer_first_scanline  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );-  -  // mark it as empty-  ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER;--  // advance the first scanline-  split_info->ring_buffer_first_scanline++;-  if ( ++split_info->ring_buffer_begin_index == stbir_info->ring_buffer_num_entries )-    split_info->ring_buffer_begin_index = 0;-}--static void stbir__resample_vertical_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n0, int n1, float const * vertical_coefficients, float const * vertical_buffer, float const * vertical_buffer_end )-{-  STBIR_ASSERT( !stbir_info->vertical.is_gather );--  STBIR_PROFILE_START( vertical );-  {-    int k = 0, total = n1 - n0 + 1;-    STBIR_ASSERT( total > 0 );-    do {-      float * outputs[8];-      int i, n = total; if ( n > 8 ) n = 8;-      for( i = 0 ; i < n ; i++ )-      {-        outputs[ i ] = stbir__get_ring_buffer_scanline(stbir_info, split_info, k+i+n0 );-        if ( ( i ) && ( STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[i] ) != STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[0] ) ) ) // make sure runs are of the same type-        {-          n = i;-          break;-        }-      }-      // call the scatter to N scanlines at a time function (up to 8 scanlines of scattering at once)-      ((STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[0] ))?stbir__vertical_scatter_sets:stbir__vertical_scatter_blends)[n-1]( outputs, vertical_coefficients + k, vertical_buffer, vertical_buffer_end );-      k += n;-      total -= n;-    } while ( total );-  }--  STBIR_PROFILE_END( vertical );-}--typedef void stbir__handle_scanline_for_scatter_func(stbir__info const * stbir_info, stbir__per_split_info* split_info); --static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count )-{-  int y, start_output_y, end_output_y, start_input_y, end_input_y;-  stbir__contributors* vertical_contributors = stbir_info->vertical.contributors;-  float const * vertical_coefficients = stbir_info->vertical.coefficients;-  stbir__handle_scanline_for_scatter_func * handle_scanline_for_scatter;-  void * scanline_scatter_buffer;-  void * scanline_scatter_buffer_end;-  int on_first_input_y, last_input_y;--  STBIR_ASSERT( !stbir_info->vertical.is_gather );--  start_output_y = split_info->start_output_y;-  end_output_y = split_info[split_count-1].end_output_y;  // may do multiple split counts--  start_input_y = split_info->start_input_y;-  end_input_y = split_info[split_count-1].end_input_y;--  // adjust for starting offset start_input_y-  y = start_input_y + stbir_info->vertical.filter_pixel_margin; -  vertical_contributors += y ;-  vertical_coefficients += stbir_info->vertical.coefficient_width * y;--  if ( stbir_info->vertical_first )-  {-    handle_scanline_for_scatter = stbir__horizontal_resample_and_encode_first_scanline_from_scatter;-    scanline_scatter_buffer = split_info->decode_buffer;-    scanline_scatter_buffer_end = ( (char*) scanline_scatter_buffer ) + sizeof( float ) * stbir_info->effective_channels * (stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1);-  }-  else-  {-    handle_scanline_for_scatter = stbir__encode_first_scanline_from_scatter;-    scanline_scatter_buffer = split_info->vertical_buffer;-    scanline_scatter_buffer_end = ( (char*) scanline_scatter_buffer ) + sizeof( float ) * stbir_info->effective_channels * stbir_info->horizontal.scale_info.output_sub_size;-  }--  // initialize the ring buffer for scattering-  split_info->ring_buffer_first_scanline = start_output_y;-  split_info->ring_buffer_last_scanline = -1;-  split_info->ring_buffer_begin_index = -1;--  // mark all the buffers as empty to start-  for( y = 0 ; y < stbir_info->ring_buffer_num_entries ; y++ )-    stbir__get_ring_buffer_entry( stbir_info, split_info, y )[0] = STBIR__FLOAT_EMPTY_MARKER; // only used on scatter--  // do the loop in input space-  on_first_input_y = 1; last_input_y = start_input_y;-  for (y = start_input_y ; y < end_input_y; y++)-  {-    int out_first_scanline, out_last_scanline;--    out_first_scanline = vertical_contributors->n0;-    out_last_scanline = vertical_contributors->n1;--    STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);--    if ( ( out_last_scanline >= out_first_scanline ) && ( ( ( out_first_scanline >= start_output_y ) && ( out_first_scanline < end_output_y ) ) || ( ( out_last_scanline >= start_output_y ) && ( out_last_scanline < end_output_y ) ) ) )-    {-      float const * vc = vertical_coefficients;--      // keep track of the range actually seen for the next resize-      last_input_y = y;-      if ( ( on_first_input_y ) && ( y > start_input_y ) )-        split_info->start_input_y = y;-      on_first_input_y = 0;--      // clip the region -      if ( out_first_scanline < start_output_y )-      {-        vc += start_output_y - out_first_scanline;-        out_first_scanline = start_output_y;-      }--      if ( out_last_scanline >= end_output_y )-        out_last_scanline = end_output_y - 1;--      // if very first scanline, init the index-      if (split_info->ring_buffer_begin_index < 0)-        split_info->ring_buffer_begin_index = out_first_scanline - start_output_y;-      -      STBIR_ASSERT( split_info->ring_buffer_begin_index <= out_first_scanline );--      // Decode the nth scanline from the source image into the decode buffer.-      stbir__decode_scanline( stbir_info, y, split_info->decode_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); --      // When horizontal first, we resample horizontally into the vertical buffer before we scatter it out-      if ( !stbir_info->vertical_first )-        stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, split_info->decode_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );--      // Now it's sitting in the buffer ready to be distributed into the ring buffers.--      // evict from the ringbuffer, if we need are full-      if ( ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries ) &&-           ( out_last_scanline > split_info->ring_buffer_last_scanline ) )-        handle_scanline_for_scatter( stbir_info, split_info );-    -      // Now the horizontal buffer is ready to write to all ring buffer rows, so do it.-      stbir__resample_vertical_scatter(stbir_info, split_info, out_first_scanline, out_last_scanline, vc, (float*)scanline_scatter_buffer, (float*)scanline_scatter_buffer_end );--      // update the end of the buffer-      if ( out_last_scanline > split_info->ring_buffer_last_scanline )-        split_info->ring_buffer_last_scanline = out_last_scanline;-    }-    ++vertical_contributors;-    vertical_coefficients += stbir_info->vertical.coefficient_width;-  }--  // now evict the scanlines that are left over in the ring buffer-  while ( split_info->ring_buffer_first_scanline < end_output_y )-    handle_scanline_for_scatter(stbir_info, split_info);--  // update the end_input_y if we do multiple resizes with the same data-  ++last_input_y;-  for( y = 0 ; y < split_count; y++ )-    if ( split_info[y].end_input_y > last_input_y )-      split_info[y].end_input_y = last_input_y;-}---static stbir__kernel_callback * stbir__builtin_kernels[] =   { 0, stbir__filter_trapezoid,  stbir__filter_triangle, stbir__filter_cubic, stbir__filter_catmullrom, stbir__filter_mitchell, stbir__filter_point };-static stbir__support_callback * stbir__builtin_supports[] = { 0, stbir__support_trapezoid, stbir__support_one,     stbir__support_two,  stbir__support_two,       stbir__support_two,     stbir__support_zeropoint5 };--static void stbir__set_sampler(stbir__sampler * samp, stbir_filter filter, stbir__kernel_callback * kernel, stbir__support_callback * support, stbir_edge edge, stbir__scale_info * scale_info, int always_gather, void * user_data )-{-  // set filter-  if (filter == 0)-  {-    filter = STBIR_DEFAULT_FILTER_DOWNSAMPLE; // default to downsample-    if (scale_info->scale >= ( 1.0f - stbir__small_float ) )-    {-      if ( (scale_info->scale <= ( 1.0f + stbir__small_float ) ) && ( STBIR_CEILF(scale_info->pixel_shift) == scale_info->pixel_shift ) )-        filter = STBIR_FILTER_POINT_SAMPLE;  -      else-        filter = STBIR_DEFAULT_FILTER_UPSAMPLE;-    }-  }-  samp->filter_enum = filter;--  STBIR_ASSERT(samp->filter_enum != 0);-  STBIR_ASSERT((unsigned)samp->filter_enum < STBIR_FILTER_OTHER); -  samp->filter_kernel = stbir__builtin_kernels[ filter ];-  samp->filter_support = stbir__builtin_supports[ filter ];--  if ( kernel && support )-  {-    samp->filter_kernel = kernel;-    samp->filter_support = support;-    samp->filter_enum = STBIR_FILTER_OTHER;-  }--  samp->edge = edge;-  samp->filter_pixel_width  = stbir__get_filter_pixel_width (samp->filter_support, scale_info->scale, user_data );-  // Gather is always better, but in extreme downsamples, you have to most or all of the data in memory-  //    For horizontal, we always have all the pixels, so we always use gather here (always_gather==1).-  //    For vertical, we use gather if scaling up (which means we will have samp->filter_pixel_width-  //    scanlines in memory at once).-  samp->is_gather = 0;-  if ( scale_info->scale >= ( 1.0f - stbir__small_float ) )-    samp->is_gather = 1;-  else if ( ( always_gather ) || ( samp->filter_pixel_width <= STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT ) )-    samp->is_gather = 2;--  // pre calculate stuff based on the above-  samp->coefficient_width = stbir__get_coefficient_width(samp, samp->is_gather, user_data);--  if ( edge == STBIR_EDGE_WRAP )-    if ( samp->filter_pixel_width > ( scale_info->input_full_size * 2 ) )  // this can only happen when shrinking to a single pixel-      samp->filter_pixel_width = scale_info->input_full_size * 2;--  // This is how much to expand buffers to account for filters seeking outside-  // the image boundaries.-  samp->filter_pixel_margin = samp->filter_pixel_width / 2;--  samp->num_contributors = stbir__get_contributors(samp, samp->is_gather);-  samp->contributors_size = samp->num_contributors * sizeof(stbir__contributors);-  samp->coefficients_size = samp->num_contributors * samp->coefficient_width * sizeof(float) + sizeof(float); // extra sizeof(float) is padding--  samp->gather_prescatter_contributors = 0;-  samp->gather_prescatter_coefficients = 0;-  if ( samp->is_gather == 0 )-  {-    samp->gather_prescatter_coefficient_width = samp->filter_pixel_width;-    samp->gather_prescatter_num_contributors  = stbir__get_contributors(samp, 2);-    samp->gather_prescatter_contributors_size = samp->gather_prescatter_num_contributors * sizeof(stbir__contributors);-    samp->gather_prescatter_coefficients_size = samp->gather_prescatter_num_contributors * samp->gather_prescatter_coefficient_width * sizeof(float);-  }-}--static void stbir__get_conservative_extents( stbir__sampler * samp, stbir__contributors * range, void * user_data )-{-  float scale = samp->scale_info.scale;-  float out_shift = samp->scale_info.pixel_shift;-  stbir__support_callback * support = samp->filter_support;-  int input_full_size = samp->scale_info.input_full_size;-  stbir_edge edge = samp->edge;-  float inv_scale = samp->scale_info.inv_scale;--  STBIR_ASSERT( samp->is_gather != 0 );--  if ( samp->is_gather == 1 )-  {-    int in_first_pixel, in_last_pixel;-    float out_filter_radius = support(inv_scale, user_data) * scale;--    stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, 0.5, out_filter_radius, inv_scale, out_shift, input_full_size, edge );-    range->n0 = in_first_pixel;-    stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, ( (float)(samp->scale_info.output_sub_size-1) ) + 0.5f, out_filter_radius, inv_scale, out_shift, input_full_size, edge );-    range->n1 = in_last_pixel;-  }-  else if ( samp->is_gather == 2 ) // downsample gather, refine-  {-    float in_pixels_radius = support(scale, user_data) * inv_scale;-    int filter_pixel_margin = samp->filter_pixel_margin;-    int output_sub_size = samp->scale_info.output_sub_size;-    int input_end;-    int n;-    int in_first_pixel, in_last_pixel;--    // get a conservative area of the input range-    stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, 0, 0, inv_scale, out_shift, input_full_size, edge );-    range->n0 = in_first_pixel;-    stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, (float)output_sub_size, 0, inv_scale, out_shift, input_full_size, edge );-    range->n1 = in_last_pixel;-     -    // now go through the margin to the start of area to find bottom -    n = range->n0 + 1;-    input_end = -filter_pixel_margin;-    while( n >= input_end )-    {-      int out_first_pixel, out_last_pixel;-      stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, ((float)n)+0.5f, in_pixels_radius, scale, out_shift, output_sub_size );-      if ( out_first_pixel > out_last_pixel )-        break;--      if ( ( out_first_pixel < output_sub_size ) || ( out_last_pixel >= 0 ) )-        range->n0 = n;-      --n;-    }--    // now go through the end of the area through the margin to find top -    n = range->n1 - 1;-    input_end = n + 1 + filter_pixel_margin;-    while( n <= input_end )-    {-      int out_first_pixel, out_last_pixel;-      stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, ((float)n)+0.5f, in_pixels_radius, scale, out_shift, output_sub_size );-      if ( out_first_pixel > out_last_pixel )-        break;-      if ( ( out_first_pixel < output_sub_size ) || ( out_last_pixel >= 0 ) )-        range->n1 = n;-      ++n;-    }-  }--  if ( samp->edge == STBIR_EDGE_WRAP )-  {-    // if we are wrapping, and we are very close to the image size (so the edges might merge), just use the scanline up to the edge-    if ( ( range->n0 > 0 ) && ( range->n1 >= input_full_size ) )-    {-      int marg = range->n1 - input_full_size + 1;-      if ( ( marg + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= range->n0 )-        range->n0 = 0;-    }-    if ( ( range->n0 < 0 ) && ( range->n1 < (input_full_size-1) ) )-    {-      int marg = -range->n0;-      if ( ( input_full_size - marg - STBIR__MERGE_RUNS_PIXEL_THRESHOLD - 1 ) <= range->n1 )-        range->n1 = input_full_size - 1;-    }-  }-  else-  {-    // for non-edge-wrap modes, we never read over the edge, so clamp-    if ( range->n0 < 0 )-      range->n0 = 0;-    if ( range->n1 >= input_full_size )-      range->n1 = input_full_size - 1;-  }-}--static void stbir__get_split_info( stbir__per_split_info* split_info, int splits, int output_height, int vertical_pixel_margin, int input_full_height )-{-  int i, cur;-  int left = output_height;--  cur = 0;-  for( i = 0 ; i < splits ; i++ )-  {-    int each; -    split_info[i].start_output_y = cur;-    each = left / ( splits - i );-    split_info[i].end_output_y = cur + each;-    cur += each;-    left -= each;--    // scatter range (updated to minimum as you run it)-    split_info[i].start_input_y = -vertical_pixel_margin;-    split_info[i].end_input_y = input_full_height + vertical_pixel_margin;-  }-}--static void stbir__free_internal_mem( stbir__info *info )-{-  #define STBIR__FREE_AND_CLEAR( ptr ) { if ( ptr ) { void * p = (ptr); (ptr) = 0; STBIR_FREE( p, info->user_data); } }-  -  if ( info )-  {-  #ifndef STBIR__SEPARATE_ALLOCATIONS-    STBIR__FREE_AND_CLEAR( info->alloced_mem );-  #else-    int i,j;--    if ( ( info->vertical.gather_prescatter_contributors ) && ( (void*)info->vertical.gather_prescatter_contributors != (void*)info->split_info[0].decode_buffer ) )-    {-      STBIR__FREE_AND_CLEAR( info->vertical.gather_prescatter_coefficients );-      STBIR__FREE_AND_CLEAR( info->vertical.gather_prescatter_contributors );-    }-    for( i = 0 ; i < info->splits ; i++ )-    {-      for( j = 0 ; j < info->alloc_ring_buffer_num_entries ; j++ )-      {-        #ifdef STBIR_SIMD8-        if ( info->effective_channels == 3 ) -          --info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer-        #endif  -        STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers[j] );-      }--      #ifdef STBIR_SIMD8-      if ( info->effective_channels == 3 ) -        --info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer-      #endif  -      STBIR__FREE_AND_CLEAR( info->split_info[i].decode_buffer );-      STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers );-      STBIR__FREE_AND_CLEAR( info->split_info[i].vertical_buffer );-    }-    STBIR__FREE_AND_CLEAR( info->split_info );-    if ( info->vertical.coefficients != info->horizontal.coefficients )-    {-      STBIR__FREE_AND_CLEAR( info->vertical.coefficients );-      STBIR__FREE_AND_CLEAR( info->vertical.contributors );-    }-    STBIR__FREE_AND_CLEAR( info->horizontal.coefficients );-    STBIR__FREE_AND_CLEAR( info->horizontal.contributors );-    STBIR__FREE_AND_CLEAR( info->alloced_mem );-    STBIR__FREE_AND_CLEAR( info );-  #endif-  }-  -  #undef STBIR__FREE_AND_CLEAR-}--static int stbir__get_max_split( int splits, int height )-{-  int i;-  int max = 0;--  for( i = 0 ; i < splits ; i++ )-  {-    int each = height / ( splits - i );-    if ( each > max ) -      max = each;-    height -= each;-  }-  return max;-}--static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_n_coeffs_funcs[8] = -{ -  0, stbir__horizontal_gather_1_channels_with_n_coeffs_funcs, stbir__horizontal_gather_2_channels_with_n_coeffs_funcs, stbir__horizontal_gather_3_channels_with_n_coeffs_funcs, stbir__horizontal_gather_4_channels_with_n_coeffs_funcs, 0,0, stbir__horizontal_gather_7_channels_with_n_coeffs_funcs-};--static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_channels_funcs[8] = -{ -  0, stbir__horizontal_gather_1_channels_funcs, stbir__horizontal_gather_2_channels_funcs, stbir__horizontal_gather_3_channels_funcs, stbir__horizontal_gather_4_channels_funcs, 0,0, stbir__horizontal_gather_7_channels_funcs-};--// there are six resize classifications: 0 == vertical scatter, 1 == vertical gather < 1x scale, 2 == vertical gather 1x-2x scale, 4 == vertical gather < 3x scale, 4 == vertical gather > 3x scale, 5 == <=4 pixel height, 6 == <=4 pixel wide column-#define STBIR_RESIZE_CLASSIFICATIONS 8--static float stbir__compute_weights[5][STBIR_RESIZE_CLASSIFICATIONS][4]=  // 5 = 0=1chan, 1=2chan, 2=3chan, 3=4chan, 4=7chan-{-  {-    { 1.00000f, 1.00000f, 0.31250f, 1.00000f },-    { 0.56250f, 0.59375f, 0.00000f, 0.96875f },-    { 1.00000f, 0.06250f, 0.00000f, 1.00000f },-    { 0.00000f, 0.09375f, 1.00000f, 1.00000f },-    { 1.00000f, 1.00000f, 1.00000f, 1.00000f },-    { 0.03125f, 0.12500f, 1.00000f, 1.00000f },-    { 0.06250f, 0.12500f, 0.00000f, 1.00000f },-    { 0.00000f, 1.00000f, 0.00000f, 0.03125f },-  }, {-    { 0.00000f, 0.84375f, 0.00000f, 0.03125f },-    { 0.09375f, 0.93750f, 0.00000f, 0.78125f },-    { 0.87500f, 0.21875f, 0.00000f, 0.96875f },-    { 0.09375f, 0.09375f, 1.00000f, 1.00000f },-    { 1.00000f, 1.00000f, 1.00000f, 1.00000f },-    { 0.03125f, 0.12500f, 1.00000f, 1.00000f },-    { 0.06250f, 0.12500f, 0.00000f, 1.00000f },-    { 0.00000f, 1.00000f, 0.00000f, 0.53125f },-  }, {-    { 0.00000f, 0.53125f, 0.00000f, 0.03125f },-    { 0.06250f, 0.96875f, 0.00000f, 0.53125f },-    { 0.87500f, 0.18750f, 0.00000f, 0.93750f },-    { 0.00000f, 0.09375f, 1.00000f, 1.00000f },-    { 1.00000f, 1.00000f, 1.00000f, 1.00000f },-    { 0.03125f, 0.12500f, 1.00000f, 1.00000f },-    { 0.06250f, 0.12500f, 0.00000f, 1.00000f },-    { 0.00000f, 1.00000f, 0.00000f, 0.56250f },-  }, {-    { 0.00000f, 0.50000f, 0.00000f, 0.71875f },-    { 0.06250f, 0.84375f, 0.00000f, 0.87500f },-    { 1.00000f, 0.50000f, 0.50000f, 0.96875f },-    { 1.00000f, 0.09375f, 0.31250f, 0.50000f },-    { 1.00000f, 1.00000f, 1.00000f, 1.00000f },-    { 1.00000f, 0.03125f, 0.03125f, 0.53125f },-    { 0.18750f, 0.12500f, 0.00000f, 1.00000f },-    { 0.00000f, 1.00000f, 0.03125f, 0.18750f },-  }, {-    { 0.00000f, 0.59375f, 0.00000f, 0.96875f },-    { 0.06250f, 0.81250f, 0.06250f, 0.59375f },-    { 0.75000f, 0.43750f, 0.12500f, 0.96875f },-    { 0.87500f, 0.06250f, 0.18750f, 0.43750f },-    { 1.00000f, 1.00000f, 1.00000f, 1.00000f },-    { 0.15625f, 0.12500f, 1.00000f, 1.00000f },-    { 0.06250f, 0.12500f, 0.00000f, 1.00000f },-    { 0.00000f, 1.00000f, 0.03125f, 0.34375f },-  }-};--// structure that allow us to query and override info for training the costs-typedef struct STBIR__V_FIRST_INFO-{-  double v_cost, h_cost;-  int control_v_first; // 0 = no control, 1 = force hori, 2 = force vert-  int v_first;-  int v_resize_classification;-  int is_gather;-} STBIR__V_FIRST_INFO;--#ifdef STBIR__V_FIRST_INFO_BUFFER-static STBIR__V_FIRST_INFO STBIR__V_FIRST_INFO_BUFFER = {0};-#define STBIR__V_FIRST_INFO_POINTER &STBIR__V_FIRST_INFO_BUFFER-#else-#define STBIR__V_FIRST_INFO_POINTER 0-#endif--// Figure out whether to scale along the horizontal or vertical first.-//   This only *super* important when you are scaling by a massively -//   different amount in the vertical vs the horizontal (for example, if -//   you are scaling by 2x in the width, and 0.5x in the height, then you -//   want to do the vertical scale first, because it's around 3x faster -//   in that order.-//-//   In more normal circumstances, this makes a 20-40% differences, so -//     it's good to get right, but not critical. The normal way that you-//     decide which direction goes first is just figuring out which -//     direction does more multiplies. But with modern CPUs with their -//     fancy caches and SIMD and high IPC abilities, so there's just a lot-//     more that goes into it. -//-//   My handwavy sort of solution is to have an app that does a whole -//     bunch of timing for both vertical and horizontal first modes,-//     and then another app that can read lots of these timing files-//     and try to search for the best weights to use. Dotimings.c-//     is the app that does a bunch of timings, and vf_train.c is the-//     app that solves for the best weights (and shows how well it -//     does currently).--static int stbir__should_do_vertical_first( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int horizontal_filter_pixel_width, float horizontal_scale, int horizontal_output_size, int vertical_filter_pixel_width, float vertical_scale, int vertical_output_size, int is_gather, STBIR__V_FIRST_INFO * info )    -{-  double v_cost, h_cost;-  float * weights;-  int vertical_first;-  int v_classification;--  // categorize the resize into buckets-  if ( ( vertical_output_size <= 4 ) || ( horizontal_output_size <= 4 ) )-    v_classification = ( vertical_output_size < horizontal_output_size ) ? 6 : 7;-  else if ( vertical_scale <= 1.0f )-    v_classification = ( is_gather ) ? 1 : 0;-  else if ( vertical_scale <= 2.0f) -    v_classification = 2;-  else if ( vertical_scale <= 3.0f) -    v_classification = 3;-  else if ( vertical_scale <= 4.0f) -    v_classification = 5;-  else -    v_classification = 6;-  -  // use the right weights-  weights = weights_table[ v_classification ];--  // this is the costs when you don't take into account modern CPUs with high ipc and simd and caches - wish we had a better estimate-  h_cost = (float)horizontal_filter_pixel_width * weights[0] + horizontal_scale * (float)vertical_filter_pixel_width * weights[1];-  v_cost = (float)vertical_filter_pixel_width  * weights[2] + vertical_scale * (float)horizontal_filter_pixel_width * weights[3];--  // use computation estimate to decide vertical first or not-  vertical_first = ( v_cost <= h_cost ) ? 1 : 0;--  // save these, if requested-  if ( info )-  {-    info->h_cost = h_cost;-    info->v_cost = v_cost;-    info->v_resize_classification = v_classification;-    info->v_first = vertical_first;-    info->is_gather = is_gather;-  }--  // and this allows us to override everything for testing (see dotiming.c) -  if ( ( info ) && ( info->control_v_first ) ) -    vertical_first = ( info->control_v_first == 2 ) ? 1 : 0;-  -  return vertical_first;-}--// layout lookups - must match stbir_internal_pixel_layout-static unsigned char stbir__pixel_channels[] = {-  1,2,3,3,4,   // 1ch, 2ch, rgb, bgr, 4ch-  4,4,4,4,2,2, // RGBA,BGRA,ARGB,ABGR,RA,AR-  4,4,4,4,2,2, // RGBA_PM,BGRA_PM,ARGB_PM,ABGR_PM,RA_PM,AR_PM-};--// the internal pixel layout enums are in a different order, so we can easily do range comparisons of types-//   the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible -static stbir_internal_pixel_layout stbir__pixel_layout_convert_public_to_internal[] = {-  STBIRI_BGR, STBIRI_1CHANNEL, STBIRI_2CHANNEL, STBIRI_RGB, STBIRI_RGBA, -  STBIRI_4CHANNEL, STBIRI_BGRA, STBIRI_ARGB, STBIRI_ABGR, STBIRI_RA, STBIRI_AR,-  STBIRI_RGBA_PM, STBIRI_BGRA_PM, STBIRI_ARGB_PM, STBIRI_ABGR_PM, STBIRI_RA_PM, STBIRI_AR_PM,-};--static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sampler * horizontal, stbir__sampler * vertical, stbir__contributors * conservative, stbir_pixel_layout input_pixel_layout_public, stbir_pixel_layout output_pixel_layout_public, int splits, int new_x, int new_y, int fast_alpha, void * user_data STBIR_ONLY_PROFILE_BUILD_GET_INFO )-{-  static char stbir_channel_count_index[8]={ 9,0,1,2, 3,9,9,4 };--  stbir__info * info = 0;-  void * alloced = 0;-  int alloced_total = 0;-  int vertical_first;-  int decode_buffer_size, ring_buffer_length_bytes, ring_buffer_size, vertical_buffer_size, alloc_ring_buffer_num_entries;--  int alpha_weighting_type = 0; // 0=none, 1=simple, 2=fancy-  int conservative_split_output_size = stbir__get_max_split( splits, vertical->scale_info.output_sub_size ); -  stbir_internal_pixel_layout input_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ input_pixel_layout_public ];  -  stbir_internal_pixel_layout output_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ output_pixel_layout_public ];-  int channels = stbir__pixel_channels[ input_pixel_layout ];      -  int effective_channels = channels;-  -  // first figure out what type of alpha weighting to use (if any)-  if ( ( horizontal->filter_enum != STBIR_FILTER_POINT_SAMPLE ) || ( vertical->filter_enum != STBIR_FILTER_POINT_SAMPLE ) ) // no alpha weighting on point sampling-  {-    if ( ( input_pixel_layout >= STBIRI_RGBA ) && ( input_pixel_layout <= STBIRI_AR ) && ( output_pixel_layout >= STBIRI_RGBA ) && ( output_pixel_layout <= STBIRI_AR ) )-    {-      if ( fast_alpha )-      {-        alpha_weighting_type = 4;-      }-      else-      {-        static int fancy_alpha_effective_cnts[6] = { 7, 7, 7, 7, 3, 3 };-        alpha_weighting_type = 2;-        effective_channels = fancy_alpha_effective_cnts[ input_pixel_layout - STBIRI_RGBA ];-      }-    }-    else if ( ( input_pixel_layout >= STBIRI_RGBA_PM ) && ( input_pixel_layout <= STBIRI_AR_PM ) && ( output_pixel_layout >= STBIRI_RGBA ) && ( output_pixel_layout <= STBIRI_AR ) )-    {-      // input premult, output non-premult-      alpha_weighting_type = 3;-    }-    else if ( ( input_pixel_layout >= STBIRI_RGBA ) && ( input_pixel_layout <= STBIRI_AR ) && ( output_pixel_layout >= STBIRI_RGBA_PM ) && ( output_pixel_layout <= STBIRI_AR_PM ) )-    {-      // input non-premult, output premult-      alpha_weighting_type = 1;-    }-  }--  // channel in and out count must match currently-  if ( channels != stbir__pixel_channels[ output_pixel_layout ] )-    return 0;--  // get vertical first-  vertical_first = stbir__should_do_vertical_first( stbir__compute_weights[ (int)stbir_channel_count_index[ effective_channels ] ], horizontal->filter_pixel_width, horizontal->scale_info.scale, horizontal->scale_info.output_sub_size, vertical->filter_pixel_width, vertical->scale_info.scale, vertical->scale_info.output_sub_size, vertical->is_gather, STBIR__V_FIRST_INFO_POINTER );--  // sometimes read one float off in some of the unrolled loops (with a weight of zero coeff, so it doesn't have an effect)-  decode_buffer_size = ( conservative->n1 - conservative->n0 + 1 ) * effective_channels * sizeof(float) + sizeof(float); // extra float for padding-  -#if defined( STBIR__SEPARATE_ALLOCATIONS ) && defined(STBIR_SIMD8)-  if ( effective_channels == 3 )-    decode_buffer_size += sizeof(float); // avx in 3 channel mode needs one float at the start of the buffer (only with separate allocations)-#endif  --  ring_buffer_length_bytes = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding--  // if we do vertical first, the ring buffer holds a whole decoded line-  if ( vertical_first )-    ring_buffer_length_bytes = ( decode_buffer_size + 15 ) & ~15;--  if ( ( ring_buffer_length_bytes & 4095 ) == 0 ) ring_buffer_length_bytes += 64*3; // avoid 4k alias--  // One extra entry because floating point precision problems sometimes cause an extra to be necessary.-  alloc_ring_buffer_num_entries = vertical->filter_pixel_width + 1;--  // we never need more ring buffer entries than the scanlines we're outputting when in scatter mode-  if ( ( !vertical->is_gather ) && ( alloc_ring_buffer_num_entries > conservative_split_output_size ) )-    alloc_ring_buffer_num_entries = conservative_split_output_size;--  ring_buffer_size = alloc_ring_buffer_num_entries * ring_buffer_length_bytes;--  // The vertical buffer is used differently, depending on whether we are scattering-  //   the vertical scanlines, or gathering them.-  //   If scattering, it's used at the temp buffer to accumulate each output.-  //   If gathering, it's just the output buffer.-  vertical_buffer_size = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float);  // extra float for padding--  // we make two passes through this loop, 1st to add everything up, 2nd to allocate and init-  for(;;)-  {-    int i;-    void * advance_mem = alloced;-    int copy_horizontal = 0;-    stbir__sampler * possibly_use_horizontal_for_pivot = 0;--#ifdef STBIR__SEPARATE_ALLOCATIONS-    #define STBIR__NEXT_PTR( ptr, size, ntype ) if ( alloced ) { void * p = STBIR_MALLOC( size, user_data); if ( p == 0 ) { stbir__free_internal_mem( info ); return 0; } (ptr) = (ntype*)p; }-#else-    #define STBIR__NEXT_PTR( ptr, size, ntype ) advance_mem = (void*) ( ( ((size_t)advance_mem) + 15 ) & ~15 ); if ( alloced ) ptr = (ntype*)advance_mem; advance_mem = ((char*)advance_mem) + (size);-#endif--    STBIR__NEXT_PTR( info, sizeof( stbir__info ), stbir__info );      --    STBIR__NEXT_PTR( info->split_info, sizeof( stbir__per_split_info ) * splits, stbir__per_split_info );      --    if ( info )-    {-      static stbir__alpha_weight_func * fancy_alpha_weights[6]  =    { stbir__fancy_alpha_weight_4ch,   stbir__fancy_alpha_weight_4ch,   stbir__fancy_alpha_weight_4ch,   stbir__fancy_alpha_weight_4ch,   stbir__fancy_alpha_weight_2ch,   stbir__fancy_alpha_weight_2ch };-      static stbir__alpha_unweight_func * fancy_alpha_unweights[6] = { stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_2ch, stbir__fancy_alpha_unweight_2ch };-      static stbir__alpha_weight_func * simple_alpha_weights[6] = { stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_2ch, stbir__simple_alpha_weight_2ch };-      static stbir__alpha_unweight_func * simple_alpha_unweights[6] = { stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_2ch, stbir__simple_alpha_unweight_2ch };--      // initialize info fields-      info->alloced_mem = alloced;-      info->alloced_total = alloced_total;--      info->channels = channels;-      info->effective_channels = effective_channels;-  -      info->offset_x = new_x;-      info->offset_y = new_y;-      info->alloc_ring_buffer_num_entries = alloc_ring_buffer_num_entries;-      info->ring_buffer_num_entries = 0;  -      info->ring_buffer_length_bytes = ring_buffer_length_bytes;-      info->splits = splits;-      info->vertical_first = vertical_first;--      info->input_pixel_layout_internal = input_pixel_layout;  -      info->output_pixel_layout_internal = output_pixel_layout;--      // setup alpha weight functions-      info->alpha_weight = 0;-      info->alpha_unweight = 0;-    -      // handle alpha weighting functions and overrides-      if ( alpha_weighting_type == 2 )-      {-        // high quality alpha multiplying on the way in, dividing on the way out-        info->alpha_weight = fancy_alpha_weights[ input_pixel_layout - STBIRI_RGBA ];  -        info->alpha_unweight = fancy_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ];-      }-      else if ( alpha_weighting_type == 4 )-      {-        // fast alpha multiplying on the way in, dividing on the way out-        info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ];  -        info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ];-      }-      else if ( alpha_weighting_type == 1 )-      {-        // fast alpha on the way in, leave in premultiplied form on way out-        info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; -      }-      else if ( alpha_weighting_type == 3 )-      {-        // incoming is premultiplied, fast alpha dividing on the way out - non-premultiplied output-        info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ];-      }--      // handle 3-chan color flipping, using the alpha weight path-      if ( ( ( input_pixel_layout == STBIRI_RGB ) && ( output_pixel_layout == STBIRI_BGR ) ) ||-           ( ( input_pixel_layout == STBIRI_BGR ) && ( output_pixel_layout == STBIRI_RGB ) ) )-      {-        // do the flipping on the smaller of the two ends-        if ( horizontal->scale_info.scale < 1.0f )-          info->alpha_unweight = stbir__simple_flip_3ch;-        else-          info->alpha_weight = stbir__simple_flip_3ch;-      }--    }        --    // get all the per-split buffers-    for( i = 0 ; i < splits ; i++ )-    {-      STBIR__NEXT_PTR( info->split_info[i].decode_buffer, decode_buffer_size, float );--#ifdef STBIR__SEPARATE_ALLOCATIONS--      #ifdef STBIR_SIMD8-      if ( ( info ) && ( effective_channels == 3 ) )-        ++info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer-      #endif  --      STBIR__NEXT_PTR( info->split_info[i].ring_buffers, alloc_ring_buffer_num_entries * sizeof(float*), float* );-      {-        int j;-        for( j = 0 ; j < alloc_ring_buffer_num_entries ; j++ )-        {-          STBIR__NEXT_PTR( info->split_info[i].ring_buffers[j], ring_buffer_length_bytes, float );-          #ifdef STBIR_SIMD8-          if ( ( info ) && ( effective_channels == 3 ) )-            ++info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer-          #endif  -        }-      }-#else-      STBIR__NEXT_PTR( info->split_info[i].ring_buffer, ring_buffer_size, float );-#endif-      STBIR__NEXT_PTR( info->split_info[i].vertical_buffer, vertical_buffer_size, float );-    }--    // alloc memory for to-be-pivoted coeffs (if necessary)-    if ( vertical->is_gather == 0 )-    {-      int both;-      int temp_mem_amt;--      // when in vertical scatter mode, we first build the coefficients in gather mode, and then pivot after,-      //   that means we need two buffers, so we try to use the decode buffer and ring buffer for this. if that-      //   is too small, we just allocate extra memory to use as this temp.--      both = vertical->gather_prescatter_contributors_size + vertical->gather_prescatter_coefficients_size;--#ifdef STBIR__SEPARATE_ALLOCATIONS-      temp_mem_amt = decode_buffer_size;-#else-      temp_mem_amt = ( decode_buffer_size + ring_buffer_size + vertical_buffer_size ) * splits;-#endif-      if ( temp_mem_amt >= both )-      {-        if ( info ) -        { -          vertical->gather_prescatter_contributors = (stbir__contributors*)info->split_info[0].decode_buffer; -          vertical->gather_prescatter_coefficients = (float*) ( ( (char*)info->split_info[0].decode_buffer ) + vertical->gather_prescatter_contributors_size ); -        }-      }-      else-      {-        // ring+decode memory is too small, so allocate temp memory-        STBIR__NEXT_PTR( vertical->gather_prescatter_contributors, vertical->gather_prescatter_contributors_size, stbir__contributors );-        STBIR__NEXT_PTR( vertical->gather_prescatter_coefficients, vertical->gather_prescatter_coefficients_size, float );-      }-    }--    STBIR__NEXT_PTR( horizontal->contributors, horizontal->contributors_size, stbir__contributors );-    STBIR__NEXT_PTR( horizontal->coefficients, horizontal->coefficients_size, float );--    // are the two filters identical?? (happens a lot with mipmap generation)-    if ( ( horizontal->filter_kernel == vertical->filter_kernel ) && ( horizontal->filter_support == vertical->filter_support ) && ( horizontal->edge == vertical->edge ) && ( horizontal->scale_info.output_sub_size == vertical->scale_info.output_sub_size ) )-    {-      float diff_scale = horizontal->scale_info.scale - vertical->scale_info.scale;-      float diff_shift = horizontal->scale_info.pixel_shift - vertical->scale_info.pixel_shift;-      if ( diff_scale < 0.0f ) diff_scale = -diff_scale;-      if ( diff_shift < 0.0f ) diff_shift = -diff_shift;-      if ( ( diff_scale <= stbir__small_float ) && ( diff_shift <= stbir__small_float ) )-      {-        if ( horizontal->is_gather == vertical->is_gather ) -        {-          copy_horizontal = 1;-          goto no_vert_alloc;-        }-        // everything matches, but vertical is scatter, horizontal is gather, use horizontal coeffs for vertical pivot coeffs-        possibly_use_horizontal_for_pivot = horizontal;-      }-    }--    STBIR__NEXT_PTR( vertical->contributors, vertical->contributors_size, stbir__contributors );-    STBIR__NEXT_PTR( vertical->coefficients, vertical->coefficients_size, float );--   no_vert_alloc:--    if ( info )-    {-      STBIR_PROFILE_BUILD_START( horizontal );--      stbir__calculate_filters( horizontal, 0, user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO );--      // setup the horizontal gather functions-      // start with defaulting to the n_coeffs functions (specialized on channels and remnant leftover)-      info->horizontal_gather_channels = stbir__horizontal_gather_n_coeffs_funcs[ effective_channels ][ horizontal->extent_info.widest & 3 ];-      // but if the number of coeffs <= 12, use another set of special cases. <=12 coeffs is any enlarging resize, or shrinking resize down to about 1/3 size-      if ( horizontal->extent_info.widest <= 12 )-        info->horizontal_gather_channels = stbir__horizontal_gather_channels_funcs[ effective_channels ][ horizontal->extent_info.widest - 1 ];-      -      info->scanline_extents.conservative.n0 = conservative->n0;-      info->scanline_extents.conservative.n1 = conservative->n1;-      -      // get exact extents-      stbir__get_extents( horizontal, &info->scanline_extents );--      // pack the horizontal coeffs-      horizontal->coefficient_width = stbir__pack_coefficients(horizontal->num_contributors, horizontal->contributors, horizontal->coefficients, horizontal->coefficient_width, horizontal->extent_info.widest, info->scanline_extents.conservative.n1 + 1 );-      -      STBIR_MEMCPY( &info->horizontal, horizontal, sizeof( stbir__sampler ) );--      STBIR_PROFILE_BUILD_END( horizontal );--      if ( copy_horizontal )-      {-        STBIR_MEMCPY( &info->vertical, horizontal, sizeof( stbir__sampler ) );-      }-      else-      {-        STBIR_PROFILE_BUILD_START( vertical );--        stbir__calculate_filters( vertical, possibly_use_horizontal_for_pivot, user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO );-        STBIR_MEMCPY( &info->vertical, vertical, sizeof( stbir__sampler ) );--        STBIR_PROFILE_BUILD_END( vertical );-      }--      // setup the vertical split ranges-      stbir__get_split_info( info->split_info, info->splits, info->vertical.scale_info.output_sub_size, info->vertical.filter_pixel_margin, info->vertical.scale_info.input_full_size );--      // now we know precisely how many entries we need-      info->ring_buffer_num_entries = info->vertical.extent_info.widest;--      // we never need more ring buffer entries than the scanlines we're outputting-      if ( ( !info->vertical.is_gather ) && ( info->ring_buffer_num_entries > conservative_split_output_size ) )-        info->ring_buffer_num_entries = conservative_split_output_size;-      STBIR_ASSERT( info->ring_buffer_num_entries <= info->alloc_ring_buffer_num_entries );--      // a few of the horizontal gather functions read one dword past the end (but mask it out), so put in a normal value so no snans or denormals accidentally sneak in-      for( i = 0 ; i < splits ; i++ )-      {-        int width, ofs;-        -        // find the right most span-        if ( info->scanline_extents.spans[0].n1 > info->scanline_extents.spans[1].n1 )-          width = info->scanline_extents.spans[0].n1 - info->scanline_extents.spans[0].n0;-        else-          width = info->scanline_extents.spans[1].n1 - info->scanline_extents.spans[1].n0;-        -        // this calc finds the exact end of the decoded scanline for all filter modes.-        //   usually this is just the width * effective channels.  But we have to account -        //   for the area to the left of the scanline for wrap filtering and alignment, this -        //   is stored as a negative value in info->scanline_extents.conservative.n0. Next,-        //   we need to skip the exact size of the right hand size filter area (again for-        //   wrap mode), this is in info->scanline_extents.edge_sizes[1]).-        ofs = ( width + 1 - info->scanline_extents.conservative.n0 + info->scanline_extents.edge_sizes[1] ) * effective_channels;-        -        // place a known, but numerically valid value in the decode buffer-        info->split_info[i].decode_buffer[ ofs ] = 9999.0f;--        // if vertical filtering first, place a known, but numerically valid value in the all-        //   of the ring buffer accumulators-        if ( vertical_first )-        {-          int j;  -          for( j = 0; j < info->ring_buffer_num_entries ; j++ )-          {-            stbir__get_ring_buffer_entry( info, info->split_info + i, j )[ ofs ] = 9999.0f;-          }-        }-      }-    }--    #undef STBIR__NEXT_PTR---    // is this the first time through loop?-    if ( info == 0 )-    {-      alloced_total = (int) ( 15 + (size_t)advance_mem );-      alloced = STBIR_MALLOC( alloced_total, user_data );-      if ( alloced == 0 )-        return 0;-    }-    else-      return info;  // success-  }-}--static int stbir__perform_resize( stbir__info const * info, int split_start, int split_count ) -{-  stbir__per_split_info * split_info = info->split_info + split_start;--  STBIR_PROFILE_CLEAR_EXTRAS();--  STBIR_PROFILE_FIRST_START( looping );-  if (info->vertical.is_gather)-    stbir__vertical_gather_loop( info, split_info, split_count );-  else-    stbir__vertical_scatter_loop( info, split_info, split_count );-  STBIR_PROFILE_END( looping );--  return 1;-}--static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * resize )-{-  static stbir__decode_pixels_func * decode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]=-  {-    /* 1ch-4ch */ stbir__decode_uint8_srgb, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear, -  };--  static stbir__decode_pixels_func * decode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]=-  {-    { /* RGBA */ stbir__decode_uint8_srgb4_linearalpha,      stbir__decode_uint8_srgb,      0, stbir__decode_float_linear,      stbir__decode_half_float_linear },-    { /* BGRA */ stbir__decode_uint8_srgb4_linearalpha_BGRA, stbir__decode_uint8_srgb_BGRA, 0, stbir__decode_float_linear_BGRA, stbir__decode_half_float_linear_BGRA },-    { /* ARGB */ stbir__decode_uint8_srgb4_linearalpha_ARGB, stbir__decode_uint8_srgb_ARGB, 0, stbir__decode_float_linear_ARGB, stbir__decode_half_float_linear_ARGB },-    { /* ABGR */ stbir__decode_uint8_srgb4_linearalpha_ABGR, stbir__decode_uint8_srgb_ABGR, 0, stbir__decode_float_linear_ABGR, stbir__decode_half_float_linear_ABGR },-    { /* RA   */ stbir__decode_uint8_srgb2_linearalpha,      stbir__decode_uint8_srgb,      0, stbir__decode_float_linear,      stbir__decode_half_float_linear },-    { /* AR   */ stbir__decode_uint8_srgb2_linearalpha_AR,   stbir__decode_uint8_srgb_AR,   0, stbir__decode_float_linear_AR,   stbir__decode_half_float_linear_AR },-  };--  static stbir__decode_pixels_func * decode_simple_scaled_or_not[2][2]=-  {-    { stbir__decode_uint8_linear_scaled,  stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear },-  };--  static stbir__decode_pixels_func * decode_alphas_scaled_or_not[STBIRI_AR-STBIRI_RGBA+1][2][2]=-  {-    { /* RGBA */ { stbir__decode_uint8_linear_scaled,       stbir__decode_uint8_linear },      { stbir__decode_uint16_linear_scaled,      stbir__decode_uint16_linear } },-    { /* BGRA */ { stbir__decode_uint8_linear_scaled_BGRA,  stbir__decode_uint8_linear_BGRA }, { stbir__decode_uint16_linear_scaled_BGRA, stbir__decode_uint16_linear_BGRA } },-    { /* ARGB */ { stbir__decode_uint8_linear_scaled_ARGB,  stbir__decode_uint8_linear_ARGB }, { stbir__decode_uint16_linear_scaled_ARGB, stbir__decode_uint16_linear_ARGB } },-    { /* ABGR */ { stbir__decode_uint8_linear_scaled_ABGR,  stbir__decode_uint8_linear_ABGR }, { stbir__decode_uint16_linear_scaled_ABGR, stbir__decode_uint16_linear_ABGR } },-    { /* RA   */ { stbir__decode_uint8_linear_scaled,       stbir__decode_uint8_linear },      { stbir__decode_uint16_linear_scaled,      stbir__decode_uint16_linear } },-    { /* AR   */ { stbir__decode_uint8_linear_scaled_AR,    stbir__decode_uint8_linear_AR },   { stbir__decode_uint16_linear_scaled_AR,   stbir__decode_uint16_linear_AR } }-  };--  static stbir__encode_pixels_func * encode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]=-  {-    /* 1ch-4ch */ stbir__encode_uint8_srgb, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear,-  };--  static stbir__encode_pixels_func * encode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]=-  {-    { /* RGBA */ stbir__encode_uint8_srgb4_linearalpha,      stbir__encode_uint8_srgb,      0, stbir__encode_float_linear,      stbir__encode_half_float_linear },-    { /* BGRA */ stbir__encode_uint8_srgb4_linearalpha_BGRA, stbir__encode_uint8_srgb_BGRA, 0, stbir__encode_float_linear_BGRA, stbir__encode_half_float_linear_BGRA },-    { /* ARGB */ stbir__encode_uint8_srgb4_linearalpha_ARGB, stbir__encode_uint8_srgb_ARGB, 0, stbir__encode_float_linear_ARGB, stbir__encode_half_float_linear_ARGB },-    { /* ABGR */ stbir__encode_uint8_srgb4_linearalpha_ABGR, stbir__encode_uint8_srgb_ABGR, 0, stbir__encode_float_linear_ABGR, stbir__encode_half_float_linear_ABGR },-    { /* RA   */ stbir__encode_uint8_srgb2_linearalpha,      stbir__encode_uint8_srgb,      0, stbir__encode_float_linear,      stbir__encode_half_float_linear },-    { /* AR   */ stbir__encode_uint8_srgb2_linearalpha_AR,   stbir__encode_uint8_srgb_AR,   0, stbir__encode_float_linear_AR,   stbir__encode_half_float_linear_AR }-  };--  static stbir__encode_pixels_func * encode_simple_scaled_or_not[2][2]=-  {-    { stbir__encode_uint8_linear_scaled,  stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear },-  };--  static stbir__encode_pixels_func * encode_alphas_scaled_or_not[STBIRI_AR-STBIRI_RGBA+1][2][2]=-  {-    { /* RGBA */ { stbir__encode_uint8_linear_scaled,       stbir__encode_uint8_linear },       { stbir__encode_uint16_linear_scaled,      stbir__encode_uint16_linear } },-    { /* BGRA */ { stbir__encode_uint8_linear_scaled_BGRA,  stbir__encode_uint8_linear_BGRA },  { stbir__encode_uint16_linear_scaled_BGRA, stbir__encode_uint16_linear_BGRA } },-    { /* ARGB */ { stbir__encode_uint8_linear_scaled_ARGB,  stbir__encode_uint8_linear_ARGB },  { stbir__encode_uint16_linear_scaled_ARGB, stbir__encode_uint16_linear_ARGB } },-    { /* ABGR */ { stbir__encode_uint8_linear_scaled_ABGR,  stbir__encode_uint8_linear_ABGR },  { stbir__encode_uint16_linear_scaled_ABGR, stbir__encode_uint16_linear_ABGR } },-    { /* RA   */ { stbir__encode_uint8_linear_scaled,       stbir__encode_uint8_linear },       { stbir__encode_uint16_linear_scaled,      stbir__encode_uint16_linear } },-    { /* AR   */ { stbir__encode_uint8_linear_scaled_AR,    stbir__encode_uint8_linear_AR },    { stbir__encode_uint16_linear_scaled_AR,   stbir__encode_uint16_linear_AR } }-  };--  stbir__decode_pixels_func * decode_pixels = 0;-  stbir__encode_pixels_func * encode_pixels = 0;-  stbir_datatype input_type, output_type;--  input_type = resize->input_data_type;-  output_type = resize->output_data_type; -  info->input_data = resize->input_pixels;-  info->input_stride_bytes = resize->input_stride_in_bytes;-  info->output_stride_bytes = resize->output_stride_in_bytes;--  // if we're completely point sampling, then we can turn off SRGB-  if ( ( info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( info->vertical.filter_enum == STBIR_FILTER_POINT_SAMPLE ) )-  {-    if ( ( ( input_type  == STBIR_TYPE_UINT8_SRGB ) || ( input_type  == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) && -         ( ( output_type == STBIR_TYPE_UINT8_SRGB ) || ( output_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) )-    {-      input_type = STBIR_TYPE_UINT8;-      output_type = STBIR_TYPE_UINT8;-    }-  }--  // recalc the output and input strides  -  if ( info->input_stride_bytes == 0 )-    info->input_stride_bytes = info->channels * info->horizontal.scale_info.input_full_size * stbir__type_size[input_type];--  if ( info->output_stride_bytes == 0 )-    info->output_stride_bytes = info->channels * info->horizontal.scale_info.output_sub_size * stbir__type_size[output_type];--  // calc offset-  info->output_data = ( (char*) resize->output_pixels ) + ( (ptrdiff_t) info->offset_y * (ptrdiff_t) resize->output_stride_in_bytes ) + ( info->offset_x * info->channels * stbir__type_size[output_type] );--  info->in_pixels_cb = resize->input_cb;-  info->user_data = resize->user_data;-  info->out_pixels_cb = resize->output_cb;--  // setup the input format converters-  if ( ( input_type == STBIR_TYPE_UINT8 ) || ( input_type == STBIR_TYPE_UINT16 ) )-  {-    int non_scaled = 0;--    // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16)-    if ( ( !info->alpha_weight ) && ( !info->alpha_unweight )  ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual)-      if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) )-        non_scaled = 1;--    if ( info->input_pixel_layout_internal <= STBIRI_4CHANNEL )-      decode_pixels = decode_simple_scaled_or_not[ input_type == STBIR_TYPE_UINT16 ][ non_scaled ];-    else-      decode_pixels = decode_alphas_scaled_or_not[ ( info->input_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ input_type == STBIR_TYPE_UINT16 ][ non_scaled ];-  }-  else-  {-    if ( info->input_pixel_layout_internal <= STBIRI_4CHANNEL )-      decode_pixels = decode_simple[ input_type - STBIR_TYPE_UINT8_SRGB ];-    else-      decode_pixels = decode_alphas[ ( info->input_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ input_type - STBIR_TYPE_UINT8_SRGB ];-  }--  // setup the output format converters-  if ( ( output_type == STBIR_TYPE_UINT8 ) || ( output_type == STBIR_TYPE_UINT16 ) )-  {-    int non_scaled = 0;-    -    // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16)-    if ( ( !info->alpha_weight ) && ( !info->alpha_unweight ) ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual)-      if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) )-        non_scaled = 1;--    if ( info->output_pixel_layout_internal <= STBIRI_4CHANNEL )-      encode_pixels = encode_simple_scaled_or_not[ output_type == STBIR_TYPE_UINT16 ][ non_scaled ];-    else-      encode_pixels = encode_alphas_scaled_or_not[ ( info->output_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ output_type == STBIR_TYPE_UINT16 ][ non_scaled ];-  }-  else-  {-    if ( info->output_pixel_layout_internal <= STBIRI_4CHANNEL )-      encode_pixels = encode_simple[ output_type - STBIR_TYPE_UINT8_SRGB ];-    else-      encode_pixels = encode_alphas[ ( info->output_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ output_type - STBIR_TYPE_UINT8_SRGB ];-  }--  info->input_type = input_type;-  info->output_type = output_type; -  info->decode_pixels = decode_pixels;-  info->encode_pixels = encode_pixels; -}--static void stbir__clip( int * outx, int * outsubw, int outw, double * u0, double * u1 )-{-  double per, adj;-  int over;-  -  // do left/top edge-  if ( *outx < 0 )-  {-    per = ( (double)*outx ) / ( (double)*outsubw ); // is negative-    adj = per * ( *u1 - *u0 );-    *u0 -= adj; // increases u0-    *outx = 0;-  }--  // do right/bot edge-  over = outw - ( *outx + *outsubw );-  if ( over < 0 )-  {-    per = ( (double)over ) / ( (double)*outsubw ); // is negative-    adj = per * ( *u1 - *u0 );-    *u1 += adj; // decrease u1-    *outsubw = outw - *outx;-  }-}    --// converts a double to a rational that has less than one float bit of error (returns 0 if unable to do so)-static int stbir__double_to_rational(double f, stbir_uint32 limit, stbir_uint32 *numer, stbir_uint32 *denom, int limit_denom ) // limit_denom (1) or limit numer (0)-{-  double err;-  stbir_uint64 top, bot;-  stbir_uint64 numer_last = 0;-  stbir_uint64 denom_last = 1;-  stbir_uint64 numer_estimate = 1;-  stbir_uint64 denom_estimate = 0;--  // scale to past float error range-  top = (stbir_uint64)( f * (double)(1 << 25) );-  bot = 1 << 25;--  // keep refining, but usually stops in a few loops - usually 5 for bad cases-  for(;;)  -  {-    stbir_uint64 est, temp;--    // hit limit, break out and do best full range estimate-    if ( ( ( limit_denom ) ? denom_estimate : numer_estimate ) >= limit )-      break;--    // is the current error less than 1 bit of a float? if so, we're done-    if ( denom_estimate )-    {-      err = ( (double)numer_estimate / (double)denom_estimate ) - f;-      if ( err < 0.0 ) err = -err;-      if ( err < ( 1.0 / (double)(1<<24) ) )-      {-        // yup, found it-        *numer = (stbir_uint32) numer_estimate;-        *denom = (stbir_uint32) denom_estimate;-        return 1;-      }-    }--    // no more refinement bits left? break out and do full range estimate-    if ( bot == 0 )-      break;--    // gcd the estimate bits-    est = top / bot;-    temp = top % bot;-    top = bot;-    bot = temp;--    // move remainders-    temp = est * denom_estimate + denom_last; -    denom_last = denom_estimate; -    denom_estimate = temp;--    // move remainders-    temp = est * numer_estimate + numer_last; -    numer_last = numer_estimate; -    numer_estimate = temp;-  }--  // we didn't fine anything good enough for float, use a full range estimate-  if ( limit_denom )-  {-    numer_estimate= (stbir_uint64)( f * (double)limit + 0.5 );-    denom_estimate = limit;-  }-  else-  {-    numer_estimate = limit;-    denom_estimate = (stbir_uint64)( ( (double)limit / f ) + 0.5 );-  }--  *numer = (stbir_uint32) numer_estimate;-  *denom = (stbir_uint32) denom_estimate;--  err = ( denom_estimate ) ? ( ( (double)(stbir_uint32)numer_estimate / (double)(stbir_uint32)denom_estimate ) - f ) : 1.0;-  if ( err < 0.0 ) err = -err;-  return ( err < ( 1.0 / (double)(1<<24) ) ) ? 1 : 0;-}--static int stbir__calculate_region_transform( stbir__scale_info * scale_info, int output_full_range, int * output_offset, int output_sub_range, int input_full_range, double input_s0, double input_s1 )-{-  double output_range, input_range, output_s, input_s, ratio, scale;--  input_s = input_s1 - input_s0;--  // null area-  if ( ( output_full_range == 0 ) || ( input_full_range == 0 ) ||-       ( output_sub_range == 0 ) || ( input_s <= stbir__small_float ) )-    return 0;--  // are either of the ranges completely out of bounds?-  if ( ( *output_offset >= output_full_range ) || ( ( *output_offset + output_sub_range ) <= 0 ) || ( input_s0 >= (1.0f-stbir__small_float) ) || ( input_s1 <= stbir__small_float ) )-    return 0;--  output_range = (double)output_full_range;-  input_range = (double)input_full_range;--  output_s = ( (double)output_sub_range) / output_range;--  // figure out the scaling to use -  ratio = output_s / input_s; --  // save scale before clipping-  scale = ( output_range / input_range ) * ratio; -  scale_info->scale = (float)scale;-  scale_info->inv_scale = (float)( 1.0 / scale );--  // clip output area to left/right output edges (and adjust input area)-  stbir__clip( output_offset, &output_sub_range, output_full_range, &input_s0, &input_s1 );--  // recalc input area-  input_s = input_s1 - input_s0;--  // after clipping do we have zero input area?-  if ( input_s <= stbir__small_float ) -    return 0;--  // calculate and store the starting source offsets in output pixel space -  scale_info->pixel_shift = (float) ( input_s0 * ratio * output_range ); --  scale_info->scale_is_rational = stbir__double_to_rational( scale, ( scale <= 1.0 ) ? output_full_range : input_full_range, &scale_info->scale_numerator, &scale_info->scale_denominator, ( scale >= 1.0 ) );--  scale_info->input_full_size = input_full_range;-  scale_info->output_sub_size = output_sub_range;--  return 1;-}---static void stbir__init_and_set_layout( STBIR_RESIZE * resize, stbir_pixel_layout pixel_layout, stbir_datatype data_type )-{-  resize->input_cb = 0;-  resize->output_cb = 0;-  resize->user_data = resize;-  resize->samplers = 0;-  resize->needs_rebuild = 1;-  resize->called_alloc = 0;-  resize->horizontal_filter = STBIR_FILTER_DEFAULT;-  resize->horizontal_filter_kernel = 0; resize->horizontal_filter_support = 0;-  resize->vertical_filter = STBIR_FILTER_DEFAULT;-  resize->vertical_filter_kernel = 0; resize->vertical_filter_support = 0;-  resize->horizontal_edge = STBIR_EDGE_CLAMP;-  resize->vertical_edge = STBIR_EDGE_CLAMP;-  resize->input_s0 = 0; resize->input_t0 = 0; resize->input_s1 = 1; resize->input_t1 = 1;-  resize->output_subx = 0; resize->output_suby = 0; resize->output_subw = resize->output_w; resize->output_subh = resize->output_h;-  resize->input_data_type = data_type;-  resize->output_data_type = data_type;-  resize->input_pixel_layout_public = pixel_layout;-  resize->output_pixel_layout_public = pixel_layout;-}--STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize, -                                 const void *input_pixels,  int input_w,  int input_h, int input_stride_in_bytes, // stride can be zero-                                       void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero-                                 stbir_pixel_layout pixel_layout, stbir_datatype data_type )-{-  resize->input_pixels = input_pixels;-  resize->input_w = input_w;-  resize->input_h = input_h;-  resize->input_stride_in_bytes = input_stride_in_bytes;-  resize->output_pixels = output_pixels;-  resize->output_w = output_w;-  resize->output_h = output_h;-  resize->output_stride_in_bytes = output_stride_in_bytes;-  resize->fast_alpha = 0;--  stbir__init_and_set_layout( resize, pixel_layout, data_type );-}--// You can update parameters any time after resize_init-STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type )  // by default, datatype from resize_init-{-  resize->input_data_type = input_type;-  resize->output_data_type = output_type;-}--STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb )   // no callbacks by default-{-  resize->input_cb = input_cb;-  resize->output_cb = output_cb;-}--STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data )                                     // pass back STBIR_RESIZE* by default-{-  resize->user_data = user_data;-}--STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes )-{-  resize->input_pixels = input_pixels;-  resize->input_stride_in_bytes = input_stride_in_bytes;-  resize->output_pixels = output_pixels;-  resize->output_stride_in_bytes = output_stride_in_bytes;-}---STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge )       // CLAMP by default-{-  resize->horizontal_edge = horizontal_edge;-  resize->vertical_edge = vertical_edge;-  resize->needs_rebuild = 1;-  return 1;-}--STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ) // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default-{-  resize->horizontal_filter = horizontal_filter;-  resize->vertical_filter = vertical_filter;-  resize->needs_rebuild = 1;-  return 1;-}--STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support )-{-  resize->horizontal_filter_kernel = horizontal_filter; resize->horizontal_filter_support = horizontal_support;-  resize->vertical_filter_kernel = vertical_filter; resize->vertical_filter_support = vertical_support;-  resize->needs_rebuild = 1;-  return 1;-}--STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout input_pixel_layout, stbir_pixel_layout output_pixel_layout )   // sets new pixel layouts-{-  resize->input_pixel_layout_public = input_pixel_layout;-  resize->output_pixel_layout_public = output_pixel_layout;-  resize->needs_rebuild = 1;-  return 1;-}---STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, int non_pma_alpha_speed_over_quality )   // sets alpha speed-{-  resize->fast_alpha = non_pma_alpha_speed_over_quality;-  resize->needs_rebuild = 1;-  return 1;-}--STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 )                 // sets input region (full region by default)-{-  resize->input_s0 = s0;-  resize->input_t0 = t0;-  resize->input_s1 = s1;-  resize->input_t1 = t1;-  resize->needs_rebuild = 1;--  // are we inbounds?-  if ( ( s1 < stbir__small_float ) || ( (s1-s0) < stbir__small_float ) ||-       ( t1 < stbir__small_float ) || ( (t1-t0) < stbir__small_float ) ||-       ( s0 > (1.0f-stbir__small_float) ) ||-       ( t0 > (1.0f-stbir__small_float) ) )-    return 0;--  return 1;-}--STBIRDEF int stbir_set_output_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh )          // sets input region (full region by default)-{-  resize->output_subx = subx;-  resize->output_suby = suby;-  resize->output_subw = subw;-  resize->output_subh = subh;-  resize->needs_rebuild = 1;--  // are we inbounds?-  if ( ( subx >= resize->output_w ) || ( ( subx + subw ) <= 0 ) || ( suby >= resize->output_h ) || ( ( suby + subh ) <= 0 ) || ( subw == 0 ) || ( subh == 0 ) )-    return 0;--  return 1;-}--STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh )                 // sets both regions (full regions by default)-{-  double s0, t0, s1, t1;--  s0 = ( (double)subx ) / ( (double)resize->output_w );-  t0 = ( (double)suby ) / ( (double)resize->output_h );-  s1 = ( (double)(subx+subw) ) / ( (double)resize->output_w );-  t1 = ( (double)(suby+subh) ) / ( (double)resize->output_h );--  resize->input_s0 = s0;-  resize->input_t0 = t0;-  resize->input_s1 = s1;-  resize->input_t1 = t1;-  resize->output_subx = subx;-  resize->output_suby = suby;-  resize->output_subw = subw;-  resize->output_subh = subh;-  resize->needs_rebuild = 1;--  // are we inbounds?-  if ( ( subx >= resize->output_w ) || ( ( subx + subw ) <= 0 ) || ( suby >= resize->output_h ) || ( ( suby + subh ) <= 0 ) || ( subw == 0 ) || ( subh == 0 ) )-    return 0;--  return 1;-}--static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) -{-  stbir__contributors conservative = { 0, 0 };-  stbir__sampler horizontal, vertical;-  int new_output_subx, new_output_suby;-  stbir__info * out_info;-  #ifdef STBIR_PROFILE-  stbir__info profile_infod;  // used to contain building profile info before everything is allocated-  stbir__info * profile_info = &profile_infod;-  #endif--  // have we already built the samplers?-  if ( resize->samplers )-    return 0;-  -  #define STBIR_RETURN_ERROR_AND_ASSERT( exp )  STBIR_ASSERT( !(exp) ); if (exp) return 0;-  STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->horizontal_filter >= STBIR_FILTER_OTHER)-  STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->vertical_filter >= STBIR_FILTER_OTHER)-  #undef STBIR_RETURN_ERROR_AND_ASSERT--  if ( splits <= 0 ) -    return 0;--  STBIR_PROFILE_BUILD_FIRST_START( build );--  new_output_subx = resize->output_subx;-  new_output_suby = resize->output_suby;--  // do horizontal clip and scale calcs-  if ( !stbir__calculate_region_transform( &horizontal.scale_info, resize->output_w, &new_output_subx, resize->output_subw, resize->input_w, resize->input_s0, resize->input_s1 ) )-    return 0;--  // do vertical clip and scale calcs-  if ( !stbir__calculate_region_transform( &vertical.scale_info, resize->output_h, &new_output_suby, resize->output_subh, resize->input_h, resize->input_t0, resize->input_t1 ) )-    return 0;--  // if nothing to do, just return-  if ( ( horizontal.scale_info.output_sub_size == 0 ) || ( vertical.scale_info.output_sub_size == 0 ) )-    return 0;--  stbir__set_sampler(&horizontal, resize->horizontal_filter, resize->horizontal_filter_kernel, resize->horizontal_filter_support, resize->horizontal_edge, &horizontal.scale_info, 1, resize->user_data );-  stbir__get_conservative_extents( &horizontal, &conservative, resize->user_data );-  stbir__set_sampler(&vertical, resize->vertical_filter, resize->horizontal_filter_kernel, resize->vertical_filter_support, resize->vertical_edge, &vertical.scale_info, 0, resize->user_data );--  if ( ( vertical.scale_info.output_sub_size / splits ) < 4 ) // each split should be a minimum of 4 scanlines (handwavey choice)-  {-    splits = vertical.scale_info.output_sub_size / 4;-    if ( splits == 0 ) splits = 1;-  }--  STBIR_PROFILE_BUILD_START( alloc );-  out_info = stbir__alloc_internal_mem_and_build_samplers( &horizontal, &vertical, &conservative, resize->input_pixel_layout_public, resize->output_pixel_layout_public, splits, new_output_subx, new_output_suby, resize->fast_alpha, resize->user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO );-  STBIR_PROFILE_BUILD_END( alloc );-  STBIR_PROFILE_BUILD_END( build );- -  if ( out_info )-  {-    resize->splits = splits;-    resize->samplers = out_info;-    resize->needs_rebuild = 0;-    #ifdef STBIR_PROFILE-      STBIR_MEMCPY( &out_info->profile, &profile_infod.profile, sizeof( out_info->profile ) );-    #endif-    return splits;-  }--  return 0;-}--void stbir_free_samplers( STBIR_RESIZE * resize )-{-  if ( resize->samplers )-  {-    stbir__free_internal_mem( resize->samplers );-    resize->samplers = 0;-    resize->called_alloc = 0;-  }-}--STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int splits )-{-  if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) )-  {-    if ( resize->samplers )-      stbir_free_samplers( resize );--    resize->called_alloc = 1;-    return stbir__perform_build( resize, splits );-  }--  STBIR_PROFILE_BUILD_CLEAR( resize->samplers );-  -  return 1;-}--STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize )-{-  return stbir_build_samplers_with_splits( resize, 1 );-}--STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize )-{-  int result;-  -  if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) )-  {-    int alloc_state = resize->called_alloc;  // remember allocated state--    if ( resize->samplers )-    {-      stbir__free_internal_mem( resize->samplers );-      resize->samplers = 0;-    }--    if ( !stbir_build_samplers( resize ) )-      return 0;-    -    resize->called_alloc = alloc_state;--    // if build_samplers succeeded (above), but there are no samplers set, then -    //   the area to stretch into was zero pixels, so don't do anything and return-    //   success-    if ( resize->samplers == 0 )-      return 1;-  }-  else-  {-    // didn't build anything - clear it-    STBIR_PROFILE_BUILD_CLEAR( resize->samplers );-  }---  // update anything that can be changed without recalcing samplers-  stbir__update_info_from_resize( resize->samplers, resize );--  // do resize-  result = stbir__perform_resize( resize->samplers, 0, resize->splits );--  // if we alloced, then free-  if ( !resize->called_alloc )-  {-    stbir_free_samplers( resize );-    resize->samplers = 0;-  } --  return result;-}--STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count )-{-  STBIR_ASSERT( resize->samplers );--  // if we're just doing the whole thing, call full-  if ( ( split_start == -1 ) || ( ( split_start == 0 ) && ( split_count == resize->splits ) ) )-    return stbir_resize_extended( resize );--  // you **must** build samplers first when using split resize-  if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) )-    return 0; -    -  if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) )-    return 0;-  -  // update anything that can be changed without recalcing samplers-  stbir__update_info_from_resize( resize->samplers, resize );- -  // do resize-  return stbir__perform_resize( resize->samplers, split_start, split_count );-}--static int stbir__check_output_stuff( void ** ret_ptr, int * ret_pitch, void * output_pixels, int type_size, int output_w, int output_h, int output_stride_in_bytes, stbir_internal_pixel_layout pixel_layout )-{-  size_t size;-  int pitch;-  void * ptr;--  pitch = output_w * type_size * stbir__pixel_channels[ pixel_layout ];-  if ( pitch == 0 )-    return 0;--  if ( output_stride_in_bytes == 0 )-    output_stride_in_bytes = pitch;--  if ( output_stride_in_bytes < pitch )-    return 0;--  size = output_stride_in_bytes * output_h;-  if ( size == 0 )-    return 0;--  *ret_ptr = 0;-  *ret_pitch = output_stride_in_bytes;--  if ( output_pixels == 0 )-  {-    ptr = STBIR_MALLOC( size, 0 );-    if ( ptr == 0 )-      return 0;--    *ret_ptr = ptr;-    *ret_pitch = pitch;-  }--  return 1;  -}---STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes,-                                                          unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,-                                                          stbir_pixel_layout pixel_layout )-{-  STBIR_RESIZE resize;-  unsigned char * optr;-  int opitch;--  if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) )-    return 0;--  stbir_resize_init( &resize, -                     input_pixels,  input_w,  input_h,  input_stride_in_bytes, -                     (optr) ? optr : output_pixels, output_w, output_h, opitch, -                     pixel_layout, STBIR_TYPE_UINT8 );--  if ( !stbir_resize_extended( &resize ) )-  {-    if ( optr )-      STBIR_FREE( optr, 0 );-    return 0;-  }--  return (optr) ? optr : output_pixels;-}--STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes,-                                                        unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,-                                                        stbir_pixel_layout pixel_layout )-{-  STBIR_RESIZE resize;-  unsigned char * optr;-  int opitch;--  if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) )-    return 0;--  stbir_resize_init( &resize, -                     input_pixels,  input_w,  input_h,  input_stride_in_bytes, -                     (optr) ? optr : output_pixels, output_w, output_h, opitch, -                     pixel_layout, STBIR_TYPE_UINT8_SRGB );--  if ( !stbir_resize_extended( &resize ) )-  {-    if ( optr )-      STBIR_FREE( optr, 0 );-    return 0;-  }--  return (optr) ? optr : output_pixels;-}---STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes,-                                                  float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,-                                                  stbir_pixel_layout pixel_layout )-{-  STBIR_RESIZE resize;-  float * optr;-  int opitch;--  if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( float ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) )-    return 0;--  stbir_resize_init( &resize, -                     input_pixels,  input_w,  input_h,  input_stride_in_bytes, -                     (optr) ? optr : output_pixels, output_w, output_h, opitch, -                     pixel_layout, STBIR_TYPE_FLOAT );--  if ( !stbir_resize_extended( &resize ) )-  {-    if ( optr )-      STBIR_FREE( optr, 0 );-    return 0;-  }--  return (optr) ? optr : output_pixels;-}---STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes,-                                    void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,-                              stbir_pixel_layout pixel_layout, stbir_datatype data_type, -                              stbir_edge edge, stbir_filter filter )-{-  STBIR_RESIZE resize;-  float * optr;-  int opitch;--  if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, stbir__type_size[data_type], output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) )-    return 0;--  stbir_resize_init( &resize, -                     input_pixels,  input_w,  input_h,  input_stride_in_bytes, -                     (optr) ? optr : output_pixels, output_w, output_h, output_stride_in_bytes, -                     pixel_layout, data_type );--  resize.horizontal_edge = edge;-  resize.vertical_edge = edge;-  resize.horizontal_filter = filter;-  resize.vertical_filter = filter;--  if ( !stbir_resize_extended( &resize ) )-  {-    if ( optr )-      STBIR_FREE( optr, 0 );-    return 0;-  }--  return (optr) ? optr : output_pixels;-}--#ifdef STBIR_PROFILE--STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize )-{-  static char const * bdescriptions[6] = { "Building", "Allocating", "Horizontal sampler", "Vertical sampler", "Coefficient cleanup", "Coefficient piovot" } ;-  stbir__info* samp = resize->samplers;-  int i;--  typedef int testa[ (STBIR__ARRAY_SIZE( bdescriptions ) == (STBIR__ARRAY_SIZE( samp->profile.array )-1) )?1:-1];-  typedef int testb[ (sizeof( samp->profile.array ) == (sizeof(samp->profile.named)) )?1:-1];-  typedef int testc[ (sizeof( info->clocks ) >= (sizeof(samp->profile.named)) )?1:-1];--  for( i = 0 ; i < STBIR__ARRAY_SIZE( bdescriptions ) ; i++)-    info->clocks[i] = samp->profile.array[i+1];--  info->total_clocks = samp->profile.named.total;-  info->descriptions = bdescriptions;-  info->count = STBIR__ARRAY_SIZE( bdescriptions );-}--STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize, int split_start, int split_count )-{-  static char const * descriptions[7] = { "Looping", "Vertical sampling", "Horizontal sampling", "Scanline input", "Scanline output", "Alpha weighting", "Alpha unweighting" };-  stbir__per_split_info * split_info;-  int s, i;--  typedef int testa[ (STBIR__ARRAY_SIZE( descriptions ) == (STBIR__ARRAY_SIZE( split_info->profile.array )-1) )?1:-1];-  typedef int testb[ (sizeof( split_info->profile.array ) == (sizeof(split_info->profile.named)) )?1:-1];-  typedef int testc[ (sizeof( info->clocks ) >= (sizeof(split_info->profile.named)) )?1:-1];--  if ( split_start == -1 )-  {-    split_start = 0;-    split_count = resize->samplers->splits;-  }--  if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) )-  {-    info->total_clocks = 0;-    info->descriptions = 0;-    info->count = 0;-    return;-  }--  split_info = resize->samplers->split_info + split_start;--  // sum up the profile from all the splits-  for( i = 0 ; i < STBIR__ARRAY_SIZE( descriptions ) ; i++ )-  {-    stbir_uint64 sum = 0;-    for( s = 0 ; s < split_count ; s++ )-      sum += split_info[s].profile.array[i+1];-    info->clocks[i] = sum;-  }--  info->total_clocks = split_info->profile.named.total;-  info->descriptions = descriptions;-  info->count = STBIR__ARRAY_SIZE( descriptions );-}--STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize )-{-  stbir_resize_split_profile_info( info, resize, -1, 0 );-}--#endif // STBIR_PROFILE--#undef STBIR_BGR-#undef STBIR_1CHANNEL-#undef STBIR_2CHANNEL-#undef STBIR_RGB-#undef STBIR_RGBA-#undef STBIR_4CHANNEL-#undef STBIR_BGRA-#undef STBIR_ARGB-#undef STBIR_ABGR-#undef STBIR_RA-#undef STBIR_AR-#undef STBIR_RGBA_PM-#undef STBIR_BGRA_PM-#undef STBIR_ARGB_PM-#undef STBIR_ABGR_PM-#undef STBIR_RA_PM-#undef STBIR_AR_PM--#endif // STB_IMAGE_RESIZE_IMPLEMENTATION--#else  // STB_IMAGE_RESIZE_HORIZONTALS&STB_IMAGE_RESIZE_DO_VERTICALS--// we reinclude the header file to define all the horizontal functions-//   specializing each function for the number of coeffs is 20-40% faster *OVERALL* --// by including the header file again this way, we can still debug the functions--#define STBIR_strs_join2( start, mid, end ) start##mid##end-#define STBIR_strs_join1( start, mid, end ) STBIR_strs_join2( start, mid, end )--#define STBIR_strs_join24( start, mid1, mid2, end ) start##mid1##mid2##end-#define STBIR_strs_join14( start, mid1, mid2, end ) STBIR_strs_join24( start, mid1, mid2, end )--#ifdef STB_IMAGE_RESIZE_DO_CODERS--#ifdef stbir__decode_suffix-#define STBIR__CODER_NAME( name ) STBIR_strs_join1( name, _, stbir__decode_suffix )-#else-#define STBIR__CODER_NAME( name ) name-#endif--#ifdef stbir__decode_swizzle-#define stbir__decode_simdf8_flip(reg) STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( stbir__simdf8_0123to,stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3),stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3)(reg, reg)-#define stbir__decode_simdf4_flip(reg) STBIR_strs_join1( STBIR_strs_join1( stbir__simdf_0123to,stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3)(reg, reg)-#define stbir__encode_simdf8_unflip(reg) STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( stbir__simdf8_0123to,stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3),stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3)(reg, reg)-#define stbir__encode_simdf4_unflip(reg) STBIR_strs_join1( STBIR_strs_join1( stbir__simdf_0123to,stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3)(reg, reg)-#else-#define stbir__decode_order0 0-#define stbir__decode_order1 1-#define stbir__decode_order2 2-#define stbir__decode_order3 3-#define stbir__encode_order0 0-#define stbir__encode_order1 1-#define stbir__encode_order2 2-#define stbir__encode_order3 3-#define stbir__decode_simdf8_flip(reg)-#define stbir__decode_simdf4_flip(reg) -#define stbir__encode_simdf8_unflip(reg)-#define stbir__encode_simdf4_unflip(reg) -#endif--#ifdef STBIR_SIMD8-#define stbir__encode_simdfX_unflip  stbir__encode_simdf8_unflip-#else-#define stbir__encode_simdfX_unflip  stbir__encode_simdf4_unflip-#endif --static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * decodep, int width_times_channels, void const * inputp )-{-  float STBIR_STREAMOUT_PTR( * ) decode = decodep;-  float * decode_end = (float*) decode + width_times_channels;-  unsigned char const * input = (unsigned char const*)inputp;--  #ifdef STBIR_SIMD-  unsigned char const * end_input_m16 = input + width_times_channels - 16;-  if ( width_times_channels >= 16 )-  {-    decode_end -= 16;-    for(;;)-    {-      #ifdef STBIR_SIMD8-      stbir__simdi i; stbir__simdi8 o0,o1;-      stbir__simdf8 of0, of1;-      STBIR_NO_UNROLL(decode);-      stbir__simdi_load( i, input );-      stbir__simdi8_expand_u8_to_u32( o0, o1, i );-      stbir__simdi8_convert_i32_to_float( of0, o0 );-      stbir__simdi8_convert_i32_to_float( of1, o1 );-      stbir__simdf8_mult( of0, of0, STBIR_max_uint8_as_float_inverted8);-      stbir__simdf8_mult( of1, of1, STBIR_max_uint8_as_float_inverted8);-      stbir__decode_simdf8_flip( of0 );-      stbir__decode_simdf8_flip( of1 );-      stbir__simdf8_store( decode + 0, of0 );-      stbir__simdf8_store( decode + 8, of1 );-      #else-      stbir__simdi i, o0, o1, o2, o3;-      stbir__simdf of0, of1, of2, of3;-      STBIR_NO_UNROLL(decode);-      stbir__simdi_load( i, input );-      stbir__simdi_expand_u8_to_u32( o0,o1,o2,o3,i);-      stbir__simdi_convert_i32_to_float( of0, o0 );-      stbir__simdi_convert_i32_to_float( of1, o1 );-      stbir__simdi_convert_i32_to_float( of2, o2 );-      stbir__simdi_convert_i32_to_float( of3, o3 );-      stbir__simdf_mult( of0, of0, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) );-      stbir__simdf_mult( of1, of1, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) );-      stbir__simdf_mult( of2, of2, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) );-      stbir__simdf_mult( of3, of3, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) );-      stbir__decode_simdf4_flip( of0 );-      stbir__decode_simdf4_flip( of1 );-      stbir__decode_simdf4_flip( of2 );-      stbir__decode_simdf4_flip( of3 );-      stbir__simdf_store( decode + 0,  of0 );-      stbir__simdf_store( decode + 4,  of1 );-      stbir__simdf_store( decode + 8,  of2 );-      stbir__simdf_store( decode + 12, of3 );-      #endif-      decode += 16;-      input += 16;-      if ( decode <= decode_end ) -        continue;-      if ( decode == ( decode_end + 16 ) )-        break;-      decode = decode_end; // backup and do last couple-      input = end_input_m16;-    }-    return;-  }-  #endif--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  decode += 4;-  while( decode <= decode_end )-  {-    STBIR_SIMD_NO_UNROLL(decode);-    decode[0-4] = ((float)(input[stbir__decode_order0])) * stbir__max_uint8_as_float_inverted;-    decode[1-4] = ((float)(input[stbir__decode_order1])) * stbir__max_uint8_as_float_inverted;-    decode[2-4] = ((float)(input[stbir__decode_order2])) * stbir__max_uint8_as_float_inverted;-    decode[3-4] = ((float)(input[stbir__decode_order3])) * stbir__max_uint8_as_float_inverted;-    decode += 4;-    input += 4;-  }-  decode -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( decode < decode_end )-  {-    STBIR_NO_UNROLL(decode);-    decode[0] = ((float)(input[stbir__decode_order0])) * stbir__max_uint8_as_float_inverted;-    #if stbir__coder_min_num >= 2-    decode[1] = ((float)(input[stbir__decode_order1])) * stbir__max_uint8_as_float_inverted;-    #endif-    #if stbir__coder_min_num >= 3-    decode[2] = ((float)(input[stbir__decode_order2])) * stbir__max_uint8_as_float_inverted;-    #endif-    decode += stbir__coder_min_num;-    input += stbir__coder_min_num;-  }-  #endif-}--static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outputp, int width_times_channels, float const * encode )-{-  unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char *) outputp;-  unsigned char * end_output = ( (unsigned char *) output ) + width_times_channels;--  #ifdef STBIR_SIMD-  if ( width_times_channels >= stbir__simdfX_float_count*2 )-  {-    float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2;-    end_output -= stbir__simdfX_float_count*2;-    for(;;)-    {-      stbir__simdfX e0, e1;-      stbir__simdi i;-      STBIR_SIMD_NO_UNROLL(encode);-      stbir__simdfX_madd_mem( e0, STBIR_simd_point5X, STBIR_max_uint8_as_floatX, encode );-      stbir__simdfX_madd_mem( e1, STBIR_simd_point5X, STBIR_max_uint8_as_floatX, encode+stbir__simdfX_float_count );-      stbir__encode_simdfX_unflip( e0 );-      stbir__encode_simdfX_unflip( e1 );-      #ifdef STBIR_SIMD8-      stbir__simdf8_pack_to_16bytes( i, e0, e1 ); -      stbir__simdi_store( output, i );-      #else-      stbir__simdf_pack_to_8bytes( i, e0, e1 ); -      stbir__simdi_store2( output, i );-      #endif-      encode += stbir__simdfX_float_count*2;-      output += stbir__simdfX_float_count*2;-      if ( output <= end_output ) -        continue;-      if ( output == ( end_output + stbir__simdfX_float_count*2 ) )-        break;-      output = end_output; // backup and do last couple-      encode = end_encode_m8;-    }-    return;-  }--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    stbir__simdf e0;-    stbir__simdi i0;-    STBIR_NO_UNROLL(encode);-    stbir__simdf_load( e0, encode );-    stbir__simdf_madd( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), e0 );-    stbir__encode_simdf4_unflip( e0 );-    stbir__simdf_pack_to_8bytes( i0, e0, e0 );  // only use first 4-    *(int*)(output-4) = stbir__simdi_to_int( i0 );-    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( output < end_output )-  {-    stbir__simdf e0; -    STBIR_NO_UNROLL(encode);-    stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_uint8( e0 );-    #if stbir__coder_min_num >= 2-    stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order1 ); output[1] = stbir__simdf_convert_float_to_uint8( e0 );-    #endif-    #if stbir__coder_min_num >= 3-    stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order2 ); output[2] = stbir__simdf_convert_float_to_uint8( e0 );-    #endif-    output += stbir__coder_min_num;-    encode += stbir__coder_min_num;-  }-  #endif-  -  #else--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    float f;-    f = encode[stbir__encode_order0] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[0-4] = (unsigned char)f;-    f = encode[stbir__encode_order1] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[1-4] = (unsigned char)f;-    f = encode[stbir__encode_order2] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[2-4] = (unsigned char)f;-    f = encode[stbir__encode_order3] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[3-4] = (unsigned char)f;-    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( output < end_output )-  {-    float f;-    STBIR_NO_UNROLL(encode);-    f = encode[stbir__encode_order0] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[0] = (unsigned char)f;-    #if stbir__coder_min_num >= 2-    f = encode[stbir__encode_order1] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[1] = (unsigned char)f;-    #endif-    #if stbir__coder_min_num >= 3-    f = encode[stbir__encode_order2] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[2] = (unsigned char)f;-    #endif-    output += stbir__coder_min_num;-    encode += stbir__coder_min_num;-  }-  #endif-  #endif-}--static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int width_times_channels, void const * inputp )-{-  float STBIR_STREAMOUT_PTR( * ) decode = decodep;-  float * decode_end = (float*) decode + width_times_channels;-  unsigned char const * input = (unsigned char const*)inputp;--  #ifdef STBIR_SIMD-  unsigned char const * end_input_m16 = input + width_times_channels - 16;-  if ( width_times_channels >= 16 )-  {-    decode_end -= 16;-    for(;;)-    {-      #ifdef STBIR_SIMD8-      stbir__simdi i; stbir__simdi8 o0,o1;-      stbir__simdf8 of0, of1;-      STBIR_NO_UNROLL(decode);-      stbir__simdi_load( i, input );-      stbir__simdi8_expand_u8_to_u32( o0, o1, i );-      stbir__simdi8_convert_i32_to_float( of0, o0 );-      stbir__simdi8_convert_i32_to_float( of1, o1 );-      stbir__decode_simdf8_flip( of0 );-      stbir__decode_simdf8_flip( of1 );-      stbir__simdf8_store( decode + 0, of0 );-      stbir__simdf8_store( decode + 8, of1 );-      #else-      stbir__simdi i, o0, o1, o2, o3;-      stbir__simdf of0, of1, of2, of3;-      STBIR_NO_UNROLL(decode);-      stbir__simdi_load( i, input );-      stbir__simdi_expand_u8_to_u32( o0,o1,o2,o3,i);-      stbir__simdi_convert_i32_to_float( of0, o0 );-      stbir__simdi_convert_i32_to_float( of1, o1 );-      stbir__simdi_convert_i32_to_float( of2, o2 );-      stbir__simdi_convert_i32_to_float( of3, o3 );-      stbir__decode_simdf4_flip( of0 );-      stbir__decode_simdf4_flip( of1 );-      stbir__decode_simdf4_flip( of2 );-      stbir__decode_simdf4_flip( of3 );-      stbir__simdf_store( decode + 0,  of0 );-      stbir__simdf_store( decode + 4,  of1 );-      stbir__simdf_store( decode + 8,  of2 );-      stbir__simdf_store( decode + 12, of3 );-#endif-      decode += 16;-      input += 16;-      if ( decode <= decode_end ) -        continue;-      if ( decode == ( decode_end + 16 ) )-        break;-      decode = decode_end; // backup and do last couple-      input = end_input_m16;-    }-    return;-  }-  #endif--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  decode += 4;-  while( decode <= decode_end )-  {-    STBIR_SIMD_NO_UNROLL(decode);-    decode[0-4] = ((float)(input[stbir__decode_order0]));-    decode[1-4] = ((float)(input[stbir__decode_order1]));-    decode[2-4] = ((float)(input[stbir__decode_order2]));-    decode[3-4] = ((float)(input[stbir__decode_order3]));-    decode += 4;-    input += 4;-  }-  decode -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( decode < decode_end )-  {-    STBIR_NO_UNROLL(decode);-    decode[0] = ((float)(input[stbir__decode_order0]));-    #if stbir__coder_min_num >= 2-    decode[1] = ((float)(input[stbir__decode_order1]));-    #endif-    #if stbir__coder_min_num >= 3-    decode[2] = ((float)(input[stbir__decode_order2]));-    #endif-    decode += stbir__coder_min_num;-    input += stbir__coder_min_num;-  }-  #endif-}--static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int width_times_channels, float const * encode )-{-  unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char *) outputp;-  unsigned char * end_output = ( (unsigned char *) output ) + width_times_channels;--  #ifdef STBIR_SIMD-  if ( width_times_channels >= stbir__simdfX_float_count*2 )-  {-    float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2;-    end_output -= stbir__simdfX_float_count*2;-    for(;;)-    {-      stbir__simdfX e0, e1;-      stbir__simdi i;-      STBIR_SIMD_NO_UNROLL(encode);-      stbir__simdfX_add_mem( e0, STBIR_simd_point5X, encode );-      stbir__simdfX_add_mem( e1, STBIR_simd_point5X, encode+stbir__simdfX_float_count );-      stbir__encode_simdfX_unflip( e0 );-      stbir__encode_simdfX_unflip( e1 );-      #ifdef STBIR_SIMD8-      stbir__simdf8_pack_to_16bytes( i, e0, e1 ); -      stbir__simdi_store( output, i );-      #else-      stbir__simdf_pack_to_8bytes( i, e0, e1 ); -      stbir__simdi_store2( output, i );-      #endif-      encode += stbir__simdfX_float_count*2;-      output += stbir__simdfX_float_count*2;-      if ( output <= end_output ) -        continue;-      if ( output == ( end_output + stbir__simdfX_float_count*2 ) )-        break;-      output = end_output; // backup and do last couple-      encode = end_encode_m8;-    }-    return;-  }--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    stbir__simdf e0;-    stbir__simdi i0;-    STBIR_NO_UNROLL(encode);-    stbir__simdf_load( e0, encode );-    stbir__simdf_add( e0, STBIR__CONSTF(STBIR_simd_point5), e0 );-    stbir__encode_simdf4_unflip( e0 );-    stbir__simdf_pack_to_8bytes( i0, e0, e0 );  // only use first 4-    *(int*)(output-4) = stbir__simdi_to_int( i0 );-    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  #else--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    float f;-    f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 255); output[0-4] = (unsigned char)f;-    f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 255); output[1-4] = (unsigned char)f;-    f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 255); output[2-4] = (unsigned char)f;-    f = encode[stbir__encode_order3] + 0.5f; STBIR_CLAMP(f, 0, 255); output[3-4] = (unsigned char)f;-    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( output < end_output )-  {-    float f;-    STBIR_NO_UNROLL(encode);-    f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 255); output[0] = (unsigned char)f;-    #if stbir__coder_min_num >= 2-    f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 255); output[1] = (unsigned char)f;-    #endif-    #if stbir__coder_min_num >= 3-    f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 255); output[2] = (unsigned char)f;-    #endif-    output += stbir__coder_min_num;-    encode += stbir__coder_min_num;-  }-  #endif-}--static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int width_times_channels, void const * inputp )-{-  float STBIR_STREAMOUT_PTR( * ) decode = decodep;-  float const * decode_end = (float*) decode + width_times_channels;-  unsigned char const * input = (unsigned char const *)inputp;--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  decode += 4;-  while( decode <= decode_end )-  {-    decode[0-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order0 ] ];-    decode[1-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order1 ] ];-    decode[2-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order2 ] ];-    decode[3-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order3 ] ];-    decode += 4;-    input += 4;-  }-  decode -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( decode < decode_end )-  {-    STBIR_NO_UNROLL(decode);-    decode[0] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order0 ] ];-    #if stbir__coder_min_num >= 2-    decode[1] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order1 ] ];-    #endif-    #if stbir__coder_min_num >= 3-    decode[2] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order2 ] ];-    #endif-    decode += stbir__coder_min_num;-    input += stbir__coder_min_num;-  }-  #endif-}--#define stbir__min_max_shift20( i, f ) \-    stbir__simdf_max( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_zero )) ); \-    stbir__simdf_min( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_one  )) ); \-    stbir__simdi_32shr( i, stbir_simdi_castf( f ), 20 ); --#define stbir__scale_and_convert( i, f ) \-    stbir__simdf_madd( f, STBIR__CONSTF( STBIR_simd_point5 ), STBIR__CONSTF( STBIR_max_uint8_as_float ), f ); \-    stbir__simdf_max( f, f, stbir__simdf_zeroP() ); \-    stbir__simdf_min( f, f, STBIR__CONSTF( STBIR_max_uint8_as_float ) ); \-    stbir__simdf_convert_float_to_i32( i, f );--#define stbir__linear_to_srgb_finish( i, f ) \-{ \-    stbir__simdi temp;  \-    stbir__simdi_32shr( temp, stbir_simdi_castf( f ), 12 ) ; \-    stbir__simdi_and( temp, temp, STBIR__CONSTI(STBIR_mastissa_mask) ); \-    stbir__simdi_or( temp, temp, STBIR__CONSTI(STBIR_topscale) ); \-    stbir__simdi_16madd( i, i, temp ); \-    stbir__simdi_32shr( i, i, 16 ); \-}--#define stbir__simdi_table_lookup2( v0,v1, table ) \-{ \-  stbir__simdi_u32 temp0,temp1; \-  temp0.m128i_i128 = v0; \-  temp1.m128i_i128 = v1; \-  temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \-  temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \-  v0 = temp0.m128i_i128; \-  v1 = temp1.m128i_i128; \-} --#define stbir__simdi_table_lookup3( v0,v1,v2, table ) \-{ \-  stbir__simdi_u32 temp0,temp1,temp2; \-  temp0.m128i_i128 = v0; \-  temp1.m128i_i128 = v1; \-  temp2.m128i_i128 = v2; \-  temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \-  temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \-  temp2.m128i_u32[0] = table[temp2.m128i_i32[0]]; temp2.m128i_u32[1] = table[temp2.m128i_i32[1]]; temp2.m128i_u32[2] = table[temp2.m128i_i32[2]]; temp2.m128i_u32[3] = table[temp2.m128i_i32[3]]; \-  v0 = temp0.m128i_i128; \-  v1 = temp1.m128i_i128; \-  v2 = temp2.m128i_i128; \-}--#define stbir__simdi_table_lookup4( v0,v1,v2,v3, table ) \-{ \-  stbir__simdi_u32 temp0,temp1,temp2,temp3; \-  temp0.m128i_i128 = v0; \-  temp1.m128i_i128 = v1; \-  temp2.m128i_i128 = v2; \-  temp3.m128i_i128 = v3; \-  temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \-  temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \-  temp2.m128i_u32[0] = table[temp2.m128i_i32[0]]; temp2.m128i_u32[1] = table[temp2.m128i_i32[1]]; temp2.m128i_u32[2] = table[temp2.m128i_i32[2]]; temp2.m128i_u32[3] = table[temp2.m128i_i32[3]]; \-  temp3.m128i_u32[0] = table[temp3.m128i_i32[0]]; temp3.m128i_u32[1] = table[temp3.m128i_i32[1]]; temp3.m128i_u32[2] = table[temp3.m128i_i32[2]]; temp3.m128i_u32[3] = table[temp3.m128i_i32[3]]; \-  v0 = temp0.m128i_i128; \-  v1 = temp1.m128i_i128; \-  v2 = temp2.m128i_i128; \-  v3 = temp3.m128i_i128; \-} --static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int width_times_channels, float const * encode )-{-  unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp;-  unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels;--  #ifdef STBIR_SIMD-  stbir_uint32 const * to_srgb = fp32_to_srgb8_tab4 - (127-13)*8;--  if ( width_times_channels >= 16 )-  {-    float const * end_encode_m16 = encode + width_times_channels - 16;-    end_output -= 16;-    for(;;)-    {-      stbir__simdf f0, f1, f2, f3;-      stbir__simdi i0, i1, i2, i3; -      STBIR_SIMD_NO_UNROLL(encode);--      stbir__simdf_load4_transposed( f0, f1, f2, f3, encode );--      stbir__min_max_shift20( i0, f0 );-      stbir__min_max_shift20( i1, f1 );-      stbir__min_max_shift20( i2, f2 );-      stbir__min_max_shift20( i3, f3 );-      -      stbir__simdi_table_lookup4( i0, i1, i2, i3, to_srgb );-     -      stbir__linear_to_srgb_finish( i0, f0 );-      stbir__linear_to_srgb_finish( i1, f1 );-      stbir__linear_to_srgb_finish( i2, f2 );-      stbir__linear_to_srgb_finish( i3, f3 );--      stbir__interleave_pack_and_store_16_u8( output,  STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) );--      encode += 16;-      output += 16;-      if ( output <= end_output ) -        continue;-      if ( output == ( end_output + 16 ) )-        break;-      output = end_output; // backup and do last couple-      encode = end_encode_m16;-    }-    return;-  }-  #endif--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while ( output <= end_output )-  {-    STBIR_SIMD_NO_UNROLL(encode);--    output[0-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] );-    output[1-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order1] );-    output[2-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order2] );-    output[3-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order3] );--    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( output < end_output ) -  {-    STBIR_NO_UNROLL(encode);-    output[0] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] );-    #if stbir__coder_min_num >= 2-    output[1] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order1] );-    #endif-    #if stbir__coder_min_num >= 3-    output[2] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order2] );-    #endif-    output += stbir__coder_min_num;-    encode += stbir__coder_min_num;-  }-  #endif-}--#if ( stbir__coder_min_num == 4 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) )--static void STBIR__CODER_NAME(stbir__decode_uint8_srgb4_linearalpha)( float * decodep, int width_times_channels, void const * inputp )-{-  float STBIR_STREAMOUT_PTR( * ) decode = decodep;-  float const * decode_end = (float*) decode + width_times_channels;-  unsigned char const * input = (unsigned char const *)inputp;-  do {-    decode[0] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ];-    decode[1] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order1] ];-    decode[2] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order2] ];-    decode[3] = ( (float) input[stbir__decode_order3] ) * stbir__max_uint8_as_float_inverted;-    input += 4;-    decode += 4;-  } while( decode < decode_end );-}---static void STBIR__CODER_NAME( stbir__encode_uint8_srgb4_linearalpha )( void * outputp, int width_times_channels, float const * encode )-{-  unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp;-  unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels;--  #ifdef STBIR_SIMD-  stbir_uint32 const * to_srgb = fp32_to_srgb8_tab4 - (127-13)*8;--  if ( width_times_channels >= 16 )-  {-    float const * end_encode_m16 = encode + width_times_channels - 16;-    end_output -= 16;-    for(;;)-    {-      stbir__simdf f0, f1, f2, f3;-      stbir__simdi i0, i1, i2, i3;--      STBIR_SIMD_NO_UNROLL(encode);-      stbir__simdf_load4_transposed( f0, f1, f2, f3, encode );--      stbir__min_max_shift20( i0, f0 );-      stbir__min_max_shift20( i1, f1 );-      stbir__min_max_shift20( i2, f2 );-      stbir__scale_and_convert( i3, f3 ); -      -      stbir__simdi_table_lookup3( i0, i1, i2, to_srgb );-     -      stbir__linear_to_srgb_finish( i0, f0 );-      stbir__linear_to_srgb_finish( i1, f1 );-      stbir__linear_to_srgb_finish( i2, f2 );--      stbir__interleave_pack_and_store_16_u8( output,  STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) );--      output += 16;-      encode += 16;--      if ( output <= end_output ) -        continue;-      if ( output == ( end_output + 16 ) )-        break;-      output = end_output; // backup and do last couple-      encode = end_encode_m16;-    }-    return;-  }-  #endif--  do {-    float f;-    STBIR_SIMD_NO_UNROLL(encode);                                        --    output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] );-    output[stbir__decode_order1] = stbir__linear_to_srgb_uchar( encode[1] );-    output[stbir__decode_order2] = stbir__linear_to_srgb_uchar( encode[2] );--    f = encode[3] * stbir__max_uint8_as_float + 0.5f;-    STBIR_CLAMP(f, 0, 255);-    output[stbir__decode_order3] = (unsigned char) f;--    output += 4;-    encode += 4;-  } while( output < end_output );-}--#endif--#if ( stbir__coder_min_num == 2 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) )--static void STBIR__CODER_NAME(stbir__decode_uint8_srgb2_linearalpha)( float * decodep, int width_times_channels, void const * inputp )-{-  float STBIR_STREAMOUT_PTR( * ) decode = decodep;-  float const * decode_end = (float*) decode + width_times_channels;-  unsigned char const * input = (unsigned char const *)inputp;-  decode += 4;-  while( decode <= decode_end )-  {-    decode[0-4] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ];-    decode[1-4] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted;-    decode[2-4] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0+2] ];-    decode[3-4] = ( (float) input[stbir__decode_order1+2] ) * stbir__max_uint8_as_float_inverted;-    input += 4;-    decode += 4;-  }-  decode -= 4;-  if( decode < decode_end ) -  {-    decode[0] = stbir__srgb_uchar_to_linear_float[ stbir__decode_order0 ];-    decode[1] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted;-  }-}--static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * outputp, int width_times_channels, float const * encode )-{-  unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp;-  unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels;--  #ifdef STBIR_SIMD-  stbir_uint32 const * to_srgb = fp32_to_srgb8_tab4 - (127-13)*8;--  if ( width_times_channels >= 16 )-  {-    float const * end_encode_m16 = encode + width_times_channels - 16;-    end_output -= 16;-    for(;;)-    {-      stbir__simdf f0, f1, f2, f3;-      stbir__simdi i0, i1, i2, i3; --      STBIR_SIMD_NO_UNROLL(encode);-      stbir__simdf_load4_transposed( f0, f1, f2, f3, encode );--      stbir__min_max_shift20( i0, f0 );-      stbir__scale_and_convert( i1, f1 );-      stbir__min_max_shift20( i2, f2 );-      stbir__scale_and_convert( i3, f3 );-      -      stbir__simdi_table_lookup2( i0, i2, to_srgb );-     -      stbir__linear_to_srgb_finish( i0, f0 );-      stbir__linear_to_srgb_finish( i2, f2 );--      stbir__interleave_pack_and_store_16_u8( output,  STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) );--      output += 16;-      encode += 16;-      if ( output <= end_output ) -        continue;-      if ( output == ( end_output + 16 ) )-        break;-      output = end_output; // backup and do last couple-      encode = end_encode_m16;-    }-    return;-  }-  #endif--  do {-    float f;-    STBIR_SIMD_NO_UNROLL(encode);--    output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] );--    f = encode[1] * stbir__max_uint8_as_float + 0.5f;-    STBIR_CLAMP(f, 0, 255);-    output[stbir__decode_order1] = (unsigned char) f;--    output += 2;-    encode += 2;-  } while( output < end_output );-}--#endif--static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decodep, int width_times_channels, void const * inputp )-{-  float STBIR_STREAMOUT_PTR( * ) decode = decodep;-  float * decode_end = (float*) decode + width_times_channels;-  unsigned short const * input = (unsigned short const *)inputp;--  #ifdef STBIR_SIMD-  unsigned short const * end_input_m8 = input + width_times_channels - 8;-  if ( width_times_channels >= 8 )-  {-    decode_end -= 8;-    for(;;)-    {-      #ifdef STBIR_SIMD8-      stbir__simdi i; stbir__simdi8 o;-      stbir__simdf8 of;-      STBIR_NO_UNROLL(decode);-      stbir__simdi_load( i, input );-      stbir__simdi8_expand_u16_to_u32( o, i );-      stbir__simdi8_convert_i32_to_float( of, o );-      stbir__simdf8_mult( of, of, STBIR_max_uint16_as_float_inverted8);-      stbir__decode_simdf8_flip( of );-      stbir__simdf8_store( decode + 0, of );-      #else-      stbir__simdi i, o0, o1;-      stbir__simdf of0, of1;-      STBIR_NO_UNROLL(decode);-      stbir__simdi_load( i, input );-      stbir__simdi_expand_u16_to_u32( o0,o1,i );-      stbir__simdi_convert_i32_to_float( of0, o0 );-      stbir__simdi_convert_i32_to_float( of1, o1 );-      stbir__simdf_mult( of0, of0, STBIR__CONSTF(STBIR_max_uint16_as_float_inverted) );-      stbir__simdf_mult( of1, of1, STBIR__CONSTF(STBIR_max_uint16_as_float_inverted));-      stbir__decode_simdf4_flip( of0 );-      stbir__decode_simdf4_flip( of1 );-      stbir__simdf_store( decode + 0,  of0 );-      stbir__simdf_store( decode + 4,  of1 );-      #endif-      decode += 8;  -      input += 8;-      if ( decode <= decode_end ) -        continue;-      if ( decode == ( decode_end + 8 ) )-        break;-      decode = decode_end; // backup and do last couple-      input = end_input_m8;-    }-    return;-  }-  #endif--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  decode += 4;-  while( decode <= decode_end )-  {-    STBIR_SIMD_NO_UNROLL(decode);-    decode[0-4] = ((float)(input[stbir__decode_order0])) * stbir__max_uint16_as_float_inverted;-    decode[1-4] = ((float)(input[stbir__decode_order1])) * stbir__max_uint16_as_float_inverted;-    decode[2-4] = ((float)(input[stbir__decode_order2])) * stbir__max_uint16_as_float_inverted;-    decode[3-4] = ((float)(input[stbir__decode_order3])) * stbir__max_uint16_as_float_inverted;-    decode += 4;-    input += 4;-  }-  decode -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( decode < decode_end )-  {-    STBIR_NO_UNROLL(decode);-    decode[0] = ((float)(input[stbir__decode_order0])) * stbir__max_uint16_as_float_inverted;-    #if stbir__coder_min_num >= 2-    decode[1] = ((float)(input[stbir__decode_order1])) * stbir__max_uint16_as_float_inverted;-    #endif-    #if stbir__coder_min_num >= 3-    decode[2] = ((float)(input[stbir__decode_order2])) * stbir__max_uint16_as_float_inverted;-    #endif-    decode += stbir__coder_min_num;-    input += stbir__coder_min_num;-  }-  #endif-}---static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * outputp, int width_times_channels, float const * encode )-{-  unsigned short STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned short*) outputp;-  unsigned short * end_output = ( (unsigned short*) output ) + width_times_channels;--  #ifdef STBIR_SIMD-  {-    if ( width_times_channels >= stbir__simdfX_float_count*2 )-    {-      float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2;-      end_output -= stbir__simdfX_float_count*2;-      for(;;)-      {-        stbir__simdfX e0, e1;-        stbir__simdiX i;-        STBIR_SIMD_NO_UNROLL(encode);-        stbir__simdfX_madd_mem( e0, STBIR_simd_point5X, STBIR_max_uint16_as_floatX, encode );-        stbir__simdfX_madd_mem( e1, STBIR_simd_point5X, STBIR_max_uint16_as_floatX, encode+stbir__simdfX_float_count );-        stbir__encode_simdfX_unflip( e0 );-        stbir__encode_simdfX_unflip( e1 );-        stbir__simdfX_pack_to_words( i, e0, e1 );-        stbir__simdiX_store( output, i );-        encode += stbir__simdfX_float_count*2;-        output += stbir__simdfX_float_count*2;-        if ( output <= end_output ) -          continue;-        if ( output == ( end_output + stbir__simdfX_float_count*2 ) )-          break;-        output = end_output;     // backup and do last couple-        encode = end_encode_m8;-      }-      return;-    }-  }--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    stbir__simdf e;-    stbir__simdi i;-    STBIR_NO_UNROLL(encode);-    stbir__simdf_load( e, encode );-    stbir__simdf_madd( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), e );-    stbir__encode_simdf4_unflip( e );-    stbir__simdf_pack_to_8words( i, e, e );  // only use first 4-    stbir__simdi_store2( output-4, i );-    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( output < end_output )-  {-    stbir__simdf e;-    STBIR_NO_UNROLL(encode);-    stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_short( e );-    #if stbir__coder_min_num >= 2-    stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order1 ); output[1] = stbir__simdf_convert_float_to_short( e );-    #endif-    #if stbir__coder_min_num >= 3-    stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order2 ); output[2] = stbir__simdf_convert_float_to_short( e );-    #endif-    output += stbir__coder_min_num;-    encode += stbir__coder_min_num;-  }-  #endif-  -  #else--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    float f;-    STBIR_SIMD_NO_UNROLL(encode);-    f = encode[stbir__encode_order0] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0-4] = (unsigned short)f;-    f = encode[stbir__encode_order1] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1-4] = (unsigned short)f;-    f = encode[stbir__encode_order2] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2-4] = (unsigned short)f;-    f = encode[stbir__encode_order3] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[3-4] = (unsigned short)f;-    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( output < end_output )-  {-    float f;-    STBIR_NO_UNROLL(encode);-    f = encode[stbir__encode_order0] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0] = (unsigned short)f;-    #if stbir__coder_min_num >= 2-    f = encode[stbir__encode_order1] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1] = (unsigned short)f;-    #endif-    #if stbir__coder_min_num >= 3-    f = encode[stbir__encode_order2] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2] = (unsigned short)f;-    #endif-    output += stbir__coder_min_num;-    encode += stbir__coder_min_num;-  }-  #endif-  #endif-}--static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int width_times_channels, void const * inputp )-{-  float STBIR_STREAMOUT_PTR( * ) decode = decodep;-  float * decode_end = (float*) decode + width_times_channels;-  unsigned short const * input = (unsigned short const *)inputp;--  #ifdef STBIR_SIMD-  unsigned short const * end_input_m8 = input + width_times_channels - 8;-  if ( width_times_channels >= 8 )-  {-    decode_end -= 8;-    for(;;)-    {-      #ifdef STBIR_SIMD8-      stbir__simdi i; stbir__simdi8 o;-      stbir__simdf8 of;-      STBIR_NO_UNROLL(decode);-      stbir__simdi_load( i, input );-      stbir__simdi8_expand_u16_to_u32( o, i );-      stbir__simdi8_convert_i32_to_float( of, o );-      stbir__decode_simdf8_flip( of );-      stbir__simdf8_store( decode + 0, of );-      #else-      stbir__simdi i, o0, o1;-      stbir__simdf of0, of1;-      STBIR_NO_UNROLL(decode);-      stbir__simdi_load( i, input );-      stbir__simdi_expand_u16_to_u32( o0, o1, i );-      stbir__simdi_convert_i32_to_float( of0, o0 );-      stbir__simdi_convert_i32_to_float( of1, o1 );-      stbir__decode_simdf4_flip( of0 );-      stbir__decode_simdf4_flip( of1 );-      stbir__simdf_store( decode + 0,  of0 );-      stbir__simdf_store( decode + 4,  of1 );-      #endif-      decode += 8;-      input += 8;-      if ( decode <= decode_end ) -        continue;-      if ( decode == ( decode_end + 8 ) )-        break;-      decode = decode_end; // backup and do last couple-      input = end_input_m8;-    }-    return;-  }-  #endif--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  decode += 4;-  while( decode <= decode_end )-  {-    STBIR_SIMD_NO_UNROLL(decode);-    decode[0-4] = ((float)(input[stbir__decode_order0]));-    decode[1-4] = ((float)(input[stbir__decode_order1]));-    decode[2-4] = ((float)(input[stbir__decode_order2]));-    decode[3-4] = ((float)(input[stbir__decode_order3]));-    decode += 4;-    input += 4;-  }-  decode -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( decode < decode_end )-  {-    STBIR_NO_UNROLL(decode);-    decode[0] = ((float)(input[stbir__decode_order0]));-    #if stbir__coder_min_num >= 2-    decode[1] = ((float)(input[stbir__decode_order1]));-    #endif-    #if stbir__coder_min_num >= 3-    decode[2] = ((float)(input[stbir__decode_order2]));-    #endif-    decode += stbir__coder_min_num;-    input += stbir__coder_min_num;-  }-  #endif-}--static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int width_times_channels, float const * encode )-{-  unsigned short STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned short*) outputp;-  unsigned short * end_output = ( (unsigned short*) output ) + width_times_channels;--  #ifdef STBIR_SIMD-  {-    if ( width_times_channels >= stbir__simdfX_float_count*2 )-    {-      float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2;-      end_output -= stbir__simdfX_float_count*2;-      for(;;)-      {-        stbir__simdfX e0, e1;-        stbir__simdiX i;-        STBIR_SIMD_NO_UNROLL(encode);-        stbir__simdfX_add_mem( e0, STBIR_simd_point5X, encode );-        stbir__simdfX_add_mem( e1, STBIR_simd_point5X, encode+stbir__simdfX_float_count );-        stbir__encode_simdfX_unflip( e0 );-        stbir__encode_simdfX_unflip( e1 );-        stbir__simdfX_pack_to_words( i, e0, e1 );-        stbir__simdiX_store( output, i );-        encode += stbir__simdfX_float_count*2;-        output += stbir__simdfX_float_count*2;-        if ( output <= end_output ) -          continue;-        if ( output == ( end_output + stbir__simdfX_float_count*2 ) )-          break;-        output = end_output; // backup and do last couple-        encode = end_encode_m8;-      }-      return;-    }-  }--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    stbir__simdf e;-    stbir__simdi i;-    STBIR_NO_UNROLL(encode);-    stbir__simdf_load( e, encode );-    stbir__simdf_add( e, STBIR__CONSTF(STBIR_simd_point5), e );-    stbir__encode_simdf4_unflip( e );-    stbir__simdf_pack_to_8words( i, e, e );  // only use first 4-    stbir__simdi_store2( output-4, i );-    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  #else--  // try to do blocks of 4 when you can-  #if  stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    float f;-    STBIR_SIMD_NO_UNROLL(encode);-    f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0-4] = (unsigned short)f;-    f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1-4] = (unsigned short)f;-    f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2-4] = (unsigned short)f;-    f = encode[stbir__encode_order3] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[3-4] = (unsigned short)f;-    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( output < end_output )-  {-    float f;-    STBIR_NO_UNROLL(encode);-    f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0] = (unsigned short)f;-    #if stbir__coder_min_num >= 2-    f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1] = (unsigned short)f;-    #endif-    #if stbir__coder_min_num >= 3-    f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2] = (unsigned short)f;-    #endif-    output += stbir__coder_min_num;-    encode += stbir__coder_min_num;-  }-  #endif-}--static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, int width_times_channels, void const * inputp )-{-  float STBIR_STREAMOUT_PTR( * ) decode = decodep;-  float * decode_end = (float*) decode + width_times_channels;-  stbir__FP16 const * input = (stbir__FP16 const *)inputp;--  #ifdef STBIR_SIMD-  if ( width_times_channels >= 8 )-  {-    stbir__FP16 const * end_input_m8 = input + width_times_channels - 8;-    decode_end -= 8;-    for(;;)-    {-      STBIR_NO_UNROLL(decode);--      stbir__half_to_float_SIMD( decode, input );-      #ifdef stbir__decode_swizzle-      #ifdef STBIR_SIMD8-      {-        stbir__simdf8 of;-        stbir__simdf8_load( of, decode );-        stbir__decode_simdf8_flip( of );-        stbir__simdf8_store( decode, of );-      }-      #else-      {-        stbir__simdf of0,of1;-        stbir__simdf_load( of0, decode );-        stbir__simdf_load( of1, decode+4 );-        stbir__decode_simdf4_flip( of0 );-        stbir__decode_simdf4_flip( of1 );-        stbir__simdf_store( decode, of0 );-        stbir__simdf_store( decode+4, of1 );-      }-      #endif-      #endif-      decode += 8;-      input += 8;-      if ( decode <= decode_end ) -        continue;-      if ( decode == ( decode_end + 8 ) )-        break;-      decode = decode_end; // backup and do last couple-      input = end_input_m8;-    }-    return;-  }-  #endif--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  decode += 4;-  while( decode <= decode_end )-  {-    STBIR_SIMD_NO_UNROLL(decode);-    decode[0-4] = stbir__half_to_float(input[stbir__decode_order0]);-    decode[1-4] = stbir__half_to_float(input[stbir__decode_order1]);-    decode[2-4] = stbir__half_to_float(input[stbir__decode_order2]);-    decode[3-4] = stbir__half_to_float(input[stbir__decode_order3]);-    decode += 4;-    input += 4;-  }-  decode -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( decode < decode_end )-  {-    STBIR_NO_UNROLL(decode);-    decode[0] = stbir__half_to_float(input[stbir__decode_order0]);-    #if stbir__coder_min_num >= 2-    decode[1] = stbir__half_to_float(input[stbir__decode_order1]);-    #endif-    #if stbir__coder_min_num >= 3-    decode[2] = stbir__half_to_float(input[stbir__decode_order2]);-    #endif-    decode += stbir__coder_min_num;-    input += stbir__coder_min_num;-  }-  #endif-}--static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp, int width_times_channels, float const * encode )-{-  stbir__FP16 STBIR_SIMD_STREAMOUT_PTR( * ) output = (stbir__FP16*) outputp;-  stbir__FP16 * end_output = ( (stbir__FP16*) output ) + width_times_channels;--  #ifdef STBIR_SIMD-  if ( width_times_channels >= 8 )-  {-    float const * end_encode_m8 = encode + width_times_channels - 8;-    end_output -= 8;-    for(;;)-    {-      STBIR_SIMD_NO_UNROLL(encode);-      #ifdef stbir__decode_swizzle-      #ifdef STBIR_SIMD8-      {-        stbir__simdf8 of;-        stbir__simdf8_load( of, encode );-        stbir__encode_simdf8_unflip( of );-        stbir__float_to_half_SIMD( output, (float*)&of );-      }-      #else-      {-        stbir__simdf of[2];-        stbir__simdf_load( of[0], encode );-        stbir__simdf_load( of[1], encode+4 );-        stbir__encode_simdf4_unflip( of[0] );-        stbir__encode_simdf4_unflip( of[1] );-        stbir__float_to_half_SIMD( output, (float*)of );-      }-      #endif-      #else-      stbir__float_to_half_SIMD( output, encode );-      #endif-      encode += 8;-      output += 8;-      if ( output <= end_output ) -        continue;-      if ( output == ( end_output + 8 ) )-        break;-      output = end_output; // backup and do last couple-      encode = end_encode_m8;-    }-    return;-  }-  #endif--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    STBIR_SIMD_NO_UNROLL(output);-    output[0-4] = stbir__float_to_half(encode[stbir__encode_order0]);-    output[1-4] = stbir__float_to_half(encode[stbir__encode_order1]);-    output[2-4] = stbir__float_to_half(encode[stbir__encode_order2]);-    output[3-4] = stbir__float_to_half(encode[stbir__encode_order3]);-    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( output < end_output )-  {-    STBIR_NO_UNROLL(output);-    output[0] = stbir__float_to_half(encode[stbir__encode_order0]);-    #if stbir__coder_min_num >= 2-    output[1] = stbir__float_to_half(encode[stbir__encode_order1]);-    #endif-    #if stbir__coder_min_num >= 3-    output[2] = stbir__float_to_half(encode[stbir__encode_order2]);-    #endif-    output += stbir__coder_min_num;-    encode += stbir__coder_min_num;-  }-  #endif-}--static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int width_times_channels, void const * inputp )-{-  #ifdef stbir__decode_swizzle-  float STBIR_STREAMOUT_PTR( * ) decode = decodep;-  float * decode_end = (float*) decode + width_times_channels;-  float const * input = (float const *)inputp;--  #ifdef STBIR_SIMD-  if ( width_times_channels >= 16 )-  {-    float const * end_input_m16 = input + width_times_channels - 16;-    decode_end -= 16;-    for(;;)-    {-      STBIR_NO_UNROLL(decode);-      #ifdef stbir__decode_swizzle-      #ifdef STBIR_SIMD8-      {-        stbir__simdf8 of0,of1;-        stbir__simdf8_load( of0, input );-        stbir__simdf8_load( of1, input+8 );-        stbir__decode_simdf8_flip( of0 );-        stbir__decode_simdf8_flip( of1 );-        stbir__simdf8_store( decode, of0 );-        stbir__simdf8_store( decode+8, of1 );-      }-      #else-      {-        stbir__simdf of0,of1,of2,of3;-        stbir__simdf_load( of0, input );-        stbir__simdf_load( of1, input+4 );-        stbir__simdf_load( of2, input+8 );-        stbir__simdf_load( of3, input+12 );-        stbir__decode_simdf4_flip( of0 );-        stbir__decode_simdf4_flip( of1 );-        stbir__decode_simdf4_flip( of2 );-        stbir__decode_simdf4_flip( of3 );-        stbir__simdf_store( decode, of0 );-        stbir__simdf_store( decode+4, of1 );-        stbir__simdf_store( decode+8, of2 );-        stbir__simdf_store( decode+12, of3 );-      }-      #endif-      #endif-      decode += 16;-      input += 16;-      if ( decode <= decode_end ) -        continue;-      if ( decode == ( decode_end + 16 ) )-        break;-      decode = decode_end; // backup and do last couple-      input = end_input_m16;-    }-    return;-  }-  #endif--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  decode += 4;-  while( decode <= decode_end )-  {-    STBIR_SIMD_NO_UNROLL(decode);-    decode[0-4] = input[stbir__decode_order0];-    decode[1-4] = input[stbir__decode_order1];-    decode[2-4] = input[stbir__decode_order2];-    decode[3-4] = input[stbir__decode_order3];-    decode += 4;-    input += 4;-  }-  decode -= 4;-  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( decode < decode_end )-  {-    STBIR_NO_UNROLL(decode);-    decode[0] = input[stbir__decode_order0];-    #if stbir__coder_min_num >= 2-    decode[1] = input[stbir__decode_order1];-    #endif-    #if stbir__coder_min_num >= 3-    decode[2] = input[stbir__decode_order2];-    #endif-    decode += stbir__coder_min_num;-    input += stbir__coder_min_num;-  }-  #endif--  #else-  -  if ( (void*)decodep != inputp )-    STBIR_MEMCPY( decodep, inputp, width_times_channels * sizeof( float ) );-  -  #endif-}--static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int width_times_channels, float const * encode )-{-  #if !defined( STBIR_FLOAT_HIGH_CLAMP ) && !defined(STBIR_FLOAT_LO_CLAMP) && !defined(stbir__decode_swizzle)--  if ( (void*)outputp != (void*) encode )-    STBIR_MEMCPY( outputp, encode, width_times_channels * sizeof( float ) );--  #else--  float STBIR_SIMD_STREAMOUT_PTR( * ) output = (float*) outputp;-  float * end_output = ( (float*) output ) + width_times_channels;--  #ifdef STBIR_FLOAT_HIGH_CLAMP-  #define stbir_scalar_hi_clamp( v ) if ( v > STBIR_FLOAT_HIGH_CLAMP ) v = STBIR_FLOAT_HIGH_CLAMP;-  #else-  #define stbir_scalar_hi_clamp( v )-  #endif-  #ifdef STBIR_FLOAT_LOW_CLAMP-  #define stbir_scalar_lo_clamp( v ) if ( v < STBIR_FLOAT_LOW_CLAMP ) v = STBIR_FLOAT_LOW_CLAMP;-  #else-  #define stbir_scalar_lo_clamp( v )-  #endif--  #ifdef STBIR_SIMD--  #ifdef STBIR_FLOAT_HIGH_CLAMP-  const stbir__simdfX high_clamp = stbir__simdf_frepX(STBIR_FLOAT_HIGH_CLAMP);-  #endif-  #ifdef STBIR_FLOAT_LOW_CLAMP-  const stbir__simdfX low_clamp = stbir__simdf_frepX(STBIR_FLOAT_LOW_CLAMP);-  #endif--  if ( width_times_channels >= ( stbir__simdfX_float_count * 2 ) )-  {-    float const * end_encode_m8 = encode + width_times_channels - ( stbir__simdfX_float_count * 2 );-    end_output -= ( stbir__simdfX_float_count * 2 );-    for(;;)-    {-      stbir__simdfX e0, e1;-      STBIR_SIMD_NO_UNROLL(encode);-      stbir__simdfX_load( e0, encode );-      stbir__simdfX_load( e1, encode+stbir__simdfX_float_count );-#ifdef STBIR_FLOAT_HIGH_CLAMP-      stbir__simdfX_min( e0, e0, high_clamp );-      stbir__simdfX_min( e1, e1, high_clamp );-#endif      -#ifdef STBIR_FLOAT_LOW_CLAMP-      stbir__simdfX_max( e0, e0, low_clamp );-      stbir__simdfX_max( e1, e1, low_clamp );-#endif      -      stbir__encode_simdfX_unflip( e0 );-      stbir__encode_simdfX_unflip( e1 );-      stbir__simdfX_store( output, e0 );-      stbir__simdfX_store( output+stbir__simdfX_float_count, e1 );-      encode += stbir__simdfX_float_count * 2;-      output += stbir__simdfX_float_count * 2;-      if ( output < end_output ) -        continue;-      if ( output == ( end_output + ( stbir__simdfX_float_count * 2 ) ) )-        break;-      output = end_output; // backup and do last couple-      encode = end_encode_m8;-    }-    return;-  }--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    stbir__simdf e0;-    STBIR_NO_UNROLL(encode);-    stbir__simdf_load( e0, encode );-#ifdef STBIR_FLOAT_HIGH_CLAMP-    stbir__simdf_min( e0, e0, high_clamp );-#endif      -#ifdef STBIR_FLOAT_LOW_CLAMP-    stbir__simdf_max( e0, e0, low_clamp );-#endif      -    stbir__encode_simdf4_unflip( e0 );-    stbir__simdf_store( output-4, e0 );-    output += 4;-    encode += 4;-  }-  output -= 4;-  #endif--  #else--  // try to do blocks of 4 when you can-  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four-  output += 4;-  while( output <= end_output )-  {-    float e;-    STBIR_SIMD_NO_UNROLL(encode);-    e = encode[ stbir__encode_order0 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[0-4] = e;-    e = encode[ stbir__encode_order1 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[1-4] = e;-    e = encode[ stbir__encode_order2 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[2-4] = e;-    e = encode[ stbir__encode_order3 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[3-4] = e;-    output += 4;-    encode += 4;-  }-  output -= 4;--  #endif--  #endif--  // do the remnants-  #if stbir__coder_min_num < 4-  while( output < end_output )-  {-    float e;-    STBIR_NO_UNROLL(encode);-    e = encode[ stbir__encode_order0 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[0] = e;-    #if stbir__coder_min_num >= 2-    e = encode[ stbir__encode_order1 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[1] = e;-    #endif-    #if stbir__coder_min_num >= 3-    e = encode[ stbir__encode_order2 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[2] = e;-    #endif-    output += stbir__coder_min_num;-    encode += stbir__coder_min_num;-  }-  #endif-  -  #endif-}--#undef stbir__decode_suffix -#undef stbir__decode_simdf8_flip-#undef stbir__decode_simdf4_flip-#undef stbir__decode_order0 -#undef stbir__decode_order1-#undef stbir__decode_order2-#undef stbir__decode_order3-#undef stbir__encode_order0 -#undef stbir__encode_order1-#undef stbir__encode_order2-#undef stbir__encode_order3-#undef stbir__encode_simdf8_unflip-#undef stbir__encode_simdf4_unflip-#undef stbir__encode_simdfX_unflip-#undef STBIR__CODER_NAME-#undef stbir__coder_min_num-#undef stbir__decode_swizzle-#undef stbir_scalar_hi_clamp-#undef stbir_scalar_lo_clamp-#undef STB_IMAGE_RESIZE_DO_CODERS--#elif defined( STB_IMAGE_RESIZE_DO_VERTICALS)--#ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#define STBIR_chans( start, end ) STBIR_strs_join14(start,STBIR__vertical_channels,end,_cont)-#else-#define STBIR_chans( start, end ) STBIR_strs_join1(start,STBIR__vertical_channels,end)-#endif--#if STBIR__vertical_channels >= 1-#define stbIF0( code ) code-#else-#define stbIF0( code )-#endif-#if STBIR__vertical_channels >= 2-#define stbIF1( code ) code-#else-#define stbIF1( code )-#endif-#if STBIR__vertical_channels >= 3-#define stbIF2( code ) code-#else-#define stbIF2( code )-#endif-#if STBIR__vertical_channels >= 4-#define stbIF3( code ) code-#else-#define stbIF3( code )-#endif-#if STBIR__vertical_channels >= 5-#define stbIF4( code ) code-#else-#define stbIF4( code )-#endif-#if STBIR__vertical_channels >= 6-#define stbIF5( code ) code-#else-#define stbIF5( code )-#endif-#if STBIR__vertical_channels >= 7-#define stbIF6( code ) code-#else-#define stbIF6( code )-#endif-#if STBIR__vertical_channels >= 8-#define stbIF7( code ) code-#else-#define stbIF7( code )-#endif--static void STBIR_chans( stbir__vertical_scatter_with_,_coeffs)( float ** outputs, float const * vertical_coefficients, float const * input, float const * input_end )-{-  stbIF0( float STBIR_SIMD_STREAMOUT_PTR( * ) output0 = outputs[0]; float c0s = vertical_coefficients[0]; )-  stbIF1( float STBIR_SIMD_STREAMOUT_PTR( * ) output1 = outputs[1]; float c1s = vertical_coefficients[1]; )-  stbIF2( float STBIR_SIMD_STREAMOUT_PTR( * ) output2 = outputs[2]; float c2s = vertical_coefficients[2]; )-  stbIF3( float STBIR_SIMD_STREAMOUT_PTR( * ) output3 = outputs[3]; float c3s = vertical_coefficients[3]; )-  stbIF4( float STBIR_SIMD_STREAMOUT_PTR( * ) output4 = outputs[4]; float c4s = vertical_coefficients[4]; )-  stbIF5( float STBIR_SIMD_STREAMOUT_PTR( * ) output5 = outputs[5]; float c5s = vertical_coefficients[5]; )-  stbIF6( float STBIR_SIMD_STREAMOUT_PTR( * ) output6 = outputs[6]; float c6s = vertical_coefficients[6]; )-  stbIF7( float STBIR_SIMD_STREAMOUT_PTR( * ) output7 = outputs[7]; float c7s = vertical_coefficients[7]; )--  #ifdef STBIR_SIMD-  {-    stbIF0(stbir__simdfX c0 = stbir__simdf_frepX( c0s ); )-    stbIF1(stbir__simdfX c1 = stbir__simdf_frepX( c1s ); )-    stbIF2(stbir__simdfX c2 = stbir__simdf_frepX( c2s ); )-    stbIF3(stbir__simdfX c3 = stbir__simdf_frepX( c3s ); )-    stbIF4(stbir__simdfX c4 = stbir__simdf_frepX( c4s ); )-    stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); )-    stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); )-    stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); )-    while ( ( (char*)input_end - (char*) input ) >= (16*stbir__simdfX_float_count) ) -    {-      stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3;-      STBIR_SIMD_NO_UNROLL(output0);--      stbir__simdfX_load( r0, input );               stbir__simdfX_load( r1, input+stbir__simdfX_float_count );     stbir__simdfX_load( r2, input+(2*stbir__simdfX_float_count) );      stbir__simdfX_load( r3, input+(3*stbir__simdfX_float_count) );--      #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-      stbIF0( stbir__simdfX_load( o0, output0 );     stbir__simdfX_load( o1, output0+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output0+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output0+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c0 );  stbir__simdfX_madd( o1, o1, r1, c0 );  stbir__simdfX_madd( o2, o2, r2, c0 );   stbir__simdfX_madd( o3, o3, r3, c0 );           -              stbir__simdfX_store( output0, o0 );    stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); )-      stbIF1( stbir__simdfX_load( o0, output1 );     stbir__simdfX_load( o1, output1+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output1+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output1+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c1 );  stbir__simdfX_madd( o1, o1, r1, c1 );  stbir__simdfX_madd( o2, o2, r2, c1 );   stbir__simdfX_madd( o3, o3, r3, c1 );             -              stbir__simdfX_store( output1, o0 );    stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); )-      stbIF2( stbir__simdfX_load( o0, output2 );     stbir__simdfX_load( o1, output2+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output2+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output2+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c2 );  stbir__simdfX_madd( o1, o1, r1, c2 );  stbir__simdfX_madd( o2, o2, r2, c2 );   stbir__simdfX_madd( o3, o3, r3, c2 );             -              stbir__simdfX_store( output2, o0 );    stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); )-      stbIF3( stbir__simdfX_load( o0, output3 );     stbir__simdfX_load( o1, output3+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output3+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output3+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c3 );  stbir__simdfX_madd( o1, o1, r1, c3 );  stbir__simdfX_madd( o2, o2, r2, c3 );   stbir__simdfX_madd( o3, o3, r3, c3 );             -              stbir__simdfX_store( output3, o0 );    stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); )-      stbIF4( stbir__simdfX_load( o0, output4 );     stbir__simdfX_load( o1, output4+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output4+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output4+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c4 );  stbir__simdfX_madd( o1, o1, r1, c4 );  stbir__simdfX_madd( o2, o2, r2, c4 );   stbir__simdfX_madd( o3, o3, r3, c4 );             -              stbir__simdfX_store( output4, o0 );    stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); )-      stbIF5( stbir__simdfX_load( o0, output5 );     stbir__simdfX_load( o1, output5+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output5+(2*stbir__simdfX_float_count));    stbir__simdfX_load( o3, output5+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c5 );  stbir__simdfX_madd( o1, o1, r1, c5 );  stbir__simdfX_madd( o2, o2, r2, c5 );   stbir__simdfX_madd( o3, o3, r3, c5 );             -              stbir__simdfX_store( output5, o0 );    stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); )-      stbIF6( stbir__simdfX_load( o0, output6 );     stbir__simdfX_load( o1, output6+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output6+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output6+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c6 );  stbir__simdfX_madd( o1, o1, r1, c6 );  stbir__simdfX_madd( o2, o2, r2, c6 );   stbir__simdfX_madd( o3, o3, r3, c6 );             -              stbir__simdfX_store( output6, o0 );    stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); )-      stbIF7( stbir__simdfX_load( o0, output7 );     stbir__simdfX_load( o1, output7+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output7+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output7+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c7 );  stbir__simdfX_madd( o1, o1, r1, c7 );  stbir__simdfX_madd( o2, o2, r2, c7 );   stbir__simdfX_madd( o3, o3, r3, c7 );             -              stbir__simdfX_store( output7, o0 );    stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); )-      #else-      stbIF0( stbir__simdfX_mult( o0, r0, c0 );      stbir__simdfX_mult( o1, r1, c0 );      stbir__simdfX_mult( o2, r2, c0 );       stbir__simdfX_mult( o3, r3, c0 );  -              stbir__simdfX_store( output0, o0 );    stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); )-      stbIF1( stbir__simdfX_mult( o0, r0, c1 );      stbir__simdfX_mult( o1, r1, c1 );      stbir__simdfX_mult( o2, r2, c1 );       stbir__simdfX_mult( o3, r3, c1 );  -              stbir__simdfX_store( output1, o0 );    stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); )-      stbIF2( stbir__simdfX_mult( o0, r0, c2 );      stbir__simdfX_mult( o1, r1, c2 );      stbir__simdfX_mult( o2, r2, c2 );       stbir__simdfX_mult( o3, r3, c2 );  -              stbir__simdfX_store( output2, o0 );    stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); )-      stbIF3( stbir__simdfX_mult( o0, r0, c3 );      stbir__simdfX_mult( o1, r1, c3 );      stbir__simdfX_mult( o2, r2, c3 );       stbir__simdfX_mult( o3, r3, c3 );  -              stbir__simdfX_store( output3, o0 );    stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); )-      stbIF4( stbir__simdfX_mult( o0, r0, c4 );      stbir__simdfX_mult( o1, r1, c4 );      stbir__simdfX_mult( o2, r2, c4 );       stbir__simdfX_mult( o3, r3, c4 );  -              stbir__simdfX_store( output4, o0 );    stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); )-      stbIF5( stbir__simdfX_mult( o0, r0, c5 );      stbir__simdfX_mult( o1, r1, c5 );      stbir__simdfX_mult( o2, r2, c5 );       stbir__simdfX_mult( o3, r3, c5 );  -              stbir__simdfX_store( output5, o0 );    stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); )-      stbIF6( stbir__simdfX_mult( o0, r0, c6 );      stbir__simdfX_mult( o1, r1, c6 );      stbir__simdfX_mult( o2, r2, c6 );       stbir__simdfX_mult( o3, r3, c6 );  -              stbir__simdfX_store( output6, o0 );    stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); )-      stbIF7( stbir__simdfX_mult( o0, r0, c7 );      stbir__simdfX_mult( o1, r1, c7 );      stbir__simdfX_mult( o2, r2, c7 );       stbir__simdfX_mult( o3, r3, c7 );  -              stbir__simdfX_store( output7, o0 );    stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); )-      #endif--      input += (4*stbir__simdfX_float_count);-      stbIF0( output0 += (4*stbir__simdfX_float_count); ) stbIF1( output1 += (4*stbir__simdfX_float_count); ) stbIF2( output2 += (4*stbir__simdfX_float_count); ) stbIF3( output3 += (4*stbir__simdfX_float_count); ) stbIF4( output4 += (4*stbir__simdfX_float_count); ) stbIF5( output5 += (4*stbir__simdfX_float_count); ) stbIF6( output6 += (4*stbir__simdfX_float_count); ) stbIF7( output7 += (4*stbir__simdfX_float_count); )-    }-    while ( ( (char*)input_end - (char*) input ) >= 16 ) -    {-      stbir__simdf o0, r0;-      STBIR_SIMD_NO_UNROLL(output0);--      stbir__simdf_load( r0, input );--      #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-      stbIF0( stbir__simdf_load( o0, output0 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) );  stbir__simdf_store( output0, o0 ); )-      stbIF1( stbir__simdf_load( o0, output1 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) );  stbir__simdf_store( output1, o0 ); )-      stbIF2( stbir__simdf_load( o0, output2 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) );  stbir__simdf_store( output2, o0 ); )-      stbIF3( stbir__simdf_load( o0, output3 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) );  stbir__simdf_store( output3, o0 ); )-      stbIF4( stbir__simdf_load( o0, output4 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) );  stbir__simdf_store( output4, o0 ); )-      stbIF5( stbir__simdf_load( o0, output5 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) );  stbir__simdf_store( output5, o0 ); )-      stbIF6( stbir__simdf_load( o0, output6 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) );  stbir__simdf_store( output6, o0 ); )-      stbIF7( stbir__simdf_load( o0, output7 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) );  stbir__simdf_store( output7, o0 ); )-      #else-      stbIF0( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) );   stbir__simdf_store( output0, o0 ); )-      stbIF1( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) );   stbir__simdf_store( output1, o0 ); )-      stbIF2( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) );   stbir__simdf_store( output2, o0 ); )-      stbIF3( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) );   stbir__simdf_store( output3, o0 ); )-      stbIF4( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) );   stbir__simdf_store( output4, o0 ); )-      stbIF5( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) );   stbir__simdf_store( output5, o0 ); )-      stbIF6( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) );   stbir__simdf_store( output6, o0 ); )-      stbIF7( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) );   stbir__simdf_store( output7, o0 ); )-      #endif-      -      input += 4;-      stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; )-    }-  }-  #else-  while ( ( (char*)input_end - (char*) input ) >= 16 ) -  {-    float r0, r1, r2, r3;-    STBIR_NO_UNROLL(input);--    r0 = input[0], r1 = input[1], r2 = input[2], r3 = input[3];--    #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-    stbIF0( output0[0] += ( r0 * c0s ); output0[1] += ( r1 * c0s ); output0[2] += ( r2 * c0s ); output0[3] += ( r3 * c0s ); )-    stbIF1( output1[0] += ( r0 * c1s ); output1[1] += ( r1 * c1s ); output1[2] += ( r2 * c1s ); output1[3] += ( r3 * c1s ); )-    stbIF2( output2[0] += ( r0 * c2s ); output2[1] += ( r1 * c2s ); output2[2] += ( r2 * c2s ); output2[3] += ( r3 * c2s ); )-    stbIF3( output3[0] += ( r0 * c3s ); output3[1] += ( r1 * c3s ); output3[2] += ( r2 * c3s ); output3[3] += ( r3 * c3s ); )-    stbIF4( output4[0] += ( r0 * c4s ); output4[1] += ( r1 * c4s ); output4[2] += ( r2 * c4s ); output4[3] += ( r3 * c4s ); )-    stbIF5( output5[0] += ( r0 * c5s ); output5[1] += ( r1 * c5s ); output5[2] += ( r2 * c5s ); output5[3] += ( r3 * c5s ); )-    stbIF6( output6[0] += ( r0 * c6s ); output6[1] += ( r1 * c6s ); output6[2] += ( r2 * c6s ); output6[3] += ( r3 * c6s ); )-    stbIF7( output7[0] += ( r0 * c7s ); output7[1] += ( r1 * c7s ); output7[2] += ( r2 * c7s ); output7[3] += ( r3 * c7s ); )-    #else-    stbIF0( output0[0]  = ( r0 * c0s ); output0[1]  = ( r1 * c0s ); output0[2]  = ( r2 * c0s ); output0[3]  = ( r3 * c0s ); )-    stbIF1( output1[0]  = ( r0 * c1s ); output1[1]  = ( r1 * c1s ); output1[2]  = ( r2 * c1s ); output1[3]  = ( r3 * c1s ); )-    stbIF2( output2[0]  = ( r0 * c2s ); output2[1]  = ( r1 * c2s ); output2[2]  = ( r2 * c2s ); output2[3]  = ( r3 * c2s ); )-    stbIF3( output3[0]  = ( r0 * c3s ); output3[1]  = ( r1 * c3s ); output3[2]  = ( r2 * c3s ); output3[3]  = ( r3 * c3s ); )-    stbIF4( output4[0]  = ( r0 * c4s ); output4[1]  = ( r1 * c4s ); output4[2]  = ( r2 * c4s ); output4[3]  = ( r3 * c4s ); )-    stbIF5( output5[0]  = ( r0 * c5s ); output5[1]  = ( r1 * c5s ); output5[2]  = ( r2 * c5s ); output5[3]  = ( r3 * c5s ); )-    stbIF6( output6[0]  = ( r0 * c6s ); output6[1]  = ( r1 * c6s ); output6[2]  = ( r2 * c6s ); output6[3]  = ( r3 * c6s ); )-    stbIF7( output7[0]  = ( r0 * c7s ); output7[1]  = ( r1 * c7s ); output7[2]  = ( r2 * c7s ); output7[3]  = ( r3 * c7s ); )-    #endif--    input += 4;-    stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; )-  }-  #endif-  while ( input < input_end ) -  {-    float r = input[0];-    STBIR_NO_UNROLL(output0);--    #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-    stbIF0( output0[0] += ( r * c0s ); )-    stbIF1( output1[0] += ( r * c1s ); )-    stbIF2( output2[0] += ( r * c2s ); )-    stbIF3( output3[0] += ( r * c3s ); )-    stbIF4( output4[0] += ( r * c4s ); )-    stbIF5( output5[0] += ( r * c5s ); )-    stbIF6( output6[0] += ( r * c6s ); )-    stbIF7( output7[0] += ( r * c7s ); )-    #else-    stbIF0( output0[0]  = ( r * c0s ); )-    stbIF1( output1[0]  = ( r * c1s ); )-    stbIF2( output2[0]  = ( r * c2s ); )-    stbIF3( output3[0]  = ( r * c3s ); )-    stbIF4( output4[0]  = ( r * c4s ); )-    stbIF5( output5[0]  = ( r * c5s ); )-    stbIF6( output6[0]  = ( r * c6s ); )-    stbIF7( output7[0]  = ( r * c7s ); )-    #endif--    ++input;-    stbIF0( ++output0; ) stbIF1( ++output1; ) stbIF2( ++output2; ) stbIF3( ++output3; ) stbIF4( ++output4; ) stbIF5( ++output5; ) stbIF6( ++output6; ) stbIF7( ++output7; )-  }-}--static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, float const * vertical_coefficients, float const ** inputs, float const * input0_end )-{-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = outputp;--  stbIF0( float const * input0 = inputs[0]; float c0s = vertical_coefficients[0]; )-  stbIF1( float const * input1 = inputs[1]; float c1s = vertical_coefficients[1]; )-  stbIF2( float const * input2 = inputs[2]; float c2s = vertical_coefficients[2]; )-  stbIF3( float const * input3 = inputs[3]; float c3s = vertical_coefficients[3]; )-  stbIF4( float const * input4 = inputs[4]; float c4s = vertical_coefficients[4]; )-  stbIF5( float const * input5 = inputs[5]; float c5s = vertical_coefficients[5]; )-  stbIF6( float const * input6 = inputs[6]; float c6s = vertical_coefficients[6]; )-  stbIF7( float const * input7 = inputs[7]; float c7s = vertical_coefficients[7]; )--#if ( STBIR__vertical_channels == 1 ) && !defined(STB_IMAGE_RESIZE_VERTICAL_CONTINUE)-  // check single channel one weight-  if ( ( c0s >= (1.0f-0.000001f) ) && ( c0s <= (1.0f+0.000001f) ) )-  {-    STBIR_MEMCPY( output, input0, (char*)input0_end - (char*)input0 );-    return;-  }-#endif  --  #ifdef STBIR_SIMD-  {-    stbIF0(stbir__simdfX c0 = stbir__simdf_frepX( c0s ); )-    stbIF1(stbir__simdfX c1 = stbir__simdf_frepX( c1s ); )-    stbIF2(stbir__simdfX c2 = stbir__simdf_frepX( c2s ); )-    stbIF3(stbir__simdfX c3 = stbir__simdf_frepX( c3s ); )-    stbIF4(stbir__simdfX c4 = stbir__simdf_frepX( c4s ); )-    stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); )-    stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); )-    stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); )-    -    while ( ( (char*)input0_end - (char*) input0 ) >= (16*stbir__simdfX_float_count) ) -    {-      stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3;-      STBIR_SIMD_NO_UNROLL(output);--      // prefetch four loop iterations ahead (doesn't affect much for small resizes, but helps with big ones)-      stbIF0( stbir__prefetch( input0 + (16*stbir__simdfX_float_count) ); ) -      stbIF1( stbir__prefetch( input1 + (16*stbir__simdfX_float_count) ); )-      stbIF2( stbir__prefetch( input2 + (16*stbir__simdfX_float_count) ); )-      stbIF3( stbir__prefetch( input3 + (16*stbir__simdfX_float_count) ); )-      stbIF4( stbir__prefetch( input4 + (16*stbir__simdfX_float_count) ); )-      stbIF5( stbir__prefetch( input5 + (16*stbir__simdfX_float_count) ); )-      stbIF6( stbir__prefetch( input6 + (16*stbir__simdfX_float_count) ); )-      stbIF7( stbir__prefetch( input7 + (16*stbir__simdfX_float_count) ); )--      #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-      stbIF0( stbir__simdfX_load( o0, output );      stbir__simdfX_load( o1, output+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( o3, output+(3*stbir__simdfX_float_count) );-              stbir__simdfX_load( r0, input0 );      stbir__simdfX_load( r1, input0+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input0+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input0+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c0 );  stbir__simdfX_madd( o1, o1, r1, c0 );                         stbir__simdfX_madd( o2, o2, r2, c0 );                             stbir__simdfX_madd( o3, o3, r3, c0 ); )-      #else-      stbIF0( stbir__simdfX_load( r0, input0 );      stbir__simdfX_load( r1, input0+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input0+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input0+(3*stbir__simdfX_float_count) );-              stbir__simdfX_mult( o0, r0, c0 );      stbir__simdfX_mult( o1, r1, c0 );                             stbir__simdfX_mult( o2, r2, c0 );                                 stbir__simdfX_mult( o3, r3, c0 );  )-      #endif--      stbIF1( stbir__simdfX_load( r0, input1 );      stbir__simdfX_load( r1, input1+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input1+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input1+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c1 );  stbir__simdfX_madd( o1, o1, r1, c1 );                         stbir__simdfX_madd( o2, o2, r2, c1 );                             stbir__simdfX_madd( o3, o3, r3, c1 ); )-      stbIF2( stbir__simdfX_load( r0, input2 );      stbir__simdfX_load( r1, input2+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input2+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input2+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c2 );  stbir__simdfX_madd( o1, o1, r1, c2 );                         stbir__simdfX_madd( o2, o2, r2, c2 );                             stbir__simdfX_madd( o3, o3, r3, c2 ); )-      stbIF3( stbir__simdfX_load( r0, input3 );      stbir__simdfX_load( r1, input3+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input3+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input3+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c3 );  stbir__simdfX_madd( o1, o1, r1, c3 );                         stbir__simdfX_madd( o2, o2, r2, c3 );                             stbir__simdfX_madd( o3, o3, r3, c3 ); )-      stbIF4( stbir__simdfX_load( r0, input4 );      stbir__simdfX_load( r1, input4+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input4+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input4+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c4 );  stbir__simdfX_madd( o1, o1, r1, c4 );                         stbir__simdfX_madd( o2, o2, r2, c4 );                             stbir__simdfX_madd( o3, o3, r3, c4 ); )-      stbIF5( stbir__simdfX_load( r0, input5 );      stbir__simdfX_load( r1, input5+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input5+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input5+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c5 );  stbir__simdfX_madd( o1, o1, r1, c5 );                         stbir__simdfX_madd( o2, o2, r2, c5 );                             stbir__simdfX_madd( o3, o3, r3, c5 ); )-      stbIF6( stbir__simdfX_load( r0, input6 );      stbir__simdfX_load( r1, input6+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input6+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input6+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c6 );  stbir__simdfX_madd( o1, o1, r1, c6 );                         stbir__simdfX_madd( o2, o2, r2, c6 );                             stbir__simdfX_madd( o3, o3, r3, c6 ); )-      stbIF7( stbir__simdfX_load( r0, input7 );      stbir__simdfX_load( r1, input7+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input7+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input7+(3*stbir__simdfX_float_count) );-              stbir__simdfX_madd( o0, o0, r0, c7 );  stbir__simdfX_madd( o1, o1, r1, c7 );                         stbir__simdfX_madd( o2, o2, r2, c7 );                             stbir__simdfX_madd( o3, o3, r3, c7 ); )--      stbir__simdfX_store( output, o0 );             stbir__simdfX_store( output+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output+(2*stbir__simdfX_float_count), o2 );  stbir__simdfX_store( output+(3*stbir__simdfX_float_count), o3 );-      output += (4*stbir__simdfX_float_count);-      stbIF0( input0 += (4*stbir__simdfX_float_count); ) stbIF1( input1 += (4*stbir__simdfX_float_count); ) stbIF2( input2 += (4*stbir__simdfX_float_count); ) stbIF3( input3 += (4*stbir__simdfX_float_count); ) stbIF4( input4 += (4*stbir__simdfX_float_count); ) stbIF5( input5 += (4*stbir__simdfX_float_count); ) stbIF6( input6 += (4*stbir__simdfX_float_count); ) stbIF7( input7 += (4*stbir__simdfX_float_count); )-    }--    while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) -    {-      stbir__simdf o0, r0;-      STBIR_SIMD_NO_UNROLL(output);--      #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-      stbIF0( stbir__simdf_load( o0, output );   stbir__simdf_load( r0, input0 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); )-      #else-      stbIF0( stbir__simdf_load( r0, input0 );  stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); )-      #endif-      stbIF1( stbir__simdf_load( r0, input1 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); )-      stbIF2( stbir__simdf_load( r0, input2 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); )-      stbIF3( stbir__simdf_load( r0, input3 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); )-      stbIF4( stbir__simdf_load( r0, input4 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); )-      stbIF5( stbir__simdf_load( r0, input5 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); )-      stbIF6( stbir__simdf_load( r0, input6 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); )-      stbIF7( stbir__simdf_load( r0, input7 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); )--      stbir__simdf_store( output, o0 );-      output += 4;-      stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; )-    }-  }-  #else-  while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) -  {-    float o0, o1, o2, o3;-    STBIR_NO_UNROLL(output);-    #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-    stbIF0( o0 = output[0] + input0[0] * c0s; o1 = output[1] + input0[1] * c0s; o2 = output[2] + input0[2] * c0s; o3 = output[3] + input0[3] * c0s; )-    #else-    stbIF0( o0  = input0[0] * c0s; o1  = input0[1] * c0s; o2  = input0[2] * c0s; o3  = input0[3] * c0s; )-    #endif-    stbIF1( o0 += input1[0] * c1s; o1 += input1[1] * c1s; o2 += input1[2] * c1s; o3 += input1[3] * c1s; )-    stbIF2( o0 += input2[0] * c2s; o1 += input2[1] * c2s; o2 += input2[2] * c2s; o3 += input2[3] * c2s; )-    stbIF3( o0 += input3[0] * c3s; o1 += input3[1] * c3s; o2 += input3[2] * c3s; o3 += input3[3] * c3s; )-    stbIF4( o0 += input4[0] * c4s; o1 += input4[1] * c4s; o2 += input4[2] * c4s; o3 += input4[3] * c4s; )-    stbIF5( o0 += input5[0] * c5s; o1 += input5[1] * c5s; o2 += input5[2] * c5s; o3 += input5[3] * c5s; )-    stbIF6( o0 += input6[0] * c6s; o1 += input6[1] * c6s; o2 += input6[2] * c6s; o3 += input6[3] * c6s; )-    stbIF7( o0 += input7[0] * c7s; o1 += input7[1] * c7s; o2 += input7[2] * c7s; o3 += input7[3] * c7s; )-    output[0] = o0; output[1] = o1; output[2] = o2; output[3] = o3;-    output += 4;-    stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; )-  }-  #endif-  while ( input0 < input0_end ) -  {-    float o0;-    STBIR_NO_UNROLL(output);-    #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-    stbIF0( o0 = output[0] + input0[0] * c0s; )-    #else-    stbIF0( o0  = input0[0] * c0s; )-    #endif-    stbIF1( o0 += input1[0] * c1s; )-    stbIF2( o0 += input2[0] * c2s; )-    stbIF3( o0 += input3[0] * c3s; )-    stbIF4( o0 += input4[0] * c4s; )-    stbIF5( o0 += input5[0] * c5s; )-    stbIF6( o0 += input6[0] * c6s; )-    stbIF7( o0 += input7[0] * c7s; )-    output[0] = o0; -    ++output;-    stbIF0( ++input0; ) stbIF1( ++input1; ) stbIF2( ++input2; ) stbIF3( ++input3; ) stbIF4( ++input4; ) stbIF5( ++input5; ) stbIF6( ++input6; ) stbIF7( ++input7; )-  }-}--#undef stbIF0-#undef stbIF1-#undef stbIF2-#undef stbIF3-#undef stbIF4-#undef stbIF5-#undef stbIF6-#undef stbIF7-#undef STB_IMAGE_RESIZE_DO_VERTICALS-#undef STBIR__vertical_channels-#undef STB_IMAGE_RESIZE_DO_HORIZONTALS-#undef STBIR_strs_join24-#undef STBIR_strs_join14-#undef STBIR_chans-#ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#undef STB_IMAGE_RESIZE_VERTICAL_CONTINUE-#endif--#else // !STB_IMAGE_RESIZE_DO_VERTICALS--#define STBIR_chans( start, end ) STBIR_strs_join1(start,STBIR__horizontal_channels,end)--#ifndef stbir__2_coeff_only-#define stbir__2_coeff_only()             \-    stbir__1_coeff_only();                \-    stbir__1_coeff_remnant(1);            -#endif--#ifndef stbir__2_coeff_remnant-#define stbir__2_coeff_remnant( ofs )     \-    stbir__1_coeff_remnant(ofs);          \-    stbir__1_coeff_remnant((ofs)+1);      -#endif-    -#ifndef stbir__3_coeff_only-#define stbir__3_coeff_only()             \-    stbir__2_coeff_only();                \-    stbir__1_coeff_remnant(2);            -#endif-    -#ifndef stbir__3_coeff_remnant-#define stbir__3_coeff_remnant( ofs )     \-    stbir__2_coeff_remnant(ofs);          \-    stbir__1_coeff_remnant((ofs)+2);      -#endif--#ifndef stbir__3_coeff_setup-#define stbir__3_coeff_setup()-#endif--#ifndef stbir__4_coeff_start-#define stbir__4_coeff_start()            \-    stbir__2_coeff_only();                \-    stbir__2_coeff_remnant(2);            -#endif-    -#ifndef stbir__4_coeff_continue_from_4-#define stbir__4_coeff_continue_from_4( ofs )     \-    stbir__2_coeff_remnant(ofs);                  \-    stbir__2_coeff_remnant((ofs)+2);      -#endif--#ifndef stbir__store_output_tiny-#define stbir__store_output_tiny stbir__store_output-#endif--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_1_coeff)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__1_coeff_only();-    stbir__store_output_tiny();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_2_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__2_coeff_only();-    stbir__store_output_tiny();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_3_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__3_coeff_only();-    stbir__store_output_tiny();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_4_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__4_coeff_start();-    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_5_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__4_coeff_start();-    stbir__1_coeff_remnant(4);-    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_6_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__4_coeff_start();-    stbir__2_coeff_remnant(4);-    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_7_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  stbir__3_coeff_setup();-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-  -    stbir__4_coeff_start();-    stbir__3_coeff_remnant(4);-    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_8_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__4_coeff_start();-    stbir__4_coeff_continue_from_4(4);-    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_9_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__4_coeff_start();-    stbir__4_coeff_continue_from_4(4);-    stbir__1_coeff_remnant(8);-    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_10_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__4_coeff_start();-    stbir__4_coeff_continue_from_4(4);-    stbir__2_coeff_remnant(8);-    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_11_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  stbir__3_coeff_setup();-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__4_coeff_start();-    stbir__4_coeff_continue_from_4(4);-    stbir__3_coeff_remnant(8);-    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_12_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    float const * hc = horizontal_coefficients;-    stbir__4_coeff_start();-    stbir__4_coeff_continue_from_4(4);-    stbir__4_coeff_continue_from_4(8);-    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod0 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 4 + 3 ) >> 2; -    float const * hc = horizontal_coefficients;--    stbir__4_coeff_start();-    do {-      hc += 4;-      decode += STBIR__horizontal_channels * 4;-      stbir__4_coeff_continue_from_4( 0 );-      --n;-    } while ( n > 0 );-    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod1 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 5 + 3 ) >> 2; -    float const * hc = horizontal_coefficients;--    stbir__4_coeff_start();-    do {-      hc += 4;-      decode += STBIR__horizontal_channels * 4;-      stbir__4_coeff_continue_from_4( 0 );-      --n;-    } while ( n > 0 );-    stbir__1_coeff_remnant( 4 ); -    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod2 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 6 + 3 ) >> 2; -    float const * hc = horizontal_coefficients;--    stbir__4_coeff_start();-    do {-      hc += 4;-      decode += STBIR__horizontal_channels * 4;-      stbir__4_coeff_continue_from_4( 0 );-      --n;-    } while ( n > 0 );-    stbir__2_coeff_remnant( 4 ); --    stbir__store_output();-  } while ( output < output_end );-}--static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod3 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )-{-  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;-  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;-  stbir__3_coeff_setup();-  do {-    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; -    int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 7 + 3 ) >> 2; -    float const * hc = horizontal_coefficients;--    stbir__4_coeff_start();-    do {-      hc += 4;-      decode += STBIR__horizontal_channels * 4;-      stbir__4_coeff_continue_from_4( 0 );-      --n;-    } while ( n > 0 );-    stbir__3_coeff_remnant( 4 ); --    stbir__store_output();-  } while ( output < output_end );-}--static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_funcs)[4]=-{-  STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod0),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod1),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod2),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod3),  -};--static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_funcs)[12]=-{-  STBIR_chans(stbir__horizontal_gather_,_channels_with_1_coeff),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_2_coeffs),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_3_coeffs),-  STBIR_chans(stbir__horizontal_gather_,_channels_with_4_coeffs),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_5_coeffs),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_6_coeffs),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_7_coeffs),-  STBIR_chans(stbir__horizontal_gather_,_channels_with_8_coeffs),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_9_coeffs),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_10_coeffs),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_11_coeffs),  -  STBIR_chans(stbir__horizontal_gather_,_channels_with_12_coeffs),  -};--#undef STBIR__horizontal_channels-#undef STB_IMAGE_RESIZE_DO_HORIZONTALS-#undef stbir__1_coeff_only-#undef stbir__1_coeff_remnant-#undef stbir__2_coeff_only-#undef stbir__2_coeff_remnant-#undef stbir__3_coeff_only-#undef stbir__3_coeff_remnant-#undef stbir__3_coeff_setup-#undef stbir__4_coeff_start-#undef stbir__4_coeff_continue_from_4-#undef stbir__store_output-#undef stbir__store_output_tiny-#undef STBIR_chans--#endif  // HORIZONALS--#undef STBIR_strs_join2-#undef STBIR_strs_join1--#endif // STB_IMAGE_RESIZE_DO_HORIZONTALS/VERTICALS/CODERS--/*--------------------------------------------------------------------------------This software is available under 2 licenses -- choose whichever you prefer.--------------------------------------------------------------------------------ALTERNATIVE A - MIT License-Copyright (c) 2017 Sean Barrett-Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions:-The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software.-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE.--------------------------------------------------------------------------------ALTERNATIVE B - Public Domain (www.unlicense.org)-This is free and unencumbered software released into the public domain.-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means.-In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law.-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +/* stb_image_resize2 - v2.10 - public domain image resizing++   by Jeff Roberts (v2) and Jorge L Rodriguez+   http://github.com/nothings/stb++   Can be threaded with the extended API. SSE2, AVX, Neon and WASM SIMD support. Only+   scaling and translation is supported, no rotations or shears.++   COMPILING & LINKING+      In one C/C++ file that #includes this file, do this:+         #define STB_IMAGE_RESIZE_IMPLEMENTATION+      before the #include. That will create the implementation in that file.++   PORTING FROM VERSION 1++      The API has changed. You can continue to use the old version of stb_image_resize.h,+      which is available in the "deprecated/" directory.++      If you're using the old simple-to-use API, porting is straightforward.+      (For more advanced APIs, read the documentation.)++        stbir_resize_uint8():+          - call `stbir_resize_uint8_linear`, cast channel count to `stbir_pixel_layout`++        stbir_resize_float():+          - call `stbir_resize_float_linear`, cast channel count to `stbir_pixel_layout`++        stbir_resize_uint8_srgb():+          - function name is unchanged+          - cast channel count to `stbir_pixel_layout`+          - above is sufficient unless your image has alpha and it's not RGBA/BGRA+            - in that case, follow the below instructions for stbir_resize_uint8_srgb_edgemode++        stbir_resize_uint8_srgb_edgemode()+          - switch to the "medium complexity" API+          - stbir_resize(), very similar API but a few more parameters:+            - pixel_layout: cast channel count to `stbir_pixel_layout`+            - data_type:    STBIR_TYPE_UINT8_SRGB+            - edge:         unchanged (STBIR_EDGE_WRAP, etc.)+            - filter:       STBIR_FILTER_DEFAULT+          - which channel is alpha is specified in stbir_pixel_layout, see enum for details++   EASY API CALLS:+     Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation, clamps to edge.++     stbir_resize_uint8_srgb( input_pixels,  input_w,  input_h,  input_stride_in_bytes,+                              output_pixels, output_w, output_h, output_stride_in_bytes,+                              pixel_layout_enum )++     stbir_resize_uint8_linear( input_pixels,  input_w,  input_h,  input_stride_in_bytes,+                                output_pixels, output_w, output_h, output_stride_in_bytes,+                                pixel_layout_enum )++     stbir_resize_float_linear( input_pixels,  input_w,  input_h,  input_stride_in_bytes,+                                output_pixels, output_w, output_h, output_stride_in_bytes,+                                pixel_layout_enum )++     If you pass NULL or zero for the output_pixels, we will allocate the output buffer+     for you and return it from the function (free with free() or STBIR_FREE).+     As a special case, XX_stride_in_bytes of 0 means packed continuously in memory.++   API LEVELS+      There are three levels of API - easy-to-use, medium-complexity and extended-complexity.++      See the "header file" section of the source for API documentation.++   ADDITIONAL DOCUMENTATION++      MEMORY ALLOCATION+         By default, we use malloc and free for memory allocation.  To override the+         memory allocation, before the implementation #include, add a:++            #define STBIR_MALLOC(size,user_data) ...+            #define STBIR_FREE(ptr,user_data)   ...++         Each resize makes exactly one call to malloc/free (unless you use the+         extended API where you can do one allocation for many resizes). Under+         address sanitizer, we do separate allocations to find overread/writes.++      PERFORMANCE+         This library was written with an emphasis on performance. When testing+         stb_image_resize with RGBA, the fastest mode is STBIR_4CHANNEL with+         STBIR_TYPE_UINT8 pixels and CLAMPed edges (which is what many other resize+         libs do by default). Also, make sure SIMD is turned on of course (default+         for 64-bit targets). Avoid WRAP edge mode if you want the fastest speed.++         This library also comes with profiling built-in. If you define STBIR_PROFILE,+         you can use the advanced API and get low-level profiling information by+         calling stbir_resize_extended_profile_info() or stbir_resize_split_profile_info()+         after a resize.++      SIMD+         Most of the routines have optimized SSE2, AVX, NEON and WASM versions.++         On Microsoft compilers, we automatically turn on SIMD for 64-bit x64 and+         ARM; for 32-bit x86 and ARM, you select SIMD mode by defining STBIR_SSE2 or+         STBIR_NEON. For AVX and AVX2, we auto-select it by detecting the /arch:AVX+         or /arch:AVX2 switches. You can also always manually turn SSE2, AVX or AVX2+         support on by defining STBIR_SSE2, STBIR_AVX or STBIR_AVX2.++         On Linux, SSE2 and Neon is on by default for 64-bit x64 or ARM64. For 32-bit,+         we select x86 SIMD mode by whether you have -msse2, -mavx or -mavx2 enabled+         on the command line. For 32-bit ARM, you must pass -mfpu=neon-vfpv4 for both+         clang and GCC, but GCC also requires an additional -mfp16-format=ieee to+         automatically enable NEON.++         On x86 platforms, you can also define STBIR_FP16C to turn on FP16C instructions+         for converting back and forth to half-floats. This is autoselected when we+         are using AVX2. Clang and GCC also require the -mf16c switch. ARM always uses+         the built-in half float hardware NEON instructions.++         You can also tell us to use multiply-add instructions with STBIR_USE_FMA.+         Because x86 doesn't always have fma, we turn it off by default to maintain+         determinism across all platforms. If you don't care about non-FMA determinism+         and are willing to restrict yourself to more recent x86 CPUs (around the AVX+         timeframe), then fma will give you around a 15% speedup.++         You can force off SIMD in all cases by defining STBIR_NO_SIMD. You can turn+         off AVX or AVX2 specifically with STBIR_NO_AVX or STBIR_NO_AVX2. AVX is 10%+         to 40% faster, and AVX2 is generally another 12%.++      ALPHA CHANNEL+         Most of the resizing functions provide the ability to control how the alpha+         channel of an image is processed.++         When alpha represents transparency, it is important that when combining+         colors with filtering, the pixels should not be treated equally; they+         should use a weighted average based on their alpha values. For example,+         if a pixel is 1% opaque bright green and another pixel is 99% opaque+         black and you average them, the average will be 50% opaque, but the+         unweighted average and will be a middling green color, while the weighted+         average will be nearly black. This means the unweighted version introduced+         green energy that didn't exist in the source image.++         (If you want to know why this makes sense, you can work out the math for+         the following: consider what happens if you alpha composite a source image+         over a fixed color and then average the output, vs. if you average the+         source image pixels and then composite that over the same fixed color.+         Only the weighted average produces the same result as the ground truth+         composite-then-average result.)++         Therefore, it is in general best to "alpha weight" the pixels when applying+         filters to them. This essentially means multiplying the colors by the alpha+         values before combining them, and then dividing by the alpha value at the+         end.++         The computer graphics industry introduced a technique called "premultiplied+         alpha" or "associated alpha" in which image colors are stored in image files+         already multiplied by their alpha. This saves some math when compositing,+         and also avoids the need to divide by the alpha at the end (which is quite+         inefficient). However, while premultiplied alpha is common in the movie CGI+         industry, it is not commonplace in other industries like videogames, and most+         consumer file formats are generally expected to contain not-premultiplied+         colors. For example, Photoshop saves PNG files "unpremultiplied", and web+         browsers like Chrome and Firefox expect PNG images to be unpremultiplied.++         Note that there are three possibilities that might describe your image+         and resize expectation:++             1. images are not premultiplied, alpha weighting is desired+             2. images are not premultiplied, alpha weighting is not desired+             3. images are premultiplied++         Both case #2 and case #3 require the exact same math: no alpha weighting+         should be applied or removed. Only case 1 requires extra math operations;+         the other two cases can be handled identically.++         stb_image_resize expects case #1 by default, applying alpha weighting to+         images, expecting the input images to be unpremultiplied. This is what the+         COLOR+ALPHA buffer types tell the resizer to do.++         When you use the pixel layouts STBIR_RGBA, STBIR_BGRA, STBIR_ARGB,+         STBIR_ABGR, STBIR_RX, or STBIR_XR you are telling us that the pixels are+         non-premultiplied. In these cases, the resizer will alpha weight the colors+         (effectively creating the premultiplied image), do the filtering, and then+         convert back to non-premult on exit.++         When you use the pixel layouts STBIR_RGBA_PM, STBIR_RGBA_PM, STBIR_RGBA_PM,+         STBIR_RGBA_PM, STBIR_RX_PM or STBIR_XR_PM, you are telling that the pixels+         ARE premultiplied. In this case, the resizer doesn't have to do the+         premultipling - it can filter directly on the input. This about twice as+         fast as the non-premultiplied case, so it's the right option if your data is+         already setup correctly.++         When you use the pixel layout STBIR_4CHANNEL or STBIR_2CHANNEL, you are+         telling us that there is no channel that represents transparency; it may be+         RGB and some unrelated fourth channel that has been stored in the alpha+         channel, but it is actually not alpha. No special processing will be+         performed.++         The difference between the generic 4 or 2 channel layouts, and the+         specialized _PM versions is with the _PM versions you are telling us that+         the data *is* alpha, just don't premultiply it. That's important when+         using SRGB pixel formats, we need to know where the alpha is, because+         it is converted linearly (rather than with the SRGB converters).++         Because alpha weighting produces the same effect as premultiplying, you+         even have the option with non-premultiplied inputs to let the resizer+         produce a premultiplied output. Because the intially computed alpha-weighted+         output image is effectively premultiplied, this is actually more performant+         than the normal path which un-premultiplies the output image as a final step.++         Finally, when converting both in and out of non-premulitplied space (for+         example, when using STBIR_RGBA), we go to somewhat heroic measures to+         ensure that areas with zero alpha value pixels get something reasonable+         in the RGB values. If you don't care about the RGB values of zero alpha+         pixels, you can call the stbir_set_non_pm_alpha_speed_over_quality()+         function - this runs a premultiplied resize about 25% faster. That said,+         when you really care about speed, using premultiplied pixels for both in+         and out (STBIR_RGBA_PM, etc) much faster than both of these premultiplied+         options.++      PIXEL LAYOUT CONVERSION+         The resizer can convert from some pixel layouts to others. When using the+         stbir_set_pixel_layouts(), you can, for example, specify STBIR_RGBA+         on input, and STBIR_ARGB on output, and it will re-organize the channels+         during the resize. Currently, you can only convert between two pixel+         layouts with the same number of channels.++      DETERMINISM+         We commit to being deterministic (from x64 to ARM to scalar to SIMD, etc).+         This requires compiling with fast-math off (using at least /fp:precise).+         Also, you must turn off fp-contracting (which turns mult+adds into fmas)!+         We attempt to do this with pragmas, but with Clang, you usually want to add+         -ffp-contract=off to the command line as well.++         For 32-bit x86, you must use SSE and SSE2 codegen for determinism. That is,+         if the scalar x87 unit gets used at all, we immediately lose determinism.+         On Microsoft Visual Studio 2008 and earlier, from what we can tell there is+         no way to be deterministic in 32-bit x86 (some x87 always leaks in, even+         with fp:strict). On 32-bit x86 GCC, determinism requires both -msse2 and+         -fpmath=sse.++         Note that we will not be deterministic with float data containing NaNs -+         the NaNs will propagate differently on different SIMD and platforms.++         If you turn on STBIR_USE_FMA, then we will be deterministic with other+         fma targets, but we will differ from non-fma targets (this is unavoidable,+         because a fma isn't simply an add with a mult - it also introduces a+         rounding difference compared to non-fma instruction sequences.++      FLOAT PIXEL FORMAT RANGE+         Any range of values can be used for the non-alpha float data that you pass+         in (0 to 1, -1 to 1, whatever). However, if you are inputting float values+         but *outputting* bytes or shorts, you must use a range of 0 to 1 so that we+         scale back properly. The alpha channel must also be 0 to 1 for any format+         that does premultiplication prior to resizing.++         Note also that with float output, using filters with negative lobes, the+         output filtered values might go slightly out of range. You can define+         STBIR_FLOAT_LOW_CLAMP and/or STBIR_FLOAT_HIGH_CLAMP to specify the range+         to clamp to on output, if that's important.++      MAX/MIN SCALE FACTORS+         The input pixel resolutions are in integers, and we do the internal pointer+         resolution in size_t sized integers. However, the scale ratio from input+         resolution to output resolution is calculated in float form. This means+         the effective possible scale ratio is limited to 24 bits (or 16 million+         to 1). As you get close to the size of the float resolution (again, 16+         million pixels wide or high), you might start seeing float inaccuracy+         issues in general in the pipeline. If you have to do extreme resizes,+         you can usually do this is multiple stages (using float intermediate+         buffers).++      FLIPPED IMAGES+         Stride is just the delta from one scanline to the next. This means you can+         use a negative stride to handle inverted images (point to the final+         scanline and use a negative stride). You can invert the input or output,+         using negative strides.++      DEFAULT FILTERS+         For functions which don't provide explicit control over what filters to+         use, you can change the compile-time defaults with:++            #define STBIR_DEFAULT_FILTER_UPSAMPLE     STBIR_FILTER_something+            #define STBIR_DEFAULT_FILTER_DOWNSAMPLE   STBIR_FILTER_something++         See stbir_filter in the header-file section for the list of filters.++      NEW FILTERS+         A number of 1D filter kernels are supplied. For a list of supported+         filters, see the stbir_filter enum. You can install your own filters by+         using the stbir_set_filter_callbacks function.++      PROGRESS+         For interactive use with slow resize operations, you can use the the+         scanline callbacks in the extended API. It would have to be a *very* large+         image resample to need progress though - we're very fast.++      CEIL and FLOOR+         In scalar mode, the only functions we use from math.h are ceilf and floorf,+         but if you have your own versions, you can define the STBIR_CEILF(v) and+         STBIR_FLOORF(v) macros and we'll use them instead. In SIMD, we just use+         our own versions.++      ASSERT+         Define STBIR_ASSERT(boolval) to override assert() and not use assert.h++      FUTURE TODOS+        *  For polyphase integral filters, we just memcpy the coeffs to dupe+           them, but we should indirect and use the same coeff memory.+        *  Add pixel layout conversions for sensible different channel counts+           (maybe, 1->3/4, 3->4, 4->1, 3->1).+         * For SIMD encode and decode scanline routines, do any pre-aligning+           for bad input/output buffer alignments and pitch?+         * For very wide scanlines, we should we do vertical strips to stay within+           L2 cache. Maybe do chunks of 1K pixels at a time. There would be+           some pixel reconversion, but probably dwarfed by things falling out+           of cache. Probably also something possible with alternating between+           scattering and gathering at high resize scales?+         * Rewrite the coefficient generator to do many at once.+         * AVX-512 vertical kernels - worried about downclocking here.+         * Convert the reincludes to macros when we know they aren't changing.+         * Experiment with pivoting the horizontal and always using the+           vertical filters (which are faster, but perhaps not enough to overcome+           the pivot cost and the extra memory touches). Need to buffer the whole+           image so have to balance memory use.+         * Most of our code is internally function pointers, should we compile+           all the SIMD stuff always and dynamically dispatch?++   CONTRIBUTORS+      Jeff Roberts: 2.0 implementation, optimizations, SIMD+      Martins Mozeiko: NEON simd, WASM simd, clang and GCC whisperer+      Fabian Giesen: half float and srgb converters+      Sean Barrett: API design, optimizations+      Jorge L Rodriguez: Original 1.0 implementation+      Aras Pranckevicius: bugfixes+      Nathan Reed: warning fixes for 1.0++   REVISIONS+      2.10 (2024-07-27) fix the defines GCC and mingw for loop unroll control,+                          fix MSVC 32-bit arm half float routines.+      2.09 (2024-06-19) fix the defines for 32-bit ARM GCC builds (was selecting+                          hardware half floats).+      2.08 (2024-06-10) fix for RGB->BGR three channel flips and add SIMD (thanks+                          to Ryan Salsbury), fix for sub-rect resizes, use the+                          pragmas to control unrolling when they are available.+      2.07 (2024-05-24) fix for slow final split during threaded conversions of very +                          wide scanlines when downsampling (caused by extra input +                          converting), fix for wide scanline resamples with many +                          splits (int overflow), fix GCC warning.+      2.06 (2024-02-10) fix for identical width/height 3x or more down-scaling +                          undersampling a single row on rare resize ratios (about 1%).+      2.05 (2024-02-07) fix for 2 pixel to 1 pixel resizes with wrap (thanks Aras),+                        fix for output callback (thanks Julien Koenen).+      2.04 (2023-11-17) fix for rare AVX bug, shadowed symbol (thanks Nikola Smiljanic).+      2.03 (2023-11-01) ASAN and TSAN warnings fixed, minor tweaks.+      2.00 (2023-10-10) mostly new source: new api, optimizations, simd, vertical-first, etc+                          2x-5x faster without simd, 4x-12x faster with simd,+                          in some cases, 20x to 40x faster esp resizing large to very small.+      0.96 (2019-03-04) fixed warnings+      0.95 (2017-07-23) fixed warnings+      0.94 (2017-03-18) fixed warnings+      0.93 (2017-03-03) fixed bug with certain combinations of heights+      0.92 (2017-01-02) fix integer overflow on large (>2GB) images+      0.91 (2016-04-02) fix warnings; fix handling of subpixel regions+      0.90 (2014-09-17) first released version++   LICENSE+     See end of file for license information.+*/++#if !defined(STB_IMAGE_RESIZE_DO_HORIZONTALS) && !defined(STB_IMAGE_RESIZE_DO_VERTICALS) && !defined(STB_IMAGE_RESIZE_DO_CODERS)   // for internal re-includes++#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE2_H+#define STBIR_INCLUDE_STB_IMAGE_RESIZE2_H++#include <stddef.h>+#ifdef _MSC_VER+typedef unsigned char    stbir_uint8;+typedef unsigned short   stbir_uint16;+typedef unsigned int     stbir_uint32;+typedef unsigned __int64 stbir_uint64;+#else+#include <stdint.h>+typedef uint8_t  stbir_uint8;+typedef uint16_t stbir_uint16;+typedef uint32_t stbir_uint32;+typedef uint64_t stbir_uint64;+#endif++#ifdef _M_IX86_FP+#if ( _M_IX86_FP >= 1 )+#ifndef STBIR_SSE+#define STBIR_SSE+#endif+#endif+#endif++#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(_M_AMD64) || defined(__SSE2__) || defined(STBIR_SSE) || defined(STBIR_SSE2)+  #ifndef STBIR_SSE2+    #define STBIR_SSE2+  #endif+  #if defined(__AVX__) || defined(STBIR_AVX2)+    #ifndef STBIR_AVX+      #ifndef STBIR_NO_AVX+        #define STBIR_AVX+      #endif+    #endif+  #endif+  #if defined(__AVX2__) || defined(STBIR_AVX2)+    #ifndef STBIR_NO_AVX2+      #ifndef STBIR_AVX2+        #define STBIR_AVX2+      #endif+      #if defined( _MSC_VER ) && !defined(__clang__)+        #ifndef STBIR_FP16C  // FP16C instructions are on all AVX2 cpus, so we can autoselect it here on microsoft - clang needs -m16c+          #define STBIR_FP16C+        #endif+      #endif+    #endif+  #endif+  #ifdef __F16C__+    #ifndef STBIR_FP16C  // turn on FP16C instructions if the define is set (for clang and gcc)+      #define STBIR_FP16C+    #endif+  #endif+#endif++#if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || ((__ARM_NEON_FP & 4) != 0) || defined(__ARM_NEON__)+#ifndef STBIR_NEON+#define STBIR_NEON+#endif+#endif++#if defined(_M_ARM) || defined(__arm__)+#ifdef STBIR_USE_FMA+#undef STBIR_USE_FMA // no FMA for 32-bit arm on MSVC+#endif+#endif++#if defined(__wasm__) && defined(__wasm_simd128__)+#ifndef STBIR_WASM+#define STBIR_WASM+#endif+#endif++#ifndef STBIRDEF+#ifdef STB_IMAGE_RESIZE_STATIC+#define STBIRDEF static+#else+#ifdef __cplusplus+#define STBIRDEF extern "C"+#else+#define STBIRDEF extern+#endif+#endif+#endif++//////////////////////////////////////////////////////////////////////////////+////   start "header file" ///////////////////////////////////////////////////+//+// Easy-to-use API:+//+//     * stride is the offset between successive rows of image data+//        in memory, in bytes. specify 0 for packed continuously in memory+//     * colorspace is linear or sRGB as specified by function name+//     * Uses the default filters+//     * Uses edge mode clamped+//     * returned result is 1 for success or 0 in case of an error.+++// stbir_pixel_layout specifies:+//   number of channels+//   order of channels+//   whether color is premultiplied by alpha+// for back compatibility, you can cast the old channel count to an stbir_pixel_layout+typedef enum+{+  STBIR_1CHANNEL = 1,+  STBIR_2CHANNEL = 2,+  STBIR_RGB      = 3,               // 3-chan, with order specified (for channel flipping)+  STBIR_BGR      = 0,               // 3-chan, with order specified (for channel flipping)+  STBIR_4CHANNEL = 5,++  STBIR_RGBA = 4,                   // alpha formats, where alpha is NOT premultiplied into color channels+  STBIR_BGRA = 6,+  STBIR_ARGB = 7,+  STBIR_ABGR = 8,+  STBIR_RA   = 9,+  STBIR_AR   = 10,++  STBIR_RGBA_PM = 11,               // alpha formats, where alpha is premultiplied into color channels+  STBIR_BGRA_PM = 12,+  STBIR_ARGB_PM = 13,+  STBIR_ABGR_PM = 14,+  STBIR_RA_PM   = 15,+  STBIR_AR_PM   = 16,++  STBIR_RGBA_NO_AW = 11,            // alpha formats, where NO alpha weighting is applied at all!+  STBIR_BGRA_NO_AW = 12,            //   these are just synonyms for the _PM flags (which also do+  STBIR_ARGB_NO_AW = 13,            //   no alpha weighting). These names just make it more clear+  STBIR_ABGR_NO_AW = 14,            //   for some folks).+  STBIR_RA_NO_AW   = 15,+  STBIR_AR_NO_AW   = 16,++} stbir_pixel_layout;++//===============================================================+//  Simple-complexity API+//+//    If output_pixels is NULL (0), then we will allocate the buffer and return it to you.+//--------------------------------++STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes,+                                                        unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+                                                        stbir_pixel_layout pixel_type );++STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes,+                                                          unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+                                                          stbir_pixel_layout pixel_type );++STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes,+                                                  float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+                                                  stbir_pixel_layout pixel_type );+//===============================================================++//===============================================================+// Medium-complexity API+//+// This extends the easy-to-use API as follows:+//+//     * Can specify the datatype - U8, U8_SRGB, U16, FLOAT, HALF_FLOAT+//     * Edge wrap can selected explicitly+//     * Filter can be selected explicitly+//--------------------------------++typedef enum+{+  STBIR_EDGE_CLAMP   = 0,+  STBIR_EDGE_REFLECT = 1,+  STBIR_EDGE_WRAP    = 2,  // this edge mode is slower and uses more memory+  STBIR_EDGE_ZERO    = 3,+} stbir_edge;++typedef enum+{+  STBIR_FILTER_DEFAULT      = 0,  // use same filter type that easy-to-use API chooses+  STBIR_FILTER_BOX          = 1,  // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios+  STBIR_FILTER_TRIANGLE     = 2,  // On upsampling, produces same results as bilinear texture filtering+  STBIR_FILTER_CUBICBSPLINE = 3,  // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque+  STBIR_FILTER_CATMULLROM   = 4,  // An interpolating cubic spline+  STBIR_FILTER_MITCHELL     = 5,  // Mitchell-Netrevalli filter with B=1/3, C=1/3+  STBIR_FILTER_POINT_SAMPLE = 6,  // Simple point sampling+  STBIR_FILTER_OTHER        = 7,  // User callback specified+} stbir_filter;++typedef enum+{+  STBIR_TYPE_UINT8            = 0,+  STBIR_TYPE_UINT8_SRGB       = 1,+  STBIR_TYPE_UINT8_SRGB_ALPHA = 2,  // alpha channel, when present, should also be SRGB (this is very unusual)+  STBIR_TYPE_UINT16           = 3,+  STBIR_TYPE_FLOAT            = 4,+  STBIR_TYPE_HALF_FLOAT       = 5+} stbir_datatype;++// medium api+STBIRDEF void *  stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes,+                                     void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+                               stbir_pixel_layout pixel_layout, stbir_datatype data_type,+                               stbir_edge edge, stbir_filter filter );+//===============================================================++++//===============================================================+// Extended-complexity API+//+// This API exposes all resize functionality.+//+//     * Separate filter types for each axis+//     * Separate edge modes for each axis+//     * Separate input and output data types+//     * Can specify regions with subpixel correctness+//     * Can specify alpha flags+//     * Can specify a memory callback+//     * Can specify a callback data type for pixel input and output+//     * Can be threaded for a single resize+//     * Can be used to resize many frames without recalculating the sampler info+//+//  Use this API as follows:+//     1) Call the stbir_resize_init function on a local STBIR_RESIZE structure+//     2) Call any of the stbir_set functions+//     3) Optionally call stbir_build_samplers() if you are going to resample multiple times+//        with the same input and output dimensions (like resizing video frames)+//     4) Resample by calling stbir_resize_extended().+//     5) Call stbir_free_samplers() if you called stbir_build_samplers()+//--------------------------------+++// Types:++// INPUT CALLBACK: this callback is used for input scanlines+typedef void const * stbir_input_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context );++// OUTPUT CALLBACK: this callback is used for output scanlines+typedef void stbir_output_callback( void const * output_ptr, int num_pixels, int y, void * context );++// callbacks for user installed filters+typedef float stbir__kernel_callback( float x, float scale, void * user_data ); // centered at zero+typedef float stbir__support_callback( float scale, void * user_data );++// internal structure with precomputed scaling+typedef struct stbir__info stbir__info;++typedef struct STBIR_RESIZE  // use the stbir_resize_init and stbir_override functions to set these values for future compatibility+{+  void * user_data;+  void const * input_pixels;+  int input_w, input_h;+  double input_s0, input_t0, input_s1, input_t1;+  stbir_input_callback * input_cb;+  void * output_pixels;+  int output_w, output_h;+  int output_subx, output_suby, output_subw, output_subh;+  stbir_output_callback * output_cb;+  int input_stride_in_bytes;+  int output_stride_in_bytes;+  int splits;+  int fast_alpha;+  int needs_rebuild;+  int called_alloc;+  stbir_pixel_layout input_pixel_layout_public;+  stbir_pixel_layout output_pixel_layout_public;+  stbir_datatype input_data_type;+  stbir_datatype output_data_type;+  stbir_filter horizontal_filter, vertical_filter;+  stbir_edge horizontal_edge, vertical_edge;+  stbir__kernel_callback * horizontal_filter_kernel; stbir__support_callback * horizontal_filter_support;+  stbir__kernel_callback * vertical_filter_kernel; stbir__support_callback * vertical_filter_support;+  stbir__info * samplers;+} STBIR_RESIZE;++// extended complexity api+++// First off, you must ALWAYS call stbir_resize_init on your resize structure before any of the other calls!+STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize,+                                 const void *input_pixels,  int input_w,  int input_h, int input_stride_in_bytes, // stride can be zero+                                       void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero+                                 stbir_pixel_layout pixel_layout, stbir_datatype data_type );++//===============================================================+// You can update these parameters any time after resize_init and there is no cost+//--------------------------------++STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type );+STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb );   // no callbacks by default+STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data );                                               // pass back STBIR_RESIZE* by default+STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes );++//===============================================================+++//===============================================================+// If you call any of these functions, you will trigger a sampler rebuild!+//--------------------------------++STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout input_pixel_layout, stbir_pixel_layout output_pixel_layout );  // sets new buffer layouts+STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge );       // CLAMP by default++STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ); // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default+STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support );++STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh );        // sets both sub-regions (full regions by default)+STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 );    // sets input sub-region (full region by default)+STBIRDEF int stbir_set_output_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ); // sets output sub-region (full region by default)++// when inputting AND outputting non-premultiplied alpha pixels, we use a slower but higher quality technique+//   that fills the zero alpha pixel's RGB values with something plausible.  If you don't care about areas of+//   zero alpha, you can call this function to get about a 25% speed improvement for STBIR_RGBA to STBIR_RGBA+//   types of resizes.+STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, int non_pma_alpha_speed_over_quality );+//===============================================================+++//===============================================================+// You can call build_samplers to prebuild all the internal data we need to resample.+//   Then, if you call resize_extended many times with the same resize, you only pay the+//   cost once.+// If you do call build_samplers, you MUST call free_samplers eventually.+//--------------------------------++// This builds the samplers and does one allocation+STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize );++// You MUST call this, if you call stbir_build_samplers or stbir_build_samplers_with_splits+STBIRDEF void stbir_free_samplers( STBIR_RESIZE * resize );+//===============================================================+++// And this is the main function to perform the resize synchronously on one thread.+STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize );+++//===============================================================+// Use these functions for multithreading.+//   1) You call stbir_build_samplers_with_splits first on the main thread+//   2) Then stbir_resize_with_split on each thread+//   3) stbir_free_samplers when done on the main thread+//--------------------------------++// This will build samplers for threading.+//   You can pass in the number of threads you'd like to use (try_splits).+//   It returns the number of splits (threads) that you can call it with.+///  It might be less if the image resize can't be split up that many ways.++STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int try_splits );++// This function does a split of the resizing (you call this fuction for each+// split, on multiple threads). A split is a piece of the output resize pixel space.++// Note that you MUST call stbir_build_samplers_with_splits before stbir_resize_extended_split!++// Usually, you will always call stbir_resize_split with split_start as the thread_index+//   and "1" for the split_count.+// But, if you have a weird situation where you MIGHT want 8 threads, but sometimes+//   only 4 threads, you can use 0,2,4,6 for the split_start's and use "2" for the+//   split_count each time to turn in into a 4 thread resize. (This is unusual).++STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count );+//===============================================================+++//===============================================================+// Pixel Callbacks info:+//--------------------------------++//   The input callback is super flexible - it calls you with the input address+//   (based on the stride and base pointer), it gives you an optional_output+//   pointer that you can fill, or you can just return your own pointer into+//   your own data.+//+//   You can also do conversion from non-supported data types if necessary - in+//   this case, you ignore the input_ptr and just use the x and y parameters to+//   calculate your own input_ptr based on the size of each non-supported pixel.+//   (Something like the third example below.)+//+//   You can also install just an input or just an output callback by setting the+//   callback that you don't want to zero.+//+//     First example, progress: (getting a callback that you can monitor the progress):+//        void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context )+//        {+//           percentage_done = y / input_height;+//           return input_ptr;  // use buffer from call+//        }+//+//     Next example, copying: (copy from some other buffer or stream):+//        void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context )+//        {+//           CopyOrStreamData( optional_output, other_data_src, num_pixels * pixel_width_in_bytes );+//           return optional_output;  // return the optional buffer that we filled+//        }+//+//     Third example, input another buffer without copying: (zero-copy from other buffer):+//        void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context )+//        {+//           void * pixels = ( (char*) other_image_base ) + ( y * other_image_stride ) + ( x * other_pixel_width_in_bytes );+//           return pixels;       // return pointer to your data without copying+//        }+//+//+//   The output callback is considerably simpler - it just calls you so that you can dump+//   out each scanline. You could even directly copy out to disk if you have a simple format+//   like TGA or BMP. You can also convert to other output types here if you want.+//+//   Simple example:+//        void const * my_output( void * output_ptr, int num_pixels, int y, void * context )+//        {+//           percentage_done = y / output_height;+//           fwrite( output_ptr, pixel_width_in_bytes, num_pixels, output_file );+//        }+//===============================================================+++++//===============================================================+// optional built-in profiling API+//--------------------------------++#ifdef STBIR_PROFILE++typedef struct STBIR_PROFILE_INFO+{+  stbir_uint64 total_clocks;++  // how many clocks spent (of total_clocks) in the various resize routines, along with a string description+  //    there are "resize_count" number of zones+  stbir_uint64 clocks[ 8 ];+  char const ** descriptions;++  // count of clocks and descriptions+  stbir_uint32 count;+} STBIR_PROFILE_INFO;++// use after calling stbir_resize_extended (or stbir_build_samplers or stbir_build_samplers_with_splits)+STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize );++// use after calling stbir_resize_extended+STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize );++// use after calling stbir_resize_extended_split+STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize, int split_start, int split_num );++//===============================================================++#endif+++////   end header file   /////////////////////////////////////////////////////+#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE2_H++#if defined(STB_IMAGE_RESIZE_IMPLEMENTATION) || defined(STB_IMAGE_RESIZE2_IMPLEMENTATION)++#ifndef STBIR_ASSERT+#include <assert.h>+#define STBIR_ASSERT(x) assert(x)+#endif++#ifndef STBIR_MALLOC+#include <stdlib.h>+#define STBIR_MALLOC(size,user_data) ((void)(user_data), malloc(size))+#define STBIR_FREE(ptr,user_data)    ((void)(user_data), free(ptr))+// (we used the comma operator to evaluate user_data, to avoid "unused parameter" warnings)+#endif++#ifdef _MSC_VER++#define stbir__inline __forceinline++#else++#define stbir__inline __inline__++// Clang address sanitizer+#if defined(__has_feature)+  #if __has_feature(address_sanitizer) || __has_feature(memory_sanitizer)+    #ifndef STBIR__SEPARATE_ALLOCATIONS+      #define STBIR__SEPARATE_ALLOCATIONS+    #endif+  #endif+#endif++#endif++// GCC and MSVC+#if defined(__SANITIZE_ADDRESS__)+  #ifndef STBIR__SEPARATE_ALLOCATIONS+    #define STBIR__SEPARATE_ALLOCATIONS+  #endif+#endif++// Always turn off automatic FMA use - use STBIR_USE_FMA if you want.+// Otherwise, this is a determinism disaster.+#ifndef STBIR_DONT_CHANGE_FP_CONTRACT  // override in case you don't want this behavior+#if defined(_MSC_VER) && !defined(__clang__)+#if _MSC_VER > 1200+#pragma fp_contract(off)+#endif+#elif defined(__GNUC__) &&  !defined(__clang__)+#pragma GCC optimize("fp-contract=off")+#else+#pragma STDC FP_CONTRACT OFF+#endif+#endif++#ifdef _MSC_VER+#define STBIR__UNUSED(v)  (void)(v)+#else+#define STBIR__UNUSED(v)  (void)sizeof(v)+#endif++#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0]))+++#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE+#define STBIR_DEFAULT_FILTER_UPSAMPLE    STBIR_FILTER_CATMULLROM+#endif++#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE+#define STBIR_DEFAULT_FILTER_DOWNSAMPLE  STBIR_FILTER_MITCHELL+#endif+++#ifndef STBIR__HEADER_FILENAME+#define STBIR__HEADER_FILENAME "stb_image_resize2.h"+#endif++// the internal pixel layout enums are in a different order, so we can easily do range comparisons of types+//   the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible+typedef enum+{+  STBIRI_1CHANNEL = 0,+  STBIRI_2CHANNEL = 1,+  STBIRI_RGB      = 2,+  STBIRI_BGR      = 3,+  STBIRI_4CHANNEL = 4,++  STBIRI_RGBA = 5,+  STBIRI_BGRA = 6,+  STBIRI_ARGB = 7,+  STBIRI_ABGR = 8,+  STBIRI_RA   = 9,+  STBIRI_AR   = 10,++  STBIRI_RGBA_PM = 11,+  STBIRI_BGRA_PM = 12,+  STBIRI_ARGB_PM = 13,+  STBIRI_ABGR_PM = 14,+  STBIRI_RA_PM   = 15,+  STBIRI_AR_PM   = 16,+} stbir_internal_pixel_layout;++// define the public pixel layouts to not compile inside the implementation (to avoid accidental use)+#define STBIR_BGR bad_dont_use_in_implementation+#define STBIR_1CHANNEL STBIR_BGR+#define STBIR_2CHANNEL STBIR_BGR+#define STBIR_RGB STBIR_BGR+#define STBIR_RGBA STBIR_BGR+#define STBIR_4CHANNEL STBIR_BGR+#define STBIR_BGRA STBIR_BGR+#define STBIR_ARGB STBIR_BGR+#define STBIR_ABGR STBIR_BGR+#define STBIR_RA STBIR_BGR+#define STBIR_AR STBIR_BGR+#define STBIR_RGBA_PM STBIR_BGR+#define STBIR_BGRA_PM STBIR_BGR+#define STBIR_ARGB_PM STBIR_BGR+#define STBIR_ABGR_PM STBIR_BGR+#define STBIR_RA_PM STBIR_BGR+#define STBIR_AR_PM STBIR_BGR++// must match stbir_datatype+static unsigned char stbir__type_size[] = {+  1,1,1,2,4,2 // STBIR_TYPE_UINT8,STBIR_TYPE_UINT8_SRGB,STBIR_TYPE_UINT8_SRGB_ALPHA,STBIR_TYPE_UINT16,STBIR_TYPE_FLOAT,STBIR_TYPE_HALF_FLOAT+};++// When gathering, the contributors are which source pixels contribute.+// When scattering, the contributors are which destination pixels are contributed to.+typedef struct+{+  int n0; // First contributing pixel+  int n1; // Last contributing pixel+} stbir__contributors;++typedef struct+{+  int lowest;    // First sample index for whole filter+  int highest;   // Last sample index for whole filter+  int widest;    // widest single set of samples for an output+} stbir__filter_extent_info;++typedef struct+{+  int n0; // First pixel of decode buffer to write to+  int n1; // Last pixel of decode that will be written to+  int pixel_offset_for_input;  // Pixel offset into input_scanline+} stbir__span;++typedef struct stbir__scale_info+{+  int input_full_size;+  int output_sub_size;+  float scale;+  float inv_scale;+  float pixel_shift; // starting shift in output pixel space (in pixels)+  int scale_is_rational;+  stbir_uint32 scale_numerator, scale_denominator;+} stbir__scale_info;++typedef struct+{+  stbir__contributors * contributors;+  float* coefficients;+  stbir__contributors * gather_prescatter_contributors;+  float * gather_prescatter_coefficients;+  stbir__scale_info scale_info;+  float support;+  stbir_filter filter_enum;+  stbir__kernel_callback * filter_kernel;+  stbir__support_callback * filter_support;+  stbir_edge edge;+  int coefficient_width;+  int filter_pixel_width;+  int filter_pixel_margin;+  int num_contributors;+  int contributors_size;+  int coefficients_size;+  stbir__filter_extent_info extent_info;+  int is_gather;  // 0 = scatter, 1 = gather with scale >= 1, 2 = gather with scale < 1+  int gather_prescatter_num_contributors;+  int gather_prescatter_coefficient_width;+  int gather_prescatter_contributors_size;+  int gather_prescatter_coefficients_size;+} stbir__sampler;++typedef struct+{+  stbir__contributors conservative;+  int edge_sizes[2];    // this can be less than filter_pixel_margin, if the filter and scaling falls off+  stbir__span spans[2]; // can be two spans, if doing input subrect with clamp mode WRAP+} stbir__extents;++typedef struct+{+#ifdef STBIR_PROFILE+  union+  {+    struct { stbir_uint64 total, looping, vertical, horizontal, decode, encode, alpha, unalpha; } named;+    stbir_uint64 array[8];+  } profile;+  stbir_uint64 * current_zone_excluded_ptr;+#endif+  float* decode_buffer;++  int ring_buffer_first_scanline;+  int ring_buffer_last_scanline;+  int ring_buffer_begin_index;    // first_scanline is at this index in the ring buffer+  int start_output_y, end_output_y;+  int start_input_y, end_input_y;  // used in scatter only++  #ifdef STBIR__SEPARATE_ALLOCATIONS+    float** ring_buffers; // one pointer for each ring buffer+  #else+    float* ring_buffer;  // one big buffer that we index into+  #endif++  float* vertical_buffer;++  char no_cache_straddle[64];+} stbir__per_split_info;++typedef void stbir__decode_pixels_func( float * decode, int width_times_channels, void const * input );+typedef void stbir__alpha_weight_func( float * decode_buffer, int width_times_channels );+typedef void stbir__horizontal_gather_channels_func( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer,+  stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width );+typedef void stbir__alpha_unweight_func(float * encode_buffer, int width_times_channels );+typedef void stbir__encode_pixels_func( void * output, int width_times_channels, float const * encode );++struct stbir__info+{+#ifdef STBIR_PROFILE+  union+  {+    struct { stbir_uint64 total, build, alloc, horizontal, vertical, cleanup, pivot; } named;+    stbir_uint64 array[7];+  } profile;+  stbir_uint64 * current_zone_excluded_ptr;+#endif+  stbir__sampler horizontal;+  stbir__sampler vertical;++  void const * input_data;+  void * output_data;++  int input_stride_bytes;+  int output_stride_bytes;+  int ring_buffer_length_bytes;   // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter)+  int ring_buffer_num_entries;    // Total number of entries in the ring buffer.++  stbir_datatype input_type;+  stbir_datatype output_type;++  stbir_input_callback * in_pixels_cb;+  void * user_data;+  stbir_output_callback * out_pixels_cb;++  stbir__extents scanline_extents;++  void * alloced_mem;+  stbir__per_split_info * split_info;  // by default 1, but there will be N of these allocated based on the thread init you did++  stbir__decode_pixels_func * decode_pixels;+  stbir__alpha_weight_func * alpha_weight;+  stbir__horizontal_gather_channels_func * horizontal_gather_channels;+  stbir__alpha_unweight_func * alpha_unweight;+  stbir__encode_pixels_func * encode_pixels;++  int alloc_ring_buffer_num_entries;    // Number of entries in the ring buffer that will be allocated+  int splits; // count of splits++  stbir_internal_pixel_layout input_pixel_layout_internal;+  stbir_internal_pixel_layout output_pixel_layout_internal;++  int input_color_and_type;+  int offset_x, offset_y; // offset within output_data+  int vertical_first;+  int channels;+  int effective_channels; // same as channels, except on RGBA/ARGB (7), or XA/AX (3)+  size_t alloced_total;+};+++#define stbir__max_uint8_as_float             255.0f+#define stbir__max_uint16_as_float            65535.0f+#define stbir__max_uint8_as_float_inverted    (1.0f/255.0f)+#define stbir__max_uint16_as_float_inverted   (1.0f/65535.0f)+#define stbir__small_float ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20))++// min/max friendly+#define STBIR_CLAMP(x, xmin, xmax) for(;;) { \+  if ( (x) < (xmin) ) (x) = (xmin);     \+  if ( (x) > (xmax) ) (x) = (xmax);     \+  break;                                \+}++static stbir__inline int stbir__min(int a, int b)+{+  return a < b ? a : b;+}++static stbir__inline int stbir__max(int a, int b)+{+  return a > b ? a : b;+}++static float stbir__srgb_uchar_to_linear_float[256] = {+  0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,+  0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f,+  0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f,+  0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f,+  0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f,+  0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f,+  0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f,+  0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,+  0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f,+  0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f,+  0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f,+  0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f,+  0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f,+  0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f,+  0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,+  0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f,+  0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f,+  0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f,+  0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f,+  0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f,+  0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f,+  0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,+  0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f,+  0.982251f, 0.991102f, 1.0f+};++typedef union+{+  unsigned int u;+  float f;+} stbir__FP32;++// From https://gist.github.com/rygorous/2203834++static const stbir_uint32 fp32_to_srgb8_tab4[104] = {+  0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d,+  0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a,+  0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033,+  0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067,+  0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5,+  0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2,+  0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143,+  0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af,+  0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240,+  0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300,+  0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401,+  0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559,+  0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723,+};++static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in)+{+  static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps+  static const stbir__FP32 minval = { (127-13) << 23 };+  stbir_uint32 tab,bias,scale,t;+  stbir__FP32 f;++  // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively.+  // The tests are carefully written so that NaNs map to 0, same as in the reference+  // implementation.+  if (!(in > minval.f)) // written this way to catch NaNs+      return 0;+  if (in > almostone.f)+      return 255;++  // Do the table lookup and unpack bias, scale+  f.f = in;+  tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20];+  bias = (tab >> 16) << 9;+  scale = tab & 0xffff;++  // Grab next-highest mantissa bits and perform linear interpolation+  t = (f.u >> 12) & 0xff;+  return (unsigned char) ((bias + scale*t) >> 16);+}++#ifndef STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT+#define STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT 32 // when downsampling and <= 32 scanlines of buffering, use gather. gather used down to 1/8th scaling for 25% win.+#endif++#ifndef STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS+#define STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS 4 // when threading, what is the minimum number of scanlines for a split?+#endif++// restrict pointers for the output pointers, other loop and unroll control+#if defined( _MSC_VER ) && !defined(__clang__)+  #define STBIR_STREAMOUT_PTR( star ) star __restrict+  #define STBIR_NO_UNROLL( ptr ) __assume(ptr) // this oddly keeps msvc from unrolling a loop+  #if _MSC_VER >= 1900+    #define STBIR_NO_UNROLL_LOOP_START __pragma(loop( no_vector )) +  #else+    #define STBIR_NO_UNROLL_LOOP_START +  #endif+#elif defined( __clang__ )+  #define STBIR_STREAMOUT_PTR( star ) star __restrict__+  #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr)) +  #if ( __clang_major__ >= 4 ) || ( ( __clang_major__ >= 3 ) && ( __clang_minor__ >= 5 ) )+    #define STBIR_NO_UNROLL_LOOP_START _Pragma("clang loop unroll(disable)") _Pragma("clang loop vectorize(disable)")+  #else+    #define STBIR_NO_UNROLL_LOOP_START+  #endif +#elif defined( __GNUC__ )+  #define STBIR_STREAMOUT_PTR( star ) star __restrict__+  #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr))+  #if __GNUC__ >= 14+    #define STBIR_NO_UNROLL_LOOP_START _Pragma("GCC unroll 0") _Pragma("GCC novector")+  #else+    #define STBIR_NO_UNROLL_LOOP_START+  #endif+  #define STBIR_NO_UNROLL_LOOP_START_INF_FOR+#else+  #define STBIR_STREAMOUT_PTR( star ) star+  #define STBIR_NO_UNROLL( ptr )+  #define STBIR_NO_UNROLL_LOOP_START+#endif++#ifndef STBIR_NO_UNROLL_LOOP_START_INF_FOR+#define STBIR_NO_UNROLL_LOOP_START_INF_FOR STBIR_NO_UNROLL_LOOP_START+#endif++#ifdef STBIR_NO_SIMD // force simd off for whatever reason++// force simd off overrides everything else, so clear it all++#ifdef STBIR_SSE2+#undef STBIR_SSE2+#endif++#ifdef STBIR_AVX+#undef STBIR_AVX+#endif++#ifdef STBIR_NEON+#undef STBIR_NEON+#endif++#ifdef STBIR_AVX2+#undef STBIR_AVX2+#endif++#ifdef STBIR_FP16C+#undef STBIR_FP16C+#endif++#ifdef STBIR_WASM+#undef STBIR_WASM+#endif++#ifdef STBIR_SIMD+#undef STBIR_SIMD+#endif++#else // STBIR_SIMD++#ifdef STBIR_SSE2+  #include <emmintrin.h>++  #define stbir__simdf __m128+  #define stbir__simdi __m128i++  #define stbir_simdi_castf( reg ) _mm_castps_si128(reg)+  #define stbir_simdf_casti( reg ) _mm_castsi128_ps(reg)++  #define stbir__simdf_load( reg, ptr ) (reg) = _mm_loadu_ps( (float const*)(ptr) )+  #define stbir__simdi_load( reg, ptr ) (reg) = _mm_loadu_si128 ( (stbir__simdi const*)(ptr) )+  #define stbir__simdf_load1( out, ptr ) (out) = _mm_load_ss( (float const*)(ptr) )  // top values can be random (not denormal or nan for perf)+  #define stbir__simdi_load1( out, ptr ) (out) = _mm_castps_si128( _mm_load_ss( (float const*)(ptr) ))+  #define stbir__simdf_load1z( out, ptr ) (out) = _mm_load_ss( (float const*)(ptr) )  // top values must be zero+  #define stbir__simdf_frep4( fvar ) _mm_set_ps1( fvar )+  #define stbir__simdf_load1frep4( out, fvar ) (out) = _mm_set_ps1( fvar )+  #define stbir__simdf_load2( out, ptr ) (out) = _mm_castsi128_ps( _mm_loadl_epi64( (__m128i*)(ptr)) ) // top values can be random (not denormal or nan for perf)+  #define stbir__simdf_load2z( out, ptr ) (out) = _mm_castsi128_ps( _mm_loadl_epi64( (__m128i*)(ptr)) ) // top values must be zero+  #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = _mm_castpd_ps(_mm_loadh_pd( _mm_castps_pd(reg), (double*)(ptr) ))++  #define stbir__simdf_zeroP() _mm_setzero_ps()+  #define stbir__simdf_zero( reg ) (reg) = _mm_setzero_ps()++  #define stbir__simdf_store( ptr, reg )  _mm_storeu_ps( (float*)(ptr), reg )+  #define stbir__simdf_store1( ptr, reg ) _mm_store_ss( (float*)(ptr), reg )+  #define stbir__simdf_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), _mm_castps_si128(reg) )+  #define stbir__simdf_store2h( ptr, reg ) _mm_storeh_pd( (double*)(ptr), _mm_castps_pd(reg) )++  #define stbir__simdi_store( ptr, reg )  _mm_storeu_si128( (__m128i*)(ptr), reg )+  #define stbir__simdi_store1( ptr, reg ) _mm_store_ss( (float*)(ptr), _mm_castsi128_ps(reg) )+  #define stbir__simdi_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), (reg) )++  #define stbir__prefetch( ptr ) _mm_prefetch((char*)(ptr), _MM_HINT_T0 )++  #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \+  { \+    stbir__simdi zero = _mm_setzero_si128(); \+    out2 = _mm_unpacklo_epi8( ireg, zero ); \+    out3 = _mm_unpackhi_epi8( ireg, zero ); \+    out0 = _mm_unpacklo_epi16( out2, zero ); \+    out1 = _mm_unpackhi_epi16( out2, zero ); \+    out2 = _mm_unpacklo_epi16( out3, zero ); \+    out3 = _mm_unpackhi_epi16( out3, zero ); \+  }++#define stbir__simdi_expand_u8_to_1u32(out,ireg) \+  { \+    stbir__simdi zero = _mm_setzero_si128(); \+    out = _mm_unpacklo_epi8( ireg, zero ); \+    out = _mm_unpacklo_epi16( out, zero ); \+  }++  #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \+  { \+    stbir__simdi zero = _mm_setzero_si128(); \+    out0 = _mm_unpacklo_epi16( ireg, zero ); \+    out1 = _mm_unpackhi_epi16( ireg, zero ); \+  }++  #define stbir__simdf_convert_float_to_i32( i, f ) (i) = _mm_cvttps_epi32(f)+  #define stbir__simdf_convert_float_to_int( f ) _mm_cvtt_ss2si(f)+  #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),_mm_setzero_ps()))))+  #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps()))))++  #define stbir__simdi_to_int( i ) _mm_cvtsi128_si32(i)+  #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = _mm_cvtepi32_ps( ireg )+  #define stbir__simdf_add( out, reg0, reg1 ) (out) = _mm_add_ps( reg0, reg1 )+  #define stbir__simdf_mult( out, reg0, reg1 ) (out) = _mm_mul_ps( reg0, reg1 )+  #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = _mm_mul_ps( reg, _mm_loadu_ps( (float const*)(ptr) ) )+  #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = _mm_mul_ss( reg, _mm_load_ss( (float const*)(ptr) ) )+  #define stbir__simdf_add_mem( out, reg, ptr ) (out) = _mm_add_ps( reg, _mm_loadu_ps( (float const*)(ptr) ) )+  #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = _mm_add_ss( reg, _mm_load_ss( (float const*)(ptr) ) )++  #ifdef STBIR_USE_FMA           // not on by default to maintain bit identical simd to non-simd+  #include <immintrin.h>+  #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = _mm_fmadd_ps( mul1, mul2, add )+  #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = _mm_fmadd_ss( mul1, mul2, add )+  #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = _mm_fmadd_ps( mul, _mm_loadu_ps( (float const*)(ptr) ), add )+  #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = _mm_fmadd_ss( mul, _mm_load_ss( (float const*)(ptr) ), add )+  #else+  #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = _mm_add_ps( add, _mm_mul_ps( mul1, mul2 ) )+  #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = _mm_add_ss( add, _mm_mul_ss( mul1, mul2 ) )+  #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = _mm_add_ps( add, _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ) )+  #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = _mm_add_ss( add, _mm_mul_ss( mul, _mm_load_ss( (float const*)(ptr) ) ) )+  #endif++  #define stbir__simdf_add1( out, reg0, reg1 ) (out) = _mm_add_ss( reg0, reg1 )+  #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = _mm_mul_ss( reg0, reg1 )++  #define stbir__simdf_and( out, reg0, reg1 ) (out) = _mm_and_ps( reg0, reg1 )+  #define stbir__simdf_or( out, reg0, reg1 ) (out) = _mm_or_ps( reg0, reg1 )++  #define stbir__simdf_min( out, reg0, reg1 ) (out) = _mm_min_ps( reg0, reg1 )+  #define stbir__simdf_max( out, reg0, reg1 ) (out) = _mm_max_ps( reg0, reg1 )+  #define stbir__simdf_min1( out, reg0, reg1 ) (out) = _mm_min_ss( reg0, reg1 )+  #define stbir__simdf_max1( out, reg0, reg1 ) (out) = _mm_max_ss( reg0, reg1 )++  #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_shuffle_ps( reg1,reg0, (0<<0) + (1<<2) + (2<<4) + (3<<6) )), (3<<0) + (0<<2) + (1<<4) + (2<<6) ) )+  #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_shuffle_ps( reg1,reg0, (0<<0) + (1<<2) + (2<<4) + (3<<6) )), (2<<0) + (3<<2) + (0<<4) + (1<<6) ) )++  static const stbir__simdf STBIR_zeroones = { 0.0f,1.0f,0.0f,1.0f };+  static const stbir__simdf STBIR_onezeros = { 1.0f,0.0f,1.0f,0.0f };+  #define stbir__simdf_aaa1( out, alp, ones ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_movehl_ps( ones, alp ) ), (1<<0) + (1<<2) + (1<<4) + (2<<6) ) )+  #define stbir__simdf_1aaa( out, alp, ones ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_movelh_ps( ones, alp ) ), (0<<0) + (2<<2) + (2<<4) + (2<<6) ) )+  #define stbir__simdf_a1a1( out, alp, ones) (out) = _mm_or_ps( _mm_castsi128_ps( _mm_srli_epi64( _mm_castps_si128(alp), 32 ) ), STBIR_zeroones )+  #define stbir__simdf_1a1a( out, alp, ones) (out) = _mm_or_ps( _mm_castsi128_ps( _mm_slli_epi64( _mm_castps_si128(alp), 32 ) ), STBIR_onezeros )++  #define stbir__simdf_swiz( reg, one, two, three, four ) _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( reg ), (one<<0) + (two<<2) + (three<<4) + (four<<6) ) )++  #define stbir__simdi_and( out, reg0, reg1 ) (out) = _mm_and_si128( reg0, reg1 )+  #define stbir__simdi_or( out, reg0, reg1 ) (out) = _mm_or_si128( reg0, reg1 )+  #define stbir__simdi_16madd( out, reg0, reg1 ) (out) = _mm_madd_epi16( reg0, reg1 )++  #define stbir__simdf_pack_to_8bytes(out,aa,bb) \+  { \+    stbir__simdf af,bf; \+    stbir__simdi a,b; \+    af = _mm_min_ps( aa, STBIR_max_uint8_as_float ); \+    bf = _mm_min_ps( bb, STBIR_max_uint8_as_float ); \+    af = _mm_max_ps( af, _mm_setzero_ps() ); \+    bf = _mm_max_ps( bf, _mm_setzero_ps() ); \+    a = _mm_cvttps_epi32( af ); \+    b = _mm_cvttps_epi32( bf ); \+    a = _mm_packs_epi32( a, b ); \+    out = _mm_packus_epi16( a, a ); \+  }++  #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \+      stbir__simdf_load( o0, (ptr) );    \+      stbir__simdf_load( o1, (ptr)+4 );  \+      stbir__simdf_load( o2, (ptr)+8 );  \+      stbir__simdf_load( o3, (ptr)+12 ); \+      {                                  \+        __m128 tmp0, tmp1, tmp2, tmp3;   \+        tmp0 = _mm_unpacklo_ps(o0, o1);  \+        tmp2 = _mm_unpacklo_ps(o2, o3);  \+        tmp1 = _mm_unpackhi_ps(o0, o1);  \+        tmp3 = _mm_unpackhi_ps(o2, o3);  \+        o0 = _mm_movelh_ps(tmp0, tmp2);  \+        o1 = _mm_movehl_ps(tmp2, tmp0);  \+        o2 = _mm_movelh_ps(tmp1, tmp3);  \+        o3 = _mm_movehl_ps(tmp3, tmp1);  \+      }++  #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \+      r0 = _mm_packs_epi32( r0, r1 ); \+      r2 = _mm_packs_epi32( r2, r3 ); \+      r1 = _mm_unpacklo_epi16( r0, r2 ); \+      r3 = _mm_unpackhi_epi16( r0, r2 ); \+      r0 = _mm_unpacklo_epi16( r1, r3 ); \+      r2 = _mm_unpackhi_epi16( r1, r3 ); \+      r0 = _mm_packus_epi16( r0, r2 ); \+      stbir__simdi_store( ptr, r0 ); \++  #define stbir__simdi_32shr( out, reg, imm ) out = _mm_srli_epi32( reg, imm )++  #if defined(_MSC_VER) && !defined(__clang__)+    // msvc inits with 8 bytes+    #define STBIR__CONST_32_TO_8( v ) (char)(unsigned char)((v)&255),(char)(unsigned char)(((v)>>8)&255),(char)(unsigned char)(((v)>>16)&255),(char)(unsigned char)(((v)>>24)&255)+    #define STBIR__CONST_4_32i( v ) STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v )+    #define STBIR__CONST_4d_32i( v0, v1, v2, v3 ) STBIR__CONST_32_TO_8( v0 ), STBIR__CONST_32_TO_8( v1 ), STBIR__CONST_32_TO_8( v2 ), STBIR__CONST_32_TO_8( v3 )+  #else+    // everything else inits with long long's+    #define STBIR__CONST_4_32i( v ) (long long)((((stbir_uint64)(stbir_uint32)(v))<<32)|((stbir_uint64)(stbir_uint32)(v))),(long long)((((stbir_uint64)(stbir_uint32)(v))<<32)|((stbir_uint64)(stbir_uint32)(v)))+    #define STBIR__CONST_4d_32i( v0, v1, v2, v3 ) (long long)((((stbir_uint64)(stbir_uint32)(v1))<<32)|((stbir_uint64)(stbir_uint32)(v0))),(long long)((((stbir_uint64)(stbir_uint32)(v3))<<32)|((stbir_uint64)(stbir_uint32)(v2)))+  #endif++  #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = { x, x, x, x }+  #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { STBIR__CONST_4_32i(x) }+  #define STBIR__CONSTF(var) (var)+  #define STBIR__CONSTI(var) (var)++  #if defined(STBIR_AVX) || defined(__SSE4_1__)+    #include <smmintrin.h>+    #define stbir__simdf_pack_to_8words(out,reg0,reg1) out = _mm_packus_epi32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())), _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())))+  #else+    STBIR__SIMDI_CONST(stbir__s32_32768, 32768);+    STBIR__SIMDI_CONST(stbir__s16_32768, ((32768<<16)|32768));++    #define stbir__simdf_pack_to_8words(out,reg0,reg1) \+      { \+        stbir__simdi tmp0,tmp1; \+        tmp0 = _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())); \+        tmp1 = _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())); \+        tmp0 = _mm_sub_epi32( tmp0, stbir__s32_32768 ); \+        tmp1 = _mm_sub_epi32( tmp1, stbir__s32_32768 ); \+        out = _mm_packs_epi32( tmp0, tmp1 ); \+        out = _mm_sub_epi16( out, stbir__s16_32768 ); \+      }++  #endif++  #define STBIR_SIMD++  // if we detect AVX, set the simd8 defines+  #ifdef STBIR_AVX+    #include <immintrin.h>+    #define STBIR_SIMD8+    #define stbir__simdf8 __m256+    #define stbir__simdi8 __m256i+    #define stbir__simdf8_load( out, ptr ) (out) = _mm256_loadu_ps( (float const *)(ptr) )+    #define stbir__simdi8_load( out, ptr ) (out) = _mm256_loadu_si256( (__m256i const *)(ptr) )+    #define stbir__simdf8_mult( out, a, b ) (out) = _mm256_mul_ps( (a), (b) )+    #define stbir__simdf8_store( ptr, out ) _mm256_storeu_ps( (float*)(ptr), out )+    #define stbir__simdi8_store( ptr, reg )  _mm256_storeu_si256( (__m256i*)(ptr), reg )+    #define stbir__simdf8_frep8( fval ) _mm256_set1_ps( fval )++    #define stbir__simdf8_min( out, reg0, reg1 ) (out) = _mm256_min_ps( reg0, reg1 )+    #define stbir__simdf8_max( out, reg0, reg1 ) (out) = _mm256_max_ps( reg0, reg1 )++    #define stbir__simdf8_add4halves( out, bot4, top8 ) (out) = _mm_add_ps( bot4, _mm256_extractf128_ps( top8, 1 ) )+    #define stbir__simdf8_mult_mem( out, reg, ptr ) (out) = _mm256_mul_ps( reg, _mm256_loadu_ps( (float const*)(ptr) ) )+    #define stbir__simdf8_add_mem( out, reg, ptr ) (out) = _mm256_add_ps( reg, _mm256_loadu_ps( (float const*)(ptr) ) )+    #define stbir__simdf8_add( out, a, b ) (out) = _mm256_add_ps( a, b )+    #define stbir__simdf8_load1b( out, ptr ) (out) = _mm256_broadcast_ss( ptr )+    #define stbir__simdf_load1rep4( out, ptr ) (out) = _mm_broadcast_ss( ptr )  // avx load instruction++    #define stbir__simdi8_convert_i32_to_float(out, ireg) (out) = _mm256_cvtepi32_ps( ireg )+    #define stbir__simdf8_convert_float_to_i32( i, f ) (i) = _mm256_cvttps_epi32(f)++    #define stbir__simdf8_bot4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (0<<0)+(2<<4) )+    #define stbir__simdf8_top4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (1<<0)+(3<<4) )++    #define stbir__simdf8_gettop4( reg ) _mm256_extractf128_ps(reg,1)++    #ifdef STBIR_AVX2++    #define stbir__simdi8_expand_u8_to_u32(out0,out1,ireg) \+    { \+      stbir__simdi8 a, zero  =_mm256_setzero_si256();\+      a = _mm256_permute4x64_epi64( _mm256_unpacklo_epi8( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), zero ),(0<<0)+(2<<2)+(1<<4)+(3<<6)); \+      out0 = _mm256_unpacklo_epi16( a, zero ); \+      out1 = _mm256_unpackhi_epi16( a, zero ); \+    }++    #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \+    { \+      stbir__simdi8 t; \+      stbir__simdf8 af,bf; \+      stbir__simdi8 a,b; \+      af = _mm256_min_ps( aa, STBIR_max_uint8_as_floatX ); \+      bf = _mm256_min_ps( bb, STBIR_max_uint8_as_floatX ); \+      af = _mm256_max_ps( af, _mm256_setzero_ps() ); \+      bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \+      a = _mm256_cvttps_epi32( af ); \+      b = _mm256_cvttps_epi32( bf ); \+      t = _mm256_permute4x64_epi64( _mm256_packs_epi32( a, b ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ); \+      out = _mm256_castsi256_si128( _mm256_permute4x64_epi64( _mm256_packus_epi16( t, t ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ) ); \+    }++    #define stbir__simdi8_expand_u16_to_u32(out,ireg) out = _mm256_unpacklo_epi16( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), _mm256_setzero_si256() );++    #define stbir__simdf8_pack_to_16words(out,aa,bb) \+      { \+        stbir__simdf8 af,bf; \+        stbir__simdi8 a,b; \+        af = _mm256_min_ps( aa, STBIR_max_uint16_as_floatX ); \+        bf = _mm256_min_ps( bb, STBIR_max_uint16_as_floatX ); \+        af = _mm256_max_ps( af, _mm256_setzero_ps() ); \+        bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \+        a = _mm256_cvttps_epi32( af ); \+        b = _mm256_cvttps_epi32( bf ); \+        (out) = _mm256_permute4x64_epi64( _mm256_packus_epi32(a, b), (0<<0)+(2<<2)+(1<<4)+(3<<6) ); \+      }++    #else++    #define stbir__simdi8_expand_u8_to_u32(out0,out1,ireg) \+    { \+      stbir__simdi a,zero = _mm_setzero_si128(); \+      a = _mm_unpacklo_epi8( ireg, zero ); \+      out0 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \+      a = _mm_unpackhi_epi8( ireg, zero ); \+      out1 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \+    }++    #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \+    { \+      stbir__simdi t; \+      stbir__simdf8 af,bf; \+      stbir__simdi8 a,b; \+      af = _mm256_min_ps( aa, STBIR_max_uint8_as_floatX ); \+      bf = _mm256_min_ps( bb, STBIR_max_uint8_as_floatX ); \+      af = _mm256_max_ps( af, _mm256_setzero_ps() ); \+      bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \+      a = _mm256_cvttps_epi32( af ); \+      b = _mm256_cvttps_epi32( bf ); \+      out = _mm_packs_epi32( _mm256_castsi256_si128(a), _mm256_extractf128_si256( a, 1 ) ); \+      out = _mm_packus_epi16( out, out ); \+      t = _mm_packs_epi32( _mm256_castsi256_si128(b), _mm256_extractf128_si256( b, 1 ) ); \+      t = _mm_packus_epi16( t, t ); \+      out = _mm_castps_si128( _mm_shuffle_ps( _mm_castsi128_ps(out), _mm_castsi128_ps(t), (0<<0)+(1<<2)+(0<<4)+(1<<6) ) ); \+    }++    #define stbir__simdi8_expand_u16_to_u32(out,ireg) \+    { \+      stbir__simdi a,b,zero = _mm_setzero_si128(); \+      a = _mm_unpacklo_epi16( ireg, zero ); \+      b = _mm_unpackhi_epi16( ireg, zero ); \+      out = _mm256_insertf128_si256( _mm256_castsi128_si256( a ), b, 1 ); \+    }++    #define stbir__simdf8_pack_to_16words(out,aa,bb) \+      { \+        stbir__simdi t0,t1; \+        stbir__simdf8 af,bf; \+        stbir__simdi8 a,b; \+        af = _mm256_min_ps( aa, STBIR_max_uint16_as_floatX ); \+        bf = _mm256_min_ps( bb, STBIR_max_uint16_as_floatX ); \+        af = _mm256_max_ps( af, _mm256_setzero_ps() ); \+        bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \+        a = _mm256_cvttps_epi32( af ); \+        b = _mm256_cvttps_epi32( bf ); \+        t0 = _mm_packus_epi32( _mm256_castsi256_si128(a), _mm256_extractf128_si256( a, 1 ) ); \+        t1 = _mm_packus_epi32( _mm256_castsi256_si128(b), _mm256_extractf128_si256( b, 1 ) ); \+        out = _mm256_setr_m128i( t0, t1 ); \+      }++    #endif++    static __m256i stbir_00001111 = { STBIR__CONST_4d_32i( 0, 0, 0, 0 ), STBIR__CONST_4d_32i( 1, 1, 1, 1 ) };+    #define stbir__simdf8_0123to00001111( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_00001111 )++    static __m256i stbir_22223333 = { STBIR__CONST_4d_32i( 2, 2, 2, 2 ), STBIR__CONST_4d_32i( 3, 3, 3, 3 ) };+    #define stbir__simdf8_0123to22223333( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_22223333 )++    #define stbir__simdf8_0123to2222( out, in ) (out) = stbir__simdf_swiz(_mm256_castps256_ps128(in), 2,2,2,2 )++    #define stbir__simdf8_load4b( out, ptr ) (out) = _mm256_broadcast_ps( (__m128 const *)(ptr) )++    static __m256i stbir_00112233 = { STBIR__CONST_4d_32i( 0, 0, 1, 1 ), STBIR__CONST_4d_32i( 2, 2, 3, 3 ) };+    #define stbir__simdf8_0123to00112233( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_00112233 )+    #define stbir__simdf8_add4( out, a8, b ) (out) = _mm256_add_ps( a8,  _mm256_castps128_ps256( b ) )++    static __m256i stbir_load6 = { STBIR__CONST_4_32i( 0x80000000 ), STBIR__CONST_4d_32i(  0x80000000,  0x80000000, 0, 0 ) };+    #define stbir__simdf8_load6z( out, ptr ) (out) = _mm256_maskload_ps( ptr, stbir_load6 )++    #define stbir__simdf8_0123to00000000( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (0<<0)+(0<<2)+(0<<4)+(0<<6) )+    #define stbir__simdf8_0123to11111111( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (1<<0)+(1<<2)+(1<<4)+(1<<6) )+    #define stbir__simdf8_0123to22222222( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (2<<0)+(2<<2)+(2<<4)+(2<<6) )+    #define stbir__simdf8_0123to33333333( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (3<<0)+(3<<2)+(3<<4)+(3<<6) )+    #define stbir__simdf8_0123to21032103( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (2<<0)+(1<<2)+(0<<4)+(3<<6) )+    #define stbir__simdf8_0123to32103210( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (3<<0)+(2<<2)+(1<<4)+(0<<6) )+    #define stbir__simdf8_0123to12301230( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (1<<0)+(2<<2)+(3<<4)+(0<<6) )+    #define stbir__simdf8_0123to10321032( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (1<<0)+(0<<2)+(3<<4)+(2<<6) )+    #define stbir__simdf8_0123to30123012( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (3<<0)+(0<<2)+(1<<4)+(2<<6) )++    #define stbir__simdf8_0123to11331133( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (1<<0)+(1<<2)+(3<<4)+(3<<6) )+    #define stbir__simdf8_0123to00220022( out, in ) (out) =  _mm256_shuffle_ps ( in, in, (0<<0)+(0<<2)+(2<<4)+(2<<6) )++    #define stbir__simdf8_aaa1( out, alp, ones ) (out) = _mm256_blend_ps( alp, ones, (1<<0)+(1<<1)+(1<<2)+(0<<3)+(1<<4)+(1<<5)+(1<<6)+(0<<7)); (out)=_mm256_shuffle_ps( out,out, (3<<0) + (3<<2) + (3<<4) + (0<<6) )+    #define stbir__simdf8_1aaa( out, alp, ones ) (out) = _mm256_blend_ps( alp, ones, (0<<0)+(1<<1)+(1<<2)+(1<<3)+(0<<4)+(1<<5)+(1<<6)+(1<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (0<<4) + (0<<6) )+    #define stbir__simdf8_a1a1( out, alp, ones) (out) = _mm256_blend_ps( alp, ones, (1<<0)+(0<<1)+(1<<2)+(0<<3)+(1<<4)+(0<<5)+(1<<6)+(0<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (3<<4) + (2<<6) )+    #define stbir__simdf8_1a1a( out, alp, ones) (out) = _mm256_blend_ps( alp, ones, (0<<0)+(1<<1)+(0<<2)+(1<<3)+(0<<4)+(1<<5)+(0<<6)+(1<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (3<<4) + (2<<6) )++    #define stbir__simdf8_zero( reg ) (reg) = _mm256_setzero_ps()++    #ifdef STBIR_USE_FMA           // not on by default to maintain bit identical simd to non-simd+    #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_fmadd_ps( mul1, mul2, add )+    #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_fmadd_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ), add )+    #define stbir__simdf8_madd_mem4( out, add, mul, ptr )(out) = _mm256_fmadd_ps( _mm256_setr_m128( mul, _mm_setzero_ps() ), _mm256_setr_m128( _mm_loadu_ps( (float const*)(ptr) ), _mm_setzero_ps() ), add )+    #else+    #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul1, mul2 ) )+    #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ) ) )+    #define stbir__simdf8_madd_mem4( out, add, mul, ptr )  (out) = _mm256_add_ps( add, _mm256_setr_m128( _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ), _mm_setzero_ps() ) )+    #endif+    #define stbir__if_simdf8_cast_to_simdf4( val ) _mm256_castps256_ps128( val )++  #endif++  #ifdef STBIR_FLOORF+  #undef STBIR_FLOORF+  #endif+  #define STBIR_FLOORF stbir_simd_floorf+  static stbir__inline float stbir_simd_floorf(float x)  // martins floorf+  {+    #if defined(STBIR_AVX) || defined(__SSE4_1__) || defined(STBIR_SSE41)+    __m128 t = _mm_set_ss(x);+    return _mm_cvtss_f32( _mm_floor_ss(t, t) );+    #else+    __m128 f = _mm_set_ss(x);+    __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f));+    __m128 r = _mm_add_ss(t, _mm_and_ps(_mm_cmplt_ss(f, t), _mm_set_ss(-1.0f)));+    return _mm_cvtss_f32(r);+    #endif+  }++  #ifdef STBIR_CEILF+  #undef STBIR_CEILF+  #endif+  #define STBIR_CEILF stbir_simd_ceilf+  static stbir__inline float stbir_simd_ceilf(float x)  // martins ceilf+  {+    #if defined(STBIR_AVX) || defined(__SSE4_1__) || defined(STBIR_SSE41)+    __m128 t = _mm_set_ss(x);+    return _mm_cvtss_f32( _mm_ceil_ss(t, t) );+    #else+    __m128 f = _mm_set_ss(x);+    __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f));+    __m128 r = _mm_add_ss(t, _mm_and_ps(_mm_cmplt_ss(t, f), _mm_set_ss(1.0f)));+    return _mm_cvtss_f32(r);+    #endif+  }++#elif defined(STBIR_NEON)++  #include <arm_neon.h>++  #define stbir__simdf float32x4_t+  #define stbir__simdi uint32x4_t++  #define stbir_simdi_castf( reg ) vreinterpretq_u32_f32(reg)+  #define stbir_simdf_casti( reg ) vreinterpretq_f32_u32(reg)++  #define stbir__simdf_load( reg, ptr ) (reg) = vld1q_f32( (float const*)(ptr) )+  #define stbir__simdi_load( reg, ptr ) (reg) = vld1q_u32( (uint32_t const*)(ptr) )+  #define stbir__simdf_load1( out, ptr ) (out) = vld1q_dup_f32( (float const*)(ptr) ) // top values can be random (not denormal or nan for perf)+  #define stbir__simdi_load1( out, ptr ) (out) = vld1q_dup_u32( (uint32_t const*)(ptr) )+  #define stbir__simdf_load1z( out, ptr ) (out) = vld1q_lane_f32( (float const*)(ptr), vdupq_n_f32(0), 0 ) // top values must be zero+  #define stbir__simdf_frep4( fvar ) vdupq_n_f32( fvar )+  #define stbir__simdf_load1frep4( out, fvar ) (out) = vdupq_n_f32( fvar )+  #define stbir__simdf_load2( out, ptr ) (out) = vcombine_f32( vld1_f32( (float const*)(ptr) ), vcreate_f32(0) ) // top values can be random (not denormal or nan for perf)+  #define stbir__simdf_load2z( out, ptr ) (out) = vcombine_f32( vld1_f32( (float const*)(ptr) ), vcreate_f32(0) )  // top values must be zero+  #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = vcombine_f32( vget_low_f32(reg), vld1_f32( (float const*)(ptr) ) )++  #define stbir__simdf_zeroP() vdupq_n_f32(0)+  #define stbir__simdf_zero( reg ) (reg) = vdupq_n_f32(0)++  #define stbir__simdf_store( ptr, reg )  vst1q_f32( (float*)(ptr), reg )+  #define stbir__simdf_store1( ptr, reg ) vst1q_lane_f32( (float*)(ptr), reg, 0)+  #define stbir__simdf_store2( ptr, reg ) vst1_f32( (float*)(ptr), vget_low_f32(reg) )+  #define stbir__simdf_store2h( ptr, reg ) vst1_f32( (float*)(ptr), vget_high_f32(reg) )++  #define stbir__simdi_store( ptr, reg )  vst1q_u32( (uint32_t*)(ptr), reg )+  #define stbir__simdi_store1( ptr, reg ) vst1q_lane_u32( (uint32_t*)(ptr), reg, 0 )+  #define stbir__simdi_store2( ptr, reg ) vst1_u32( (uint32_t*)(ptr), vget_low_u32(reg) )++  #define stbir__prefetch( ptr )++  #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \+  { \+    uint16x8_t l = vmovl_u8( vget_low_u8 ( vreinterpretq_u8_u32(ireg) ) ); \+    uint16x8_t h = vmovl_u8( vget_high_u8( vreinterpretq_u8_u32(ireg) ) ); \+    out0 = vmovl_u16( vget_low_u16 ( l ) ); \+    out1 = vmovl_u16( vget_high_u16( l ) ); \+    out2 = vmovl_u16( vget_low_u16 ( h ) ); \+    out3 = vmovl_u16( vget_high_u16( h ) ); \+  }++  #define stbir__simdi_expand_u8_to_1u32(out,ireg) \+  { \+    uint16x8_t tmp = vmovl_u8( vget_low_u8( vreinterpretq_u8_u32(ireg) ) ); \+    out = vmovl_u16( vget_low_u16( tmp ) ); \+  }++  #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \+  { \+    uint16x8_t tmp = vreinterpretq_u16_u32(ireg); \+    out0 = vmovl_u16( vget_low_u16 ( tmp ) ); \+    out1 = vmovl_u16( vget_high_u16( tmp ) ); \+  }++  #define stbir__simdf_convert_float_to_i32( i, f ) (i) = vreinterpretq_u32_s32( vcvtq_s32_f32(f) )+  #define stbir__simdf_convert_float_to_int( f ) vgetq_lane_s32(vcvtq_s32_f32(f), 0)+  #define stbir__simdi_to_int( i ) (int)vgetq_lane_u32(i, 0)+  #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),vdupq_n_f32(0))), 0))+  #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),vdupq_n_f32(0))), 0))+  #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = vcvtq_f32_s32( vreinterpretq_s32_u32(ireg) )+  #define stbir__simdf_add( out, reg0, reg1 ) (out) = vaddq_f32( reg0, reg1 )+  #define stbir__simdf_mult( out, reg0, reg1 ) (out) = vmulq_f32( reg0, reg1 )+  #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = vmulq_f32( reg, vld1q_f32( (float const*)(ptr) ) )+  #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = vmulq_f32( reg, vld1q_dup_f32( (float const*)(ptr) ) )+  #define stbir__simdf_add_mem( out, reg, ptr ) (out) = vaddq_f32( reg, vld1q_f32( (float const*)(ptr) ) )+  #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = vaddq_f32( reg, vld1q_dup_f32( (float const*)(ptr) ) )++  #ifdef STBIR_USE_FMA           // not on by default to maintain bit identical simd to non-simd (and also x64 no madd to arm madd)+  #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = vfmaq_f32( add, mul1, mul2 )+  #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = vfmaq_f32( add, mul1, mul2 )+  #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = vfmaq_f32( add, mul, vld1q_f32( (float const*)(ptr) ) )+  #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = vfmaq_f32( add, mul, vld1q_dup_f32( (float const*)(ptr) ) )+  #else+  #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = vaddq_f32( add, vmulq_f32( mul1, mul2 ) )+  #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = vaddq_f32( add, vmulq_f32( mul1, mul2 ) )+  #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = vaddq_f32( add, vmulq_f32( mul, vld1q_f32( (float const*)(ptr) ) ) )+  #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = vaddq_f32( add, vmulq_f32( mul, vld1q_dup_f32( (float const*)(ptr) ) ) )+  #endif++  #define stbir__simdf_add1( out, reg0, reg1 ) (out) = vaddq_f32( reg0, reg1 )+  #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = vmulq_f32( reg0, reg1 )++  #define stbir__simdf_and( out, reg0, reg1 ) (out) = vreinterpretq_f32_u32( vandq_u32( vreinterpretq_u32_f32(reg0), vreinterpretq_u32_f32(reg1) ) )+  #define stbir__simdf_or( out, reg0, reg1 ) (out) = vreinterpretq_f32_u32( vorrq_u32( vreinterpretq_u32_f32(reg0), vreinterpretq_u32_f32(reg1) ) )++  #define stbir__simdf_min( out, reg0, reg1 ) (out) = vminq_f32( reg0, reg1 )+  #define stbir__simdf_max( out, reg0, reg1 ) (out) = vmaxq_f32( reg0, reg1 )+  #define stbir__simdf_min1( out, reg0, reg1 ) (out) = vminq_f32( reg0, reg1 )+  #define stbir__simdf_max1( out, reg0, reg1 ) (out) = vmaxq_f32( reg0, reg1 )++  #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out) = vextq_f32( reg0, reg1, 3 )+  #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out) = vextq_f32( reg0, reg1, 2 )++  #define stbir__simdf_a1a1( out, alp, ones ) (out) = vzipq_f32(vuzpq_f32(alp, alp).val[1], ones).val[0]+  #define stbir__simdf_1a1a( out, alp, ones ) (out) = vzipq_f32(ones, vuzpq_f32(alp, alp).val[0]).val[0]++  #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ )++    #define stbir__simdf_aaa1( out, alp, ones ) (out) = vcopyq_laneq_f32(vdupq_n_f32(vgetq_lane_f32(alp, 3)), 3, ones, 3)+    #define stbir__simdf_1aaa( out, alp, ones ) (out) = vcopyq_laneq_f32(vdupq_n_f32(vgetq_lane_f32(alp, 0)), 0, ones, 0)++    #if defined( _MSC_VER ) && !defined(__clang__)+      #define stbir_make16(a,b,c,d) vcombine_u8( \+        vcreate_u8( (4*a+0) | ((4*a+1)<<8) | ((4*a+2)<<16) | ((4*a+3)<<24) | \+          ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56)), \+        vcreate_u8( (4*c+0) | ((4*c+1)<<8) | ((4*c+2)<<16) | ((4*c+3)<<24) | \+          ((stbir_uint64)(4*d+0)<<32) | ((stbir_uint64)(4*d+1)<<40) | ((stbir_uint64)(4*d+2)<<48) | ((stbir_uint64)(4*d+3)<<56) ) )++      static stbir__inline uint8x16x2_t stbir_make16x2(float32x4_t rega,float32x4_t regb)+      {+        uint8x16x2_t r = { vreinterpretq_u8_f32(rega), vreinterpretq_u8_f32(regb) };+        return r;+      }+    #else+      #define stbir_make16(a,b,c,d) (uint8x16_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3,4*c+0,4*c+1,4*c+2,4*c+3,4*d+0,4*d+1,4*d+2,4*d+3}+      #define stbir_make16x2(a,b) (uint8x16x2_t){{vreinterpretq_u8_f32(a),vreinterpretq_u8_f32(b)}}+    #endif++    #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vqtbl1q_u8( vreinterpretq_u8_f32(reg), stbir_make16(one, two, three, four) ) )+    #define stbir__simdf_swiz2( rega, regb, one, two, three, four ) vreinterpretq_f32_u8( vqtbl2q_u8( stbir_make16x2(rega,regb), stbir_make16(one, two, three, four) ) )++    #define stbir__simdi_16madd( out, reg0, reg1 ) \+    { \+      int16x8_t r0 = vreinterpretq_s16_u32(reg0); \+      int16x8_t r1 = vreinterpretq_s16_u32(reg1); \+      int32x4_t tmp0 = vmull_s16( vget_low_s16(r0), vget_low_s16(r1) ); \+      int32x4_t tmp1 = vmull_s16( vget_high_s16(r0), vget_high_s16(r1) ); \+      (out) = vreinterpretq_u32_s32( vpaddq_s32(tmp0, tmp1) ); \+    }++  #else++    #define stbir__simdf_aaa1( out, alp, ones ) (out) = vsetq_lane_f32(1.0f, vdupq_n_f32(vgetq_lane_f32(alp, 3)), 3)+    #define stbir__simdf_1aaa( out, alp, ones ) (out) = vsetq_lane_f32(1.0f, vdupq_n_f32(vgetq_lane_f32(alp, 0)), 0)++    #if defined( _MSC_VER ) && !defined(__clang__)+      static stbir__inline uint8x8x2_t stbir_make8x2(float32x4_t reg)+      {+        uint8x8x2_t r = { { vget_low_u8(vreinterpretq_u8_f32(reg)), vget_high_u8(vreinterpretq_u8_f32(reg)) } };+        return r;+      }+      #define stbir_make8(a,b) vcreate_u8( \+        (4*a+0) | ((4*a+1)<<8) | ((4*a+2)<<16) | ((4*a+3)<<24) | \+        ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56) )+    #else+      #define stbir_make8x2(reg) (uint8x8x2_t){ { vget_low_u8(vreinterpretq_u8_f32(reg)), vget_high_u8(vreinterpretq_u8_f32(reg)) } }+      #define stbir_make8(a,b) (uint8x8_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3}+    #endif++    #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vcombine_u8( \+        vtbl2_u8( stbir_make8x2( reg ), stbir_make8( one, two ) ), \+        vtbl2_u8( stbir_make8x2( reg ), stbir_make8( three, four ) ) ) )++    #define stbir__simdi_16madd( out, reg0, reg1 ) \+    { \+      int16x8_t r0 = vreinterpretq_s16_u32(reg0); \+      int16x8_t r1 = vreinterpretq_s16_u32(reg1); \+      int32x4_t tmp0 = vmull_s16( vget_low_s16(r0), vget_low_s16(r1) ); \+      int32x4_t tmp1 = vmull_s16( vget_high_s16(r0), vget_high_s16(r1) ); \+      int32x2_t out0 = vpadd_s32( vget_low_s32(tmp0), vget_high_s32(tmp0) ); \+      int32x2_t out1 = vpadd_s32( vget_low_s32(tmp1), vget_high_s32(tmp1) ); \+      (out) = vreinterpretq_u32_s32( vcombine_s32(out0, out1) ); \+    }++  #endif++  #define stbir__simdi_and( out, reg0, reg1 ) (out) = vandq_u32( reg0, reg1 )+  #define stbir__simdi_or( out, reg0, reg1 ) (out) = vorrq_u32( reg0, reg1 )++  #define stbir__simdf_pack_to_8bytes(out,aa,bb) \+  { \+    float32x4_t af = vmaxq_f32( vminq_f32(aa,STBIR__CONSTF(STBIR_max_uint8_as_float) ), vdupq_n_f32(0) ); \+    float32x4_t bf = vmaxq_f32( vminq_f32(bb,STBIR__CONSTF(STBIR_max_uint8_as_float) ), vdupq_n_f32(0) ); \+    int16x4_t ai = vqmovn_s32( vcvtq_s32_f32( af ) ); \+    int16x4_t bi = vqmovn_s32( vcvtq_s32_f32( bf ) ); \+    uint8x8_t out8 = vqmovun_s16( vcombine_s16(ai, bi) ); \+    out = vreinterpretq_u32_u8( vcombine_u8(out8, out8) ); \+  }++  #define stbir__simdf_pack_to_8words(out,aa,bb) \+  { \+    float32x4_t af = vmaxq_f32( vminq_f32(aa,STBIR__CONSTF(STBIR_max_uint16_as_float) ), vdupq_n_f32(0) ); \+    float32x4_t bf = vmaxq_f32( vminq_f32(bb,STBIR__CONSTF(STBIR_max_uint16_as_float) ), vdupq_n_f32(0) ); \+    int32x4_t ai = vcvtq_s32_f32( af ); \+    int32x4_t bi = vcvtq_s32_f32( bf ); \+    out = vreinterpretq_u32_u16( vcombine_u16(vqmovun_s32(ai), vqmovun_s32(bi)) ); \+  }++  #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \+  { \+    int16x4x2_t tmp0 = vzip_s16( vqmovn_s32(vreinterpretq_s32_u32(r0)), vqmovn_s32(vreinterpretq_s32_u32(r2)) ); \+    int16x4x2_t tmp1 = vzip_s16( vqmovn_s32(vreinterpretq_s32_u32(r1)), vqmovn_s32(vreinterpretq_s32_u32(r3)) ); \+    uint8x8x2_t out = \+    { { \+      vqmovun_s16( vcombine_s16(tmp0.val[0], tmp0.val[1]) ), \+      vqmovun_s16( vcombine_s16(tmp1.val[0], tmp1.val[1]) ), \+    } }; \+    vst2_u8(ptr, out); \+  }++  #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \+  { \+    float32x4x4_t tmp = vld4q_f32(ptr); \+    o0 = tmp.val[0]; \+    o1 = tmp.val[1]; \+    o2 = tmp.val[2]; \+    o3 = tmp.val[3]; \+  }++  #define stbir__simdi_32shr( out, reg, imm ) out = vshrq_n_u32( reg, imm )++  #if defined( _MSC_VER ) && !defined(__clang__)+    #define STBIR__SIMDF_CONST(var, x) __declspec(align(8)) float var[] = { x, x, x, x }+    #define STBIR__SIMDI_CONST(var, x) __declspec(align(8)) uint32_t var[] = { x, x, x, x }+    #define STBIR__CONSTF(var) (*(const float32x4_t*)var)+    #define STBIR__CONSTI(var) (*(const uint32x4_t*)var)+  #else+    #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = { x, x, x, x }+    #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { x, x, x, x }+    #define STBIR__CONSTF(var) (var)+    #define STBIR__CONSTI(var) (var)+  #endif++  #ifdef STBIR_FLOORF+  #undef STBIR_FLOORF+  #endif+  #define STBIR_FLOORF stbir_simd_floorf+  static stbir__inline float stbir_simd_floorf(float x)+  {+    #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ )+    return vget_lane_f32( vrndm_f32( vdup_n_f32(x) ), 0);+    #else+    float32x2_t f = vdup_n_f32(x);+    float32x2_t t = vcvt_f32_s32(vcvt_s32_f32(f));+    uint32x2_t a = vclt_f32(f, t);+    uint32x2_t b = vreinterpret_u32_f32(vdup_n_f32(-1.0f));+    float32x2_t r = vadd_f32(t, vreinterpret_f32_u32(vand_u32(a, b)));+    return vget_lane_f32(r, 0);+    #endif+  }++  #ifdef STBIR_CEILF+  #undef STBIR_CEILF+  #endif+  #define STBIR_CEILF stbir_simd_ceilf+  static stbir__inline float stbir_simd_ceilf(float x)+  {+    #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ )+    return vget_lane_f32( vrndp_f32( vdup_n_f32(x) ), 0);+    #else+    float32x2_t f = vdup_n_f32(x);+    float32x2_t t = vcvt_f32_s32(vcvt_s32_f32(f));+    uint32x2_t a = vclt_f32(t, f);+    uint32x2_t b = vreinterpret_u32_f32(vdup_n_f32(1.0f));+    float32x2_t r = vadd_f32(t, vreinterpret_f32_u32(vand_u32(a, b)));+    return vget_lane_f32(r, 0);+    #endif+  }++  #define STBIR_SIMD++#elif defined(STBIR_WASM)++  #include <wasm_simd128.h>++  #define stbir__simdf v128_t+  #define stbir__simdi v128_t++  #define stbir_simdi_castf( reg ) (reg)+  #define stbir_simdf_casti( reg ) (reg)++  #define stbir__simdf_load( reg, ptr )             (reg) = wasm_v128_load( (void const*)(ptr) )+  #define stbir__simdi_load( reg, ptr )             (reg) = wasm_v128_load( (void const*)(ptr) )+  #define stbir__simdf_load1( out, ptr )            (out) = wasm_v128_load32_splat( (void const*)(ptr) ) // top values can be random (not denormal or nan for perf)+  #define stbir__simdi_load1( out, ptr )            (out) = wasm_v128_load32_splat( (void const*)(ptr) )+  #define stbir__simdf_load1z( out, ptr )           (out) = wasm_v128_load32_zero( (void const*)(ptr) ) // top values must be zero+  #define stbir__simdf_frep4( fvar )                wasm_f32x4_splat( fvar )+  #define stbir__simdf_load1frep4( out, fvar )      (out) = wasm_f32x4_splat( fvar )+  #define stbir__simdf_load2( out, ptr )            (out) = wasm_v128_load64_splat( (void const*)(ptr) ) // top values can be random (not denormal or nan for perf)+  #define stbir__simdf_load2z( out, ptr )           (out) = wasm_v128_load64_zero( (void const*)(ptr) ) // top values must be zero+  #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = wasm_v128_load64_lane( (void const*)(ptr), reg, 1 )++  #define stbir__simdf_zeroP() wasm_f32x4_const_splat(0)+  #define stbir__simdf_zero( reg ) (reg) = wasm_f32x4_const_splat(0)++  #define stbir__simdf_store( ptr, reg )   wasm_v128_store( (void*)(ptr), reg )+  #define stbir__simdf_store1( ptr, reg )  wasm_v128_store32_lane( (void*)(ptr), reg, 0 )+  #define stbir__simdf_store2( ptr, reg )  wasm_v128_store64_lane( (void*)(ptr), reg, 0 )+  #define stbir__simdf_store2h( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 1 )++  #define stbir__simdi_store( ptr, reg )  wasm_v128_store( (void*)(ptr), reg )+  #define stbir__simdi_store1( ptr, reg ) wasm_v128_store32_lane( (void*)(ptr), reg, 0 )+  #define stbir__simdi_store2( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 0 )++  #define stbir__prefetch( ptr )++  #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \+  { \+    v128_t l = wasm_u16x8_extend_low_u8x16 ( ireg ); \+    v128_t h = wasm_u16x8_extend_high_u8x16( ireg ); \+    out0 = wasm_u32x4_extend_low_u16x8 ( l ); \+    out1 = wasm_u32x4_extend_high_u16x8( l ); \+    out2 = wasm_u32x4_extend_low_u16x8 ( h ); \+    out3 = wasm_u32x4_extend_high_u16x8( h ); \+  }++  #define stbir__simdi_expand_u8_to_1u32(out,ireg) \+  { \+    v128_t tmp = wasm_u16x8_extend_low_u8x16(ireg); \+    out = wasm_u32x4_extend_low_u16x8(tmp); \+  }++  #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \+  { \+    out0 = wasm_u32x4_extend_low_u16x8 ( ireg ); \+    out1 = wasm_u32x4_extend_high_u16x8( ireg ); \+  }++  #define stbir__simdf_convert_float_to_i32( i, f )    (i) = wasm_i32x4_trunc_sat_f32x4(f)+  #define stbir__simdf_convert_float_to_int( f )       wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(f), 0)+  #define stbir__simdi_to_int( i )                     wasm_i32x4_extract_lane(i, 0)+  #define stbir__simdf_convert_float_to_uint8( f )     ((unsigned char)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint8_as_float),wasm_f32x4_const_splat(0))), 0))+  #define stbir__simdf_convert_float_to_short( f )     ((unsigned short)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint16_as_float),wasm_f32x4_const_splat(0))), 0))+  #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = wasm_f32x4_convert_i32x4(ireg)+  #define stbir__simdf_add( out, reg0, reg1 )          (out) = wasm_f32x4_add( reg0, reg1 )+  #define stbir__simdf_mult( out, reg0, reg1 )         (out) = wasm_f32x4_mul( reg0, reg1 )+  #define stbir__simdf_mult_mem( out, reg, ptr )       (out) = wasm_f32x4_mul( reg, wasm_v128_load( (void const*)(ptr) ) )+  #define stbir__simdf_mult1_mem( out, reg, ptr )      (out) = wasm_f32x4_mul( reg, wasm_v128_load32_splat( (void const*)(ptr) ) )+  #define stbir__simdf_add_mem( out, reg, ptr )        (out) = wasm_f32x4_add( reg, wasm_v128_load( (void const*)(ptr) ) )+  #define stbir__simdf_add1_mem( out, reg, ptr )       (out) = wasm_f32x4_add( reg, wasm_v128_load32_splat( (void const*)(ptr) ) )++  #define stbir__simdf_madd( out, add, mul1, mul2 )    (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul1, mul2 ) )+  #define stbir__simdf_madd1( out, add, mul1, mul2 )   (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul1, mul2 ) )+  #define stbir__simdf_madd_mem( out, add, mul, ptr )  (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul, wasm_v128_load( (void const*)(ptr) ) ) )+  #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul, wasm_v128_load32_splat( (void const*)(ptr) ) ) )++  #define stbir__simdf_add1( out, reg0, reg1 )  (out) = wasm_f32x4_add( reg0, reg1 )+  #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = wasm_f32x4_mul( reg0, reg1 )++  #define stbir__simdf_and( out, reg0, reg1 ) (out) = wasm_v128_and( reg0, reg1 )+  #define stbir__simdf_or( out, reg0, reg1 )  (out) = wasm_v128_or( reg0, reg1 )++  #define stbir__simdf_min( out, reg0, reg1 ) (out) = wasm_f32x4_min( reg0, reg1 )+  #define stbir__simdf_max( out, reg0, reg1 ) (out) = wasm_f32x4_max( reg0, reg1 )+  #define stbir__simdf_min1( out, reg0, reg1 ) (out) = wasm_f32x4_min( reg0, reg1 )+  #define stbir__simdf_max1( out, reg0, reg1 ) (out) = wasm_f32x4_max( reg0, reg1 )++  #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out) = wasm_i32x4_shuffle( reg0, reg1, 3, 4, 5, -1 )+  #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out) = wasm_i32x4_shuffle( reg0, reg1, 2, 3, 4, -1 )++  #define stbir__simdf_aaa1(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 3, 3, 3, 4)+  #define stbir__simdf_1aaa(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 4, 0, 0, 0)+  #define stbir__simdf_a1a1(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 1, 4, 3, 4)+  #define stbir__simdf_1a1a(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 4, 0, 4, 2)++  #define stbir__simdf_swiz( reg, one, two, three, four ) wasm_i32x4_shuffle(reg, reg, one, two, three, four)++  #define stbir__simdi_and( out, reg0, reg1 )    (out) = wasm_v128_and( reg0, reg1 )+  #define stbir__simdi_or( out, reg0, reg1 )     (out) = wasm_v128_or( reg0, reg1 )+  #define stbir__simdi_16madd( out, reg0, reg1 ) (out) = wasm_i32x4_dot_i16x8( reg0, reg1 )++  #define stbir__simdf_pack_to_8bytes(out,aa,bb) \+  { \+    v128_t af = wasm_f32x4_max( wasm_f32x4_min(aa, STBIR_max_uint8_as_float), wasm_f32x4_const_splat(0) ); \+    v128_t bf = wasm_f32x4_max( wasm_f32x4_min(bb, STBIR_max_uint8_as_float), wasm_f32x4_const_splat(0) ); \+    v128_t ai = wasm_i32x4_trunc_sat_f32x4( af ); \+    v128_t bi = wasm_i32x4_trunc_sat_f32x4( bf ); \+    v128_t out16 = wasm_i16x8_narrow_i32x4( ai, bi ); \+    out = wasm_u8x16_narrow_i16x8( out16, out16 ); \+  }++  #define stbir__simdf_pack_to_8words(out,aa,bb) \+  { \+    v128_t af = wasm_f32x4_max( wasm_f32x4_min(aa, STBIR_max_uint16_as_float), wasm_f32x4_const_splat(0)); \+    v128_t bf = wasm_f32x4_max( wasm_f32x4_min(bb, STBIR_max_uint16_as_float), wasm_f32x4_const_splat(0)); \+    v128_t ai = wasm_i32x4_trunc_sat_f32x4( af ); \+    v128_t bi = wasm_i32x4_trunc_sat_f32x4( bf ); \+    out = wasm_u16x8_narrow_i32x4( ai, bi ); \+  }++  #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \+  { \+    v128_t tmp0 = wasm_i16x8_narrow_i32x4(r0, r1); \+    v128_t tmp1 = wasm_i16x8_narrow_i32x4(r2, r3); \+    v128_t tmp = wasm_u8x16_narrow_i16x8(tmp0, tmp1); \+    tmp = wasm_i8x16_shuffle(tmp, tmp, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15); \+    wasm_v128_store( (void*)(ptr), tmp); \+  }++  #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \+  { \+    v128_t t0 = wasm_v128_load( ptr    ); \+    v128_t t1 = wasm_v128_load( ptr+4  ); \+    v128_t t2 = wasm_v128_load( ptr+8  ); \+    v128_t t3 = wasm_v128_load( ptr+12 ); \+    v128_t s0 = wasm_i32x4_shuffle(t0, t1, 0, 4, 2, 6); \+    v128_t s1 = wasm_i32x4_shuffle(t0, t1, 1, 5, 3, 7); \+    v128_t s2 = wasm_i32x4_shuffle(t2, t3, 0, 4, 2, 6); \+    v128_t s3 = wasm_i32x4_shuffle(t2, t3, 1, 5, 3, 7); \+    o0 = wasm_i32x4_shuffle(s0, s2, 0, 1, 4, 5); \+    o1 = wasm_i32x4_shuffle(s1, s3, 0, 1, 4, 5); \+    o2 = wasm_i32x4_shuffle(s0, s2, 2, 3, 6, 7); \+    o3 = wasm_i32x4_shuffle(s1, s3, 2, 3, 6, 7); \+  }++  #define stbir__simdi_32shr( out, reg, imm ) out = wasm_u32x4_shr( reg, imm )++  typedef float stbir__f32x4 __attribute__((__vector_size__(16), __aligned__(16)));+  #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = (v128_t)(stbir__f32x4){ x, x, x, x }+  #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { x, x, x, x }+  #define STBIR__CONSTF(var) (var)+  #define STBIR__CONSTI(var) (var)++  #ifdef STBIR_FLOORF+  #undef STBIR_FLOORF+  #endif+  #define STBIR_FLOORF stbir_simd_floorf+  static stbir__inline float stbir_simd_floorf(float x)+  {+    return wasm_f32x4_extract_lane( wasm_f32x4_floor( wasm_f32x4_splat(x) ), 0);+  }++  #ifdef STBIR_CEILF+  #undef STBIR_CEILF+  #endif+  #define STBIR_CEILF stbir_simd_ceilf+  static stbir__inline float stbir_simd_ceilf(float x)+  {+    return wasm_f32x4_extract_lane( wasm_f32x4_ceil( wasm_f32x4_splat(x) ), 0);+  }++  #define STBIR_SIMD++#endif  // SSE2/NEON/WASM++#endif // NO SIMD++#ifdef STBIR_SIMD8+  #define stbir__simdfX stbir__simdf8+  #define stbir__simdiX stbir__simdi8+  #define stbir__simdfX_load stbir__simdf8_load+  #define stbir__simdiX_load stbir__simdi8_load+  #define stbir__simdfX_mult stbir__simdf8_mult+  #define stbir__simdfX_add_mem stbir__simdf8_add_mem+  #define stbir__simdfX_madd_mem stbir__simdf8_madd_mem+  #define stbir__simdfX_store stbir__simdf8_store+  #define stbir__simdiX_store stbir__simdi8_store+  #define stbir__simdf_frepX  stbir__simdf8_frep8+  #define stbir__simdfX_madd stbir__simdf8_madd+  #define stbir__simdfX_min stbir__simdf8_min+  #define stbir__simdfX_max stbir__simdf8_max+  #define stbir__simdfX_aaa1 stbir__simdf8_aaa1+  #define stbir__simdfX_1aaa stbir__simdf8_1aaa+  #define stbir__simdfX_a1a1 stbir__simdf8_a1a1+  #define stbir__simdfX_1a1a stbir__simdf8_1a1a+  #define stbir__simdfX_convert_float_to_i32 stbir__simdf8_convert_float_to_i32+  #define stbir__simdfX_pack_to_words stbir__simdf8_pack_to_16words+  #define stbir__simdfX_zero stbir__simdf8_zero+  #define STBIR_onesX STBIR_ones8+  #define STBIR_max_uint8_as_floatX STBIR_max_uint8_as_float8+  #define STBIR_max_uint16_as_floatX STBIR_max_uint16_as_float8+  #define STBIR_simd_point5X STBIR_simd_point58+  #define stbir__simdfX_float_count 8+  #define stbir__simdfX_0123to1230 stbir__simdf8_0123to12301230+  #define stbir__simdfX_0123to2103 stbir__simdf8_0123to21032103+  static const stbir__simdf8 STBIR_max_uint16_as_float_inverted8 = { stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted };+  static const stbir__simdf8 STBIR_max_uint8_as_float_inverted8 = { stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted };+  static const stbir__simdf8 STBIR_ones8 = { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 };+  static const stbir__simdf8 STBIR_simd_point58 = { 0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5 };+  static const stbir__simdf8 STBIR_max_uint8_as_float8 = { stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float, stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float };+  static const stbir__simdf8 STBIR_max_uint16_as_float8 = { stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float, stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float };+#else+  #define stbir__simdfX stbir__simdf+  #define stbir__simdiX stbir__simdi+  #define stbir__simdfX_load stbir__simdf_load+  #define stbir__simdiX_load stbir__simdi_load+  #define stbir__simdfX_mult stbir__simdf_mult+  #define stbir__simdfX_add_mem stbir__simdf_add_mem+  #define stbir__simdfX_madd_mem stbir__simdf_madd_mem+  #define stbir__simdfX_store stbir__simdf_store+  #define stbir__simdiX_store stbir__simdi_store+  #define stbir__simdf_frepX  stbir__simdf_frep4+  #define stbir__simdfX_madd stbir__simdf_madd+  #define stbir__simdfX_min stbir__simdf_min+  #define stbir__simdfX_max stbir__simdf_max+  #define stbir__simdfX_aaa1 stbir__simdf_aaa1+  #define stbir__simdfX_1aaa stbir__simdf_1aaa+  #define stbir__simdfX_a1a1 stbir__simdf_a1a1+  #define stbir__simdfX_1a1a stbir__simdf_1a1a+  #define stbir__simdfX_convert_float_to_i32 stbir__simdf_convert_float_to_i32+  #define stbir__simdfX_pack_to_words stbir__simdf_pack_to_8words+  #define stbir__simdfX_zero stbir__simdf_zero+  #define STBIR_onesX STBIR__CONSTF(STBIR_ones)+  #define STBIR_simd_point5X STBIR__CONSTF(STBIR_simd_point5)+  #define STBIR_max_uint8_as_floatX STBIR__CONSTF(STBIR_max_uint8_as_float)+  #define STBIR_max_uint16_as_floatX STBIR__CONSTF(STBIR_max_uint16_as_float)+  #define stbir__simdfX_float_count 4+  #define stbir__if_simdf8_cast_to_simdf4( val ) ( val )+  #define stbir__simdfX_0123to1230 stbir__simdf_0123to1230+  #define stbir__simdfX_0123to2103 stbir__simdf_0123to2103+#endif+++#if defined(STBIR_NEON) && !defined(_M_ARM) && !defined(__arm__)++  #if defined( _MSC_VER ) && !defined(__clang__)+  typedef __int16 stbir__FP16;+  #else+  typedef float16_t stbir__FP16;+  #endif++#else // no NEON, or 32-bit ARM for MSVC++  typedef union stbir__FP16+  {+    unsigned short u;+  } stbir__FP16;++#endif++#if (!defined(STBIR_NEON) && !defined(STBIR_FP16C)) || (defined(STBIR_NEON) && defined(_M_ARM)) || (defined(STBIR_NEON) && defined(__arm__))++  // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668++  static stbir__inline float stbir__half_to_float( stbir__FP16 h )+  {+    static const stbir__FP32 magic = { (254 - 15) << 23 };+    static const stbir__FP32 was_infnan = { (127 + 16) << 23 };+    stbir__FP32 o;++    o.u = (h.u & 0x7fff) << 13;     // exponent/mantissa bits+    o.f *= magic.f;                 // exponent adjust+    if (o.f >= was_infnan.f)        // make sure Inf/NaN survive+      o.u |= 255 << 23;+    o.u |= (h.u & 0x8000) << 16;    // sign bit+    return o.f;+  }++  static stbir__inline stbir__FP16 stbir__float_to_half(float val)+  {+    stbir__FP32 f32infty = { 255 << 23 };+    stbir__FP32 f16max   = { (127 + 16) << 23 };+    stbir__FP32 denorm_magic = { ((127 - 15) + (23 - 10) + 1) << 23 };+    unsigned int sign_mask = 0x80000000u;+    stbir__FP16 o = { 0 };+    stbir__FP32 f;+    unsigned int sign;++    f.f = val;+    sign = f.u & sign_mask;+    f.u ^= sign;++    if (f.u >= f16max.u) // result is Inf or NaN (all exponent bits set)+      o.u = (f.u > f32infty.u) ? 0x7e00 : 0x7c00; // NaN->qNaN and Inf->Inf+    else // (De)normalized number or zero+    {+      if (f.u < (113 << 23)) // resulting FP16 is subnormal or zero+      {+        // use a magic value to align our 10 mantissa bits at the bottom of+        // the float. as long as FP addition is round-to-nearest-even this+        // just works.+        f.f += denorm_magic.f;+        // and one integer subtract of the bias later, we have our final float!+        o.u = (unsigned short) ( f.u - denorm_magic.u );+      }+      else+      {+        unsigned int mant_odd = (f.u >> 13) & 1; // resulting mantissa is odd+        // update exponent, rounding bias part 1+        f.u = f.u + ((15u - 127) << 23) + 0xfff;+        // rounding bias part 2+        f.u += mant_odd;+        // take the bits!+        o.u = (unsigned short) ( f.u >> 13 );+      }+    }++    o.u |= sign >> 16;+    return o;+  }++#endif+++#if defined(STBIR_FP16C)++  #include <immintrin.h>++  static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input)+  {+    _mm256_storeu_ps( (float*)output, _mm256_cvtph_ps( _mm_loadu_si128( (__m128i const* )input ) ) );+  }++  static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input)+  {+    _mm_storeu_si128( (__m128i*)output, _mm256_cvtps_ph( _mm256_loadu_ps( input ), 0 ) );+  }++  static stbir__inline float stbir__half_to_float( stbir__FP16 h )+  {+    return _mm_cvtss_f32( _mm_cvtph_ps( _mm_cvtsi32_si128( (int)h.u ) ) );+  }++  static stbir__inline stbir__FP16 stbir__float_to_half( float f )+  {+    stbir__FP16 h;+    h.u = (unsigned short) _mm_cvtsi128_si32( _mm_cvtps_ph( _mm_set_ss( f ), 0 ) );+    return h;+  }++#elif defined(STBIR_SSE2)++  // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668+  stbir__inline static void stbir__half_to_float_SIMD(float * output, void const * input)+  {+    static const STBIR__SIMDI_CONST(mask_nosign,      0x7fff);+    static const STBIR__SIMDI_CONST(smallest_normal,  0x0400);+    static const STBIR__SIMDI_CONST(infinity,         0x7c00);+    static const STBIR__SIMDI_CONST(expadjust_normal, (127 - 15) << 23);+    static const STBIR__SIMDI_CONST(magic_denorm,     113 << 23);++    __m128i i = _mm_loadu_si128 ( (__m128i const*)(input) );+    __m128i h = _mm_unpacklo_epi16 ( i, _mm_setzero_si128() );+    __m128i mnosign     = STBIR__CONSTI(mask_nosign);+    __m128i eadjust     = STBIR__CONSTI(expadjust_normal);+    __m128i smallest    = STBIR__CONSTI(smallest_normal);+    __m128i infty       = STBIR__CONSTI(infinity);+    __m128i expmant     = _mm_and_si128(mnosign, h);+    __m128i justsign    = _mm_xor_si128(h, expmant);+    __m128i b_notinfnan = _mm_cmpgt_epi32(infty, expmant);+    __m128i b_isdenorm  = _mm_cmpgt_epi32(smallest, expmant);+    __m128i shifted     = _mm_slli_epi32(expmant, 13);+    __m128i adj_infnan  = _mm_andnot_si128(b_notinfnan, eadjust);+    __m128i adjusted    = _mm_add_epi32(eadjust, shifted);+    __m128i den1        = _mm_add_epi32(shifted, STBIR__CONSTI(magic_denorm));+    __m128i adjusted2   = _mm_add_epi32(adjusted, adj_infnan);+    __m128  den2        = _mm_sub_ps(_mm_castsi128_ps(den1), *(const __m128 *)&magic_denorm);+    __m128  adjusted3   = _mm_and_ps(den2, _mm_castsi128_ps(b_isdenorm));+    __m128  adjusted4   = _mm_andnot_ps(_mm_castsi128_ps(b_isdenorm), _mm_castsi128_ps(adjusted2));+    __m128  adjusted5   = _mm_or_ps(adjusted3, adjusted4);+    __m128i sign        = _mm_slli_epi32(justsign, 16);+    __m128  final       = _mm_or_ps(adjusted5, _mm_castsi128_ps(sign));+    stbir__simdf_store( output + 0,  final );++    h = _mm_unpackhi_epi16 ( i, _mm_setzero_si128() );+    expmant     = _mm_and_si128(mnosign, h);+    justsign    = _mm_xor_si128(h, expmant);+    b_notinfnan = _mm_cmpgt_epi32(infty, expmant);+    b_isdenorm  = _mm_cmpgt_epi32(smallest, expmant);+    shifted     = _mm_slli_epi32(expmant, 13);+    adj_infnan  = _mm_andnot_si128(b_notinfnan, eadjust);+    adjusted    = _mm_add_epi32(eadjust, shifted);+    den1        = _mm_add_epi32(shifted, STBIR__CONSTI(magic_denorm));+    adjusted2   = _mm_add_epi32(adjusted, adj_infnan);+    den2        = _mm_sub_ps(_mm_castsi128_ps(den1), *(const __m128 *)&magic_denorm);+    adjusted3   = _mm_and_ps(den2, _mm_castsi128_ps(b_isdenorm));+    adjusted4   = _mm_andnot_ps(_mm_castsi128_ps(b_isdenorm), _mm_castsi128_ps(adjusted2));+    adjusted5   = _mm_or_ps(adjusted3, adjusted4);+    sign        = _mm_slli_epi32(justsign, 16);+    final       = _mm_or_ps(adjusted5, _mm_castsi128_ps(sign));+    stbir__simdf_store( output + 4,  final );++    // ~38 SSE2 ops for 8 values+  }++  // Fabian's round-to-nearest-even float to half+  // ~48 SSE2 ops for 8 output+  stbir__inline static void stbir__float_to_half_SIMD(void * output, float const * input)+  {+    static const STBIR__SIMDI_CONST(mask_sign,      0x80000000u);+    static const STBIR__SIMDI_CONST(c_f16max,       (127 + 16) << 23); // all FP32 values >=this round to +inf+    static const STBIR__SIMDI_CONST(c_nanbit,        0x200);+    static const STBIR__SIMDI_CONST(c_infty_as_fp16, 0x7c00);+    static const STBIR__SIMDI_CONST(c_min_normal,    (127 - 14) << 23); // smallest FP32 that yields a normalized FP16+    static const STBIR__SIMDI_CONST(c_subnorm_magic, ((127 - 15) + (23 - 10) + 1) << 23);+    static const STBIR__SIMDI_CONST(c_normal_bias,    0xfff - ((127 - 15) << 23)); // adjust exponent and add mantissa rounding++    __m128  f           =  _mm_loadu_ps(input);+    __m128  msign       = _mm_castsi128_ps(STBIR__CONSTI(mask_sign));+    __m128  justsign    = _mm_and_ps(msign, f);+    __m128  absf        = _mm_xor_ps(f, justsign);+    __m128i absf_int    = _mm_castps_si128(absf); // the cast is "free" (extra bypass latency, but no thruput hit)+    __m128i f16max      = STBIR__CONSTI(c_f16max);+    __m128  b_isnan     = _mm_cmpunord_ps(absf, absf); // is this a NaN?+    __m128i b_isregular = _mm_cmpgt_epi32(f16max, absf_int); // (sub)normalized or special?+    __m128i nanbit      = _mm_and_si128(_mm_castps_si128(b_isnan), STBIR__CONSTI(c_nanbit));+    __m128i inf_or_nan  = _mm_or_si128(nanbit, STBIR__CONSTI(c_infty_as_fp16)); // output for specials++    __m128i min_normal  = STBIR__CONSTI(c_min_normal);+    __m128i b_issub     = _mm_cmpgt_epi32(min_normal, absf_int);++    // "result is subnormal" path+    __m128  subnorm1    = _mm_add_ps(absf, _mm_castsi128_ps(STBIR__CONSTI(c_subnorm_magic))); // magic value to round output mantissa+    __m128i subnorm2    = _mm_sub_epi32(_mm_castps_si128(subnorm1), STBIR__CONSTI(c_subnorm_magic)); // subtract out bias++    // "result is normal" path+    __m128i mantoddbit  = _mm_slli_epi32(absf_int, 31 - 13); // shift bit 13 (mantissa LSB) to sign+    __m128i mantodd     = _mm_srai_epi32(mantoddbit, 31); // -1 if FP16 mantissa odd, else 0++    __m128i round1      = _mm_add_epi32(absf_int, STBIR__CONSTI(c_normal_bias));+    __m128i round2      = _mm_sub_epi32(round1, mantodd); // if mantissa LSB odd, bias towards rounding up (RTNE)+    __m128i normal      = _mm_srli_epi32(round2, 13); // rounded result++    // combine the two non-specials+    __m128i nonspecial  = _mm_or_si128(_mm_and_si128(subnorm2, b_issub), _mm_andnot_si128(b_issub, normal));++    // merge in specials as well+    __m128i joined      = _mm_or_si128(_mm_and_si128(nonspecial, b_isregular), _mm_andnot_si128(b_isregular, inf_or_nan));++    __m128i sign_shift  = _mm_srai_epi32(_mm_castps_si128(justsign), 16);+    __m128i final2, final= _mm_or_si128(joined, sign_shift);++    f           =  _mm_loadu_ps(input+4);+    justsign    = _mm_and_ps(msign, f);+    absf        = _mm_xor_ps(f, justsign);+    absf_int    = _mm_castps_si128(absf); // the cast is "free" (extra bypass latency, but no thruput hit)+    b_isnan     = _mm_cmpunord_ps(absf, absf); // is this a NaN?+    b_isregular = _mm_cmpgt_epi32(f16max, absf_int); // (sub)normalized or special?+    nanbit      = _mm_and_si128(_mm_castps_si128(b_isnan), c_nanbit);+    inf_or_nan  = _mm_or_si128(nanbit, STBIR__CONSTI(c_infty_as_fp16)); // output for specials++    b_issub     = _mm_cmpgt_epi32(min_normal, absf_int);++    // "result is subnormal" path+    subnorm1    = _mm_add_ps(absf, _mm_castsi128_ps(STBIR__CONSTI(c_subnorm_magic))); // magic value to round output mantissa+    subnorm2    = _mm_sub_epi32(_mm_castps_si128(subnorm1), STBIR__CONSTI(c_subnorm_magic)); // subtract out bias++    // "result is normal" path+    mantoddbit  = _mm_slli_epi32(absf_int, 31 - 13); // shift bit 13 (mantissa LSB) to sign+    mantodd     = _mm_srai_epi32(mantoddbit, 31); // -1 if FP16 mantissa odd, else 0++    round1      = _mm_add_epi32(absf_int, STBIR__CONSTI(c_normal_bias));+    round2      = _mm_sub_epi32(round1, mantodd); // if mantissa LSB odd, bias towards rounding up (RTNE)+    normal      = _mm_srli_epi32(round2, 13); // rounded result++    // combine the two non-specials+    nonspecial  = _mm_or_si128(_mm_and_si128(subnorm2, b_issub), _mm_andnot_si128(b_issub, normal));++    // merge in specials as well+    joined      = _mm_or_si128(_mm_and_si128(nonspecial, b_isregular), _mm_andnot_si128(b_isregular, inf_or_nan));++    sign_shift  = _mm_srai_epi32(_mm_castps_si128(justsign), 16);+    final2      = _mm_or_si128(joined, sign_shift);+    final       = _mm_packs_epi32(final, final2);+    stbir__simdi_store( output,final );+  }++#elif defined(STBIR_NEON) && defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__) // 64-bit ARM on MSVC (not clang)++  static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input)+  {+    float16x4_t in0 = vld1_f16(input + 0);+    float16x4_t in1 = vld1_f16(input + 4);+    vst1q_f32(output + 0, vcvt_f32_f16(in0));+    vst1q_f32(output + 4, vcvt_f32_f16(in1));+  }++  static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input)+  {+    float16x4_t out0 = vcvt_f16_f32(vld1q_f32(input + 0));+    float16x4_t out1 = vcvt_f16_f32(vld1q_f32(input + 4));+    vst1_f16(output+0, out0);+    vst1_f16(output+4, out1);+  }++  static stbir__inline float stbir__half_to_float( stbir__FP16 h )+  {+    return vgetq_lane_f32(vcvt_f32_f16(vld1_dup_f16(&h)), 0);+  }++  static stbir__inline stbir__FP16 stbir__float_to_half( float f )+  {+    return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0).n16_u16[0];+  }++#elif defined(STBIR_NEON) && ( defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) ) // 64-bit ARM++  static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input)+  {+    float16x8_t in = vld1q_f16(input);+    vst1q_f32(output + 0, vcvt_f32_f16(vget_low_f16(in)));+    vst1q_f32(output + 4, vcvt_f32_f16(vget_high_f16(in)));+  }++  static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input)+  {+    float16x4_t out0 = vcvt_f16_f32(vld1q_f32(input + 0));+    float16x4_t out1 = vcvt_f16_f32(vld1q_f32(input + 4));+    vst1q_f16(output, vcombine_f16(out0, out1));+  }++  static stbir__inline float stbir__half_to_float( stbir__FP16 h )+  {+    return vgetq_lane_f32(vcvt_f32_f16(vdup_n_f16(h)), 0);+  }++  static stbir__inline stbir__FP16 stbir__float_to_half( float f )+  {+    return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0);+  }++#elif defined(STBIR_WASM) || (defined(STBIR_NEON) && (defined(_MSC_VER) || defined(_M_ARM) || defined(__arm__))) // WASM or 32-bit ARM on MSVC/clang++  static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input)+  {+    for (int i=0; i<8; i++)+    {+      output[i] = stbir__half_to_float(input[i]);+    }+  }+  static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input)+  {+    for (int i=0; i<8; i++)+    {+      output[i] = stbir__float_to_half(input[i]);+    }+  }++#endif+++#ifdef STBIR_SIMD++#define stbir__simdf_0123to3333( out, reg ) (out) = stbir__simdf_swiz( reg, 3,3,3,3 )+#define stbir__simdf_0123to2222( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,2,2 )+#define stbir__simdf_0123to1111( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,1,1 )+#define stbir__simdf_0123to0000( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,0 )+#define stbir__simdf_0123to0003( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,3 )+#define stbir__simdf_0123to0001( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,1 )+#define stbir__simdf_0123to1122( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,2,2 )+#define stbir__simdf_0123to2333( out, reg ) (out) = stbir__simdf_swiz( reg, 2,3,3,3 )+#define stbir__simdf_0123to0023( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,3 )+#define stbir__simdf_0123to1230( out, reg ) (out) = stbir__simdf_swiz( reg, 1,2,3,0 )+#define stbir__simdf_0123to2103( out, reg ) (out) = stbir__simdf_swiz( reg, 2,1,0,3 )+#define stbir__simdf_0123to3210( out, reg ) (out) = stbir__simdf_swiz( reg, 3,2,1,0 )+#define stbir__simdf_0123to2301( out, reg ) (out) = stbir__simdf_swiz( reg, 2,3,0,1 )+#define stbir__simdf_0123to3012( out, reg ) (out) = stbir__simdf_swiz( reg, 3,0,1,2 )+#define stbir__simdf_0123to0011( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,1,1 )+#define stbir__simdf_0123to1100( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,0,0 )+#define stbir__simdf_0123to2233( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,3,3 )+#define stbir__simdf_0123to1133( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,3,3 )+#define stbir__simdf_0123to0022( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,2 )+#define stbir__simdf_0123to1032( out, reg ) (out) = stbir__simdf_swiz( reg, 1,0,3,2 )++typedef union stbir__simdi_u32+{+  stbir_uint32 m128i_u32[4];+  int m128i_i32[4];+  stbir__simdi m128i_i128;+} stbir__simdi_u32;++static const int STBIR_mask[9] = { 0,0,0,-1,-1,-1,0,0,0 };++static const STBIR__SIMDF_CONST(STBIR_max_uint8_as_float,           stbir__max_uint8_as_float);+static const STBIR__SIMDF_CONST(STBIR_max_uint16_as_float,          stbir__max_uint16_as_float);+static const STBIR__SIMDF_CONST(STBIR_max_uint8_as_float_inverted,  stbir__max_uint8_as_float_inverted);+static const STBIR__SIMDF_CONST(STBIR_max_uint16_as_float_inverted, stbir__max_uint16_as_float_inverted);++static const STBIR__SIMDF_CONST(STBIR_simd_point5,   0.5f);+static const STBIR__SIMDF_CONST(STBIR_ones,          1.0f);+static const STBIR__SIMDI_CONST(STBIR_almost_zero,   (127 - 13) << 23);+static const STBIR__SIMDI_CONST(STBIR_almost_one,    0x3f7fffff);+static const STBIR__SIMDI_CONST(STBIR_mastissa_mask, 0xff);+static const STBIR__SIMDI_CONST(STBIR_topscale,      0x02000000);++//   Basically, in simd mode, we unroll the proper amount, and we don't want+//   the non-simd remnant loops to be unroll because they only run a few times+//   Adding this switch saves about 5K on clang which is Captain Unroll the 3rd.+#define STBIR_SIMD_STREAMOUT_PTR( star )  STBIR_STREAMOUT_PTR( star )+#define STBIR_SIMD_NO_UNROLL(ptr) STBIR_NO_UNROLL(ptr)+#define STBIR_SIMD_NO_UNROLL_LOOP_START STBIR_NO_UNROLL_LOOP_START+#define STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR STBIR_NO_UNROLL_LOOP_START_INF_FOR++#ifdef STBIR_MEMCPY+#undef STBIR_MEMCPY+#endif+#define STBIR_MEMCPY stbir_simd_memcpy++// override normal use of memcpy with much simpler copy (faster and smaller with our sized copies)+static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes )+{+  char STBIR_SIMD_STREAMOUT_PTR (*) d = (char*) dest;+  char STBIR_SIMD_STREAMOUT_PTR( * ) d_end = ((char*) dest) + bytes;+  ptrdiff_t ofs_to_src = (char*)src - (char*)dest;++  // check overlaps+  STBIR_ASSERT( ( ( d >= ( (char*)src) + bytes ) ) || ( ( d + bytes ) <= (char*)src ) );++  if ( bytes < (16*stbir__simdfX_float_count) )+  {+    if ( bytes < 16 )+    {+      if ( bytes )+      {+        STBIR_SIMD_NO_UNROLL_LOOP_START+        do+        {+          STBIR_SIMD_NO_UNROLL(d);+          d[ 0 ] = d[ ofs_to_src ];+          ++d;+        } while ( d < d_end );+      }+    }+    else+    {+      stbir__simdf x;+      // do one unaligned to get us aligned for the stream out below+      stbir__simdf_load( x, ( d + ofs_to_src ) );+      stbir__simdf_store( d, x );+      d = (char*)( ( ( (size_t)d ) + 16 ) & ~15 );++      STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR+      for(;;)+      {+        STBIR_SIMD_NO_UNROLL(d);++        if ( d > ( d_end - 16 ) )+        {+          if ( d == d_end )+            return;+          d = d_end - 16;+        }++        stbir__simdf_load( x, ( d + ofs_to_src ) );+        stbir__simdf_store( d, x );+        d += 16;+      }+    }+  }+  else+  {+    stbir__simdfX x0,x1,x2,x3;++    // do one unaligned to get us aligned for the stream out below+    stbir__simdfX_load( x0, ( d + ofs_to_src ) +  0*stbir__simdfX_float_count );+    stbir__simdfX_load( x1, ( d + ofs_to_src ) +  4*stbir__simdfX_float_count );+    stbir__simdfX_load( x2, ( d + ofs_to_src ) +  8*stbir__simdfX_float_count );+    stbir__simdfX_load( x3, ( d + ofs_to_src ) + 12*stbir__simdfX_float_count );+    stbir__simdfX_store( d +  0*stbir__simdfX_float_count, x0 );+    stbir__simdfX_store( d +  4*stbir__simdfX_float_count, x1 );+    stbir__simdfX_store( d +  8*stbir__simdfX_float_count, x2 );+    stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 );+    d = (char*)( ( ( (size_t)d ) + (16*stbir__simdfX_float_count) ) & ~((16*stbir__simdfX_float_count)-1) );++    STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      STBIR_SIMD_NO_UNROLL(d);++      if ( d > ( d_end - (16*stbir__simdfX_float_count) ) )+      {+        if ( d == d_end )+          return;+        d = d_end - (16*stbir__simdfX_float_count);+      }++      stbir__simdfX_load( x0, ( d + ofs_to_src ) +  0*stbir__simdfX_float_count );+      stbir__simdfX_load( x1, ( d + ofs_to_src ) +  4*stbir__simdfX_float_count );+      stbir__simdfX_load( x2, ( d + ofs_to_src ) +  8*stbir__simdfX_float_count );+      stbir__simdfX_load( x3, ( d + ofs_to_src ) + 12*stbir__simdfX_float_count );+      stbir__simdfX_store( d +  0*stbir__simdfX_float_count, x0 );+      stbir__simdfX_store( d +  4*stbir__simdfX_float_count, x1 );+      stbir__simdfX_store( d +  8*stbir__simdfX_float_count, x2 );+      stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 );+      d += (16*stbir__simdfX_float_count);+    }+  }+}++// memcpy that is specically intentionally overlapping (src is smaller then dest, so can be+//   a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to+//   the diff between dest and src)+static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes )+{+  char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src;+  char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes;+  ptrdiff_t ofs_to_dest = (char*)dest - (char*)src;++  if ( ofs_to_dest >= 16 ) // is the overlap more than 16 away?+  {+    char STBIR_SIMD_STREAMOUT_PTR( * ) s_end16 = ((char*) src) + (bytes&~15);+    STBIR_SIMD_NO_UNROLL_LOOP_START+    do+    {+      stbir__simdf x;+      STBIR_SIMD_NO_UNROLL(sd);+      stbir__simdf_load( x, sd );+      stbir__simdf_store(  ( sd + ofs_to_dest ), x );+      sd += 16;+    } while ( sd < s_end16 );++    if ( sd == s_end )+      return;+  }++  do+  {+    STBIR_SIMD_NO_UNROLL(sd);+    *(int*)( sd + ofs_to_dest ) = *(int*) sd;+    sd += 4;+  } while ( sd < s_end );+}++#else // no SSE2++// when in scalar mode, we let unrolling happen, so this macro just does the __restrict+#define STBIR_SIMD_STREAMOUT_PTR( star ) STBIR_STREAMOUT_PTR( star )+#define STBIR_SIMD_NO_UNROLL(ptr)+#define STBIR_SIMD_NO_UNROLL_LOOP_START+#define STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR++#endif // SSE2+++#ifdef STBIR_PROFILE++#ifndef STBIR_PROFILE_FUNC++#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined(STBIR_SSE) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ )++#ifdef _MSC_VER++  STBIRDEF stbir_uint64 __rdtsc();+  #define STBIR_PROFILE_FUNC() __rdtsc()++#else // non msvc++  static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC()+  {+    stbir_uint32 lo, hi;+    asm volatile ("rdtsc" : "=a" (lo), "=d" (hi) );+    return ( ( (stbir_uint64) hi ) << 32 ) | ( (stbir_uint64) lo );+  }++#endif  // msvc++#elif defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__)++#if defined( _MSC_VER ) && !defined(__clang__)++  #define STBIR_PROFILE_FUNC() _ReadStatusReg(ARM64_CNTVCT)++#else++  static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC()+  {+    stbir_uint64 tsc;+    asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));+    return tsc;+  }++#endif++#else // x64, arm++#error Unknown platform for profiling.++#endif  // x64, arm++#endif // STBIR_PROFILE_FUNC++#define STBIR_ONLY_PROFILE_GET_SPLIT_INFO ,stbir__per_split_info * split_info+#define STBIR_ONLY_PROFILE_SET_SPLIT_INFO ,split_info++#define STBIR_ONLY_PROFILE_BUILD_GET_INFO ,stbir__info * profile_info+#define STBIR_ONLY_PROFILE_BUILD_SET_INFO ,profile_info++// super light-weight micro profiler+#define STBIR_PROFILE_START_ll( info, wh ) { stbir_uint64 wh##thiszonetime = STBIR_PROFILE_FUNC(); stbir_uint64 * wh##save_parent_excluded_ptr = info->current_zone_excluded_ptr; stbir_uint64 wh##current_zone_excluded = 0; info->current_zone_excluded_ptr = &wh##current_zone_excluded;+#define STBIR_PROFILE_END_ll( info, wh ) wh##thiszonetime = STBIR_PROFILE_FUNC() - wh##thiszonetime; info->profile.named.wh += wh##thiszonetime - wh##current_zone_excluded; *wh##save_parent_excluded_ptr += wh##thiszonetime; info->current_zone_excluded_ptr = wh##save_parent_excluded_ptr; }+#define STBIR_PROFILE_FIRST_START_ll( info, wh ) { int i; info->current_zone_excluded_ptr = &info->profile.named.total; for(i=0;i<STBIR__ARRAY_SIZE(info->profile.array);i++) info->profile.array[i]=0; } STBIR_PROFILE_START_ll( info, wh );+#define STBIR_PROFILE_CLEAR_EXTRAS_ll( info, num ) { int extra; for(extra=1;extra<(num);extra++) { int i; for(i=0;i<STBIR__ARRAY_SIZE((info)->profile.array);i++) (info)[extra].profile.array[i]=0; } }++// for thread data+#define STBIR_PROFILE_START( wh ) STBIR_PROFILE_START_ll( split_info, wh )+#define STBIR_PROFILE_END( wh ) STBIR_PROFILE_END_ll( split_info, wh )+#define STBIR_PROFILE_FIRST_START( wh ) STBIR_PROFILE_FIRST_START_ll( split_info, wh )+#define STBIR_PROFILE_CLEAR_EXTRAS() STBIR_PROFILE_CLEAR_EXTRAS_ll( split_info, split_count )++// for build data+#define STBIR_PROFILE_BUILD_START( wh ) STBIR_PROFILE_START_ll( profile_info, wh )+#define STBIR_PROFILE_BUILD_END( wh ) STBIR_PROFILE_END_ll( profile_info, wh )+#define STBIR_PROFILE_BUILD_FIRST_START( wh ) STBIR_PROFILE_FIRST_START_ll( profile_info, wh )+#define STBIR_PROFILE_BUILD_CLEAR( info ) { int i; for(i=0;i<STBIR__ARRAY_SIZE(info->profile.array);i++) info->profile.array[i]=0; }++#else  // no profile++#define STBIR_ONLY_PROFILE_GET_SPLIT_INFO+#define STBIR_ONLY_PROFILE_SET_SPLIT_INFO++#define STBIR_ONLY_PROFILE_BUILD_GET_INFO+#define STBIR_ONLY_PROFILE_BUILD_SET_INFO++#define STBIR_PROFILE_START( wh )+#define STBIR_PROFILE_END( wh )+#define STBIR_PROFILE_FIRST_START( wh )+#define STBIR_PROFILE_CLEAR_EXTRAS( )++#define STBIR_PROFILE_BUILD_START( wh )+#define STBIR_PROFILE_BUILD_END( wh )+#define STBIR_PROFILE_BUILD_FIRST_START( wh )+#define STBIR_PROFILE_BUILD_CLEAR( info )++#endif  // stbir_profile++#ifndef STBIR_CEILF+#include <math.h>+#if _MSC_VER <= 1200 // support VC6 for Sean+#define STBIR_CEILF(x) ((float)ceil((float)(x)))+#define STBIR_FLOORF(x) ((float)floor((float)(x)))+#else+#define STBIR_CEILF(x) ceilf(x)+#define STBIR_FLOORF(x) floorf(x)+#endif+#endif++#ifndef STBIR_MEMCPY+// For memcpy+#include <string.h>+#define STBIR_MEMCPY( dest, src, len ) memcpy( dest, src, len )+#endif++#ifndef STBIR_SIMD++// memcpy that is specifically intentionally overlapping (src is smaller then dest, so can be+//   a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to+//   the diff between dest and src)+static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes )+{+  char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src;+  char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes;+  ptrdiff_t ofs_to_dest = (char*)dest - (char*)src;++  if ( ofs_to_dest >= 8 ) // is the overlap more than 8 away?+  {+    char STBIR_SIMD_STREAMOUT_PTR( * ) s_end8 = ((char*) src) + (bytes&~7);+    STBIR_NO_UNROLL_LOOP_START+    do+    {+      STBIR_NO_UNROLL(sd);+      *(stbir_uint64*)( sd + ofs_to_dest ) = *(stbir_uint64*) sd;+      sd += 8;+    } while ( sd < s_end8 );++    if ( sd == s_end )+      return;+  }++  STBIR_NO_UNROLL_LOOP_START+  do+  {+    STBIR_NO_UNROLL(sd);+    *(int*)( sd + ofs_to_dest ) = *(int*) sd;+    sd += 4;+  } while ( sd < s_end );+}++#endif++static float stbir__filter_trapezoid(float x, float scale, void * user_data)+{+  float halfscale = scale / 2;+  float t = 0.5f + halfscale;+  STBIR_ASSERT(scale <= 1);+  STBIR__UNUSED(user_data);++  if ( x < 0.0f ) x = -x;++  if (x >= t)+    return 0.0f;+  else+  {+    float r = 0.5f - halfscale;+    if (x <= r)+      return 1.0f;+    else+      return (t - x) / scale;+  }+}++static float stbir__support_trapezoid(float scale, void * user_data)+{+  STBIR__UNUSED(user_data);+  return 0.5f + scale / 2.0f;+}++static float stbir__filter_triangle(float x, float s, void * user_data)+{+  STBIR__UNUSED(s);+  STBIR__UNUSED(user_data);++  if ( x < 0.0f ) x = -x;++  if (x <= 1.0f)+    return 1.0f - x;+  else+    return 0.0f;+}++static float stbir__filter_point(float x, float s, void * user_data)+{+  STBIR__UNUSED(x);+  STBIR__UNUSED(s);+  STBIR__UNUSED(user_data);++  return 1.0f;+}++static float stbir__filter_cubic(float x, float s, void * user_data)+{+  STBIR__UNUSED(s);+  STBIR__UNUSED(user_data);++  if ( x < 0.0f ) x = -x;++  if (x < 1.0f)+    return (4.0f + x*x*(3.0f*x - 6.0f))/6.0f;+  else if (x < 2.0f)+    return (8.0f + x*(-12.0f + x*(6.0f - x)))/6.0f;++  return (0.0f);+}++static float stbir__filter_catmullrom(float x, float s, void * user_data)+{+  STBIR__UNUSED(s);+  STBIR__UNUSED(user_data);++  if ( x < 0.0f ) x = -x;++  if (x < 1.0f)+    return 1.0f - x*x*(2.5f - 1.5f*x);+  else if (x < 2.0f)+    return 2.0f - x*(4.0f + x*(0.5f*x - 2.5f));++  return (0.0f);+}++static float stbir__filter_mitchell(float x, float s, void * user_data)+{+  STBIR__UNUSED(s);+  STBIR__UNUSED(user_data);++  if ( x < 0.0f ) x = -x;++  if (x < 1.0f)+    return (16.0f + x*x*(21.0f * x - 36.0f))/18.0f;+  else if (x < 2.0f)+    return (32.0f + x*(-60.0f + x*(36.0f - 7.0f*x)))/18.0f;++  return (0.0f);+}++static float stbir__support_zeropoint5(float s, void * user_data)+{+  STBIR__UNUSED(s);+  STBIR__UNUSED(user_data);+  return 0.5f;+}++static float stbir__support_one(float s, void * user_data)+{+  STBIR__UNUSED(s);+  STBIR__UNUSED(user_data);+  return 1;+}++static float stbir__support_two(float s, void * user_data)+{+  STBIR__UNUSED(s);+  STBIR__UNUSED(user_data);+  return 2;+}++// This is the maximum number of input samples that can affect an output sample+// with the given filter from the output pixel's perspective+static int stbir__get_filter_pixel_width(stbir__support_callback * support, float scale, void * user_data)+{+  STBIR_ASSERT(support != 0);++  if ( scale >= ( 1.0f-stbir__small_float ) ) // upscale+    return (int)STBIR_CEILF(support(1.0f/scale,user_data) * 2.0f);+  else+    return (int)STBIR_CEILF(support(scale,user_data) * 2.0f / scale);+}++// this is how many coefficents per run of the filter (which is different+//   from the filter_pixel_width depending on if we are scattering or gathering)+static int stbir__get_coefficient_width(stbir__sampler * samp, int is_gather, void * user_data)+{+  float scale = samp->scale_info.scale;+  stbir__support_callback * support = samp->filter_support;++  switch( is_gather )+  {+    case 1:+      return (int)STBIR_CEILF(support(1.0f / scale, user_data) * 2.0f);+    case 2:+      return (int)STBIR_CEILF(support(scale, user_data) * 2.0f / scale);+    case 0:+      return (int)STBIR_CEILF(support(scale, user_data) * 2.0f);+    default:+      STBIR_ASSERT( (is_gather >= 0 ) && (is_gather <= 2 ) );+      return 0;+  }+}++static int stbir__get_contributors(stbir__sampler * samp, int is_gather)+{+  if (is_gather)+      return samp->scale_info.output_sub_size;+  else+      return (samp->scale_info.input_full_size + samp->filter_pixel_margin * 2);+}++static int stbir__edge_zero_full( int n, int max )+{+  STBIR__UNUSED(n);+  STBIR__UNUSED(max);+  return 0; // NOTREACHED+}++static int stbir__edge_clamp_full( int n, int max )+{+  if (n < 0)+    return 0;++  if (n >= max)+    return max - 1;++  return n; // NOTREACHED+}++static int stbir__edge_reflect_full( int n, int max )+{+  if (n < 0)+  {+    if (n > -max)+      return -n;+    else+      return max - 1;+  }++  if (n >= max)+  {+    int max2 = max * 2;+    if (n >= max2)+      return 0;+    else+      return max2 - n - 1;+  }++  return n; // NOTREACHED+}++static int stbir__edge_wrap_full( int n, int max )+{+  if (n >= 0)+    return (n % max);+  else+  {+    int m = (-n) % max;++    if (m != 0)+      m = max - m;++    return (m);+  }+}++typedef int stbir__edge_wrap_func( int n, int max );+static stbir__edge_wrap_func * stbir__edge_wrap_slow[] =+{+  stbir__edge_clamp_full,    // STBIR_EDGE_CLAMP+  stbir__edge_reflect_full,  // STBIR_EDGE_REFLECT+  stbir__edge_wrap_full,     // STBIR_EDGE_WRAP+  stbir__edge_zero_full,     // STBIR_EDGE_ZERO+};++stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max)+{+  // avoid per-pixel switch+  if (n >= 0 && n < max)+      return n;+  return stbir__edge_wrap_slow[edge]( n, max );+}++#define STBIR__MERGE_RUNS_PIXEL_THRESHOLD 16++// get information on the extents of a sampler+static void stbir__get_extents( stbir__sampler * samp, stbir__extents * scanline_extents )+{+  int j, stop;+  int left_margin, right_margin;+  int min_n = 0x7fffffff, max_n = -0x7fffffff;+  int min_left = 0x7fffffff, max_left = -0x7fffffff;+  int min_right = 0x7fffffff, max_right = -0x7fffffff;+  stbir_edge edge = samp->edge;+  stbir__contributors* contributors = samp->contributors;+  int output_sub_size = samp->scale_info.output_sub_size;+  int input_full_size = samp->scale_info.input_full_size;+  int filter_pixel_margin = samp->filter_pixel_margin;++  STBIR_ASSERT( samp->is_gather );++  stop = output_sub_size;+  for (j = 0; j < stop; j++ )+  {+    STBIR_ASSERT( contributors[j].n1 >= contributors[j].n0 );+    if ( contributors[j].n0 < min_n )+    {+      min_n = contributors[j].n0;+      stop = j + filter_pixel_margin;  // if we find a new min, only scan another filter width+      if ( stop > output_sub_size ) stop = output_sub_size;+    }+  }++  stop = 0;+  for (j = output_sub_size - 1; j >= stop; j-- )+  {+    STBIR_ASSERT( contributors[j].n1 >= contributors[j].n0 );+    if ( contributors[j].n1 > max_n )+    {+      max_n = contributors[j].n1;+      stop = j - filter_pixel_margin;  // if we find a new max, only scan another filter width+      if (stop<0) stop = 0;+    }+  }++  STBIR_ASSERT( scanline_extents->conservative.n0 <= min_n );+  STBIR_ASSERT( scanline_extents->conservative.n1 >= max_n );++  // now calculate how much into the margins we really read+  left_margin = 0;+  if ( min_n < 0 )+  {+    left_margin = -min_n;+    min_n = 0;+  }++  right_margin = 0;+  if ( max_n >= input_full_size )+  {+    right_margin = max_n - input_full_size + 1;+    max_n = input_full_size - 1;+  }++  // index 1 is margin pixel extents (how many pixels we hang over the edge)+  scanline_extents->edge_sizes[0] = left_margin;+  scanline_extents->edge_sizes[1] = right_margin;++  // index 2 is pixels read from the input+  scanline_extents->spans[0].n0 = min_n;+  scanline_extents->spans[0].n1 = max_n;+  scanline_extents->spans[0].pixel_offset_for_input = min_n;++  // default to no other input range+  scanline_extents->spans[1].n0 = 0;+  scanline_extents->spans[1].n1 = -1;+  scanline_extents->spans[1].pixel_offset_for_input = 0;++  // don't have to do edge calc for zero clamp+  if ( edge == STBIR_EDGE_ZERO )+    return;++  // convert margin pixels to the pixels within the input (min and max)+  for( j = -left_margin ; j < 0 ; j++ )+  {+      int p = stbir__edge_wrap( edge, j, input_full_size );+      if ( p < min_left )+        min_left = p;+      if ( p > max_left )+        max_left = p;+  }++  for( j = input_full_size ; j < (input_full_size + right_margin) ; j++ )+  {+      int p = stbir__edge_wrap( edge, j, input_full_size );+      if ( p < min_right )+        min_right = p;+      if ( p > max_right )+        max_right = p;+  }++  // merge the left margin pixel region if it connects within 4 pixels of main pixel region+  if ( min_left != 0x7fffffff )+  {+    if ( ( ( min_left <= min_n ) && ( ( max_left  + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= min_n ) ) ||+         ( ( min_n <= min_left ) && ( ( max_n  + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= max_left ) ) )+    {+      scanline_extents->spans[0].n0 = min_n = stbir__min( min_n, min_left );+      scanline_extents->spans[0].n1 = max_n = stbir__max( max_n, max_left );+      scanline_extents->spans[0].pixel_offset_for_input = min_n;+      left_margin = 0;+    }+  }++  // merge the right margin pixel region if it connects within 4 pixels of main pixel region+  if ( min_right != 0x7fffffff )+  {+    if ( ( ( min_right <= min_n ) && ( ( max_right  + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= min_n ) ) ||+         ( ( min_n <= min_right ) && ( ( max_n  + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= max_right ) ) )+    {+      scanline_extents->spans[0].n0 = min_n = stbir__min( min_n, min_right );+      scanline_extents->spans[0].n1 = max_n = stbir__max( max_n, max_right );+      scanline_extents->spans[0].pixel_offset_for_input = min_n;+      right_margin = 0;+    }+  }++  STBIR_ASSERT( scanline_extents->conservative.n0 <= min_n );+  STBIR_ASSERT( scanline_extents->conservative.n1 >= max_n );++  // you get two ranges when you have the WRAP edge mode and you are doing just the a piece of the resize+  //   so you need to get a second run of pixels from the opposite side of the scanline (which you+  //   wouldn't need except for WRAP)+++  // if we can't merge the min_left range, add it as a second range+  if ( ( left_margin ) && ( min_left != 0x7fffffff ) )+  {+    stbir__span * newspan = scanline_extents->spans + 1;+    STBIR_ASSERT( right_margin == 0 );+    if ( min_left < scanline_extents->spans[0].n0 )+    {+      scanline_extents->spans[1].pixel_offset_for_input = scanline_extents->spans[0].n0;+      scanline_extents->spans[1].n0 = scanline_extents->spans[0].n0;+      scanline_extents->spans[1].n1 = scanline_extents->spans[0].n1;+      --newspan;+    }+    newspan->pixel_offset_for_input = min_left;+    newspan->n0 = -left_margin;+    newspan->n1 = ( max_left - min_left ) - left_margin;+    scanline_extents->edge_sizes[0] = 0;  // don't need to copy the left margin, since we are directly decoding into the margin+    return;+  }++  // if we can't merge the min_left range, add it as a second range+  if ( ( right_margin ) && ( min_right != 0x7fffffff ) )+  {+    stbir__span * newspan = scanline_extents->spans + 1;+    if ( min_right < scanline_extents->spans[0].n0 )+    {+      scanline_extents->spans[1].pixel_offset_for_input = scanline_extents->spans[0].n0;+      scanline_extents->spans[1].n0 = scanline_extents->spans[0].n0;+      scanline_extents->spans[1].n1 = scanline_extents->spans[0].n1;+      --newspan;+    }+    newspan->pixel_offset_for_input = min_right;+    newspan->n0 = scanline_extents->spans[1].n1 + 1;+    newspan->n1 = scanline_extents->spans[1].n1 + 1 + ( max_right - min_right );+    scanline_extents->edge_sizes[1] = 0;  // don't need to copy the right margin, since we are directly decoding into the margin+    return;+  }+}++static void stbir__calculate_in_pixel_range( int * first_pixel, int * last_pixel, float out_pixel_center, float out_filter_radius, float inv_scale, float out_shift, int input_size, stbir_edge edge )+{+  int first, last;+  float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius;+  float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius;++  float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) * inv_scale;+  float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) * inv_scale;++  first = (int)(STBIR_FLOORF(in_pixel_influence_lowerbound + 0.5f));+  last = (int)(STBIR_FLOORF(in_pixel_influence_upperbound - 0.5f));++  if ( edge == STBIR_EDGE_WRAP )+  {+    if ( first < -input_size )+      first = -input_size;+    if ( last >= (input_size*2))+      last = (input_size*2) - 1;+  }++  *first_pixel = first;+  *last_pixel = last;+}++static void stbir__calculate_coefficients_for_gather_upsample( float out_filter_radius, stbir__kernel_callback * kernel, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float* coefficient_group, int coefficient_width, stbir_edge edge, void * user_data )+{+  int n, end;+  float inv_scale = scale_info->inv_scale;+  float out_shift = scale_info->pixel_shift;+  int input_size  = scale_info->input_full_size;+  int numerator = scale_info->scale_numerator;+  int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < num_contributors ) );++  // Looping through out pixels+  end = num_contributors; if ( polyphase ) end = numerator;+  for (n = 0; n < end; n++)+  {+    int i;+    int last_non_zero;+    float out_pixel_center = (float)n + 0.5f;+    float in_center_of_out = (out_pixel_center + out_shift) * inv_scale;++    int in_first_pixel, in_last_pixel;++    stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, out_pixel_center, out_filter_radius, inv_scale, out_shift, input_size, edge );++    last_non_zero = -1;+    for (i = 0; i <= in_last_pixel - in_first_pixel; i++)+    {+      float in_pixel_center = (float)(i + in_first_pixel) + 0.5f;+      float coeff = kernel(in_center_of_out - in_pixel_center, inv_scale, user_data);++      // kill denormals+      if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) )+      {+        if ( i == 0 )  // if we're at the front, just eat zero contributors+        {+          STBIR_ASSERT ( ( in_last_pixel - in_first_pixel ) != 0 ); // there should be at least one contrib+          ++in_first_pixel;+          i--;+          continue;+        }+        coeff = 0;  // make sure is fully zero (should keep denormals away)+      }+      else+        last_non_zero = i;++      coefficient_group[i] = coeff;+    }++    in_last_pixel = last_non_zero+in_first_pixel; // kills trailing zeros+    contributors->n0 = in_first_pixel;+    contributors->n1 = in_last_pixel;++    STBIR_ASSERT(contributors->n1 >= contributors->n0);++    ++contributors;+    coefficient_group += coefficient_width;+  }+}++static void stbir__insert_coeff( stbir__contributors * contribs, float * coeffs, int new_pixel, float new_coeff )+{+  if ( new_pixel <= contribs->n1 )  // before the end+  {+    if ( new_pixel < contribs->n0 ) // before the front?+    {+      int j, o = contribs->n0 - new_pixel;+      for ( j = contribs->n1 - contribs->n0 ; j <= 0 ; j-- )+        coeffs[ j + o ] = coeffs[ j ];+      for ( j = 1 ; j < o ; j-- )+        coeffs[ j ] = coeffs[ 0 ];+      coeffs[ 0 ] = new_coeff;+      contribs->n0 = new_pixel;+    }+    else+    {+      coeffs[ new_pixel - contribs->n0 ] += new_coeff;+    }+  }+  else+  {+    int j, e = new_pixel - contribs->n0;+    for( j = ( contribs->n1 - contribs->n0 ) + 1 ; j < e ; j++ ) // clear in-betweens coeffs if there are any+      coeffs[j] = 0;++    coeffs[ e ] = new_coeff;+    contribs->n1 = new_pixel;+  }+}++static void stbir__calculate_out_pixel_range( int * first_pixel, int * last_pixel, float in_pixel_center, float in_pixels_radius, float scale, float out_shift, int out_size )+{+  float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius;+  float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius;+  float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale - out_shift;+  float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale - out_shift;+  int out_first_pixel = (int)(STBIR_FLOORF(out_pixel_influence_lowerbound + 0.5f));+  int out_last_pixel = (int)(STBIR_FLOORF(out_pixel_influence_upperbound - 0.5f));++  if ( out_first_pixel < 0 )+    out_first_pixel = 0;+  if ( out_last_pixel >= out_size )+    out_last_pixel = out_size - 1;+  *first_pixel = out_first_pixel;+  *last_pixel = out_last_pixel;+}++static void stbir__calculate_coefficients_for_gather_downsample( int start, int end, float in_pixels_radius, stbir__kernel_callback * kernel, stbir__scale_info * scale_info, int coefficient_width, int num_contributors, stbir__contributors * contributors, float * coefficient_group, void * user_data )+{+  int in_pixel;+  int i;+  int first_out_inited = -1;+  float scale = scale_info->scale;+  float out_shift = scale_info->pixel_shift;+  int out_size = scale_info->output_sub_size;+  int numerator = scale_info->scale_numerator;+  int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < out_size ) );++  STBIR__UNUSED(num_contributors);++  // Loop through the input pixels+  for (in_pixel = start; in_pixel < end; in_pixel++)+  {+    float in_pixel_center = (float)in_pixel + 0.5f;+    float out_center_of_in = in_pixel_center * scale - out_shift;+    int out_first_pixel, out_last_pixel;++    stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, in_pixel_center, in_pixels_radius, scale, out_shift, out_size );++    if ( out_first_pixel > out_last_pixel )+      continue;++    // clamp or exit if we are using polyphase filtering, and the limit is up+    if ( polyphase )+    {+      // when polyphase, you only have to do coeffs up to the numerator count+      if ( out_first_pixel == numerator )+        break;++      // don't do any extra work, clamp last pixel at numerator too+      if ( out_last_pixel >= numerator )+        out_last_pixel = numerator - 1;+    }++    for (i = 0; i <= out_last_pixel - out_first_pixel; i++)+    {+      float out_pixel_center = (float)(i + out_first_pixel) + 0.5f;+      float x = out_pixel_center - out_center_of_in;+      float coeff = kernel(x, scale, user_data) * scale;++      // kill the coeff if it's too small (avoid denormals)+      if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) )+        coeff = 0.0f;++      {+        int out = i + out_first_pixel;+        float * coeffs = coefficient_group + out * coefficient_width;+        stbir__contributors * contribs = contributors + out;++        // is this the first time this output pixel has been seen?  Init it.+        if ( out > first_out_inited )+        {+          STBIR_ASSERT( out == ( first_out_inited + 1 ) ); // ensure we have only advanced one at time+          first_out_inited = out;+          contribs->n0 = in_pixel;+          contribs->n1 = in_pixel;+          coeffs[0]  = coeff;+        }+        else+        {+          // insert on end (always in order)+          if ( coeffs[0] == 0.0f )  // if the first coefficent is zero, then zap it for this coeffs+          {+            STBIR_ASSERT( ( in_pixel - contribs->n0 ) == 1 ); // ensure that when we zap, we're at the 2nd pos+            contribs->n0 = in_pixel;+          }+          contribs->n1 = in_pixel;+          STBIR_ASSERT( ( in_pixel - contribs->n0 ) < coefficient_width );+          coeffs[in_pixel - contribs->n0]  = coeff;+        }+      }+    }+  }+}++#ifdef STBIR_RENORMALIZE_IN_FLOAT+#define STBIR_RENORM_TYPE float+#else+#define STBIR_RENORM_TYPE double+#endif++static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter_extent_info* filter_info, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float * coefficient_group, int coefficient_width )+{+  int input_size = scale_info->input_full_size;+  int input_last_n1 = input_size - 1;+  int n, end;+  int lowest = 0x7fffffff;+  int highest = -0x7fffffff;+  int widest = -1;+  int numerator = scale_info->scale_numerator;+  int denominator = scale_info->scale_denominator;+  int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < num_contributors ) );+  float * coeffs;+  stbir__contributors * contribs;++  // weight all the coeffs for each sample+  coeffs = coefficient_group;+  contribs = contributors;+  end = num_contributors; if ( polyphase ) end = numerator;+  for (n = 0; n < end; n++)+  {+    int i;+    STBIR_RENORM_TYPE filter_scale, total_filter = 0;+    int e;++    // add all contribs+    e = contribs->n1 - contribs->n0;+    for( i = 0 ; i <= e ; i++ )+    {+      total_filter += (STBIR_RENORM_TYPE) coeffs[i];+      STBIR_ASSERT( ( coeffs[i] >= -2.0f ) && ( coeffs[i] <= 2.0f )  ); // check for wonky weights+    }++    // rescale+    if ( ( total_filter < stbir__small_float ) && ( total_filter > -stbir__small_float ) )+    {+      // all coeffs are extremely small, just zero it+      contribs->n1 = contribs->n0;+      coeffs[0] = 0.0f;+    }+    else+    {+      // if the total isn't 1.0, rescale everything+      if ( ( total_filter < (1.0f-stbir__small_float) ) || ( total_filter > (1.0f+stbir__small_float) ) )+      {+        filter_scale = ((STBIR_RENORM_TYPE)1.0) / total_filter;++        // scale them all+        for (i = 0; i <= e; i++)+          coeffs[i] = (float) ( coeffs[i] * filter_scale );+      }+    }+    ++contribs;+    coeffs += coefficient_width;+  }++  // if we have a rational for the scale, we can exploit the polyphaseness to not calculate+  //   most of the coefficients, so we copy them here+  if ( polyphase )+  {+    stbir__contributors * prev_contribs = contributors;+    stbir__contributors * cur_contribs = contributors + numerator;++    for( n = numerator ; n < num_contributors ; n++ )+    {+      cur_contribs->n0 = prev_contribs->n0 + denominator;+      cur_contribs->n1 = prev_contribs->n1 + denominator;+      ++cur_contribs;+      ++prev_contribs;+    }+    stbir_overlapping_memcpy( coefficient_group + numerator * coefficient_width, coefficient_group, ( num_contributors - numerator ) * coefficient_width * sizeof( coeffs[ 0 ] ) );+  }++  coeffs = coefficient_group;+  contribs = contributors;+  for (n = 0; n < num_contributors; n++)+  {+    int i;++    // in zero edge mode, just remove out of bounds contribs completely (since their weights are accounted for now)+    if ( edge == STBIR_EDGE_ZERO )+    {+      // shrink the right side if necessary+      if ( contribs->n1 > input_last_n1 )+        contribs->n1 = input_last_n1;++      // shrink the left side+      if ( contribs->n0 < 0 )+      {+        int j, left, skips = 0;++        skips = -contribs->n0;+        contribs->n0 = 0;++        // now move down the weights+        left = contribs->n1 - contribs->n0 + 1;+        if ( left > 0 )+        {+          for( j = 0 ; j < left ; j++ )+            coeffs[ j ] = coeffs[ j + skips ];+        }+      }+    }+    else if ( ( edge == STBIR_EDGE_CLAMP ) || ( edge == STBIR_EDGE_REFLECT ) )+    {+      // for clamp and reflect, calculate the true inbounds position (based on edge type) and just add that to the existing weight++      // right hand side first+      if ( contribs->n1 > input_last_n1 )+      {+        int start = contribs->n0;+        int endi = contribs->n1;+        contribs->n1 = input_last_n1;+        for( i = input_size; i <= endi; i++ )+          stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), coeffs[i-start] );+      }++      // now check left hand edge+      if ( contribs->n0 < 0 )+      {+        int save_n0;+        float save_n0_coeff;+        float * c = coeffs - ( contribs->n0 + 1 );++        // reinsert the coeffs with it reflected or clamped (insert accumulates, if the coeffs exist)+        for( i = -1 ; i > contribs->n0 ; i-- )+          stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), *c-- );+        save_n0 = contribs->n0;+        save_n0_coeff = c[0]; // save it, since we didn't do the final one (i==n0), because there might be too many coeffs to hold (before we resize)!++        // now slide all the coeffs down (since we have accumulated them in the positive contribs) and reset the first contrib+        contribs->n0 = 0;+        for(i = 0 ; i <= contribs->n1 ; i++ )+          coeffs[i] = coeffs[i-save_n0];++        // now that we have shrunk down the contribs, we insert the first one safely+        stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( save_n0, input_size ), save_n0_coeff );+      }+    }++    if ( contribs->n0 <= contribs->n1 )+    {+      int diff = contribs->n1 - contribs->n0 + 1;+      while ( diff && ( coeffs[ diff-1 ] == 0.0f ) )+        --diff;+      contribs->n1 = contribs->n0 + diff - 1;++      if ( contribs->n0 <= contribs->n1 )+      {+        if ( contribs->n0 < lowest )+          lowest = contribs->n0;+        if ( contribs->n1 > highest )+          highest = contribs->n1;+        if ( diff > widest )+          widest = diff;+      }++      // re-zero out unused coefficients (if any)+      for( i = diff ; i < coefficient_width ; i++ )+        coeffs[i] = 0.0f;+    }++    ++contribs;+    coeffs += coefficient_width;+  }+  filter_info->lowest = lowest;+  filter_info->highest = highest;+  filter_info->widest = widest;+}++#undef STBIR_RENORM_TYPE ++static int stbir__pack_coefficients( int num_contributors, stbir__contributors* contributors, float * coefficents, int coefficient_width, int widest, int row0, int row1 ) +{+  #define STBIR_MOVE_1( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint32*)(dest))[0] = ((stbir_uint32*)(src))[0]; }+  #define STBIR_MOVE_2( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; }+  #ifdef STBIR_SIMD+  #define STBIR_MOVE_4( dest, src ) { stbir__simdf t; STBIR_NO_UNROLL(dest); stbir__simdf_load( t, src ); stbir__simdf_store( dest, t ); }+  #else+  #define STBIR_MOVE_4( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; ((stbir_uint64*)(dest))[1] = ((stbir_uint64*)(src))[1]; }+  #endif++  int row_end = row1 + 1;+  STBIR__UNUSED( row0 ); // only used in an assert++  if ( coefficient_width != widest )+  {+    float * pc = coefficents;+    float * coeffs = coefficents;+    float * pc_end = coefficents + num_contributors * widest;+    switch( widest )+    {+      case 1:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_1( pc, coeffs );+          ++pc;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 2:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_2( pc, coeffs );+          pc += 2;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 3:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_2( pc, coeffs );+          STBIR_MOVE_1( pc+2, coeffs+2 );+          pc += 3;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 4:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_4( pc, coeffs );+          pc += 4;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 5:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_4( pc, coeffs );+          STBIR_MOVE_1( pc+4, coeffs+4 );+          pc += 5;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 6:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_4( pc, coeffs );+          STBIR_MOVE_2( pc+4, coeffs+4 );+          pc += 6;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 7:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_4( pc, coeffs );+          STBIR_MOVE_2( pc+4, coeffs+4 );+          STBIR_MOVE_1( pc+6, coeffs+6 );+          pc += 7;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 8:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_4( pc, coeffs );+          STBIR_MOVE_4( pc+4, coeffs+4 );+          pc += 8;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 9:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_4( pc, coeffs );+          STBIR_MOVE_4( pc+4, coeffs+4 );+          STBIR_MOVE_1( pc+8, coeffs+8 );+          pc += 9;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 10:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_4( pc, coeffs );+          STBIR_MOVE_4( pc+4, coeffs+4 );+          STBIR_MOVE_2( pc+8, coeffs+8 );+          pc += 10;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 11:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_4( pc, coeffs );+          STBIR_MOVE_4( pc+4, coeffs+4 );+          STBIR_MOVE_2( pc+8, coeffs+8 );+          STBIR_MOVE_1( pc+10, coeffs+10 );+          pc += 11;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      case 12:+        STBIR_NO_UNROLL_LOOP_START+        do {+          STBIR_MOVE_4( pc, coeffs );+          STBIR_MOVE_4( pc+4, coeffs+4 );+          STBIR_MOVE_4( pc+8, coeffs+8 );+          pc += 12;+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+      default:+        STBIR_NO_UNROLL_LOOP_START+        do {+          float * copy_end = pc + widest - 4;+          float * c = coeffs;+          do {+            STBIR_NO_UNROLL( pc );+            STBIR_MOVE_4( pc, c );+            pc += 4;+            c += 4;+          } while ( pc <= copy_end );+          copy_end += 4;+          STBIR_NO_UNROLL_LOOP_START+          while ( pc < copy_end )+          {+            STBIR_MOVE_1( pc, c );+            ++pc; ++c;+          }+          coeffs += coefficient_width;+        } while ( pc < pc_end );+        break;+    }+  }++  // some horizontal routines read one float off the end (which is then masked off), so put in a sentinal so we don't read an snan or denormal+  coefficents[ widest * num_contributors ] = 8888.0f;++  // the minimum we might read for unrolled filters widths is 12. So, we need to+  //   make sure we never read outside the decode buffer, by possibly moving+  //   the sample area back into the scanline, and putting zeros weights first.+  // we start on the right edge and check until we're well past the possible+  //   clip area (2*widest).+  {+    stbir__contributors * contribs = contributors + num_contributors - 1;+    float * coeffs = coefficents + widest * ( num_contributors - 1 );++    // go until no chance of clipping (this is usually less than 8 lops)+    while ( ( contribs >= contributors ) && ( ( contribs->n0 + widest*2 ) >= row_end ) )+    {+      // might we clip??+      if ( ( contribs->n0 + widest ) > row_end )+      {+        int stop_range = widest;++        // if range is larger than 12, it will be handled by generic loops that can terminate on the exact length+        //   of this contrib n1, instead of a fixed widest amount - so calculate this+        if ( widest > 12 )+        {+          int mod;++          // how far will be read in the n_coeff loop (which depends on the widest count mod4);+          mod = widest & 3;+          stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod;++          // the n_coeff loops do a minimum amount of coeffs, so factor that in!+          if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod;+        }++        // now see if we still clip with the refined range+        if ( ( contribs->n0 + stop_range ) > row_end )+        {+          int new_n0 = row_end - stop_range;+          int num = contribs->n1 - contribs->n0 + 1;+          int backup = contribs->n0 - new_n0;+          float * from_co = coeffs + num - 1;+          float * to_co = from_co + backup;++          STBIR_ASSERT( ( new_n0 >= row0 ) && ( new_n0 < contribs->n0 ) );++          // move the coeffs over+          while( num )+          {+            *to_co-- = *from_co--;+            --num;+          }+          // zero new positions+          while ( to_co >= coeffs )+            *to_co-- = 0;+          // set new start point+          contribs->n0 = new_n0;+          if ( widest > 12 )+          {+            int mod;++            // how far will be read in the n_coeff loop (which depends on the widest count mod4);+            mod = widest & 3;+            stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod;++            // the n_coeff loops do a minimum amount of coeffs, so factor that in!+            if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod;+          }+        }+      }+      --contribs;+      coeffs -= widest;+    }+  }++  return widest;+  #undef STBIR_MOVE_1+  #undef STBIR_MOVE_2+  #undef STBIR_MOVE_4+}++static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * other_axis_for_pivot, void * user_data STBIR_ONLY_PROFILE_BUILD_GET_INFO )+{+  int n;+  float scale = samp->scale_info.scale;+  stbir__kernel_callback * kernel = samp->filter_kernel;+  stbir__support_callback * support = samp->filter_support;+  float inv_scale = samp->scale_info.inv_scale;+  int input_full_size = samp->scale_info.input_full_size;+  int gather_num_contributors = samp->num_contributors;+  stbir__contributors* gather_contributors = samp->contributors;+  float * gather_coeffs = samp->coefficients;+  int gather_coefficient_width = samp->coefficient_width;++  switch ( samp->is_gather )+  {+    case 1: // gather upsample+    {+      float out_pixels_radius = support(inv_scale,user_data) * scale;++      stbir__calculate_coefficients_for_gather_upsample( out_pixels_radius, kernel, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width, samp->edge, user_data );++      STBIR_PROFILE_BUILD_START( cleanup );+      stbir__cleanup_gathered_coefficients( samp->edge, &samp->extent_info, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width );+      STBIR_PROFILE_BUILD_END( cleanup );+    }+    break;++    case 0: // scatter downsample (only on vertical)+    case 2: // gather downsample+    {+      float in_pixels_radius = support(scale,user_data) * inv_scale;+      int filter_pixel_margin = samp->filter_pixel_margin;+      int input_end = input_full_size + filter_pixel_margin;++      // if this is a scatter, we do a downsample gather to get the coeffs, and then pivot after+      if ( !samp->is_gather )+      {+        // check if we are using the same gather downsample on the horizontal as this vertical,+        //   if so, then we don't have to generate them, we can just pivot from the horizontal.+        if ( other_axis_for_pivot )+        {+          gather_contributors = other_axis_for_pivot->contributors;+          gather_coeffs = other_axis_for_pivot->coefficients;+          gather_coefficient_width = other_axis_for_pivot->coefficient_width;+          gather_num_contributors = other_axis_for_pivot->num_contributors;+          samp->extent_info.lowest = other_axis_for_pivot->extent_info.lowest;+          samp->extent_info.highest = other_axis_for_pivot->extent_info.highest;+          samp->extent_info.widest = other_axis_for_pivot->extent_info.widest;+          goto jump_right_to_pivot;+        }++        gather_contributors = samp->gather_prescatter_contributors;+        gather_coeffs = samp->gather_prescatter_coefficients;+        gather_coefficient_width = samp->gather_prescatter_coefficient_width;+        gather_num_contributors = samp->gather_prescatter_num_contributors;+      }++      stbir__calculate_coefficients_for_gather_downsample( -filter_pixel_margin, input_end, in_pixels_radius, kernel, &samp->scale_info, gather_coefficient_width, gather_num_contributors, gather_contributors, gather_coeffs, user_data );++      STBIR_PROFILE_BUILD_START( cleanup );+      stbir__cleanup_gathered_coefficients( samp->edge, &samp->extent_info, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width );+      STBIR_PROFILE_BUILD_END( cleanup );++      if ( !samp->is_gather )+      {+        // if this is a scatter (vertical only), then we need to pivot the coeffs+        stbir__contributors * scatter_contributors;+        int highest_set;++        jump_right_to_pivot:++        STBIR_PROFILE_BUILD_START( pivot );++        highest_set = (-filter_pixel_margin) - 1;+        for (n = 0; n < gather_num_contributors; n++)+        {+          int k;+          int gn0 = gather_contributors->n0, gn1 = gather_contributors->n1;+          int scatter_coefficient_width = samp->coefficient_width;+          float * scatter_coeffs = samp->coefficients + ( gn0 + filter_pixel_margin ) * scatter_coefficient_width;+          float * g_coeffs = gather_coeffs;+          scatter_contributors = samp->contributors + ( gn0 + filter_pixel_margin );++          for (k = gn0 ; k <= gn1 ; k++ )+          {+            float gc = *g_coeffs++;+            +            // skip zero and denormals - must skip zeros to avoid adding coeffs beyond scatter_coefficient_width+            //   (which happens when pivoting from horizontal, which might have dummy zeros)+            if ( ( ( gc >= stbir__small_float ) || ( gc <= -stbir__small_float ) ) )+            {+              if ( ( k > highest_set ) || ( scatter_contributors->n0 > scatter_contributors->n1 ) )+              {+                {+                  // if we are skipping over several contributors, we need to clear the skipped ones+                  stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1);+                  while ( clear_contributors < scatter_contributors )+                  {+                    clear_contributors->n0 = 0;+                    clear_contributors->n1 = -1;+                    ++clear_contributors;+                  }+                }+                scatter_contributors->n0 = n;+                scatter_contributors->n1 = n;+                scatter_coeffs[0]  = gc;+                highest_set = k;+              }+              else+              {+                stbir__insert_coeff( scatter_contributors, scatter_coeffs, n, gc );+              }+              STBIR_ASSERT( ( scatter_contributors->n1 - scatter_contributors->n0 + 1 ) <= scatter_coefficient_width );+            }+            ++scatter_contributors;+            scatter_coeffs += scatter_coefficient_width;+          }++          ++gather_contributors;+          gather_coeffs += gather_coefficient_width;+        }++        // now clear any unset contribs+        {+          stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1);+          stbir__contributors * end_contributors = samp->contributors + samp->num_contributors;+          while ( clear_contributors < end_contributors )+          {+            clear_contributors->n0 = 0;+            clear_contributors->n1 = -1;+            ++clear_contributors;+          }+        }++        STBIR_PROFILE_BUILD_END( pivot );+      }+    }+    break;+  }+}+++//========================================================================================================+// scanline decoders and encoders++#define stbir__coder_min_num 1+#define STB_IMAGE_RESIZE_DO_CODERS+#include STBIR__HEADER_FILENAME++#define stbir__decode_suffix BGRA+#define stbir__decode_swizzle+#define stbir__decode_order0  2+#define stbir__decode_order1  1+#define stbir__decode_order2  0+#define stbir__decode_order3  3+#define stbir__encode_order0  2+#define stbir__encode_order1  1+#define stbir__encode_order2  0+#define stbir__encode_order3  3+#define stbir__coder_min_num 4+#define STB_IMAGE_RESIZE_DO_CODERS+#include STBIR__HEADER_FILENAME++#define stbir__decode_suffix ARGB+#define stbir__decode_swizzle+#define stbir__decode_order0  1+#define stbir__decode_order1  2+#define stbir__decode_order2  3+#define stbir__decode_order3  0+#define stbir__encode_order0  3+#define stbir__encode_order1  0+#define stbir__encode_order2  1+#define stbir__encode_order3  2+#define stbir__coder_min_num 4+#define STB_IMAGE_RESIZE_DO_CODERS+#include STBIR__HEADER_FILENAME++#define stbir__decode_suffix ABGR+#define stbir__decode_swizzle+#define stbir__decode_order0  3+#define stbir__decode_order1  2+#define stbir__decode_order2  1+#define stbir__decode_order3  0+#define stbir__encode_order0  3+#define stbir__encode_order1  2+#define stbir__encode_order2  1+#define stbir__encode_order3  0+#define stbir__coder_min_num 4+#define STB_IMAGE_RESIZE_DO_CODERS+#include STBIR__HEADER_FILENAME++#define stbir__decode_suffix AR+#define stbir__decode_swizzle+#define stbir__decode_order0  1+#define stbir__decode_order1  0+#define stbir__decode_order2  3+#define stbir__decode_order3  2+#define stbir__encode_order0  1+#define stbir__encode_order1  0+#define stbir__encode_order2  3+#define stbir__encode_order3  2+#define stbir__coder_min_num 2+#define STB_IMAGE_RESIZE_DO_CODERS+#include STBIR__HEADER_FILENAME+++// fancy alpha means we expand to keep both premultipied and non-premultiplied color channels+static void stbir__fancy_alpha_weight_4ch( float * out_buffer, int width_times_channels )+{+  float STBIR_STREAMOUT_PTR(*) out = out_buffer;+  float const * end_decode = out_buffer + ( width_times_channels / 4 ) * 7;  // decode buffer aligned to end of out_buffer+  float STBIR_STREAMOUT_PTR(*) decode = (float*)end_decode - width_times_channels;++  // fancy alpha is stored internally as R G B A Rpm Gpm Bpm++  #ifdef STBIR_SIMD++  #ifdef STBIR_SIMD8+  decode += 16;+  STBIR_NO_UNROLL_LOOP_START+  while ( decode <= end_decode )+  {+    stbir__simdf8 d0,d1,a0,a1,p0,p1;+    STBIR_NO_UNROLL(decode);+    stbir__simdf8_load( d0, decode-16 );+    stbir__simdf8_load( d1, decode-16+8 );+    stbir__simdf8_0123to33333333( a0, d0 );+    stbir__simdf8_0123to33333333( a1, d1 );+    stbir__simdf8_mult( p0, a0, d0 );+    stbir__simdf8_mult( p1, a1, d1 );+    stbir__simdf8_bot4s( a0, d0, p0 );+    stbir__simdf8_bot4s( a1, d1, p1 );+    stbir__simdf8_top4s( d0, d0, p0 );+    stbir__simdf8_top4s( d1, d1, p1 );+    stbir__simdf8_store ( out, a0 );+    stbir__simdf8_store ( out+7, d0 );+    stbir__simdf8_store ( out+14, a1 );+    stbir__simdf8_store ( out+21, d1 );+    decode += 16;+    out += 28;+  }+  decode -= 16;+  #else+  decode += 8;+  STBIR_NO_UNROLL_LOOP_START+  while ( decode <= end_decode )+  {+    stbir__simdf d0,a0,d1,a1,p0,p1;+    STBIR_NO_UNROLL(decode);+    stbir__simdf_load( d0, decode-8 );+    stbir__simdf_load( d1, decode-8+4 );+    stbir__simdf_0123to3333( a0, d0 );+    stbir__simdf_0123to3333( a1, d1 );+    stbir__simdf_mult( p0, a0, d0 );+    stbir__simdf_mult( p1, a1, d1 );+    stbir__simdf_store ( out, d0 );+    stbir__simdf_store ( out+4, p0 );+    stbir__simdf_store ( out+7, d1 );+    stbir__simdf_store ( out+7+4, p1 );+    decode += 8;+    out += 14;+  }+  decode -= 8;+  #endif++  // might be one last odd pixel+  #ifdef STBIR_SIMD8+  STBIR_NO_UNROLL_LOOP_START+  while ( decode < end_decode )+  #else+  if ( decode < end_decode )+  #endif+  {+    stbir__simdf d,a,p;+    STBIR_NO_UNROLL(decode);+    stbir__simdf_load( d, decode );+    stbir__simdf_0123to3333( a, d );+    stbir__simdf_mult( p, a, d );+    stbir__simdf_store ( out, d );+    stbir__simdf_store ( out+4, p );+    decode += 4;+    out += 7;+  }++  #else++  while( decode < end_decode )+  {+    float r = decode[0], g = decode[1], b = decode[2], alpha = decode[3];+    out[0] = r;+    out[1] = g;+    out[2] = b;+    out[3] = alpha;+    out[4] = r * alpha;+    out[5] = g * alpha;+    out[6] = b * alpha;+    out += 7;+    decode += 4;+  }++  #endif+}++static void stbir__fancy_alpha_weight_2ch( float * out_buffer, int width_times_channels )+{+  float STBIR_STREAMOUT_PTR(*) out = out_buffer;+  float const * end_decode = out_buffer + ( width_times_channels / 2 ) * 3;+  float STBIR_STREAMOUT_PTR(*) decode = (float*)end_decode - width_times_channels;++  //  for fancy alpha, turns into: [X A Xpm][X A Xpm],etc++  #ifdef STBIR_SIMD++  decode += 8;+  if ( decode <= end_decode )+  {+    STBIR_NO_UNROLL_LOOP_START+    do {+      #ifdef STBIR_SIMD8+      stbir__simdf8 d0,a0,p0;+      STBIR_NO_UNROLL(decode);+      stbir__simdf8_load( d0, decode-8 );+      stbir__simdf8_0123to11331133( p0, d0 );+      stbir__simdf8_0123to00220022( a0, d0 );+      stbir__simdf8_mult( p0, p0, a0 );++      stbir__simdf_store2( out, stbir__if_simdf8_cast_to_simdf4( d0 ) );+      stbir__simdf_store( out+2, stbir__if_simdf8_cast_to_simdf4( p0 ) );+      stbir__simdf_store2h( out+3, stbir__if_simdf8_cast_to_simdf4( d0 ) );++      stbir__simdf_store2( out+6, stbir__simdf8_gettop4( d0 ) );+      stbir__simdf_store( out+8, stbir__simdf8_gettop4( p0 ) );+      stbir__simdf_store2h( out+9, stbir__simdf8_gettop4( d0 ) );+      #else+      stbir__simdf d0,a0,d1,a1,p0,p1;+      STBIR_NO_UNROLL(decode);+      stbir__simdf_load( d0, decode-8 );+      stbir__simdf_load( d1, decode-8+4 );+      stbir__simdf_0123to1133( p0, d0 );+      stbir__simdf_0123to1133( p1, d1 );+      stbir__simdf_0123to0022( a0, d0 );+      stbir__simdf_0123to0022( a1, d1 );+      stbir__simdf_mult( p0, p0, a0 );+      stbir__simdf_mult( p1, p1, a1 );++      stbir__simdf_store2( out, d0 );+      stbir__simdf_store( out+2, p0 );+      stbir__simdf_store2h( out+3, d0 );++      stbir__simdf_store2( out+6, d1 );+      stbir__simdf_store( out+8, p1 );+      stbir__simdf_store2h( out+9, d1 );+      #endif+      decode += 8;+      out += 12;+    } while ( decode <= end_decode );+  }+  decode -= 8;+  #endif++  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( decode < end_decode )+  {+    float x = decode[0], y = decode[1];+    STBIR_SIMD_NO_UNROLL(decode);+    out[0] = x;+    out[1] = y;+    out[2] = x * y;+    out += 3;+    decode += 2;+  }+}++static void stbir__fancy_alpha_unweight_4ch( float * encode_buffer, int width_times_channels )+{+  float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer;+  float STBIR_SIMD_STREAMOUT_PTR(*) input = encode_buffer;+  float const * end_output = encode_buffer + width_times_channels;++  // fancy RGBA is stored internally as R G B A Rpm Gpm Bpm++  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float alpha = input[3];+#ifdef STBIR_SIMD+    stbir__simdf i,ia;+    STBIR_SIMD_NO_UNROLL(encode);+    if ( alpha < stbir__small_float )+    {+      stbir__simdf_load( i, input );+      stbir__simdf_store( encode, i );+    }+    else+    {+      stbir__simdf_load1frep4( ia, 1.0f / alpha );+      stbir__simdf_load( i, input+4 );+      stbir__simdf_mult( i, i, ia );+      stbir__simdf_store( encode, i );+      encode[3] = alpha;+    }+#else+    if ( alpha < stbir__small_float )+    {+      encode[0] = input[0];+      encode[1] = input[1];+      encode[2] = input[2];+    }+    else+    {+      float ialpha = 1.0f / alpha;+      encode[0] = input[4] * ialpha;+      encode[1] = input[5] * ialpha;+      encode[2] = input[6] * ialpha;+    }+    encode[3] = alpha;+#endif++    input += 7;+    encode += 4;+  } while ( encode < end_output );+}++//  format: [X A Xpm][X A Xpm] etc+static void stbir__fancy_alpha_unweight_2ch( float * encode_buffer, int width_times_channels )+{+  float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer;+  float STBIR_SIMD_STREAMOUT_PTR(*) input = encode_buffer;+  float const * end_output = encode_buffer + width_times_channels;++  do {+    float alpha = input[1];+    encode[0] = input[0];+    if ( alpha >= stbir__small_float )+      encode[0] = input[2] / alpha;+    encode[1] = alpha;++    input += 3;+    encode += 2;+  } while ( encode < end_output );+}++static void stbir__simple_alpha_weight_4ch( float * decode_buffer, int width_times_channels )+{+  float STBIR_STREAMOUT_PTR(*) decode = decode_buffer;+  float const * end_decode = decode_buffer + width_times_channels;++  #ifdef STBIR_SIMD+  {+    decode += 2 * stbir__simdfX_float_count;+    STBIR_NO_UNROLL_LOOP_START+    while ( decode <= end_decode )+    {+      stbir__simdfX d0,a0,d1,a1;+      STBIR_NO_UNROLL(decode);+      stbir__simdfX_load( d0, decode-2*stbir__simdfX_float_count );+      stbir__simdfX_load( d1, decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count );+      stbir__simdfX_aaa1( a0, d0, STBIR_onesX );+      stbir__simdfX_aaa1( a1, d1, STBIR_onesX );+      stbir__simdfX_mult( d0, d0, a0 );+      stbir__simdfX_mult( d1, d1, a1 );+      stbir__simdfX_store ( decode-2*stbir__simdfX_float_count, d0 );+      stbir__simdfX_store ( decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count, d1 );+      decode += 2 * stbir__simdfX_float_count;+    }+    decode -= 2 * stbir__simdfX_float_count;++    // few last pixels remnants+    #ifdef STBIR_SIMD8+    STBIR_NO_UNROLL_LOOP_START+    while ( decode < end_decode )+    #else+    if ( decode < end_decode )+    #endif+    {+      stbir__simdf d,a;+      stbir__simdf_load( d, decode );+      stbir__simdf_aaa1( a, d, STBIR__CONSTF(STBIR_ones) );+      stbir__simdf_mult( d, d, a );+      stbir__simdf_store ( decode, d );+      decode += 4;+    }+  }++  #else++  while( decode < end_decode )+  {+    float alpha = decode[3];+    decode[0] *= alpha;+    decode[1] *= alpha;+    decode[2] *= alpha;+    decode += 4;+  }++  #endif+}++static void stbir__simple_alpha_weight_2ch( float * decode_buffer, int width_times_channels )+{+  float STBIR_STREAMOUT_PTR(*) decode = decode_buffer;+  float const * end_decode = decode_buffer + width_times_channels;++  #ifdef STBIR_SIMD+  decode += 2 * stbir__simdfX_float_count;+  STBIR_NO_UNROLL_LOOP_START+  while ( decode <= end_decode )+  {+    stbir__simdfX d0,a0,d1,a1;+    STBIR_NO_UNROLL(decode);+    stbir__simdfX_load( d0, decode-2*stbir__simdfX_float_count );+    stbir__simdfX_load( d1, decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count );+    stbir__simdfX_a1a1( a0, d0, STBIR_onesX );+    stbir__simdfX_a1a1( a1, d1, STBIR_onesX );+    stbir__simdfX_mult( d0, d0, a0 );+    stbir__simdfX_mult( d1, d1, a1 );+    stbir__simdfX_store ( decode-2*stbir__simdfX_float_count, d0 );+    stbir__simdfX_store ( decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count, d1 );+    decode += 2 * stbir__simdfX_float_count;+  }+  decode -= 2 * stbir__simdfX_float_count;+  #endif++  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( decode < end_decode )+  {+    float alpha = decode[1];+    STBIR_SIMD_NO_UNROLL(decode);+    decode[0] *= alpha;+    decode += 2;+  }+}++static void stbir__simple_alpha_unweight_4ch( float * encode_buffer, int width_times_channels )+{+  float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer;+  float const * end_output = encode_buffer + width_times_channels;++  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float alpha = encode[3];++#ifdef STBIR_SIMD+    stbir__simdf i,ia;+    STBIR_SIMD_NO_UNROLL(encode);+    if ( alpha >= stbir__small_float )+    {+      stbir__simdf_load1frep4( ia, 1.0f / alpha );+      stbir__simdf_load( i, encode );+      stbir__simdf_mult( i, i, ia );+      stbir__simdf_store( encode, i );+      encode[3] = alpha;+    }+#else+    if ( alpha >= stbir__small_float )+    {+      float ialpha = 1.0f / alpha;+      encode[0] *= ialpha;+      encode[1] *= ialpha;+      encode[2] *= ialpha;+    }+#endif+    encode += 4;+  } while ( encode < end_output );+}++static void stbir__simple_alpha_unweight_2ch( float * encode_buffer, int width_times_channels )+{+  float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer;+  float const * end_output = encode_buffer + width_times_channels;++  do {+    float alpha = encode[1];+    if ( alpha >= stbir__small_float )+      encode[0] /= alpha;+    encode += 2;+  } while ( encode < end_output );+}+++// only used in RGB->BGR or BGR->RGB+static void stbir__simple_flip_3ch( float * decode_buffer, int width_times_channels )+{+  float STBIR_STREAMOUT_PTR(*) decode = decode_buffer;+  float const * end_decode = decode_buffer + width_times_channels;++#ifdef STBIR_SIMD+    #ifdef stbir__simdf_swiz2 // do we have two argument swizzles?+      end_decode -= 12; +      STBIR_NO_UNROLL_LOOP_START+      while( decode <= end_decode )+      {+        // on arm64 8 instructions, no overlapping stores+        stbir__simdf a,b,c,na,nb;+        STBIR_SIMD_NO_UNROLL(decode);+        stbir__simdf_load( a, decode );+        stbir__simdf_load( b, decode+4 );+        stbir__simdf_load( c, decode+8 );++        na = stbir__simdf_swiz2( a, b, 2, 1, 0, 5 );   +        b  = stbir__simdf_swiz2( a, b, 4, 3, 6, 7 );   +        nb = stbir__simdf_swiz2( b, c, 0, 1, 4, 3 );   +        c  = stbir__simdf_swiz2( b, c, 2, 7, 6, 5 );   ++        stbir__simdf_store( decode, na );+        stbir__simdf_store( decode+4, nb ); +        stbir__simdf_store( decode+8, c );+        decode += 12;+      }+      end_decode += 12;+    #else+      end_decode -= 24;+      STBIR_NO_UNROLL_LOOP_START+      while( decode <= end_decode )+      {+        // 26 instructions on x64+        stbir__simdf a,b,c,d,e,f,g;+        float i21, i23;+        STBIR_SIMD_NO_UNROLL(decode);+        stbir__simdf_load( a, decode );+        stbir__simdf_load( b, decode+3 );+        stbir__simdf_load( c, decode+6 );+        stbir__simdf_load( d, decode+9 );+        stbir__simdf_load( e, decode+12 );+        stbir__simdf_load( f, decode+15 );+        stbir__simdf_load( g, decode+18 );++        a = stbir__simdf_swiz( a, 2, 1, 0, 3 );   +        b = stbir__simdf_swiz( b, 2, 1, 0, 3 );   +        c = stbir__simdf_swiz( c, 2, 1, 0, 3 );   +        d = stbir__simdf_swiz( d, 2, 1, 0, 3 );   +        e = stbir__simdf_swiz( e, 2, 1, 0, 3 );   +        f = stbir__simdf_swiz( f, 2, 1, 0, 3 );   +        g = stbir__simdf_swiz( g, 2, 1, 0, 3 );   ++        // stores overlap, need to be in order, +        stbir__simdf_store( decode,    a );+        i21 = decode[21];+        stbir__simdf_store( decode+3,  b ); +        i23 = decode[23];+        stbir__simdf_store( decode+6,  c );+        stbir__simdf_store( decode+9,  d );+        stbir__simdf_store( decode+12, e );+        stbir__simdf_store( decode+15, f );+        stbir__simdf_store( decode+18, g );+        decode[21] = i23;+        decode[23] = i21;+        decode += 24;+      }+      end_decode += 24;+    #endif+#else+  end_decode -= 12;+  STBIR_NO_UNROLL_LOOP_START+  while( decode <= end_decode )+  {+    // 16 instructions+    float t0,t1,t2,t3;+    STBIR_NO_UNROLL(decode);+    t0 = decode[0]; t1 = decode[3]; t2 = decode[6]; t3 = decode[9];+    decode[0] = decode[2]; decode[3] = decode[5]; decode[6] = decode[8]; decode[9] = decode[11];+    decode[2] = t0; decode[5] = t1; decode[8] = t2; decode[11] = t3;+    decode += 12;+  }+  end_decode += 12;+#endif++  STBIR_NO_UNROLL_LOOP_START+  while( decode < end_decode )+  {+    float t = decode[0];+    STBIR_NO_UNROLL(decode);+    decode[0] = decode[2];+    decode[2] = t;+    decode += 3;+  }+}++++static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float * output_buffer STBIR_ONLY_PROFILE_GET_SPLIT_INFO )+{+  int channels = stbir_info->channels;+  int effective_channels = stbir_info->effective_channels;+  int input_sample_in_bytes = stbir__type_size[stbir_info->input_type] * channels;+  stbir_edge edge_horizontal = stbir_info->horizontal.edge;+  stbir_edge edge_vertical = stbir_info->vertical.edge;+  int row = stbir__edge_wrap(edge_vertical, n, stbir_info->vertical.scale_info.input_full_size);+  const void* input_plane_data = ( (char *) stbir_info->input_data ) + (size_t)row * (size_t) stbir_info->input_stride_bytes;+  stbir__span const * spans = stbir_info->scanline_extents.spans;+  float* full_decode_buffer = output_buffer - stbir_info->scanline_extents.conservative.n0 * effective_channels;++  // if we are on edge_zero, and we get in here with an out of bounds n, then the calculate filters has failed+  STBIR_ASSERT( !(edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->vertical.scale_info.input_full_size)) );++  do+  {+    float * decode_buffer;+    void const * input_data;+    float * end_decode;+    int width_times_channels;+    int width;++    if ( spans->n1 < spans->n0 )+      break;++    width = spans->n1 + 1 - spans->n0;+    decode_buffer = full_decode_buffer + spans->n0 * effective_channels;+    end_decode = full_decode_buffer + ( spans->n1 + 1 ) * effective_channels;+    width_times_channels = width * channels;++    // read directly out of input plane by default+    input_data = ( (char*)input_plane_data ) + spans->pixel_offset_for_input * input_sample_in_bytes;++    // if we have an input callback, call it to get the input data+    if ( stbir_info->in_pixels_cb )+    {+      // call the callback with a temp buffer (that they can choose to use or not).  the temp is just right aligned memory in the decode_buffer itself+      input_data = stbir_info->in_pixels_cb( ( (char*) end_decode ) - ( width * input_sample_in_bytes ), input_plane_data, width, spans->pixel_offset_for_input, row, stbir_info->user_data );+    }++    STBIR_PROFILE_START( decode );+    // convert the pixels info the float decode_buffer, (we index from end_decode, so that when channels<effective_channels, we are right justified in the buffer)+    stbir_info->decode_pixels( (float*)end_decode - width_times_channels, width_times_channels, input_data );+    STBIR_PROFILE_END( decode );++    if (stbir_info->alpha_weight)+    {+      STBIR_PROFILE_START( alpha );+      stbir_info->alpha_weight( decode_buffer, width_times_channels );+      STBIR_PROFILE_END( alpha );+    }++    ++spans;+  } while ( spans <= ( &stbir_info->scanline_extents.spans[1] ) );++  // handle the edge_wrap filter (all other types are handled back out at the calculate_filter stage)+  // basically the idea here is that if we have the whole scanline in memory, we don't redecode the+  //   wrapped edge pixels, and instead just memcpy them from the scanline into the edge positions+  if ( ( edge_horizontal == STBIR_EDGE_WRAP ) && ( stbir_info->scanline_extents.edge_sizes[0] | stbir_info->scanline_extents.edge_sizes[1] ) )+  {+    // this code only runs if we're in edge_wrap, and we're doing the entire scanline+    int e, start_x[2];+    int input_full_size = stbir_info->horizontal.scale_info.input_full_size;++    start_x[0] = -stbir_info->scanline_extents.edge_sizes[0];  // left edge start x+    start_x[1] =  input_full_size;                             // right edge++    for( e = 0; e < 2 ; e++ )+    {+      // do each margin+      int margin = stbir_info->scanline_extents.edge_sizes[e];+      if ( margin )+      {+        int x = start_x[e];+        float * marg = full_decode_buffer + x * effective_channels;+        float const * src = full_decode_buffer + stbir__edge_wrap(edge_horizontal, x, input_full_size) * effective_channels;+        STBIR_MEMCPY( marg, src, margin * effective_channels * sizeof(float) );+      }+    }+  }+}+++//=================+// Do 1 channel horizontal routines++#ifdef STBIR_SIMD++#define stbir__1_coeff_only()          \+    stbir__simdf tot,c;                \+    STBIR_SIMD_NO_UNROLL(decode);      \+    stbir__simdf_load1( c, hc );       \+    stbir__simdf_mult1_mem( tot, c, decode );++#define stbir__2_coeff_only()          \+    stbir__simdf tot,c,d;              \+    STBIR_SIMD_NO_UNROLL(decode);      \+    stbir__simdf_load2z( c, hc );      \+    stbir__simdf_load2( d, decode );   \+    stbir__simdf_mult( tot, c, d );    \+    stbir__simdf_0123to1230( c, tot ); \+    stbir__simdf_add1( tot, tot, c );++#define stbir__3_coeff_only()                  \+    stbir__simdf tot,c,t;                      \+    STBIR_SIMD_NO_UNROLL(decode);              \+    stbir__simdf_load( c, hc );                \+    stbir__simdf_mult_mem( tot, c, decode );   \+    stbir__simdf_0123to1230( c, tot );         \+    stbir__simdf_0123to2301( t, tot );         \+    stbir__simdf_add1( tot, tot, c );          \+    stbir__simdf_add1( tot, tot, t );++#define stbir__store_output_tiny()                \+    stbir__simdf_store1( output, tot );           \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 1;++#define stbir__4_coeff_start()                 \+    stbir__simdf tot,c;                        \+    STBIR_SIMD_NO_UNROLL(decode);              \+    stbir__simdf_load( c, hc );                \+    stbir__simdf_mult_mem( tot, c, decode );   \++#define stbir__4_coeff_continue_from_4( ofs )  \+    STBIR_SIMD_NO_UNROLL(decode);              \+    stbir__simdf_load( c, hc + (ofs) );        \+    stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) );++#define stbir__1_coeff_remnant( ofs )          \+    { stbir__simdf d;                          \+    stbir__simdf_load1z( c, hc + (ofs) );      \+    stbir__simdf_load1( d, decode + (ofs) );   \+    stbir__simdf_madd( tot, tot, d, c ); }++#define stbir__2_coeff_remnant( ofs )          \+    { stbir__simdf d;                          \+    stbir__simdf_load2z( c, hc+(ofs) );        \+    stbir__simdf_load2( d, decode+(ofs) );     \+    stbir__simdf_madd( tot, tot, d, c ); }++#define stbir__3_coeff_setup()                 \+    stbir__simdf mask;                         \+    stbir__simdf_load( mask, STBIR_mask + 3 );++#define stbir__3_coeff_remnant( ofs )                  \+    stbir__simdf_load( c, hc+(ofs) );                  \+    stbir__simdf_and( c, c, mask );                    \+    stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) );++#define stbir__store_output()                     \+    stbir__simdf_0123to2301( c, tot );            \+    stbir__simdf_add( tot, tot, c );              \+    stbir__simdf_0123to1230( c, tot );            \+    stbir__simdf_add1( tot, tot, c );             \+    stbir__simdf_store1( output, tot );           \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 1;++#else++#define stbir__1_coeff_only()  \+    float tot;                 \+    tot = decode[0]*hc[0];++#define stbir__2_coeff_only()  \+    float tot;                 \+    tot = decode[0] * hc[0];   \+    tot += decode[1] * hc[1];++#define stbir__3_coeff_only()  \+    float tot;                 \+    tot = decode[0] * hc[0];   \+    tot += decode[1] * hc[1];  \+    tot += decode[2] * hc[2];++#define stbir__store_output_tiny()                \+    output[0] = tot;                              \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 1;++#define stbir__4_coeff_start()  \+    float tot0,tot1,tot2,tot3;  \+    tot0 = decode[0] * hc[0];   \+    tot1 = decode[1] * hc[1];   \+    tot2 = decode[2] * hc[2];   \+    tot3 = decode[3] * hc[3];++#define stbir__4_coeff_continue_from_4( ofs )  \+    tot0 += decode[0+(ofs)] * hc[0+(ofs)];     \+    tot1 += decode[1+(ofs)] * hc[1+(ofs)];     \+    tot2 += decode[2+(ofs)] * hc[2+(ofs)];     \+    tot3 += decode[3+(ofs)] * hc[3+(ofs)];++#define stbir__1_coeff_remnant( ofs )        \+    tot0 += decode[0+(ofs)] * hc[0+(ofs)];++#define stbir__2_coeff_remnant( ofs )        \+    tot0 += decode[0+(ofs)] * hc[0+(ofs)];   \+    tot1 += decode[1+(ofs)] * hc[1+(ofs)];   \++#define stbir__3_coeff_remnant( ofs )        \+    tot0 += decode[0+(ofs)] * hc[0+(ofs)];   \+    tot1 += decode[1+(ofs)] * hc[1+(ofs)];   \+    tot2 += decode[2+(ofs)] * hc[2+(ofs)];++#define stbir__store_output()                     \+    output[0] = (tot0+tot2)+(tot1+tot3);          \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 1;++#endif++#define STBIR__horizontal_channels 1+#define STB_IMAGE_RESIZE_DO_HORIZONTALS+#include STBIR__HEADER_FILENAME+++//=================+// Do 2 channel horizontal routines++#ifdef STBIR_SIMD++#define stbir__1_coeff_only()         \+    stbir__simdf tot,c,d;             \+    STBIR_SIMD_NO_UNROLL(decode);     \+    stbir__simdf_load1z( c, hc );     \+    stbir__simdf_0123to0011( c, c );  \+    stbir__simdf_load2( d, decode );  \+    stbir__simdf_mult( tot, d, c );++#define stbir__2_coeff_only()         \+    stbir__simdf tot,c;               \+    STBIR_SIMD_NO_UNROLL(decode);     \+    stbir__simdf_load2( c, hc );      \+    stbir__simdf_0123to0011( c, c );  \+    stbir__simdf_mult_mem( tot, c, decode );++#define stbir__3_coeff_only()                \+    stbir__simdf tot,c,cs,d;                 \+    STBIR_SIMD_NO_UNROLL(decode);            \+    stbir__simdf_load( cs, hc );             \+    stbir__simdf_0123to0011( c, cs );        \+    stbir__simdf_mult_mem( tot, c, decode ); \+    stbir__simdf_0123to2222( c, cs );        \+    stbir__simdf_load2z( d, decode+4 );      \+    stbir__simdf_madd( tot, tot, d, c );++#define stbir__store_output_tiny()                \+    stbir__simdf_0123to2301( c, tot );            \+    stbir__simdf_add( tot, tot, c );              \+    stbir__simdf_store2( output, tot );           \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 2;++#ifdef STBIR_SIMD8++#define stbir__4_coeff_start()                    \+    stbir__simdf8 tot0,c,cs;                      \+    STBIR_SIMD_NO_UNROLL(decode);                 \+    stbir__simdf8_load4b( cs, hc );               \+    stbir__simdf8_0123to00112233( c, cs );        \+    stbir__simdf8_mult_mem( tot0, c, decode );++#define stbir__4_coeff_continue_from_4( ofs )        \+    STBIR_SIMD_NO_UNROLL(decode);                    \+    stbir__simdf8_load4b( cs, hc + (ofs) );          \+    stbir__simdf8_0123to00112233( c, cs );           \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*2 );++#define stbir__1_coeff_remnant( ofs )                \+    { stbir__simdf t;                                \+    stbir__simdf_load1z( t, hc + (ofs) );            \+    stbir__simdf_0123to0011( t, t );                 \+    stbir__simdf_mult_mem( t, t, decode+(ofs)*2 );   \+    stbir__simdf8_add4( tot0, tot0, t ); }++#define stbir__2_coeff_remnant( ofs )                \+    { stbir__simdf t;                                \+    stbir__simdf_load2( t, hc + (ofs) );             \+    stbir__simdf_0123to0011( t, t );                 \+    stbir__simdf_mult_mem( t, t, decode+(ofs)*2 );   \+    stbir__simdf8_add4( tot0, tot0, t ); }++#define stbir__3_coeff_remnant( ofs )                \+    { stbir__simdf8 d;                               \+    stbir__simdf8_load4b( cs, hc + (ofs) );          \+    stbir__simdf8_0123to00112233( c, cs );           \+    stbir__simdf8_load6z( d, decode+(ofs)*2 );       \+    stbir__simdf8_madd( tot0, tot0, c, d ); }++#define stbir__store_output()                     \+    { stbir__simdf t,d;                           \+    stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 );    \+    stbir__simdf_0123to2301( d, t );              \+    stbir__simdf_add( t, t, d );                  \+    stbir__simdf_store2( output, t );             \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 2; }++#else++#define stbir__4_coeff_start()                   \+    stbir__simdf tot0,tot1,c,cs;                 \+    STBIR_SIMD_NO_UNROLL(decode);                \+    stbir__simdf_load( cs, hc );                 \+    stbir__simdf_0123to0011( c, cs );            \+    stbir__simdf_mult_mem( tot0, c, decode );    \+    stbir__simdf_0123to2233( c, cs );            \+    stbir__simdf_mult_mem( tot1, c, decode+4 );++#define stbir__4_coeff_continue_from_4( ofs )                \+    STBIR_SIMD_NO_UNROLL(decode);                            \+    stbir__simdf_load( cs, hc + (ofs) );                     \+    stbir__simdf_0123to0011( c, cs );                        \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 );  \+    stbir__simdf_0123to2233( c, cs );                        \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*2+4 );++#define stbir__1_coeff_remnant( ofs )            \+    { stbir__simdf d;                            \+    stbir__simdf_load1z( cs, hc + (ofs) );       \+    stbir__simdf_0123to0011( c, cs );            \+    stbir__simdf_load2( d, decode + (ofs) * 2 ); \+    stbir__simdf_madd( tot0, tot0, d, c ); }++#define stbir__2_coeff_remnant( ofs )                      \+    stbir__simdf_load2( cs, hc + (ofs) );                  \+    stbir__simdf_0123to0011( c, cs );                      \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 );++#define stbir__3_coeff_remnant( ofs )                       \+    { stbir__simdf d;                                       \+    stbir__simdf_load( cs, hc + (ofs) );                    \+    stbir__simdf_0123to0011( c, cs );                       \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); \+    stbir__simdf_0123to2222( c, cs );                       \+    stbir__simdf_load2z( d, decode + (ofs) * 2 + 4 );       \+    stbir__simdf_madd( tot1, tot1, d, c ); }++#define stbir__store_output()                     \+    stbir__simdf_add( tot0, tot0, tot1 );         \+    stbir__simdf_0123to2301( c, tot0 );           \+    stbir__simdf_add( tot0, tot0, c );            \+    stbir__simdf_store2( output, tot0 );          \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 2;++#endif++#else++#define stbir__1_coeff_only()  \+    float tota,totb,c;         \+    c = hc[0];                 \+    tota = decode[0]*c;        \+    totb = decode[1]*c;++#define stbir__2_coeff_only()  \+    float tota,totb,c;         \+    c = hc[0];                 \+    tota = decode[0]*c;        \+    totb = decode[1]*c;        \+    c = hc[1];                 \+    tota += decode[2]*c;       \+    totb += decode[3]*c;++// this weird order of add matches the simd+#define stbir__3_coeff_only()  \+    float tota,totb,c;         \+    c = hc[0];                 \+    tota = decode[0]*c;        \+    totb = decode[1]*c;        \+    c = hc[2];                 \+    tota += decode[4]*c;       \+    totb += decode[5]*c;       \+    c = hc[1];                 \+    tota += decode[2]*c;       \+    totb += decode[3]*c;++#define stbir__store_output_tiny()                \+    output[0] = tota;                             \+    output[1] = totb;                             \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 2;++#define stbir__4_coeff_start()      \+    float tota0,tota1,tota2,tota3,totb0,totb1,totb2,totb3,c;  \+    c = hc[0];                      \+    tota0 = decode[0]*c;            \+    totb0 = decode[1]*c;            \+    c = hc[1];                      \+    tota1 = decode[2]*c;            \+    totb1 = decode[3]*c;            \+    c = hc[2];                      \+    tota2 = decode[4]*c;            \+    totb2 = decode[5]*c;            \+    c = hc[3];                      \+    tota3 = decode[6]*c;            \+    totb3 = decode[7]*c;++#define stbir__4_coeff_continue_from_4( ofs )  \+    c = hc[0+(ofs)];                           \+    tota0 += decode[0+(ofs)*2]*c;              \+    totb0 += decode[1+(ofs)*2]*c;              \+    c = hc[1+(ofs)];                           \+    tota1 += decode[2+(ofs)*2]*c;              \+    totb1 += decode[3+(ofs)*2]*c;              \+    c = hc[2+(ofs)];                           \+    tota2 += decode[4+(ofs)*2]*c;              \+    totb2 += decode[5+(ofs)*2]*c;              \+    c = hc[3+(ofs)];                           \+    tota3 += decode[6+(ofs)*2]*c;              \+    totb3 += decode[7+(ofs)*2]*c;++#define stbir__1_coeff_remnant( ofs )  \+    c = hc[0+(ofs)];                   \+    tota0 += decode[0+(ofs)*2] * c;    \+    totb0 += decode[1+(ofs)*2] * c;++#define stbir__2_coeff_remnant( ofs )  \+    c = hc[0+(ofs)];                   \+    tota0 += decode[0+(ofs)*2] * c;    \+    totb0 += decode[1+(ofs)*2] * c;    \+    c = hc[1+(ofs)];                   \+    tota1 += decode[2+(ofs)*2] * c;    \+    totb1 += decode[3+(ofs)*2] * c;++#define stbir__3_coeff_remnant( ofs )  \+    c = hc[0+(ofs)];                   \+    tota0 += decode[0+(ofs)*2] * c;    \+    totb0 += decode[1+(ofs)*2] * c;    \+    c = hc[1+(ofs)];                   \+    tota1 += decode[2+(ofs)*2] * c;    \+    totb1 += decode[3+(ofs)*2] * c;    \+    c = hc[2+(ofs)];                   \+    tota2 += decode[4+(ofs)*2] * c;    \+    totb2 += decode[5+(ofs)*2] * c;++#define stbir__store_output()                     \+    output[0] = (tota0+tota2)+(tota1+tota3);      \+    output[1] = (totb0+totb2)+(totb1+totb3);      \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 2;++#endif++#define STBIR__horizontal_channels 2+#define STB_IMAGE_RESIZE_DO_HORIZONTALS+#include STBIR__HEADER_FILENAME+++//=================+// Do 3 channel horizontal routines++#ifdef STBIR_SIMD++#define stbir__1_coeff_only()         \+    stbir__simdf tot,c,d;             \+    STBIR_SIMD_NO_UNROLL(decode);     \+    stbir__simdf_load1z( c, hc );     \+    stbir__simdf_0123to0001( c, c );  \+    stbir__simdf_load( d, decode );   \+    stbir__simdf_mult( tot, d, c );++#define stbir__2_coeff_only()         \+    stbir__simdf tot,c,cs,d;          \+    STBIR_SIMD_NO_UNROLL(decode);     \+    stbir__simdf_load2( cs, hc );     \+    stbir__simdf_0123to0000( c, cs ); \+    stbir__simdf_load( d, decode );   \+    stbir__simdf_mult( tot, d, c );   \+    stbir__simdf_0123to1111( c, cs ); \+    stbir__simdf_load( d, decode+3 ); \+    stbir__simdf_madd( tot, tot, d, c );++#define stbir__3_coeff_only()            \+    stbir__simdf tot,c,d,cs;             \+    STBIR_SIMD_NO_UNROLL(decode);        \+    stbir__simdf_load( cs, hc );         \+    stbir__simdf_0123to0000( c, cs );    \+    stbir__simdf_load( d, decode );      \+    stbir__simdf_mult( tot, d, c );      \+    stbir__simdf_0123to1111( c, cs );    \+    stbir__simdf_load( d, decode+3 );    \+    stbir__simdf_madd( tot, tot, d, c ); \+    stbir__simdf_0123to2222( c, cs );    \+    stbir__simdf_load( d, decode+6 );    \+    stbir__simdf_madd( tot, tot, d, c );++#define stbir__store_output_tiny()                \+    stbir__simdf_store2( output, tot );           \+    stbir__simdf_0123to2301( tot, tot );          \+    stbir__simdf_store1( output+2, tot );         \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 3;++#ifdef STBIR_SIMD8++// we're loading from the XXXYYY decode by -1 to get the XXXYYY into different halves of the AVX reg fyi+#define stbir__4_coeff_start()                     \+    stbir__simdf8 tot0,tot1,c,cs; stbir__simdf t;  \+    STBIR_SIMD_NO_UNROLL(decode);                  \+    stbir__simdf8_load4b( cs, hc );                \+    stbir__simdf8_0123to00001111( c, cs );         \+    stbir__simdf8_mult_mem( tot0, c, decode - 1 ); \+    stbir__simdf8_0123to22223333( c, cs );         \+    stbir__simdf8_mult_mem( tot1, c, decode+6 - 1 );++#define stbir__4_coeff_continue_from_4( ofs )      \+    STBIR_SIMD_NO_UNROLL(decode);                  \+    stbir__simdf8_load4b( cs, hc + (ofs) );        \+    stbir__simdf8_0123to00001111( c, cs );         \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \+    stbir__simdf8_0123to22223333( c, cs );         \+    stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*3 + 6 - 1 );++#define stbir__1_coeff_remnant( ofs )                          \+    STBIR_SIMD_NO_UNROLL(decode);                              \+    stbir__simdf_load1rep4( t, hc + (ofs) );                   \+    stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*3 - 1 );++#define stbir__2_coeff_remnant( ofs )                          \+    STBIR_SIMD_NO_UNROLL(decode);                              \+    stbir__simdf8_load4b( cs, hc + (ofs) - 2 );                \+    stbir__simdf8_0123to22223333( c, cs );                     \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 );++ #define stbir__3_coeff_remnant( ofs )                           \+    STBIR_SIMD_NO_UNROLL(decode);                                \+    stbir__simdf8_load4b( cs, hc + (ofs) );                      \+    stbir__simdf8_0123to00001111( c, cs );                       \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \+    stbir__simdf8_0123to2222( t, cs );                           \+    stbir__simdf8_madd_mem4( tot1, tot1, t, decode+(ofs)*3 + 6 - 1 );++#define stbir__store_output()                       \+    stbir__simdf8_add( tot0, tot0, tot1 );          \+    stbir__simdf_0123to1230( t, stbir__if_simdf8_cast_to_simdf4( tot0 ) ); \+    stbir__simdf8_add4halves( t, t, tot0 );         \+    horizontal_coefficients += coefficient_width;   \+    ++horizontal_contributors;                      \+    output += 3;                                    \+    if ( output < output_end )                      \+    {                                               \+      stbir__simdf_store( output-3, t );            \+      continue;                                     \+    }                                               \+    { stbir__simdf tt; stbir__simdf_0123to2301( tt, t ); \+    stbir__simdf_store2( output-3, t );             \+    stbir__simdf_store1( output+2-3, tt ); }        \+    break;+++#else++#define stbir__4_coeff_start()                  \+    stbir__simdf tot0,tot1,tot2,c,cs;           \+    STBIR_SIMD_NO_UNROLL(decode);               \+    stbir__simdf_load( cs, hc );                \+    stbir__simdf_0123to0001( c, cs );           \+    stbir__simdf_mult_mem( tot0, c, decode );   \+    stbir__simdf_0123to1122( c, cs );           \+    stbir__simdf_mult_mem( tot1, c, decode+4 ); \+    stbir__simdf_0123to2333( c, cs );           \+    stbir__simdf_mult_mem( tot2, c, decode+8 );++#define stbir__4_coeff_continue_from_4( ofs )                 \+    STBIR_SIMD_NO_UNROLL(decode);                             \+    stbir__simdf_load( cs, hc + (ofs) );                      \+    stbir__simdf_0123to0001( c, cs );                         \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 );   \+    stbir__simdf_0123to1122( c, cs );                         \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \+    stbir__simdf_0123to2333( c, cs );                         \+    stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*3+8 );++#define stbir__1_coeff_remnant( ofs )         \+    STBIR_SIMD_NO_UNROLL(decode);             \+    stbir__simdf_load1z( c, hc + (ofs) );     \+    stbir__simdf_0123to0001( c, c );          \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 );++#define stbir__2_coeff_remnant( ofs )                       \+    { stbir__simdf d;                                       \+    STBIR_SIMD_NO_UNROLL(decode);                           \+    stbir__simdf_load2z( cs, hc + (ofs) );                  \+    stbir__simdf_0123to0001( c, cs );                       \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \+    stbir__simdf_0123to1122( c, cs );                       \+    stbir__simdf_load2z( d, decode+(ofs)*3+4 );             \+    stbir__simdf_madd( tot1, tot1, c, d ); }++#define stbir__3_coeff_remnant( ofs )                         \+    { stbir__simdf d;                                         \+    STBIR_SIMD_NO_UNROLL(decode);                             \+    stbir__simdf_load( cs, hc + (ofs) );                      \+    stbir__simdf_0123to0001( c, cs );                         \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 );   \+    stbir__simdf_0123to1122( c, cs );                         \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \+    stbir__simdf_0123to2222( c, cs );                         \+    stbir__simdf_load1z( d, decode+(ofs)*3+8 );               \+    stbir__simdf_madd( tot2, tot2, c, d );  }++#define stbir__store_output()                       \+    stbir__simdf_0123ABCDto3ABx( c, tot0, tot1 );   \+    stbir__simdf_0123ABCDto23Ax( cs, tot1, tot2 );  \+    stbir__simdf_0123to1230( tot2, tot2 );          \+    stbir__simdf_add( tot0, tot0, cs );             \+    stbir__simdf_add( c, c, tot2 );                 \+    stbir__simdf_add( tot0, tot0, c );              \+    horizontal_coefficients += coefficient_width;   \+    ++horizontal_contributors;                      \+    output += 3;                                    \+    if ( output < output_end )                      \+    {                                               \+      stbir__simdf_store( output-3, tot0 );         \+      continue;                                     \+    }                                               \+    stbir__simdf_0123to2301( tot1, tot0 );          \+    stbir__simdf_store2( output-3, tot0 );          \+    stbir__simdf_store1( output+2-3, tot1 );        \+    break;++#endif++#else++#define stbir__1_coeff_only()  \+    float tot0, tot1, tot2, c; \+    c = hc[0];                 \+    tot0 = decode[0]*c;        \+    tot1 = decode[1]*c;        \+    tot2 = decode[2]*c;++#define stbir__2_coeff_only()  \+    float tot0, tot1, tot2, c; \+    c = hc[0];                 \+    tot0 = decode[0]*c;        \+    tot1 = decode[1]*c;        \+    tot2 = decode[2]*c;        \+    c = hc[1];                 \+    tot0 += decode[3]*c;       \+    tot1 += decode[4]*c;       \+    tot2 += decode[5]*c;++#define stbir__3_coeff_only()  \+    float tot0, tot1, tot2, c; \+    c = hc[0];                 \+    tot0 = decode[0]*c;        \+    tot1 = decode[1]*c;        \+    tot2 = decode[2]*c;        \+    c = hc[1];                 \+    tot0 += decode[3]*c;       \+    tot1 += decode[4]*c;       \+    tot2 += decode[5]*c;       \+    c = hc[2];                 \+    tot0 += decode[6]*c;       \+    tot1 += decode[7]*c;       \+    tot2 += decode[8]*c;++#define stbir__store_output_tiny()                \+    output[0] = tot0;                             \+    output[1] = tot1;                             \+    output[2] = tot2;                             \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 3;++#define stbir__4_coeff_start()      \+    float tota0,tota1,tota2,totb0,totb1,totb2,totc0,totc1,totc2,totd0,totd1,totd2,c;  \+    c = hc[0];                      \+    tota0 = decode[0]*c;            \+    tota1 = decode[1]*c;            \+    tota2 = decode[2]*c;            \+    c = hc[1];                      \+    totb0 = decode[3]*c;            \+    totb1 = decode[4]*c;            \+    totb2 = decode[5]*c;            \+    c = hc[2];                      \+    totc0 = decode[6]*c;            \+    totc1 = decode[7]*c;            \+    totc2 = decode[8]*c;            \+    c = hc[3];                      \+    totd0 = decode[9]*c;            \+    totd1 = decode[10]*c;           \+    totd2 = decode[11]*c;++#define stbir__4_coeff_continue_from_4( ofs )  \+    c = hc[0+(ofs)];                           \+    tota0 += decode[0+(ofs)*3]*c;              \+    tota1 += decode[1+(ofs)*3]*c;              \+    tota2 += decode[2+(ofs)*3]*c;              \+    c = hc[1+(ofs)];                           \+    totb0 += decode[3+(ofs)*3]*c;              \+    totb1 += decode[4+(ofs)*3]*c;              \+    totb2 += decode[5+(ofs)*3]*c;              \+    c = hc[2+(ofs)];                           \+    totc0 += decode[6+(ofs)*3]*c;              \+    totc1 += decode[7+(ofs)*3]*c;              \+    totc2 += decode[8+(ofs)*3]*c;              \+    c = hc[3+(ofs)];                           \+    totd0 += decode[9+(ofs)*3]*c;              \+    totd1 += decode[10+(ofs)*3]*c;             \+    totd2 += decode[11+(ofs)*3]*c;++#define stbir__1_coeff_remnant( ofs )  \+    c = hc[0+(ofs)];                   \+    tota0 += decode[0+(ofs)*3]*c;      \+    tota1 += decode[1+(ofs)*3]*c;      \+    tota2 += decode[2+(ofs)*3]*c;++#define stbir__2_coeff_remnant( ofs )  \+    c = hc[0+(ofs)];                   \+    tota0 += decode[0+(ofs)*3]*c;      \+    tota1 += decode[1+(ofs)*3]*c;      \+    tota2 += decode[2+(ofs)*3]*c;      \+    c = hc[1+(ofs)];                   \+    totb0 += decode[3+(ofs)*3]*c;      \+    totb1 += decode[4+(ofs)*3]*c;      \+    totb2 += decode[5+(ofs)*3]*c;      \++#define stbir__3_coeff_remnant( ofs )  \+    c = hc[0+(ofs)];                   \+    tota0 += decode[0+(ofs)*3]*c;      \+    tota1 += decode[1+(ofs)*3]*c;      \+    tota2 += decode[2+(ofs)*3]*c;      \+    c = hc[1+(ofs)];                   \+    totb0 += decode[3+(ofs)*3]*c;      \+    totb1 += decode[4+(ofs)*3]*c;      \+    totb2 += decode[5+(ofs)*3]*c;      \+    c = hc[2+(ofs)];                   \+    totc0 += decode[6+(ofs)*3]*c;      \+    totc1 += decode[7+(ofs)*3]*c;      \+    totc2 += decode[8+(ofs)*3]*c;++#define stbir__store_output()                     \+    output[0] = (tota0+totc0)+(totb0+totd0);      \+    output[1] = (tota1+totc1)+(totb1+totd1);      \+    output[2] = (tota2+totc2)+(totb2+totd2);      \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 3;++#endif++#define STBIR__horizontal_channels 3+#define STB_IMAGE_RESIZE_DO_HORIZONTALS+#include STBIR__HEADER_FILENAME++//=================+// Do 4 channel horizontal routines++#ifdef STBIR_SIMD++#define stbir__1_coeff_only()             \+    stbir__simdf tot,c;                   \+    STBIR_SIMD_NO_UNROLL(decode);         \+    stbir__simdf_load1( c, hc );          \+    stbir__simdf_0123to0000( c, c );      \+    stbir__simdf_mult_mem( tot, c, decode );++#define stbir__2_coeff_only()                       \+    stbir__simdf tot,c,cs;                          \+    STBIR_SIMD_NO_UNROLL(decode);                   \+    stbir__simdf_load2( cs, hc );                   \+    stbir__simdf_0123to0000( c, cs );               \+    stbir__simdf_mult_mem( tot, c, decode );        \+    stbir__simdf_0123to1111( c, cs );               \+    stbir__simdf_madd_mem( tot, tot, c, decode+4 );++#define stbir__3_coeff_only()                       \+    stbir__simdf tot,c,cs;                          \+    STBIR_SIMD_NO_UNROLL(decode);                   \+    stbir__simdf_load( cs, hc );                    \+    stbir__simdf_0123to0000( c, cs );               \+    stbir__simdf_mult_mem( tot, c, decode );        \+    stbir__simdf_0123to1111( c, cs );               \+    stbir__simdf_madd_mem( tot, tot, c, decode+4 ); \+    stbir__simdf_0123to2222( c, cs );               \+    stbir__simdf_madd_mem( tot, tot, c, decode+8 );++#define stbir__store_output_tiny()                \+    stbir__simdf_store( output, tot );            \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 4;++#ifdef STBIR_SIMD8++#define stbir__4_coeff_start()                     \+    stbir__simdf8 tot0,c,cs; stbir__simdf t;  \+    STBIR_SIMD_NO_UNROLL(decode);                  \+    stbir__simdf8_load4b( cs, hc );                \+    stbir__simdf8_0123to00001111( c, cs );         \+    stbir__simdf8_mult_mem( tot0, c, decode );     \+    stbir__simdf8_0123to22223333( c, cs );         \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+8 );++#define stbir__4_coeff_continue_from_4( ofs )                  \+    STBIR_SIMD_NO_UNROLL(decode);                              \+    stbir__simdf8_load4b( cs, hc + (ofs) );                    \+    stbir__simdf8_0123to00001111( c, cs );                     \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 );   \+    stbir__simdf8_0123to22223333( c, cs );                     \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 );++#define stbir__1_coeff_remnant( ofs )                          \+    STBIR_SIMD_NO_UNROLL(decode);                              \+    stbir__simdf_load1rep4( t, hc + (ofs) );                   \+    stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4 );++#define stbir__2_coeff_remnant( ofs )                          \+    STBIR_SIMD_NO_UNROLL(decode);                              \+    stbir__simdf8_load4b( cs, hc + (ofs) - 2 );                \+    stbir__simdf8_0123to22223333( c, cs );                     \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 );++ #define stbir__3_coeff_remnant( ofs )                         \+    STBIR_SIMD_NO_UNROLL(decode);                              \+    stbir__simdf8_load4b( cs, hc + (ofs) );                    \+    stbir__simdf8_0123to00001111( c, cs );                     \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 );   \+    stbir__simdf8_0123to2222( t, cs );                         \+    stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4+8 );++#define stbir__store_output()                      \+    stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 );     \+    stbir__simdf_store( output, t );               \+    horizontal_coefficients += coefficient_width;  \+    ++horizontal_contributors;                     \+    output += 4;++#else++#define stbir__4_coeff_start()                        \+    stbir__simdf tot0,tot1,c,cs;                      \+    STBIR_SIMD_NO_UNROLL(decode);                     \+    stbir__simdf_load( cs, hc );                      \+    stbir__simdf_0123to0000( c, cs );                 \+    stbir__simdf_mult_mem( tot0, c, decode );         \+    stbir__simdf_0123to1111( c, cs );                 \+    stbir__simdf_mult_mem( tot1, c, decode+4 );       \+    stbir__simdf_0123to2222( c, cs );                 \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+8 ); \+    stbir__simdf_0123to3333( c, cs );                 \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+12 );++#define stbir__4_coeff_continue_from_4( ofs )                  \+    STBIR_SIMD_NO_UNROLL(decode);                              \+    stbir__simdf_load( cs, hc + (ofs) );                       \+    stbir__simdf_0123to0000( c, cs );                          \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 );    \+    stbir__simdf_0123to1111( c, cs );                          \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 );  \+    stbir__simdf_0123to2222( c, cs );                          \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 );  \+    stbir__simdf_0123to3333( c, cs );                          \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+12 );++#define stbir__1_coeff_remnant( ofs )                       \+    STBIR_SIMD_NO_UNROLL(decode);                           \+    stbir__simdf_load1( c, hc + (ofs) );                    \+    stbir__simdf_0123to0000( c, c );                        \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 );++#define stbir__2_coeff_remnant( ofs )                         \+    STBIR_SIMD_NO_UNROLL(decode);                             \+    stbir__simdf_load2( cs, hc + (ofs) );                     \+    stbir__simdf_0123to0000( c, cs );                         \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 );   \+    stbir__simdf_0123to1111( c, cs );                         \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 );++#define stbir__3_coeff_remnant( ofs )                          \+    STBIR_SIMD_NO_UNROLL(decode);                              \+    stbir__simdf_load( cs, hc + (ofs) );                       \+    stbir__simdf_0123to0000( c, cs );                          \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 );    \+    stbir__simdf_0123to1111( c, cs );                          \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 );  \+    stbir__simdf_0123to2222( c, cs );                          \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 );++#define stbir__store_output()                     \+    stbir__simdf_add( tot0, tot0, tot1 );         \+    stbir__simdf_store( output, tot0 );           \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 4;++#endif++#else++#define stbir__1_coeff_only()         \+    float p0,p1,p2,p3,c;              \+    STBIR_SIMD_NO_UNROLL(decode);     \+    c = hc[0];                        \+    p0 = decode[0] * c;               \+    p1 = decode[1] * c;               \+    p2 = decode[2] * c;               \+    p3 = decode[3] * c;++#define stbir__2_coeff_only()         \+    float p0,p1,p2,p3,c;              \+    STBIR_SIMD_NO_UNROLL(decode);     \+    c = hc[0];                        \+    p0 = decode[0] * c;               \+    p1 = decode[1] * c;               \+    p2 = decode[2] * c;               \+    p3 = decode[3] * c;               \+    c = hc[1];                        \+    p0 += decode[4] * c;              \+    p1 += decode[5] * c;              \+    p2 += decode[6] * c;              \+    p3 += decode[7] * c;++#define stbir__3_coeff_only()         \+    float p0,p1,p2,p3,c;              \+    STBIR_SIMD_NO_UNROLL(decode);     \+    c = hc[0];                        \+    p0 = decode[0] * c;               \+    p1 = decode[1] * c;               \+    p2 = decode[2] * c;               \+    p3 = decode[3] * c;               \+    c = hc[1];                        \+    p0 += decode[4] * c;              \+    p1 += decode[5] * c;              \+    p2 += decode[6] * c;              \+    p3 += decode[7] * c;              \+    c = hc[2];                        \+    p0 += decode[8] * c;              \+    p1 += decode[9] * c;              \+    p2 += decode[10] * c;             \+    p3 += decode[11] * c;++#define stbir__store_output_tiny()                \+    output[0] = p0;                               \+    output[1] = p1;                               \+    output[2] = p2;                               \+    output[3] = p3;                               \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 4;++#define stbir__4_coeff_start()        \+    float x0,x1,x2,x3,y0,y1,y2,y3,c;  \+    STBIR_SIMD_NO_UNROLL(decode);     \+    c = hc[0];                        \+    x0 = decode[0] * c;               \+    x1 = decode[1] * c;               \+    x2 = decode[2] * c;               \+    x3 = decode[3] * c;               \+    c = hc[1];                        \+    y0 = decode[4] * c;               \+    y1 = decode[5] * c;               \+    y2 = decode[6] * c;               \+    y3 = decode[7] * c;               \+    c = hc[2];                        \+    x0 += decode[8] * c;              \+    x1 += decode[9] * c;              \+    x2 += decode[10] * c;             \+    x3 += decode[11] * c;             \+    c = hc[3];                        \+    y0 += decode[12] * c;             \+    y1 += decode[13] * c;             \+    y2 += decode[14] * c;             \+    y3 += decode[15] * c;++#define stbir__4_coeff_continue_from_4( ofs ) \+    STBIR_SIMD_NO_UNROLL(decode);     \+    c = hc[0+(ofs)];                  \+    x0 += decode[0+(ofs)*4] * c;      \+    x1 += decode[1+(ofs)*4] * c;      \+    x2 += decode[2+(ofs)*4] * c;      \+    x3 += decode[3+(ofs)*4] * c;      \+    c = hc[1+(ofs)];                  \+    y0 += decode[4+(ofs)*4] * c;      \+    y1 += decode[5+(ofs)*4] * c;      \+    y2 += decode[6+(ofs)*4] * c;      \+    y3 += decode[7+(ofs)*4] * c;      \+    c = hc[2+(ofs)];                  \+    x0 += decode[8+(ofs)*4] * c;      \+    x1 += decode[9+(ofs)*4] * c;      \+    x2 += decode[10+(ofs)*4] * c;     \+    x3 += decode[11+(ofs)*4] * c;     \+    c = hc[3+(ofs)];                  \+    y0 += decode[12+(ofs)*4] * c;     \+    y1 += decode[13+(ofs)*4] * c;     \+    y2 += decode[14+(ofs)*4] * c;     \+    y3 += decode[15+(ofs)*4] * c;++#define stbir__1_coeff_remnant( ofs ) \+    STBIR_SIMD_NO_UNROLL(decode);     \+    c = hc[0+(ofs)];                  \+    x0 += decode[0+(ofs)*4] * c;      \+    x1 += decode[1+(ofs)*4] * c;      \+    x2 += decode[2+(ofs)*4] * c;      \+    x3 += decode[3+(ofs)*4] * c;++#define stbir__2_coeff_remnant( ofs ) \+    STBIR_SIMD_NO_UNROLL(decode);     \+    c = hc[0+(ofs)];                  \+    x0 += decode[0+(ofs)*4] * c;      \+    x1 += decode[1+(ofs)*4] * c;      \+    x2 += decode[2+(ofs)*4] * c;      \+    x3 += decode[3+(ofs)*4] * c;      \+    c = hc[1+(ofs)];                  \+    y0 += decode[4+(ofs)*4] * c;      \+    y1 += decode[5+(ofs)*4] * c;      \+    y2 += decode[6+(ofs)*4] * c;      \+    y3 += decode[7+(ofs)*4] * c;++#define stbir__3_coeff_remnant( ofs ) \+    STBIR_SIMD_NO_UNROLL(decode);     \+    c = hc[0+(ofs)];                  \+    x0 += decode[0+(ofs)*4] * c;      \+    x1 += decode[1+(ofs)*4] * c;      \+    x2 += decode[2+(ofs)*4] * c;      \+    x3 += decode[3+(ofs)*4] * c;      \+    c = hc[1+(ofs)];                  \+    y0 += decode[4+(ofs)*4] * c;      \+    y1 += decode[5+(ofs)*4] * c;      \+    y2 += decode[6+(ofs)*4] * c;      \+    y3 += decode[7+(ofs)*4] * c;      \+    c = hc[2+(ofs)];                  \+    x0 += decode[8+(ofs)*4] * c;      \+    x1 += decode[9+(ofs)*4] * c;      \+    x2 += decode[10+(ofs)*4] * c;     \+    x3 += decode[11+(ofs)*4] * c;++#define stbir__store_output()                     \+    output[0] = x0 + y0;                          \+    output[1] = x1 + y1;                          \+    output[2] = x2 + y2;                          \+    output[3] = x3 + y3;                          \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 4;++#endif++#define STBIR__horizontal_channels 4+#define STB_IMAGE_RESIZE_DO_HORIZONTALS+#include STBIR__HEADER_FILENAME++++//=================+// Do 7 channel horizontal routines++#ifdef STBIR_SIMD++#define stbir__1_coeff_only()                   \+    stbir__simdf tot0,tot1,c;                   \+    STBIR_SIMD_NO_UNROLL(decode);               \+    stbir__simdf_load1( c, hc );                \+    stbir__simdf_0123to0000( c, c );            \+    stbir__simdf_mult_mem( tot0, c, decode );   \+    stbir__simdf_mult_mem( tot1, c, decode+3 );++#define stbir__2_coeff_only()                         \+    stbir__simdf tot0,tot1,c,cs;                      \+    STBIR_SIMD_NO_UNROLL(decode);                     \+    stbir__simdf_load2( cs, hc );                     \+    stbir__simdf_0123to0000( c, cs );                 \+    stbir__simdf_mult_mem( tot0, c, decode );         \+    stbir__simdf_mult_mem( tot1, c, decode+3 );       \+    stbir__simdf_0123to1111( c, cs );                 \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+7 ); \+    stbir__simdf_madd_mem( tot1, tot1, c,decode+10 );++#define stbir__3_coeff_only()                           \+    stbir__simdf tot0,tot1,c,cs;                        \+    STBIR_SIMD_NO_UNROLL(decode);                       \+    stbir__simdf_load( cs, hc );                        \+    stbir__simdf_0123to0000( c, cs );                   \+    stbir__simdf_mult_mem( tot0, c, decode );           \+    stbir__simdf_mult_mem( tot1, c, decode+3 );         \+    stbir__simdf_0123to1111( c, cs );                   \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+7 );   \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+10 );  \+    stbir__simdf_0123to2222( c, cs );                   \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+14 );  \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+17 );++#define stbir__store_output_tiny()                \+    stbir__simdf_store( output+3, tot1 );         \+    stbir__simdf_store( output, tot0 );           \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 7;++#ifdef STBIR_SIMD8++#define stbir__4_coeff_start()                     \+    stbir__simdf8 tot0,tot1,c,cs;                  \+    STBIR_SIMD_NO_UNROLL(decode);                  \+    stbir__simdf8_load4b( cs, hc );                \+    stbir__simdf8_0123to00000000( c, cs );         \+    stbir__simdf8_mult_mem( tot0, c, decode );     \+    stbir__simdf8_0123to11111111( c, cs );         \+    stbir__simdf8_mult_mem( tot1, c, decode+7 );   \+    stbir__simdf8_0123to22222222( c, cs );         \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+14 );  \+    stbir__simdf8_0123to33333333( c, cs );         \+    stbir__simdf8_madd_mem( tot1, tot1, c, decode+21 );++#define stbir__4_coeff_continue_from_4( ofs )                   \+    STBIR_SIMD_NO_UNROLL(decode);                               \+    stbir__simdf8_load4b( cs, hc + (ofs) );                     \+    stbir__simdf8_0123to00000000( c, cs );                      \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 );    \+    stbir__simdf8_0123to11111111( c, cs );                      \+    stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 );  \+    stbir__simdf8_0123to22222222( c, cs );                      \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \+    stbir__simdf8_0123to33333333( c, cs );                      \+    stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+21 );++#define stbir__1_coeff_remnant( ofs )                           \+    STBIR_SIMD_NO_UNROLL(decode);                               \+    stbir__simdf8_load1b( c, hc + (ofs) );                      \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 );++#define stbir__2_coeff_remnant( ofs )                           \+    STBIR_SIMD_NO_UNROLL(decode);                               \+    stbir__simdf8_load1b( c, hc + (ofs) );                      \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 );    \+    stbir__simdf8_load1b( c, hc + (ofs)+1 );                    \+    stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 );++#define stbir__3_coeff_remnant( ofs )                           \+    STBIR_SIMD_NO_UNROLL(decode);                               \+    stbir__simdf8_load4b( cs, hc + (ofs) );                     \+    stbir__simdf8_0123to00000000( c, cs );                      \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 );    \+    stbir__simdf8_0123to11111111( c, cs );                      \+    stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 );  \+    stbir__simdf8_0123to22222222( c, cs );                      \+    stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 );++#define stbir__store_output()                     \+    stbir__simdf8_add( tot0, tot0, tot1 );        \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 7;                                  \+    if ( output < output_end )                    \+    {                                             \+      stbir__simdf8_store( output-7, tot0 );      \+      continue;                                   \+    }                                             \+    stbir__simdf_store( output-7+3, stbir__simdf_swiz(stbir__simdf8_gettop4(tot0),0,0,1,2) ); \+    stbir__simdf_store( output-7, stbir__if_simdf8_cast_to_simdf4(tot0) );           \+    break;++#else++#define stbir__4_coeff_start()                    \+    stbir__simdf tot0,tot1,tot2,tot3,c,cs;        \+    STBIR_SIMD_NO_UNROLL(decode);                 \+    stbir__simdf_load( cs, hc );                  \+    stbir__simdf_0123to0000( c, cs );             \+    stbir__simdf_mult_mem( tot0, c, decode );     \+    stbir__simdf_mult_mem( tot1, c, decode+3 );   \+    stbir__simdf_0123to1111( c, cs );             \+    stbir__simdf_mult_mem( tot2, c, decode+7 );   \+    stbir__simdf_mult_mem( tot3, c, decode+10 );  \+    stbir__simdf_0123to2222( c, cs );             \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+14 );  \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+17 );  \+    stbir__simdf_0123to3333( c, cs );                   \+    stbir__simdf_madd_mem( tot2, tot2, c, decode+21 );  \+    stbir__simdf_madd_mem( tot3, tot3, c, decode+24 );++#define stbir__4_coeff_continue_from_4( ofs )                   \+    STBIR_SIMD_NO_UNROLL(decode);                               \+    stbir__simdf_load( cs, hc + (ofs) );                        \+    stbir__simdf_0123to0000( c, cs );                           \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 );     \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 );   \+    stbir__simdf_0123to1111( c, cs );                           \+    stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 );   \+    stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 );  \+    stbir__simdf_0123to2222( c, cs );                           \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 );  \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 );  \+    stbir__simdf_0123to3333( c, cs );                           \+    stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+21 );  \+    stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+24 );++#define stbir__1_coeff_remnant( ofs )                           \+    STBIR_SIMD_NO_UNROLL(decode);                               \+    stbir__simdf_load1( c, hc + (ofs) );                        \+    stbir__simdf_0123to0000( c, c );                            \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 );     \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 );   \++#define stbir__2_coeff_remnant( ofs )                           \+    STBIR_SIMD_NO_UNROLL(decode);                               \+    stbir__simdf_load2( cs, hc + (ofs) );                       \+    stbir__simdf_0123to0000( c, cs );                           \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 );     \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 );   \+    stbir__simdf_0123to1111( c, cs );                           \+    stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 );   \+    stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 );++#define stbir__3_coeff_remnant( ofs )                           \+    STBIR_SIMD_NO_UNROLL(decode);                               \+    stbir__simdf_load( cs, hc + (ofs) );                        \+    stbir__simdf_0123to0000( c, cs );                           \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 );     \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 );   \+    stbir__simdf_0123to1111( c, cs );                           \+    stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 );   \+    stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 );  \+    stbir__simdf_0123to2222( c, cs );                           \+    stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 );  \+    stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 );++#define stbir__store_output()                     \+    stbir__simdf_add( tot0, tot0, tot2 );         \+    stbir__simdf_add( tot1, tot1, tot3 );         \+    stbir__simdf_store( output+3, tot1 );         \+    stbir__simdf_store( output, tot0 );           \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 7;++#endif++#else++#define stbir__1_coeff_only()        \+    float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \+    c = hc[0];                       \+    tot0 = decode[0]*c;              \+    tot1 = decode[1]*c;              \+    tot2 = decode[2]*c;              \+    tot3 = decode[3]*c;              \+    tot4 = decode[4]*c;              \+    tot5 = decode[5]*c;              \+    tot6 = decode[6]*c;++#define stbir__2_coeff_only()        \+    float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \+    c = hc[0];                       \+    tot0 = decode[0]*c;              \+    tot1 = decode[1]*c;              \+    tot2 = decode[2]*c;              \+    tot3 = decode[3]*c;              \+    tot4 = decode[4]*c;              \+    tot5 = decode[5]*c;              \+    tot6 = decode[6]*c;              \+    c = hc[1];                       \+    tot0 += decode[7]*c;             \+    tot1 += decode[8]*c;             \+    tot2 += decode[9]*c;             \+    tot3 += decode[10]*c;            \+    tot4 += decode[11]*c;            \+    tot5 += decode[12]*c;            \+    tot6 += decode[13]*c;            \++#define stbir__3_coeff_only()        \+    float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \+    c = hc[0];                       \+    tot0 = decode[0]*c;              \+    tot1 = decode[1]*c;              \+    tot2 = decode[2]*c;              \+    tot3 = decode[3]*c;              \+    tot4 = decode[4]*c;              \+    tot5 = decode[5]*c;              \+    tot6 = decode[6]*c;              \+    c = hc[1];                       \+    tot0 += decode[7]*c;             \+    tot1 += decode[8]*c;             \+    tot2 += decode[9]*c;             \+    tot3 += decode[10]*c;            \+    tot4 += decode[11]*c;            \+    tot5 += decode[12]*c;            \+    tot6 += decode[13]*c;            \+    c = hc[2];                       \+    tot0 += decode[14]*c;            \+    tot1 += decode[15]*c;            \+    tot2 += decode[16]*c;            \+    tot3 += decode[17]*c;            \+    tot4 += decode[18]*c;            \+    tot5 += decode[19]*c;            \+    tot6 += decode[20]*c;            \++#define stbir__store_output_tiny()                \+    output[0] = tot0;                             \+    output[1] = tot1;                             \+    output[2] = tot2;                             \+    output[3] = tot3;                             \+    output[4] = tot4;                             \+    output[5] = tot5;                             \+    output[6] = tot6;                             \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 7;++#define stbir__4_coeff_start()    \+    float x0,x1,x2,x3,x4,x5,x6,y0,y1,y2,y3,y4,y5,y6,c; \+    STBIR_SIMD_NO_UNROLL(decode); \+    c = hc[0];                    \+    x0 = decode[0] * c;           \+    x1 = decode[1] * c;           \+    x2 = decode[2] * c;           \+    x3 = decode[3] * c;           \+    x4 = decode[4] * c;           \+    x5 = decode[5] * c;           \+    x6 = decode[6] * c;           \+    c = hc[1];                    \+    y0 = decode[7] * c;           \+    y1 = decode[8] * c;           \+    y2 = decode[9] * c;           \+    y3 = decode[10] * c;          \+    y4 = decode[11] * c;          \+    y5 = decode[12] * c;          \+    y6 = decode[13] * c;          \+    c = hc[2];                    \+    x0 += decode[14] * c;         \+    x1 += decode[15] * c;         \+    x2 += decode[16] * c;         \+    x3 += decode[17] * c;         \+    x4 += decode[18] * c;         \+    x5 += decode[19] * c;         \+    x6 += decode[20] * c;         \+    c = hc[3];                    \+    y0 += decode[21] * c;         \+    y1 += decode[22] * c;         \+    y2 += decode[23] * c;         \+    y3 += decode[24] * c;         \+    y4 += decode[25] * c;         \+    y5 += decode[26] * c;         \+    y6 += decode[27] * c;++#define stbir__4_coeff_continue_from_4( ofs ) \+    STBIR_SIMD_NO_UNROLL(decode);  \+    c = hc[0+(ofs)];               \+    x0 += decode[0+(ofs)*7] * c;   \+    x1 += decode[1+(ofs)*7] * c;   \+    x2 += decode[2+(ofs)*7] * c;   \+    x3 += decode[3+(ofs)*7] * c;   \+    x4 += decode[4+(ofs)*7] * c;   \+    x5 += decode[5+(ofs)*7] * c;   \+    x6 += decode[6+(ofs)*7] * c;   \+    c = hc[1+(ofs)];               \+    y0 += decode[7+(ofs)*7] * c;   \+    y1 += decode[8+(ofs)*7] * c;   \+    y2 += decode[9+(ofs)*7] * c;   \+    y3 += decode[10+(ofs)*7] * c;  \+    y4 += decode[11+(ofs)*7] * c;  \+    y5 += decode[12+(ofs)*7] * c;  \+    y6 += decode[13+(ofs)*7] * c;  \+    c = hc[2+(ofs)];               \+    x0 += decode[14+(ofs)*7] * c;  \+    x1 += decode[15+(ofs)*7] * c;  \+    x2 += decode[16+(ofs)*7] * c;  \+    x3 += decode[17+(ofs)*7] * c;  \+    x4 += decode[18+(ofs)*7] * c;  \+    x5 += decode[19+(ofs)*7] * c;  \+    x6 += decode[20+(ofs)*7] * c;  \+    c = hc[3+(ofs)];               \+    y0 += decode[21+(ofs)*7] * c;  \+    y1 += decode[22+(ofs)*7] * c;  \+    y2 += decode[23+(ofs)*7] * c;  \+    y3 += decode[24+(ofs)*7] * c;  \+    y4 += decode[25+(ofs)*7] * c;  \+    y5 += decode[26+(ofs)*7] * c;  \+    y6 += decode[27+(ofs)*7] * c;++#define stbir__1_coeff_remnant( ofs ) \+    STBIR_SIMD_NO_UNROLL(decode);  \+    c = hc[0+(ofs)];               \+    x0 += decode[0+(ofs)*7] * c;   \+    x1 += decode[1+(ofs)*7] * c;   \+    x2 += decode[2+(ofs)*7] * c;   \+    x3 += decode[3+(ofs)*7] * c;   \+    x4 += decode[4+(ofs)*7] * c;   \+    x5 += decode[5+(ofs)*7] * c;   \+    x6 += decode[6+(ofs)*7] * c;   \++#define stbir__2_coeff_remnant( ofs ) \+    STBIR_SIMD_NO_UNROLL(decode);  \+    c = hc[0+(ofs)];               \+    x0 += decode[0+(ofs)*7] * c;   \+    x1 += decode[1+(ofs)*7] * c;   \+    x2 += decode[2+(ofs)*7] * c;   \+    x3 += decode[3+(ofs)*7] * c;   \+    x4 += decode[4+(ofs)*7] * c;   \+    x5 += decode[5+(ofs)*7] * c;   \+    x6 += decode[6+(ofs)*7] * c;   \+    c = hc[1+(ofs)];               \+    y0 += decode[7+(ofs)*7] * c;   \+    y1 += decode[8+(ofs)*7] * c;   \+    y2 += decode[9+(ofs)*7] * c;   \+    y3 += decode[10+(ofs)*7] * c;  \+    y4 += decode[11+(ofs)*7] * c;  \+    y5 += decode[12+(ofs)*7] * c;  \+    y6 += decode[13+(ofs)*7] * c;  \++#define stbir__3_coeff_remnant( ofs ) \+    STBIR_SIMD_NO_UNROLL(decode);  \+    c = hc[0+(ofs)];               \+    x0 += decode[0+(ofs)*7] * c;   \+    x1 += decode[1+(ofs)*7] * c;   \+    x2 += decode[2+(ofs)*7] * c;   \+    x3 += decode[3+(ofs)*7] * c;   \+    x4 += decode[4+(ofs)*7] * c;   \+    x5 += decode[5+(ofs)*7] * c;   \+    x6 += decode[6+(ofs)*7] * c;   \+    c = hc[1+(ofs)];               \+    y0 += decode[7+(ofs)*7] * c;   \+    y1 += decode[8+(ofs)*7] * c;   \+    y2 += decode[9+(ofs)*7] * c;   \+    y3 += decode[10+(ofs)*7] * c;  \+    y4 += decode[11+(ofs)*7] * c;  \+    y5 += decode[12+(ofs)*7] * c;  \+    y6 += decode[13+(ofs)*7] * c;  \+    c = hc[2+(ofs)];               \+    x0 += decode[14+(ofs)*7] * c;  \+    x1 += decode[15+(ofs)*7] * c;  \+    x2 += decode[16+(ofs)*7] * c;  \+    x3 += decode[17+(ofs)*7] * c;  \+    x4 += decode[18+(ofs)*7] * c;  \+    x5 += decode[19+(ofs)*7] * c;  \+    x6 += decode[20+(ofs)*7] * c;  \++#define stbir__store_output()                     \+    output[0] = x0 + y0;                          \+    output[1] = x1 + y1;                          \+    output[2] = x2 + y2;                          \+    output[3] = x3 + y3;                          \+    output[4] = x4 + y4;                          \+    output[5] = x5 + y5;                          \+    output[6] = x6 + y6;                          \+    horizontal_coefficients += coefficient_width; \+    ++horizontal_contributors;                    \+    output += 7;++#endif++#define STBIR__horizontal_channels 7+#define STB_IMAGE_RESIZE_DO_HORIZONTALS+#include STBIR__HEADER_FILENAME+++// include all of the vertical resamplers (both scatter and gather versions)++#define STBIR__vertical_channels 1+#define STB_IMAGE_RESIZE_DO_VERTICALS+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 1+#define STB_IMAGE_RESIZE_DO_VERTICALS+#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 2+#define STB_IMAGE_RESIZE_DO_VERTICALS+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 2+#define STB_IMAGE_RESIZE_DO_VERTICALS+#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 3+#define STB_IMAGE_RESIZE_DO_VERTICALS+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 3+#define STB_IMAGE_RESIZE_DO_VERTICALS+#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 4+#define STB_IMAGE_RESIZE_DO_VERTICALS+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 4+#define STB_IMAGE_RESIZE_DO_VERTICALS+#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 5+#define STB_IMAGE_RESIZE_DO_VERTICALS+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 5+#define STB_IMAGE_RESIZE_DO_VERTICALS+#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 6+#define STB_IMAGE_RESIZE_DO_VERTICALS+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 6+#define STB_IMAGE_RESIZE_DO_VERTICALS+#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 7+#define STB_IMAGE_RESIZE_DO_VERTICALS+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 7+#define STB_IMAGE_RESIZE_DO_VERTICALS+#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 8+#define STB_IMAGE_RESIZE_DO_VERTICALS+#include STBIR__HEADER_FILENAME++#define STBIR__vertical_channels 8+#define STB_IMAGE_RESIZE_DO_VERTICALS+#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#include STBIR__HEADER_FILENAME++typedef void STBIR_VERTICAL_GATHERFUNC( float * output, float const * coeffs, float const ** inputs, float const * input0_end );++static STBIR_VERTICAL_GATHERFUNC * stbir__vertical_gathers[ 8 ] =+{+  stbir__vertical_gather_with_1_coeffs,stbir__vertical_gather_with_2_coeffs,stbir__vertical_gather_with_3_coeffs,stbir__vertical_gather_with_4_coeffs,stbir__vertical_gather_with_5_coeffs,stbir__vertical_gather_with_6_coeffs,stbir__vertical_gather_with_7_coeffs,stbir__vertical_gather_with_8_coeffs+};++static STBIR_VERTICAL_GATHERFUNC * stbir__vertical_gathers_continues[ 8 ] =+{+  stbir__vertical_gather_with_1_coeffs_cont,stbir__vertical_gather_with_2_coeffs_cont,stbir__vertical_gather_with_3_coeffs_cont,stbir__vertical_gather_with_4_coeffs_cont,stbir__vertical_gather_with_5_coeffs_cont,stbir__vertical_gather_with_6_coeffs_cont,stbir__vertical_gather_with_7_coeffs_cont,stbir__vertical_gather_with_8_coeffs_cont+};++typedef void STBIR_VERTICAL_SCATTERFUNC( float ** outputs, float const * coeffs, float const * input, float const * input_end );++static STBIR_VERTICAL_SCATTERFUNC * stbir__vertical_scatter_sets[ 8 ] =+{+  stbir__vertical_scatter_with_1_coeffs,stbir__vertical_scatter_with_2_coeffs,stbir__vertical_scatter_with_3_coeffs,stbir__vertical_scatter_with_4_coeffs,stbir__vertical_scatter_with_5_coeffs,stbir__vertical_scatter_with_6_coeffs,stbir__vertical_scatter_with_7_coeffs,stbir__vertical_scatter_with_8_coeffs+};++static STBIR_VERTICAL_SCATTERFUNC * stbir__vertical_scatter_blends[ 8 ] =+{+  stbir__vertical_scatter_with_1_coeffs_cont,stbir__vertical_scatter_with_2_coeffs_cont,stbir__vertical_scatter_with_3_coeffs_cont,stbir__vertical_scatter_with_4_coeffs_cont,stbir__vertical_scatter_with_5_coeffs_cont,stbir__vertical_scatter_with_6_coeffs_cont,stbir__vertical_scatter_with_7_coeffs_cont,stbir__vertical_scatter_with_8_coeffs_cont+};+++static void stbir__encode_scanline( stbir__info const * stbir_info, void *output_buffer_data, float * encode_buffer, int row  STBIR_ONLY_PROFILE_GET_SPLIT_INFO )+{+  int num_pixels = stbir_info->horizontal.scale_info.output_sub_size;+  int channels = stbir_info->channels;+  int width_times_channels = num_pixels * channels;+  void * output_buffer;++  // un-alpha weight if we need to+  if ( stbir_info->alpha_unweight )+  {+    STBIR_PROFILE_START( unalpha );+    stbir_info->alpha_unweight( encode_buffer, width_times_channels );+    STBIR_PROFILE_END( unalpha );+  }++  // write directly into output by default+  output_buffer = output_buffer_data;++  // if we have an output callback, we first convert the decode buffer in place (and then hand that to the callback)+  if ( stbir_info->out_pixels_cb )+    output_buffer = encode_buffer;++  STBIR_PROFILE_START( encode );+  // convert into the output buffer+  stbir_info->encode_pixels( output_buffer, width_times_channels, encode_buffer );+  STBIR_PROFILE_END( encode );++  // if we have an output callback, call it to send the data+  if ( stbir_info->out_pixels_cb )+    stbir_info->out_pixels_cb( output_buffer, num_pixels, row, stbir_info->user_data );+}+++// Get the ring buffer pointer for an index+static float* stbir__get_ring_buffer_entry(stbir__info const * stbir_info, stbir__per_split_info const * split_info, int index )+{+  STBIR_ASSERT( index < stbir_info->ring_buffer_num_entries );++  #ifdef STBIR__SEPARATE_ALLOCATIONS+    return split_info->ring_buffers[ index ];+  #else+    return (float*) ( ( (char*) split_info->ring_buffer ) + ( index * stbir_info->ring_buffer_length_bytes ) );+  #endif+}++// Get the specified scan line from the ring buffer+static float* stbir__get_ring_buffer_scanline(stbir__info const * stbir_info, stbir__per_split_info const * split_info, int get_scanline)+{+  int ring_buffer_index = (split_info->ring_buffer_begin_index + (get_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries;+  return stbir__get_ring_buffer_entry( stbir_info, split_info, ring_buffer_index );+}++static void stbir__resample_horizontal_gather(stbir__info const * stbir_info, float* output_buffer, float const * input_buffer STBIR_ONLY_PROFILE_GET_SPLIT_INFO )+{+  float const * decode_buffer = input_buffer - ( stbir_info->scanline_extents.conservative.n0 * stbir_info->effective_channels );++  STBIR_PROFILE_START( horizontal );+  if ( ( stbir_info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( stbir_info->horizontal.scale_info.scale == 1.0f ) )+    STBIR_MEMCPY( output_buffer, input_buffer, stbir_info->horizontal.scale_info.output_sub_size * sizeof( float ) * stbir_info->effective_channels );+  else+    stbir_info->horizontal_gather_channels( output_buffer, stbir_info->horizontal.scale_info.output_sub_size, decode_buffer, stbir_info->horizontal.contributors, stbir_info->horizontal.coefficients, stbir_info->horizontal.coefficient_width );+  STBIR_PROFILE_END( horizontal );+}++static void stbir__resample_vertical_gather(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n, int contrib_n0, int contrib_n1, float const * vertical_coefficients )+{+  float* encode_buffer = split_info->vertical_buffer;+  float* decode_buffer = split_info->decode_buffer;+  int vertical_first = stbir_info->vertical_first;+  int width = (vertical_first) ? ( stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1 ) : stbir_info->horizontal.scale_info.output_sub_size;+  int width_times_channels = stbir_info->effective_channels * width;++  STBIR_ASSERT( stbir_info->vertical.is_gather );++  // loop over the contributing scanlines and scale into the buffer+  STBIR_PROFILE_START( vertical );+  {+    int k = 0, total = contrib_n1 - contrib_n0 + 1;+    STBIR_ASSERT( total > 0 );+    do {+      float const * inputs[8];+      int i, cnt = total; if ( cnt > 8 ) cnt = 8;+      for( i = 0 ; i < cnt ; i++ )+        inputs[ i ] = stbir__get_ring_buffer_scanline(stbir_info, split_info, k+i+contrib_n0 );++      // call the N scanlines at a time function (up to 8 scanlines of blending at once)+      ((k==0)?stbir__vertical_gathers:stbir__vertical_gathers_continues)[cnt-1]( (vertical_first) ? decode_buffer : encode_buffer, vertical_coefficients + k, inputs, inputs[0] + width_times_channels );+      k += cnt;+      total -= cnt;+    } while ( total );+  }+  STBIR_PROFILE_END( vertical );++  if ( vertical_first )+  {+    // Now resample the gathered vertical data in the horizontal axis into the encode buffer+    stbir__resample_horizontal_gather(stbir_info, encode_buffer, decode_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );+  }++  stbir__encode_scanline( stbir_info, ( (char *) stbir_info->output_data ) + ((size_t)n * (size_t)stbir_info->output_stride_bytes),+                          encode_buffer, n  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );+}++static void stbir__decode_and_resample_for_vertical_gather_loop(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n)+{+  int ring_buffer_index;+  float* ring_buffer;++  // Decode the nth scanline from the source image into the decode buffer.+  stbir__decode_scanline( stbir_info, n, split_info->decode_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );++  // update new end scanline+  split_info->ring_buffer_last_scanline = n;++  // get ring buffer+  ring_buffer_index = (split_info->ring_buffer_begin_index + (split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries;+  ring_buffer = stbir__get_ring_buffer_entry(stbir_info, split_info, ring_buffer_index);++  // Now resample it into the ring buffer.+  stbir__resample_horizontal_gather( stbir_info, ring_buffer, split_info->decode_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );++  // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling.+}++static void stbir__vertical_gather_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count )+{+  int y, start_output_y, end_output_y;+  stbir__contributors* vertical_contributors = stbir_info->vertical.contributors;+  float const * vertical_coefficients = stbir_info->vertical.coefficients;++  STBIR_ASSERT( stbir_info->vertical.is_gather );++  start_output_y = split_info->start_output_y;+  end_output_y = split_info[split_count-1].end_output_y;++  vertical_contributors += start_output_y;+  vertical_coefficients += start_output_y * stbir_info->vertical.coefficient_width;++  // initialize the ring buffer for gathering+  split_info->ring_buffer_begin_index = 0;+  split_info->ring_buffer_first_scanline = vertical_contributors->n0;+  split_info->ring_buffer_last_scanline = split_info->ring_buffer_first_scanline - 1; // means "empty"++  for (y = start_output_y; y < end_output_y; y++)+  {+    int in_first_scanline, in_last_scanline;++    in_first_scanline = vertical_contributors->n0;+    in_last_scanline = vertical_contributors->n1;++    // make sure the indexing hasn't broken+    STBIR_ASSERT( in_first_scanline >= split_info->ring_buffer_first_scanline );++    // Load in new scanlines+    while (in_last_scanline > split_info->ring_buffer_last_scanline)+    {+      STBIR_ASSERT( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) <= stbir_info->ring_buffer_num_entries );++      // make sure there was room in the ring buffer when we add new scanlines+      if ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries )+      {+        split_info->ring_buffer_first_scanline++;+        split_info->ring_buffer_begin_index++;+      }++      if ( stbir_info->vertical_first )+      {+        float * ring_buffer = stbir__get_ring_buffer_scanline( stbir_info, split_info, ++split_info->ring_buffer_last_scanline );+        // Decode the nth scanline from the source image into the decode buffer.+        stbir__decode_scanline( stbir_info, split_info->ring_buffer_last_scanline, ring_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );+      }+      else+      {+        stbir__decode_and_resample_for_vertical_gather_loop(stbir_info, split_info, split_info->ring_buffer_last_scanline + 1);+      }+    }++    // Now all buffers should be ready to write a row of vertical sampling, so do it.+    stbir__resample_vertical_gather(stbir_info, split_info, y, in_first_scanline, in_last_scanline, vertical_coefficients );++    ++vertical_contributors;+    vertical_coefficients += stbir_info->vertical.coefficient_width;+  }+}++#define STBIR__FLOAT_EMPTY_MARKER 3.0e+38F+#define STBIR__FLOAT_BUFFER_IS_EMPTY(ptr) ((ptr)[0]==STBIR__FLOAT_EMPTY_MARKER)++static void stbir__encode_first_scanline_from_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info)+{+  // evict a scanline out into the output buffer+  float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index );++  // dump the scanline out+  stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (size_t)split_info->ring_buffer_first_scanline * (size_t)stbir_info->output_stride_bytes ), ring_buffer_entry, split_info->ring_buffer_first_scanline  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );++  // mark it as empty+  ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER;++  // advance the first scanline+  split_info->ring_buffer_first_scanline++;+  if ( ++split_info->ring_buffer_begin_index == stbir_info->ring_buffer_num_entries )+    split_info->ring_buffer_begin_index = 0;+}++static void stbir__horizontal_resample_and_encode_first_scanline_from_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info)+{+  // evict a scanline out into the output buffer++  float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index );++  // Now resample it into the buffer.+  stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, ring_buffer_entry  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );++  // dump the scanline out+  stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (size_t)split_info->ring_buffer_first_scanline * (size_t)stbir_info->output_stride_bytes ), split_info->vertical_buffer, split_info->ring_buffer_first_scanline  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );++  // mark it as empty+  ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER;++  // advance the first scanline+  split_info->ring_buffer_first_scanline++;+  if ( ++split_info->ring_buffer_begin_index == stbir_info->ring_buffer_num_entries )+    split_info->ring_buffer_begin_index = 0;+}++static void stbir__resample_vertical_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n0, int n1, float const * vertical_coefficients, float const * vertical_buffer, float const * vertical_buffer_end )+{+  STBIR_ASSERT( !stbir_info->vertical.is_gather );++  STBIR_PROFILE_START( vertical );+  {+    int k = 0, total = n1 - n0 + 1;+    STBIR_ASSERT( total > 0 );+    do {+      float * outputs[8];+      int i, n = total; if ( n > 8 ) n = 8;+      for( i = 0 ; i < n ; i++ )+      {+        outputs[ i ] = stbir__get_ring_buffer_scanline(stbir_info, split_info, k+i+n0 );+        if ( ( i ) && ( STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[i] ) != STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[0] ) ) ) // make sure runs are of the same type+        {+          n = i;+          break;+        }+      }+      // call the scatter to N scanlines at a time function (up to 8 scanlines of scattering at once)+      ((STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[0] ))?stbir__vertical_scatter_sets:stbir__vertical_scatter_blends)[n-1]( outputs, vertical_coefficients + k, vertical_buffer, vertical_buffer_end );+      k += n;+      total -= n;+    } while ( total );+  }++  STBIR_PROFILE_END( vertical );+}++typedef void stbir__handle_scanline_for_scatter_func(stbir__info const * stbir_info, stbir__per_split_info* split_info);++static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count )+{+  int y, start_output_y, end_output_y, start_input_y, end_input_y;+  stbir__contributors* vertical_contributors = stbir_info->vertical.contributors;+  float const * vertical_coefficients = stbir_info->vertical.coefficients;+  stbir__handle_scanline_for_scatter_func * handle_scanline_for_scatter;+  void * scanline_scatter_buffer;+  void * scanline_scatter_buffer_end;+  int on_first_input_y, last_input_y;++  STBIR_ASSERT( !stbir_info->vertical.is_gather );++  start_output_y = split_info->start_output_y;+  end_output_y = split_info[split_count-1].end_output_y;  // may do multiple split counts++  start_input_y = split_info->start_input_y;+  end_input_y = split_info[split_count-1].end_input_y;++  // adjust for starting offset start_input_y+  y = start_input_y + stbir_info->vertical.filter_pixel_margin;+  vertical_contributors += y ;+  vertical_coefficients += stbir_info->vertical.coefficient_width * y;++  if ( stbir_info->vertical_first )+  {+    handle_scanline_for_scatter = stbir__horizontal_resample_and_encode_first_scanline_from_scatter;+    scanline_scatter_buffer = split_info->decode_buffer;+    scanline_scatter_buffer_end = ( (char*) scanline_scatter_buffer ) + sizeof( float ) * stbir_info->effective_channels * (stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1);+  }+  else+  {+    handle_scanline_for_scatter = stbir__encode_first_scanline_from_scatter;+    scanline_scatter_buffer = split_info->vertical_buffer;+    scanline_scatter_buffer_end = ( (char*) scanline_scatter_buffer ) + sizeof( float ) * stbir_info->effective_channels * stbir_info->horizontal.scale_info.output_sub_size;+  }++  // initialize the ring buffer for scattering+  split_info->ring_buffer_first_scanline = start_output_y;+  split_info->ring_buffer_last_scanline = -1;+  split_info->ring_buffer_begin_index = -1;++  // mark all the buffers as empty to start+  for( y = 0 ; y < stbir_info->ring_buffer_num_entries ; y++ )+    stbir__get_ring_buffer_entry( stbir_info, split_info, y )[0] = STBIR__FLOAT_EMPTY_MARKER; // only used on scatter++  // do the loop in input space+  on_first_input_y = 1; last_input_y = start_input_y;+  for (y = start_input_y ; y < end_input_y; y++)+  {+    int out_first_scanline, out_last_scanline;++    out_first_scanline = vertical_contributors->n0;+    out_last_scanline = vertical_contributors->n1;++    STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);++    if ( ( out_last_scanline >= out_first_scanline ) && ( ( ( out_first_scanline >= start_output_y ) && ( out_first_scanline < end_output_y ) ) || ( ( out_last_scanline >= start_output_y ) && ( out_last_scanline < end_output_y ) ) ) )+    {+      float const * vc = vertical_coefficients;++      // keep track of the range actually seen for the next resize+      last_input_y = y;+      if ( ( on_first_input_y ) && ( y > start_input_y ) )+        split_info->start_input_y = y;+      on_first_input_y = 0;++      // clip the region+      if ( out_first_scanline < start_output_y )+      {+        vc += start_output_y - out_first_scanline;+        out_first_scanline = start_output_y;+      }++      if ( out_last_scanline >= end_output_y )+        out_last_scanline = end_output_y - 1;++      // if very first scanline, init the index+      if (split_info->ring_buffer_begin_index < 0)+        split_info->ring_buffer_begin_index = out_first_scanline - start_output_y;++      STBIR_ASSERT( split_info->ring_buffer_begin_index <= out_first_scanline );++      // Decode the nth scanline from the source image into the decode buffer.+      stbir__decode_scanline( stbir_info, y, split_info->decode_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );++      // When horizontal first, we resample horizontally into the vertical buffer before we scatter it out+      if ( !stbir_info->vertical_first )+        stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, split_info->decode_buffer  STBIR_ONLY_PROFILE_SET_SPLIT_INFO );++      // Now it's sitting in the buffer ready to be distributed into the ring buffers.++      // evict from the ringbuffer, if we need are full+      if ( ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries ) &&+           ( out_last_scanline > split_info->ring_buffer_last_scanline ) )+        handle_scanline_for_scatter( stbir_info, split_info );++      // Now the horizontal buffer is ready to write to all ring buffer rows, so do it.+      stbir__resample_vertical_scatter(stbir_info, split_info, out_first_scanline, out_last_scanline, vc, (float*)scanline_scatter_buffer, (float*)scanline_scatter_buffer_end );++      // update the end of the buffer+      if ( out_last_scanline > split_info->ring_buffer_last_scanline )+        split_info->ring_buffer_last_scanline = out_last_scanline;+    }+    ++vertical_contributors;+    vertical_coefficients += stbir_info->vertical.coefficient_width;+  }++  // now evict the scanlines that are left over in the ring buffer+  while ( split_info->ring_buffer_first_scanline < end_output_y )+    handle_scanline_for_scatter(stbir_info, split_info);++  // update the end_input_y if we do multiple resizes with the same data+  ++last_input_y;+  for( y = 0 ; y < split_count; y++ )+    if ( split_info[y].end_input_y > last_input_y )+      split_info[y].end_input_y = last_input_y;+}+++static stbir__kernel_callback * stbir__builtin_kernels[] =   { 0, stbir__filter_trapezoid,  stbir__filter_triangle, stbir__filter_cubic, stbir__filter_catmullrom, stbir__filter_mitchell, stbir__filter_point };+static stbir__support_callback * stbir__builtin_supports[] = { 0, stbir__support_trapezoid, stbir__support_one,     stbir__support_two,  stbir__support_two,       stbir__support_two,     stbir__support_zeropoint5 };++static void stbir__set_sampler(stbir__sampler * samp, stbir_filter filter, stbir__kernel_callback * kernel, stbir__support_callback * support, stbir_edge edge, stbir__scale_info * scale_info, int always_gather, void * user_data )+{+  // set filter+  if (filter == 0)+  {+    filter = STBIR_DEFAULT_FILTER_DOWNSAMPLE; // default to downsample+    if (scale_info->scale >= ( 1.0f - stbir__small_float ) )+    {+      if ( (scale_info->scale <= ( 1.0f + stbir__small_float ) ) && ( STBIR_CEILF(scale_info->pixel_shift) == scale_info->pixel_shift ) )+        filter = STBIR_FILTER_POINT_SAMPLE;+      else+        filter = STBIR_DEFAULT_FILTER_UPSAMPLE;+    }+  }+  samp->filter_enum = filter;++  STBIR_ASSERT(samp->filter_enum != 0);+  STBIR_ASSERT((unsigned)samp->filter_enum < STBIR_FILTER_OTHER);+  samp->filter_kernel = stbir__builtin_kernels[ filter ];+  samp->filter_support = stbir__builtin_supports[ filter ];++  if ( kernel && support )+  {+    samp->filter_kernel = kernel;+    samp->filter_support = support;+    samp->filter_enum = STBIR_FILTER_OTHER;+  }++  samp->edge = edge;+  samp->filter_pixel_width  = stbir__get_filter_pixel_width (samp->filter_support, scale_info->scale, user_data );+  // Gather is always better, but in extreme downsamples, you have to most or all of the data in memory+  //    For horizontal, we always have all the pixels, so we always use gather here (always_gather==1).+  //    For vertical, we use gather if scaling up (which means we will have samp->filter_pixel_width+  //    scanlines in memory at once).+  samp->is_gather = 0;+  if ( scale_info->scale >= ( 1.0f - stbir__small_float ) )+    samp->is_gather = 1;+  else if ( ( always_gather ) || ( samp->filter_pixel_width <= STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT ) )+    samp->is_gather = 2;++  // pre calculate stuff based on the above+  samp->coefficient_width = stbir__get_coefficient_width(samp, samp->is_gather, user_data);++  // filter_pixel_width is the conservative size in pixels of input that affect an output pixel.+  //   In rare cases (only with 2 pix to 1 pix with the default filters), it's possible that the +  //   filter will extend before or after the scanline beyond just one extra entire copy of the +  //   scanline (we would hit the edge twice). We don't let you do that, so we clamp the total +  //   width to 3x the total of input pixel (once for the scanline, once for the left side +  //   overhang, and once for the right side). We only do this for edge mode, since the other +  //   modes can just re-edge clamp back in again.+  if ( edge == STBIR_EDGE_WRAP )+    if ( samp->filter_pixel_width > ( scale_info->input_full_size * 3 ) )+      samp->filter_pixel_width = scale_info->input_full_size * 3;++  // This is how much to expand buffers to account for filters seeking outside+  // the image boundaries.+  samp->filter_pixel_margin = samp->filter_pixel_width / 2;+  +  // filter_pixel_margin is the amount that this filter can overhang on just one side of either +  //   end of the scanline (left or the right). Since we only allow you to overhang 1 scanline's +  //   worth of pixels, we clamp this one side of overhang to the input scanline size. Again, +  //   this clamping only happens in rare cases with the default filters (2 pix to 1 pix). +  if ( edge == STBIR_EDGE_WRAP )+    if ( samp->filter_pixel_margin > scale_info->input_full_size )+      samp->filter_pixel_margin = scale_info->input_full_size;++  samp->num_contributors = stbir__get_contributors(samp, samp->is_gather);++  samp->contributors_size = samp->num_contributors * sizeof(stbir__contributors);+  samp->coefficients_size = samp->num_contributors * samp->coefficient_width * sizeof(float) + sizeof(float); // extra sizeof(float) is padding++  samp->gather_prescatter_contributors = 0;+  samp->gather_prescatter_coefficients = 0;+  if ( samp->is_gather == 0 )+  {+    samp->gather_prescatter_coefficient_width = samp->filter_pixel_width;+    samp->gather_prescatter_num_contributors  = stbir__get_contributors(samp, 2);+    samp->gather_prescatter_contributors_size = samp->gather_prescatter_num_contributors * sizeof(stbir__contributors);+    samp->gather_prescatter_coefficients_size = samp->gather_prescatter_num_contributors * samp->gather_prescatter_coefficient_width * sizeof(float);+  }+}++static void stbir__get_conservative_extents( stbir__sampler * samp, stbir__contributors * range, void * user_data )+{+  float scale = samp->scale_info.scale;+  float out_shift = samp->scale_info.pixel_shift;+  stbir__support_callback * support = samp->filter_support;+  int input_full_size = samp->scale_info.input_full_size;+  stbir_edge edge = samp->edge;+  float inv_scale = samp->scale_info.inv_scale;++  STBIR_ASSERT( samp->is_gather != 0 );++  if ( samp->is_gather == 1 )+  {+    int in_first_pixel, in_last_pixel;+    float out_filter_radius = support(inv_scale, user_data) * scale;++    stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, 0.5, out_filter_radius, inv_scale, out_shift, input_full_size, edge );+    range->n0 = in_first_pixel;+    stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, ( (float)(samp->scale_info.output_sub_size-1) ) + 0.5f, out_filter_radius, inv_scale, out_shift, input_full_size, edge );+    range->n1 = in_last_pixel;+  }+  else if ( samp->is_gather == 2 ) // downsample gather, refine+  {+    float in_pixels_radius = support(scale, user_data) * inv_scale;+    int filter_pixel_margin = samp->filter_pixel_margin;+    int output_sub_size = samp->scale_info.output_sub_size;+    int input_end;+    int n;+    int in_first_pixel, in_last_pixel;++    // get a conservative area of the input range+    stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, 0, 0, inv_scale, out_shift, input_full_size, edge );+    range->n0 = in_first_pixel;+    stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, (float)output_sub_size, 0, inv_scale, out_shift, input_full_size, edge );+    range->n1 = in_last_pixel;++    // now go through the margin to the start of area to find bottom+    n = range->n0 + 1;+    input_end = -filter_pixel_margin;+    while( n >= input_end )+    {+      int out_first_pixel, out_last_pixel;+      stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, ((float)n)+0.5f, in_pixels_radius, scale, out_shift, output_sub_size );+      if ( out_first_pixel > out_last_pixel )+        break;++      if ( ( out_first_pixel < output_sub_size ) || ( out_last_pixel >= 0 ) )+        range->n0 = n;+      --n;+    }++    // now go through the end of the area through the margin to find top+    n = range->n1 - 1;+    input_end = n + 1 + filter_pixel_margin;+    while( n <= input_end )+    {+      int out_first_pixel, out_last_pixel;+      stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, ((float)n)+0.5f, in_pixels_radius, scale, out_shift, output_sub_size );+      if ( out_first_pixel > out_last_pixel )+        break;+      if ( ( out_first_pixel < output_sub_size ) || ( out_last_pixel >= 0 ) )+        range->n1 = n;+      ++n;+    }+  }++  if ( samp->edge == STBIR_EDGE_WRAP )+  {+    // if we are wrapping, and we are very close to the image size (so the edges might merge), just use the scanline up to the edge+    if ( ( range->n0 > 0 ) && ( range->n1 >= input_full_size ) )+    {+      int marg = range->n1 - input_full_size + 1;+      if ( ( marg + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= range->n0 )+        range->n0 = 0;+    }+    if ( ( range->n0 < 0 ) && ( range->n1 < (input_full_size-1) ) )+    {+      int marg = -range->n0;+      if ( ( input_full_size - marg - STBIR__MERGE_RUNS_PIXEL_THRESHOLD - 1 ) <= range->n1 )+        range->n1 = input_full_size - 1;+    }+  }+  else+  {+    // for non-edge-wrap modes, we never read over the edge, so clamp+    if ( range->n0 < 0 )+      range->n0 = 0;+    if ( range->n1 >= input_full_size )+      range->n1 = input_full_size - 1;+  }+}++static void stbir__get_split_info( stbir__per_split_info* split_info, int splits, int output_height, int vertical_pixel_margin, int input_full_height )+{+  int i, cur;+  int left = output_height;++  cur = 0;+  for( i = 0 ; i < splits ; i++ )+  {+    int each;+    split_info[i].start_output_y = cur;+    each = left / ( splits - i );+    split_info[i].end_output_y = cur + each;+    cur += each;+    left -= each;++    // scatter range (updated to minimum as you run it)+    split_info[i].start_input_y = -vertical_pixel_margin;+    split_info[i].end_input_y = input_full_height + vertical_pixel_margin;+  }+}++static void stbir__free_internal_mem( stbir__info *info )+{+  #define STBIR__FREE_AND_CLEAR( ptr ) { if ( ptr ) { void * p = (ptr); (ptr) = 0; STBIR_FREE( p, info->user_data); } }++  if ( info )+  {+  #ifndef STBIR__SEPARATE_ALLOCATIONS+    STBIR__FREE_AND_CLEAR( info->alloced_mem );+  #else+    int i,j;++    if ( ( info->vertical.gather_prescatter_contributors ) && ( (void*)info->vertical.gather_prescatter_contributors != (void*)info->split_info[0].decode_buffer ) )+    {+      STBIR__FREE_AND_CLEAR( info->vertical.gather_prescatter_coefficients );+      STBIR__FREE_AND_CLEAR( info->vertical.gather_prescatter_contributors );+    }+    for( i = 0 ; i < info->splits ; i++ )+    {+      for( j = 0 ; j < info->alloc_ring_buffer_num_entries ; j++ )+      {+        #ifdef STBIR_SIMD8+        if ( info->effective_channels == 3 )+          --info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer+        #endif+        STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers[j] );+      }++      #ifdef STBIR_SIMD8+      if ( info->effective_channels == 3 )+        --info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer+      #endif+      STBIR__FREE_AND_CLEAR( info->split_info[i].decode_buffer );+      STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers );+      STBIR__FREE_AND_CLEAR( info->split_info[i].vertical_buffer );+    }+    STBIR__FREE_AND_CLEAR( info->split_info );+    if ( info->vertical.coefficients != info->horizontal.coefficients )+    {+      STBIR__FREE_AND_CLEAR( info->vertical.coefficients );+      STBIR__FREE_AND_CLEAR( info->vertical.contributors );+    }+    STBIR__FREE_AND_CLEAR( info->horizontal.coefficients );+    STBIR__FREE_AND_CLEAR( info->horizontal.contributors );+    STBIR__FREE_AND_CLEAR( info->alloced_mem );+    STBIR__FREE_AND_CLEAR( info );+  #endif+  }++  #undef STBIR__FREE_AND_CLEAR+}++static int stbir__get_max_split( int splits, int height )+{+  int i;+  int max = 0;++  for( i = 0 ; i < splits ; i++ )+  {+    int each = height / ( splits - i );+    if ( each > max )+      max = each;+    height -= each;+  }+  return max;+}++static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_n_coeffs_funcs[8] =+{+  0, stbir__horizontal_gather_1_channels_with_n_coeffs_funcs, stbir__horizontal_gather_2_channels_with_n_coeffs_funcs, stbir__horizontal_gather_3_channels_with_n_coeffs_funcs, stbir__horizontal_gather_4_channels_with_n_coeffs_funcs, 0,0, stbir__horizontal_gather_7_channels_with_n_coeffs_funcs+};++static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_channels_funcs[8] =+{+  0, stbir__horizontal_gather_1_channels_funcs, stbir__horizontal_gather_2_channels_funcs, stbir__horizontal_gather_3_channels_funcs, stbir__horizontal_gather_4_channels_funcs, 0,0, stbir__horizontal_gather_7_channels_funcs+};++// there are six resize classifications: 0 == vertical scatter, 1 == vertical gather < 1x scale, 2 == vertical gather 1x-2x scale, 4 == vertical gather < 3x scale, 4 == vertical gather > 3x scale, 5 == <=4 pixel height, 6 == <=4 pixel wide column+#define STBIR_RESIZE_CLASSIFICATIONS 8++static float stbir__compute_weights[5][STBIR_RESIZE_CLASSIFICATIONS][4]=  // 5 = 0=1chan, 1=2chan, 2=3chan, 3=4chan, 4=7chan+{+  {+    { 1.00000f, 1.00000f, 0.31250f, 1.00000f },+    { 0.56250f, 0.59375f, 0.00000f, 0.96875f },+    { 1.00000f, 0.06250f, 0.00000f, 1.00000f },+    { 0.00000f, 0.09375f, 1.00000f, 1.00000f },+    { 1.00000f, 1.00000f, 1.00000f, 1.00000f },+    { 0.03125f, 0.12500f, 1.00000f, 1.00000f },+    { 0.06250f, 0.12500f, 0.00000f, 1.00000f },+    { 0.00000f, 1.00000f, 0.00000f, 0.03125f },+  }, {+    { 0.00000f, 0.84375f, 0.00000f, 0.03125f },+    { 0.09375f, 0.93750f, 0.00000f, 0.78125f },+    { 0.87500f, 0.21875f, 0.00000f, 0.96875f },+    { 0.09375f, 0.09375f, 1.00000f, 1.00000f },+    { 1.00000f, 1.00000f, 1.00000f, 1.00000f },+    { 0.03125f, 0.12500f, 1.00000f, 1.00000f },+    { 0.06250f, 0.12500f, 0.00000f, 1.00000f },+    { 0.00000f, 1.00000f, 0.00000f, 0.53125f },+  }, {+    { 0.00000f, 0.53125f, 0.00000f, 0.03125f },+    { 0.06250f, 0.96875f, 0.00000f, 0.53125f },+    { 0.87500f, 0.18750f, 0.00000f, 0.93750f },+    { 0.00000f, 0.09375f, 1.00000f, 1.00000f },+    { 1.00000f, 1.00000f, 1.00000f, 1.00000f },+    { 0.03125f, 0.12500f, 1.00000f, 1.00000f },+    { 0.06250f, 0.12500f, 0.00000f, 1.00000f },+    { 0.00000f, 1.00000f, 0.00000f, 0.56250f },+  }, {+    { 0.00000f, 0.50000f, 0.00000f, 0.71875f },+    { 0.06250f, 0.84375f, 0.00000f, 0.87500f },+    { 1.00000f, 0.50000f, 0.50000f, 0.96875f },+    { 1.00000f, 0.09375f, 0.31250f, 0.50000f },+    { 1.00000f, 1.00000f, 1.00000f, 1.00000f },+    { 1.00000f, 0.03125f, 0.03125f, 0.53125f },+    { 0.18750f, 0.12500f, 0.00000f, 1.00000f },+    { 0.00000f, 1.00000f, 0.03125f, 0.18750f },+  }, {+    { 0.00000f, 0.59375f, 0.00000f, 0.96875f },+    { 0.06250f, 0.81250f, 0.06250f, 0.59375f },+    { 0.75000f, 0.43750f, 0.12500f, 0.96875f },+    { 0.87500f, 0.06250f, 0.18750f, 0.43750f },+    { 1.00000f, 1.00000f, 1.00000f, 1.00000f },+    { 0.15625f, 0.12500f, 1.00000f, 1.00000f },+    { 0.06250f, 0.12500f, 0.00000f, 1.00000f },+    { 0.00000f, 1.00000f, 0.03125f, 0.34375f },+  }+};++// structure that allow us to query and override info for training the costs+typedef struct STBIR__V_FIRST_INFO+{+  double v_cost, h_cost;+  int control_v_first; // 0 = no control, 1 = force hori, 2 = force vert+  int v_first;+  int v_resize_classification;+  int is_gather;+} STBIR__V_FIRST_INFO;++#ifdef STBIR__V_FIRST_INFO_BUFFER+static STBIR__V_FIRST_INFO STBIR__V_FIRST_INFO_BUFFER = {0};+#define STBIR__V_FIRST_INFO_POINTER &STBIR__V_FIRST_INFO_BUFFER+#else+#define STBIR__V_FIRST_INFO_POINTER 0+#endif++// Figure out whether to scale along the horizontal or vertical first.+//   This only *super* important when you are scaling by a massively+//   different amount in the vertical vs the horizontal (for example, if+//   you are scaling by 2x in the width, and 0.5x in the height, then you+//   want to do the vertical scale first, because it's around 3x faster+//   in that order.+//+//   In more normal circumstances, this makes a 20-40% differences, so+//     it's good to get right, but not critical. The normal way that you+//     decide which direction goes first is just figuring out which+//     direction does more multiplies. But with modern CPUs with their+//     fancy caches and SIMD and high IPC abilities, so there's just a lot+//     more that goes into it.+//+//   My handwavy sort of solution is to have an app that does a whole+//     bunch of timing for both vertical and horizontal first modes,+//     and then another app that can read lots of these timing files+//     and try to search for the best weights to use. Dotimings.c+//     is the app that does a bunch of timings, and vf_train.c is the+//     app that solves for the best weights (and shows how well it+//     does currently).++static int stbir__should_do_vertical_first( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int horizontal_filter_pixel_width, float horizontal_scale, int horizontal_output_size, int vertical_filter_pixel_width, float vertical_scale, int vertical_output_size, int is_gather, STBIR__V_FIRST_INFO * info )+{+  double v_cost, h_cost;+  float * weights;+  int vertical_first;+  int v_classification;++  // categorize the resize into buckets+  if ( ( vertical_output_size <= 4 ) || ( horizontal_output_size <= 4 ) )+    v_classification = ( vertical_output_size < horizontal_output_size ) ? 6 : 7;+  else if ( vertical_scale <= 1.0f )+    v_classification = ( is_gather ) ? 1 : 0;+  else if ( vertical_scale <= 2.0f)+    v_classification = 2;+  else if ( vertical_scale <= 3.0f)+    v_classification = 3;+  else if ( vertical_scale <= 4.0f)+    v_classification = 5;+  else+    v_classification = 6;++  // use the right weights+  weights = weights_table[ v_classification ];++  // this is the costs when you don't take into account modern CPUs with high ipc and simd and caches - wish we had a better estimate+  h_cost = (float)horizontal_filter_pixel_width * weights[0] + horizontal_scale * (float)vertical_filter_pixel_width * weights[1];+  v_cost = (float)vertical_filter_pixel_width  * weights[2] + vertical_scale * (float)horizontal_filter_pixel_width * weights[3];++  // use computation estimate to decide vertical first or not+  vertical_first = ( v_cost <= h_cost ) ? 1 : 0;++  // save these, if requested+  if ( info )+  {+    info->h_cost = h_cost;+    info->v_cost = v_cost;+    info->v_resize_classification = v_classification;+    info->v_first = vertical_first;+    info->is_gather = is_gather;+  }++  // and this allows us to override everything for testing (see dotiming.c)+  if ( ( info ) && ( info->control_v_first ) )+    vertical_first = ( info->control_v_first == 2 ) ? 1 : 0;++  return vertical_first;+}++// layout lookups - must match stbir_internal_pixel_layout+static unsigned char stbir__pixel_channels[] = {+  1,2,3,3,4,   // 1ch, 2ch, rgb, bgr, 4ch+  4,4,4,4,2,2, // RGBA,BGRA,ARGB,ABGR,RA,AR+  4,4,4,4,2,2, // RGBA_PM,BGRA_PM,ARGB_PM,ABGR_PM,RA_PM,AR_PM+};++// the internal pixel layout enums are in a different order, so we can easily do range comparisons of types+//   the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible+static stbir_internal_pixel_layout stbir__pixel_layout_convert_public_to_internal[] = {+  STBIRI_BGR, STBIRI_1CHANNEL, STBIRI_2CHANNEL, STBIRI_RGB, STBIRI_RGBA,+  STBIRI_4CHANNEL, STBIRI_BGRA, STBIRI_ARGB, STBIRI_ABGR, STBIRI_RA, STBIRI_AR,+  STBIRI_RGBA_PM, STBIRI_BGRA_PM, STBIRI_ARGB_PM, STBIRI_ABGR_PM, STBIRI_RA_PM, STBIRI_AR_PM,+};++static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sampler * horizontal, stbir__sampler * vertical, stbir__contributors * conservative, stbir_pixel_layout input_pixel_layout_public, stbir_pixel_layout output_pixel_layout_public, int splits, int new_x, int new_y, int fast_alpha, void * user_data STBIR_ONLY_PROFILE_BUILD_GET_INFO )+{+  static char stbir_channel_count_index[8]={ 9,0,1,2, 3,9,9,4 };++  stbir__info * info = 0;+  void * alloced = 0;+  size_t alloced_total = 0;+  int vertical_first;+  int decode_buffer_size, ring_buffer_length_bytes, ring_buffer_size, vertical_buffer_size, alloc_ring_buffer_num_entries;++  int alpha_weighting_type = 0; // 0=none, 1=simple, 2=fancy+  int conservative_split_output_size = stbir__get_max_split( splits, vertical->scale_info.output_sub_size );+  stbir_internal_pixel_layout input_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ input_pixel_layout_public ];+  stbir_internal_pixel_layout output_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ output_pixel_layout_public ];+  int channels = stbir__pixel_channels[ input_pixel_layout ];+  int effective_channels = channels;++  // first figure out what type of alpha weighting to use (if any)+  if ( ( horizontal->filter_enum != STBIR_FILTER_POINT_SAMPLE ) || ( vertical->filter_enum != STBIR_FILTER_POINT_SAMPLE ) ) // no alpha weighting on point sampling+  {+    if ( ( input_pixel_layout >= STBIRI_RGBA ) && ( input_pixel_layout <= STBIRI_AR ) && ( output_pixel_layout >= STBIRI_RGBA ) && ( output_pixel_layout <= STBIRI_AR ) )+    {+      if ( fast_alpha )+      {+        alpha_weighting_type = 4;+      }+      else+      {+        static int fancy_alpha_effective_cnts[6] = { 7, 7, 7, 7, 3, 3 };+        alpha_weighting_type = 2;+        effective_channels = fancy_alpha_effective_cnts[ input_pixel_layout - STBIRI_RGBA ];+      }+    }+    else if ( ( input_pixel_layout >= STBIRI_RGBA_PM ) && ( input_pixel_layout <= STBIRI_AR_PM ) && ( output_pixel_layout >= STBIRI_RGBA ) && ( output_pixel_layout <= STBIRI_AR ) )+    {+      // input premult, output non-premult+      alpha_weighting_type = 3;+    }+    else if ( ( input_pixel_layout >= STBIRI_RGBA ) && ( input_pixel_layout <= STBIRI_AR ) && ( output_pixel_layout >= STBIRI_RGBA_PM ) && ( output_pixel_layout <= STBIRI_AR_PM ) )+    {+      // input non-premult, output premult+      alpha_weighting_type = 1;+    }+  }++  // channel in and out count must match currently+  if ( channels != stbir__pixel_channels[ output_pixel_layout ] )+    return 0;++  // get vertical first+  vertical_first = stbir__should_do_vertical_first( stbir__compute_weights[ (int)stbir_channel_count_index[ effective_channels ] ], horizontal->filter_pixel_width, horizontal->scale_info.scale, horizontal->scale_info.output_sub_size, vertical->filter_pixel_width, vertical->scale_info.scale, vertical->scale_info.output_sub_size, vertical->is_gather, STBIR__V_FIRST_INFO_POINTER );++  // sometimes read one float off in some of the unrolled loops (with a weight of zero coeff, so it doesn't have an effect)+  decode_buffer_size = ( conservative->n1 - conservative->n0 + 1 ) * effective_channels * sizeof(float) + sizeof(float); // extra float for padding++#if defined( STBIR__SEPARATE_ALLOCATIONS ) && defined(STBIR_SIMD8)+  if ( effective_channels == 3 )+    decode_buffer_size += sizeof(float); // avx in 3 channel mode needs one float at the start of the buffer (only with separate allocations)+#endif++  ring_buffer_length_bytes = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding++  // if we do vertical first, the ring buffer holds a whole decoded line+  if ( vertical_first )+    ring_buffer_length_bytes = ( decode_buffer_size + 15 ) & ~15;++  if ( ( ring_buffer_length_bytes & 4095 ) == 0 ) ring_buffer_length_bytes += 64*3; // avoid 4k alias++  // One extra entry because floating point precision problems sometimes cause an extra to be necessary.+  alloc_ring_buffer_num_entries = vertical->filter_pixel_width + 1;++  // we never need more ring buffer entries than the scanlines we're outputting when in scatter mode+  if ( ( !vertical->is_gather ) && ( alloc_ring_buffer_num_entries > conservative_split_output_size ) )+    alloc_ring_buffer_num_entries = conservative_split_output_size;++  ring_buffer_size = alloc_ring_buffer_num_entries * ring_buffer_length_bytes;++  // The vertical buffer is used differently, depending on whether we are scattering+  //   the vertical scanlines, or gathering them.+  //   If scattering, it's used at the temp buffer to accumulate each output.+  //   If gathering, it's just the output buffer.+  vertical_buffer_size = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float);  // extra float for padding++  // we make two passes through this loop, 1st to add everything up, 2nd to allocate and init+  for(;;)+  {+    int i;+    void * advance_mem = alloced;+    int copy_horizontal = 0;+    stbir__sampler * possibly_use_horizontal_for_pivot = 0;++#ifdef STBIR__SEPARATE_ALLOCATIONS+    #define STBIR__NEXT_PTR( ptr, size, ntype ) if ( alloced ) { void * p = STBIR_MALLOC( size, user_data); if ( p == 0 ) { stbir__free_internal_mem( info ); return 0; } (ptr) = (ntype*)p; }+#else+    #define STBIR__NEXT_PTR( ptr, size, ntype ) advance_mem = (void*) ( ( ((size_t)advance_mem) + 15 ) & ~15 ); if ( alloced ) ptr = (ntype*)advance_mem; advance_mem = ((char*)advance_mem) + (size);+#endif++    STBIR__NEXT_PTR( info, sizeof( stbir__info ), stbir__info );++    STBIR__NEXT_PTR( info->split_info, sizeof( stbir__per_split_info ) * splits, stbir__per_split_info );++    if ( info )+    {+      static stbir__alpha_weight_func * fancy_alpha_weights[6]  =    { stbir__fancy_alpha_weight_4ch,   stbir__fancy_alpha_weight_4ch,   stbir__fancy_alpha_weight_4ch,   stbir__fancy_alpha_weight_4ch,   stbir__fancy_alpha_weight_2ch,   stbir__fancy_alpha_weight_2ch };+      static stbir__alpha_unweight_func * fancy_alpha_unweights[6] = { stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_2ch, stbir__fancy_alpha_unweight_2ch };+      static stbir__alpha_weight_func * simple_alpha_weights[6] = { stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_2ch, stbir__simple_alpha_weight_2ch };+      static stbir__alpha_unweight_func * simple_alpha_unweights[6] = { stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_2ch, stbir__simple_alpha_unweight_2ch };++      // initialize info fields+      info->alloced_mem = alloced;+      info->alloced_total = alloced_total;++      info->channels = channels;+      info->effective_channels = effective_channels;++      info->offset_x = new_x;+      info->offset_y = new_y;+      info->alloc_ring_buffer_num_entries = alloc_ring_buffer_num_entries;+      info->ring_buffer_num_entries = 0;+      info->ring_buffer_length_bytes = ring_buffer_length_bytes;+      info->splits = splits;+      info->vertical_first = vertical_first;++      info->input_pixel_layout_internal = input_pixel_layout;+      info->output_pixel_layout_internal = output_pixel_layout;++      // setup alpha weight functions+      info->alpha_weight = 0;+      info->alpha_unweight = 0;++      // handle alpha weighting functions and overrides+      if ( alpha_weighting_type == 2 )+      {+        // high quality alpha multiplying on the way in, dividing on the way out+        info->alpha_weight = fancy_alpha_weights[ input_pixel_layout - STBIRI_RGBA ];+        info->alpha_unweight = fancy_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ];+      }+      else if ( alpha_weighting_type == 4 )+      {+        // fast alpha multiplying on the way in, dividing on the way out+        info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ];+        info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ];+      }+      else if ( alpha_weighting_type == 1 )+      {+        // fast alpha on the way in, leave in premultiplied form on way out+        info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ];+      }+      else if ( alpha_weighting_type == 3 )+      {+        // incoming is premultiplied, fast alpha dividing on the way out - non-premultiplied output+        info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ];+      }++      // handle 3-chan color flipping, using the alpha weight path+      if ( ( ( input_pixel_layout == STBIRI_RGB ) && ( output_pixel_layout == STBIRI_BGR ) ) ||+           ( ( input_pixel_layout == STBIRI_BGR ) && ( output_pixel_layout == STBIRI_RGB ) ) )+      {+        // do the flipping on the smaller of the two ends+        if ( horizontal->scale_info.scale < 1.0f )+          info->alpha_unweight = stbir__simple_flip_3ch;+        else+          info->alpha_weight = stbir__simple_flip_3ch;+      }++    }++    // get all the per-split buffers+    for( i = 0 ; i < splits ; i++ )+    {+      STBIR__NEXT_PTR( info->split_info[i].decode_buffer, decode_buffer_size, float );++#ifdef STBIR__SEPARATE_ALLOCATIONS++      #ifdef STBIR_SIMD8+      if ( ( info ) && ( effective_channels == 3 ) )+        ++info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer+      #endif++      STBIR__NEXT_PTR( info->split_info[i].ring_buffers, alloc_ring_buffer_num_entries * sizeof(float*), float* );+      {+        int j;+        for( j = 0 ; j < alloc_ring_buffer_num_entries ; j++ )+        {+          STBIR__NEXT_PTR( info->split_info[i].ring_buffers[j], ring_buffer_length_bytes, float );+          #ifdef STBIR_SIMD8+          if ( ( info ) && ( effective_channels == 3 ) )+            ++info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer+          #endif+        }+      }+#else+      STBIR__NEXT_PTR( info->split_info[i].ring_buffer, ring_buffer_size, float );+#endif+      STBIR__NEXT_PTR( info->split_info[i].vertical_buffer, vertical_buffer_size, float );+    }++    // alloc memory for to-be-pivoted coeffs (if necessary)+    if ( vertical->is_gather == 0 )+    {+      int both;+      int temp_mem_amt;++      // when in vertical scatter mode, we first build the coefficients in gather mode, and then pivot after,+      //   that means we need two buffers, so we try to use the decode buffer and ring buffer for this. if that+      //   is too small, we just allocate extra memory to use as this temp.++      both = vertical->gather_prescatter_contributors_size + vertical->gather_prescatter_coefficients_size;++#ifdef STBIR__SEPARATE_ALLOCATIONS+      temp_mem_amt = decode_buffer_size;+#else+      temp_mem_amt = ( decode_buffer_size + ring_buffer_size + vertical_buffer_size ) * splits;+#endif+      if ( temp_mem_amt >= both )+      {+        if ( info )+        {+          vertical->gather_prescatter_contributors = (stbir__contributors*)info->split_info[0].decode_buffer;+          vertical->gather_prescatter_coefficients = (float*) ( ( (char*)info->split_info[0].decode_buffer ) + vertical->gather_prescatter_contributors_size );+        }+      }+      else+      {+        // ring+decode memory is too small, so allocate temp memory+        STBIR__NEXT_PTR( vertical->gather_prescatter_contributors, vertical->gather_prescatter_contributors_size, stbir__contributors );+        STBIR__NEXT_PTR( vertical->gather_prescatter_coefficients, vertical->gather_prescatter_coefficients_size, float );+      }+    }++    STBIR__NEXT_PTR( horizontal->contributors, horizontal->contributors_size, stbir__contributors );+    STBIR__NEXT_PTR( horizontal->coefficients, horizontal->coefficients_size, float );++    // are the two filters identical?? (happens a lot with mipmap generation)+    if ( ( horizontal->filter_kernel == vertical->filter_kernel ) && ( horizontal->filter_support == vertical->filter_support ) && ( horizontal->edge == vertical->edge ) && ( horizontal->scale_info.output_sub_size == vertical->scale_info.output_sub_size ) )+    {+      float diff_scale = horizontal->scale_info.scale - vertical->scale_info.scale;+      float diff_shift = horizontal->scale_info.pixel_shift - vertical->scale_info.pixel_shift;+      if ( diff_scale < 0.0f ) diff_scale = -diff_scale;+      if ( diff_shift < 0.0f ) diff_shift = -diff_shift;+      if ( ( diff_scale <= stbir__small_float ) && ( diff_shift <= stbir__small_float ) )+      {+        if ( horizontal->is_gather == vertical->is_gather )+        {+          copy_horizontal = 1;+          goto no_vert_alloc;+        }+        // everything matches, but vertical is scatter, horizontal is gather, use horizontal coeffs for vertical pivot coeffs+        possibly_use_horizontal_for_pivot = horizontal;+      }+    }++    STBIR__NEXT_PTR( vertical->contributors, vertical->contributors_size, stbir__contributors );+    STBIR__NEXT_PTR( vertical->coefficients, vertical->coefficients_size, float );++   no_vert_alloc:++    if ( info )+    {+      STBIR_PROFILE_BUILD_START( horizontal );++      stbir__calculate_filters( horizontal, 0, user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO );++      // setup the horizontal gather functions+      // start with defaulting to the n_coeffs functions (specialized on channels and remnant leftover)+      info->horizontal_gather_channels = stbir__horizontal_gather_n_coeffs_funcs[ effective_channels ][ horizontal->extent_info.widest & 3 ];+      // but if the number of coeffs <= 12, use another set of special cases. <=12 coeffs is any enlarging resize, or shrinking resize down to about 1/3 size+      if ( horizontal->extent_info.widest <= 12 )+        info->horizontal_gather_channels = stbir__horizontal_gather_channels_funcs[ effective_channels ][ horizontal->extent_info.widest - 1 ];++      info->scanline_extents.conservative.n0 = conservative->n0;+      info->scanline_extents.conservative.n1 = conservative->n1;++      // get exact extents+      stbir__get_extents( horizontal, &info->scanline_extents );++      // pack the horizontal coeffs+      horizontal->coefficient_width = stbir__pack_coefficients(horizontal->num_contributors, horizontal->contributors, horizontal->coefficients, horizontal->coefficient_width, horizontal->extent_info.widest, info->scanline_extents.conservative.n0, info->scanline_extents.conservative.n1 );++      STBIR_MEMCPY( &info->horizontal, horizontal, sizeof( stbir__sampler ) );++      STBIR_PROFILE_BUILD_END( horizontal );++      if ( copy_horizontal )+      {+        STBIR_MEMCPY( &info->vertical, horizontal, sizeof( stbir__sampler ) );+      }+      else+      {+        STBIR_PROFILE_BUILD_START( vertical );++        stbir__calculate_filters( vertical, possibly_use_horizontal_for_pivot, user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO );+        STBIR_MEMCPY( &info->vertical, vertical, sizeof( stbir__sampler ) );++        STBIR_PROFILE_BUILD_END( vertical );+      }++      // setup the vertical split ranges+      stbir__get_split_info( info->split_info, info->splits, info->vertical.scale_info.output_sub_size, info->vertical.filter_pixel_margin, info->vertical.scale_info.input_full_size );++      // now we know precisely how many entries we need+      info->ring_buffer_num_entries = info->vertical.extent_info.widest;++      // we never need more ring buffer entries than the scanlines we're outputting+      if ( ( !info->vertical.is_gather ) && ( info->ring_buffer_num_entries > conservative_split_output_size ) )+        info->ring_buffer_num_entries = conservative_split_output_size;+      STBIR_ASSERT( info->ring_buffer_num_entries <= info->alloc_ring_buffer_num_entries );++      // a few of the horizontal gather functions read past the end of the decode (but mask it out), +      //   so put in normal values so no snans or denormals accidentally sneak in (also, in the ring +      //   buffer for vertical first)+      for( i = 0 ; i < splits ; i++ )+      {+        int t, ofs, start;++        ofs = decode_buffer_size / 4;+        start = ofs - 4;+        if ( start < 0 ) start = 0;++        for( t = start ; t < ofs; t++ )+          info->split_info[i].decode_buffer[ t ] = 9999.0f;++        if ( vertical_first )+        {+          int j;+          for( j = 0; j < info->ring_buffer_num_entries ; j++ )+          {+            for( t = start ; t < ofs; t++ )+              stbir__get_ring_buffer_entry( info, info->split_info + i, j )[ t ] = 9999.0f;+          }+        }+      }+    }++    #undef STBIR__NEXT_PTR+++    // is this the first time through loop?+    if ( info == 0 )+    {+      alloced_total = ( 15 + (size_t)advance_mem );+      alloced = STBIR_MALLOC( alloced_total, user_data );+      if ( alloced == 0 )+        return 0;+    }+    else+      return info;  // success+  }+}++static int stbir__perform_resize( stbir__info const * info, int split_start, int split_count )+{+  stbir__per_split_info * split_info = info->split_info + split_start;++  STBIR_PROFILE_CLEAR_EXTRAS();++  STBIR_PROFILE_FIRST_START( looping );+  if (info->vertical.is_gather)+    stbir__vertical_gather_loop( info, split_info, split_count );+  else+    stbir__vertical_scatter_loop( info, split_info, split_count );+  STBIR_PROFILE_END( looping );++  return 1;+}++static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * resize )+{+  static stbir__decode_pixels_func * decode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]=+  {+    /* 1ch-4ch */ stbir__decode_uint8_srgb, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear,+  };++  static stbir__decode_pixels_func * decode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]=+  {+    { /* RGBA */ stbir__decode_uint8_srgb4_linearalpha,      stbir__decode_uint8_srgb,      0, stbir__decode_float_linear,      stbir__decode_half_float_linear },+    { /* BGRA */ stbir__decode_uint8_srgb4_linearalpha_BGRA, stbir__decode_uint8_srgb_BGRA, 0, stbir__decode_float_linear_BGRA, stbir__decode_half_float_linear_BGRA },+    { /* ARGB */ stbir__decode_uint8_srgb4_linearalpha_ARGB, stbir__decode_uint8_srgb_ARGB, 0, stbir__decode_float_linear_ARGB, stbir__decode_half_float_linear_ARGB },+    { /* ABGR */ stbir__decode_uint8_srgb4_linearalpha_ABGR, stbir__decode_uint8_srgb_ABGR, 0, stbir__decode_float_linear_ABGR, stbir__decode_half_float_linear_ABGR },+    { /* RA   */ stbir__decode_uint8_srgb2_linearalpha,      stbir__decode_uint8_srgb,      0, stbir__decode_float_linear,      stbir__decode_half_float_linear },+    { /* AR   */ stbir__decode_uint8_srgb2_linearalpha_AR,   stbir__decode_uint8_srgb_AR,   0, stbir__decode_float_linear_AR,   stbir__decode_half_float_linear_AR },+  };++  static stbir__decode_pixels_func * decode_simple_scaled_or_not[2][2]=+  {+    { stbir__decode_uint8_linear_scaled,  stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear },+  };++  static stbir__decode_pixels_func * decode_alphas_scaled_or_not[STBIRI_AR-STBIRI_RGBA+1][2][2]=+  {+    { /* RGBA */ { stbir__decode_uint8_linear_scaled,       stbir__decode_uint8_linear },      { stbir__decode_uint16_linear_scaled,      stbir__decode_uint16_linear } },+    { /* BGRA */ { stbir__decode_uint8_linear_scaled_BGRA,  stbir__decode_uint8_linear_BGRA }, { stbir__decode_uint16_linear_scaled_BGRA, stbir__decode_uint16_linear_BGRA } },+    { /* ARGB */ { stbir__decode_uint8_linear_scaled_ARGB,  stbir__decode_uint8_linear_ARGB }, { stbir__decode_uint16_linear_scaled_ARGB, stbir__decode_uint16_linear_ARGB } },+    { /* ABGR */ { stbir__decode_uint8_linear_scaled_ABGR,  stbir__decode_uint8_linear_ABGR }, { stbir__decode_uint16_linear_scaled_ABGR, stbir__decode_uint16_linear_ABGR } },+    { /* RA   */ { stbir__decode_uint8_linear_scaled,       stbir__decode_uint8_linear },      { stbir__decode_uint16_linear_scaled,      stbir__decode_uint16_linear } },+    { /* AR   */ { stbir__decode_uint8_linear_scaled_AR,    stbir__decode_uint8_linear_AR },   { stbir__decode_uint16_linear_scaled_AR,   stbir__decode_uint16_linear_AR } }+  };++  static stbir__encode_pixels_func * encode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]=+  {+    /* 1ch-4ch */ stbir__encode_uint8_srgb, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear,+  };++  static stbir__encode_pixels_func * encode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]=+  {+    { /* RGBA */ stbir__encode_uint8_srgb4_linearalpha,      stbir__encode_uint8_srgb,      0, stbir__encode_float_linear,      stbir__encode_half_float_linear },+    { /* BGRA */ stbir__encode_uint8_srgb4_linearalpha_BGRA, stbir__encode_uint8_srgb_BGRA, 0, stbir__encode_float_linear_BGRA, stbir__encode_half_float_linear_BGRA },+    { /* ARGB */ stbir__encode_uint8_srgb4_linearalpha_ARGB, stbir__encode_uint8_srgb_ARGB, 0, stbir__encode_float_linear_ARGB, stbir__encode_half_float_linear_ARGB },+    { /* ABGR */ stbir__encode_uint8_srgb4_linearalpha_ABGR, stbir__encode_uint8_srgb_ABGR, 0, stbir__encode_float_linear_ABGR, stbir__encode_half_float_linear_ABGR },+    { /* RA   */ stbir__encode_uint8_srgb2_linearalpha,      stbir__encode_uint8_srgb,      0, stbir__encode_float_linear,      stbir__encode_half_float_linear },+    { /* AR   */ stbir__encode_uint8_srgb2_linearalpha_AR,   stbir__encode_uint8_srgb_AR,   0, stbir__encode_float_linear_AR,   stbir__encode_half_float_linear_AR }+  };++  static stbir__encode_pixels_func * encode_simple_scaled_or_not[2][2]=+  {+    { stbir__encode_uint8_linear_scaled,  stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear },+  };++  static stbir__encode_pixels_func * encode_alphas_scaled_or_not[STBIRI_AR-STBIRI_RGBA+1][2][2]=+  {+    { /* RGBA */ { stbir__encode_uint8_linear_scaled,       stbir__encode_uint8_linear },       { stbir__encode_uint16_linear_scaled,      stbir__encode_uint16_linear } },+    { /* BGRA */ { stbir__encode_uint8_linear_scaled_BGRA,  stbir__encode_uint8_linear_BGRA },  { stbir__encode_uint16_linear_scaled_BGRA, stbir__encode_uint16_linear_BGRA } },+    { /* ARGB */ { stbir__encode_uint8_linear_scaled_ARGB,  stbir__encode_uint8_linear_ARGB },  { stbir__encode_uint16_linear_scaled_ARGB, stbir__encode_uint16_linear_ARGB } },+    { /* ABGR */ { stbir__encode_uint8_linear_scaled_ABGR,  stbir__encode_uint8_linear_ABGR },  { stbir__encode_uint16_linear_scaled_ABGR, stbir__encode_uint16_linear_ABGR } },+    { /* RA   */ { stbir__encode_uint8_linear_scaled,       stbir__encode_uint8_linear },       { stbir__encode_uint16_linear_scaled,      stbir__encode_uint16_linear } },+    { /* AR   */ { stbir__encode_uint8_linear_scaled_AR,    stbir__encode_uint8_linear_AR },    { stbir__encode_uint16_linear_scaled_AR,   stbir__encode_uint16_linear_AR } }+  };++  stbir__decode_pixels_func * decode_pixels = 0;+  stbir__encode_pixels_func * encode_pixels = 0;+  stbir_datatype input_type, output_type;++  input_type = resize->input_data_type;+  output_type = resize->output_data_type;+  info->input_data = resize->input_pixels;+  info->input_stride_bytes = resize->input_stride_in_bytes;+  info->output_stride_bytes = resize->output_stride_in_bytes;++  // if we're completely point sampling, then we can turn off SRGB+  if ( ( info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( info->vertical.filter_enum == STBIR_FILTER_POINT_SAMPLE ) )+  {+    if ( ( ( input_type  == STBIR_TYPE_UINT8_SRGB ) || ( input_type  == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) &&+         ( ( output_type == STBIR_TYPE_UINT8_SRGB ) || ( output_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) )+    {+      input_type = STBIR_TYPE_UINT8;+      output_type = STBIR_TYPE_UINT8;+    }+  }++  // recalc the output and input strides+  if ( info->input_stride_bytes == 0 )+    info->input_stride_bytes = info->channels * info->horizontal.scale_info.input_full_size * stbir__type_size[input_type];++  if ( info->output_stride_bytes == 0 )+    info->output_stride_bytes = info->channels * info->horizontal.scale_info.output_sub_size * stbir__type_size[output_type];++  // calc offset+  info->output_data = ( (char*) resize->output_pixels ) + ( (size_t) info->offset_y * (size_t) resize->output_stride_in_bytes ) + ( info->offset_x * info->channels * stbir__type_size[output_type] );++  info->in_pixels_cb = resize->input_cb;+  info->user_data = resize->user_data;+  info->out_pixels_cb = resize->output_cb;++  // setup the input format converters+  if ( ( input_type == STBIR_TYPE_UINT8 ) || ( input_type == STBIR_TYPE_UINT16 ) )+  {+    int non_scaled = 0;++    // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16)+    if ( ( !info->alpha_weight ) && ( !info->alpha_unweight )  ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual)+      if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) )+        non_scaled = 1;++    if ( info->input_pixel_layout_internal <= STBIRI_4CHANNEL )+      decode_pixels = decode_simple_scaled_or_not[ input_type == STBIR_TYPE_UINT16 ][ non_scaled ];+    else+      decode_pixels = decode_alphas_scaled_or_not[ ( info->input_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ input_type == STBIR_TYPE_UINT16 ][ non_scaled ];+  }+  else+  {+    if ( info->input_pixel_layout_internal <= STBIRI_4CHANNEL )+      decode_pixels = decode_simple[ input_type - STBIR_TYPE_UINT8_SRGB ];+    else+      decode_pixels = decode_alphas[ ( info->input_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ input_type - STBIR_TYPE_UINT8_SRGB ];+  }++  // setup the output format converters+  if ( ( output_type == STBIR_TYPE_UINT8 ) || ( output_type == STBIR_TYPE_UINT16 ) )+  {+    int non_scaled = 0;++    // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16)+    if ( ( !info->alpha_weight ) && ( !info->alpha_unweight ) ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual)+      if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) )+        non_scaled = 1;++    if ( info->output_pixel_layout_internal <= STBIRI_4CHANNEL )+      encode_pixels = encode_simple_scaled_or_not[ output_type == STBIR_TYPE_UINT16 ][ non_scaled ];+    else+      encode_pixels = encode_alphas_scaled_or_not[ ( info->output_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ output_type == STBIR_TYPE_UINT16 ][ non_scaled ];+  }+  else+  {+    if ( info->output_pixel_layout_internal <= STBIRI_4CHANNEL )+      encode_pixels = encode_simple[ output_type - STBIR_TYPE_UINT8_SRGB ];+    else+      encode_pixels = encode_alphas[ ( info->output_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ output_type - STBIR_TYPE_UINT8_SRGB ];+  }++  info->input_type = input_type;+  info->output_type = output_type;+  info->decode_pixels = decode_pixels;+  info->encode_pixels = encode_pixels;+}++static void stbir__clip( int * outx, int * outsubw, int outw, double * u0, double * u1 )+{+  double per, adj;+  int over;++  // do left/top edge+  if ( *outx < 0 )+  {+    per = ( (double)*outx ) / ( (double)*outsubw ); // is negative+    adj = per * ( *u1 - *u0 );+    *u0 -= adj; // increases u0+    *outx = 0;+  }++  // do right/bot edge+  over = outw - ( *outx + *outsubw );+  if ( over < 0 )+  {+    per = ( (double)over ) / ( (double)*outsubw ); // is negative+    adj = per * ( *u1 - *u0 );+    *u1 += adj; // decrease u1+    *outsubw = outw - *outx;+  }+}++// converts a double to a rational that has less than one float bit of error (returns 0 if unable to do so)+static int stbir__double_to_rational(double f, stbir_uint32 limit, stbir_uint32 *numer, stbir_uint32 *denom, int limit_denom ) // limit_denom (1) or limit numer (0)+{+  double err;+  stbir_uint64 top, bot;+  stbir_uint64 numer_last = 0;+  stbir_uint64 denom_last = 1;+  stbir_uint64 numer_estimate = 1;+  stbir_uint64 denom_estimate = 0;++  // scale to past float error range+  top = (stbir_uint64)( f * (double)(1 << 25) );+  bot = 1 << 25;++  // keep refining, but usually stops in a few loops - usually 5 for bad cases+  for(;;)+  {+    stbir_uint64 est, temp;++    // hit limit, break out and do best full range estimate+    if ( ( ( limit_denom ) ? denom_estimate : numer_estimate ) >= limit )+      break;++    // is the current error less than 1 bit of a float? if so, we're done+    if ( denom_estimate )+    {+      err = ( (double)numer_estimate / (double)denom_estimate ) - f;+      if ( err < 0.0 ) err = -err;+      if ( err < ( 1.0 / (double)(1<<24) ) )+      {+        // yup, found it+        *numer = (stbir_uint32) numer_estimate;+        *denom = (stbir_uint32) denom_estimate;+        return 1;+      }+    }++    // no more refinement bits left? break out and do full range estimate+    if ( bot == 0 )+      break;++    // gcd the estimate bits+    est = top / bot;+    temp = top % bot;+    top = bot;+    bot = temp;++    // move remainders+    temp = est * denom_estimate + denom_last;+    denom_last = denom_estimate;+    denom_estimate = temp;++    // move remainders+    temp = est * numer_estimate + numer_last;+    numer_last = numer_estimate;+    numer_estimate = temp;+  }++  // we didn't fine anything good enough for float, use a full range estimate+  if ( limit_denom )+  {+    numer_estimate= (stbir_uint64)( f * (double)limit + 0.5 );+    denom_estimate = limit;+  }+  else+  {+    numer_estimate = limit;+    denom_estimate = (stbir_uint64)( ( (double)limit / f ) + 0.5 );+  }++  *numer = (stbir_uint32) numer_estimate;+  *denom = (stbir_uint32) denom_estimate;++  err = ( denom_estimate ) ? ( ( (double)(stbir_uint32)numer_estimate / (double)(stbir_uint32)denom_estimate ) - f ) : 1.0;+  if ( err < 0.0 ) err = -err;+  return ( err < ( 1.0 / (double)(1<<24) ) ) ? 1 : 0;+}++static int stbir__calculate_region_transform( stbir__scale_info * scale_info, int output_full_range, int * output_offset, int output_sub_range, int input_full_range, double input_s0, double input_s1 )+{+  double output_range, input_range, output_s, input_s, ratio, scale;++  input_s = input_s1 - input_s0;++  // null area+  if ( ( output_full_range == 0 ) || ( input_full_range == 0 ) ||+       ( output_sub_range == 0 ) || ( input_s <= stbir__small_float ) )+    return 0;++  // are either of the ranges completely out of bounds?+  if ( ( *output_offset >= output_full_range ) || ( ( *output_offset + output_sub_range ) <= 0 ) || ( input_s0 >= (1.0f-stbir__small_float) ) || ( input_s1 <= stbir__small_float ) )+    return 0;++  output_range = (double)output_full_range;+  input_range = (double)input_full_range;++  output_s = ( (double)output_sub_range) / output_range;++  // figure out the scaling to use+  ratio = output_s / input_s;++  // save scale before clipping+  scale = ( output_range / input_range ) * ratio;+  scale_info->scale = (float)scale;+  scale_info->inv_scale = (float)( 1.0 / scale );++  // clip output area to left/right output edges (and adjust input area)+  stbir__clip( output_offset, &output_sub_range, output_full_range, &input_s0, &input_s1 );++  // recalc input area+  input_s = input_s1 - input_s0;++  // after clipping do we have zero input area?+  if ( input_s <= stbir__small_float )+    return 0;++  // calculate and store the starting source offsets in output pixel space+  scale_info->pixel_shift = (float) ( input_s0 * ratio * output_range );++  scale_info->scale_is_rational = stbir__double_to_rational( scale, ( scale <= 1.0 ) ? output_full_range : input_full_range, &scale_info->scale_numerator, &scale_info->scale_denominator, ( scale >= 1.0 ) );++  scale_info->input_full_size = input_full_range;+  scale_info->output_sub_size = output_sub_range;++  return 1;+}+++static void stbir__init_and_set_layout( STBIR_RESIZE * resize, stbir_pixel_layout pixel_layout, stbir_datatype data_type )+{+  resize->input_cb = 0;+  resize->output_cb = 0;+  resize->user_data = resize;+  resize->samplers = 0;+  resize->called_alloc = 0;+  resize->horizontal_filter = STBIR_FILTER_DEFAULT;+  resize->horizontal_filter_kernel = 0; resize->horizontal_filter_support = 0;+  resize->vertical_filter = STBIR_FILTER_DEFAULT;+  resize->vertical_filter_kernel = 0; resize->vertical_filter_support = 0;+  resize->horizontal_edge = STBIR_EDGE_CLAMP;+  resize->vertical_edge = STBIR_EDGE_CLAMP;+  resize->input_s0 = 0; resize->input_t0 = 0; resize->input_s1 = 1; resize->input_t1 = 1;+  resize->output_subx = 0; resize->output_suby = 0; resize->output_subw = resize->output_w; resize->output_subh = resize->output_h;+  resize->input_data_type = data_type;+  resize->output_data_type = data_type;+  resize->input_pixel_layout_public = pixel_layout;+  resize->output_pixel_layout_public = pixel_layout;+  resize->needs_rebuild = 1;+}++STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize,+                                 const void *input_pixels,  int input_w,  int input_h, int input_stride_in_bytes, // stride can be zero+                                       void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero+                                 stbir_pixel_layout pixel_layout, stbir_datatype data_type )+{+  resize->input_pixels = input_pixels;+  resize->input_w = input_w;+  resize->input_h = input_h;+  resize->input_stride_in_bytes = input_stride_in_bytes;+  resize->output_pixels = output_pixels;+  resize->output_w = output_w;+  resize->output_h = output_h;+  resize->output_stride_in_bytes = output_stride_in_bytes;+  resize->fast_alpha = 0;++  stbir__init_and_set_layout( resize, pixel_layout, data_type );+}++// You can update parameters any time after resize_init+STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type )  // by default, datatype from resize_init+{+  resize->input_data_type = input_type;+  resize->output_data_type = output_type;+  if ( ( resize->samplers ) && ( !resize->needs_rebuild ) )+    stbir__update_info_from_resize( resize->samplers, resize );+}++STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb )   // no callbacks by default+{+  resize->input_cb = input_cb;+  resize->output_cb = output_cb;++  if ( ( resize->samplers ) && ( !resize->needs_rebuild ) )+  {+    resize->samplers->in_pixels_cb = input_cb;+    resize->samplers->out_pixels_cb = output_cb;+  }+}++STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data )                                     // pass back STBIR_RESIZE* by default+{+  resize->user_data = user_data;+  if ( ( resize->samplers ) && ( !resize->needs_rebuild ) )+    resize->samplers->user_data = user_data;+}++STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes )+{+  resize->input_pixels = input_pixels;+  resize->input_stride_in_bytes = input_stride_in_bytes;+  resize->output_pixels = output_pixels;+  resize->output_stride_in_bytes = output_stride_in_bytes;+  if ( ( resize->samplers ) && ( !resize->needs_rebuild ) )+    stbir__update_info_from_resize( resize->samplers, resize );+}+++STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge )       // CLAMP by default+{+  resize->horizontal_edge = horizontal_edge;+  resize->vertical_edge = vertical_edge;+  resize->needs_rebuild = 1;+  return 1;+}++STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ) // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default+{+  resize->horizontal_filter = horizontal_filter;+  resize->vertical_filter = vertical_filter;+  resize->needs_rebuild = 1;+  return 1;+}++STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support )+{+  resize->horizontal_filter_kernel = horizontal_filter; resize->horizontal_filter_support = horizontal_support;+  resize->vertical_filter_kernel = vertical_filter; resize->vertical_filter_support = vertical_support;+  resize->needs_rebuild = 1;+  return 1;+}++STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout input_pixel_layout, stbir_pixel_layout output_pixel_layout )   // sets new pixel layouts+{+  resize->input_pixel_layout_public = input_pixel_layout;+  resize->output_pixel_layout_public = output_pixel_layout;+  resize->needs_rebuild = 1;+  return 1;+}+++STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, int non_pma_alpha_speed_over_quality )   // sets alpha speed+{+  resize->fast_alpha = non_pma_alpha_speed_over_quality;+  resize->needs_rebuild = 1;+  return 1;+}++STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 )                 // sets input region (full region by default)+{+  resize->input_s0 = s0;+  resize->input_t0 = t0;+  resize->input_s1 = s1;+  resize->input_t1 = t1;+  resize->needs_rebuild = 1;++  // are we inbounds?+  if ( ( s1 < stbir__small_float ) || ( (s1-s0) < stbir__small_float ) ||+       ( t1 < stbir__small_float ) || ( (t1-t0) < stbir__small_float ) ||+       ( s0 > (1.0f-stbir__small_float) ) ||+       ( t0 > (1.0f-stbir__small_float) ) )+    return 0;++  return 1;+}++STBIRDEF int stbir_set_output_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh )          // sets input region (full region by default)+{+  resize->output_subx = subx;+  resize->output_suby = suby;+  resize->output_subw = subw;+  resize->output_subh = subh;+  resize->needs_rebuild = 1;++  // are we inbounds?+  if ( ( subx >= resize->output_w ) || ( ( subx + subw ) <= 0 ) || ( suby >= resize->output_h ) || ( ( suby + subh ) <= 0 ) || ( subw == 0 ) || ( subh == 0 ) )+    return 0;++  return 1;+}++STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh )                 // sets both regions (full regions by default)+{+  double s0, t0, s1, t1;++  s0 = ( (double)subx ) / ( (double)resize->output_w );+  t0 = ( (double)suby ) / ( (double)resize->output_h );+  s1 = ( (double)(subx+subw) ) / ( (double)resize->output_w );+  t1 = ( (double)(suby+subh) ) / ( (double)resize->output_h );++  resize->input_s0 = s0;+  resize->input_t0 = t0;+  resize->input_s1 = s1;+  resize->input_t1 = t1;+  resize->output_subx = subx;+  resize->output_suby = suby;+  resize->output_subw = subw;+  resize->output_subh = subh;+  resize->needs_rebuild = 1;++  // are we inbounds?+  if ( ( subx >= resize->output_w ) || ( ( subx + subw ) <= 0 ) || ( suby >= resize->output_h ) || ( ( suby + subh ) <= 0 ) || ( subw == 0 ) || ( subh == 0 ) )+    return 0;++  return 1;+}++static int stbir__perform_build( STBIR_RESIZE * resize, int splits )+{+  stbir__contributors conservative = { 0, 0 };+  stbir__sampler horizontal, vertical;+  int new_output_subx, new_output_suby;+  stbir__info * out_info;+  #ifdef STBIR_PROFILE+  stbir__info profile_infod;  // used to contain building profile info before everything is allocated+  stbir__info * profile_info = &profile_infod;+  #endif++  // have we already built the samplers?+  if ( resize->samplers )+    return 0;++  #define STBIR_RETURN_ERROR_AND_ASSERT( exp )  STBIR_ASSERT( !(exp) ); if (exp) return 0;+  STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->horizontal_filter >= STBIR_FILTER_OTHER)+  STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->vertical_filter >= STBIR_FILTER_OTHER)+  #undef STBIR_RETURN_ERROR_AND_ASSERT++  if ( splits <= 0 )+    return 0;++  STBIR_PROFILE_BUILD_FIRST_START( build );++  new_output_subx = resize->output_subx;+  new_output_suby = resize->output_suby;++  // do horizontal clip and scale calcs+  if ( !stbir__calculate_region_transform( &horizontal.scale_info, resize->output_w, &new_output_subx, resize->output_subw, resize->input_w, resize->input_s0, resize->input_s1 ) )+    return 0;++  // do vertical clip and scale calcs+  if ( !stbir__calculate_region_transform( &vertical.scale_info, resize->output_h, &new_output_suby, resize->output_subh, resize->input_h, resize->input_t0, resize->input_t1 ) )+    return 0;++  // if nothing to do, just return+  if ( ( horizontal.scale_info.output_sub_size == 0 ) || ( vertical.scale_info.output_sub_size == 0 ) )+    return 0;++  stbir__set_sampler(&horizontal, resize->horizontal_filter, resize->horizontal_filter_kernel, resize->horizontal_filter_support, resize->horizontal_edge, &horizontal.scale_info, 1, resize->user_data );+  stbir__get_conservative_extents( &horizontal, &conservative, resize->user_data );+  stbir__set_sampler(&vertical, resize->vertical_filter, resize->horizontal_filter_kernel, resize->vertical_filter_support, resize->vertical_edge, &vertical.scale_info, 0, resize->user_data );++  if ( ( vertical.scale_info.output_sub_size / splits ) < STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS ) // each split should be a minimum of 4 scanlines (handwavey choice)+  {+    splits = vertical.scale_info.output_sub_size / STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS;+    if ( splits == 0 ) splits = 1;+  }++  STBIR_PROFILE_BUILD_START( alloc );+  out_info = stbir__alloc_internal_mem_and_build_samplers( &horizontal, &vertical, &conservative, resize->input_pixel_layout_public, resize->output_pixel_layout_public, splits, new_output_subx, new_output_suby, resize->fast_alpha, resize->user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO );+  STBIR_PROFILE_BUILD_END( alloc );+  STBIR_PROFILE_BUILD_END( build );++  if ( out_info )+  {+    resize->splits = splits;+    resize->samplers = out_info;+    resize->needs_rebuild = 0;+    #ifdef STBIR_PROFILE+      STBIR_MEMCPY( &out_info->profile, &profile_infod.profile, sizeof( out_info->profile ) );+    #endif++    // update anything that can be changed without recalcing samplers+    stbir__update_info_from_resize( out_info, resize );++    return splits;+  }++  return 0;+}++void stbir_free_samplers( STBIR_RESIZE * resize )+{+  if ( resize->samplers )+  {+    stbir__free_internal_mem( resize->samplers );+    resize->samplers = 0;+    resize->called_alloc = 0;+  }+}++STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int splits )+{+  if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) )+  {+    if ( resize->samplers )+      stbir_free_samplers( resize );++    resize->called_alloc = 1;+    return stbir__perform_build( resize, splits );+  }++  STBIR_PROFILE_BUILD_CLEAR( resize->samplers );++  return 1;+}++STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize )+{+  return stbir_build_samplers_with_splits( resize, 1 );+}++STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize )+{+  int result;++  if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) )+  {+    int alloc_state = resize->called_alloc;  // remember allocated state++    if ( resize->samplers )+    {+      stbir__free_internal_mem( resize->samplers );+      resize->samplers = 0;+    }++    if ( !stbir_build_samplers( resize ) )+      return 0;++    resize->called_alloc = alloc_state;++    // if build_samplers succeeded (above), but there are no samplers set, then+    //   the area to stretch into was zero pixels, so don't do anything and return+    //   success+    if ( resize->samplers == 0 )+      return 1;+  }+  else+  {+    // didn't build anything - clear it+    STBIR_PROFILE_BUILD_CLEAR( resize->samplers );+  }++  // do resize+  result = stbir__perform_resize( resize->samplers, 0, resize->splits );++  // if we alloced, then free+  if ( !resize->called_alloc )+  {+    stbir_free_samplers( resize );+    resize->samplers = 0;+  }++  return result;+}++STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count )+{+  STBIR_ASSERT( resize->samplers );++  // if we're just doing the whole thing, call full+  if ( ( split_start == -1 ) || ( ( split_start == 0 ) && ( split_count == resize->splits ) ) )+    return stbir_resize_extended( resize );++  // you **must** build samplers first when using split resize+  if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) )+    return 0;++  if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) )+    return 0;++  // do resize+  return stbir__perform_resize( resize->samplers, split_start, split_count );+}++static int stbir__check_output_stuff( void ** ret_ptr, int * ret_pitch, void * output_pixels, int type_size, int output_w, int output_h, int output_stride_in_bytes, stbir_internal_pixel_layout pixel_layout )+{+  size_t size;+  int pitch;+  void * ptr;++  pitch = output_w * type_size * stbir__pixel_channels[ pixel_layout ];+  if ( pitch == 0 )+    return 0;++  if ( output_stride_in_bytes == 0 )+    output_stride_in_bytes = pitch;++  if ( output_stride_in_bytes < pitch )+    return 0;++  size = (size_t)output_stride_in_bytes * (size_t)output_h;+  if ( size == 0 )+    return 0;++  *ret_ptr = 0;+  *ret_pitch = output_stride_in_bytes;++  if ( output_pixels == 0 )+  {+    ptr = STBIR_MALLOC( size, 0 );+    if ( ptr == 0 )+      return 0;++    *ret_ptr = ptr;+    *ret_pitch = pitch;+  }++  return 1;+}+++STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes,+                                                          unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+                                                          stbir_pixel_layout pixel_layout )+{+  STBIR_RESIZE resize;+  unsigned char * optr;+  int opitch;++  if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) )+    return 0;++  stbir_resize_init( &resize,+                     input_pixels,  input_w,  input_h,  input_stride_in_bytes,+                     (optr) ? optr : output_pixels, output_w, output_h, opitch,+                     pixel_layout, STBIR_TYPE_UINT8 );++  if ( !stbir_resize_extended( &resize ) )+  {+    if ( optr )+      STBIR_FREE( optr, 0 );+    return 0;+  }++  return (optr) ? optr : output_pixels;+}++STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes,+                                                        unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+                                                        stbir_pixel_layout pixel_layout )+{+  STBIR_RESIZE resize;+  unsigned char * optr;+  int opitch;++  if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) )+    return 0;++  stbir_resize_init( &resize,+                     input_pixels,  input_w,  input_h,  input_stride_in_bytes,+                     (optr) ? optr : output_pixels, output_w, output_h, opitch,+                     pixel_layout, STBIR_TYPE_UINT8_SRGB );++  if ( !stbir_resize_extended( &resize ) )+  {+    if ( optr )+      STBIR_FREE( optr, 0 );+    return 0;+  }++  return (optr) ? optr : output_pixels;+}+++STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes,+                                                  float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+                                                  stbir_pixel_layout pixel_layout )+{+  STBIR_RESIZE resize;+  float * optr;+  int opitch;++  if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( float ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) )+    return 0;++  stbir_resize_init( &resize,+                     input_pixels,  input_w,  input_h,  input_stride_in_bytes,+                     (optr) ? optr : output_pixels, output_w, output_h, opitch,+                     pixel_layout, STBIR_TYPE_FLOAT );++  if ( !stbir_resize_extended( &resize ) )+  {+    if ( optr )+      STBIR_FREE( optr, 0 );+    return 0;+  }++  return (optr) ? optr : output_pixels;+}+++STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes,+                                    void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+                              stbir_pixel_layout pixel_layout, stbir_datatype data_type,+                              stbir_edge edge, stbir_filter filter )+{+  STBIR_RESIZE resize;+  float * optr;+  int opitch;++  if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, stbir__type_size[data_type], output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) )+    return 0;++  stbir_resize_init( &resize,+                     input_pixels,  input_w,  input_h,  input_stride_in_bytes,+                     (optr) ? optr : output_pixels, output_w, output_h, output_stride_in_bytes,+                     pixel_layout, data_type );++  resize.horizontal_edge = edge;+  resize.vertical_edge = edge;+  resize.horizontal_filter = filter;+  resize.vertical_filter = filter;++  if ( !stbir_resize_extended( &resize ) )+  {+    if ( optr )+      STBIR_FREE( optr, 0 );+    return 0;+  }++  return (optr) ? optr : output_pixels;+}++#ifdef STBIR_PROFILE++STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize )+{+  static char const * bdescriptions[6] = { "Building", "Allocating", "Horizontal sampler", "Vertical sampler", "Coefficient cleanup", "Coefficient piovot" } ;+  stbir__info* samp = resize->samplers;+  int i;++  typedef int testa[ (STBIR__ARRAY_SIZE( bdescriptions ) == (STBIR__ARRAY_SIZE( samp->profile.array )-1) )?1:-1];+  typedef int testb[ (sizeof( samp->profile.array ) == (sizeof(samp->profile.named)) )?1:-1];+  typedef int testc[ (sizeof( info->clocks ) >= (sizeof(samp->profile.named)) )?1:-1];++  for( i = 0 ; i < STBIR__ARRAY_SIZE( bdescriptions ) ; i++)+    info->clocks[i] = samp->profile.array[i+1];++  info->total_clocks = samp->profile.named.total;+  info->descriptions = bdescriptions;+  info->count = STBIR__ARRAY_SIZE( bdescriptions );+}++STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize, int split_start, int split_count )+{+  static char const * descriptions[7] = { "Looping", "Vertical sampling", "Horizontal sampling", "Scanline input", "Scanline output", "Alpha weighting", "Alpha unweighting" };+  stbir__per_split_info * split_info;+  int s, i;++  typedef int testa[ (STBIR__ARRAY_SIZE( descriptions ) == (STBIR__ARRAY_SIZE( split_info->profile.array )-1) )?1:-1];+  typedef int testb[ (sizeof( split_info->profile.array ) == (sizeof(split_info->profile.named)) )?1:-1];+  typedef int testc[ (sizeof( info->clocks ) >= (sizeof(split_info->profile.named)) )?1:-1];++  if ( split_start == -1 )+  {+    split_start = 0;+    split_count = resize->samplers->splits;+  }++  if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) )+  {+    info->total_clocks = 0;+    info->descriptions = 0;+    info->count = 0;+    return;+  }++  split_info = resize->samplers->split_info + split_start;++  // sum up the profile from all the splits+  for( i = 0 ; i < STBIR__ARRAY_SIZE( descriptions ) ; i++ )+  {+    stbir_uint64 sum = 0;+    for( s = 0 ; s < split_count ; s++ )+      sum += split_info[s].profile.array[i+1];+    info->clocks[i] = sum;+  }++  info->total_clocks = split_info->profile.named.total;+  info->descriptions = descriptions;+  info->count = STBIR__ARRAY_SIZE( descriptions );+}++STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize )+{+  stbir_resize_split_profile_info( info, resize, -1, 0 );+}++#endif // STBIR_PROFILE++#undef STBIR_BGR+#undef STBIR_1CHANNEL+#undef STBIR_2CHANNEL+#undef STBIR_RGB+#undef STBIR_RGBA+#undef STBIR_4CHANNEL+#undef STBIR_BGRA+#undef STBIR_ARGB+#undef STBIR_ABGR+#undef STBIR_RA+#undef STBIR_AR+#undef STBIR_RGBA_PM+#undef STBIR_BGRA_PM+#undef STBIR_ARGB_PM+#undef STBIR_ABGR_PM+#undef STBIR_RA_PM+#undef STBIR_AR_PM++#endif // STB_IMAGE_RESIZE_IMPLEMENTATION++#else  // STB_IMAGE_RESIZE_HORIZONTALS&STB_IMAGE_RESIZE_DO_VERTICALS++// we reinclude the header file to define all the horizontal functions+//   specializing each function for the number of coeffs is 20-40% faster *OVERALL*++// by including the header file again this way, we can still debug the functions++#define STBIR_strs_join2( start, mid, end ) start##mid##end+#define STBIR_strs_join1( start, mid, end ) STBIR_strs_join2( start, mid, end )++#define STBIR_strs_join24( start, mid1, mid2, end ) start##mid1##mid2##end+#define STBIR_strs_join14( start, mid1, mid2, end ) STBIR_strs_join24( start, mid1, mid2, end )++#ifdef STB_IMAGE_RESIZE_DO_CODERS++#ifdef stbir__decode_suffix+#define STBIR__CODER_NAME( name ) STBIR_strs_join1( name, _, stbir__decode_suffix )+#else+#define STBIR__CODER_NAME( name ) name+#endif++#ifdef stbir__decode_swizzle+#define stbir__decode_simdf8_flip(reg) STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( stbir__simdf8_0123to,stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3),stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3)(reg, reg)+#define stbir__decode_simdf4_flip(reg) STBIR_strs_join1( STBIR_strs_join1( stbir__simdf_0123to,stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3)(reg, reg)+#define stbir__encode_simdf8_unflip(reg) STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( stbir__simdf8_0123to,stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3),stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3)(reg, reg)+#define stbir__encode_simdf4_unflip(reg) STBIR_strs_join1( STBIR_strs_join1( stbir__simdf_0123to,stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3)(reg, reg)+#else+#define stbir__decode_order0 0+#define stbir__decode_order1 1+#define stbir__decode_order2 2+#define stbir__decode_order3 3+#define stbir__encode_order0 0+#define stbir__encode_order1 1+#define stbir__encode_order2 2+#define stbir__encode_order3 3+#define stbir__decode_simdf8_flip(reg)+#define stbir__decode_simdf4_flip(reg)+#define stbir__encode_simdf8_unflip(reg)+#define stbir__encode_simdf4_unflip(reg)+#endif++#ifdef STBIR_SIMD8+#define stbir__encode_simdfX_unflip  stbir__encode_simdf8_unflip+#else+#define stbir__encode_simdfX_unflip  stbir__encode_simdf4_unflip+#endif++static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * decodep, int width_times_channels, void const * inputp )+{+  float STBIR_STREAMOUT_PTR( * ) decode = decodep;+  float * decode_end = (float*) decode + width_times_channels;+  unsigned char const * input = (unsigned char const*)inputp;++  #ifdef STBIR_SIMD+  unsigned char const * end_input_m16 = input + width_times_channels - 16;+  if ( width_times_channels >= 16 )+  {+    decode_end -= 16;+    STBIR_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      #ifdef STBIR_SIMD8+      stbir__simdi i; stbir__simdi8 o0,o1;+      stbir__simdf8 of0, of1;+      STBIR_NO_UNROLL(decode);+      stbir__simdi_load( i, input );+      stbir__simdi8_expand_u8_to_u32( o0, o1, i );+      stbir__simdi8_convert_i32_to_float( of0, o0 );+      stbir__simdi8_convert_i32_to_float( of1, o1 );+      stbir__simdf8_mult( of0, of0, STBIR_max_uint8_as_float_inverted8);+      stbir__simdf8_mult( of1, of1, STBIR_max_uint8_as_float_inverted8);+      stbir__decode_simdf8_flip( of0 );+      stbir__decode_simdf8_flip( of1 );+      stbir__simdf8_store( decode + 0, of0 );+      stbir__simdf8_store( decode + 8, of1 );+      #else+      stbir__simdi i, o0, o1, o2, o3;+      stbir__simdf of0, of1, of2, of3;+      STBIR_NO_UNROLL(decode);+      stbir__simdi_load( i, input );+      stbir__simdi_expand_u8_to_u32( o0,o1,o2,o3,i);+      stbir__simdi_convert_i32_to_float( of0, o0 );+      stbir__simdi_convert_i32_to_float( of1, o1 );+      stbir__simdi_convert_i32_to_float( of2, o2 );+      stbir__simdi_convert_i32_to_float( of3, o3 );+      stbir__simdf_mult( of0, of0, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) );+      stbir__simdf_mult( of1, of1, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) );+      stbir__simdf_mult( of2, of2, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) );+      stbir__simdf_mult( of3, of3, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) );+      stbir__decode_simdf4_flip( of0 );+      stbir__decode_simdf4_flip( of1 );+      stbir__decode_simdf4_flip( of2 );+      stbir__decode_simdf4_flip( of3 );+      stbir__simdf_store( decode + 0,  of0 );+      stbir__simdf_store( decode + 4,  of1 );+      stbir__simdf_store( decode + 8,  of2 );+      stbir__simdf_store( decode + 12, of3 );+      #endif+      decode += 16;+      input += 16;+      if ( decode <= decode_end )+        continue;+      if ( decode == ( decode_end + 16 ) )+        break;+      decode = decode_end; // backup and do last couple+      input = end_input_m16;+    }+    return;+  }+  #endif++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  decode += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( decode <= decode_end )+  {+    STBIR_SIMD_NO_UNROLL(decode);+    decode[0-4] = ((float)(input[stbir__decode_order0])) * stbir__max_uint8_as_float_inverted;+    decode[1-4] = ((float)(input[stbir__decode_order1])) * stbir__max_uint8_as_float_inverted;+    decode[2-4] = ((float)(input[stbir__decode_order2])) * stbir__max_uint8_as_float_inverted;+    decode[3-4] = ((float)(input[stbir__decode_order3])) * stbir__max_uint8_as_float_inverted;+    decode += 4;+    input += 4;+  }+  decode -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( decode < decode_end )+  {+    STBIR_NO_UNROLL(decode);+    decode[0] = ((float)(input[stbir__decode_order0])) * stbir__max_uint8_as_float_inverted;+    #if stbir__coder_min_num >= 2+    decode[1] = ((float)(input[stbir__decode_order1])) * stbir__max_uint8_as_float_inverted;+    #endif+    #if stbir__coder_min_num >= 3+    decode[2] = ((float)(input[stbir__decode_order2])) * stbir__max_uint8_as_float_inverted;+    #endif+    decode += stbir__coder_min_num;+    input += stbir__coder_min_num;+  }+  #endif+}++static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outputp, int width_times_channels, float const * encode )+{+  unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char *) outputp;+  unsigned char * end_output = ( (unsigned char *) output ) + width_times_channels;++  #ifdef STBIR_SIMD+  if ( width_times_channels >= stbir__simdfX_float_count*2 )+  {+    float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2;+    end_output -= stbir__simdfX_float_count*2;+    STBIR_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      stbir__simdfX e0, e1;+      stbir__simdi i;+      STBIR_SIMD_NO_UNROLL(encode);+      stbir__simdfX_madd_mem( e0, STBIR_simd_point5X, STBIR_max_uint8_as_floatX, encode );+      stbir__simdfX_madd_mem( e1, STBIR_simd_point5X, STBIR_max_uint8_as_floatX, encode+stbir__simdfX_float_count );+      stbir__encode_simdfX_unflip( e0 );+      stbir__encode_simdfX_unflip( e1 );+      #ifdef STBIR_SIMD8+      stbir__simdf8_pack_to_16bytes( i, e0, e1 );+      stbir__simdi_store( output, i );+      #else+      stbir__simdf_pack_to_8bytes( i, e0, e1 );+      stbir__simdi_store2( output, i );+      #endif+      encode += stbir__simdfX_float_count*2;+      output += stbir__simdfX_float_count*2;+      if ( output <= end_output )+        continue;+      if ( output == ( end_output + stbir__simdfX_float_count*2 ) )+        break;+      output = end_output; // backup and do last couple+      encode = end_encode_m8;+    }+    return;+  }++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  STBIR_NO_UNROLL_LOOP_START+  while( output <= end_output )+  {+    stbir__simdf e0;+    stbir__simdi i0;+    STBIR_NO_UNROLL(encode);+    stbir__simdf_load( e0, encode );+    stbir__simdf_madd( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), e0 );+    stbir__encode_simdf4_unflip( e0 );+    stbir__simdf_pack_to_8bytes( i0, e0, e0 );  // only use first 4+    *(int*)(output-4) = stbir__simdi_to_int( i0 );+    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( output < end_output )+  {+    stbir__simdf e0;+    STBIR_NO_UNROLL(encode);+    stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_uint8( e0 );+    #if stbir__coder_min_num >= 2+    stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order1 ); output[1] = stbir__simdf_convert_float_to_uint8( e0 );+    #endif+    #if stbir__coder_min_num >= 3+    stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order2 ); output[2] = stbir__simdf_convert_float_to_uint8( e0 );+    #endif+    output += stbir__coder_min_num;+    encode += stbir__coder_min_num;+  }+  #endif++  #else++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  while( output <= end_output )+  {+    float f;+    f = encode[stbir__encode_order0] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[0-4] = (unsigned char)f;+    f = encode[stbir__encode_order1] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[1-4] = (unsigned char)f;+    f = encode[stbir__encode_order2] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[2-4] = (unsigned char)f;+    f = encode[stbir__encode_order3] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[3-4] = (unsigned char)f;+    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( output < end_output )+  {+    float f;+    STBIR_NO_UNROLL(encode);+    f = encode[stbir__encode_order0] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[0] = (unsigned char)f;+    #if stbir__coder_min_num >= 2+    f = encode[stbir__encode_order1] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[1] = (unsigned char)f;+    #endif+    #if stbir__coder_min_num >= 3+    f = encode[stbir__encode_order2] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[2] = (unsigned char)f;+    #endif+    output += stbir__coder_min_num;+    encode += stbir__coder_min_num;+  }+  #endif+  #endif+}++static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int width_times_channels, void const * inputp )+{+  float STBIR_STREAMOUT_PTR( * ) decode = decodep;+  float * decode_end = (float*) decode + width_times_channels;+  unsigned char const * input = (unsigned char const*)inputp;++  #ifdef STBIR_SIMD+  unsigned char const * end_input_m16 = input + width_times_channels - 16;+  if ( width_times_channels >= 16 )+  {+    decode_end -= 16;+    STBIR_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      #ifdef STBIR_SIMD8+      stbir__simdi i; stbir__simdi8 o0,o1;+      stbir__simdf8 of0, of1;+      STBIR_NO_UNROLL(decode);+      stbir__simdi_load( i, input );+      stbir__simdi8_expand_u8_to_u32( o0, o1, i );+      stbir__simdi8_convert_i32_to_float( of0, o0 );+      stbir__simdi8_convert_i32_to_float( of1, o1 );+      stbir__decode_simdf8_flip( of0 );+      stbir__decode_simdf8_flip( of1 );+      stbir__simdf8_store( decode + 0, of0 );+      stbir__simdf8_store( decode + 8, of1 );+      #else+      stbir__simdi i, o0, o1, o2, o3;+      stbir__simdf of0, of1, of2, of3;+      STBIR_NO_UNROLL(decode);+      stbir__simdi_load( i, input );+      stbir__simdi_expand_u8_to_u32( o0,o1,o2,o3,i);+      stbir__simdi_convert_i32_to_float( of0, o0 );+      stbir__simdi_convert_i32_to_float( of1, o1 );+      stbir__simdi_convert_i32_to_float( of2, o2 );+      stbir__simdi_convert_i32_to_float( of3, o3 );+      stbir__decode_simdf4_flip( of0 );+      stbir__decode_simdf4_flip( of1 );+      stbir__decode_simdf4_flip( of2 );+      stbir__decode_simdf4_flip( of3 );+      stbir__simdf_store( decode + 0,  of0 );+      stbir__simdf_store( decode + 4,  of1 );+      stbir__simdf_store( decode + 8,  of2 );+      stbir__simdf_store( decode + 12, of3 );+#endif+      decode += 16;+      input += 16;+      if ( decode <= decode_end )+        continue;+      if ( decode == ( decode_end + 16 ) )+        break;+      decode = decode_end; // backup and do last couple+      input = end_input_m16;+    }+    return;+  }+  #endif++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  decode += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( decode <= decode_end )+  {+    STBIR_SIMD_NO_UNROLL(decode);+    decode[0-4] = ((float)(input[stbir__decode_order0]));+    decode[1-4] = ((float)(input[stbir__decode_order1]));+    decode[2-4] = ((float)(input[stbir__decode_order2]));+    decode[3-4] = ((float)(input[stbir__decode_order3]));+    decode += 4;+    input += 4;+  }+  decode -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( decode < decode_end )+  {+    STBIR_NO_UNROLL(decode);+    decode[0] = ((float)(input[stbir__decode_order0]));+    #if stbir__coder_min_num >= 2+    decode[1] = ((float)(input[stbir__decode_order1]));+    #endif+    #if stbir__coder_min_num >= 3+    decode[2] = ((float)(input[stbir__decode_order2]));+    #endif+    decode += stbir__coder_min_num;+    input += stbir__coder_min_num;+  }+  #endif+}++static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int width_times_channels, float const * encode )+{+  unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char *) outputp;+  unsigned char * end_output = ( (unsigned char *) output ) + width_times_channels;++  #ifdef STBIR_SIMD+  if ( width_times_channels >= stbir__simdfX_float_count*2 )+  {+    float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2;+    end_output -= stbir__simdfX_float_count*2;+    STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      stbir__simdfX e0, e1;+      stbir__simdi i;+      STBIR_SIMD_NO_UNROLL(encode);+      stbir__simdfX_add_mem( e0, STBIR_simd_point5X, encode );+      stbir__simdfX_add_mem( e1, STBIR_simd_point5X, encode+stbir__simdfX_float_count );+      stbir__encode_simdfX_unflip( e0 );+      stbir__encode_simdfX_unflip( e1 );+      #ifdef STBIR_SIMD8+      stbir__simdf8_pack_to_16bytes( i, e0, e1 );+      stbir__simdi_store( output, i );+      #else+      stbir__simdf_pack_to_8bytes( i, e0, e1 );+      stbir__simdi_store2( output, i );+      #endif+      encode += stbir__simdfX_float_count*2;+      output += stbir__simdfX_float_count*2;+      if ( output <= end_output )+        continue;+      if ( output == ( end_output + stbir__simdfX_float_count*2 ) )+        break;+      output = end_output; // backup and do last couple+      encode = end_encode_m8;+    }+    return;+  }++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  STBIR_NO_UNROLL_LOOP_START+  while( output <= end_output )+  {+    stbir__simdf e0;+    stbir__simdi i0;+    STBIR_NO_UNROLL(encode);+    stbir__simdf_load( e0, encode );+    stbir__simdf_add( e0, STBIR__CONSTF(STBIR_simd_point5), e0 );+    stbir__encode_simdf4_unflip( e0 );+    stbir__simdf_pack_to_8bytes( i0, e0, e0 );  // only use first 4+    *(int*)(output-4) = stbir__simdi_to_int( i0 );+    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  #else++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  while( output <= end_output )+  {+    float f;+    f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 255); output[0-4] = (unsigned char)f;+    f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 255); output[1-4] = (unsigned char)f;+    f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 255); output[2-4] = (unsigned char)f;+    f = encode[stbir__encode_order3] + 0.5f; STBIR_CLAMP(f, 0, 255); output[3-4] = (unsigned char)f;+    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( output < end_output )+  {+    float f;+    STBIR_NO_UNROLL(encode);+    f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 255); output[0] = (unsigned char)f;+    #if stbir__coder_min_num >= 2+    f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 255); output[1] = (unsigned char)f;+    #endif+    #if stbir__coder_min_num >= 3+    f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 255); output[2] = (unsigned char)f;+    #endif+    output += stbir__coder_min_num;+    encode += stbir__coder_min_num;+  }+  #endif+}++static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int width_times_channels, void const * inputp )+{+  float STBIR_STREAMOUT_PTR( * ) decode = decodep;+  float const * decode_end = (float*) decode + width_times_channels;+  unsigned char const * input = (unsigned char const *)inputp;++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  decode += 4;+  while( decode <= decode_end )+  {+    decode[0-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order0 ] ];+    decode[1-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order1 ] ];+    decode[2-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order2 ] ];+    decode[3-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order3 ] ];+    decode += 4;+    input += 4;+  }+  decode -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( decode < decode_end )+  {+    STBIR_NO_UNROLL(decode);+    decode[0] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order0 ] ];+    #if stbir__coder_min_num >= 2+    decode[1] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order1 ] ];+    #endif+    #if stbir__coder_min_num >= 3+    decode[2] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order2 ] ];+    #endif+    decode += stbir__coder_min_num;+    input += stbir__coder_min_num;+  }+  #endif+}++#define stbir__min_max_shift20( i, f ) \+    stbir__simdf_max( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_zero )) ); \+    stbir__simdf_min( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_one  )) ); \+    stbir__simdi_32shr( i, stbir_simdi_castf( f ), 20 );++#define stbir__scale_and_convert( i, f ) \+    stbir__simdf_madd( f, STBIR__CONSTF( STBIR_simd_point5 ), STBIR__CONSTF( STBIR_max_uint8_as_float ), f ); \+    stbir__simdf_max( f, f, stbir__simdf_zeroP() ); \+    stbir__simdf_min( f, f, STBIR__CONSTF( STBIR_max_uint8_as_float ) ); \+    stbir__simdf_convert_float_to_i32( i, f );++#define stbir__linear_to_srgb_finish( i, f ) \+{ \+    stbir__simdi temp;  \+    stbir__simdi_32shr( temp, stbir_simdi_castf( f ), 12 ) ; \+    stbir__simdi_and( temp, temp, STBIR__CONSTI(STBIR_mastissa_mask) ); \+    stbir__simdi_or( temp, temp, STBIR__CONSTI(STBIR_topscale) ); \+    stbir__simdi_16madd( i, i, temp ); \+    stbir__simdi_32shr( i, i, 16 ); \+}++#define stbir__simdi_table_lookup2( v0,v1, table ) \+{ \+  stbir__simdi_u32 temp0,temp1; \+  temp0.m128i_i128 = v0; \+  temp1.m128i_i128 = v1; \+  temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \+  temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \+  v0 = temp0.m128i_i128; \+  v1 = temp1.m128i_i128; \+}++#define stbir__simdi_table_lookup3( v0,v1,v2, table ) \+{ \+  stbir__simdi_u32 temp0,temp1,temp2; \+  temp0.m128i_i128 = v0; \+  temp1.m128i_i128 = v1; \+  temp2.m128i_i128 = v2; \+  temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \+  temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \+  temp2.m128i_u32[0] = table[temp2.m128i_i32[0]]; temp2.m128i_u32[1] = table[temp2.m128i_i32[1]]; temp2.m128i_u32[2] = table[temp2.m128i_i32[2]]; temp2.m128i_u32[3] = table[temp2.m128i_i32[3]]; \+  v0 = temp0.m128i_i128; \+  v1 = temp1.m128i_i128; \+  v2 = temp2.m128i_i128; \+}++#define stbir__simdi_table_lookup4( v0,v1,v2,v3, table ) \+{ \+  stbir__simdi_u32 temp0,temp1,temp2,temp3; \+  temp0.m128i_i128 = v0; \+  temp1.m128i_i128 = v1; \+  temp2.m128i_i128 = v2; \+  temp3.m128i_i128 = v3; \+  temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \+  temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \+  temp2.m128i_u32[0] = table[temp2.m128i_i32[0]]; temp2.m128i_u32[1] = table[temp2.m128i_i32[1]]; temp2.m128i_u32[2] = table[temp2.m128i_i32[2]]; temp2.m128i_u32[3] = table[temp2.m128i_i32[3]]; \+  temp3.m128i_u32[0] = table[temp3.m128i_i32[0]]; temp3.m128i_u32[1] = table[temp3.m128i_i32[1]]; temp3.m128i_u32[2] = table[temp3.m128i_i32[2]]; temp3.m128i_u32[3] = table[temp3.m128i_i32[3]]; \+  v0 = temp0.m128i_i128; \+  v1 = temp1.m128i_i128; \+  v2 = temp2.m128i_i128; \+  v3 = temp3.m128i_i128; \+}++static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int width_times_channels, float const * encode )+{+  unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp;+  unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels;++  #ifdef STBIR_SIMD++  if ( width_times_channels >= 16 )+  {+    float const * end_encode_m16 = encode + width_times_channels - 16;+    end_output -= 16;+    STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      stbir__simdf f0, f1, f2, f3;+      stbir__simdi i0, i1, i2, i3;+      STBIR_SIMD_NO_UNROLL(encode);++      stbir__simdf_load4_transposed( f0, f1, f2, f3, encode );++      stbir__min_max_shift20( i0, f0 );+      stbir__min_max_shift20( i1, f1 );+      stbir__min_max_shift20( i2, f2 );+      stbir__min_max_shift20( i3, f3 );++      stbir__simdi_table_lookup4( i0, i1, i2, i3, ( fp32_to_srgb8_tab4 - (127-13)*8 ) );++      stbir__linear_to_srgb_finish( i0, f0 );+      stbir__linear_to_srgb_finish( i1, f1 );+      stbir__linear_to_srgb_finish( i2, f2 );+      stbir__linear_to_srgb_finish( i3, f3 );++      stbir__interleave_pack_and_store_16_u8( output,  STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) );++      encode += 16;+      output += 16;+      if ( output <= end_output )+        continue;+      if ( output == ( end_output + 16 ) )+        break;+      output = end_output; // backup and do last couple+      encode = end_encode_m16;+    }+    return;+  }+  #endif++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while ( output <= end_output )+  {+    STBIR_SIMD_NO_UNROLL(encode);++    output[0-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] );+    output[1-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order1] );+    output[2-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order2] );+    output[3-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order3] );++    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( output < end_output )+  {+    STBIR_NO_UNROLL(encode);+    output[0] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] );+    #if stbir__coder_min_num >= 2+    output[1] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order1] );+    #endif+    #if stbir__coder_min_num >= 3+    output[2] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order2] );+    #endif+    output += stbir__coder_min_num;+    encode += stbir__coder_min_num;+  }+  #endif+}++#if ( stbir__coder_min_num == 4 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) )++static void STBIR__CODER_NAME(stbir__decode_uint8_srgb4_linearalpha)( float * decodep, int width_times_channels, void const * inputp )+{+  float STBIR_STREAMOUT_PTR( * ) decode = decodep;+  float const * decode_end = (float*) decode + width_times_channels;+  unsigned char const * input = (unsigned char const *)inputp;+  do {+    decode[0] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ];+    decode[1] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order1] ];+    decode[2] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order2] ];+    decode[3] = ( (float) input[stbir__decode_order3] ) * stbir__max_uint8_as_float_inverted;+    input += 4;+    decode += 4;+  } while( decode < decode_end );+}+++static void STBIR__CODER_NAME( stbir__encode_uint8_srgb4_linearalpha )( void * outputp, int width_times_channels, float const * encode )+{+  unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp;+  unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels;++  #ifdef STBIR_SIMD++  if ( width_times_channels >= 16 )+  {+    float const * end_encode_m16 = encode + width_times_channels - 16;+    end_output -= 16;+    STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      stbir__simdf f0, f1, f2, f3;+      stbir__simdi i0, i1, i2, i3;++      STBIR_SIMD_NO_UNROLL(encode);+      stbir__simdf_load4_transposed( f0, f1, f2, f3, encode );++      stbir__min_max_shift20( i0, f0 );+      stbir__min_max_shift20( i1, f1 );+      stbir__min_max_shift20( i2, f2 );+      stbir__scale_and_convert( i3, f3 );++      stbir__simdi_table_lookup3( i0, i1, i2, ( fp32_to_srgb8_tab4 - (127-13)*8 ) );++      stbir__linear_to_srgb_finish( i0, f0 );+      stbir__linear_to_srgb_finish( i1, f1 );+      stbir__linear_to_srgb_finish( i2, f2 );++      stbir__interleave_pack_and_store_16_u8( output,  STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) );++      output += 16;+      encode += 16;++      if ( output <= end_output )+        continue;+      if ( output == ( end_output + 16 ) )+        break;+      output = end_output; // backup and do last couple+      encode = end_encode_m16;+    }+    return;+  }+  #endif++  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float f;+    STBIR_SIMD_NO_UNROLL(encode);++    output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] );+    output[stbir__decode_order1] = stbir__linear_to_srgb_uchar( encode[1] );+    output[stbir__decode_order2] = stbir__linear_to_srgb_uchar( encode[2] );++    f = encode[3] * stbir__max_uint8_as_float + 0.5f;+    STBIR_CLAMP(f, 0, 255);+    output[stbir__decode_order3] = (unsigned char) f;++    output += 4;+    encode += 4;+  } while( output < end_output );+}++#endif++#if ( stbir__coder_min_num == 2 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) )++static void STBIR__CODER_NAME(stbir__decode_uint8_srgb2_linearalpha)( float * decodep, int width_times_channels, void const * inputp )+{+  float STBIR_STREAMOUT_PTR( * ) decode = decodep;+  float const * decode_end = (float*) decode + width_times_channels;+  unsigned char const * input = (unsigned char const *)inputp;+  decode += 4;+  while( decode <= decode_end )+  {+    decode[0-4] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ];+    decode[1-4] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted;+    decode[2-4] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0+2] ];+    decode[3-4] = ( (float) input[stbir__decode_order1+2] ) * stbir__max_uint8_as_float_inverted;+    input += 4;+    decode += 4;+  }+  decode -= 4;+  if( decode < decode_end )+  {+    decode[0] = stbir__srgb_uchar_to_linear_float[ stbir__decode_order0 ];+    decode[1] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted;+  }+}++static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * outputp, int width_times_channels, float const * encode )+{+  unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp;+  unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels;++  #ifdef STBIR_SIMD++  if ( width_times_channels >= 16 )+  {+    float const * end_encode_m16 = encode + width_times_channels - 16;+    end_output -= 16;+    STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      stbir__simdf f0, f1, f2, f3;+      stbir__simdi i0, i1, i2, i3;++      STBIR_SIMD_NO_UNROLL(encode);+      stbir__simdf_load4_transposed( f0, f1, f2, f3, encode );++      stbir__min_max_shift20( i0, f0 );+      stbir__scale_and_convert( i1, f1 );+      stbir__min_max_shift20( i2, f2 );+      stbir__scale_and_convert( i3, f3 );++      stbir__simdi_table_lookup2( i0, i2, ( fp32_to_srgb8_tab4 - (127-13)*8 ) );++      stbir__linear_to_srgb_finish( i0, f0 );+      stbir__linear_to_srgb_finish( i2, f2 );++      stbir__interleave_pack_and_store_16_u8( output,  STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) );++      output += 16;+      encode += 16;+      if ( output <= end_output )+        continue;+      if ( output == ( end_output + 16 ) )+        break;+      output = end_output; // backup and do last couple+      encode = end_encode_m16;+    }+    return;+  }+  #endif++  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float f;+    STBIR_SIMD_NO_UNROLL(encode);++    output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] );++    f = encode[1] * stbir__max_uint8_as_float + 0.5f;+    STBIR_CLAMP(f, 0, 255);+    output[stbir__decode_order1] = (unsigned char) f;++    output += 2;+    encode += 2;+  } while( output < end_output );+}++#endif++static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decodep, int width_times_channels, void const * inputp )+{+  float STBIR_STREAMOUT_PTR( * ) decode = decodep;+  float * decode_end = (float*) decode + width_times_channels;+  unsigned short const * input = (unsigned short const *)inputp;++  #ifdef STBIR_SIMD+  unsigned short const * end_input_m8 = input + width_times_channels - 8;+  if ( width_times_channels >= 8 )+  {+    decode_end -= 8;+    STBIR_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      #ifdef STBIR_SIMD8+      stbir__simdi i; stbir__simdi8 o;+      stbir__simdf8 of;+      STBIR_NO_UNROLL(decode);+      stbir__simdi_load( i, input );+      stbir__simdi8_expand_u16_to_u32( o, i );+      stbir__simdi8_convert_i32_to_float( of, o );+      stbir__simdf8_mult( of, of, STBIR_max_uint16_as_float_inverted8);+      stbir__decode_simdf8_flip( of );+      stbir__simdf8_store( decode + 0, of );+      #else+      stbir__simdi i, o0, o1;+      stbir__simdf of0, of1;+      STBIR_NO_UNROLL(decode);+      stbir__simdi_load( i, input );+      stbir__simdi_expand_u16_to_u32( o0,o1,i );+      stbir__simdi_convert_i32_to_float( of0, o0 );+      stbir__simdi_convert_i32_to_float( of1, o1 );+      stbir__simdf_mult( of0, of0, STBIR__CONSTF(STBIR_max_uint16_as_float_inverted) );+      stbir__simdf_mult( of1, of1, STBIR__CONSTF(STBIR_max_uint16_as_float_inverted));+      stbir__decode_simdf4_flip( of0 );+      stbir__decode_simdf4_flip( of1 );+      stbir__simdf_store( decode + 0,  of0 );+      stbir__simdf_store( decode + 4,  of1 );+      #endif+      decode += 8;+      input += 8;+      if ( decode <= decode_end )+        continue;+      if ( decode == ( decode_end + 8 ) )+        break;+      decode = decode_end; // backup and do last couple+      input = end_input_m8;+    }+    return;+  }+  #endif++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  decode += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( decode <= decode_end )+  {+    STBIR_SIMD_NO_UNROLL(decode);+    decode[0-4] = ((float)(input[stbir__decode_order0])) * stbir__max_uint16_as_float_inverted;+    decode[1-4] = ((float)(input[stbir__decode_order1])) * stbir__max_uint16_as_float_inverted;+    decode[2-4] = ((float)(input[stbir__decode_order2])) * stbir__max_uint16_as_float_inverted;+    decode[3-4] = ((float)(input[stbir__decode_order3])) * stbir__max_uint16_as_float_inverted;+    decode += 4;+    input += 4;+  }+  decode -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( decode < decode_end )+  {+    STBIR_NO_UNROLL(decode);+    decode[0] = ((float)(input[stbir__decode_order0])) * stbir__max_uint16_as_float_inverted;+    #if stbir__coder_min_num >= 2+    decode[1] = ((float)(input[stbir__decode_order1])) * stbir__max_uint16_as_float_inverted;+    #endif+    #if stbir__coder_min_num >= 3+    decode[2] = ((float)(input[stbir__decode_order2])) * stbir__max_uint16_as_float_inverted;+    #endif+    decode += stbir__coder_min_num;+    input += stbir__coder_min_num;+  }+  #endif+}+++static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * outputp, int width_times_channels, float const * encode )+{+  unsigned short STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned short*) outputp;+  unsigned short * end_output = ( (unsigned short*) output ) + width_times_channels;++  #ifdef STBIR_SIMD+  {+    if ( width_times_channels >= stbir__simdfX_float_count*2 )+    {+      float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2;+      end_output -= stbir__simdfX_float_count*2;+      STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR+      for(;;)+      {+        stbir__simdfX e0, e1;+        stbir__simdiX i;+        STBIR_SIMD_NO_UNROLL(encode);+        stbir__simdfX_madd_mem( e0, STBIR_simd_point5X, STBIR_max_uint16_as_floatX, encode );+        stbir__simdfX_madd_mem( e1, STBIR_simd_point5X, STBIR_max_uint16_as_floatX, encode+stbir__simdfX_float_count );+        stbir__encode_simdfX_unflip( e0 );+        stbir__encode_simdfX_unflip( e1 );+        stbir__simdfX_pack_to_words( i, e0, e1 );+        stbir__simdiX_store( output, i );+        encode += stbir__simdfX_float_count*2;+        output += stbir__simdfX_float_count*2;+        if ( output <= end_output )+          continue;+        if ( output == ( end_output + stbir__simdfX_float_count*2 ) )+          break;+        output = end_output;     // backup and do last couple+        encode = end_encode_m8;+      }+      return;+    }+  }++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  STBIR_NO_UNROLL_LOOP_START+  while( output <= end_output )+  {+    stbir__simdf e;+    stbir__simdi i;+    STBIR_NO_UNROLL(encode);+    stbir__simdf_load( e, encode );+    stbir__simdf_madd( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), e );+    stbir__encode_simdf4_unflip( e );+    stbir__simdf_pack_to_8words( i, e, e );  // only use first 4+    stbir__simdi_store2( output-4, i );+    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( output < end_output )+  {+    stbir__simdf e;+    STBIR_NO_UNROLL(encode);+    stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_short( e );+    #if stbir__coder_min_num >= 2+    stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order1 ); output[1] = stbir__simdf_convert_float_to_short( e );+    #endif+    #if stbir__coder_min_num >= 3+    stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order2 ); output[2] = stbir__simdf_convert_float_to_short( e );+    #endif+    output += stbir__coder_min_num;+    encode += stbir__coder_min_num;+  }+  #endif++  #else++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( output <= end_output )+  {+    float f;+    STBIR_SIMD_NO_UNROLL(encode);+    f = encode[stbir__encode_order0] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0-4] = (unsigned short)f;+    f = encode[stbir__encode_order1] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1-4] = (unsigned short)f;+    f = encode[stbir__encode_order2] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2-4] = (unsigned short)f;+    f = encode[stbir__encode_order3] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[3-4] = (unsigned short)f;+    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( output < end_output )+  {+    float f;+    STBIR_NO_UNROLL(encode);+    f = encode[stbir__encode_order0] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0] = (unsigned short)f;+    #if stbir__coder_min_num >= 2+    f = encode[stbir__encode_order1] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1] = (unsigned short)f;+    #endif+    #if stbir__coder_min_num >= 3+    f = encode[stbir__encode_order2] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2] = (unsigned short)f;+    #endif+    output += stbir__coder_min_num;+    encode += stbir__coder_min_num;+  }+  #endif+  #endif+}++static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int width_times_channels, void const * inputp )+{+  float STBIR_STREAMOUT_PTR( * ) decode = decodep;+  float * decode_end = (float*) decode + width_times_channels;+  unsigned short const * input = (unsigned short const *)inputp;++  #ifdef STBIR_SIMD+  unsigned short const * end_input_m8 = input + width_times_channels - 8;+  if ( width_times_channels >= 8 )+  {+    decode_end -= 8;+    STBIR_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      #ifdef STBIR_SIMD8+      stbir__simdi i; stbir__simdi8 o;+      stbir__simdf8 of;+      STBIR_NO_UNROLL(decode);+      stbir__simdi_load( i, input );+      stbir__simdi8_expand_u16_to_u32( o, i );+      stbir__simdi8_convert_i32_to_float( of, o );+      stbir__decode_simdf8_flip( of );+      stbir__simdf8_store( decode + 0, of );+      #else+      stbir__simdi i, o0, o1;+      stbir__simdf of0, of1;+      STBIR_NO_UNROLL(decode);+      stbir__simdi_load( i, input );+      stbir__simdi_expand_u16_to_u32( o0, o1, i );+      stbir__simdi_convert_i32_to_float( of0, o0 );+      stbir__simdi_convert_i32_to_float( of1, o1 );+      stbir__decode_simdf4_flip( of0 );+      stbir__decode_simdf4_flip( of1 );+      stbir__simdf_store( decode + 0,  of0 );+      stbir__simdf_store( decode + 4,  of1 );+      #endif+      decode += 8;+      input += 8;+      if ( decode <= decode_end )+        continue;+      if ( decode == ( decode_end + 8 ) )+        break;+      decode = decode_end; // backup and do last couple+      input = end_input_m8;+    }+    return;+  }+  #endif++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  decode += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( decode <= decode_end )+  {+    STBIR_SIMD_NO_UNROLL(decode);+    decode[0-4] = ((float)(input[stbir__decode_order0]));+    decode[1-4] = ((float)(input[stbir__decode_order1]));+    decode[2-4] = ((float)(input[stbir__decode_order2]));+    decode[3-4] = ((float)(input[stbir__decode_order3]));+    decode += 4;+    input += 4;+  }+  decode -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( decode < decode_end )+  {+    STBIR_NO_UNROLL(decode);+    decode[0] = ((float)(input[stbir__decode_order0]));+    #if stbir__coder_min_num >= 2+    decode[1] = ((float)(input[stbir__decode_order1]));+    #endif+    #if stbir__coder_min_num >= 3+    decode[2] = ((float)(input[stbir__decode_order2]));+    #endif+    decode += stbir__coder_min_num;+    input += stbir__coder_min_num;+  }+  #endif+}++static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int width_times_channels, float const * encode )+{+  unsigned short STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned short*) outputp;+  unsigned short * end_output = ( (unsigned short*) output ) + width_times_channels;++  #ifdef STBIR_SIMD+  {+    if ( width_times_channels >= stbir__simdfX_float_count*2 )+    {+      float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2;+      end_output -= stbir__simdfX_float_count*2;+      STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR+      for(;;)+      {+        stbir__simdfX e0, e1;+        stbir__simdiX i;+        STBIR_SIMD_NO_UNROLL(encode);+        stbir__simdfX_add_mem( e0, STBIR_simd_point5X, encode );+        stbir__simdfX_add_mem( e1, STBIR_simd_point5X, encode+stbir__simdfX_float_count );+        stbir__encode_simdfX_unflip( e0 );+        stbir__encode_simdfX_unflip( e1 );+        stbir__simdfX_pack_to_words( i, e0, e1 );+        stbir__simdiX_store( output, i );+        encode += stbir__simdfX_float_count*2;+        output += stbir__simdfX_float_count*2;+        if ( output <= end_output )+          continue;+        if ( output == ( end_output + stbir__simdfX_float_count*2 ) )+          break;+        output = end_output; // backup and do last couple+        encode = end_encode_m8;+      }+      return;+    }+  }++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  STBIR_NO_UNROLL_LOOP_START+  while( output <= end_output )+  {+    stbir__simdf e;+    stbir__simdi i;+    STBIR_NO_UNROLL(encode);+    stbir__simdf_load( e, encode );+    stbir__simdf_add( e, STBIR__CONSTF(STBIR_simd_point5), e );+    stbir__encode_simdf4_unflip( e );+    stbir__simdf_pack_to_8words( i, e, e );  // only use first 4+    stbir__simdi_store2( output-4, i );+    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  #else++  // try to do blocks of 4 when you can+  #if  stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( output <= end_output )+  {+    float f;+    STBIR_SIMD_NO_UNROLL(encode);+    f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0-4] = (unsigned short)f;+    f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1-4] = (unsigned short)f;+    f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2-4] = (unsigned short)f;+    f = encode[stbir__encode_order3] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[3-4] = (unsigned short)f;+    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( output < end_output )+  {+    float f;+    STBIR_NO_UNROLL(encode);+    f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0] = (unsigned short)f;+    #if stbir__coder_min_num >= 2+    f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1] = (unsigned short)f;+    #endif+    #if stbir__coder_min_num >= 3+    f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2] = (unsigned short)f;+    #endif+    output += stbir__coder_min_num;+    encode += stbir__coder_min_num;+  }+  #endif+}++static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, int width_times_channels, void const * inputp )+{+  float STBIR_STREAMOUT_PTR( * ) decode = decodep;+  float * decode_end = (float*) decode + width_times_channels;+  stbir__FP16 const * input = (stbir__FP16 const *)inputp;++  #ifdef STBIR_SIMD+  if ( width_times_channels >= 8 )+  {+    stbir__FP16 const * end_input_m8 = input + width_times_channels - 8;+    decode_end -= 8;+    STBIR_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      STBIR_NO_UNROLL(decode);++      stbir__half_to_float_SIMD( decode, input );+      #ifdef stbir__decode_swizzle+      #ifdef STBIR_SIMD8+      {+        stbir__simdf8 of;+        stbir__simdf8_load( of, decode );+        stbir__decode_simdf8_flip( of );+        stbir__simdf8_store( decode, of );+      }+      #else+      {+        stbir__simdf of0,of1;+        stbir__simdf_load( of0, decode );+        stbir__simdf_load( of1, decode+4 );+        stbir__decode_simdf4_flip( of0 );+        stbir__decode_simdf4_flip( of1 );+        stbir__simdf_store( decode, of0 );+        stbir__simdf_store( decode+4, of1 );+      }+      #endif+      #endif+      decode += 8;+      input += 8;+      if ( decode <= decode_end )+        continue;+      if ( decode == ( decode_end + 8 ) )+        break;+      decode = decode_end; // backup and do last couple+      input = end_input_m8;+    }+    return;+  }+  #endif++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  decode += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( decode <= decode_end )+  {+    STBIR_SIMD_NO_UNROLL(decode);+    decode[0-4] = stbir__half_to_float(input[stbir__decode_order0]);+    decode[1-4] = stbir__half_to_float(input[stbir__decode_order1]);+    decode[2-4] = stbir__half_to_float(input[stbir__decode_order2]);+    decode[3-4] = stbir__half_to_float(input[stbir__decode_order3]);+    decode += 4;+    input += 4;+  }+  decode -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( decode < decode_end )+  {+    STBIR_NO_UNROLL(decode);+    decode[0] = stbir__half_to_float(input[stbir__decode_order0]);+    #if stbir__coder_min_num >= 2+    decode[1] = stbir__half_to_float(input[stbir__decode_order1]);+    #endif+    #if stbir__coder_min_num >= 3+    decode[2] = stbir__half_to_float(input[stbir__decode_order2]);+    #endif+    decode += stbir__coder_min_num;+    input += stbir__coder_min_num;+  }+  #endif+}++static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp, int width_times_channels, float const * encode )+{+  stbir__FP16 STBIR_SIMD_STREAMOUT_PTR( * ) output = (stbir__FP16*) outputp;+  stbir__FP16 * end_output = ( (stbir__FP16*) output ) + width_times_channels;++  #ifdef STBIR_SIMD+  if ( width_times_channels >= 8 )+  {+    float const * end_encode_m8 = encode + width_times_channels - 8;+    end_output -= 8;+    STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      STBIR_SIMD_NO_UNROLL(encode);+      #ifdef stbir__decode_swizzle+      #ifdef STBIR_SIMD8+      {+        stbir__simdf8 of;+        stbir__simdf8_load( of, encode );+        stbir__encode_simdf8_unflip( of );+        stbir__float_to_half_SIMD( output, (float*)&of );+      }+      #else+      {+        stbir__simdf of[2];+        stbir__simdf_load( of[0], encode );+        stbir__simdf_load( of[1], encode+4 );+        stbir__encode_simdf4_unflip( of[0] );+        stbir__encode_simdf4_unflip( of[1] );+        stbir__float_to_half_SIMD( output, (float*)of );+      }+      #endif+      #else+      stbir__float_to_half_SIMD( output, encode );+      #endif+      encode += 8;+      output += 8;+      if ( output <= end_output )+        continue;+      if ( output == ( end_output + 8 ) )+        break;+      output = end_output; // backup and do last couple+      encode = end_encode_m8;+    }+    return;+  }+  #endif++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( output <= end_output )+  {+    STBIR_SIMD_NO_UNROLL(output);+    output[0-4] = stbir__float_to_half(encode[stbir__encode_order0]);+    output[1-4] = stbir__float_to_half(encode[stbir__encode_order1]);+    output[2-4] = stbir__float_to_half(encode[stbir__encode_order2]);+    output[3-4] = stbir__float_to_half(encode[stbir__encode_order3]);+    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( output < end_output )+  {+    STBIR_NO_UNROLL(output);+    output[0] = stbir__float_to_half(encode[stbir__encode_order0]);+    #if stbir__coder_min_num >= 2+    output[1] = stbir__float_to_half(encode[stbir__encode_order1]);+    #endif+    #if stbir__coder_min_num >= 3+    output[2] = stbir__float_to_half(encode[stbir__encode_order2]);+    #endif+    output += stbir__coder_min_num;+    encode += stbir__coder_min_num;+  }+  #endif+}++static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int width_times_channels, void const * inputp )+{+  #ifdef stbir__decode_swizzle+  float STBIR_STREAMOUT_PTR( * ) decode = decodep;+  float * decode_end = (float*) decode + width_times_channels;+  float const * input = (float const *)inputp;++  #ifdef STBIR_SIMD+  if ( width_times_channels >= 16 )+  {+    float const * end_input_m16 = input + width_times_channels - 16;+    decode_end -= 16;+    STBIR_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      STBIR_NO_UNROLL(decode);+      #ifdef stbir__decode_swizzle+      #ifdef STBIR_SIMD8+      {+        stbir__simdf8 of0,of1;+        stbir__simdf8_load( of0, input );+        stbir__simdf8_load( of1, input+8 );+        stbir__decode_simdf8_flip( of0 );+        stbir__decode_simdf8_flip( of1 );+        stbir__simdf8_store( decode, of0 );+        stbir__simdf8_store( decode+8, of1 );+      }+      #else+      {+        stbir__simdf of0,of1,of2,of3;+        stbir__simdf_load( of0, input );+        stbir__simdf_load( of1, input+4 );+        stbir__simdf_load( of2, input+8 );+        stbir__simdf_load( of3, input+12 );+        stbir__decode_simdf4_flip( of0 );+        stbir__decode_simdf4_flip( of1 );+        stbir__decode_simdf4_flip( of2 );+        stbir__decode_simdf4_flip( of3 );+        stbir__simdf_store( decode, of0 );+        stbir__simdf_store( decode+4, of1 );+        stbir__simdf_store( decode+8, of2 );+        stbir__simdf_store( decode+12, of3 );+      }+      #endif+      #endif+      decode += 16;+      input += 16;+      if ( decode <= decode_end )+        continue;+      if ( decode == ( decode_end + 16 ) )+        break;+      decode = decode_end; // backup and do last couple+      input = end_input_m16;+    }+    return;+  }+  #endif++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  decode += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( decode <= decode_end )+  {+    STBIR_SIMD_NO_UNROLL(decode);+    decode[0-4] = input[stbir__decode_order0];+    decode[1-4] = input[stbir__decode_order1];+    decode[2-4] = input[stbir__decode_order2];+    decode[3-4] = input[stbir__decode_order3];+    decode += 4;+    input += 4;+  }+  decode -= 4;+  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( decode < decode_end )+  {+    STBIR_NO_UNROLL(decode);+    decode[0] = input[stbir__decode_order0];+    #if stbir__coder_min_num >= 2+    decode[1] = input[stbir__decode_order1];+    #endif+    #if stbir__coder_min_num >= 3+    decode[2] = input[stbir__decode_order2];+    #endif+    decode += stbir__coder_min_num;+    input += stbir__coder_min_num;+  }+  #endif++  #else++  if ( (void*)decodep != inputp )+    STBIR_MEMCPY( decodep, inputp, width_times_channels * sizeof( float ) );++  #endif+}++static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int width_times_channels, float const * encode )+{+  #if !defined( STBIR_FLOAT_HIGH_CLAMP ) && !defined(STBIR_FLOAT_LO_CLAMP) && !defined(stbir__decode_swizzle)++  if ( (void*)outputp != (void*) encode )+    STBIR_MEMCPY( outputp, encode, width_times_channels * sizeof( float ) );++  #else++  float STBIR_SIMD_STREAMOUT_PTR( * ) output = (float*) outputp;+  float * end_output = ( (float*) output ) + width_times_channels;++  #ifdef STBIR_FLOAT_HIGH_CLAMP+  #define stbir_scalar_hi_clamp( v ) if ( v > STBIR_FLOAT_HIGH_CLAMP ) v = STBIR_FLOAT_HIGH_CLAMP;+  #else+  #define stbir_scalar_hi_clamp( v )+  #endif+  #ifdef STBIR_FLOAT_LOW_CLAMP+  #define stbir_scalar_lo_clamp( v ) if ( v < STBIR_FLOAT_LOW_CLAMP ) v = STBIR_FLOAT_LOW_CLAMP;+  #else+  #define stbir_scalar_lo_clamp( v )+  #endif++  #ifdef STBIR_SIMD++  #ifdef STBIR_FLOAT_HIGH_CLAMP+  const stbir__simdfX high_clamp = stbir__simdf_frepX(STBIR_FLOAT_HIGH_CLAMP);+  #endif+  #ifdef STBIR_FLOAT_LOW_CLAMP+  const stbir__simdfX low_clamp = stbir__simdf_frepX(STBIR_FLOAT_LOW_CLAMP);+  #endif++  if ( width_times_channels >= ( stbir__simdfX_float_count * 2 ) )+  {+    float const * end_encode_m8 = encode + width_times_channels - ( stbir__simdfX_float_count * 2 );+    end_output -= ( stbir__simdfX_float_count * 2 );+    STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR+    for(;;)+    {+      stbir__simdfX e0, e1;+      STBIR_SIMD_NO_UNROLL(encode);+      stbir__simdfX_load( e0, encode );+      stbir__simdfX_load( e1, encode+stbir__simdfX_float_count );+#ifdef STBIR_FLOAT_HIGH_CLAMP+      stbir__simdfX_min( e0, e0, high_clamp );+      stbir__simdfX_min( e1, e1, high_clamp );+#endif+#ifdef STBIR_FLOAT_LOW_CLAMP+      stbir__simdfX_max( e0, e0, low_clamp );+      stbir__simdfX_max( e1, e1, low_clamp );+#endif+      stbir__encode_simdfX_unflip( e0 );+      stbir__encode_simdfX_unflip( e1 );+      stbir__simdfX_store( output, e0 );+      stbir__simdfX_store( output+stbir__simdfX_float_count, e1 );+      encode += stbir__simdfX_float_count * 2;+      output += stbir__simdfX_float_count * 2;+      if ( output < end_output )+        continue;+      if ( output == ( end_output + ( stbir__simdfX_float_count * 2 ) ) )+        break;+      output = end_output; // backup and do last couple+      encode = end_encode_m8;+    }+    return;+  }++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  STBIR_NO_UNROLL_LOOP_START+  while( output <= end_output )+  {+    stbir__simdf e0;+    STBIR_NO_UNROLL(encode);+    stbir__simdf_load( e0, encode );+#ifdef STBIR_FLOAT_HIGH_CLAMP+    stbir__simdf_min( e0, e0, high_clamp );+#endif+#ifdef STBIR_FLOAT_LOW_CLAMP+    stbir__simdf_max( e0, e0, low_clamp );+#endif+    stbir__encode_simdf4_unflip( e0 );+    stbir__simdf_store( output-4, e0 );+    output += 4;+    encode += 4;+  }+  output -= 4;+  #endif++  #else++  // try to do blocks of 4 when you can+  #if stbir__coder_min_num != 3 // doesn't divide cleanly by four+  output += 4;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  while( output <= end_output )+  {+    float e;+    STBIR_SIMD_NO_UNROLL(encode);+    e = encode[ stbir__encode_order0 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[0-4] = e;+    e = encode[ stbir__encode_order1 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[1-4] = e;+    e = encode[ stbir__encode_order2 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[2-4] = e;+    e = encode[ stbir__encode_order3 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[3-4] = e;+    output += 4;+    encode += 4;+  }+  output -= 4;++  #endif++  #endif++  // do the remnants+  #if stbir__coder_min_num < 4+  STBIR_NO_UNROLL_LOOP_START+  while( output < end_output )+  {+    float e;+    STBIR_NO_UNROLL(encode);+    e = encode[ stbir__encode_order0 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[0] = e;+    #if stbir__coder_min_num >= 2+    e = encode[ stbir__encode_order1 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[1] = e;+    #endif+    #if stbir__coder_min_num >= 3+    e = encode[ stbir__encode_order2 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[2] = e;+    #endif+    output += stbir__coder_min_num;+    encode += stbir__coder_min_num;+  }+  #endif++  #endif+}++#undef stbir__decode_suffix+#undef stbir__decode_simdf8_flip+#undef stbir__decode_simdf4_flip+#undef stbir__decode_order0+#undef stbir__decode_order1+#undef stbir__decode_order2+#undef stbir__decode_order3+#undef stbir__encode_order0+#undef stbir__encode_order1+#undef stbir__encode_order2+#undef stbir__encode_order3+#undef stbir__encode_simdf8_unflip+#undef stbir__encode_simdf4_unflip+#undef stbir__encode_simdfX_unflip+#undef STBIR__CODER_NAME+#undef stbir__coder_min_num+#undef stbir__decode_swizzle+#undef stbir_scalar_hi_clamp+#undef stbir_scalar_lo_clamp+#undef STB_IMAGE_RESIZE_DO_CODERS++#elif defined( STB_IMAGE_RESIZE_DO_VERTICALS)++#ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#define STBIR_chans( start, end ) STBIR_strs_join14(start,STBIR__vertical_channels,end,_cont)+#else+#define STBIR_chans( start, end ) STBIR_strs_join1(start,STBIR__vertical_channels,end)+#endif++#if STBIR__vertical_channels >= 1+#define stbIF0( code ) code+#else+#define stbIF0( code )+#endif+#if STBIR__vertical_channels >= 2+#define stbIF1( code ) code+#else+#define stbIF1( code )+#endif+#if STBIR__vertical_channels >= 3+#define stbIF2( code ) code+#else+#define stbIF2( code )+#endif+#if STBIR__vertical_channels >= 4+#define stbIF3( code ) code+#else+#define stbIF3( code )+#endif+#if STBIR__vertical_channels >= 5+#define stbIF4( code ) code+#else+#define stbIF4( code )+#endif+#if STBIR__vertical_channels >= 6+#define stbIF5( code ) code+#else+#define stbIF5( code )+#endif+#if STBIR__vertical_channels >= 7+#define stbIF6( code ) code+#else+#define stbIF6( code )+#endif+#if STBIR__vertical_channels >= 8+#define stbIF7( code ) code+#else+#define stbIF7( code )+#endif++static void STBIR_chans( stbir__vertical_scatter_with_,_coeffs)( float ** outputs, float const * vertical_coefficients, float const * input, float const * input_end )+{+  stbIF0( float STBIR_SIMD_STREAMOUT_PTR( * ) output0 = outputs[0]; float c0s = vertical_coefficients[0]; )+  stbIF1( float STBIR_SIMD_STREAMOUT_PTR( * ) output1 = outputs[1]; float c1s = vertical_coefficients[1]; )+  stbIF2( float STBIR_SIMD_STREAMOUT_PTR( * ) output2 = outputs[2]; float c2s = vertical_coefficients[2]; )+  stbIF3( float STBIR_SIMD_STREAMOUT_PTR( * ) output3 = outputs[3]; float c3s = vertical_coefficients[3]; )+  stbIF4( float STBIR_SIMD_STREAMOUT_PTR( * ) output4 = outputs[4]; float c4s = vertical_coefficients[4]; )+  stbIF5( float STBIR_SIMD_STREAMOUT_PTR( * ) output5 = outputs[5]; float c5s = vertical_coefficients[5]; )+  stbIF6( float STBIR_SIMD_STREAMOUT_PTR( * ) output6 = outputs[6]; float c6s = vertical_coefficients[6]; )+  stbIF7( float STBIR_SIMD_STREAMOUT_PTR( * ) output7 = outputs[7]; float c7s = vertical_coefficients[7]; )++  #ifdef STBIR_SIMD+  {+    stbIF0(stbir__simdfX c0 = stbir__simdf_frepX( c0s ); )+    stbIF1(stbir__simdfX c1 = stbir__simdf_frepX( c1s ); )+    stbIF2(stbir__simdfX c2 = stbir__simdf_frepX( c2s ); )+    stbIF3(stbir__simdfX c3 = stbir__simdf_frepX( c3s ); )+    stbIF4(stbir__simdfX c4 = stbir__simdf_frepX( c4s ); )+    stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); )+    stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); )+    stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); )+    STBIR_SIMD_NO_UNROLL_LOOP_START+    while ( ( (char*)input_end - (char*) input ) >= (16*stbir__simdfX_float_count) )+    {+      stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3;+      STBIR_SIMD_NO_UNROLL(output0);++      stbir__simdfX_load( r0, input );               stbir__simdfX_load( r1, input+stbir__simdfX_float_count );     stbir__simdfX_load( r2, input+(2*stbir__simdfX_float_count) );      stbir__simdfX_load( r3, input+(3*stbir__simdfX_float_count) );++      #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+      stbIF0( stbir__simdfX_load( o0, output0 );     stbir__simdfX_load( o1, output0+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output0+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output0+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c0 );  stbir__simdfX_madd( o1, o1, r1, c0 );  stbir__simdfX_madd( o2, o2, r2, c0 );   stbir__simdfX_madd( o3, o3, r3, c0 );+              stbir__simdfX_store( output0, o0 );    stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); )+      stbIF1( stbir__simdfX_load( o0, output1 );     stbir__simdfX_load( o1, output1+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output1+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output1+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c1 );  stbir__simdfX_madd( o1, o1, r1, c1 );  stbir__simdfX_madd( o2, o2, r2, c1 );   stbir__simdfX_madd( o3, o3, r3, c1 );+              stbir__simdfX_store( output1, o0 );    stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); )+      stbIF2( stbir__simdfX_load( o0, output2 );     stbir__simdfX_load( o1, output2+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output2+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output2+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c2 );  stbir__simdfX_madd( o1, o1, r1, c2 );  stbir__simdfX_madd( o2, o2, r2, c2 );   stbir__simdfX_madd( o3, o3, r3, c2 );+              stbir__simdfX_store( output2, o0 );    stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); )+      stbIF3( stbir__simdfX_load( o0, output3 );     stbir__simdfX_load( o1, output3+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output3+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output3+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c3 );  stbir__simdfX_madd( o1, o1, r1, c3 );  stbir__simdfX_madd( o2, o2, r2, c3 );   stbir__simdfX_madd( o3, o3, r3, c3 );+              stbir__simdfX_store( output3, o0 );    stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); )+      stbIF4( stbir__simdfX_load( o0, output4 );     stbir__simdfX_load( o1, output4+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output4+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output4+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c4 );  stbir__simdfX_madd( o1, o1, r1, c4 );  stbir__simdfX_madd( o2, o2, r2, c4 );   stbir__simdfX_madd( o3, o3, r3, c4 );+              stbir__simdfX_store( output4, o0 );    stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); )+      stbIF5( stbir__simdfX_load( o0, output5 );     stbir__simdfX_load( o1, output5+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output5+(2*stbir__simdfX_float_count));    stbir__simdfX_load( o3, output5+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c5 );  stbir__simdfX_madd( o1, o1, r1, c5 );  stbir__simdfX_madd( o2, o2, r2, c5 );   stbir__simdfX_madd( o3, o3, r3, c5 );+              stbir__simdfX_store( output5, o0 );    stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); )+      stbIF6( stbir__simdfX_load( o0, output6 );     stbir__simdfX_load( o1, output6+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output6+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output6+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c6 );  stbir__simdfX_madd( o1, o1, r1, c6 );  stbir__simdfX_madd( o2, o2, r2, c6 );   stbir__simdfX_madd( o3, o3, r3, c6 );+              stbir__simdfX_store( output6, o0 );    stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); )+      stbIF7( stbir__simdfX_load( o0, output7 );     stbir__simdfX_load( o1, output7+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output7+(2*stbir__simdfX_float_count) );    stbir__simdfX_load( o3, output7+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c7 );  stbir__simdfX_madd( o1, o1, r1, c7 );  stbir__simdfX_madd( o2, o2, r2, c7 );   stbir__simdfX_madd( o3, o3, r3, c7 );+              stbir__simdfX_store( output7, o0 );    stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); )+      #else+      stbIF0( stbir__simdfX_mult( o0, r0, c0 );      stbir__simdfX_mult( o1, r1, c0 );      stbir__simdfX_mult( o2, r2, c0 );       stbir__simdfX_mult( o3, r3, c0 );+              stbir__simdfX_store( output0, o0 );    stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); )+      stbIF1( stbir__simdfX_mult( o0, r0, c1 );      stbir__simdfX_mult( o1, r1, c1 );      stbir__simdfX_mult( o2, r2, c1 );       stbir__simdfX_mult( o3, r3, c1 );+              stbir__simdfX_store( output1, o0 );    stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); )+      stbIF2( stbir__simdfX_mult( o0, r0, c2 );      stbir__simdfX_mult( o1, r1, c2 );      stbir__simdfX_mult( o2, r2, c2 );       stbir__simdfX_mult( o3, r3, c2 );+              stbir__simdfX_store( output2, o0 );    stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); )+      stbIF3( stbir__simdfX_mult( o0, r0, c3 );      stbir__simdfX_mult( o1, r1, c3 );      stbir__simdfX_mult( o2, r2, c3 );       stbir__simdfX_mult( o3, r3, c3 );+              stbir__simdfX_store( output3, o0 );    stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); )+      stbIF4( stbir__simdfX_mult( o0, r0, c4 );      stbir__simdfX_mult( o1, r1, c4 );      stbir__simdfX_mult( o2, r2, c4 );       stbir__simdfX_mult( o3, r3, c4 );+              stbir__simdfX_store( output4, o0 );    stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); )+      stbIF5( stbir__simdfX_mult( o0, r0, c5 );      stbir__simdfX_mult( o1, r1, c5 );      stbir__simdfX_mult( o2, r2, c5 );       stbir__simdfX_mult( o3, r3, c5 );+              stbir__simdfX_store( output5, o0 );    stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); )+      stbIF6( stbir__simdfX_mult( o0, r0, c6 );      stbir__simdfX_mult( o1, r1, c6 );      stbir__simdfX_mult( o2, r2, c6 );       stbir__simdfX_mult( o3, r3, c6 );+              stbir__simdfX_store( output6, o0 );    stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); )+      stbIF7( stbir__simdfX_mult( o0, r0, c7 );      stbir__simdfX_mult( o1, r1, c7 );      stbir__simdfX_mult( o2, r2, c7 );       stbir__simdfX_mult( o3, r3, c7 );+              stbir__simdfX_store( output7, o0 );    stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 );   stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); )+      #endif++      input += (4*stbir__simdfX_float_count);+      stbIF0( output0 += (4*stbir__simdfX_float_count); ) stbIF1( output1 += (4*stbir__simdfX_float_count); ) stbIF2( output2 += (4*stbir__simdfX_float_count); ) stbIF3( output3 += (4*stbir__simdfX_float_count); ) stbIF4( output4 += (4*stbir__simdfX_float_count); ) stbIF5( output5 += (4*stbir__simdfX_float_count); ) stbIF6( output6 += (4*stbir__simdfX_float_count); ) stbIF7( output7 += (4*stbir__simdfX_float_count); )+    }+    STBIR_SIMD_NO_UNROLL_LOOP_START+    while ( ( (char*)input_end - (char*) input ) >= 16 )+    {+      stbir__simdf o0, r0;+      STBIR_SIMD_NO_UNROLL(output0);++      stbir__simdf_load( r0, input );++      #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+      stbIF0( stbir__simdf_load( o0, output0 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) );  stbir__simdf_store( output0, o0 ); )+      stbIF1( stbir__simdf_load( o0, output1 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) );  stbir__simdf_store( output1, o0 ); )+      stbIF2( stbir__simdf_load( o0, output2 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) );  stbir__simdf_store( output2, o0 ); )+      stbIF3( stbir__simdf_load( o0, output3 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) );  stbir__simdf_store( output3, o0 ); )+      stbIF4( stbir__simdf_load( o0, output4 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) );  stbir__simdf_store( output4, o0 ); )+      stbIF5( stbir__simdf_load( o0, output5 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) );  stbir__simdf_store( output5, o0 ); )+      stbIF6( stbir__simdf_load( o0, output6 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) );  stbir__simdf_store( output6, o0 ); )+      stbIF7( stbir__simdf_load( o0, output7 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) );  stbir__simdf_store( output7, o0 ); )+      #else+      stbIF0( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) );   stbir__simdf_store( output0, o0 ); )+      stbIF1( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) );   stbir__simdf_store( output1, o0 ); )+      stbIF2( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) );   stbir__simdf_store( output2, o0 ); )+      stbIF3( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) );   stbir__simdf_store( output3, o0 ); )+      stbIF4( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) );   stbir__simdf_store( output4, o0 ); )+      stbIF5( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) );   stbir__simdf_store( output5, o0 ); )+      stbIF6( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) );   stbir__simdf_store( output6, o0 ); )+      stbIF7( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) );   stbir__simdf_store( output7, o0 ); )+      #endif++      input += 4;+      stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; )+    }+  }+  #else+  STBIR_NO_UNROLL_LOOP_START+  while ( ( (char*)input_end - (char*) input ) >= 16 )+  {+    float r0, r1, r2, r3;+    STBIR_NO_UNROLL(input);++    r0 = input[0], r1 = input[1], r2 = input[2], r3 = input[3];++    #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+    stbIF0( output0[0] += ( r0 * c0s ); output0[1] += ( r1 * c0s ); output0[2] += ( r2 * c0s ); output0[3] += ( r3 * c0s ); )+    stbIF1( output1[0] += ( r0 * c1s ); output1[1] += ( r1 * c1s ); output1[2] += ( r2 * c1s ); output1[3] += ( r3 * c1s ); )+    stbIF2( output2[0] += ( r0 * c2s ); output2[1] += ( r1 * c2s ); output2[2] += ( r2 * c2s ); output2[3] += ( r3 * c2s ); )+    stbIF3( output3[0] += ( r0 * c3s ); output3[1] += ( r1 * c3s ); output3[2] += ( r2 * c3s ); output3[3] += ( r3 * c3s ); )+    stbIF4( output4[0] += ( r0 * c4s ); output4[1] += ( r1 * c4s ); output4[2] += ( r2 * c4s ); output4[3] += ( r3 * c4s ); )+    stbIF5( output5[0] += ( r0 * c5s ); output5[1] += ( r1 * c5s ); output5[2] += ( r2 * c5s ); output5[3] += ( r3 * c5s ); )+    stbIF6( output6[0] += ( r0 * c6s ); output6[1] += ( r1 * c6s ); output6[2] += ( r2 * c6s ); output6[3] += ( r3 * c6s ); )+    stbIF7( output7[0] += ( r0 * c7s ); output7[1] += ( r1 * c7s ); output7[2] += ( r2 * c7s ); output7[3] += ( r3 * c7s ); )+    #else+    stbIF0( output0[0]  = ( r0 * c0s ); output0[1]  = ( r1 * c0s ); output0[2]  = ( r2 * c0s ); output0[3]  = ( r3 * c0s ); )+    stbIF1( output1[0]  = ( r0 * c1s ); output1[1]  = ( r1 * c1s ); output1[2]  = ( r2 * c1s ); output1[3]  = ( r3 * c1s ); )+    stbIF2( output2[0]  = ( r0 * c2s ); output2[1]  = ( r1 * c2s ); output2[2]  = ( r2 * c2s ); output2[3]  = ( r3 * c2s ); )+    stbIF3( output3[0]  = ( r0 * c3s ); output3[1]  = ( r1 * c3s ); output3[2]  = ( r2 * c3s ); output3[3]  = ( r3 * c3s ); )+    stbIF4( output4[0]  = ( r0 * c4s ); output4[1]  = ( r1 * c4s ); output4[2]  = ( r2 * c4s ); output4[3]  = ( r3 * c4s ); )+    stbIF5( output5[0]  = ( r0 * c5s ); output5[1]  = ( r1 * c5s ); output5[2]  = ( r2 * c5s ); output5[3]  = ( r3 * c5s ); )+    stbIF6( output6[0]  = ( r0 * c6s ); output6[1]  = ( r1 * c6s ); output6[2]  = ( r2 * c6s ); output6[3]  = ( r3 * c6s ); )+    stbIF7( output7[0]  = ( r0 * c7s ); output7[1]  = ( r1 * c7s ); output7[2]  = ( r2 * c7s ); output7[3]  = ( r3 * c7s ); )+    #endif++    input += 4;+    stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; )+  }+  #endif+  STBIR_NO_UNROLL_LOOP_START+  while ( input < input_end )+  {+    float r = input[0];+    STBIR_NO_UNROLL(output0);++    #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+    stbIF0( output0[0] += ( r * c0s ); )+    stbIF1( output1[0] += ( r * c1s ); )+    stbIF2( output2[0] += ( r * c2s ); )+    stbIF3( output3[0] += ( r * c3s ); )+    stbIF4( output4[0] += ( r * c4s ); )+    stbIF5( output5[0] += ( r * c5s ); )+    stbIF6( output6[0] += ( r * c6s ); )+    stbIF7( output7[0] += ( r * c7s ); )+    #else+    stbIF0( output0[0]  = ( r * c0s ); )+    stbIF1( output1[0]  = ( r * c1s ); )+    stbIF2( output2[0]  = ( r * c2s ); )+    stbIF3( output3[0]  = ( r * c3s ); )+    stbIF4( output4[0]  = ( r * c4s ); )+    stbIF5( output5[0]  = ( r * c5s ); )+    stbIF6( output6[0]  = ( r * c6s ); )+    stbIF7( output7[0]  = ( r * c7s ); )+    #endif++    ++input;+    stbIF0( ++output0; ) stbIF1( ++output1; ) stbIF2( ++output2; ) stbIF3( ++output3; ) stbIF4( ++output4; ) stbIF5( ++output5; ) stbIF6( ++output6; ) stbIF7( ++output7; )+  }+}++static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, float const * vertical_coefficients, float const ** inputs, float const * input0_end )+{+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = outputp;++  stbIF0( float const * input0 = inputs[0]; float c0s = vertical_coefficients[0]; )+  stbIF1( float const * input1 = inputs[1]; float c1s = vertical_coefficients[1]; )+  stbIF2( float const * input2 = inputs[2]; float c2s = vertical_coefficients[2]; )+  stbIF3( float const * input3 = inputs[3]; float c3s = vertical_coefficients[3]; )+  stbIF4( float const * input4 = inputs[4]; float c4s = vertical_coefficients[4]; )+  stbIF5( float const * input5 = inputs[5]; float c5s = vertical_coefficients[5]; )+  stbIF6( float const * input6 = inputs[6]; float c6s = vertical_coefficients[6]; )+  stbIF7( float const * input7 = inputs[7]; float c7s = vertical_coefficients[7]; )++#if ( STBIR__vertical_channels == 1 ) && !defined(STB_IMAGE_RESIZE_VERTICAL_CONTINUE)+  // check single channel one weight+  if ( ( c0s >= (1.0f-0.000001f) ) && ( c0s <= (1.0f+0.000001f) ) )+  {+    STBIR_MEMCPY( output, input0, (char*)input0_end - (char*)input0 );+    return;+  }+#endif++  #ifdef STBIR_SIMD+  {+    stbIF0(stbir__simdfX c0 = stbir__simdf_frepX( c0s ); )+    stbIF1(stbir__simdfX c1 = stbir__simdf_frepX( c1s ); )+    stbIF2(stbir__simdfX c2 = stbir__simdf_frepX( c2s ); )+    stbIF3(stbir__simdfX c3 = stbir__simdf_frepX( c3s ); )+    stbIF4(stbir__simdfX c4 = stbir__simdf_frepX( c4s ); )+    stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); )+    stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); )+    stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); )++    STBIR_SIMD_NO_UNROLL_LOOP_START+    while ( ( (char*)input0_end - (char*) input0 ) >= (16*stbir__simdfX_float_count) )+    {+      stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3;+      STBIR_SIMD_NO_UNROLL(output);++      // prefetch four loop iterations ahead (doesn't affect much for small resizes, but helps with big ones)+      stbIF0( stbir__prefetch( input0 + (16*stbir__simdfX_float_count) ); )+      stbIF1( stbir__prefetch( input1 + (16*stbir__simdfX_float_count) ); )+      stbIF2( stbir__prefetch( input2 + (16*stbir__simdfX_float_count) ); )+      stbIF3( stbir__prefetch( input3 + (16*stbir__simdfX_float_count) ); )+      stbIF4( stbir__prefetch( input4 + (16*stbir__simdfX_float_count) ); )+      stbIF5( stbir__prefetch( input5 + (16*stbir__simdfX_float_count) ); )+      stbIF6( stbir__prefetch( input6 + (16*stbir__simdfX_float_count) ); )+      stbIF7( stbir__prefetch( input7 + (16*stbir__simdfX_float_count) ); )++      #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+      stbIF0( stbir__simdfX_load( o0, output );      stbir__simdfX_load( o1, output+stbir__simdfX_float_count );   stbir__simdfX_load( o2, output+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( o3, output+(3*stbir__simdfX_float_count) );+              stbir__simdfX_load( r0, input0 );      stbir__simdfX_load( r1, input0+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input0+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input0+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c0 );  stbir__simdfX_madd( o1, o1, r1, c0 );                         stbir__simdfX_madd( o2, o2, r2, c0 );                             stbir__simdfX_madd( o3, o3, r3, c0 ); )+      #else+      stbIF0( stbir__simdfX_load( r0, input0 );      stbir__simdfX_load( r1, input0+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input0+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input0+(3*stbir__simdfX_float_count) );+              stbir__simdfX_mult( o0, r0, c0 );      stbir__simdfX_mult( o1, r1, c0 );                             stbir__simdfX_mult( o2, r2, c0 );                                 stbir__simdfX_mult( o3, r3, c0 );  )+      #endif++      stbIF1( stbir__simdfX_load( r0, input1 );      stbir__simdfX_load( r1, input1+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input1+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input1+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c1 );  stbir__simdfX_madd( o1, o1, r1, c1 );                         stbir__simdfX_madd( o2, o2, r2, c1 );                             stbir__simdfX_madd( o3, o3, r3, c1 ); )+      stbIF2( stbir__simdfX_load( r0, input2 );      stbir__simdfX_load( r1, input2+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input2+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input2+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c2 );  stbir__simdfX_madd( o1, o1, r1, c2 );                         stbir__simdfX_madd( o2, o2, r2, c2 );                             stbir__simdfX_madd( o3, o3, r3, c2 ); )+      stbIF3( stbir__simdfX_load( r0, input3 );      stbir__simdfX_load( r1, input3+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input3+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input3+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c3 );  stbir__simdfX_madd( o1, o1, r1, c3 );                         stbir__simdfX_madd( o2, o2, r2, c3 );                             stbir__simdfX_madd( o3, o3, r3, c3 ); )+      stbIF4( stbir__simdfX_load( r0, input4 );      stbir__simdfX_load( r1, input4+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input4+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input4+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c4 );  stbir__simdfX_madd( o1, o1, r1, c4 );                         stbir__simdfX_madd( o2, o2, r2, c4 );                             stbir__simdfX_madd( o3, o3, r3, c4 ); )+      stbIF5( stbir__simdfX_load( r0, input5 );      stbir__simdfX_load( r1, input5+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input5+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input5+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c5 );  stbir__simdfX_madd( o1, o1, r1, c5 );                         stbir__simdfX_madd( o2, o2, r2, c5 );                             stbir__simdfX_madd( o3, o3, r3, c5 ); )+      stbIF6( stbir__simdfX_load( r0, input6 );      stbir__simdfX_load( r1, input6+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input6+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input6+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c6 );  stbir__simdfX_madd( o1, o1, r1, c6 );                         stbir__simdfX_madd( o2, o2, r2, c6 );                             stbir__simdfX_madd( o3, o3, r3, c6 ); )+      stbIF7( stbir__simdfX_load( r0, input7 );      stbir__simdfX_load( r1, input7+stbir__simdfX_float_count );   stbir__simdfX_load( r2, input7+(2*stbir__simdfX_float_count) );   stbir__simdfX_load( r3, input7+(3*stbir__simdfX_float_count) );+              stbir__simdfX_madd( o0, o0, r0, c7 );  stbir__simdfX_madd( o1, o1, r1, c7 );                         stbir__simdfX_madd( o2, o2, r2, c7 );                             stbir__simdfX_madd( o3, o3, r3, c7 ); )++      stbir__simdfX_store( output, o0 );             stbir__simdfX_store( output+stbir__simdfX_float_count, o1 );  stbir__simdfX_store( output+(2*stbir__simdfX_float_count), o2 );  stbir__simdfX_store( output+(3*stbir__simdfX_float_count), o3 );+      output += (4*stbir__simdfX_float_count);+      stbIF0( input0 += (4*stbir__simdfX_float_count); ) stbIF1( input1 += (4*stbir__simdfX_float_count); ) stbIF2( input2 += (4*stbir__simdfX_float_count); ) stbIF3( input3 += (4*stbir__simdfX_float_count); ) stbIF4( input4 += (4*stbir__simdfX_float_count); ) stbIF5( input5 += (4*stbir__simdfX_float_count); ) stbIF6( input6 += (4*stbir__simdfX_float_count); ) stbIF7( input7 += (4*stbir__simdfX_float_count); )+    }++    STBIR_SIMD_NO_UNROLL_LOOP_START+    while ( ( (char*)input0_end - (char*) input0 ) >= 16 )+    {+      stbir__simdf o0, r0;+      STBIR_SIMD_NO_UNROLL(output);++      #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+      stbIF0( stbir__simdf_load( o0, output );   stbir__simdf_load( r0, input0 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); )+      #else+      stbIF0( stbir__simdf_load( r0, input0 );  stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); )+      #endif+      stbIF1( stbir__simdf_load( r0, input1 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); )+      stbIF2( stbir__simdf_load( r0, input2 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); )+      stbIF3( stbir__simdf_load( r0, input3 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); )+      stbIF4( stbir__simdf_load( r0, input4 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); )+      stbIF5( stbir__simdf_load( r0, input5 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); )+      stbIF6( stbir__simdf_load( r0, input6 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); )+      stbIF7( stbir__simdf_load( r0, input7 );  stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); )++      stbir__simdf_store( output, o0 );+      output += 4;+      stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; )+    }+  }+  #else+  STBIR_NO_UNROLL_LOOP_START+  while ( ( (char*)input0_end - (char*) input0 ) >= 16 )+  {+    float o0, o1, o2, o3;+    STBIR_NO_UNROLL(output);+    #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+    stbIF0( o0 = output[0] + input0[0] * c0s; o1 = output[1] + input0[1] * c0s; o2 = output[2] + input0[2] * c0s; o3 = output[3] + input0[3] * c0s; )+    #else+    stbIF0( o0  = input0[0] * c0s; o1  = input0[1] * c0s; o2  = input0[2] * c0s; o3  = input0[3] * c0s; )+    #endif+    stbIF1( o0 += input1[0] * c1s; o1 += input1[1] * c1s; o2 += input1[2] * c1s; o3 += input1[3] * c1s; )+    stbIF2( o0 += input2[0] * c2s; o1 += input2[1] * c2s; o2 += input2[2] * c2s; o3 += input2[3] * c2s; )+    stbIF3( o0 += input3[0] * c3s; o1 += input3[1] * c3s; o2 += input3[2] * c3s; o3 += input3[3] * c3s; )+    stbIF4( o0 += input4[0] * c4s; o1 += input4[1] * c4s; o2 += input4[2] * c4s; o3 += input4[3] * c4s; )+    stbIF5( o0 += input5[0] * c5s; o1 += input5[1] * c5s; o2 += input5[2] * c5s; o3 += input5[3] * c5s; )+    stbIF6( o0 += input6[0] * c6s; o1 += input6[1] * c6s; o2 += input6[2] * c6s; o3 += input6[3] * c6s; )+    stbIF7( o0 += input7[0] * c7s; o1 += input7[1] * c7s; o2 += input7[2] * c7s; o3 += input7[3] * c7s; )+    output[0] = o0; output[1] = o1; output[2] = o2; output[3] = o3;+    output += 4;+    stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; )+  }+  #endif+  STBIR_NO_UNROLL_LOOP_START+  while ( input0 < input0_end )+  {+    float o0;+    STBIR_NO_UNROLL(output);+    #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+    stbIF0( o0 = output[0] + input0[0] * c0s; )+    #else+    stbIF0( o0  = input0[0] * c0s; )+    #endif+    stbIF1( o0 += input1[0] * c1s; )+    stbIF2( o0 += input2[0] * c2s; )+    stbIF3( o0 += input3[0] * c3s; )+    stbIF4( o0 += input4[0] * c4s; )+    stbIF5( o0 += input5[0] * c5s; )+    stbIF6( o0 += input6[0] * c6s; )+    stbIF7( o0 += input7[0] * c7s; )+    output[0] = o0;+    ++output;+    stbIF0( ++input0; ) stbIF1( ++input1; ) stbIF2( ++input2; ) stbIF3( ++input3; ) stbIF4( ++input4; ) stbIF5( ++input5; ) stbIF6( ++input6; ) stbIF7( ++input7; )+  }+}++#undef stbIF0+#undef stbIF1+#undef stbIF2+#undef stbIF3+#undef stbIF4+#undef stbIF5+#undef stbIF6+#undef stbIF7+#undef STB_IMAGE_RESIZE_DO_VERTICALS+#undef STBIR__vertical_channels+#undef STB_IMAGE_RESIZE_DO_HORIZONTALS+#undef STBIR_strs_join24+#undef STBIR_strs_join14+#undef STBIR_chans+#ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#undef STB_IMAGE_RESIZE_VERTICAL_CONTINUE+#endif++#else // !STB_IMAGE_RESIZE_DO_VERTICALS++#define STBIR_chans( start, end ) STBIR_strs_join1(start,STBIR__horizontal_channels,end)++#ifndef stbir__2_coeff_only+#define stbir__2_coeff_only()             \+    stbir__1_coeff_only();                \+    stbir__1_coeff_remnant(1);+#endif++#ifndef stbir__2_coeff_remnant+#define stbir__2_coeff_remnant( ofs )     \+    stbir__1_coeff_remnant(ofs);          \+    stbir__1_coeff_remnant((ofs)+1);+#endif++#ifndef stbir__3_coeff_only+#define stbir__3_coeff_only()             \+    stbir__2_coeff_only();                \+    stbir__1_coeff_remnant(2);+#endif++#ifndef stbir__3_coeff_remnant+#define stbir__3_coeff_remnant( ofs )     \+    stbir__2_coeff_remnant(ofs);          \+    stbir__1_coeff_remnant((ofs)+2);+#endif++#ifndef stbir__3_coeff_setup+#define stbir__3_coeff_setup()+#endif++#ifndef stbir__4_coeff_start+#define stbir__4_coeff_start()            \+    stbir__2_coeff_only();                \+    stbir__2_coeff_remnant(2);+#endif++#ifndef stbir__4_coeff_continue_from_4+#define stbir__4_coeff_continue_from_4( ofs )     \+    stbir__2_coeff_remnant(ofs);                  \+    stbir__2_coeff_remnant((ofs)+2);+#endif++#ifndef stbir__store_output_tiny+#define stbir__store_output_tiny stbir__store_output+#endif++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_1_coeff)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__1_coeff_only();+    stbir__store_output_tiny();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_2_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__2_coeff_only();+    stbir__store_output_tiny();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_3_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__3_coeff_only();+    stbir__store_output_tiny();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_4_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__4_coeff_start();+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_5_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__4_coeff_start();+    stbir__1_coeff_remnant(4);+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_6_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__4_coeff_start();+    stbir__2_coeff_remnant(4);+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_7_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  stbir__3_coeff_setup();+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;++    stbir__4_coeff_start();+    stbir__3_coeff_remnant(4);+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_8_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__4_coeff_start();+    stbir__4_coeff_continue_from_4(4);+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_9_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__4_coeff_start();+    stbir__4_coeff_continue_from_4(4);+    stbir__1_coeff_remnant(8);+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_10_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__4_coeff_start();+    stbir__4_coeff_continue_from_4(4);+    stbir__2_coeff_remnant(8);+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_11_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  stbir__3_coeff_setup();+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__4_coeff_start();+    stbir__4_coeff_continue_from_4(4);+    stbir__3_coeff_remnant(8);+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_12_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    float const * hc = horizontal_coefficients;+    stbir__4_coeff_start();+    stbir__4_coeff_continue_from_4(4);+    stbir__4_coeff_continue_from_4(8);+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod0 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 4 + 3 ) >> 2;+    float const * hc = horizontal_coefficients;++    stbir__4_coeff_start();+    STBIR_SIMD_NO_UNROLL_LOOP_START+    do {+      hc += 4;+      decode += STBIR__horizontal_channels * 4;+      stbir__4_coeff_continue_from_4( 0 );+      --n;+    } while ( n > 0 );+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod1 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 5 + 3 ) >> 2;+    float const * hc = horizontal_coefficients;++    stbir__4_coeff_start();+    STBIR_SIMD_NO_UNROLL_LOOP_START+    do {+      hc += 4;+      decode += STBIR__horizontal_channels * 4;+      stbir__4_coeff_continue_from_4( 0 );+      --n;+    } while ( n > 0 );+    stbir__1_coeff_remnant( 4 );+    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod2 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 6 + 3 ) >> 2;+    float const * hc = horizontal_coefficients;++    stbir__4_coeff_start();+    STBIR_SIMD_NO_UNROLL_LOOP_START+    do {+      hc += 4;+      decode += STBIR__horizontal_channels * 4;+      stbir__4_coeff_continue_from_4( 0 );+      --n;+    } while ( n > 0 );+    stbir__2_coeff_remnant( 4 );++    stbir__store_output();+  } while ( output < output_end );+}++static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod3 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width )+{+  float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels;+  float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer;+  stbir__3_coeff_setup();+  STBIR_SIMD_NO_UNROLL_LOOP_START+  do {+    float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels;+    int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 7 + 3 ) >> 2;+    float const * hc = horizontal_coefficients;++    stbir__4_coeff_start();+    STBIR_SIMD_NO_UNROLL_LOOP_START+    do {+      hc += 4;+      decode += STBIR__horizontal_channels * 4;+      stbir__4_coeff_continue_from_4( 0 );+      --n;+    } while ( n > 0 );+    stbir__3_coeff_remnant( 4 );++    stbir__store_output();+  } while ( output < output_end );+}++static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_funcs)[4]=+{+  STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod0),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod1),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod2),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod3),+};++static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_funcs)[12]=+{+  STBIR_chans(stbir__horizontal_gather_,_channels_with_1_coeff),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_2_coeffs),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_3_coeffs),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_4_coeffs),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_5_coeffs),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_6_coeffs),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_7_coeffs),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_8_coeffs),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_9_coeffs),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_10_coeffs),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_11_coeffs),+  STBIR_chans(stbir__horizontal_gather_,_channels_with_12_coeffs),+};++#undef STBIR__horizontal_channels+#undef STB_IMAGE_RESIZE_DO_HORIZONTALS+#undef stbir__1_coeff_only+#undef stbir__1_coeff_remnant+#undef stbir__2_coeff_only+#undef stbir__2_coeff_remnant+#undef stbir__3_coeff_only+#undef stbir__3_coeff_remnant+#undef stbir__3_coeff_setup+#undef stbir__4_coeff_start+#undef stbir__4_coeff_continue_from_4+#undef stbir__store_output+#undef stbir__store_output_tiny+#undef STBIR_chans++#endif  // HORIZONALS++#undef STBIR_strs_join2+#undef STBIR_strs_join1++#endif // STB_IMAGE_RESIZE_DO_HORIZONTALS/VERTICALS/CODERS++/*+------------------------------------------------------------------------------+This software is available under 2 licenses -- choose whichever you prefer.+------------------------------------------------------------------------------+ALTERNATIVE A - MIT License+Copyright (c) 2017 Sean Barrett+Permission is hereby granted, free of charge, to any person obtaining a copy of+this software and associated documentation files (the "Software"), to deal in+the Software without restriction, including without limitation the rights to+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies+of the Software, and to permit persons to whom the Software is furnished to do+so, subject to the following conditions:+The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.+------------------------------------------------------------------------------+ALTERNATIVE B - Public Domain (www.unlicense.org)+This is free and unencumbered software released into the public domain.+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this+software, either in source code form or as a compiled binary, for any purpose,+commercial or non-commercial, and by any means.+In jurisdictions that recognize copyright laws, the author or authors of this+software dedicate any and all copyright interest in the software to the public+domain. We make this dedication for the benefit of the public at large and to+the detriment of our heirs and successors. We intend this dedication to be an+overt act of relinquishment in perpetuity of all present and future rights to+this software under copyright law.+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */
raylib/src/platforms/rcore_android.c view
@@ -74,7 +74,7 @@ // Global Variables Definition //---------------------------------------------------------------------------------- extern CoreData CORE;                   // Global CORE state context-+extern bool isGpuReady;                 // Flag to note GPU has been initialized successfully static PlatformData platform = { 0 };   // Platform specific data  //----------------------------------------------------------------------------------@@ -281,14 +281,15 @@     // Request to end the native activity     ANativeActivity_finish(app->activity); -    // Android ALooper_pollAll() variables+    // Android ALooper_pollOnce() variables     int pollResult = 0;     int pollEvents = 0;      // Waiting for application events before complete finishing     while (!app->destroyRequested)     {-        while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void **)&platform.source)) >= 0)+        // Poll all events until we reach return value TIMEOUT, meaning no events left to process+        while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, (void **)&platform.source)) > ALOOPER_POLL_TIMEOUT)         {             if (platform.source != NULL) platform.source->process(app, platform.source);         }@@ -632,6 +633,13 @@     TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform"); } +// Get physical key name.+const char *GetKeyName(int key)+{+    TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");+    return "";+}+ // Register all input events void PollInputEvents(void) {@@ -675,27 +683,27 @@         CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;     } -    // Android ALooper_pollAll() variables+    // Android ALooper_pollOnce() variables     int pollResult = 0;     int pollEvents = 0; -    // Poll Events (registered events)+    // Poll Events (registered events) until we reach TIMEOUT which indicates there are no events left to poll     // NOTE: Activity is paused if not enabled (platform.appEnabled)-    while ((pollResult = ALooper_pollAll(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) >= 0)+    while ((pollResult = ALooper_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT)     {         // Process this event         if (platform.source != NULL) platform.source->process(platform.app, platform.source); -        // NOTE: Never close window, native activity is controlled by the system!+        // NOTE: Allow closing the window in case a configuration change happened.+        // The android_main function should be allowed to return to its caller in order for the+        // Android OS to relaunch the activity.         if (platform.app->destroyRequested != 0)         {-            //CORE.Window.shouldClose = true;-            //ANativeActivity_finish(platform.app->activity);+            CORE.Window.shouldClose = true;         }     } } - //---------------------------------------------------------------------------------- // Module Internal Functions Definition //----------------------------------------------------------------------------------@@ -760,20 +768,20 @@      TRACELOG(LOG_INFO, "PLATFORM: ANDROID: Initialized successfully"); -    // Android ALooper_pollAll() variables+    // Android ALooper_pollOnce() variables     int pollResult = 0;     int pollEvents = 0;      // Wait for window to be initialized (display and context)     while (!CORE.Window.ready)     {-        // Process events loop-        while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&platform.source)) >= 0)+        // Process events until we reach TIMEOUT, which indicates no more events queued.+        while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT)         {             // Process this event             if (platform.source != NULL) platform.source->process(platform.app, platform.source); -            // NOTE: Never close window, native activity is controlled by the system!+            // NOTE: It's highly likely destroyRequested will never be non-zero at the start of the activity lifecycle.             //if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true;         }     }@@ -804,6 +812,12 @@         eglTerminate(platform.device);         platform.device = EGL_NO_DISPLAY;     }++    // NOTE: Reset global state in case the activity is being relaunched.+    if (platform.app->destroyRequested != 0) {+        CORE = (CoreData){0};+        platform = (PlatformData){0};+    } }  // Initialize display device and framebuffer@@ -974,6 +988,7 @@                     // Initialize OpenGL context (states and resources)                     // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl                     rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);+                    isGpuReady = true;                      // Setup default viewport                     // NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
raylib/src/platforms/rcore_desktop_glfw.c view
@@ -109,6 +109,7 @@  // Window callbacks events static void WindowSizeCallback(GLFWwindow *window, int width, int height);                 // GLFW3 WindowSize Callback, runs when window is resized+static void WindowPosCallback(GLFWwindow* window, int x, int y);                     // GLFW3 WindowPos Callback, runs when window is moved static void WindowIconifyCallback(GLFWwindow *window, int iconified);                      // GLFW3 WindowIconify Callback, runs when window is minimized/restored static void WindowMaximizeCallback(GLFWwindow* window, int maximized);                     // GLFW3 Window Maximize Callback, runs when window is maximized static void WindowFocusCallback(GLFWwindow *window, int focused);                          // GLFW3 WindowFocus Callback, runs when window get/lose focus@@ -147,8 +148,8 @@     if (!CORE.Window.fullscreen)     {         // Store previous window position (in case we exit fullscreen)-        glfwGetWindowPos(platform.handle, &CORE.Window.position.x, &CORE.Window.position.y);-+        CORE.Window.previousPosition = CORE.Window.position;+                 int monitorCount = 0;         int monitorIndex = GetCurrentMonitor();         GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);@@ -179,7 +180,11 @@         CORE.Window.fullscreen = false;         CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE; -        glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);+        glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.previousPosition.x, CORE.Window.previousPosition.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);++        // we update the window position right away+        CORE.Window.position.x = CORE.Window.previousPosition.x;+        CORE.Window.position.y = CORE.Window.previousPosition.y;     }      // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)@@ -190,11 +195,11 @@ // Toggle borderless windowed mode void ToggleBorderlessWindowed(void) {-    // Leave fullscreen before attempting to set borderless windowed mode and get screen position from it+    // Leave fullscreen before attempting to set borderless windowed mode     bool wasOnFullscreen = false;     if (CORE.Window.fullscreen)     {-        CORE.Window.previousPosition = CORE.Window.position;+        // fullscreen already saves the previous position so it does not need to be set here again         ToggleFullscreen();         wasOnFullscreen = true;     }@@ -213,7 +218,7 @@             {                 // Store screen position and size                 // NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here-                if (!wasOnFullscreen) glfwGetWindowPos(platform.handle, &CORE.Window.previousPosition.x, &CORE.Window.previousPosition.y);+                if (!wasOnFullscreen) CORE.Window.previousPosition = CORE.Window.position;                 CORE.Window.previousScreen = CORE.Window.screen;                  // Set undecorated and topmost modes and flags@@ -255,6 +260,9 @@                 glfwFocusWindow(platform.handle);                  CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;++                CORE.Window.position.x = CORE.Window.previousPosition.x;+                CORE.Window.position.y = CORE.Window.previousPosition.y;             }         }         else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");@@ -592,6 +600,9 @@ // Set window position on screen (windowed mode) void SetWindowPosition(int x, int y) {+    // Update CORE.Window.position as well+    CORE.Window.position.x = x;+    CORE.Window.position.y = y;     glfwSetWindowPos(platform.handle, x, y); } @@ -614,8 +625,9 @@         {             TRACELOG(LOG_INFO, "GLFW: Selected monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor])); -            const int screenWidth = CORE.Window.screen.width;-            const int screenHeight = CORE.Window.screen.height;+            // Here the render width has to be used again in case high dpi flag is enabled+            const int screenWidth = CORE.Window.render.width;+            const int screenHeight = CORE.Window.render.height;             int monitorWorkareaX = 0;             int monitorWorkareaY = 0;             int monitorWorkareaWidth = 0;@@ -1075,6 +1087,12 @@     } } +// Get physical key name.+const char *GetKeyName(int key)+{+    return glfwGetKeyName(key, glfwGetKeyScancode(key));+}+ // Register all input events void PollInputEvents(void) {@@ -1216,7 +1234,6 @@     glfwSetWindowShouldClose(platform.handle, GLFW_FALSE); } - //---------------------------------------------------------------------------------- // Module Internal Functions Definition //----------------------------------------------------------------------------------@@ -1269,6 +1286,11 @@     //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // OpenGL API to use. Alternative: GLFW_OPENGL_ES_API     //glfwWindowHint(GLFW_AUX_BUFFERS, 0);          // Number of auxiliar buffers +    // 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); +     // Check window creation flags     if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true; @@ -1424,7 +1446,7 @@             }         } -        TRACELOG(LOG_WARNING, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height);+        TRACELOG(LOG_INFO, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height);          // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example,         // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3),@@ -1448,11 +1470,6 @@         // No-fullscreen window creation         bool requestWindowedFullscreen = (CORE.Window.screen.height == 0) && (CORE.Window.screen.width == 0); -        // If we are windowed fullscreen, ensures that window does not minimize when focus is lost.-        // This hinting code will not work if the user already specified the correct monitor dimensions;-        // at this point we don't know the monitor's dimensions. (Though, how did the user then?)-        if (requestWindowedFullscreen) glfwWindowHint(GLFW_AUTO_ICONIFY, 0);-         // Default to at least one pixel in size, as creation with a zero dimension is not allowed.         int creationWidth = CORE.Window.screen.width != 0 ? CORE.Window.screen.width : 1;         int creationHeight = CORE.Window.screen.height != 0 ? CORE.Window.screen.height : 1;@@ -1562,12 +1579,17 @@         int monitorWidth = 0;         int monitorHeight = 0;         glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);--        int posX = monitorX + (monitorWidth - (int)CORE.Window.screen.width)/2;-        int posY = monitorY + (monitorHeight - (int)CORE.Window.screen.height)/2;+        +        // 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;         if (posX < monitorX) posX = monitorX;         if (posY < monitorY) posY = monitorY;         SetWindowPosition(posX, posY);++        // Update CORE.Window.position here so it is correct from the start+        CORE.Window.position.x = posX;+        CORE.Window.position.y = posY;     }      // Load OpenGL extensions@@ -1579,6 +1601,7 @@     //----------------------------------------------------------------------------     // Set window callback events     glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback);      // NOTE: Resizing not allowed by default!+    glfwSetWindowPosCallback(platform.handle, WindowPosCallback);     glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback);     glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);     glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);@@ -1624,16 +1647,16 @@     char *glfwPlatform = "";     switch (glfwGetPlatform())     {-        case GLFW_PLATFORM_WIN32:   glfwPlatform = "Win32";   break;-        case GLFW_PLATFORM_COCOA:   glfwPlatform = "Cocoa";   break;+        case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break;+        case GLFW_PLATFORM_COCOA: glfwPlatform = "Cocoa"; break;         case GLFW_PLATFORM_WAYLAND: glfwPlatform = "Wayland"; break;-        case GLFW_PLATFORM_X11:     glfwPlatform = "X11";     break;-        case GLFW_PLATFORM_NULL:    glfwPlatform = "Null";    break;+        case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break;+        case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break;+        default: break;     } #endif -    TRACELOG(LOG_INFO, "GLFW platform: %s", glfwPlatform);-    TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW): Initialized successfully");+    TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW - %s): Initialized successfully", glfwPlatform);      return 0; }@@ -1675,7 +1698,12 @@      // NOTE: Postprocessing texture is not scaled to new size }-+static void WindowPosCallback(GLFWwindow* window, int x, int y)+{+    // Set current window position+    CORE.Window.position.x = x;+    CORE.Window.position.y = y;+} static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley) {     CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f);
raylib/src/platforms/rcore_desktop_rgfw.c view
@@ -1,6 +1,6 @@ /**********************************************************************************************
 *
-*   rcore_desktop_rgfw template - Functions to manage window, graphics device and inputs
+*   rcore_desktop_rgfw - Functions to manage window, graphics device and inputs
 *
 *   PLATFORM: RGFW
 *       - Windows (Win32, Win64)
@@ -46,7 +46,7 @@ *
 **********************************************************************************************/
 
-#ifdef GRAPHICS_API_OPENGL_ES2
+#if defined(GRAPHICS_API_OPENGL_ES2)
     #define RGFW_OPENGL_ES2
 #endif
 
@@ -69,6 +69,7 @@     #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__)
@@ -76,10 +77,6 @@     #define Size NSSIZE
 #endif
 
-#if defined(_MSC_VER)
-__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
-#endif
-
 #include "../external/RGFW.h"
 
 #if defined(__WIN32) || defined(__WIN64)
@@ -182,7 +179,7 @@     [RGFW_u] = KEY_U,
     [RGFW_v] = KEY_V,
     [RGFW_w] = KEY_W,
-    [RGFW_x] KEY_X,
+    [RGFW_x] = KEY_X,
     [RGFW_y] = KEY_Y,
     [RGFW_z] = KEY_Z,
     [RGFW_Bracket] = KEY_LEFT_BRACKET,
@@ -291,7 +288,6 @@     }
     if (flags & FLAG_WINDOW_RESIZABLE)
     {
-        printf("%i %i\n", platform.window->r.w, platform.window->r.h);
         RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h));
         RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h));
     }
@@ -483,14 +479,14 @@ // Set title for window
 void SetWindowTitle(const char *title)
 {
-    RGFW_window_setName(platform.window, title);
+    RGFW_window_setName(platform.window, (char*)title);
     CORE.Window.title = title;
 }
 
 // Set window position on screen (windowed mode)
 void SetWindowPosition(int x, int y)
 {
-    RGFW_window_move(platform.window, RGFW_VECTOR(x, y));
+    RGFW_window_move(platform.window, RGFW_POINT(x, y));
 }
 
 // Set monitor for the current window
@@ -536,10 +532,10 @@ // Get native window handle
 void *GetWindowHandle(void)
 {
-#ifndef RGFW_WINDOWS
-    return (void *)platform.window->src.window;
+#ifdef RGFW_WEBASM
+    return (void*)platform.window->src.ctx;
 #else
-    return platform.window->src.hwnd;
+    return (void*)platform.window->src.window;
 #endif
 }
 
@@ -643,7 +639,7 @@ {
     RGFW_monitor monitor = RGFW_window_getMonitor(platform.window);
 
-    return (Vector2){((u32)monitor.scaleX)*platform.window->r.w, ((u32) monitor.scaleX)*platform.window->r.h};
+    return (Vector2){monitor.scaleX, monitor.scaleX};
 }
 
 // Set clipboard text content
@@ -689,10 +685,9 @@ void DisableCursor(void)
 {
     RGFW_disableCursor = true;
-    
-    // Set cursor position in the middle
-    SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
 
+    RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0));
+
     HideCursor();
 }
 
@@ -745,7 +740,7 @@ // Set mouse position XY
 void SetMousePosition(int x, int y)
 {
-    RGFW_window_moveMouse(platform.window, RGFW_VECTOR(x, y));
+    RGFW_window_moveMouse(platform.window, RGFW_POINT(x, y));
     CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
     CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
 }
@@ -756,6 +751,13 @@     RGFW_window_setMouseStandard(platform.window, cursor);
 }
 
+// Get physical key name.
+const char *GetKeyName(int key)
+{
+    TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");
+    return "";
+}
+
 static KeyboardKey ConvertScancodeToKey(u32 keycode);
 
 // TODO: Review function to avoid duplicate with RSGL
@@ -868,10 +870,9 @@     //-----------------------------------------------------------------------------
     CORE.Window.resizedLastFrame = false;
 
-#define RGFW_HOLD_MOUSE			(1L<<2)
-
-#if defined(RGFW_X11) //|| defined(RGFW_MACOS)
-    if (platform.window->src.winArgs & RGFW_HOLD_MOUSE)
+    CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
+    #define RGFW_HOLD_MOUSE     (1L<<2)
+    if (platform.window->_winArgs & RGFW_HOLD_MOUSE)
     {
         CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f };
         CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f };
@@ -880,11 +881,9 @@     {
         CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
     }
-#endif
 
     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])
@@ -936,7 +935,7 @@                 SetupViewport(platform.window->r.w, platform.window->r.h);
                 CORE.Window.screen.width = platform.window->r.w;
                 CORE.Window.screen.height =  platform.window->r.h;
-                CORE.Window.currentFbo.width = platform.window->r.w;;
+                CORE.Window.currentFbo.width = platform.window->r.w;
                 CORE.Window.currentFbo.height = platform.window->r.h;
                 CORE.Window.resizedLastFrame = true;
             } break;
@@ -1024,17 +1023,10 @@             } break;
             case RGFW_mousePosChanged:
             {
-                if (platform.window->src.winArgs & RGFW_HOLD_MOUSE)
+                if (platform.window->_winArgs & RGFW_HOLD_MOUSE)
                 {
-                    CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f };
-
-                    if ((event->point.x - (platform.window->r.w/2))*2)
-                        CORE.Input.Mouse.previousPosition.x = CORE.Input.Mouse.currentPosition.x;
-                    if ((event->point.y - (platform.window->r.h/2))*2)
-                        CORE.Input.Mouse.previousPosition.y = CORE.Input.Mouse.currentPosition.y;
-
-                    CORE.Input.Mouse.currentPosition.x = (event->point.x - (platform.window->r.w/2))*2;
-                    CORE.Input.Mouse.currentPosition.y = (event->point.y - (platform.window->r.h/2))*2;
+                    CORE.Input.Mouse.currentPosition.x += (float)event->point.x;
+                    CORE.Input.Mouse.currentPosition.y += (float)event->point.y;
                 }
                 else
                 {
@@ -1198,12 +1190,9 @@         }
 #endif
     }
-
-    if (RGFW_disableCursor && platform.window->event.inFocus) RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0));
     //-----------------------------------------------------------------------------
 }
 
-
 //----------------------------------------------------------------------------------
 // Module Internal Functions Definition
 //----------------------------------------------------------------------------------
@@ -1233,15 +1222,15 @@     // Check selection OpenGL version
     if (rlGetVersion() == RL_OPENGL_21)
     {
-        RGFW_setGLVersion(2, 1);
+        RGFW_setGLVersion(RGFW_GL_CORE, 2, 1);
     }
     else if (rlGetVersion() == RL_OPENGL_33)
     {
-        RGFW_setGLVersion(3, 3);
+        RGFW_setGLVersion(RGFW_GL_CORE, 3, 3);
     }
     else if (rlGetVersion() == RL_OPENGL_43)
     {
-        RGFW_setGLVersion(4, 1);
+        RGFW_setGLVersion(RGFW_GL_CORE, 4, 1);
     }
 
     if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
@@ -1250,6 +1239,15 @@     }
 
     platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags);
+
+    RGFW_area screenSize = RGFW_getScreenSize();
+    CORE.Window.display.width = screenSize.w;
+    CORE.Window.display.height = screenSize.h;
+    /* 
+        I think this is needed by Raylib now ? 
+        If so, rcore_destkop_sdl should be updated too
+    */
+    SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
 
     if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1);
 
raylib/src/platforms/rcore_desktop_sdl.c view
@@ -58,6 +58,13 @@ #endif  //----------------------------------------------------------------------------------+// Defines and Macros+//----------------------------------------------------------------------------------+#ifndef MAX_CLIPBOARD_BUFFER_LENGTH+    #define MAX_CLIPBOARD_BUFFER_LENGTH 1024 // Size of the clipboard buffer used on GetClipboardText()+#endif++//---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- typedef struct {@@ -852,10 +859,22 @@ }  // Get clipboard text content-// NOTE: returned string must be freed with SDL_free() const char *GetClipboardText(void) {-    return SDL_GetClipboardText();+    static char buffer[MAX_CLIPBOARD_BUFFER_LENGTH] = { 0 };++    char *clipboard = SDL_GetClipboardText();++    int clipboardSize = snprintf(buffer, sizeof(buffer), "%s", clipboard);+    if (clipboardSize >= MAX_CLIPBOARD_BUFFER_LENGTH)+    {+        char *truncate = buffer + MAX_CLIPBOARD_BUFFER_LENGTH - 4;+        sprintf(truncate, "...");+    }++    SDL_free(clipboard);++    return buffer; }  // Show mouse cursor@@ -966,6 +985,12 @@     CORE.Input.Mouse.cursor = cursor; } +// Get physical key name.+const char *GetKeyName(int key)+{+    return SDL_GetKeyName(key);+}+ static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event) {     CORE.Input.Touch.pointCount = SDL_GetNumTouchFingers(event.touchId);@@ -1583,8 +1608,8 @@     // Initialize storage system     //----------------------------------------------------------------------------     // Define base path for storage-    CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory();  -    CHDIR(CORE.Storage.basePath); +    CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory();+    CHDIR(CORE.Storage.basePath);     //----------------------------------------------------------------------------      TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully");
raylib/src/platforms/rcore_drm.c view
@@ -206,7 +206,7 @@     [BTN_TL] = GAMEPAD_BUTTON_LEFT_TRIGGER_1,     [BTN_TL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2,     [BTN_TR] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1,-    [BTN_TR2] GAMEPAD_BUTTON_RIGHT_TRIGGER_2,+    [BTN_TR2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2,     [BTN_SELECT] = GAMEPAD_BUTTON_MIDDLE_LEFT,     [BTN_MODE] = GAMEPAD_BUTTON_MIDDLE,     [BTN_START] = GAMEPAD_BUTTON_MIDDLE_RIGHT,@@ -628,6 +628,13 @@     TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform"); } +// Get physical key name.+const char *GetKeyName(int key)+{+    TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");+    return "";+}+ // Register all input events void PollInputEvents(void) {@@ -756,8 +763,10 @@          drmModeConnector *con = drmModeGetConnector(platform.fd, res->connectors[i]);         TRACELOG(LOG_TRACE, "DISPLAY: Connector modes detected: %i", con->count_modes);--        if ((con->connection == DRM_MODE_CONNECTED) && (con->encoder_id))+        +        // In certain cases the status of the conneciton is reported as UKNOWN, but it is still connected.+        // This might be a hardware or software limitation like on Raspberry Pi Zero with composite output.+        if (((con->connection == DRM_MODE_CONNECTED) || (con->connection == DRM_MODE_UNKNOWNCONNECTION)) && (con->encoder_id))         {             TRACELOG(LOG_TRACE, "DISPLAY: DRM mode connected");             platform.connector = con;@@ -1470,7 +1479,6 @@             TEST_BIT(relBits, REL_Y) &&             TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;     }-      if (TEST_BIT(evBits, EV_KEY))     {
raylib/src/platforms/rcore_template.c view
@@ -384,6 +384,13 @@     TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform"); } +// Get physical key name.+const char *GetKeyName(int key)+{+    TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");+    return "";+}+ // Register all input events void PollInputEvents(void) {@@ -422,7 +429,6 @@      // TODO: Poll input events for current platform }-  //---------------------------------------------------------------------------------- // Module Internal Functions Definition
raylib/src/platforms/rcore_web.c view
@@ -129,7 +129,7 @@  // Emscripten window callback events static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData);-static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData);+// static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData); static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData);  // Emscripten input callback events@@ -884,6 +884,13 @@     } } +// Get physical key name.+const char *GetKeyName(int key)+{+    TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");+    return "";+}+ // Register all input events void PollInputEvents(void) {@@ -928,7 +935,6 @@     // 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 @@ -974,7 +980,7 @@                     default: break;                 } -                if (button != -1)   // Check for valid button+                if (button + 1 != 0)   // Check for valid button                 {                     if (gamepadState.digitalButton[j] == 1)                     {@@ -1565,12 +1571,12 @@ }  // Register window resize event-static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData)-{-    // TODO: Implement EmscriptenWindowResizedCallback()?+// static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData)+// {+//     // TODO: Implement EmscriptenWindowResizedCallback()? -    return 1; // The event was consumed by the callback handler-}+//     return 1; // The event was consumed by the callback handler+// }  EM_JS(int, GetWindowInnerWidth, (), { return window.innerWidth; }); EM_JS(int, GetWindowInnerHeight, (), { return window.innerHeight; });@@ -1586,11 +1592,11 @@     int width = GetWindowInnerWidth();     int height = GetWindowInnerHeight(); -    if (width < CORE.Window.screenMin.width) width = CORE.Window.screenMin.width;-    else if (width > CORE.Window.screenMax.width && CORE.Window.screenMax.width > 0) width = CORE.Window.screenMax.width;+    if (width < (int)CORE.Window.screenMin.width) width = CORE.Window.screenMin.width;+    else if (width > (int)CORE.Window.screenMax.width && CORE.Window.screenMax.width > 0) width = CORE.Window.screenMax.width; -    if (height < CORE.Window.screenMin.height) height = CORE.Window.screenMin.height;-    else if (height > CORE.Window.screenMax.height && CORE.Window.screenMax.height > 0) height = CORE.Window.screenMax.height;+    if (height < (int)CORE.Window.screenMin.height) height = CORE.Window.screenMin.height;+    else if (height > (int)CORE.Window.screenMax.height && CORE.Window.screenMax.height > 0) height = CORE.Window.screenMax.height;      emscripten_set_canvas_element_size("#canvas", width, height); 
raylib/src/raudio.c view
@@ -1626,7 +1626,9 @@         {             music.ctxType = MUSIC_AUDIO_FLAC;             music.ctxData = ctxFlac;-            music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);+            int sampleSize = ctxFlac->bitsPerSample;+            if (ctxFlac->bitsPerSample == 24) sampleSize = 16;   // Forcing conversion to s16 on UpdateMusicStream()+            music.stream = LoadAudioStream(ctxFlac->sampleRate, sampleSize, ctxFlac->channels);             music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;             music.looping = true;   // Looping enabled by default             musicLoaded = true;
raylib/src/raylib.h view
@@ -1,6 +1,6 @@ /********************************************************************************************** *-*   raylib v5.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)+*   raylib v5.5-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * *   FEATURES: *       - NO external dependencies, all required libraries included with raylib@@ -84,7 +84,7 @@ #define RAYLIB_VERSION_MAJOR 5 #define RAYLIB_VERSION_MINOR 5 #define RAYLIB_VERSION_PATCH 0-#define RAYLIB_VERSION  "5.5"+#define RAYLIB_VERSION  "5.5-dev"  // Function specifiers in case library is build/used as a shared library // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll@@ -352,8 +352,10 @@     // Animation vertex data     float *animVertices;    // Animated vertex positions (after bones transformations)     float *animNormals;     // Animated normals (after bones transformations)-    unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning)-    float *boneWeights;     // Vertex bone weight, up to 4 bones influence by vertex (skinning)+    unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)+    float *boneWeights;     // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)+    Matrix *boneMatrices;   // Bones animated transformation matrices+    int boneCount;          // Number of bones      // OpenGL identifiers     unsigned int vaoId;     // OpenGL Vertex Array Object id@@ -790,7 +792,10 @@     SHADER_LOC_MAP_CUBEMAP,         // Shader location: samplerCube texture: cubemap     SHADER_LOC_MAP_IRRADIANCE,      // Shader location: samplerCube texture: irradiance     SHADER_LOC_MAP_PREFILTER,       // Shader location: samplerCube texture: prefilter-    SHADER_LOC_MAP_BRDF             // Shader location: sampler2d texture: brdf+    SHADER_LOC_MAP_BRDF,            // Shader location: sampler2d texture: brdf+    SHADER_LOC_VERTEX_BONEIDS,      // Shader location: vertex attribute: boneIds+    SHADER_LOC_VERTEX_BONEWEIGHTS,  // Shader location: vertex attribute: boneWeights+    SHADER_LOC_BONE_MATRICES        // Shader location: array of matrices uniform: boneMatrices } ShaderLocationIndex;  #define SHADER_LOC_MAP_DIFFUSE      SHADER_LOC_MAP_ALBEDO@@ -968,8 +973,8 @@ RLAPI bool IsWindowState(unsigned int flag);                      // Check if one specific window flag is enabled RLAPI void SetWindowState(unsigned int flags);                    // Set window configuration state using flags (only PLATFORM_DESKTOP) RLAPI void ClearWindowState(unsigned int flags);                  // Clear window configuration state flags-RLAPI void ToggleFullscreen(void);                                // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)-RLAPI void ToggleBorderlessWindowed(void);                        // Toggle window state: borderless windowed (only PLATFORM_DESKTOP)+RLAPI void ToggleFullscreen(void);                                // Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP)+RLAPI void ToggleBorderlessWindowed(void);                        // Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP) RLAPI void MaximizeWindow(void);                                  // Set window state: maximized, if resizable (only PLATFORM_DESKTOP) RLAPI void MinimizeWindow(void);                                  // Set window state: minimized, if resizable (only PLATFORM_DESKTOP) RLAPI void RestoreWindow(void);                                   // Set window state: not minimized/maximized (only PLATFORM_DESKTOP)@@ -1122,11 +1127,12 @@ RLAPI const char *GetPrevDirectoryPath(const char *dirPath);      // Get previous directory path for a given path (uses static string) RLAPI const char *GetWorkingDirectory(void);                      // Get current working directory (uses static string) RLAPI const char *GetApplicationDirectory(void);                  // Get the directory of the running application (uses static string)+RLAPI int MakeDirectory(const char *dirPath);                     // Create directories (including full path requested), returns 0 on success RLAPI bool ChangeDirectory(const char *dir);                      // Change working directory, return true on success RLAPI bool IsPathFile(const char *path);                          // Check if a given path is a file or a directory RLAPI bool IsFileNameValid(const char *fileName);                 // Check if fileName is valid for the platform/OS RLAPI FilePathList LoadDirectoryFiles(const char *dirPath);       // Load directory filepaths-RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan+RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result RLAPI void UnloadDirectoryFiles(FilePathList files);              // Unload filepaths RLAPI bool IsFileDropped(void);                                   // Check if a file has been dropped into window RLAPI FilePathList LoadDroppedFiles(void);                        // Load dropped filepaths@@ -1228,8 +1234,8 @@ RLAPI Rectangle GetShapesTextureRectangle(void);                        // Get texture source rectangle that is used for shapes drawing  // Basic shapes drawing functions-RLAPI void DrawPixel(int posX, int posY, Color color);                                                   // Draw a pixel-RLAPI void DrawPixelV(Vector2 position, Color color);                                                    // Draw a pixel (Vector version)+RLAPI void DrawPixel(int posX, int posY, Color color);                                                   // Draw a pixel using geometry [Can be slow, use with care]+RLAPI void DrawPixelV(Vector2 position, Color color);                                                    // Draw a pixel using geometry (Vector version) [Can be slow, use with care] RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color);                // Draw a line RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color);                                     // Draw a line (using gl lines) RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color);                       // Draw a line (using triangles/quads)@@ -1238,7 +1244,7 @@ RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color);                              // Draw a color-filled circle RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color);      // Draw a piece of a circle RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline-RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2);       // Draw a gradient-filled circle+RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer);         // Draw a gradient-filled circle RLAPI void DrawCircleV(Vector2 center, float radius, Color color);                                       // Draw a color-filled circle (Vector version) RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color);                         // Draw circle outline RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color);                                  // Draw circle outline (Vector version)@@ -1250,9 +1256,9 @@ RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color);                                  // Draw a color-filled rectangle (Vector version) RLAPI void DrawRectangleRec(Rectangle rec, Color color);                                                 // Draw a color-filled rectangle RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color);                 // Draw a color-filled rectangle with pro parameters-RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a vertical-gradient-filled rectangle-RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a horizontal-gradient-filled rectangle-RLAPI void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4);       // Draw a gradient-filled rectangle with custom vertex colors+RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom);   // Draw a vertical-gradient-filled rectangle+RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right);   // Draw a horizontal-gradient-filled rectangle+RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight); // Draw a gradient-filled rectangle with custom vertex colors RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color);                   // Draw rectangle outline RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color);                            // Draw rectangle outline with extended parameters RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color);              // Draw rectangle with rounded edges@@ -1306,7 +1312,6 @@ // 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'@@ -1431,6 +1436,7 @@ RLAPI Color ColorContrast(Color color, float contrast);                     // Get color with contrast correction, contrast values between -1.0f and 1.0f RLAPI Color ColorAlpha(Color color, float alpha);                           // Get color with alpha applied, alpha goes from 0.0f to 1.0f RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint);              // Get src alpha-blended into dst color with tint+RLAPI Color ColorLerp(Color color1, Color color2, float factor);            // Get color lerp interpolation between two colors, factor [0.0f..1.0f] RLAPI Color GetColor(unsigned int hexValue);                                // Get Color structure from hexadecimal value RLAPI Color GetPixelColor(void *srcPtr, int format);                        // Get Color from a source pixel pointer of certain format RLAPI void SetPixelColor(void *dstPtr, Color color, int format);            // Set color formatted into destination pixel pointer@@ -1443,7 +1449,7 @@ // Font loading/unloading functions RLAPI Font GetFontDefault(void);                                                            // Get the default Font RLAPI Font LoadFont(const char *fileName);                                                  // Load font from file into GPU memory (VRAM)-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+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@@ -1545,6 +1551,8 @@ RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint);          // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters+RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points+RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color);                                   // Draw bounding box (wires) RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint);   // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source@@ -1588,6 +1596,7 @@ RLAPI void UnloadModelAnimation(ModelAnimation anim);                                       // Unload animation data RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount);                // Unload animation array data RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim);                         // Check model animation skeleton match+RLAPI void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame);   // Update model animation mesh bone matrices (Note GPU skinning does not work on Mac)  // Collision detection functions RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2);   // Check collision between two spheres
raylib/src/rcamera.h view
@@ -162,7 +162,6 @@  #endif // RCAMERA_H - /*********************************************************************************** * *   CAMERA IMPLEMENTATION@@ -196,12 +195,12 @@ //---------------------------------------------------------------------------------- // Defines and Macros //-----------------------------------------------------------------------------------#define CAMERA_MOVE_SPEED                               0.09f+#define CAMERA_MOVE_SPEED                               5.4f       // Units per second #define CAMERA_ROTATION_SPEED                           0.03f #define CAMERA_PAN_SPEED                                0.2f  // Camera mouse movement sensitivity-#define CAMERA_MOUSE_MOVE_SENSITIVITY                   0.003f     // TODO: it should be independant of framerate+#define CAMERA_MOUSE_MOVE_SENSITIVITY                   0.003f  // Camera orbital speed in CAMERA_ORBITAL mode #define CAMERA_ORBITAL_SPEED                            0.5f       // Radians per second@@ -444,11 +443,17 @@     bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));     bool rotateUp = false; +    // Camera speeds based on frame time+    float cameraMoveSpeed = CAMERA_MOVE_SPEED*GetFrameTime();+    float cameraRotationSpeed = CAMERA_ROTATION_SPEED*GetFrameTime();+    float cameraPanSpeed = CAMERA_PAN_SPEED*GetFrameTime();+    float cameraOrbitalSpeed = CAMERA_ORBITAL_SPEED*GetFrameTime();+     if (mode == CAMERA_CUSTOM) {}     else if (mode == CAMERA_ORBITAL)     {         // Orbital can just orbit-        Matrix rotation = MatrixRotate(GetCameraUp(camera), CAMERA_ORBITAL_SPEED*GetFrameTime());+        Matrix rotation = MatrixRotate(GetCameraUp(camera), cameraOrbitalSpeed);         Vector3 view = Vector3Subtract(camera->position, camera->target);         view = Vector3Transform(view, rotation);         camera->position = Vector3Add(camera->target, view);@@ -456,22 +461,22 @@     else     {         // Camera rotation-        if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp);-        if (IsKeyDown(KEY_UP)) CameraPitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp);-        if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget);-        if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget);-        if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED);-        if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED);+        if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp);+        if (IsKeyDown(KEY_UP)) CameraPitch(camera, cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp);+        if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -cameraRotationSpeed, rotateAroundTarget);+        if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, cameraRotationSpeed, rotateAroundTarget);+        if (IsKeyDown(KEY_Q)) CameraRoll(camera, -cameraRotationSpeed);+        if (IsKeyDown(KEY_E)) CameraRoll(camera, cameraRotationSpeed);          // Camera movement         // Camera pan (for CAMERA_FREE)         if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))         {             const Vector2 mouseDelta = GetMouseDelta();-            if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane);-            if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane);-            if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED);-            if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED);+            if (mouseDelta.x > 0.0f) CameraMoveRight(camera, cameraPanSpeed, moveInWorldPlane);+            if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -cameraPanSpeed, moveInWorldPlane);+            if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -cameraPanSpeed);+            if (mouseDelta.y < 0.0f) CameraMoveUp(camera, cameraPanSpeed);         }         else         {@@ -481,10 +486,10 @@         }          // Keyboard support-        if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);-        if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);-        if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);-        if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);+        if (IsKeyDown(KEY_W)) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane);+        if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane);+        if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane);+        if (IsKeyDown(KEY_D)) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane);          // Gamepad movement         if (IsGamepadAvailable(0))@@ -493,16 +498,16 @@             CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);             CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); -            if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);-            if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);-            if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);-            if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);+            if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane);+            if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane);+            if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane);+            if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane);         }          if (mode == CAMERA_FREE)         {-            if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);-            if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);+            if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, cameraMoveSpeed);+            if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -cameraMoveSpeed);         }     } 
raylib/src/rcore.c view
@@ -165,6 +165,10 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #elif defined(__linux__)     #include <unistd.h>+#elif defined(__FreeBSD__)+    #include <sys/types.h>+    #include <sys/sysctl.h>+    #include <unistd.h> #elif defined(__APPLE__)     #include <sys/syslimits.h>     #include <mach-o/dyld.h>@@ -187,14 +191,16 @@ #endif  #if defined(_WIN32)-    #include <direct.h>             // Required for: _getch(), _chdir()+    #include <io.h>                 // Required for: _access() [Used in FileExists()]+    #include <direct.h>             // Required for: _getch(), _chdir(), _mkdir()     #define GETCWD _getcwd          // NOTE: MSDN recommends not to use getcwd(), chdir()     #define CHDIR _chdir-    #include <io.h>                 // Required for: _access() [Used in FileExists()]+    #define MKDIR(dir) _mkdir(dir) #else-    #include <unistd.h>             // Required for: getch(), chdir() (POSIX), access()+    #include <unistd.h>             // Required for: getch(), chdir(), mkdir(), access()     #define GETCWD getcwd     #define CHDIR chdir+    #define MKDIR(dir) mkdir(dir, 0777) #endif  //----------------------------------------------------------------------------------@@ -247,6 +253,10 @@     #define MAX_AUTOMATION_EVENTS      16384        // Maximum number of automation events to record #endif +#ifndef DIRECTORY_FILTER_TAG+    #define DIRECTORY_FILTER_TAG       "DIR"        // Name tag used to request directory inclusion on directory scan+#endif                                              // NOTE: Used in ScanDirectoryFiles(), ScanDirectoryFilesRecursively() and LoadDirectoryFilesEx()+ // Flags operation macros #define FLAG_SET(n, f) ((n) |= (f)) #define FLAG_CLEAR(n, f) ((n) &= ~(f))@@ -360,16 +370,21 @@ //---------------------------------------------------------------------------------- RLAPI const char *raylib_version = RAYLIB_VERSION;  // raylib version exported symbol, required for some bindings -CoreData CORE = { 0 };               // Global CORE state context+CoreData CORE = { 0 };                      // Global CORE state context +// Flag to note GPU acceleration is available,+// referenced from other modules to support GPU data loading+// NOTE: Useful to allow Texture, RenderTexture, Font.texture, Mesh.vaoId/vboId, Shader loading+bool isGpuReady = false;+ #if defined(SUPPORT_SCREEN_CAPTURE)-static int screenshotCounter = 0;    // Screenshots counter+static int screenshotCounter = 0;           // Screenshots counter #endif  #if defined(SUPPORT_GIF_RECORDING)-unsigned int gifFrameCounter = 0;    // GIF frames counter-bool gifRecording = false;           // GIF recording state-MsfGifState gifState = { 0 };        // MSGIF context state+static unsigned int gifFrameCounter = 0;    // GIF frames counter+static bool gifRecording = false;           // GIF recording state+static MsfGifState gifState = { 0 };        // MSGIF context state #endif  #if defined(SUPPORT_AUTOMATION_EVENTS)@@ -563,7 +578,6 @@ //void DisableCursor(void)  // Initialize window and OpenGL context-// NOTE: data parameter could be used to pass any kind of required data to the initialization void InitWindow(int width, int height, const char *title) {     TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);@@ -637,28 +651,31 @@     // Initialize rlgl default data (buffers and shaders)     // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl     rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);+    isGpuReady = true; // Flag to note GPU has been initialized successfully      // Setup default viewport     SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); -#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)-    // Load default font-    // WARNING: External function: Module required: rtext-    LoadFontDefault();-    #if defined(SUPPORT_MODULE_RSHAPES)-    // Set font white rectangle for shapes drawing, so shapes and text can be batched together-    // WARNING: rshapes module is required, if not available, default internal white rectangle is used-    Rectangle rec = GetFontDefault().recs[95];-    if (CORE.Window.flags & FLAG_MSAA_4X_HINT)-    {-        // NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering-        SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });-    }-    else-    {-        // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding-        SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });-    }+#if defined(SUPPORT_MODULE_RTEXT)+    #if defined(SUPPORT_DEFAULT_FONT)+        // Load default font+        // WARNING: External function: Module required: rtext+        LoadFontDefault();+        #if defined(SUPPORT_MODULE_RSHAPES)+        // Set font white rectangle for shapes drawing, so shapes and text can be batched together+        // WARNING: rshapes module is required, if not available, default internal white rectangle is used+        Rectangle rec = GetFontDefault().recs[95];+        if (CORE.Window.flags & FLAG_MSAA_4X_HINT)+        {+            // NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering+            SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });+        }+        else+        {+            // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding+            SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });+        }+        #endif     #endif #else     #if defined(SUPPORT_MODULE_RSHAPES)@@ -668,21 +685,14 @@     SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f });    // WARNING: Module required: rshapes     #endif #endif-#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)-    if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)-    {-        // Set default font texture filter for HighDPI (blurry)-        // RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps-        rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR);-        rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);-    }-#endif      CORE.Time.frameCounter = 0;     CORE.Window.shouldClose = false;      // Initialize random seed     SetRandomSeed((unsigned int)time(NULL));+    +    TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", GetWorkingDirectory()); }  // Close window and unload OpenGL context@@ -1294,6 +1304,8 @@         //          vertex color location       = 3         //          vertex tangent location     = 4         //          vertex texcoord2 location   = 5+        //          vertex boneIds location     = 6+        //          vertex boneWeights location = 7          // NOTE: If any location is not found, loc point becomes -1 @@ -1309,6 +1321,8 @@         shader.locs[SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);         shader.locs[SHADER_LOC_VERTEX_TANGENT] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);         shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);+        shader.locs[SHADER_LOC_VERTEX_BONEIDS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);+        shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS);          // Get handles to GLSL uniform locations (vertex shader)         shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP);@@ -1316,6 +1330,7 @@         shader.locs[SHADER_LOC_MATRIX_PROJECTION] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION);         shader.locs[SHADER_LOC_MATRIX_MODEL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL);         shader.locs[SHADER_LOC_MATRIX_NORMAL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL);+        shader.locs[SHADER_LOC_BONE_MATRICES] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES);          // Get handles to GLSL uniform locations (fragment shader)         shader.locs[SHADER_LOC_COLOR_DIFFUSE] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR);@@ -2160,6 +2175,28 @@         appDir[0] = '.';         appDir[1] = '/';     }+#elif defined(__FreeBSD__)+    size_t size = sizeof(appDir);+    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};++    if (sysctl(mib, 4, appDir, &size, NULL, 0) == 0)+    {+        int len = strlen(appDir);+        for (int i = len; i >= 0; --i)+        {+            if (appDir[i] == '/')+            {+                appDir[i + 1] = '\0';+                break;+            }+        }+    }+    else+    {+        appDir[0] = '.';+        appDir[1] = '/';+    }+ #endif      return appDir;@@ -2231,6 +2268,40 @@     RL_FREE(files.paths); } +// Create directories (including full path requested), returns 0 on success+int MakeDirectory(const char *dirPath)+{+    if ((dirPath == NULL) || (dirPath[0] == '\0')) return 1; // Path is not valid+    if (DirectoryExists(dirPath)) return 0; // Path already exists (is valid)++    // Copy path string to avoid modifying original+    int len = (int)strlen(dirPath) + 1;+    char *pathcpy = (char *)RL_CALLOC(len, 1);+    memcpy(pathcpy, dirPath, len);++    // Iterate over pathcpy, create each subdirectory as needed+    for (int i = 0; (i < len) && (pathcpy[i] != '\0'); i++)+    {+        if (pathcpy[i] == ':') i++;+        else+        {+            if ((pathcpy[i] == '\\') || (pathcpy[i] == '/'))+            {+                pathcpy[i] = '\0';+                if (!DirectoryExists(pathcpy)) MKDIR(pathcpy);+                pathcpy[i] = '/';+            }+        }+    }++    // Create final directory+    if (!DirectoryExists(pathcpy)) MKDIR(pathcpy);++    RL_FREE(pathcpy);++    return 0;+}+ // Change working directory, returns true on success bool ChangeDirectory(const char *dir) {@@ -2713,8 +2784,8 @@             } break;             case INPUT_MOUSE_WHEEL_MOTION:  // param[0]: x delta, param[1]: y delta             {-                CORE.Input.Mouse.currentWheelMove.x = (float)event.params[0]; break;-                CORE.Input.Mouse.currentWheelMove.y = (float)event.params[1]; break;+                CORE.Input.Mouse.currentWheelMove.x = (float)event.params[0];+                CORE.Input.Mouse.currentWheelMove.y = (float)event.params[1];             } break;             case INPUT_TOUCH_UP: CORE.Input.Touch.currentTouchState[event.params[0]] = false; break;            // param[0]: id             case INPUT_TOUCH_DOWN: CORE.Input.Touch.currentTouchState[event.params[0]] = true; break;           // param[0]: id@@ -2751,6 +2822,8 @@             case ACTION_SETTARGETFPS: SetTargetFPS(event.params[0]); break;             default: break;         }++        TRACELOG(LOG_INFO, "AUTOMATION PLAY: Frame: %i | Event type: %i | Event parameters: %i, %i, %i", event.frame, event.type, event.params[0], event.params[1], event.params[2]);     } #endif }@@ -2958,11 +3031,15 @@ // Get axis movement vector for a gamepad float GetGamepadAxisMovement(int gamepad, int axis) {-    float value = 0;+    float value = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f; -    if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS) &&-        (fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]) > 0.1f)) value = CORE.Input.Gamepad.axisState[gamepad][axis];      // 0.1f = GAMEPAD_AXIS_MINIMUM_DRIFT/DELTA+    if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS)) {+        float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]); +        // 0.1f = GAMEPAD_AXIS_MINIMUM_DRIFT/DELTA+        if (movement > value + 0.1f) value = CORE.Input.Gamepad.axisState[gamepad][axis];+    }+     return value; } @@ -3306,11 +3383,22 @@                  if (filter != NULL)                 {-                    if (IsFileExtension(path, filter))+                    if (IsPathFile(path))                     {-                        strcpy(files->paths[files->count], path);-                        files->count++;+                        if (IsFileExtension(path, filter))+                        {+                            strcpy(files->paths[files->count], path);+                            files->count++;+                        }                     }+                    else+                    {+                        if (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0)+                        {+                            strcpy(files->paths[files->count], path);+                            files->count++;+                        }+                    }                 }                 else                 {@@ -3369,7 +3457,22 @@                         break;                     }                 }-                else ScanDirectoryFilesRecursively(path, files, filter);+                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);+                        break;+                    }++                    ScanDirectoryFilesRecursively(path, files, filter);+                }             }         } @@ -3482,7 +3585,7 @@         currentEventList->events[currentEventList->count].frame = CORE.Time.frameCounter;         currentEventList->events[currentEventList->count].type = INPUT_MOUSE_WHEEL_MOTION;         currentEventList->events[currentEventList->count].params[0] = (int)CORE.Input.Mouse.currentWheelMove.x;-        currentEventList->events[currentEventList->count].params[1] = (int)CORE.Input.Mouse.currentWheelMove.y;;+        currentEventList->events[currentEventList->count].params[1] = (int)CORE.Input.Mouse.currentWheelMove.y;         currentEventList->events[currentEventList->count].params[2] = 0;          TRACELOG(LOG_INFO, "AUTOMATION: Frame: %i | Event type: INPUT_MOUSE_WHEEL_MOTION | Event parameters: %i, %i, %i", currentEventList->events[currentEventList->count].frame, currentEventList->events[currentEventList->count].params[0], currentEventList->events[currentEventList->count].params[1], currentEventList->events[currentEventList->count].params[2]);@@ -3605,7 +3708,8 @@         for (int axis = 0; axis < MAX_GAMEPAD_AXIS; axis++)         {             // Event type: INPUT_GAMEPAD_AXIS_MOTION-            if (CORE.Input.Gamepad.axisState[gamepad][axis] > 0.1f)+            float defaultMovement = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f;+            if (GetGamepadAxisMovement(gamepad, axis) != defaultMovement)             {                 currentEventList->events[currentEventList->count].frame = CORE.Time.frameCounter;                 currentEventList->events[currentEventList->count].type = INPUT_GAMEPAD_AXIS_MOTION;
raylib/src/rlgl.h view
@@ -68,12 +68,15 @@ *       #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR        "vertexColor"       // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR *       #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT      "vertexTangent"     // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT *       #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2    "vertexTexCoord2"   // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2+*       #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS      "vertexBoneIds"     // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS+*       #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS  "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS *       #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP         "mvp"               // model-view-projection matrix *       #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW        "matView"           // view matrix *       #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION  "matProjection"     // projection matrix *       #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL       "matModel"          // model matrix *       #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL      "matNormal"         // normal matrix (transpose(inverse(matModelView))) *       #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR       "colDiffuse"        // color diffuse (base tint color, multiplied by texture color)+*       #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES  "boneMatrices"   // bone matrices *       #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0  "texture0"          // texture0 (texture slot active 0) *       #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1  "texture1"          // texture1 (texture slot active 1) *       #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2  "texture2"          // texture2 (texture slot active 2)@@ -324,24 +327,36 @@  // Default shader vertex attribute locations #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION-    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION  0+    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION    0 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD-    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD  1+    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD    1 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL-    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL    2+    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL      2 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR-    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR     3+    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR       3 #endif     #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT-#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT       4+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT         4 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2-    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5+    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2   5 #endif+#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+#endif+#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS+    #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8+#endif+#endif+ //---------------------------------------------------------------------------------- // Types and Structures Definition //----------------------------------------------------------------------------------@@ -527,6 +542,10 @@     RL_SHADER_UNIFORM_IVEC2,            // Shader uniform type: ivec2 (2 int)     RL_SHADER_UNIFORM_IVEC3,            // Shader uniform type: ivec3 (3 int)     RL_SHADER_UNIFORM_IVEC4,            // Shader uniform type: ivec4 (4 int)+    RL_SHADER_UNIFORM_UINT,             // Shader uniform type: unsigned int+    RL_SHADER_UNIFORM_UIVEC2,           // Shader uniform type: uivec2 (2 unsigned int)+    RL_SHADER_UNIFORM_UIVEC3,           // Shader uniform type: uivec3 (3 unsigned int)+    RL_SHADER_UNIFORM_UIVEC4,           // Shader uniform type: uivec4 (4 unsigned int)     RL_SHADER_UNIFORM_SAMPLER2D         // Shader uniform type: sampler2d } rlShaderUniformDataType; @@ -665,7 +684,7 @@ RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test RLAPI void rlEnableWireMode(void);                      // Enable wire mode RLAPI void rlEnablePointMode(void);                     // Enable point mode-RLAPI void rlDisableWireMode(void);                     // Disable wire mode ( and point ) maybe rename+RLAPI void rlDisableWireMode(void);                     // Disable wire (and point) mode RLAPI void rlSetLineWidth(float width);                 // Set the line drawing width RLAPI float rlGetLineWidth(void);                       // Get the line drawing width RLAPI void rlEnableSmoothLines(void);                   // Enable line aliasing@@ -755,6 +774,7 @@ RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName);   // Get shader location attribute RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat);                        // Set shader value matrix+RLAPI void rlSetUniformMatrices(int locIndex, const Matrix *mat, int count);    // Set shader value matrices RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId);           // Set shader value sampler RLAPI void rlSetShader(unsigned int id, int *locs);                             // Set shader currently active (id and locations) @@ -973,6 +993,12 @@ #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2     #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2    "vertexTexCoord2"   // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 #endif+#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS+    #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS      "vertexBoneIds"     // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS+#endif+#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS+    #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS  "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS+#endif  #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP     #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP         "mvp"               // model-view-projection matrix@@ -992,6 +1018,9 @@ #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR     #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR       "colDiffuse"        // color diffuse (base tint color, multiplied by texture color) #endif+#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES+    #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES  "boneMatrices"   // bone matrices+#endif #ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0     #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0  "texture0"          // texture0 (texture slot active 0) #endif@@ -1948,6 +1977,7 @@ #endif } +// Enable point mode void rlEnablePointMode(void) { #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)@@ -1956,6 +1986,7 @@     glEnable(GL_PROGRAM_POINT_SIZE); #endif }+ // Disable wire mode void rlDisableWireMode(void) {@@ -3994,18 +4025,18 @@     unsigned int fragmentShaderId = 0;      // Compile vertex shader (if provided)+    // NOTE: If not vertex shader is provided, use default one     if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER);-    // In case no vertex shader was provided or compilation failed, we use default vertex shader-    if (vertexShaderId == 0) vertexShaderId = RLGL.State.defaultVShaderId;+    else vertexShaderId = RLGL.State.defaultVShaderId;      // Compile fragment shader (if provided)+    // NOTE: If not vertex shader is provided, use default one     if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);-    // In case no fragment shader was provided or compilation failed, we use default fragment shader-    if (fragmentShaderId == 0) fragmentShaderId = RLGL.State.defaultFShaderId;+    else fragmentShaderId = RLGL.State.defaultFShaderId;      // In case vertex and fragment shader are the default ones, no need to recompile, we can just assign the default shader program id     if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId;-    else+    else if ((vertexShaderId > 0) && (fragmentShaderId > 0))     {         // One of or both shader are new, we need to compile a new shader program         id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId);@@ -4083,6 +4114,8 @@             //case GL_GEOMETRY_SHADER:         #if defined(GRAPHICS_API_OPENGL_43)             case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile compute shader code", shader); break;+        #elif defined(GRAPHICS_API_OPENGL_33)+            case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break;         #endif             default: break;         }@@ -4098,6 +4131,8 @@             TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log);             RL_FREE(log);         }++        shader = 0;     }     else     {@@ -4108,6 +4143,8 @@             //case GL_GEOMETRY_SHADER:         #if defined(GRAPHICS_API_OPENGL_43)             case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader compiled successfully", shader); break;+        #elif defined(GRAPHICS_API_OPENGL_33)+            case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break;         #endif             default: break;         }@@ -4137,6 +4174,11 @@     glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);     glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); +#ifdef RL_SUPPORT_MESH_GPU_SKINNING+    glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);+    glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS);+#endif+     // NOTE: If some attrib name is no found on the shader, it locations becomes -1      glLinkProgram(program);@@ -4228,8 +4270,16 @@         case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break;         case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break;         case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break;+    #if !defined(GRAPHICS_API_OPENGL_ES2)+        case RL_SHADER_UNIFORM_UINT: glUniform1uiv(locIndex, count, (unsigned int *)value); break;+        case RL_SHADER_UNIFORM_UIVEC2: glUniform2uiv(locIndex, count, (unsigned int *)value); break;+        case RL_SHADER_UNIFORM_UIVEC3: glUniform3uiv(locIndex, count, (unsigned int *)value); break;+        case RL_SHADER_UNIFORM_UIVEC4: glUniform4uiv(locIndex, count, (unsigned int *)value); break;+    #endif         case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break;         default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized");++        // TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv()     } #endif }@@ -4263,6 +4313,14 @@ #endif } +// Set shader value uniform matrix+void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count)+{+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)+    glUniformMatrix4fv(locIndex, count, true, (const float*)matrices);+#endif+}+ // Set shader value uniform sampler void rlSetUniformSampler(int locIndex, unsigned int textureId) {@@ -4348,6 +4406,8 @@          TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program);     }+#else+    TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43"); #endif      return program;@@ -4372,6 +4432,8 @@     glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY);     if (data == NULL) glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL);    // Clear buffer data to 0     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);+#else+    TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43"); #endif      return ssbo;@@ -4382,7 +4444,10 @@ { #if defined(GRAPHICS_API_OPENGL_43)     glDeleteBuffers(1, &ssboId);+#else+    TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43"); #endif+ }  // Update SSBO buffer data@@ -4397,14 +4462,14 @@ // Get SSBO buffer size unsigned int rlGetShaderBufferSize(unsigned int id) {-    long long size = 0;- #if defined(GRAPHICS_API_OPENGL_43)+    GLint64 size = 0;     glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);     glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);-#endif-     return (size > 0)? (unsigned int)size : 0;+#else+    return 0;+#endif }  // Read SSBO buffer data (GPU->CPU)@@ -4442,6 +4507,8 @@      rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);     glBindImageTexture(index, id, 0, 0, 0, readonly? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat);+#else+    TRACELOG(RL_LOG_WARNING, "TEXTURE: Image texture binding not enabled. Define GRAPHICS_API_OPENGL_43"); #endif } @@ -4756,7 +4823,16 @@     "out vec2 fragTexCoord;             \n"     "out vec4 fragColor;                \n" #endif-#if defined(GRAPHICS_API_OPENGL_ES2)++#if defined(GRAPHICS_API_OPENGL_ES3)+    "#version 300 es                    \n"+    "precision mediump float;           \n"     // Precision required for OpenGL ES3 (WebGL 2) (on some browsers)+    "in vec3 vertexPosition;            \n"+    "in vec2 vertexTexCoord;            \n"+    "in vec4 vertexColor;               \n"+    "out vec2 fragTexCoord;             \n"+    "out vec4 fragColor;                \n"+#elif defined(GRAPHICS_API_OPENGL_ES2)     "#version 100                       \n"     "precision mediump float;           \n"     // Precision required for OpenGL ES2 (WebGL) (on some browsers)     "attribute vec3 vertexPosition;     \n"@@ -4765,6 +4841,7 @@     "varying vec2 fragTexCoord;         \n"     "varying vec4 fragColor;            \n" #endif+     "uniform mat4 mvp;                  \n"     "void main()                        \n"     "{                                  \n"@@ -4799,7 +4876,21 @@     "    finalColor = texelColor*colDiffuse*fragColor;        \n"     "}                                  \n"; #endif-#if defined(GRAPHICS_API_OPENGL_ES2)++#if defined(GRAPHICS_API_OPENGL_ES3)+    "#version 300 es                    \n"+    "precision mediump float;           \n"     // Precision required for OpenGL ES3 (WebGL 2)+    "in vec2 fragTexCoord;              \n"+    "in vec4 fragColor;                 \n"+    "out vec4 finalColor;               \n"+    "uniform sampler2D texture0;        \n"+    "uniform vec4 colDiffuse;           \n"+    "void main()                        \n"+    "{                                  \n"+    "    vec4 texelColor = texture(texture0, fragTexCoord);   \n"+    "    finalColor = texelColor*colDiffuse*fragColor;        \n"+    "}                                  \n";+#elif defined(GRAPHICS_API_OPENGL_ES2)     "#version 100                       \n"     "precision mediump float;           \n"     // Precision required for OpenGL ES2 (WebGL)     "varying vec2 fragTexCoord;         \n"@@ -4969,7 +5060,8 @@         default: break;     } -    dataSize = width*height*bpp/8;  // Total data size in bytes+    double bytesPerPixel = (double)bpp/8.0;+    dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes      // Most compressed formats works on 4x4 blocks,     // if texture is smaller, minimum dataSize is 8 or 16
raylib/src/rmodels.c view
@@ -130,7 +130,7 @@     #define MAX_MATERIAL_MAPS       12    // Maximum number of maps supported #endif #ifndef MAX_MESH_VERTEX_BUFFERS-    #define MAX_MESH_VERTEX_BUFFERS  7    // Maximum vertex buffers (VBO) per mesh+    #define MAX_MESH_VERTEX_BUFFERS  9    // Maximum vertex buffers (VBO) per mesh #endif  //----------------------------------------------------------------------------------@@ -702,7 +702,6 @@     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)@@ -1246,14 +1245,19 @@     mesh->vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int));      mesh->vaoId = 0;        // Vertex Array Object-    mesh->vboId[0] = 0;     // Vertex buffer: positions-    mesh->vboId[1] = 0;     // Vertex buffer: texcoords-    mesh->vboId[2] = 0;     // Vertex buffer: normals-    mesh->vboId[3] = 0;     // Vertex buffer: colors-    mesh->vboId[4] = 0;     // Vertex buffer: tangents-    mesh->vboId[5] = 0;     // Vertex buffer: texcoords2-    mesh->vboId[6] = 0;     // Vertex buffer: indices+    mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = 0;     // Vertex buffer: positions+    mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = 0;     // Vertex buffer: texcoords+    mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = 0;       // Vertex buffer: normals+    mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = 0;        // Vertex buffer: colors+    mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = 0;      // Vertex buffer: tangents+    mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = 0;    // Vertex buffer: texcoords2+    mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = 0;      // Vertex buffer: indices +#ifdef RL_SUPPORT_MESH_GPU_SKINNING+    mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = 0;      // Vertex buffer: boneIds+    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);@@ -1262,12 +1266,12 @@      // Enable vertex attributes: position (shader-location = 0)     void *vertices = (mesh->animVertices != NULL)? mesh->animVertices : mesh->vertices;-    mesh->vboId[0] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic);+    mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic);     rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, RL_FLOAT, 0, 0, 0);     rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);      // Enable vertex attributes: texcoords (shader-location = 1)-    mesh->vboId[1] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic);+    mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic);     rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, RL_FLOAT, 0, 0, 0);     rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD); @@ -1278,7 +1282,7 @@     {         // Enable vertex attributes: normals (shader-location = 2)         void *normals = (mesh->animNormals != NULL)? mesh->animNormals : mesh->normals;-        mesh->vboId[2] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic);+        mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic);         rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, 3, RL_FLOAT, 0, 0, 0);         rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);     }@@ -1294,7 +1298,7 @@     if (mesh->colors != NULL)     {         // Enable vertex attribute: color (shader-location = 3)-        mesh->vboId[3] = rlLoadVertexBuffer(mesh->colors, mesh->vertexCount*4*sizeof(unsigned char), dynamic);+        mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = rlLoadVertexBuffer(mesh->colors, mesh->vertexCount*4*sizeof(unsigned char), dynamic);         rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, 4, RL_UNSIGNED_BYTE, 1, 0, 0);         rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR);     }@@ -1310,7 +1314,7 @@     if (mesh->tangents != NULL)     {         // Enable vertex attribute: tangent (shader-location = 4)-        mesh->vboId[4] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), dynamic);+        mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), dynamic);         rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, 4, RL_FLOAT, 0, 0, 0);         rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT);     }@@ -1326,7 +1330,7 @@     if (mesh->texcoords2 != NULL)     {         // Enable vertex attribute: texcoord2 (shader-location = 5)-        mesh->vboId[5] = rlLoadVertexBuffer(mesh->texcoords2, mesh->vertexCount*2*sizeof(float), dynamic);+        mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = rlLoadVertexBuffer(mesh->texcoords2, mesh->vertexCount*2*sizeof(float), dynamic);         rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, 2, RL_FLOAT, 0, 0, 0);         rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2);     }@@ -1339,9 +1343,43 @@         rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2);     } +#ifdef RL_SUPPORT_MESH_GPU_SKINNING+    if (mesh->boneIds != NULL)+    {+        // Enable vertex attribute: boneIds (shader-location = 6)+        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);+    }+    else+    {+        // Default vertex attribute: boneIds+        // WARNING: Default value provided to shader if location available+        float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f };+        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)+        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);+    }+    else+    {+        // Default vertex attribute: boneWeights+        // WARNING: Default value provided to shader if location available+        float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f };+        rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, value, SHADER_ATTRIB_VEC4, 2);+        rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS);+    }+#endif+     if (mesh->indices != NULL)     {-        mesh->vboId[6] = rlLoadVertexBufferElement(mesh->indices, mesh->triangleCount*3*sizeof(unsigned short), dynamic);+        mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = rlLoadVertexBufferElement(mesh->indices, mesh->triangleCount*3*sizeof(unsigned short), dynamic);     }      if (mesh->vaoId > 0) TRACELOG(LOG_INFO, "VAO: [ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId);@@ -1451,6 +1489,14 @@      // 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    +    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)@@ -1478,19 +1524,19 @@     if (!rlEnableVertexArray(mesh.vaoId))     {         // Bind mesh VBO data: vertex position (shader-location = 0)-        rlEnableVertexBuffer(mesh.vboId[0]);+        rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION]);         rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);         rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);          // Bind mesh VBO data: vertex texcoords (shader-location = 1)-        rlEnableVertexBuffer(mesh.vboId[1]);+        rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD]);         rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);         rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);          if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)         {             // Bind mesh VBO data: vertex normals (shader-location = 2)-            rlEnableVertexBuffer(mesh.vboId[2]);+            rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL]);             rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);             rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);         }@@ -1498,9 +1544,9 @@         // Bind mesh VBO data: vertex colors (shader-location = 3, if available)         if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)         {-            if (mesh.vboId[3] != 0)+            if (mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] != 0)             {-                rlEnableVertexBuffer(mesh.vboId[3]);+                rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR]);                 rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);                 rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);             }@@ -1517,7 +1563,7 @@         // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)         if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)         {-            rlEnableVertexBuffer(mesh.vboId[4]);+            rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT]);             rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);             rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);         }@@ -1525,12 +1571,30 @@         // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)         if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)         {-            rlEnableVertexBuffer(mesh.vboId[5]);+            rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2]);             rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);             rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);         } -        if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);+#ifdef RL_SUPPORT_MESH_GPU_SKINNING+        // Bind mesh VBO data: vertex bone ids (shader-location = 6, if available)+        if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1)+        {+            rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS]);+            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)+        {+            rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS]);+            rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS], 4, RL_FLOAT, 0, 0, 0);+            rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS]);+        }+#endif++        if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]);     }      int eyeCount = 1;@@ -1671,6 +1735,15 @@      // 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    +    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)@@ -1696,19 +1769,19 @@     if (!rlEnableVertexArray(mesh.vaoId))     {         // Bind mesh VBO data: vertex position (shader-location = 0)-        rlEnableVertexBuffer(mesh.vboId[0]);+        rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION]);         rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);         rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);          // Bind mesh VBO data: vertex texcoords (shader-location = 1)-        rlEnableVertexBuffer(mesh.vboId[1]);+        rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD]);         rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);         rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);          if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)         {             // Bind mesh VBO data: vertex normals (shader-location = 2)-            rlEnableVertexBuffer(mesh.vboId[2]);+            rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL]);             rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);             rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);         }@@ -1716,9 +1789,9 @@         // Bind mesh VBO data: vertex colors (shader-location = 3, if available)         if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)         {-            if (mesh.vboId[3] != 0)+            if (mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] != 0)             {-                rlEnableVertexBuffer(mesh.vboId[3]);+                rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR]);                 rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);                 rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);             }@@ -1735,7 +1808,7 @@         // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)         if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)         {-            rlEnableVertexBuffer(mesh.vboId[4]);+            rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT]);             rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);             rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);         }@@ -1743,12 +1816,30 @@         // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)         if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)         {-            rlEnableVertexBuffer(mesh.vboId[5]);+            rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2]);             rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);             rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);         } -        if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);+#ifdef RL_SUPPORT_MESH_GPU_SKINNING+        // Bind mesh VBO data: vertex bone ids (shader-location = 6, if available)+        if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1)+        {+            rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS]);+            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)+        {+            rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS]);+            rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS], 4, RL_FLOAT, 0, 0, 0);+            rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS]);+        }+#endif++        if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]);     }      int eyeCount = 1;@@ -1825,6 +1916,7 @@     RL_FREE(mesh.animNormals);     RL_FREE(mesh.boneWeights);     RL_FREE(mesh.boneIds);+    RL_FREE(mesh.boneMatrices); }  // Export mesh data to file@@ -2004,7 +2096,6 @@     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)@@ -2016,6 +2107,8 @@         // NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE         materials[m] = LoadMaterialDefault(); +        if (mats == NULL) continue;+         // Get default texture, in case no texture is defined         // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8         materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };@@ -2253,6 +2346,50 @@     } } +void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame)+{+    if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL))+    {+        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;++                    Vector3 invTranslation = Vector3RotateByQuaternion(Vector3Negate(inTranslation), QuaternionInvert(inRotation));+                    Quaternion invRotation = QuaternionInvert(inRotation);+                    Vector3 invScale = Vector3Divide((Vector3){ 1.0f, 1.0f, 1.0f }, inScale);++                    Vector3 boneTranslation = Vector3Add(+                        Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation),+                        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;+                }+            }+        }+    }+}+ // Unload animation array data void UnloadModelAnimations(ModelAnimation *animations, int animCount) {@@ -3631,6 +3768,30 @@     rlDisableWireMode(); } +// Draw a model points+void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)+{+    rlEnablePointMode();+    rlDisableBackfaceCulling();++    DrawModel(model, position, scale, tint);++    rlEnableBackfaceCulling();+    rlDisableWireMode();+}++// Draw a model points+void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)+{+    rlEnablePointMode();+    rlDisableBackfaceCulling();++    DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);++    rlEnableBackfaceCulling();+    rlDisableWireMode();+}+ // Draw a billboard void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint) {@@ -4049,126 +4210,238 @@ //  - the mesh is automatically triangulated by tinyobj static Model LoadOBJ(const char *fileName) {+    tinyobj_attrib_t objAttributes = { 0 };+    tinyobj_shape_t* objShapes = NULL;+    unsigned int objShapeCount = 0;++    tinyobj_material_t* objMaterials = NULL;+    unsigned int objMaterialCount = 0;+     Model model = { 0 };+    model.transform = MatrixIdentity(); -    tinyobj_attrib_t attrib = { 0 };-    tinyobj_shape_t *meshes = NULL;-    unsigned int meshCount = 0;+    char* fileText = LoadFileText(fileName); -    tinyobj_material_t *materials = NULL;-    unsigned int materialCount = 0;+    if (fileText == NULL)+    {+        TRACELOG(LOG_ERROR, "MODEL Unable to read obj file %s", fileName);+        return model;+    } -    char *fileText = LoadFileText(fileName);+    char currentDir[1024] = { 0 };+    strcpy(currentDir, GetWorkingDirectory()); // Save current working directory+    const char* workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness+    if (CHDIR(workingDir) != 0)+    {+        TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);+    } -    if (fileText != NULL)+    unsigned int dataSize = (unsigned int)strlen(fileText);++    unsigned int flags = TINYOBJ_FLAG_TRIANGULATE;+    int ret = tinyobj_parse_obj(&objAttributes, &objShapes, &objShapeCount, &objMaterials, &objMaterialCount, fileText, dataSize, flags);++    if (ret != TINYOBJ_SUCCESS)     {-        unsigned int dataSize = (unsigned int)strlen(fileText);+        TRACELOG(LOG_ERROR, "MODEL Unable to read obj data %s", fileName);+        return model;+    } -        char currentDir[1024] = { 0 };-        strcpy(currentDir, GetWorkingDirectory()); // Save current working directory-        const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness-        if (CHDIR(workingDir) != 0)+    UnloadFileText(fileText);++    unsigned int faceVertIndex = 0;+    unsigned int nextShape = 1;+    int lastMaterial = -1;+    unsigned int meshIndex = 0;++    // count meshes+    unsigned int nextShapeEnd = objAttributes.num_face_num_verts;++    // see how many verts till the next shape++    if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;++    // walk all the faces+    for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)+    {+        if (faceVertIndex >= nextShapeEnd)         {-            TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);+            // try to find the last vert in the next shape+            nextShape++;+            if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;+            else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces+            meshIndex++;         }+        else if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial)+        {+            meshIndex++;// if this is a new material, we need to allocate a new mesh+        } -        unsigned int flags = TINYOBJ_FLAG_TRIANGULATE;-        int ret = tinyobj_parse_obj(&attrib, &meshes, &meshCount, &materials, &materialCount, fileText, dataSize, flags);+        lastMaterial = objAttributes.material_ids[faceId];+        faceVertIndex += objAttributes.face_num_verts[faceId];+    } -        if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName);-        else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount);+    // allocate the base meshes and materials+    model.meshCount = meshIndex + 1;+    model.meshes = (Mesh*)MemAlloc(sizeof(Mesh) * model.meshCount); -        // WARNING: We are not splitting meshes by materials (previous implementation)-        // Depending on the provided OBJ that was not the best option and it just crashed-        // so, implementation was simplified to prioritize parsed meshes-        model.meshCount = meshCount;+    if (objMaterialCount > 0)+    {+        model.materialCount = objMaterialCount;+        model.materials = (Material*)MemAlloc(sizeof(Material) * objMaterialCount);+    }+    else // we must allocate at least one material+    {+        model.materialCount = 1;+        model.materials = (Material*)MemAlloc(sizeof(Material) * 1);+    } -        // Set number of materials available-        // NOTE: There could be more materials available than meshes but it will be resolved at-        // model.meshMaterial, just assigning the right material to corresponding mesh-        model.materialCount = materialCount;-        if (model.materialCount == 0)+    model.meshMaterial = (int*)MemAlloc(sizeof(int) * model.meshCount);++    // see how many verts are in each mesh+    unsigned int* localMeshVertexCounts = (unsigned int*)MemAlloc(sizeof(unsigned int) * model.meshCount);++    faceVertIndex = 0;+    nextShapeEnd = objAttributes.num_face_num_verts;+    lastMaterial = -1;+    meshIndex = 0;+    unsigned int localMeshVertexCount = 0;++    nextShape = 1;+    if (objShapeCount > 1)+        nextShapeEnd = objShapes[nextShape].face_offset;++    // walk all the faces+    for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)+    {+        bool newMesh = false; // do we need a new mesh?+        if (faceVertIndex >= nextShapeEnd)         {-            model.materialCount = 1;-            TRACELOG(LOG_INFO, "MODEL: No materials provided, setting one default material for all meshes");+            // try to find the last vert in the next shape+            nextShape++;+            if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;+            else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces++            newMesh = true;         }+        else if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial)+        {+            newMesh = true;+        } -        // Init model meshes and materials-        model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));-        model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int)); // Material index assigned to each mesh-        model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));+        lastMaterial = objAttributes.material_ids[faceId]; -        // Process each provided mesh-        for (int i = 0; i < model.meshCount; i++)+        if (newMesh)         {-            // WARNING: We need to calculate the mesh triangles manually using meshes[i].face_offset-            // because in case of triangulated quads, meshes[i].length actually report quads,-            // despite the triangulation that is efectively considered on attrib.num_faces-            unsigned int tris = 0;-            if (i == model.meshCount - 1) tris = attrib.num_faces - meshes[i].face_offset;-            else tris = meshes[i + 1].face_offset;+            localMeshVertexCounts[meshIndex] = localMeshVertexCount; -            model.meshes[i].vertexCount = tris*3;-            model.meshes[i].triangleCount = tris;   // Face count (triangulated)-            model.meshes[i].vertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));-            model.meshes[i].texcoords = (float *)RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float));-            model.meshes[i].normals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));-            model.meshMaterial[i] = 0;  // By default, assign material 0 to each mesh+            localMeshVertexCount = 0;+            meshIndex++;+        } -            // Process all mesh faces-            for (unsigned int face = 0, f = meshes[i].face_offset, v = 0, vt = 0, vn = 0; face < tris; face++, f++, v += 3, vt += 3, vn += 3)-            {-                // Get indices for the face-                tinyobj_vertex_index_t idx0 = attrib.faces[f*3 + 0];-                tinyobj_vertex_index_t idx1 = attrib.faces[f*3 + 1];-                tinyobj_vertex_index_t idx2 = attrib.faces[f*3 + 2];+        faceVertIndex += objAttributes.face_num_verts[faceId];+        localMeshVertexCount += objAttributes.face_num_verts[faceId];+    }+    localMeshVertexCounts[meshIndex] = localMeshVertexCount; -                // Fill vertices buffer (float) using vertex index of the face-                for (int n = 0; n < 3; n++) { model.meshes[i].vertices[v*3 + n] = attrib.vertices[idx0.v_idx*3 + n]; }-                for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 1)*3 + n] = attrib.vertices[idx1.v_idx*3 + n]; }-                for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 2)*3 + n] = attrib.vertices[idx2.v_idx*3 + n]; }+    for (int i = 0; i < model.meshCount; i++)+    {+        // allocate the buffers for each mesh+        unsigned int vertexCount = localMeshVertexCounts[i]; -                if (attrib.num_texcoords > 0)-                {-                    // Fill texcoords buffer (float) using vertex index of the face-                    // NOTE: Y-coordinate must be flipped upside-down-                    model.meshes[i].texcoords[vt*2 + 0] = attrib.texcoords[idx0.vt_idx*2 + 0];-                    model.meshes[i].texcoords[vt*2 + 1] = 1.0f - attrib.texcoords[idx0.vt_idx*2 + 1];+        model.meshes[i].vertexCount = vertexCount;+        model.meshes[i].triangleCount = vertexCount / 3; -                    model.meshes[i].texcoords[(vt + 1)*2 + 0] = attrib.texcoords[idx1.vt_idx*2 + 0];-                    model.meshes[i].texcoords[(vt + 1)*2 + 1] = 1.0f - attrib.texcoords[idx1.vt_idx*2 + 1];+        model.meshes[i].vertices = (float*)MemAlloc(sizeof(float) * vertexCount * 3);+        model.meshes[i].normals = (float*)MemAlloc(sizeof(float) * vertexCount * 3);+        model.meshes[i].texcoords = (float*)MemAlloc(sizeof(float) * vertexCount * 2);+        model.meshes[i].colors = (unsigned char*)MemAlloc(sizeof(unsigned char) * vertexCount * 4);+    } -                    model.meshes[i].texcoords[(vt + 2)*2 + 0] = attrib.texcoords[idx2.vt_idx*2 + 0];-                    model.meshes[i].texcoords[(vt + 2)*2 + 1] = 1.0f - attrib.texcoords[idx2.vt_idx*2 + 1];-                }+    MemFree(localMeshVertexCounts);+    localMeshVertexCounts = NULL; -                if (attrib.num_normals > 0)-                {-                    // Fill normals buffer (float) using vertex index of the face-                    for (int n = 0; n < 3; n++) { model.meshes[i].normals[vn*3 + n] = attrib.normals[idx0.vn_idx*3 + n]; }-                    for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 1)*3 + n] = attrib.normals[idx1.vn_idx*3 + n]; }-                    for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 2)*3 + n] = attrib.normals[idx2.vn_idx*3 + n]; }-                }-            }+    // fill meshes+    faceVertIndex = 0;++    nextShapeEnd = objAttributes.num_face_num_verts;++    // see how many verts till the next shape+    nextShape = 1;+    if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;+    lastMaterial = -1;+    meshIndex = 0;+    localMeshVertexCount = 0;++    // walk all the faces+    for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)+    {+        bool newMesh = false; // do we need a new mesh?+        if (faceVertIndex >= nextShapeEnd)+        {+            // try to find the last vert in the next shape+            nextShape++;+            if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;+            else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces+            newMesh = true;         }+        // if this is a new material, we need to allocate a new mesh+        if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) newMesh = true;+        lastMaterial = objAttributes.material_ids[faceId]; -        // Init model materials-        if (materialCount > 0) ProcessMaterialsOBJ(model.materials, materials, materialCount);-        else model.materials[0] = LoadMaterialDefault(); // Set default material for the mesh+        if (newMesh)+        {+            localMeshVertexCount = 0;+            meshIndex++;+        } -        tinyobj_attrib_free(&attrib);-        tinyobj_shapes_free(meshes, model.meshCount);-        tinyobj_materials_free(materials, materialCount);+        int matId = 0;+        if (lastMaterial >= 0 && lastMaterial < (int)objMaterialCount)+            matId = lastMaterial; -        UnloadFileText(fileText);+        model.meshMaterial[meshIndex] = matId; -        // Restore current working directory-        if (CHDIR(currentDir) != 0)+        for (int f = 0; f < objAttributes.face_num_verts[faceId]; f++)         {-            TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir);+            int vertIndex = objAttributes.faces[faceVertIndex].v_idx;+            int normalIndex = objAttributes.faces[faceVertIndex].vn_idx;+            int texcordIndex = objAttributes.faces[faceVertIndex].vt_idx;++            for (int i = 0; i < 3; i++)+                model.meshes[meshIndex].vertices[localMeshVertexCount * 3 + i] = objAttributes.vertices[vertIndex * 3 + i];++            for (int i = 0; i < 3; i++)+                model.meshes[meshIndex].normals[localMeshVertexCount * 3 + i] = objAttributes.normals[normalIndex * 3 + i];++            for (int i = 0; i < 2; i++)+                model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + i] = objAttributes.texcoords[texcordIndex * 2 + i];++            model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + 1];++            for (int i = 0; i < 4; i++)+                model.meshes[meshIndex].colors[localMeshVertexCount * 4 + i] = 255;++            faceVertIndex++;+            localMeshVertexCount++;         }     } +    if (objMaterialCount > 0) ProcessMaterialsOBJ(model.materials, objMaterials, objMaterialCount);+    else model.materials[0] = LoadMaterialDefault(); // Set default material for the mesh++    tinyobj_attrib_free(&objAttributes);+    tinyobj_shapes_free(objShapes, objShapeCount);+    tinyobj_materials_free(objMaterials, objMaterialCount);++    for (int i = 0; i < model.meshCount; i++)+        UploadMesh(model.meshes + i, true);++    // Restore current working directory+    if (CHDIR(currentDir) != 0)+    {+        TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir);+    }+     return model; } #endif@@ -4533,6 +4806,17 @@     }      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();+        }+    }      UnloadFileData(fileData); @@ -4942,17 +5226,19 @@     ***********************************************************************************************/      // 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));\         }\     } @@ -5393,8 +5679,6 @@                             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@@ -5415,23 +5699,25 @@                         // 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 @@ -5463,7 +5749,7 @@         //  - 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);@@ -5483,9 +5769,9 @@                 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;@@ -5616,6 +5902,15 @@                 {                     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();+                }                  meshIndex++;       // Move to next mesh             }@@ -5741,11 +6036,11 @@                 cgltf_accessor_read_float(output, 3*keyframe+1, tmp, 4);                 Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]};                 cgltf_accessor_read_float(output, 3*keyframe+2, tmp, 4);-                Vector4 outTangent1 = {tmp[0], tmp[1], tmp[2]};+                Vector4 outTangent1 = {tmp[0], tmp[1], tmp[2], 0.0f};                 cgltf_accessor_read_float(output, 3*(keyframe+1)+1, tmp, 4);                 Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};                 cgltf_accessor_read_float(output, 3*(keyframe+1), tmp, 4);-                Vector4 inTangent2 = {tmp[0], tmp[1], tmp[2]};+                Vector4 inTangent2 = {tmp[0], tmp[1], tmp[2], 0.0f};                 Vector4 *r = data;                  v1 = QuaternionNormalize(v1);@@ -5797,7 +6092,7 @@      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;@@ -5932,7 +6227,11 @@                 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);     }@@ -6384,6 +6683,13 @@             {                 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++)+                {+                    model.meshes[i].boneMatrices[j] = MatrixIdentity();+                }             }         } 
raylib/src/rshapes.c view
@@ -79,8 +79,8 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //-----------------------------------------------------------------------------------Texture2D texShapes = { 1, 1, 1, 1, 7 };                // Texture used on shapes drawing (white pixel loaded by rlgl)-Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f };    // Texture source rectangle used on shapes drawing+static Texture2D texShapes = { 1, 1, 1, 1, 7 };                // Texture used on shapes drawing (white pixel loaded by rlgl)+static Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f };    // Texture source rectangle used on shapes drawing  //---------------------------------------------------------------------------------- // Module specific Functions Declaration@@ -430,17 +430,16 @@ }  // Draw a gradient-filled circle-// NOTE: Gradient goes from center (color1) to border (color2)-void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)+void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer) {     rlBegin(RL_TRIANGLES);         for (int i = 0; i < 360; i += 10)         {-            rlColor4ub(color1.r, color1.g, color1.b, color1.a);+            rlColor4ub(inner.r, inner.g, inner.b, inner.a);             rlVertex2f((float)centerX, (float)centerY);-            rlColor4ub(color2.r, color2.g, color2.b, color2.a);+            rlColor4ub(outer.r, outer.g, outer.b, outer.a);             rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius);-            rlColor4ub(color2.r, color2.g, color2.b, color2.a);+            rlColor4ub(outer.r, outer.g, outer.b, outer.a);             rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius);         }     rlEnd();@@ -761,22 +760,19 @@ }  // Draw a vertical-gradient-filled rectangle-// NOTE: Gradient goes from bottom (color1) to top (color2)-void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)+void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom) {-    DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color2, color2, color1);+    DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, top, bottom, bottom, top); }  // Draw a horizontal-gradient-filled rectangle-// NOTE: Gradient goes from bottom (color1) to top (color2)-void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2)+void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right) {-    DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color1, color2, color2);+    DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, left, left, right, right); }  // Draw a gradient-filled rectangle-// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise-void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)+void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight) {     rlSetTexture(GetShapesTexture().id);     Rectangle shapeRect = GetShapesTextureRectangle();@@ -785,19 +781,19 @@         rlNormal3f(0.0f, 0.0f, 1.0f);          // NOTE: Default raylib font character 95 is a white square-        rlColor4ub(col1.r, col1.g, col1.b, col1.a);+        rlColor4ub(topLeft.r, topLeft.g, topLeft.b, topLeft.a);         rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);         rlVertex2f(rec.x, rec.y); -        rlColor4ub(col2.r, col2.g, col2.b, col2.a);+        rlColor4ub(bottomLeft.r, bottomLeft.g, bottomLeft.b, bottomLeft.a);         rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);         rlVertex2f(rec.x, rec.y + rec.height); -        rlColor4ub(col3.r, col3.g, col3.b, col3.a);+        rlColor4ub(topRight.r, topRight.g, topRight.b, topRight.a);         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);         rlVertex2f(rec.x + rec.width, rec.y + rec.height); -        rlColor4ub(col4.r, col4.g, col4.b, col4.a);+        rlColor4ub(bottomRight.r, bottomRight.g, bottomRight.b, bottomRight.a);         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);         rlVertex2f(rec.x + rec.width, rec.y);     rlEnd();
raylib/src/rtext.c view
@@ -124,6 +124,7 @@ //---------------------------------------------------------------------------------- // Global variables //----------------------------------------------------------------------------------+extern bool isGpuReady; #if defined(SUPPORT_DEFAULT_FONT) // Default font provided by raylib // NOTE: Default font is loaded on InitWindow() and disposed on CloseWindow() [module: core]@@ -252,15 +253,15 @@         counter++;     } -    defaultFont.texture = LoadTextureFromImage(imFont);+    if (isGpuReady) defaultFont.texture = LoadTextureFromImage(imFont);      // Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount     //------------------------------------------------------------------------------      // Allocate space for our characters info data     // NOTE: This memory must be freed at end! --> Done by CloseWindow()-    defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo));-    defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle));+    defaultFont.glyphs = (GlyphInfo *)RL_CALLOC(defaultFont.glyphCount, sizeof(GlyphInfo));+    defaultFont.recs = (Rectangle *)RL_CALLOC(defaultFont.glyphCount, sizeof(Rectangle));      int currentLine = 0;     int currentPosX = charsDivisor;@@ -308,7 +309,7 @@ extern void UnloadFontDefault(void) {     for (int i = 0; i < defaultFont.glyphCount; i++) UnloadImage(defaultFont.glyphs[i].image);-    UnloadTexture(defaultFont.texture);+    if (isGpuReady) UnloadTexture(defaultFont.texture);     RL_FREE(defaultFont.glyphs);     RL_FREE(defaultFont.recs); }@@ -362,11 +363,14 @@         UnloadImage(image);     } -    if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName);-    else+    if (isGpuReady)     {-        SetTextureFilter(font.texture, TEXTURE_FILTER_POINT);    // By default, we set point filter (the best performance)-        TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS);+        if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName);+        else+        {+            SetTextureFilter(font.texture, TEXTURE_FILTER_POINT);    // By default, we set point filter (the best performance)+            TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS);+        }     }      return font;@@ -487,7 +491,7 @@     };      // Set font with all data parsed from image-    font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture+    if (isGpuReady) font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture     font.glyphCount = index;     font.glyphPadding = 0; @@ -556,7 +560,7 @@         font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;          Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0);-        font.texture = LoadTextureFromImage(atlas);+        if (isGpuReady) font.texture = LoadTextureFromImage(atlas);          // Update glyphs[i].image to use alpha, required to be used on ImageDrawText()         for (int i = 0; i < font.glyphCount; i++)@@ -580,7 +584,7 @@ // Check if a font is ready bool IsFontReady(Font font) {-    return ((font.texture.id > 0) &&    // Validate OpenGL id fot font texture atlas+    return ((font.texture.id > 0) &&    // Validate OpenGL id for font texture atlas             (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@@ -673,6 +677,8 @@                     {                         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                         chars[i].image.width = chw;@@ -946,7 +952,7 @@     if (font.texture.id != GetFontDefault().texture.id)     {         UnloadFontData(font.glyphs, font.glyphCount);-        UnloadTexture(font.texture);+        if (isGpuReady) UnloadTexture(font.texture);         RL_FREE(font.recs);          TRACELOGD("FONT: Unloaded font data from RAM and VRAM");@@ -1066,7 +1072,7 @@     byteCount += sprintf(txtData + byteCount, "    Image imFont = { fontImageData_%s, %i, %i, 1, %i };\n\n", styleName, image.width, image.height, image.format); #endif     byteCount += sprintf(txtData + byteCount, "    // Load texture from image\n");-    byteCount += sprintf(txtData + byteCount, "    font.texture = LoadTextureFromImage(imFont);\n");+    byteCount += sprintf(txtData + byteCount, "    if (isGpuReady) font.texture = LoadTextureFromImage(imFont);\n"); #if defined(SUPPORT_COMPRESSED_FONT_ATLAS)     byteCount += sprintf(txtData + byteCount, "    UnloadImage(imFont);  // Uncompressed data can be unloaded from memory\n\n"); #endif@@ -1277,7 +1283,7 @@ {     Vector2 textSize = { 0 }; -    if ((font.texture.id == 0) || (text == NULL)) return textSize; // Security check+    if ((isGpuReady && (font.texture.id == 0)) || (text == NULL)) return textSize; // Security check      int size = TextLength(text);    // Get size in bytes of text     int tempByteCounter = 0;        // Used to count longer text line num chars@@ -1467,8 +1473,7 @@     int i = 0;     for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0'); -    if (text[i++] != '.') value *= sign;-    else+    if (text[i++] == '.')     {         float divisor = 10.0f;         for (; ((text[i] >= '0') && (text[i] <= '9')); i++)@@ -1478,7 +1483,7 @@         }     } -    return value;+    return value*sign; }  #if defined(SUPPORT_TEXT_MANIPULATION)@@ -2258,7 +2263,7 @@      RL_FREE(imFonts); -    font.texture = LoadTextureFromImage(fullFont);+    if (isGpuReady) font.texture = LoadTextureFromImage(fullFont);      // Fill font characters info data     font.baseSize = fontSize;@@ -2300,7 +2305,7 @@     UnloadImage(fullFont);     UnloadFileText(fileText); -    if (font.texture.id == 0)+    if (isGpuReady && (font.texture.id == 0))     {         UnloadFont(font);         font = GetFontDefault();
raylib/src/rtextures.c view
@@ -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 @@     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-            //<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2484" viewBox="0 0 192.756 191.488">-            if ((fileNameOrString != NULL) &&-                (fileNameOrString[0] == '<') &&-                (fileNameOrString[1] == 's') &&-                (fileNameOrString[2] == 'v') &&-                (fileNameOrString[3] == 'g'))-            {-                fileData = (unsigned char *)fileNameOrString;-                isSvgStringValid = true;-            }-        }--        if (isSvgStringValid)-        {-            struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f);--            unsigned char *img = RL_MALLOC(width*height*4);--            // Calculate scales for both the width and the height-            const float scaleWidth = width/svgImage->width;-            const float scaleHeight = height/svgImage->height;--            // Set the largest of the 2 scales to be the scale to use-            const float scale = (scaleHeight > scaleWidth)? scaleWidth : scaleHeight;--            int offsetX = 0;-            int offsetY = 0;--            if (scaleHeight > scaleWidth) offsetY = (height - svgImage->height*scale)/2;-            else offsetX = (width - svgImage->width*scale)/2;--            // Rasterize-            struct NSVGrasterizer *rast = nsvgCreateRasterizer();-            nsvgRasterize(rast, svgImage, (int)offsetX, (int)offsetY, scale, img, width, height, width*4);--            // Populate image struct with all data-            image.data = img;-            image.width = width;-            image.height = height;-            image.mipmaps = 1;-            image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;--            // Free used memory-            nsvgDelete(svgImage);-            nsvgDeleteRasterizer(rast);-        }--        if (isSvgStringValid && (fileData != fileNameOrString)) UnloadFileData(fileData);-    }-#else-    TRACELOG(LOG_WARNING, "SVG image support not enabled, image can not be loaded");-#endif--    return image;-}- // Load animated image data //  - Image.data buffer includes all frames: [image#0][image#1][image#2][...] //  - Number of frames is returned through 'frames' parameter@@ -503,7 +417,16 @@     Image image = { 0 };      // Security check for input data-    if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image;+    if ((fileData == NULL) || (dataSize == 0))+    {+        TRACELOG(LOG_WARNING, "IMAGE: Invalid file data");+        return image;+    }+    if (fileType == NULL)+    {+        TRACELOG(LOG_WARNING, "IMAGE: Missing file extension");+        return image;+    }      if ((false) #if defined(SUPPORT_FILEFORMAT_PNG)@@ -591,36 +514,6 @@         }     } #endif-#if defined(SUPPORT_FILEFORMAT_SVG)-    else if ((strcmp(fileType, ".svg") == 0) || (strcmp(fileType, ".SVG") == 0))-    {-        // Validate fileData as valid SVG string data-        //<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2484" viewBox="0 0 192.756 191.488">-        if ((fileData != NULL) &&-            (fileData[0] == '<') &&-            (fileData[1] == 's') &&-            (fileData[2] == 'v') &&-            (fileData[3] == 'g'))-        {-            struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f);-            unsigned char *img = RL_MALLOC(svgImage->width*svgImage->height*4);--            // Rasterize-            struct NSVGrasterizer *rast = nsvgCreateRasterizer();-            nsvgRasterize(rast, svgImage, 0, 0, 1.0f, img, svgImage->width, svgImage->height, svgImage->width*4);--            // Populate image struct with all data-            image.data = img;-            image.width = svgImage->width;-            image.height = svgImage->height;-            image.mipmaps = 1;-            image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;--            nsvgDelete(svgImage);-            nsvgDeleteRasterizer(rast);-        }-    }-#endif #if defined(SUPPORT_FILEFORMAT_DDS)     else if ((strcmp(fileType, ".dds") == 0) || (strcmp(fileType, ".DDS") == 0))     {@@ -1103,6 +996,7 @@ {     Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color)); +    float aspectRatio = (float)width / (float)height;     for (int y = 0; y < height; y++)     {         for (int x = 0; x < width; x++)@@ -1110,6 +1004,10 @@             float nx = (float)(x + offsetX)*(scale/(float)width);             float ny = (float)(y + offsetY)*(scale/(float)height); +            // Apply aspect ratio compensation to wider side+            if (width > height) nx *= aspectRatio;+            else ny /= aspectRatio;+                         // Basic perlin noise implementation (not used)             //float p = (stb_perlin_noise3(nx, ny, 0.0f, 0, 0, 0); @@ -1213,6 +1111,7 @@ {     Image image = { 0 }; +#if defined(SUPPORT_MODULE_RTEXT)     int textLength = TextLength(text);     int imageViewSize = width*height; @@ -1223,6 +1122,10 @@     image.mipmaps = 1;      memcpy(image.data, text, (textLength > imageViewSize)? imageViewSize : textLength);+#else+    TRACELOG(LOG_WARNING, "IMAGE: GenImageText() requires module: rtext");+    image = GenImageColor(width, height, BLACK);     // Generating placeholder black image rectangle+#endif      return image; }@@ -4546,6 +4449,9 @@          if (source.width < 0) { flipX = true; source.width *= -1; }         if (source.height < 0) source.y -= source.height;+        +        if (dest.width < 0) dest.width *= -1;+        if (dest.height < 0) dest.height *= -1;          Vector2 topLeft = { 0 };         Vector2 topRight = { 0 };@@ -5164,6 +5070,22 @@     return out; } +// Get color lerp interpolation between two colors, factor [0.0f..1.0f]+Color ColorLerp(Color color1, Color color2, float factor) +{ +    Color color = { 0 };+    +    if (factor < 0.0f) factor = 0.0f;+    else if (factor > 1.0f) factor = 1.0f;++    color.r = (unsigned char)((1.0f - factor)*color1.r + factor*color2.r);+    color.g = (unsigned char)((1.0f - factor)*color1.g + factor*color2.g);+    color.b = (unsigned char)((1.0f - factor)*color1.b + factor*color2.b);+    color.a = (unsigned char)((1.0f - factor)*color1.a + factor*color2.a);++    return color;+}+ // Get a Color struct from hexadecimal value Color GetColor(unsigned int hexValue) {@@ -5389,7 +5311,8 @@         default: break;     } -    dataSize = width*height*bpp/8;  // Total data size in bytes+    double bytesPerPixel = (double)bpp/8.0;+    dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes      // Most compressed formats works on 4x4 blocks,     // if texture is smaller, minimum dataSize is 8 or 16
raylib/src/utils.c view
@@ -76,7 +76,6 @@ void SetLoadFileTextCallback(LoadFileTextCallback callback) { loadFileText = callback; }  // Set custom file text loader void SetSaveFileTextCallback(SaveFileTextCallback callback) { saveFileText = callback; }  // Set custom file text saver - #if defined(PLATFORM_ANDROID) static AAssetManager *assetManager = NULL;          // Android assets manager pointer static const char *internalDataPath = NULL;         // Android internal data path
src/Raylib/Core.hs view
@@ -112,6 +112,7 @@     traceLog,     setTraceLogLevel,     openURL,+    setTraceLogCallback,     setLoadFileDataCallback,     setSaveFileDataCallback,     setLoadFileTextCallback,@@ -132,6 +133,7 @@     getPrevDirectoryPath,     getWorkingDirectory,     getApplicationDirectory,+    makeDirectory,     changeDirectory,     isPathFile,     isFileNameValid,@@ -333,6 +335,7 @@     c'getPrevDirectoryPath,     c'getWorkingDirectory,     c'getApplicationDirectory,+    c'makeDirectory,     c'changeDirectory,     c'isPathFile,     c'isFileNameValid,@@ -482,209 +485,211 @@     VrDeviceInfo,     VrStereoConfig,     unpackShaderUniformData,-    unpackShaderUniformDataV,+    unpackShaderUniformDataV, C'TraceLogCallback, TraceLogCallback,   ) import GHC.IO (unsafePerformIO)  $( genNative-     [ ("c'initWindow", "InitWindow_", "rl_bindings.h", [t|CInt -> CInt -> CString -> IO ()|], False),-       ("c'windowShouldClose", "WindowShouldClose_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'closeWindow", "CloseWindow_", "rl_bindings.h", [t|IO ()|], False),-       ("c'isWindowReady", "IsWindowReady_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'isWindowFullscreen", "IsWindowFullscreen_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'isWindowHidden", "IsWindowHidden_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'isWindowMinimized", "IsWindowMinimized_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'isWindowMaximized", "IsWindowMaximized_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'isWindowFocused", "IsWindowFocused_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'isWindowResized", "IsWindowResized_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'isWindowState", "IsWindowState_", "rl_bindings.h", [t|CUInt -> IO CBool|], False),-       ("c'setWindowState", "SetWindowState_", "rl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'clearWindowState", "ClearWindowState_", "rl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'toggleFullscreen", "ToggleFullscreen_", "rl_bindings.h", [t|IO ()|], False),-       ("c'toggleBorderlessWindowed", "ToggleBorderlessWindowed_", "rl_bindings.h", [t|IO ()|], False),-       ("c'maximizeWindow", "MaximizeWindow_", "rl_bindings.h", [t|IO ()|], False),-       ("c'minimizeWindow", "MinimizeWindow_", "rl_bindings.h", [t|IO ()|], False),-       ("c'restoreWindow", "RestoreWindow_", "rl_bindings.h", [t|IO ()|], False),-       ("c'setWindowIcon", "SetWindowIcon_", "rl_bindings.h", [t|Ptr Image -> IO ()|], False),-       ("c'setWindowIcons", "SetWindowIcons_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|], False),-       ("c'setWindowTitle", "SetWindowTitle_", "rl_bindings.h", [t|CString -> IO ()|], False),-       ("c'setWindowPosition", "SetWindowPosition_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|], False),-       ("c'setWindowMonitor", "SetWindowMonitor_", "rl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'setWindowMinSize", "SetWindowMinSize_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|], False),-       ("c'setWindowMaxSize", "SetWindowMaxSize_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|], False),-       ("c'setWindowSize", "SetWindowSize_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|], False),-       ("c'setWindowOpacity", "SetWindowOpacity_", "rl_bindings.h", [t|CFloat -> IO ()|], False),-       ("c'setWindowFocused", "SetWindowFocused_", "rl_bindings.h", [t|IO ()|], False),-       ("c'getWindowHandle", "GetWindowHandle_", "rl_bindings.h", [t|IO (Ptr ())|], False),-       ("c'getScreenWidth", "GetScreenWidth_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getScreenHeight", "GetScreenHeight_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getRenderWidth", "GetRenderWidth_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getRenderHeight", "GetRenderHeight_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getMonitorCount", "GetMonitorCount_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getCurrentMonitor", "GetCurrentMonitor_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getMonitorPosition", "GetMonitorPosition_", "rl_bindings.h", [t|CInt -> IO (Ptr Vector2)|], False),-       ("c'getMonitorWidth", "GetMonitorWidth_", "rl_bindings.h", [t|CInt -> IO CInt|], False),-       ("c'getMonitorHeight", "GetMonitorHeight_", "rl_bindings.h", [t|CInt -> IO CInt|], False),-       ("c'getMonitorPhysicalWidth", "GetMonitorPhysicalWidth_", "rl_bindings.h", [t|CInt -> IO CInt|], False),-       ("c'getMonitorPhysicalHeight", "GetMonitorPhysicalHeight_", "rl_bindings.h", [t|CInt -> IO CInt|], False),-       ("c'getMonitorRefreshRate", "GetMonitorRefreshRate_", "rl_bindings.h", [t|CInt -> IO CInt|], False),-       ("c'getWindowPosition", "GetWindowPosition_", "rl_bindings.h", [t|IO (Ptr Vector2)|], False),-       ("c'getWindowScaleDPI", "GetWindowScaleDPI_", "rl_bindings.h", [t|IO (Ptr Vector2)|], False),-       ("c'getMonitorName", "GetMonitorName_", "rl_bindings.h", [t|CInt -> IO CString|], False),-       ("c'setClipboardText", "SetClipboardText_", "rl_bindings.h", [t|CString -> IO ()|], False),-       ("c'getClipboardText", "GetClipboardText_", "rl_bindings.h", [t|IO CString|], False),-       ("c'enableEventWaiting", "EnableEventWaiting_", "rl_bindings.h", [t|IO ()|], False),-       ("c'disableEventWaiting", "DisableEventWaiting_", "rl_bindings.h", [t|IO ()|], False),-       ("c'swapScreenBuffer", "SwapScreenBuffer_", "rl_bindings.h", [t|IO ()|], False),-       ("c'pollInputEvents", "PollInputEvents_", "rl_bindings.h", [t|IO ()|], False),-       ("c'waitTime", "WaitTime_", "rl_bindings.h", [t|CDouble -> IO ()|], False),-       ("c'showCursor", "ShowCursor_", "rl_bindings.h", [t|IO ()|], False),-       ("c'hideCursor", "HideCursor_", "rl_bindings.h", [t|IO ()|], False),-       ("c'isCursorHidden", "IsCursorHidden_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'enableCursor", "EnableCursor_", "rl_bindings.h", [t|IO ()|], False),-       ("c'disableCursor", "DisableCursor_", "rl_bindings.h", [t|IO ()|], False),-       ("c'isCursorOnScreen", "IsCursorOnScreen_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'clearBackground", "ClearBackground_", "rl_bindings.h", [t|Ptr Color -> IO ()|], False),-       ("c'beginDrawing", "BeginDrawing_", "rl_bindings.h", [t|IO ()|], False),-       ("c'endDrawing", "EndDrawing_", "rl_bindings.h", [t|IO ()|], False),-       ("c'beginMode2D", "BeginMode2D_", "rl_bindings.h", [t|Ptr Camera2D -> IO ()|], False),-       ("c'endMode2D", "EndMode2D_", "rl_bindings.h", [t|IO ()|], False),-       ("c'beginMode3D", "BeginMode3D_", "rl_bindings.h", [t|Ptr Camera3D -> IO ()|], False),-       ("c'endMode3D", "EndMode3D_", "rl_bindings.h", [t|IO ()|], False),-       ("c'beginTextureMode", "BeginTextureMode_", "rl_bindings.h", [t|Ptr RenderTexture -> IO ()|], False),-       ("c'endTextureMode", "EndTextureMode_", "rl_bindings.h", [t|IO ()|], False),-       ("c'beginShaderMode", "BeginShaderMode_", "rl_bindings.h", [t|Ptr Shader -> IO ()|], False),-       ("c'endShaderMode", "EndShaderMode_", "rl_bindings.h", [t|IO ()|], False),-       ("c'beginBlendMode", "BeginBlendMode_", "rl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'endBlendMode", "EndBlendMode_", "rl_bindings.h", [t|IO ()|], False),-       ("c'beginScissorMode", "BeginScissorMode_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> IO ()|], False),-       ("c'endScissorMode", "EndScissorMode_", "rl_bindings.h", [t|IO ()|], False),-       ("c'beginVrStereoMode", "BeginVrStereoMode_", "rl_bindings.h", [t|Ptr VrStereoConfig -> IO ()|], False),-       ("c'endVrStereoMode", "EndVrStereoMode_", "rl_bindings.h", [t|IO ()|], False),-       ("c'loadVrStereoConfig", "LoadVrStereoConfig_", "rl_bindings.h", [t|Ptr VrDeviceInfo -> IO (Ptr VrStereoConfig)|], False),-       ("c'unloadVrStereoConfig", "UnloadVrStereoConfig_", "rl_bindings.h", [t|Ptr VrStereoConfig -> IO ()|], False),-       ("c'loadShader", "LoadShader_", "rl_bindings.h", [t|CString -> CString -> IO (Ptr Shader)|], False),-       ("c'loadShaderFromMemory", "LoadShaderFromMemory_", "rl_bindings.h", [t|CString -> CString -> IO (Ptr Shader)|], False),-       ("c'isShaderReady", "IsShaderReady_", "rl_bindings.h", [t|Ptr Shader -> IO CBool|], False),-       ("c'getShaderLocation", "GetShaderLocation_", "rl_bindings.h", [t|Ptr Shader -> CString -> IO CInt|], False),-       ("c'getShaderLocationAttrib", "GetShaderLocationAttrib_", "rl_bindings.h", [t|Ptr Shader -> CString -> IO CInt|], False),-       ("c'setShaderValue", "SetShaderValue_", "rl_bindings.h", [t|Ptr Shader -> CInt -> Ptr () -> CInt -> IO ()|], False),-       ("c'setShaderValueV", "SetShaderValueV_", "rl_bindings.h", [t|Ptr Shader -> CInt -> Ptr () -> CInt -> CInt -> IO ()|], False),-       ("c'setShaderValueMatrix", "SetShaderValueMatrix_", "rl_bindings.h", [t|Ptr Shader -> CInt -> Ptr Matrix -> IO ()|], False),-       ("c'setShaderValueTexture", "SetShaderValueTexture_", "rl_bindings.h", [t|Ptr Shader -> CInt -> Ptr Texture -> IO ()|], False),-       ("c'unloadShader", "UnloadShader_", "rl_bindings.h", [t|Ptr Shader -> IO ()|], False),-       ("c'getScreenToWorldRay", "GetScreenToWorldRay_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Camera3D -> IO (Ptr Ray)|], False),-       ("c'getScreenToWorldRayEx", "GetScreenToWorldRayEx_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Camera3D -> CFloat -> CFloat -> IO (Ptr Ray)|], False),-       ("c'getCameraMatrix", "GetCameraMatrix_", "rl_bindings.h", [t|Ptr Camera3D -> IO (Ptr Matrix)|], False),-       ("c'getCameraMatrix2D", "GetCameraMatrix2D_", "rl_bindings.h", [t|Ptr Camera2D -> IO (Ptr Matrix)|], False),-       ("c'getWorldToScreen", "GetWorldToScreen_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Camera3D -> IO (Ptr Vector2)|], False),-       ("c'getScreenToWorld2D", "GetScreenToWorld2D_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Camera2D -> IO (Ptr Vector2)|], False),-       ("c'getWorldToScreenEx", "GetWorldToScreenEx_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Camera3D -> CInt -> CInt -> IO (Ptr Vector2)|], False),-       ("c'getWorldToScreen2D", "GetWorldToScreen2D_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Camera2D -> IO (Ptr Vector2)|], False),-       ("c'setTargetFPS", "SetTargetFPS_", "rl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'getFPS", "GetFPS_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getFrameTime", "GetFrameTime_", "rl_bindings.h", [t|IO CFloat|], False),-       ("c'getTime", "GetTime_", "rl_bindings.h", [t|IO CDouble|], False),-       ("c'setRandomSeed", "SetRandomSeed_", "rl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'getRandomValue", "GetRandomValue_", "rl_bindings.h", [t|CInt -> CInt -> IO CInt|], False),-       ("c'loadRandomSequence", "LoadRandomSequence_", "rl_bindings.h", [t|CUInt -> CInt -> CInt -> IO (Ptr CInt)|], False),-       ("c'takeScreenshot", "TakeScreenshot_", "rl_bindings.h", [t|CString -> IO ()|], False),-       ("c'setConfigFlags", "SetConfigFlags_", "rl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'traceLog", "TraceLog_", "rl_bindings.h", [t|CInt -> CString -> IO ()|], False), -- Uses varags, can't implement complete functionality-       ("c'setTraceLogLevel", "SetTraceLogLevel_", "rl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'memAlloc", "MemAlloc_", "rl_bindings.h", [t|CInt -> IO (Ptr ())|], False),-       ("c'memRealloc", "MemRealloc_", "rl_bindings.h", [t|Ptr () -> CInt -> IO (Ptr ())|], False),-       ("c'memFree", "MemFree_", "rl_bindings.h", [t|Ptr () -> IO ()|], False),-       ("c'openURL", "OpenURL_", "rl_bindings.h", [t|CString -> IO ()|], False),-       ("c'setLoadFileDataCallback", "SetLoadFileDataCallback_", "rl_bindings.h", [t|C'LoadFileDataCallback -> IO ()|], False),-       ("c'setSaveFileDataCallback", "SetSaveFileDataCallback_", "rl_bindings.h", [t|C'SaveFileDataCallback -> IO ()|], False),-       ("c'setLoadFileTextCallback", "SetLoadFileTextCallback_", "rl_bindings.h", [t|C'LoadFileTextCallback -> IO ()|], False),-       ("c'setSaveFileTextCallback", "SetSaveFileTextCallback_", "rl_bindings.h", [t|C'SaveFileTextCallback -> IO ()|], False),-       ("c'loadFileData", "LoadFileData_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO (Ptr CUChar)|], True),-       ("c'unloadFileData", "UnloadFileData_", "rl_bindings.h", [t|Ptr CUChar -> IO ()|], False),-       ("c'saveFileData", "SaveFileData_", "rl_bindings.h", [t|CString -> Ptr () -> CInt -> IO CBool|], True),-       ("c'exportDataAsCode", "ExportDataAsCode_", "rl_bindings.h", [t|Ptr CUChar -> CInt -> CString -> IO CBool|], False),-       ("c'loadFileText", "LoadFileText_", "rl_bindings.h", [t|CString -> IO CString|], True),-       ("c'unloadFileText", "UnloadFileText_", "rl_bindings.h", [t|CString -> IO ()|], False),-       ("c'saveFileText", "SaveFileText_", "rl_bindings.h", [t|CString -> CString -> IO CBool|], True),-       ("c'fileExists", "FileExists_", "rl_bindings.h", [t|CString -> IO CBool|], False),-       ("c'directoryExists", "DirectoryExists_", "rl_bindings.h", [t|CString -> IO CBool|], False),-       ("c'isFileExtension", "IsFileExtension_", "rl_bindings.h", [t|CString -> CString -> IO CBool|], False),-       ("c'getFileLength", "GetFileLength_", "rl_bindings.h", [t|CString -> IO CBool|], False),-       ("c'getFileExtension", "GetFileExtension_", "rl_bindings.h", [t|CString -> IO CString|], False),-       ("c'getFileName", "GetFileName_", "rl_bindings.h", [t|CString -> IO CString|], False),-       ("c'getFileNameWithoutExt", "GetFileNameWithoutExt_", "rl_bindings.h", [t|CString -> IO CString|], False),-       ("c'getDirectoryPath", "GetDirectoryPath_", "rl_bindings.h", [t|CString -> IO CString|], False),-       ("c'getPrevDirectoryPath", "GetPrevDirectoryPath_", "rl_bindings.h", [t|CString -> IO CString|], False),-       ("c'getWorkingDirectory", "GetWorkingDirectory_", "rl_bindings.h", [t|IO CString|], False),-       ("c'getApplicationDirectory", "GetApplicationDirectory_", "rl_bindings.h", [t|IO CString|], False),-       ("c'changeDirectory", "ChangeDirectory_", "rl_bindings.h", [t|CString -> IO CBool|], False),-       ("c'isPathFile", "IsPathFile_", "rl_bindings.h", [t|CString -> IO CBool|], False),-       ("c'isFileNameValid", "IsFileNameValid_", "rl_bindings.h", [t|CString -> IO CBool|], False),-       ("c'loadDirectoryFiles", "LoadDirectoryFiles_", "rl_bindings.h", [t|CString -> IO (Ptr FilePathList)|], False),-       ("c'loadDirectoryFilesEx", "LoadDirectoryFilesEx_", "rl_bindings.h", [t|CString -> CString -> CInt -> IO (Ptr FilePathList)|], False),-       ("c'unloadDirectoryFiles", "UnloadDirectoryFiles_", "rl_bindings.h", [t|Ptr FilePathList -> IO ()|], False),-       ("c'isFileDropped", "IsFileDropped_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'loadDroppedFiles", "LoadDroppedFiles_", "rl_bindings.h", [t|IO (Ptr FilePathList)|], False),-       ("c'unloadDroppedFiles", "UnloadDroppedFiles_", "rl_bindings.h", [t|Ptr FilePathList -> IO ()|], False),-       ("c'getFileModTime", "GetFileModTime_", "rl_bindings.h", [t|CString -> IO CLong|], False),-       ("c'compressData", "CompressData_", "rl_bindings.h", [t|Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr CUChar)|], False),-       ("c'decompressData", "DecompressData_", "rl_bindings.h", [t|Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr CUChar)|], False),-       ("c'encodeDataBase64", "EncodeDataBase64_", "rl_bindings.h", [t|Ptr CUChar -> CInt -> Ptr CInt -> IO CString|], False),-       ("c'decodeDataBase64", "DecodeDataBase64_", "rl_bindings.h", [t|Ptr CUChar -> Ptr CInt -> IO (Ptr CUChar)|], False),-       ("c'loadAutomationEventList", "LoadAutomationEventList_", "rl_bindings.h", [t|CString -> IO (Ptr AutomationEventList)|], False),-       ("c'exportAutomationEventList", "ExportAutomationEventList_", "rl_bindings.h", [t|Ptr AutomationEventList -> CString -> IO CBool|], False),-       ("c'setAutomationEventList", "SetAutomationEventList_", "rl_bindings.h", [t|Ptr AutomationEventList -> IO ()|], False),-       ("c'setAutomationEventBaseFrame", "SetAutomationEventBaseFrame_", "rl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'startAutomationEventRecording", "StartAutomationEventRecording_", "rl_bindings.h", [t|IO ()|], False),-       ("c'stopAutomationEventRecording", "StopAutomationEventRecording_", "rl_bindings.h", [t|IO ()|], False),-       ("c'playAutomationEvent", "PlayAutomationEvent", "rl_bindings.h", [t|Ptr AutomationEvent -> IO ()|], False),-       ("c'isKeyPressed", "IsKeyPressed_", "rl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'isKeyPressedRepeat", "IsKeyPressedRepeat_", "rl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'isKeyDown", "IsKeyDown_", "rl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'isKeyReleased", "IsKeyReleased_", "rl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'isKeyUp", "IsKeyUp_", "rl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'setExitKey", "SetExitKey_", "rl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'getKeyPressed", "GetKeyPressed_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getCharPressed", "GetCharPressed_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'isGamepadAvailable", "IsGamepadAvailable_", "rl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'getGamepadName", "GetGamepadName_", "rl_bindings.h", [t|CInt -> IO CString|], False),-       ("c'isGamepadButtonPressed", "IsGamepadButtonPressed_", "rl_bindings.h", [t|CInt -> CInt -> IO CBool|], False),-       ("c'isGamepadButtonDown", "IsGamepadButtonDown_", "rl_bindings.h", [t|CInt -> CInt -> IO CBool|], False),-       ("c'isGamepadButtonReleased", "IsGamepadButtonReleased_", "rl_bindings.h", [t|CInt -> CInt -> IO CBool|], False),-       ("c'isGamepadButtonUp", "IsGamepadButtonUp_", "rl_bindings.h", [t|CInt -> CInt -> IO CBool|], False),-       ("c'getGamepadButtonPressed", "GetGamepadButtonPressed_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getGamepadAxisCount", "GetGamepadAxisCount_", "rl_bindings.h", [t|CInt -> IO CInt|], False),-       ("c'getGamepadAxisMovement", "GetGamepadAxisMovement_", "rl_bindings.h", [t|CInt -> CInt -> IO CFloat|], False),-       ("c'setGamepadMappings", "SetGamepadMappings_", "rl_bindings.h", [t|CString -> IO CInt|], False),-       ("c'setGamepadVibration", "SetGamepadVibration_", "rl_bindings.h", [t|CInt -> CFloat -> CFloat -> IO ()|], False),-       ("c'isMouseButtonPressed", "IsMouseButtonPressed_", "rl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'isMouseButtonDown", "IsMouseButtonDown_", "rl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'isMouseButtonReleased", "IsMouseButtonReleased_", "rl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'isMouseButtonUp", "IsMouseButtonUp_", "rl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'getMouseX", "GetMouseX_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getMouseY", "GetMouseY_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getMousePosition", "GetMousePosition_", "rl_bindings.h", [t|IO (Ptr Vector2)|], False),-       ("c'getMouseDelta", "GetMouseDelta_", "rl_bindings.h", [t|IO (Ptr Vector2)|], False),-       ("c'setMousePosition", "SetMousePosition_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|], False),-       ("c'setMouseOffset", "SetMouseOffset_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|], False),-       ("c'setMouseScale", "SetMouseScale_", "rl_bindings.h", [t|CFloat -> CFloat -> IO ()|], False),-       ("c'getMouseWheelMove", "GetMouseWheelMove_", "rl_bindings.h", [t|IO CFloat|], False),-       ("c'getMouseWheelMoveV", "GetMouseWheelMoveV_", "rl_bindings.h", [t|IO (Ptr Vector2)|], False),-       ("c'setMouseCursor", "SetMouseCursor_", "rl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'getTouchX", "GetTouchX_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getTouchY", "GetTouchY_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getTouchPosition", "GetTouchPosition_", "rl_bindings.h", [t|CInt -> IO (Ptr Vector2)|], False),-       ("c'getTouchPointId", "GetTouchPointId_", "rl_bindings.h", [t|CInt -> IO CInt|], False),-       ("c'getTouchPointCount", "GetTouchPointCount_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'setGesturesEnabled", "SetGesturesEnabled_", "rl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'isGestureDetected", "IsGestureDetected_", "rl_bindings.h", [t|CUInt -> IO CBool|], False),-       ("c'getGestureDetected", "GetGestureDetected_", "rl_bindings.h", [t|IO CInt|], False),-       ("c'getGestureHoldDuration", "GetGestureHoldDuration_", "rl_bindings.h", [t|IO CFloat|], False),-       ("c'getGestureDragVector", "GetGestureDragVector_", "rl_bindings.h", [t|IO (Ptr Vector2)|], False),-       ("c'getGestureDragAngle", "GetGestureDragAngle_", "rl_bindings.h", [t|IO CFloat|], False),-       ("c'getGesturePinchVector", "GetGesturePinchVector_", "rl_bindings.h", [t|IO (Ptr Vector2)|], False),-       ("c'getGesturePinchAngle", "GetGesturePinchAngle_", "rl_bindings.h", [t|IO CFloat|], False)+     [ ("c'initWindow", "InitWindow_", "rl_bindings.h", [t|CInt -> CInt -> CString -> IO ()|]),+       ("c'windowShouldClose", "WindowShouldClose_", "rl_bindings.h", [t|IO CBool|]),+       ("c'closeWindow", "CloseWindow_", "rl_bindings.h", [t|IO ()|]),+       ("c'isWindowReady", "IsWindowReady_", "rl_bindings.h", [t|IO CBool|]),+       ("c'isWindowFullscreen", "IsWindowFullscreen_", "rl_bindings.h", [t|IO CBool|]),+       ("c'isWindowHidden", "IsWindowHidden_", "rl_bindings.h", [t|IO CBool|]),+       ("c'isWindowMinimized", "IsWindowMinimized_", "rl_bindings.h", [t|IO CBool|]),+       ("c'isWindowMaximized", "IsWindowMaximized_", "rl_bindings.h", [t|IO CBool|]),+       ("c'isWindowFocused", "IsWindowFocused_", "rl_bindings.h", [t|IO CBool|]),+       ("c'isWindowResized", "IsWindowResized_", "rl_bindings.h", [t|IO CBool|]),+       ("c'isWindowState", "IsWindowState_", "rl_bindings.h", [t|CUInt -> IO CBool|]),+       ("c'setWindowState", "SetWindowState_", "rl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'clearWindowState", "ClearWindowState_", "rl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'toggleFullscreen", "ToggleFullscreen_", "rl_bindings.h", [t|IO ()|]),+       ("c'toggleBorderlessWindowed", "ToggleBorderlessWindowed_", "rl_bindings.h", [t|IO ()|]),+       ("c'maximizeWindow", "MaximizeWindow_", "rl_bindings.h", [t|IO ()|]),+       ("c'minimizeWindow", "MinimizeWindow_", "rl_bindings.h", [t|IO ()|]),+       ("c'restoreWindow", "RestoreWindow_", "rl_bindings.h", [t|IO ()|]),+       ("c'setWindowIcon", "SetWindowIcon_", "rl_bindings.h", [t|Ptr Image -> IO ()|]),+       ("c'setWindowIcons", "SetWindowIcons_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|]),+       ("c'setWindowTitle", "SetWindowTitle_", "rl_bindings.h", [t|CString -> IO ()|]),+       ("c'setWindowPosition", "SetWindowPosition_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|]),+       ("c'setWindowMonitor", "SetWindowMonitor_", "rl_bindings.h", [t|CInt -> IO ()|]),+       ("c'setWindowMinSize", "SetWindowMinSize_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|]),+       ("c'setWindowMaxSize", "SetWindowMaxSize_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|]),+       ("c'setWindowSize", "SetWindowSize_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|]),+       ("c'setWindowOpacity", "SetWindowOpacity_", "rl_bindings.h", [t|CFloat -> IO ()|]),+       ("c'setWindowFocused", "SetWindowFocused_", "rl_bindings.h", [t|IO ()|]),+       ("c'getWindowHandle", "GetWindowHandle_", "rl_bindings.h", [t|IO (Ptr ())|]),+       ("c'getScreenWidth", "GetScreenWidth_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getScreenHeight", "GetScreenHeight_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getRenderWidth", "GetRenderWidth_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getRenderHeight", "GetRenderHeight_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getMonitorCount", "GetMonitorCount_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getCurrentMonitor", "GetCurrentMonitor_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getMonitorPosition", "GetMonitorPosition_", "rl_bindings.h", [t|CInt -> IO (Ptr Vector2)|]),+       ("c'getMonitorWidth", "GetMonitorWidth_", "rl_bindings.h", [t|CInt -> IO CInt|]),+       ("c'getMonitorHeight", "GetMonitorHeight_", "rl_bindings.h", [t|CInt -> IO CInt|]),+       ("c'getMonitorPhysicalWidth", "GetMonitorPhysicalWidth_", "rl_bindings.h", [t|CInt -> IO CInt|]),+       ("c'getMonitorPhysicalHeight", "GetMonitorPhysicalHeight_", "rl_bindings.h", [t|CInt -> IO CInt|]),+       ("c'getMonitorRefreshRate", "GetMonitorRefreshRate_", "rl_bindings.h", [t|CInt -> IO CInt|]),+       ("c'getWindowPosition", "GetWindowPosition_", "rl_bindings.h", [t|IO (Ptr Vector2)|]),+       ("c'getWindowScaleDPI", "GetWindowScaleDPI_", "rl_bindings.h", [t|IO (Ptr Vector2)|]),+       ("c'getMonitorName", "GetMonitorName_", "rl_bindings.h", [t|CInt -> IO CString|]),+       ("c'setClipboardText", "SetClipboardText_", "rl_bindings.h", [t|CString -> IO ()|]),+       ("c'getClipboardText", "GetClipboardText_", "rl_bindings.h", [t|IO CString|]),+       ("c'enableEventWaiting", "EnableEventWaiting_", "rl_bindings.h", [t|IO ()|]),+       ("c'disableEventWaiting", "DisableEventWaiting_", "rl_bindings.h", [t|IO ()|]),+       ("c'swapScreenBuffer", "SwapScreenBuffer_", "rl_bindings.h", [t|IO ()|]),+       ("c'pollInputEvents", "PollInputEvents_", "rl_bindings.h", [t|IO ()|]),+       ("c'waitTime", "WaitTime_", "rl_bindings.h", [t|CDouble -> IO ()|]),+       ("c'showCursor", "ShowCursor_", "rl_bindings.h", [t|IO ()|]),+       ("c'hideCursor", "HideCursor_", "rl_bindings.h", [t|IO ()|]),+       ("c'isCursorHidden", "IsCursorHidden_", "rl_bindings.h", [t|IO CBool|]),+       ("c'enableCursor", "EnableCursor_", "rl_bindings.h", [t|IO ()|]),+       ("c'disableCursor", "DisableCursor_", "rl_bindings.h", [t|IO ()|]),+       ("c'isCursorOnScreen", "IsCursorOnScreen_", "rl_bindings.h", [t|IO CBool|]),+       ("c'clearBackground", "ClearBackground_", "rl_bindings.h", [t|Ptr Color -> IO ()|]),+       ("c'beginDrawing", "BeginDrawing_", "rl_bindings.h", [t|IO ()|]),+       ("c'endDrawing", "EndDrawing_", "rl_bindings.h", [t|IO ()|]),+       ("c'beginMode2D", "BeginMode2D_", "rl_bindings.h", [t|Ptr Camera2D -> IO ()|]),+       ("c'endMode2D", "EndMode2D_", "rl_bindings.h", [t|IO ()|]),+       ("c'beginMode3D", "BeginMode3D_", "rl_bindings.h", [t|Ptr Camera3D -> IO ()|]),+       ("c'endMode3D", "EndMode3D_", "rl_bindings.h", [t|IO ()|]),+       ("c'beginTextureMode", "BeginTextureMode_", "rl_bindings.h", [t|Ptr RenderTexture -> IO ()|]),+       ("c'endTextureMode", "EndTextureMode_", "rl_bindings.h", [t|IO ()|]),+       ("c'beginShaderMode", "BeginShaderMode_", "rl_bindings.h", [t|Ptr Shader -> IO ()|]),+       ("c'endShaderMode", "EndShaderMode_", "rl_bindings.h", [t|IO ()|]),+       ("c'beginBlendMode", "BeginBlendMode_", "rl_bindings.h", [t|CInt -> IO ()|]),+       ("c'endBlendMode", "EndBlendMode_", "rl_bindings.h", [t|IO ()|]),+       ("c'beginScissorMode", "BeginScissorMode_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> IO ()|]),+       ("c'endScissorMode", "EndScissorMode_", "rl_bindings.h", [t|IO ()|]),+       ("c'beginVrStereoMode", "BeginVrStereoMode_", "rl_bindings.h", [t|Ptr VrStereoConfig -> IO ()|]),+       ("c'endVrStereoMode", "EndVrStereoMode_", "rl_bindings.h", [t|IO ()|]),+       ("c'loadVrStereoConfig", "LoadVrStereoConfig_", "rl_bindings.h", [t|Ptr VrDeviceInfo -> IO (Ptr VrStereoConfig)|]),+       ("c'unloadVrStereoConfig", "UnloadVrStereoConfig_", "rl_bindings.h", [t|Ptr VrStereoConfig -> IO ()|]),+       ("c'loadShader", "LoadShader_", "rl_bindings.h", [t|CString -> CString -> IO (Ptr Shader)|]),+       ("c'loadShaderFromMemory", "LoadShaderFromMemory_", "rl_bindings.h", [t|CString -> CString -> IO (Ptr Shader)|]),+       ("c'isShaderReady", "IsShaderReady_", "rl_bindings.h", [t|Ptr Shader -> IO CBool|]),+       ("c'getShaderLocation", "GetShaderLocation_", "rl_bindings.h", [t|Ptr Shader -> CString -> IO CInt|]),+       ("c'getShaderLocationAttrib", "GetShaderLocationAttrib_", "rl_bindings.h", [t|Ptr Shader -> CString -> IO CInt|]),+       ("c'setShaderValue", "SetShaderValue_", "rl_bindings.h", [t|Ptr Shader -> CInt -> Ptr () -> CInt -> IO ()|]),+       ("c'setShaderValueV", "SetShaderValueV_", "rl_bindings.h", [t|Ptr Shader -> CInt -> Ptr () -> CInt -> CInt -> IO ()|]),+       ("c'setShaderValueMatrix", "SetShaderValueMatrix_", "rl_bindings.h", [t|Ptr Shader -> CInt -> Ptr Matrix -> IO ()|]),+       ("c'setShaderValueTexture", "SetShaderValueTexture_", "rl_bindings.h", [t|Ptr Shader -> CInt -> Ptr Texture -> IO ()|]),+       ("c'unloadShader", "UnloadShader_", "rl_bindings.h", [t|Ptr Shader -> IO ()|]),+       ("c'getScreenToWorldRay", "GetScreenToWorldRay_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Camera3D -> IO (Ptr Ray)|]),+       ("c'getScreenToWorldRayEx", "GetScreenToWorldRayEx_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Camera3D -> CFloat -> CFloat -> IO (Ptr Ray)|]),+       ("c'getCameraMatrix", "GetCameraMatrix_", "rl_bindings.h", [t|Ptr Camera3D -> IO (Ptr Matrix)|]),+       ("c'getCameraMatrix2D", "GetCameraMatrix2D_", "rl_bindings.h", [t|Ptr Camera2D -> IO (Ptr Matrix)|]),+       ("c'getWorldToScreen", "GetWorldToScreen_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Camera3D -> IO (Ptr Vector2)|]),+       ("c'getScreenToWorld2D", "GetScreenToWorld2D_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Camera2D -> IO (Ptr Vector2)|]),+       ("c'getWorldToScreenEx", "GetWorldToScreenEx_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Camera3D -> CInt -> CInt -> IO (Ptr Vector2)|]),+       ("c'getWorldToScreen2D", "GetWorldToScreen2D_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Camera2D -> IO (Ptr Vector2)|]),+       ("c'setTargetFPS", "SetTargetFPS_", "rl_bindings.h", [t|CInt -> IO ()|]),+       ("c'getFPS", "GetFPS_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getFrameTime", "GetFrameTime_", "rl_bindings.h", [t|IO CFloat|]),+       ("c'getTime", "GetTime_", "rl_bindings.h", [t|IO CDouble|]),+       ("c'setRandomSeed", "SetRandomSeed_", "rl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'getRandomValue", "GetRandomValue_", "rl_bindings.h", [t|CInt -> CInt -> IO CInt|]),+       ("c'loadRandomSequence", "LoadRandomSequence_", "rl_bindings.h", [t|CUInt -> CInt -> CInt -> IO (Ptr CInt)|]),+       ("c'takeScreenshot", "TakeScreenshot_", "rl_bindings.h", [t|CString -> IO ()|]),+       ("c'setConfigFlags", "SetConfigFlags_", "rl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'traceLog", "TraceLog_", "rl_bindings.h", [t|CInt -> CString -> IO ()|]), -- Uses varags, can't implement complete functionality+       ("c'setTraceLogLevel", "SetTraceLogLevel_", "rl_bindings.h", [t|CInt -> IO ()|]),+       ("c'memAlloc", "MemAlloc_", "rl_bindings.h", [t|CInt -> IO (Ptr ())|]),+       ("c'memRealloc", "MemRealloc_", "rl_bindings.h", [t|Ptr () -> CInt -> IO (Ptr ())|]),+       ("c'memFree", "MemFree_", "rl_bindings.h", [t|Ptr () -> IO ()|]),+       ("c'openURL", "OpenURL_", "rl_bindings.h", [t|CString -> IO ()|]),+       ("c'setTraceLogCallback", "SetTraceLogCallback_", "rl_bindings.h", [t|C'TraceLogCallback -> IO ()|]),+       ("c'setLoadFileDataCallback", "SetLoadFileDataCallback_", "rl_bindings.h", [t|C'LoadFileDataCallback -> IO ()|]),+       ("c'setSaveFileDataCallback", "SetSaveFileDataCallback_", "rl_bindings.h", [t|C'SaveFileDataCallback -> IO ()|]),+       ("c'setLoadFileTextCallback", "SetLoadFileTextCallback_", "rl_bindings.h", [t|C'LoadFileTextCallback -> IO ()|]),+       ("c'setSaveFileTextCallback", "SetSaveFileTextCallback_", "rl_bindings.h", [t|C'SaveFileTextCallback -> IO ()|]),+       ("c'loadFileData", "LoadFileData_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO (Ptr CUChar)|]),+       ("c'unloadFileData", "UnloadFileData_", "rl_bindings.h", [t|Ptr CUChar -> IO ()|]),+       ("c'saveFileData", "SaveFileData_", "rl_bindings.h", [t|CString -> Ptr () -> CInt -> IO CBool|]),+       ("c'exportDataAsCode", "ExportDataAsCode_", "rl_bindings.h", [t|Ptr CUChar -> CInt -> CString -> IO CBool|]),+       ("c'loadFileText", "LoadFileText_", "rl_bindings.h", [t|CString -> IO CString|]),+       ("c'unloadFileText", "UnloadFileText_", "rl_bindings.h", [t|CString -> IO ()|]),+       ("c'saveFileText", "SaveFileText_", "rl_bindings.h", [t|CString -> CString -> IO CBool|]),+       ("c'fileExists", "FileExists_", "rl_bindings.h", [t|CString -> IO CBool|]),+       ("c'directoryExists", "DirectoryExists_", "rl_bindings.h", [t|CString -> IO CBool|]),+       ("c'isFileExtension", "IsFileExtension_", "rl_bindings.h", [t|CString -> CString -> IO CBool|]),+       ("c'getFileLength", "GetFileLength_", "rl_bindings.h", [t|CString -> IO CBool|]),+       ("c'getFileExtension", "GetFileExtension_", "rl_bindings.h", [t|CString -> IO CString|]),+       ("c'getFileName", "GetFileName_", "rl_bindings.h", [t|CString -> IO CString|]),+       ("c'getFileNameWithoutExt", "GetFileNameWithoutExt_", "rl_bindings.h", [t|CString -> IO CString|]),+       ("c'getDirectoryPath", "GetDirectoryPath_", "rl_bindings.h", [t|CString -> IO CString|]),+       ("c'getPrevDirectoryPath", "GetPrevDirectoryPath_", "rl_bindings.h", [t|CString -> IO CString|]),+       ("c'getWorkingDirectory", "GetWorkingDirectory_", "rl_bindings.h", [t|IO CString|]),+       ("c'getApplicationDirectory", "GetApplicationDirectory_", "rl_bindings.h", [t|IO CString|]),+       ("c'makeDirectory", "MakeDirectory_", "rl_bindings.h", [t|CString -> IO CInt|]),+       ("c'changeDirectory", "ChangeDirectory_", "rl_bindings.h", [t|CString -> IO CBool|]),+       ("c'isPathFile", "IsPathFile_", "rl_bindings.h", [t|CString -> IO CBool|]),+       ("c'isFileNameValid", "IsFileNameValid_", "rl_bindings.h", [t|CString -> IO CBool|]),+       ("c'loadDirectoryFiles", "LoadDirectoryFiles_", "rl_bindings.h", [t|CString -> IO (Ptr FilePathList)|]),+       ("c'loadDirectoryFilesEx", "LoadDirectoryFilesEx_", "rl_bindings.h", [t|CString -> CString -> CInt -> IO (Ptr FilePathList)|]),+       ("c'unloadDirectoryFiles", "UnloadDirectoryFiles_", "rl_bindings.h", [t|Ptr FilePathList -> IO ()|]),+       ("c'isFileDropped", "IsFileDropped_", "rl_bindings.h", [t|IO CBool|]),+       ("c'loadDroppedFiles", "LoadDroppedFiles_", "rl_bindings.h", [t|IO (Ptr FilePathList)|]),+       ("c'unloadDroppedFiles", "UnloadDroppedFiles_", "rl_bindings.h", [t|Ptr FilePathList -> IO ()|]),+       ("c'getFileModTime", "GetFileModTime_", "rl_bindings.h", [t|CString -> IO CLong|]),+       ("c'compressData", "CompressData_", "rl_bindings.h", [t|Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr CUChar)|]),+       ("c'decompressData", "DecompressData_", "rl_bindings.h", [t|Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr CUChar)|]),+       ("c'encodeDataBase64", "EncodeDataBase64_", "rl_bindings.h", [t|Ptr CUChar -> CInt -> Ptr CInt -> IO CString|]),+       ("c'decodeDataBase64", "DecodeDataBase64_", "rl_bindings.h", [t|Ptr CUChar -> Ptr CInt -> IO (Ptr CUChar)|]),+       ("c'loadAutomationEventList", "LoadAutomationEventList_", "rl_bindings.h", [t|CString -> IO (Ptr AutomationEventList)|]),+       ("c'exportAutomationEventList", "ExportAutomationEventList_", "rl_bindings.h", [t|Ptr AutomationEventList -> CString -> IO CBool|]),+       ("c'setAutomationEventList", "SetAutomationEventList_", "rl_bindings.h", [t|Ptr AutomationEventList -> IO ()|]),+       ("c'setAutomationEventBaseFrame", "SetAutomationEventBaseFrame_", "rl_bindings.h", [t|CInt -> IO ()|]),+       ("c'startAutomationEventRecording", "StartAutomationEventRecording_", "rl_bindings.h", [t|IO ()|]),+       ("c'stopAutomationEventRecording", "StopAutomationEventRecording_", "rl_bindings.h", [t|IO ()|]),+       ("c'playAutomationEvent", "PlayAutomationEvent", "rl_bindings.h", [t|Ptr AutomationEvent -> IO ()|]),+       ("c'isKeyPressed", "IsKeyPressed_", "rl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'isKeyPressedRepeat", "IsKeyPressedRepeat_", "rl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'isKeyDown", "IsKeyDown_", "rl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'isKeyReleased", "IsKeyReleased_", "rl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'isKeyUp", "IsKeyUp_", "rl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'setExitKey", "SetExitKey_", "rl_bindings.h", [t|CInt -> IO ()|]),+       ("c'getKeyPressed", "GetKeyPressed_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getCharPressed", "GetCharPressed_", "rl_bindings.h", [t|IO CInt|]),+       ("c'isGamepadAvailable", "IsGamepadAvailable_", "rl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'getGamepadName", "GetGamepadName_", "rl_bindings.h", [t|CInt -> IO CString|]),+       ("c'isGamepadButtonPressed", "IsGamepadButtonPressed_", "rl_bindings.h", [t|CInt -> CInt -> IO CBool|]),+       ("c'isGamepadButtonDown", "IsGamepadButtonDown_", "rl_bindings.h", [t|CInt -> CInt -> IO CBool|]),+       ("c'isGamepadButtonReleased", "IsGamepadButtonReleased_", "rl_bindings.h", [t|CInt -> CInt -> IO CBool|]),+       ("c'isGamepadButtonUp", "IsGamepadButtonUp_", "rl_bindings.h", [t|CInt -> CInt -> IO CBool|]),+       ("c'getGamepadButtonPressed", "GetGamepadButtonPressed_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getGamepadAxisCount", "GetGamepadAxisCount_", "rl_bindings.h", [t|CInt -> IO CInt|]),+       ("c'getGamepadAxisMovement", "GetGamepadAxisMovement_", "rl_bindings.h", [t|CInt -> CInt -> IO CFloat|]),+       ("c'setGamepadMappings", "SetGamepadMappings_", "rl_bindings.h", [t|CString -> IO CInt|]),+       ("c'setGamepadVibration", "SetGamepadVibration_", "rl_bindings.h", [t|CInt -> CFloat -> CFloat -> IO ()|]),+       ("c'isMouseButtonPressed", "IsMouseButtonPressed_", "rl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'isMouseButtonDown", "IsMouseButtonDown_", "rl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'isMouseButtonReleased", "IsMouseButtonReleased_", "rl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'isMouseButtonUp", "IsMouseButtonUp_", "rl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'getMouseX", "GetMouseX_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getMouseY", "GetMouseY_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getMousePosition", "GetMousePosition_", "rl_bindings.h", [t|IO (Ptr Vector2)|]),+       ("c'getMouseDelta", "GetMouseDelta_", "rl_bindings.h", [t|IO (Ptr Vector2)|]),+       ("c'setMousePosition", "SetMousePosition_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|]),+       ("c'setMouseOffset", "SetMouseOffset_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|]),+       ("c'setMouseScale", "SetMouseScale_", "rl_bindings.h", [t|CFloat -> CFloat -> IO ()|]),+       ("c'getMouseWheelMove", "GetMouseWheelMove_", "rl_bindings.h", [t|IO CFloat|]),+       ("c'getMouseWheelMoveV", "GetMouseWheelMoveV_", "rl_bindings.h", [t|IO (Ptr Vector2)|]),+       ("c'setMouseCursor", "SetMouseCursor_", "rl_bindings.h", [t|CInt -> IO ()|]),+       ("c'getTouchX", "GetTouchX_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getTouchY", "GetTouchY_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getTouchPosition", "GetTouchPosition_", "rl_bindings.h", [t|CInt -> IO (Ptr Vector2)|]),+       ("c'getTouchPointId", "GetTouchPointId_", "rl_bindings.h", [t|CInt -> IO CInt|]),+       ("c'getTouchPointCount", "GetTouchPointCount_", "rl_bindings.h", [t|IO CInt|]),+       ("c'setGesturesEnabled", "SetGesturesEnabled_", "rl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'isGestureDetected", "IsGestureDetected_", "rl_bindings.h", [t|CUInt -> IO CBool|]),+       ("c'getGestureDetected", "GetGestureDetected_", "rl_bindings.h", [t|IO CInt|]),+       ("c'getGestureHoldDuration", "GetGestureHoldDuration_", "rl_bindings.h", [t|IO CFloat|]),+       ("c'getGestureDragVector", "GetGestureDragVector_", "rl_bindings.h", [t|IO (Ptr Vector2)|]),+       ("c'getGestureDragAngle", "GetGestureDragAngle_", "rl_bindings.h", [t|IO CFloat|]),+       ("c'getGesturePinchVector", "GetGesturePinchVector_", "rl_bindings.h", [t|IO (Ptr Vector2)|]),+       ("c'getGesturePinchAngle", "GetGesturePinchAngle_", "rl_bindings.h", [t|IO CFloat|])      ]  ) @@ -1053,29 +1058,30 @@ openURL :: String -> IO () openURL url = withCString url c'openURL -setLoadFileDataCallback :: LoadFileDataCallback -> IO C'LoadFileDataCallback+setTraceLogCallback :: TraceLogCallback -> IO ()+setTraceLogCallback callback = do+  c <- createTraceLogCallback callback+  c'setTraceLogCallback c++setLoadFileDataCallback :: LoadFileDataCallback -> IO () setLoadFileDataCallback callback = do   c <- createLoadFileDataCallback callback   c'setLoadFileDataCallback c-  return c -setSaveFileDataCallback :: (Storable a) => SaveFileDataCallback a -> IO C'SaveFileDataCallback+setSaveFileDataCallback :: (Storable a) => SaveFileDataCallback a -> IO () setSaveFileDataCallback callback = do   c <- createSaveFileDataCallback callback   c'setSaveFileDataCallback c-  return c -setLoadFileTextCallback :: LoadFileTextCallback -> IO C'LoadFileTextCallback+setLoadFileTextCallback :: LoadFileTextCallback -> IO () setLoadFileTextCallback callback = do   c <- createLoadFileTextCallback callback   c'setLoadFileTextCallback c-  return c -setSaveFileTextCallback :: SaveFileTextCallback -> IO C'SaveFileTextCallback+setSaveFileTextCallback :: SaveFileTextCallback -> IO () setSaveFileTextCallback callback = do   c <- createSaveFileTextCallback callback   c'setSaveFileTextCallback c-  return c  loadFileData :: String -> IO [Integer] loadFileData fileName =@@ -1138,6 +1144,9 @@ getApplicationDirectory :: IO String getApplicationDirectory = c'getApplicationDirectory >>= peekCString +makeDirectory :: String -> IO Bool+makeDirectory dirPath = (== 0) <$> withCString dirPath c'makeDirectory+ changeDirectory :: String -> IO Bool changeDirectory dir = toBool <$> withCString dir c'changeDirectory @@ -1401,36 +1410,33 @@ getGesturePinchAngle = realToFrac <$> c'getGesturePinchAngle  foreign import ccall unsafe "wrapper"+  mk'traceLogCallback ::+    (CInt -> CString -> IO ()) -> IO C'TraceLogCallback++foreign import ccall unsafe "wrapper"   mk'loadFileDataCallback ::     (CString -> Ptr CUInt -> IO (Ptr CUChar)) -> IO C'LoadFileDataCallback --- foreign import ccall unsafe "dynamic"---   mK'loadFileDataCallback ::---     C'LoadFileDataCallback -> (CString -> Ptr CUInt -> IO (Ptr CUChar))- foreign import ccall unsafe "wrapper"   mk'saveFileDataCallback ::     (CString -> Ptr () -> CUInt -> IO CInt) -> IO C'SaveFileDataCallback --- foreign import ccall unsafe "dynamic"---   mK'saveFileDataCallback ::---     C'SaveFileDataCallback -> (CString -> Ptr () -> CUInt -> IO CInt)- foreign import ccall unsafe "wrapper"   mk'loadFileTextCallback ::     (CString -> IO CString) -> IO C'LoadFileTextCallback --- foreign import ccall unsafe "dynamic"---   mK'loadFileTextCallback ::---     C'LoadFileTextCallback -> (CString -> IO CString)- foreign import ccall unsafe "wrapper"   mk'saveFileTextCallback ::     (CString -> CString -> IO CInt) -> IO C'SaveFileTextCallback --- foreign import ccall unsafe "dynamic"---   mK'saveFileTextCallback ::---     C'SaveFileTextCallback -> (CString -> CString -> IO CInt)+createTraceLogCallback :: TraceLogCallback -> IO C'TraceLogCallback+createTraceLogCallback callback =+  mk'traceLogCallback+    (\logLevel text ->+        do+          t <- peekCString text+          callback (toEnum (fromIntegral logLevel)) t+    )  createLoadFileDataCallback :: LoadFileDataCallback -> IO C'LoadFileDataCallback createLoadFileDataCallback callback =
src/Raylib/Core/Audio.hs view
@@ -171,72 +171,72 @@   )  $( genNative-     [ ("c'initAudioDevice", "InitAudioDevice_", "rl_bindings.h", [t|IO ()|], False),-       ("c'closeAudioDevice", "CloseAudioDevice_", "rl_bindings.h", [t|IO ()|], False),-       ("c'isAudioDeviceReady", "IsAudioDeviceReady_", "rl_bindings.h", [t|IO CBool|], False),-       ("c'setMasterVolume", "SetMasterVolume_", "rl_bindings.h", [t|CFloat -> IO ()|], False),-       ("c'getMasterVolume", "GetMasterVolume_", "rl_bindings.h", [t|IO CFloat|], False),-       ("c'loadWave", "LoadWave_", "rl_bindings.h", [t|CString -> IO (Ptr Wave)|], False),-       ("c'loadWaveFromMemory", "LoadWaveFromMemory_", "rl_bindings.h", [t|CString -> Ptr CUChar -> CInt -> IO (Ptr Wave)|], False),-       ("c'loadSound", "LoadSound_", "rl_bindings.h", [t|CString -> IO (Ptr Sound)|], False),-       ("c'loadSoundFromWave", "LoadSoundFromWave_", "rl_bindings.h", [t|Ptr Wave -> IO (Ptr Sound)|], False),-       ("c'loadSoundAlias", "LoadSoundAlias_", "rl_bindings.h", [t|Ptr Sound -> IO (Ptr Sound)|], False),-       ("c'updateSound", "UpdateSound_", "rl_bindings.h", [t|Ptr Sound -> Ptr () -> CInt -> IO ()|], False),-       ("c'isWaveReady", "IsWaveReady_", "rl_bindings.h", [t|Ptr Wave -> IO CBool|], False),-       ("c'unloadWave", "UnloadWave_", "rl_bindings.h", [t|Ptr Wave -> IO ()|], False),-       ("c'isSoundReady", "IsSoundReady_", "rl_bindings.h", [t|Ptr Sound -> IO CBool|], False),-       ("c'unloadSound", "UnloadSound_", "rl_bindings.h", [t|Ptr Sound -> IO ()|], False),-       ("c'unloadSoundAlias", "UnloadSoundAlias_", "rl_bindings.h", [t|Ptr Sound -> IO ()|], False),-       ("c'exportWave", "ExportWave_", "rl_bindings.h", [t|Ptr Wave -> CString -> IO CBool|], False),-       ("c'exportWaveAsCode", "ExportWaveAsCode_", "rl_bindings.h", [t|Ptr Wave -> CString -> IO CBool|], False),-       ("c'playSound", "PlaySound_", "rl_bindings.h", [t|Ptr Sound -> IO ()|], False),-       ("c'stopSound", "StopSound_", "rl_bindings.h", [t|Ptr Sound -> IO ()|], False),-       ("c'pauseSound", "PauseSound_", "rl_bindings.h", [t|Ptr Sound -> IO ()|], False),-       ("c'resumeSound", "ResumeSound_", "rl_bindings.h", [t|Ptr Sound -> IO ()|], False),-       ("c'isSoundPlaying", "IsSoundPlaying_", "rl_bindings.h", [t|Ptr Sound -> IO CBool|], False),-       ("c'setSoundVolume", "SetSoundVolume_", "rl_bindings.h", [t|Ptr Sound -> CFloat -> IO ()|], False),-       ("c'setSoundPitch", "SetSoundPitch_", "rl_bindings.h", [t|Ptr Sound -> CFloat -> IO ()|], False),-       ("c'setSoundPan", "SetSoundPan_", "rl_bindings.h", [t|Ptr Sound -> CFloat -> IO ()|], False),-       ("c'waveCopy", "WaveCopy_", "rl_bindings.h", [t|Ptr Wave -> IO (Ptr Wave)|], False),-       ("c'waveCrop", "WaveCrop_", "rl_bindings.h", [t|Ptr Wave -> CInt -> CInt -> IO ()|], False),-       ("c'waveFormat", "WaveFormat_", "rl_bindings.h", [t|Ptr Wave -> CInt -> CInt -> CInt -> IO ()|], False),-       ("c'loadWaveSamples", "LoadWaveSamples_", "rl_bindings.h", [t|Ptr Wave -> IO (Ptr CFloat)|], False),-       ("c'unloadWaveSamples", "UnloadWaveSamples_", "rl_bindings.h", [t|Ptr CFloat -> IO ()|], False),-       ("c'loadMusicStream", "LoadMusicStream_", "rl_bindings.h", [t|CString -> IO (Ptr Music)|], False),-       ("c'loadMusicStreamFromMemory", "LoadMusicStreamFromMemory_", "rl_bindings.h", [t|CString -> Ptr CUChar -> CInt -> IO (Ptr Music)|], False),-       ("c'isMusicReady", "IsMusicReady_", "rl_bindings.h", [t|Ptr Music -> IO CBool|], False),-       ("c'unloadMusicStream", "UnloadMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|], False),-       ("c'playMusicStream", "PlayMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|], False),-       ("c'isMusicStreamPlaying", "IsMusicStreamPlaying_", "rl_bindings.h", [t|Ptr Music -> IO CBool|], False),-       ("c'updateMusicStream", "UpdateMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|], False),-       ("c'stopMusicStream", "StopMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|], False),-       ("c'pauseMusicStream", "PauseMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|], False),-       ("c'resumeMusicStream", "ResumeMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|], False),-       ("c'seekMusicStream", "SeekMusicStream_", "rl_bindings.h", [t|Ptr Music -> CFloat -> IO ()|], False),-       ("c'setMusicVolume", "SetMusicVolume_", "rl_bindings.h", [t|Ptr Music -> CFloat -> IO ()|], False),-       ("c'setMusicPitch", "SetMusicPitch_", "rl_bindings.h", [t|Ptr Music -> CFloat -> IO ()|], False),-       ("c'setMusicPan", "SetMusicPan_", "rl_bindings.h", [t|Ptr Music -> CFloat -> IO ()|], False),-       ("c'getMusicTimeLength", "GetMusicTimeLength_", "rl_bindings.h", [t|Ptr Music -> IO CFloat|], False),-       ("c'getMusicTimePlayed", "GetMusicTimePlayed_", "rl_bindings.h", [t|Ptr Music -> IO CFloat|], False),-       ("c'loadAudioStream", "LoadAudioStream_", "rl_bindings.h", [t|CUInt -> CUInt -> CUInt -> IO (Ptr AudioStream)|], False),-       ("c'isAudioStreamReady", "IsAudioStreamReady_", "rl_bindings.h", [t|Ptr AudioStream -> IO CBool|], False),-       ("c'unloadAudioStream", "UnloadAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> IO ()|], False),-       ("c'updateAudioStream", "UpdateAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> Ptr () -> CInt -> IO ()|], False),-       ("c'isAudioStreamProcessed", "IsAudioStreamProcessed_", "rl_bindings.h", [t|Ptr AudioStream -> IO CBool|], False),-       ("c'playAudioStream", "PlayAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> IO ()|], False),-       ("c'pauseAudioStream", "PauseAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> IO ()|], False),-       ("c'resumeAudioStream", "ResumeAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> IO ()|], False),-       ("c'isAudioStreamPlaying", "IsAudioStreamPlaying_", "rl_bindings.h", [t|Ptr AudioStream -> IO CBool|], False),-       ("c'stopAudioStream", "StopAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> IO ()|], False),-       ("c'setAudioStreamVolume", "SetAudioStreamVolume_", "rl_bindings.h", [t|Ptr AudioStream -> CFloat -> IO ()|], False),-       ("c'setAudioStreamPitch", "SetAudioStreamPitch_", "rl_bindings.h", [t|Ptr AudioStream -> CFloat -> IO ()|], False),-       ("c'setAudioStreamPan", "SetAudioStreamPan_", "rl_bindings.h", [t|Ptr AudioStream -> CFloat -> IO ()|], False),-       ("c'setAudioStreamBufferSizeDefault", "SetAudioStreamBufferSizeDefault_", "rl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'setAudioStreamCallback", "SetAudioStreamCallback_", "rl_bindings.h", [t|Ptr AudioStream -> C'AudioCallback -> IO ()|], False),-       ("c'attachAudioStreamProcessor", "AttachAudioStreamProcessor_", "rl_bindings.h", [t|Ptr AudioStream -> C'AudioCallback -> IO ()|], False),-       ("c'detachAudioStreamProcessor", "DetachAudioStreamProcessor_", "rl_bindings.h", [t|Ptr AudioStream -> C'AudioCallback -> IO ()|], False),-       ("c'attachAudioMixedProcessor", "AttachAudioMixedProcessor_", "rl_bindings.h", [t|C'AudioCallback -> IO ()|], False),-       ("c'detachAudioMixedProcessor", "DetachAudioMixedProcessor_", "rl_bindings.h", [t|C'AudioCallback -> IO ()|], False)+     [ ("c'initAudioDevice", "InitAudioDevice_", "rl_bindings.h", [t|IO ()|]),+       ("c'closeAudioDevice", "CloseAudioDevice_", "rl_bindings.h", [t|IO ()|]),+       ("c'isAudioDeviceReady", "IsAudioDeviceReady_", "rl_bindings.h", [t|IO CBool|]),+       ("c'setMasterVolume", "SetMasterVolume_", "rl_bindings.h", [t|CFloat -> IO ()|]),+       ("c'getMasterVolume", "GetMasterVolume_", "rl_bindings.h", [t|IO CFloat|]),+       ("c'loadWave", "LoadWave_", "rl_bindings.h", [t|CString -> IO (Ptr Wave)|]),+       ("c'loadWaveFromMemory", "LoadWaveFromMemory_", "rl_bindings.h", [t|CString -> Ptr CUChar -> CInt -> IO (Ptr Wave)|]),+       ("c'loadSound", "LoadSound_", "rl_bindings.h", [t|CString -> IO (Ptr Sound)|]),+       ("c'loadSoundFromWave", "LoadSoundFromWave_", "rl_bindings.h", [t|Ptr Wave -> IO (Ptr Sound)|]),+       ("c'loadSoundAlias", "LoadSoundAlias_", "rl_bindings.h", [t|Ptr Sound -> IO (Ptr Sound)|]),+       ("c'updateSound", "UpdateSound_", "rl_bindings.h", [t|Ptr Sound -> Ptr () -> CInt -> IO ()|]),+       ("c'isWaveReady", "IsWaveReady_", "rl_bindings.h", [t|Ptr Wave -> IO CBool|]),+       ("c'unloadWave", "UnloadWave_", "rl_bindings.h", [t|Ptr Wave -> IO ()|]),+       ("c'isSoundReady", "IsSoundReady_", "rl_bindings.h", [t|Ptr Sound -> IO CBool|]),+       ("c'unloadSound", "UnloadSound_", "rl_bindings.h", [t|Ptr Sound -> IO ()|]),+       ("c'unloadSoundAlias", "UnloadSoundAlias_", "rl_bindings.h", [t|Ptr Sound -> IO ()|]),+       ("c'exportWave", "ExportWave_", "rl_bindings.h", [t|Ptr Wave -> CString -> IO CBool|]),+       ("c'exportWaveAsCode", "ExportWaveAsCode_", "rl_bindings.h", [t|Ptr Wave -> CString -> IO CBool|]),+       ("c'playSound", "PlaySound_", "rl_bindings.h", [t|Ptr Sound -> IO ()|]),+       ("c'stopSound", "StopSound_", "rl_bindings.h", [t|Ptr Sound -> IO ()|]),+       ("c'pauseSound", "PauseSound_", "rl_bindings.h", [t|Ptr Sound -> IO ()|]),+       ("c'resumeSound", "ResumeSound_", "rl_bindings.h", [t|Ptr Sound -> IO ()|]),+       ("c'isSoundPlaying", "IsSoundPlaying_", "rl_bindings.h", [t|Ptr Sound -> IO CBool|]),+       ("c'setSoundVolume", "SetSoundVolume_", "rl_bindings.h", [t|Ptr Sound -> CFloat -> IO ()|]),+       ("c'setSoundPitch", "SetSoundPitch_", "rl_bindings.h", [t|Ptr Sound -> CFloat -> IO ()|]),+       ("c'setSoundPan", "SetSoundPan_", "rl_bindings.h", [t|Ptr Sound -> CFloat -> IO ()|]),+       ("c'waveCopy", "WaveCopy_", "rl_bindings.h", [t|Ptr Wave -> IO (Ptr Wave)|]),+       ("c'waveCrop", "WaveCrop_", "rl_bindings.h", [t|Ptr Wave -> CInt -> CInt -> IO ()|]),+       ("c'waveFormat", "WaveFormat_", "rl_bindings.h", [t|Ptr Wave -> CInt -> CInt -> CInt -> IO ()|]),+       ("c'loadWaveSamples", "LoadWaveSamples_", "rl_bindings.h", [t|Ptr Wave -> IO (Ptr CFloat)|]),+       ("c'unloadWaveSamples", "UnloadWaveSamples_", "rl_bindings.h", [t|Ptr CFloat -> IO ()|]),+       ("c'loadMusicStream", "LoadMusicStream_", "rl_bindings.h", [t|CString -> IO (Ptr Music)|]),+       ("c'loadMusicStreamFromMemory", "LoadMusicStreamFromMemory_", "rl_bindings.h", [t|CString -> Ptr CUChar -> CInt -> IO (Ptr Music)|]),+       ("c'isMusicReady", "IsMusicReady_", "rl_bindings.h", [t|Ptr Music -> IO CBool|]),+       ("c'unloadMusicStream", "UnloadMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|]),+       ("c'playMusicStream", "PlayMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|]),+       ("c'isMusicStreamPlaying", "IsMusicStreamPlaying_", "rl_bindings.h", [t|Ptr Music -> IO CBool|]),+       ("c'updateMusicStream", "UpdateMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|]),+       ("c'stopMusicStream", "StopMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|]),+       ("c'pauseMusicStream", "PauseMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|]),+       ("c'resumeMusicStream", "ResumeMusicStream_", "rl_bindings.h", [t|Ptr Music -> IO ()|]),+       ("c'seekMusicStream", "SeekMusicStream_", "rl_bindings.h", [t|Ptr Music -> CFloat -> IO ()|]),+       ("c'setMusicVolume", "SetMusicVolume_", "rl_bindings.h", [t|Ptr Music -> CFloat -> IO ()|]),+       ("c'setMusicPitch", "SetMusicPitch_", "rl_bindings.h", [t|Ptr Music -> CFloat -> IO ()|]),+       ("c'setMusicPan", "SetMusicPan_", "rl_bindings.h", [t|Ptr Music -> CFloat -> IO ()|]),+       ("c'getMusicTimeLength", "GetMusicTimeLength_", "rl_bindings.h", [t|Ptr Music -> IO CFloat|]),+       ("c'getMusicTimePlayed", "GetMusicTimePlayed_", "rl_bindings.h", [t|Ptr Music -> IO CFloat|]),+       ("c'loadAudioStream", "LoadAudioStream_", "rl_bindings.h", [t|CUInt -> CUInt -> CUInt -> IO (Ptr AudioStream)|]),+       ("c'isAudioStreamReady", "IsAudioStreamReady_", "rl_bindings.h", [t|Ptr AudioStream -> IO CBool|]),+       ("c'unloadAudioStream", "UnloadAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> IO ()|]),+       ("c'updateAudioStream", "UpdateAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> Ptr () -> CInt -> IO ()|]),+       ("c'isAudioStreamProcessed", "IsAudioStreamProcessed_", "rl_bindings.h", [t|Ptr AudioStream -> IO CBool|]),+       ("c'playAudioStream", "PlayAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> IO ()|]),+       ("c'pauseAudioStream", "PauseAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> IO ()|]),+       ("c'resumeAudioStream", "ResumeAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> IO ()|]),+       ("c'isAudioStreamPlaying", "IsAudioStreamPlaying_", "rl_bindings.h", [t|Ptr AudioStream -> IO CBool|]),+       ("c'stopAudioStream", "StopAudioStream_", "rl_bindings.h", [t|Ptr AudioStream -> IO ()|]),+       ("c'setAudioStreamVolume", "SetAudioStreamVolume_", "rl_bindings.h", [t|Ptr AudioStream -> CFloat -> IO ()|]),+       ("c'setAudioStreamPitch", "SetAudioStreamPitch_", "rl_bindings.h", [t|Ptr AudioStream -> CFloat -> IO ()|]),+       ("c'setAudioStreamPan", "SetAudioStreamPan_", "rl_bindings.h", [t|Ptr AudioStream -> CFloat -> IO ()|]),+       ("c'setAudioStreamBufferSizeDefault", "SetAudioStreamBufferSizeDefault_", "rl_bindings.h", [t|CInt -> IO ()|]),+       ("c'setAudioStreamCallback", "SetAudioStreamCallback_", "rl_bindings.h", [t|Ptr AudioStream -> C'AudioCallback -> IO ()|]),+       ("c'attachAudioStreamProcessor", "AttachAudioStreamProcessor_", "rl_bindings.h", [t|Ptr AudioStream -> C'AudioCallback -> IO ()|]),+       ("c'detachAudioStreamProcessor", "DetachAudioStreamProcessor_", "rl_bindings.h", [t|Ptr AudioStream -> C'AudioCallback -> IO ()|]),+       ("c'attachAudioMixedProcessor", "AttachAudioMixedProcessor_", "rl_bindings.h", [t|C'AudioCallback -> IO ()|]),+       ("c'detachAudioMixedProcessor", "DetachAudioMixedProcessor_", "rl_bindings.h", [t|C'AudioCallback -> IO ()|])      ]  ) 
src/Raylib/Core/Camera.hs view
@@ -20,8 +20,8 @@ import Raylib.Types (Camera3D, CameraMode, Vector3)  $( genNative-     [ ("c'updateCamera", "UpdateCamera_", "rl_bindings.h", [t|Ptr Camera3D -> CInt -> IO ()|], False),-       ("c'updateCameraPro", "UpdateCameraPro_", "rl_bindings.h", [t|Ptr Camera3D -> Ptr Vector3 -> Ptr Vector3 -> CFloat -> IO ()|], False)+     [ ("c'updateCamera", "UpdateCamera_", "rl_bindings.h", [t|Ptr Camera3D -> CInt -> IO ()|]),+       ("c'updateCameraPro", "UpdateCameraPro_", "rl_bindings.h", [t|Ptr Camera3D -> Ptr Vector3 -> Ptr Vector3 -> CFloat -> IO ()|])      ]  ) 
src/Raylib/Core/Models.hs view
@@ -34,6 +34,8 @@     drawModelEx,     drawModelWires,     drawModelWiresEx,+    drawModelPoints,+    drawModelPointsEx,     drawBoundingBox,     drawBillboard,     drawBillboardRec,@@ -67,6 +69,7 @@     loadModelAnimations,     updateModelAnimation,     isModelAnimationValid,+    updateModelAnimationBoneMatrices,     checkCollisionSpheres,     checkCollisionBoxes,     checkCollisionBoxSphere,@@ -107,6 +110,8 @@     c'drawModelEx,     c'drawModelWires,     c'drawModelWiresEx,+    c'drawModelPoints,+    c'drawModelPointsEx,     c'drawBoundingBox,     c'drawBillboard,     c'drawBillboardRec,@@ -142,6 +147,7 @@     c'unloadModelAnimation,     c'unloadModelAnimations,     c'isModelAnimationValid,+    c'updateModelAnimationBoneMatrices,     c'checkCollisionSpheres,     c'checkCollisionBoxes,     c'checkCollisionBoxSphere,@@ -193,79 +199,82 @@   )  $( genNative-     [ ("c'drawLine3D", "DrawLine3D_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> Ptr Color -> IO ()|], False),-       ("c'drawPoint3D", "DrawPoint3D_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Color -> IO ()|], False),-       ("c'drawCircle3D", "DrawCircle3D_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawTriangle3D", "DrawTriangle3D_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> Ptr Vector3 -> Ptr Color -> IO ()|], False),-       ("c'drawTriangleStrip3D", "DrawTriangleStrip3D_", "rl_bindings.h", [t|Ptr Vector3 -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawCube", "DrawCube_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawCubeV", "DrawCubeV_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> Ptr Color -> IO ()|], False),-       ("c'drawCubeWires", "DrawCubeWires_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawCubeWiresV", "DrawCubeWiresV_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> Ptr Color -> IO ()|], False),-       ("c'drawSphere", "DrawSphere_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSphereEx", "DrawSphereEx_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawSphereWires", "DrawSphereWires_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawCylinder", "DrawCylinder_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawCylinderEx", "DrawCylinderEx_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawCylinderWires", "DrawCylinderWires_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawCylinderWiresEx", "DrawCylinderWiresEx_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawCapsule", "DrawCapsule_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawCapsuleWires", "DrawCapsuleWires_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawPlane", "DrawPlane_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'drawRay", "DrawRay_", "rl_bindings.h", [t|Ptr Ray -> Ptr Color -> IO ()|], False),-       ("c'drawGrid", "DrawGrid_", "rl_bindings.h", [t|CInt -> CFloat -> IO ()|], False),-       ("c'loadModel", "LoadModel_", "rl_bindings.h", [t|CString -> IO (Ptr Model)|], False),-       ("c'loadModelFromMesh", "LoadModelFromMesh_", "rl_bindings.h", [t|Ptr Mesh -> IO (Ptr Model)|], False),-       ("c'isModelReady", "IsModelReady_", "rl_bindings.h", [t|Ptr Model -> IO CBool|], False),-       ("c'unloadModel", "UnloadModel_", "rl_bindings.h", [t|Ptr Model -> IO ()|], False),-       ("c'getModelBoundingBox", "GetModelBoundingBox_", "rl_bindings.h", [t|Ptr Model -> IO (Ptr BoundingBox)|], False),-       ("c'drawModel", "DrawModel_", "rl_bindings.h", [t|Ptr Model -> Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawModelEx", "DrawModelEx_", "rl_bindings.h", [t|Ptr Model -> Ptr Vector3 -> Ptr Vector3 -> CFloat -> Ptr Vector3 -> Ptr Color -> IO ()|], False),-       ("c'drawModelWires", "DrawModelWires_", "rl_bindings.h", [t|Ptr Model -> Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawModelWiresEx", "DrawModelWiresEx_", "rl_bindings.h", [t|Ptr Model -> Ptr Vector3 -> Ptr Vector3 -> CFloat -> Ptr Vector3 -> Ptr Color -> IO ()|], False),-       ("c'drawBoundingBox", "DrawBoundingBox_", "rl_bindings.h", [t|Ptr BoundingBox -> Ptr Color -> IO ()|], False),-       ("c'drawBillboard", "DrawBillboard_", "rl_bindings.h", [t|Ptr Camera3D -> Ptr Texture -> Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawBillboardRec", "DrawBillboardRec_", "rl_bindings.h", [t|Ptr Camera3D -> Ptr Texture -> Ptr Rectangle -> Ptr Vector3 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'drawBillboardPro", "DrawBillboardPro_", "rl_bindings.h", [t|Ptr Camera3D -> Ptr Texture -> Ptr Rectangle -> Ptr Vector3 -> Ptr Vector3 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'uploadMesh", "UploadMesh_", "rl_bindings.h", [t|Ptr Mesh -> CInt -> IO ()|], False),-       ("c'updateMeshBuffer", "UpdateMeshBuffer_", "rl_bindings.h", [t|Ptr Mesh -> CInt -> Ptr () -> CInt -> CInt -> IO ()|], False),-       ("c'unloadMesh", "UnloadMesh_", "rl_bindings.h", [t|Ptr Mesh -> IO ()|], False),-       ("c'drawMesh", "DrawMesh_", "rl_bindings.h", [t|Ptr Mesh -> Ptr Material -> Ptr Matrix -> IO ()|], False),-       ("c'drawMeshInstanced", "DrawMeshInstanced_", "rl_bindings.h", [t|Ptr Mesh -> Ptr Material -> Ptr Matrix -> CInt -> IO ()|], False),-       ("c'exportMesh", "ExportMesh_", "rl_bindings.h", [t|Ptr Mesh -> CString -> IO CBool|], False),-       ("c'exportMeshAsCode", "ExportMeshAsCode_", "rl_bindings.h", [t|Ptr Mesh -> CString -> IO CBool|], False),-       ("c'getMeshBoundingBox", "GetMeshBoundingBox_", "rl_bindings.h", [t|Ptr Mesh -> IO (Ptr BoundingBox)|], False),-       ("c'genMeshTangents", "GenMeshTangents_", "rl_bindings.h", [t|Ptr Mesh -> IO ()|], False),-       ("c'genMeshPoly", "GenMeshPoly_", "rl_bindings.h", [t|CInt -> CFloat -> IO (Ptr Mesh)|], False),-       ("c'genMeshPlane", "GenMeshPlane_", "rl_bindings.h", [t|CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Mesh)|], False),-       ("c'genMeshCube", "GenMeshCube_", "rl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO (Ptr Mesh)|], False),-       ("c'genMeshSphere", "GenMeshSphere_", "rl_bindings.h", [t|CFloat -> CInt -> CInt -> IO (Ptr Mesh)|], False),-       ("c'genMeshHemiSphere", "GenMeshHemiSphere_", "rl_bindings.h", [t|CFloat -> CInt -> CInt -> IO (Ptr Mesh)|], False),-       ("c'genMeshCylinder", "GenMeshCylinder_", "rl_bindings.h", [t|CFloat -> CFloat -> CInt -> IO (Ptr Mesh)|], False),-       ("c'genMeshCone", "GenMeshCone_", "rl_bindings.h", [t|CFloat -> CFloat -> CInt -> IO (Ptr Mesh)|], False),-       ("c'genMeshTorus", "GenMeshTorus_", "rl_bindings.h", [t|CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Mesh)|], False),-       ("c'genMeshKnot", "GenMeshKnot_", "rl_bindings.h", [t|CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Mesh)|], False),-       ("c'genMeshHeightmap", "GenMeshHeightmap_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector3 -> IO (Ptr Mesh)|], False),-       ("c'genMeshCubicmap", "GenMeshCubicmap_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector3 -> IO (Ptr Mesh)|], False),-       ("c'loadMaterials", "LoadMaterials_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO (Ptr Material)|], False),-       ("c'loadMaterialDefault", "LoadMaterialDefault_", "rl_bindings.h", [t|IO (Ptr Material)|], False),-       ("c'isMaterialReady", "IsMaterialReady_", "rl_bindings.h", [t|Ptr Material -> IO CBool|], False),-       ("c'unloadMaterial", "UnloadMaterial_", "rl_bindings.h", [t|Ptr Material -> IO ()|], False),-       ("c'setMaterialTexture", "SetMaterialTexture_", "rl_bindings.h", [t|Ptr Material -> CInt -> Ptr Texture -> IO ()|], False),-       ("c'setModelMeshMaterial", "SetModelMeshMaterial_", "rl_bindings.h", [t|Ptr Model -> CInt -> CInt -> IO ()|], False),-       ("c'loadModelAnimations", "LoadModelAnimations_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO (Ptr ModelAnimation)|], False),-       ("c'updateModelAnimation", "UpdateModelAnimation_", "rl_bindings.h", [t|Ptr Model -> Ptr ModelAnimation -> CInt -> IO ()|], False),-       ("c'unloadModelAnimation", "UnloadModelAnimation_", "rl_bindings.h", [t|Ptr ModelAnimation -> IO ()|], False),-       ("c'unloadModelAnimations", "UnloadModelAnimations_", "rl_bindings.h", [t|Ptr ModelAnimation -> CInt -> IO ()|], False),-       ("c'isModelAnimationValid", "IsModelAnimationValid_", "rl_bindings.h", [t|Ptr Model -> Ptr ModelAnimation -> IO CBool|], False),-       ("c'checkCollisionSpheres", "CheckCollisionSpheres_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> Ptr Vector3 -> CFloat -> IO CBool|], False),-       ("c'checkCollisionBoxes", "CheckCollisionBoxes_", "rl_bindings.h", [t|Ptr BoundingBox -> Ptr BoundingBox -> IO CBool|], False),-       ("c'checkCollisionBoxSphere", "CheckCollisionBoxSphere_", "rl_bindings.h", [t|Ptr BoundingBox -> Ptr Vector3 -> CFloat -> IO CBool|], False),-       ("c'getRayCollisionSphere", "GetRayCollisionSphere_", "rl_bindings.h", [t|Ptr Ray -> Ptr Vector3 -> CFloat -> IO (Ptr RayCollision)|], False),-       ("c'getRayCollisionBox", "GetRayCollisionBox_", "rl_bindings.h", [t|Ptr Ray -> Ptr BoundingBox -> IO (Ptr RayCollision)|], False),-       ("c'getRayCollisionMesh", "GetRayCollisionMesh_", "rl_bindings.h", [t|Ptr Ray -> Ptr Mesh -> Ptr Matrix -> IO (Ptr RayCollision)|], False),-       ("c'getRayCollisionTriangle", "GetRayCollisionTriangle_", "rl_bindings.h", [t|Ptr Ray -> Ptr Vector3 -> Ptr Vector3 -> Ptr Vector3 -> IO (Ptr RayCollision)|], False),-       ("c'getRayCollisionQuad", "GetRayCollisionQuad_", "rl_bindings.h", [t|Ptr Ray -> Ptr Vector3 -> Ptr Vector3 -> Ptr Vector3 -> Ptr Vector3 -> IO (Ptr RayCollision)|], False)+     [ ("c'drawLine3D", "DrawLine3D_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> Ptr Color -> IO ()|]),+       ("c'drawPoint3D", "DrawPoint3D_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Color -> IO ()|]),+       ("c'drawCircle3D", "DrawCircle3D_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawTriangle3D", "DrawTriangle3D_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> Ptr Vector3 -> Ptr Color -> IO ()|]),+       ("c'drawTriangleStrip3D", "DrawTriangleStrip3D_", "rl_bindings.h", [t|Ptr Vector3 -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawCube", "DrawCube_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawCubeV", "DrawCubeV_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> Ptr Color -> IO ()|]),+       ("c'drawCubeWires", "DrawCubeWires_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawCubeWiresV", "DrawCubeWiresV_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> Ptr Color -> IO ()|]),+       ("c'drawSphere", "DrawSphere_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSphereEx", "DrawSphereEx_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawSphereWires", "DrawSphereWires_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawCylinder", "DrawCylinder_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawCylinderEx", "DrawCylinderEx_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawCylinderWires", "DrawCylinderWires_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawCylinderWiresEx", "DrawCylinderWiresEx_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawCapsule", "DrawCapsule_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawCapsuleWires", "DrawCapsuleWires_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawPlane", "DrawPlane_", "rl_bindings.h", [t|Ptr Vector3 -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'drawRay", "DrawRay_", "rl_bindings.h", [t|Ptr Ray -> Ptr Color -> IO ()|]),+       ("c'drawGrid", "DrawGrid_", "rl_bindings.h", [t|CInt -> CFloat -> IO ()|]),+       ("c'loadModel", "LoadModel_", "rl_bindings.h", [t|CString -> IO (Ptr Model)|]),+       ("c'loadModelFromMesh", "LoadModelFromMesh_", "rl_bindings.h", [t|Ptr Mesh -> IO (Ptr Model)|]),+       ("c'isModelReady", "IsModelReady_", "rl_bindings.h", [t|Ptr Model -> IO CBool|]),+       ("c'unloadModel", "UnloadModel_", "rl_bindings.h", [t|Ptr Model -> IO ()|]),+       ("c'getModelBoundingBox", "GetModelBoundingBox_", "rl_bindings.h", [t|Ptr Model -> IO (Ptr BoundingBox)|]),+       ("c'drawModel", "DrawModel_", "rl_bindings.h", [t|Ptr Model -> Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawModelEx", "DrawModelEx_", "rl_bindings.h", [t|Ptr Model -> Ptr Vector3 -> Ptr Vector3 -> CFloat -> Ptr Vector3 -> Ptr Color -> IO ()|]),+       ("c'drawModelWires", "DrawModelWires_", "rl_bindings.h", [t|Ptr Model -> Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawModelWiresEx", "DrawModelWiresEx_", "rl_bindings.h", [t|Ptr Model -> Ptr Vector3 -> Ptr Vector3 -> CFloat -> Ptr Vector3 -> Ptr Color -> IO ()|]),+       ("c'drawModelPoints", "DrawModelPoints_", "rl_bindings.h", [t|Ptr Model -> Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawModelPointsEx", "DrawModelPointsEx_", "rl_bindings.h", [t|Ptr Model -> Ptr Vector3 -> Ptr Vector3 -> CFloat -> Ptr Vector3 -> Ptr Color -> IO ()|]),+       ("c'drawBoundingBox", "DrawBoundingBox_", "rl_bindings.h", [t|Ptr BoundingBox -> Ptr Color -> IO ()|]),+       ("c'drawBillboard", "DrawBillboard_", "rl_bindings.h", [t|Ptr Camera3D -> Ptr Texture -> Ptr Vector3 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawBillboardRec", "DrawBillboardRec_", "rl_bindings.h", [t|Ptr Camera3D -> Ptr Texture -> Ptr Rectangle -> Ptr Vector3 -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'drawBillboardPro", "DrawBillboardPro_", "rl_bindings.h", [t|Ptr Camera3D -> Ptr Texture -> Ptr Rectangle -> Ptr Vector3 -> Ptr Vector3 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'uploadMesh", "UploadMesh_", "rl_bindings.h", [t|Ptr Mesh -> CInt -> IO ()|]),+       ("c'updateMeshBuffer", "UpdateMeshBuffer_", "rl_bindings.h", [t|Ptr Mesh -> CInt -> Ptr () -> CInt -> CInt -> IO ()|]),+       ("c'unloadMesh", "UnloadMesh_", "rl_bindings.h", [t|Ptr Mesh -> IO ()|]),+       ("c'drawMesh", "DrawMesh_", "rl_bindings.h", [t|Ptr Mesh -> Ptr Material -> Ptr Matrix -> IO ()|]),+       ("c'drawMeshInstanced", "DrawMeshInstanced_", "rl_bindings.h", [t|Ptr Mesh -> Ptr Material -> Ptr Matrix -> CInt -> IO ()|]),+       ("c'exportMesh", "ExportMesh_", "rl_bindings.h", [t|Ptr Mesh -> CString -> IO CBool|]),+       ("c'exportMeshAsCode", "ExportMeshAsCode_", "rl_bindings.h", [t|Ptr Mesh -> CString -> IO CBool|]),+       ("c'getMeshBoundingBox", "GetMeshBoundingBox_", "rl_bindings.h", [t|Ptr Mesh -> IO (Ptr BoundingBox)|]),+       ("c'genMeshTangents", "GenMeshTangents_", "rl_bindings.h", [t|Ptr Mesh -> IO ()|]),+       ("c'genMeshPoly", "GenMeshPoly_", "rl_bindings.h", [t|CInt -> CFloat -> IO (Ptr Mesh)|]),+       ("c'genMeshPlane", "GenMeshPlane_", "rl_bindings.h", [t|CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Mesh)|]),+       ("c'genMeshCube", "GenMeshCube_", "rl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO (Ptr Mesh)|]),+       ("c'genMeshSphere", "GenMeshSphere_", "rl_bindings.h", [t|CFloat -> CInt -> CInt -> IO (Ptr Mesh)|]),+       ("c'genMeshHemiSphere", "GenMeshHemiSphere_", "rl_bindings.h", [t|CFloat -> CInt -> CInt -> IO (Ptr Mesh)|]),+       ("c'genMeshCylinder", "GenMeshCylinder_", "rl_bindings.h", [t|CFloat -> CFloat -> CInt -> IO (Ptr Mesh)|]),+       ("c'genMeshCone", "GenMeshCone_", "rl_bindings.h", [t|CFloat -> CFloat -> CInt -> IO (Ptr Mesh)|]),+       ("c'genMeshTorus", "GenMeshTorus_", "rl_bindings.h", [t|CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Mesh)|]),+       ("c'genMeshKnot", "GenMeshKnot_", "rl_bindings.h", [t|CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Mesh)|]),+       ("c'genMeshHeightmap", "GenMeshHeightmap_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector3 -> IO (Ptr Mesh)|]),+       ("c'genMeshCubicmap", "GenMeshCubicmap_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector3 -> IO (Ptr Mesh)|]),+       ("c'loadMaterials", "LoadMaterials_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO (Ptr Material)|]),+       ("c'loadMaterialDefault", "LoadMaterialDefault_", "rl_bindings.h", [t|IO (Ptr Material)|]),+       ("c'isMaterialReady", "IsMaterialReady_", "rl_bindings.h", [t|Ptr Material -> IO CBool|]),+       ("c'unloadMaterial", "UnloadMaterial_", "rl_bindings.h", [t|Ptr Material -> IO ()|]),+       ("c'setMaterialTexture", "SetMaterialTexture_", "rl_bindings.h", [t|Ptr Material -> CInt -> Ptr Texture -> IO ()|]),+       ("c'setModelMeshMaterial", "SetModelMeshMaterial_", "rl_bindings.h", [t|Ptr Model -> CInt -> CInt -> IO ()|]),+       ("c'loadModelAnimations", "LoadModelAnimations_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO (Ptr ModelAnimation)|]),+       ("c'updateModelAnimation", "UpdateModelAnimation_", "rl_bindings.h", [t|Ptr Model -> Ptr ModelAnimation -> CInt -> IO ()|]),+       ("c'unloadModelAnimation", "UnloadModelAnimation_", "rl_bindings.h", [t|Ptr ModelAnimation -> IO ()|]),+       ("c'unloadModelAnimations", "UnloadModelAnimations_", "rl_bindings.h", [t|Ptr ModelAnimation -> CInt -> IO ()|]),+       ("c'isModelAnimationValid", "IsModelAnimationValid_", "rl_bindings.h", [t|Ptr Model -> Ptr ModelAnimation -> IO CBool|]),+       ("c'updateModelAnimationBoneMatrices", "UpdateModelAnimationBoneMatrices_", "rl_bindings.h", [t|Ptr Model -> Ptr ModelAnimation -> CInt -> IO ()|]),+       ("c'checkCollisionSpheres", "CheckCollisionSpheres_", "rl_bindings.h", [t|Ptr Vector3 -> CFloat -> Ptr Vector3 -> CFloat -> IO CBool|]),+       ("c'checkCollisionBoxes", "CheckCollisionBoxes_", "rl_bindings.h", [t|Ptr BoundingBox -> Ptr BoundingBox -> IO CBool|]),+       ("c'checkCollisionBoxSphere", "CheckCollisionBoxSphere_", "rl_bindings.h", [t|Ptr BoundingBox -> Ptr Vector3 -> CFloat -> IO CBool|]),+       ("c'getRayCollisionSphere", "GetRayCollisionSphere_", "rl_bindings.h", [t|Ptr Ray -> Ptr Vector3 -> CFloat -> IO (Ptr RayCollision)|]),+       ("c'getRayCollisionBox", "GetRayCollisionBox_", "rl_bindings.h", [t|Ptr Ray -> Ptr BoundingBox -> IO (Ptr RayCollision)|]),+       ("c'getRayCollisionMesh", "GetRayCollisionMesh_", "rl_bindings.h", [t|Ptr Ray -> Ptr Mesh -> Ptr Matrix -> IO (Ptr RayCollision)|]),+       ("c'getRayCollisionTriangle", "GetRayCollisionTriangle_", "rl_bindings.h", [t|Ptr Ray -> Ptr Vector3 -> Ptr Vector3 -> Ptr Vector3 -> IO (Ptr RayCollision)|]),+       ("c'getRayCollisionQuad", "GetRayCollisionQuad_", "rl_bindings.h", [t|Ptr Ray -> Ptr Vector3 -> Ptr Vector3 -> Ptr Vector3 -> Ptr Vector3 -> IO (Ptr RayCollision)|])      ]  ) @@ -369,6 +378,12 @@ drawModelWiresEx :: Model -> Vector3 -> Vector3 -> Float -> Vector3 -> Color -> IO () drawModelWiresEx model position rotationAxis rotationAngle scale tint = withFreeable model (\m -> withFreeable position (\p -> withFreeable rotationAxis (\r -> withFreeable scale (withFreeable tint . c'drawModelWiresEx m p r (realToFrac rotationAngle))))) +drawModelPoints :: Model -> Vector3 -> Float -> Color -> IO ()+drawModelPoints model position scale tint = withFreeable model (\m -> withFreeable position (\p -> withFreeable tint (c'drawModelPoints m p (realToFrac scale))))++drawModelPointsEx :: Model -> Vector3 -> Vector3 -> Float -> Vector3 -> Color -> IO ()+drawModelPointsEx model position rotationAxis rotationAngle scale tint = withFreeable model (\m -> withFreeable position (\p -> withFreeable rotationAxis (\r -> withFreeable scale (withFreeable tint . c'drawModelPointsEx m p r (realToFrac rotationAngle)))))+ drawBoundingBox :: BoundingBox -> Color -> IO () drawBoundingBox box color = withFreeable box (withFreeable color . c'drawBoundingBox) @@ -498,6 +513,9 @@  isModelAnimationValid :: Model -> ModelAnimation -> IO Bool isModelAnimationValid model animation = toBool <$> withFreeable model (withFreeable animation . c'isModelAnimationValid)++updateModelAnimationBoneMatrices :: Model -> ModelAnimation -> Int -> IO ()+updateModelAnimationBoneMatrices model animation frame = withFreeable model (\m -> withFreeable animation (\a -> c'updateModelAnimationBoneMatrices m a (fromIntegral frame)))  checkCollisionSpheres :: Vector3 -> Float -> Vector3 -> Float -> Bool checkCollisionSpheres center1 radius1 center2 radius2 = toBool $ unsafePerformIO (withFreeable center1 (\c1 -> withFreeable center2 (\c2 -> c'checkCollisionSpheres c1 (realToFrac radius1) c2 (realToFrac radius2))))
src/Raylib/Core/Shapes.hs view
@@ -154,72 +154,72 @@ import Raylib.Types (Color, Rectangle, Texture, Vector2, pattern Vector2)  $( genNative-     [ ("c'setShapesTexture", "SetShapesTexture_", "rl_bindings.h", [t|Ptr Texture -> Ptr Rectangle -> IO ()|], False),-       ("c'getShapesTexture", "GetShapesTexture_", "rl_bindings.h", [t|IO (Ptr Texture)|], False),-       ("c'getShapesTextureRectangle", "GetShapesTextureRectangle_", "rl_bindings.h", [t|IO (Ptr Rectangle)|], False),-       ("c'drawPixel", "DrawPixel_", "rl_bindings.h", [t|CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawPixelV", "DrawPixelV_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'drawLine", "DrawLine_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawLineV", "DrawLineV_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'drawLineEx", "DrawLineEx_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawLineStrip", "DrawLineStrip_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawLineBezier", "DrawLineBezier_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawCircle", "DrawCircle_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawCircleSector", "DrawCircleSector_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawCircleSectorLines", "DrawCircleSectorLines_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawCircleGradient", "DrawCircleGradient_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> Ptr Color -> Ptr Color -> IO ()|], False),-       ("c'drawCircleV", "DrawCircleV_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawCircleLines", "DrawCircleLines_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawCircleLinesV", "DrawCircleLinesV_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawEllipse", "DrawEllipse_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawEllipseLines", "DrawEllipseLines_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawRing", "DrawRing_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawRingLines", "DrawRingLines_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawRectangle", "DrawRectangle_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawRectangleV", "DrawRectangleV_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'drawRectangleRec", "DrawRectangleRec_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Color -> IO ()|], False),-       ("c'drawRectanglePro", "DrawRectanglePro_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawRectangleGradientV", "DrawRectangleGradientV_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> Ptr Color -> IO ()|], False),-       ("c'drawRectangleGradientH", "DrawRectangleGradientH_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> Ptr Color -> IO ()|], False),-       ("c'drawRectangleGradientEx", "DrawRectangleGradientEx_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Color -> Ptr Color -> Ptr Color -> Ptr Color -> IO ()|], False),-       ("c'drawRectangleLines", "DrawRectangleLines_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawRectangleLinesEx", "DrawRectangleLinesEx_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawRectangleRounded", "DrawRectangleRounded_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawRectangleRoundedLines", "DrawRectangleRoundedLines_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawRectangleRoundedLinesEx", "DrawRectangleRoundedLinesEx_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> CInt -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawTriangle", "DrawTriangle_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'drawTriangleLines", "DrawTriangleLines_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'drawTriangleFan", "DrawTriangleFan_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawTriangleStrip", "DrawTriangleStrip_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawPoly", "DrawPoly_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawPolyLines", "DrawPolyLines_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawPolyLinesEx", "DrawPolyLinesEx_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSplineLinear", "DrawSplineLinear_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSplineBasis", "DrawSplineBasis_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSplineCatmullRom", "DrawSplineCatmullRom_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSplineBezierQuadratic", "DrawSplineBezierQuadratic_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSplineBezierCubic", "DrawSplineBezierCubic_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSplineSegmentLinear", "DrawSplineSegmentLinear_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSplineSegmentBasis", "DrawSplineSegmentBasis_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSplineSegmentCatmullRom", "DrawSplineSegmentCatmullRom_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSplineSegmentBezierQuadratic", "DrawSplineSegmentBezierQuadratic_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawSplineSegmentBezierCubic", "DrawSplineSegmentBezierCubic_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'getSplinePointLinear", "GetSplinePointLinear_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO (Ptr Vector2)|], False),-       ("c'getSplinePointBasis", "GetSplinePointBasis_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO (Ptr Vector2)|], False),-       ("c'getSplinePointCatmullRom", "GetSplinePointCatmullRom_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO (Ptr Vector2)|], False),-       ("c'getSplinePointBezierQuad", "GetSplinePointBezierQuad_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO (Ptr Vector2)|], False),-       ("c'getSplinePointBezierCubic", "GetSplinePointBezierCubic_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO (Ptr Vector2)|], False),-       ("c'checkCollisionRecs", "CheckCollisionRecs_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Rectangle -> IO CBool|], False),-       ("c'checkCollisionCircles", "CheckCollisionCircles_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Vector2 -> CFloat -> IO CBool|], False),-       ("c'checkCollisionCircleRec", "CheckCollisionCircleRec_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Rectangle -> IO CBool|], False),-       ("c'checkCollisionPointRec", "CheckCollisionPointRec_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Rectangle -> IO CBool|], False),-       ("c'checkCollisionPointCircle", "CheckCollisionPointCircle_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO CBool|], False),-       ("c'checkCollisionPointTriangle", "CheckCollisionPointTriangle_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> IO CBool|], False),-       ("c'checkCollisionPointPoly", "CheckCollisionPointPoly_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CInt -> IO CBool|], False),-       ("c'checkCollisionLines", "CheckCollisionLines_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> IO CBool|], False),-       ("c'checkCollisionPointLine", "CheckCollisionPointLine_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CInt -> IO CBool|], False),-       ("c'checkCollisionCircleLine", "CheckCollisionCircleLine_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Vector2 -> Ptr Vector2 -> IO CBool|], False),-       ("c'getCollisionRec", "GetCollisionRec_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Rectangle -> IO (Ptr Rectangle)|], False)+     [ ("c'setShapesTexture", "SetShapesTexture_", "rl_bindings.h", [t|Ptr Texture -> Ptr Rectangle -> IO ()|]),+       ("c'getShapesTexture", "GetShapesTexture_", "rl_bindings.h", [t|IO (Ptr Texture)|]),+       ("c'getShapesTextureRectangle", "GetShapesTextureRectangle_", "rl_bindings.h", [t|IO (Ptr Rectangle)|]),+       ("c'drawPixel", "DrawPixel_", "rl_bindings.h", [t|CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawPixelV", "DrawPixelV_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'drawLine", "DrawLine_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawLineV", "DrawLineV_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'drawLineEx", "DrawLineEx_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawLineStrip", "DrawLineStrip_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawLineBezier", "DrawLineBezier_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawCircle", "DrawCircle_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawCircleSector", "DrawCircleSector_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawCircleSectorLines", "DrawCircleSectorLines_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawCircleGradient", "DrawCircleGradient_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> Ptr Color -> Ptr Color -> IO ()|]),+       ("c'drawCircleV", "DrawCircleV_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawCircleLines", "DrawCircleLines_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawCircleLinesV", "DrawCircleLinesV_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawEllipse", "DrawEllipse_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawEllipseLines", "DrawEllipseLines_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawRing", "DrawRing_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawRingLines", "DrawRingLines_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawRectangle", "DrawRectangle_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawRectangleV", "DrawRectangleV_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'drawRectangleRec", "DrawRectangleRec_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Color -> IO ()|]),+       ("c'drawRectanglePro", "DrawRectanglePro_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawRectangleGradientV", "DrawRectangleGradientV_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> Ptr Color -> IO ()|]),+       ("c'drawRectangleGradientH", "DrawRectangleGradientH_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> Ptr Color -> IO ()|]),+       ("c'drawRectangleGradientEx", "DrawRectangleGradientEx_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Color -> Ptr Color -> Ptr Color -> Ptr Color -> IO ()|]),+       ("c'drawRectangleLines", "DrawRectangleLines_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawRectangleLinesEx", "DrawRectangleLinesEx_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawRectangleRounded", "DrawRectangleRounded_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawRectangleRoundedLines", "DrawRectangleRoundedLines_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawRectangleRoundedLinesEx", "DrawRectangleRoundedLinesEx_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> CInt -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawTriangle", "DrawTriangle_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'drawTriangleLines", "DrawTriangleLines_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'drawTriangleFan", "DrawTriangleFan_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawTriangleStrip", "DrawTriangleStrip_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawPoly", "DrawPoly_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawPolyLines", "DrawPolyLines_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawPolyLinesEx", "DrawPolyLinesEx_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSplineLinear", "DrawSplineLinear_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSplineBasis", "DrawSplineBasis_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSplineCatmullRom", "DrawSplineCatmullRom_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSplineBezierQuadratic", "DrawSplineBezierQuadratic_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSplineBezierCubic", "DrawSplineBezierCubic_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSplineSegmentLinear", "DrawSplineSegmentLinear_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSplineSegmentBasis", "DrawSplineSegmentBasis_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSplineSegmentCatmullRom", "DrawSplineSegmentCatmullRom_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSplineSegmentBezierQuadratic", "DrawSplineSegmentBezierQuadratic_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawSplineSegmentBezierCubic", "DrawSplineSegmentBezierCubic_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'getSplinePointLinear", "GetSplinePointLinear_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO (Ptr Vector2)|]),+       ("c'getSplinePointBasis", "GetSplinePointBasis_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO (Ptr Vector2)|]),+       ("c'getSplinePointCatmullRom", "GetSplinePointCatmullRom_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO (Ptr Vector2)|]),+       ("c'getSplinePointBezierQuad", "GetSplinePointBezierQuad_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO (Ptr Vector2)|]),+       ("c'getSplinePointBezierCubic", "GetSplinePointBezierCubic_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO (Ptr Vector2)|]),+       ("c'checkCollisionRecs", "CheckCollisionRecs_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Rectangle -> IO CBool|]),+       ("c'checkCollisionCircles", "CheckCollisionCircles_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Vector2 -> CFloat -> IO CBool|]),+       ("c'checkCollisionCircleRec", "CheckCollisionCircleRec_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Rectangle -> IO CBool|]),+       ("c'checkCollisionPointRec", "CheckCollisionPointRec_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Rectangle -> IO CBool|]),+       ("c'checkCollisionPointCircle", "CheckCollisionPointCircle_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CFloat -> IO CBool|]),+       ("c'checkCollisionPointTriangle", "CheckCollisionPointTriangle_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> IO CBool|]),+       ("c'checkCollisionPointPoly", "CheckCollisionPointPoly_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CInt -> IO CBool|]),+       ("c'checkCollisionLines", "CheckCollisionLines_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> IO CBool|]),+       ("c'checkCollisionPointLine", "CheckCollisionPointLine_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CInt -> IO CBool|]),+       ("c'checkCollisionCircleLine", "CheckCollisionCircleLine_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Vector2 -> Ptr Vector2 -> IO CBool|]),+       ("c'getCollisionRec", "GetCollisionRec_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Rectangle -> IO (Ptr Rectangle)|])      ]  ) @@ -282,8 +282,8 @@     )  drawCircleGradient :: Int -> Int -> Float -> Color -> Color -> IO ()-drawCircleGradient centerX centerY radius color1 color2 =-  withFreeable color1 (withFreeable color2 . c'drawCircleGradient (fromIntegral centerX) (fromIntegral centerY) (realToFrac radius))+drawCircleGradient centerX centerY radius inner outer =+  withFreeable inner (withFreeable outer . c'drawCircleGradient (fromIntegral centerX) (fromIntegral centerY) (realToFrac radius))  drawCircleV :: Vector2 -> Float -> Color -> IO () drawCircleV center radius color =@@ -354,10 +354,10 @@   withFreeable color (\c -> withFreeable rect (\r -> withFreeable origin (\o -> c'drawRectanglePro r o (realToFrac rotation) c)))  drawRectangleGradientV :: Int -> Int -> Int -> Int -> Color -> Color -> IO ()-drawRectangleGradientV posX posY width height color1 color2 =+drawRectangleGradientV posX posY width height top bottom =   withFreeable-    color1-    ( withFreeable color2+    top+    ( withFreeable bottom         . c'drawRectangleGradientV           (fromIntegral posX)           (fromIntegral posY)@@ -366,10 +366,10 @@     )  drawRectangleGradientH :: Int -> Int -> Int -> Int -> Color -> Color -> IO ()-drawRectangleGradientH posX posY width height color1 color2 =+drawRectangleGradientH posX posY width height left right =   withFreeable-    color1-    ( withFreeable color2+    left+    ( withFreeable right         . c'drawRectangleGradientH           (fromIntegral posX)           (fromIntegral posY)@@ -378,17 +378,17 @@     )  drawRectangleGradientEx :: Rectangle -> Color -> Color -> Color -> Color -> IO ()-drawRectangleGradientEx rect col1 col2 col3 col4 =+drawRectangleGradientEx rect topLeft bottomLeft topRight bottomRight =   withFreeable     rect     ( \r ->         withFreeable-          col1+          topLeft           ( \c1 ->               withFreeable-                col2+                bottomLeft                 ( \c2 ->-                    withFreeable col3 (withFreeable col4 . c'drawRectangleGradientEx r c1 c2)+                    withFreeable topRight (withFreeable bottomRight . c'drawRectangleGradientEx r c1 c2)                 )           )     )
src/Raylib/Core/Text.hs view
@@ -98,35 +98,35 @@   )  $( genNative-     [ ("c'getFontDefault", "GetFontDefault_", "rl_bindings.h", [t|IO (Ptr Font)|], False),-       ("c'loadFont", "LoadFont_", "rl_bindings.h", [t|CString -> IO (Ptr Font)|], False),-       ("c'loadFontEx", "LoadFontEx_", "rl_bindings.h", [t|CString -> CInt -> Ptr CInt -> CInt -> IO (Ptr Font)|], False),-       ("c'loadFontFromImage", "LoadFontFromImage_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> CInt -> IO (Ptr Font)|], False),-       ("c'loadFontFromMemory", "LoadFontFromMemory_", "rl_bindings.h", [t|CString -> Ptr CUChar -> CInt -> CInt -> Ptr CInt -> CInt -> IO (Ptr Font)|], False),-       ("c'loadFontData", "LoadFontData_", "rl_bindings.h", [t|Ptr CUChar -> CInt -> CInt -> Ptr CInt -> CInt -> CInt -> IO (Ptr GlyphInfo)|], False),-       ("c'genImageFontAtlas", "GenImageFontAtlas_", "rl_bindings.h", [t|Ptr GlyphInfo -> Ptr (Ptr Rectangle) -> CInt -> CInt -> CInt -> CInt -> IO (Ptr Image)|], False),-       ("c'unloadFontData", "UnloadFontData_", "rl_bindings.h", [t|Ptr GlyphInfo -> CInt -> IO ()|], False),-       ("c'isFontReady", "IsFontReady_", "rl_bindings.h", [t|Ptr Font -> IO CBool|], False),-       ("c'unloadFont", "UnloadFont_", "rl_bindings.h", [t|Ptr Font -> IO ()|], False),-       ("c'exportFontAsCode", "ExportFontAsCode_", "rl_bindings.h", [t|Ptr Font -> CString -> IO CBool|], False),-       ("c'drawFPS", "DrawFPS_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|], False),-       ("c'drawText", "DrawText_", "rl_bindings.h", [t|CString -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawTextEx", "DrawTextEx_", "rl_bindings.h", [t|Ptr Font -> CString -> Ptr Vector2 -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawTextPro", "DrawTextPro_", "rl_bindings.h", [t|Ptr Font -> CString -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawTextCodepoint", "DrawTextCodepoint_", "rl_bindings.h", [t|Ptr Font -> CInt -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawTextCodepoints", "DrawTextCodepoints_", "rl_bindings.h", [t|Ptr Font -> Ptr CInt -> CInt -> Ptr Vector2 -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'setTextLineSpacing", "SetTextLineSpacing_", "rl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'measureText", "MeasureText_", "rl_bindings.h", [t|CString -> CInt -> IO CInt|], False),-       ("c'measureTextEx", "MeasureTextEx_", "rl_bindings.h", [t|Ptr Font -> CString -> CFloat -> CFloat -> IO (Ptr Vector2)|], False),-       ("c'getGlyphIndex", "GetGlyphIndex_", "rl_bindings.h", [t|Ptr Font -> CInt -> IO CInt|], False),-       ("c'getGlyphInfo", "GetGlyphInfo_", "rl_bindings.h", [t|Ptr Font -> CInt -> IO (Ptr GlyphInfo)|], False),-       ("c'getGlyphAtlasRec", "GetGlyphAtlasRec_", "rl_bindings.h", [t|Ptr Font -> CInt -> IO (Ptr Rectangle)|], False),-       ("c'loadUTF8", "LoadUTF8_", "rl_bindings.h", [t|Ptr CInt -> CInt -> IO CString|], False),-       ("c'loadCodepoints", "LoadCodepoints_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO (Ptr CInt)|], False),-       ("c'getCodepointCount", "GetCodepointCount_", "rl_bindings.h", [t|CString -> IO CInt|], False),-       ("c'getCodepointNext", "GetCodepointNext_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO CInt|], False),-       ("c'getCodepointPrevious", "GetCodepointPrevious_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO CInt|], False),-       ("c'codepointToUTF8", "CodepointToUTF8_", "rl_bindings.h", [t|CInt -> Ptr CInt -> IO CString|], False)+     [ ("c'getFontDefault", "GetFontDefault_", "rl_bindings.h", [t|IO (Ptr Font)|]),+       ("c'loadFont", "LoadFont_", "rl_bindings.h", [t|CString -> IO (Ptr Font)|]),+       ("c'loadFontEx", "LoadFontEx_", "rl_bindings.h", [t|CString -> CInt -> Ptr CInt -> CInt -> IO (Ptr Font)|]),+       ("c'loadFontFromImage", "LoadFontFromImage_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> CInt -> IO (Ptr Font)|]),+       ("c'loadFontFromMemory", "LoadFontFromMemory_", "rl_bindings.h", [t|CString -> Ptr CUChar -> CInt -> CInt -> Ptr CInt -> CInt -> IO (Ptr Font)|]),+       ("c'loadFontData", "LoadFontData_", "rl_bindings.h", [t|Ptr CUChar -> CInt -> CInt -> Ptr CInt -> CInt -> CInt -> IO (Ptr GlyphInfo)|]),+       ("c'genImageFontAtlas", "GenImageFontAtlas_", "rl_bindings.h", [t|Ptr GlyphInfo -> Ptr (Ptr Rectangle) -> CInt -> CInt -> CInt -> CInt -> IO (Ptr Image)|]),+       ("c'unloadFontData", "UnloadFontData_", "rl_bindings.h", [t|Ptr GlyphInfo -> CInt -> IO ()|]),+       ("c'isFontReady", "IsFontReady_", "rl_bindings.h", [t|Ptr Font -> IO CBool|]),+       ("c'unloadFont", "UnloadFont_", "rl_bindings.h", [t|Ptr Font -> IO ()|]),+       ("c'exportFontAsCode", "ExportFontAsCode_", "rl_bindings.h", [t|Ptr Font -> CString -> IO CBool|]),+       ("c'drawFPS", "DrawFPS_", "rl_bindings.h", [t|CInt -> CInt -> IO ()|]),+       ("c'drawText", "DrawText_", "rl_bindings.h", [t|CString -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawTextEx", "DrawTextEx_", "rl_bindings.h", [t|Ptr Font -> CString -> Ptr Vector2 -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawTextPro", "DrawTextPro_", "rl_bindings.h", [t|Ptr Font -> CString -> Ptr Vector2 -> Ptr Vector2 -> CFloat -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawTextCodepoint", "DrawTextCodepoint_", "rl_bindings.h", [t|Ptr Font -> CInt -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawTextCodepoints", "DrawTextCodepoints_", "rl_bindings.h", [t|Ptr Font -> Ptr CInt -> CInt -> Ptr Vector2 -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'setTextLineSpacing", "SetTextLineSpacing_", "rl_bindings.h", [t|CInt -> IO ()|]),+       ("c'measureText", "MeasureText_", "rl_bindings.h", [t|CString -> CInt -> IO CInt|]),+       ("c'measureTextEx", "MeasureTextEx_", "rl_bindings.h", [t|Ptr Font -> CString -> CFloat -> CFloat -> IO (Ptr Vector2)|]),+       ("c'getGlyphIndex", "GetGlyphIndex_", "rl_bindings.h", [t|Ptr Font -> CInt -> IO CInt|]),+       ("c'getGlyphInfo", "GetGlyphInfo_", "rl_bindings.h", [t|Ptr Font -> CInt -> IO (Ptr GlyphInfo)|]),+       ("c'getGlyphAtlasRec", "GetGlyphAtlasRec_", "rl_bindings.h", [t|Ptr Font -> CInt -> IO (Ptr Rectangle)|]),+       ("c'loadUTF8", "LoadUTF8_", "rl_bindings.h", [t|Ptr CInt -> CInt -> IO CString|]),+       ("c'loadCodepoints", "LoadCodepoints_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO (Ptr CInt)|]),+       ("c'getCodepointCount", "GetCodepointCount_", "rl_bindings.h", [t|CString -> IO CInt|]),+       ("c'getCodepointNext", "GetCodepointNext_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO CInt|]),+       ("c'getCodepointPrevious", "GetCodepointPrevious_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO CInt|]),+       ("c'codepointToUTF8", "CodepointToUTF8_", "rl_bindings.h", [t|CInt -> Ptr CInt -> IO CString|])      ]  ) 
src/Raylib/Core/Textures.hs view
@@ -5,7 +5,6 @@   ( -- * High level     loadImage,     loadImageRaw,-    loadImageSvg,     loadImageAnim,     loadImageAnimFromMemory,     loadImageFromMemory,@@ -108,6 +107,7 @@     colorContrast,     colorAlpha,     colorAlphaBlend,+    colorLerp,     getColor,     getPixelColor,     setPixelColor,@@ -116,7 +116,6 @@     -- * Native     c'loadImage,     c'loadImageRaw,-    c'loadImageSvg,     c'loadImageAnim,     c'loadImageAnimFromMemory,     c'loadImageFromMemory,@@ -221,6 +220,7 @@     c'colorContrast,     c'colorAlpha,     c'colorAlphaBlend,+    c'colorLerp,     c'getColor,     c'getPixelColor,     c'setPixelColor,@@ -272,116 +272,116 @@   )  $( genNative-     [ ("c'loadImage", "LoadImage_", "rl_bindings.h", [t|CString -> IO (Ptr Image)|], False),-       ("c'loadImageRaw", "LoadImageRaw_", "rl_bindings.h", [t|CString -> CInt -> CInt -> CInt -> CInt -> IO (Ptr Image)|], False),-       ("c'loadImageSvg", "LoadImageSvg_", "rl_bindings.h", [t|CString -> CInt -> CInt -> IO (Ptr Image)|], False),-       ("c'loadImageAnim", "LoadImageAnim_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO (Ptr Image)|], False),-       ("c'loadImageAnimFromMemory", "LoadImageAnimFromMemory_", "rl_bindings.h", [t|CString -> Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr Image)|], False),-       ("c'loadImageFromMemory", "LoadImageFromMemory_", "rl_bindings.h", [t|CString -> Ptr CUChar -> CInt -> IO (Ptr Image)|], False),-       ("c'loadImageFromTexture", "LoadImageFromTexture_", "rl_bindings.h", [t|Ptr Texture -> IO (Ptr Image)|], False),-       ("c'loadImageFromScreen", "LoadImageFromScreen_", "rl_bindings.h", [t|IO (Ptr Image)|], False),-       ("c'isImageReady", "IsImageReady_", "rl_bindings.h", [t|Ptr Image -> IO CBool|], False),-       ("c'unloadImage", "UnloadImage_", "rl_bindings.h", [t|Ptr Image -> IO ()|], False),-       ("c'exportImage", "ExportImage_", "rl_bindings.h", [t|Ptr Image -> CString -> IO CBool|], False),-       ("c'exportImageToMemory", "ExportImageToMemory_", "rl_bindings.h", [t|Ptr Image -> CString -> Ptr CInt -> IO (Ptr CUChar)|], False),-       ("c'exportImageAsCode", "ExportImageAsCode_", "rl_bindings.h", [t|Ptr Image -> CString -> IO CBool|], False),-       ("c'genImageColor", "GenImageColor_", "rl_bindings.h", [t|CInt -> CInt -> Ptr Color -> IO (Ptr Image)|], False),-       ("c'genImageGradientLinear", "GenImageGradientLinear_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> Ptr Color -> Ptr Color -> IO (Ptr Image)|], False),-       ("c'genImageGradientRadial", "GenImageGradientRadial_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> Ptr Color -> Ptr Color -> IO (Ptr Image)|], False),-       ("c'genImageGradientSquare", "GenImageGradientSquare_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> Ptr Color -> Ptr Color -> IO (Ptr Image)|], False),-       ("c'genImageChecked", "GenImageChecked_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> Ptr Color -> IO (Ptr Image)|], False),-       ("c'genImageWhiteNoise", "GenImageWhiteNoise_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> IO (Ptr Image)|], False),-       ("c'genImagePerlinNoise", "GenImagePerlinNoise_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> CFloat -> IO (Ptr Image)|], False),-       ("c'genImageCellular", "GenImageCellular_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> IO (Ptr Image)|], False),-       ("c'genImageText", "GenImageText_", "rl_bindings.h", [t|CInt -> CInt -> CString -> IO (Ptr Image)|], False),-       ("c'imageCopy", "ImageCopy_", "rl_bindings.h", [t|Ptr Image -> IO (Ptr Image)|], False),-       ("c'imageFromImage", "ImageFromImage_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> IO (Ptr Image)|], False),-       ("c'imageFromChannel", "ImageFromChannel_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO (Ptr Image)|], False),-       ("c'imageText", "ImageText_", "rl_bindings.h", [t|CString -> CInt -> Ptr Color -> IO (Ptr Image)|], False),-       ("c'imageTextEx", "ImageTextEx_", "rl_bindings.h", [t|Ptr Font -> CString -> CFloat -> CFloat -> Ptr Color -> IO (Ptr Image)|], False),-       ("c'imageFormat", "ImageFormat_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|], False),-       ("c'imageToPOT", "ImageToPOT_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> IO ()|], False),-       ("c'imageCrop", "ImageCrop_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> IO ()|], False),-       ("c'imageAlphaCrop", "ImageAlphaCrop_", "rl_bindings.h", [t|Ptr Image -> CFloat -> IO ()|], False),-       ("c'imageAlphaClear", "ImageAlphaClear_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> CFloat -> IO ()|], False),-       ("c'imageAlphaMask", "ImageAlphaMask_", "rl_bindings.h", [t|Ptr Image -> Ptr Image -> IO ()|], False),-       ("c'imageAlphaPremultiply", "ImageAlphaPremultiply_", "rl_bindings.h", [t|Ptr Image -> IO ()|], False),-       ("c'imageBlurGaussian", "ImageBlurGaussian_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|], False),-       ("c'imageKernelConvolution", "ImageKernelConvolution_", "rl_bindings.h", [t|Ptr Image -> Ptr CFloat -> CInt -> IO ()|], False),-       ("c'imageResize", "ImageResize_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> IO ()|], False),-       ("c'imageResizeNN", "ImageResizeNN_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> IO ()|], False),-       ("c'imageResizeCanvas", "ImageResizeCanvas_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageMipmaps", "ImageMipmaps_", "rl_bindings.h", [t|Ptr Image -> IO ()|], False),-       ("c'imageDither", "ImageDither_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> CInt -> IO ()|], False),-       ("c'imageFlipVertical", "ImageFlipVertical_", "rl_bindings.h", [t|Ptr Image -> IO ()|], False),-       ("c'imageFlipHorizontal", "ImageFlipHorizontal_", "rl_bindings.h", [t|Ptr Image -> IO ()|], False),-       ("c'imageRotate", "ImageRotate_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|], False),-       ("c'imageRotateCW", "ImageRotateCW_", "rl_bindings.h", [t|Ptr Image -> IO ()|], False),-       ("c'imageRotateCCW", "ImageRotateCCW_", "rl_bindings.h", [t|Ptr Image -> IO ()|], False),-       ("c'imageColorTint", "ImageColorTint_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> IO ()|], False),-       ("c'imageColorInvert", "ImageColorInvert_", "rl_bindings.h", [t|Ptr Image -> IO ()|], False),-       ("c'imageColorGrayscale", "ImageColorGrayscale_", "rl_bindings.h", [t|Ptr Image -> IO ()|], False),-       ("c'imageColorContrast", "ImageColorContrast_", "rl_bindings.h", [t|Ptr Image -> CFloat -> IO ()|], False),-       ("c'imageColorBrightness", "ImageColorBrightness_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|], False),-       ("c'imageColorReplace", "ImageColorReplace_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> Ptr Color -> IO ()|], False),-       ("c'loadImageColors", "LoadImageColors_", "rl_bindings.h", [t|Ptr Image -> IO (Ptr Color)|], False),-       ("c'loadImagePalette", "LoadImagePalette_", "rl_bindings.h", [t|Ptr Image -> CInt -> Ptr CInt -> IO (Ptr Color)|], False),-       ("c'getImageAlphaBorder", "GetImageAlphaBorder_", "rl_bindings.h", [t|Ptr Image -> CFloat -> IO (Ptr Rectangle)|], False),-       ("c'getImageColor", "GetImageColor_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> IO (Ptr Color)|], False),-       ("c'imageClearBackground", "ImageClearBackground_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> IO ()|], False),-       ("c'imageDrawPixel", "ImageDrawPixel_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDrawPixelV", "ImageDrawPixelV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'imageDrawLine", "ImageDrawLine_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDrawLineV", "ImageDrawLineV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'imageDrawCircle", "ImageDrawCircle_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDrawCircleV", "ImageDrawCircleV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDrawCircleLines", "ImageDrawCircleLines_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDrawCircleLinesV", "ImageDrawCircleLinesV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDrawRectangle", "ImageDrawRectangle_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDrawRectangleV", "ImageDrawRectangleV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'imageDrawRectangleRec", "ImageDrawRectangleRec_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> Ptr Color -> IO ()|], False),-       ("c'imageDrawRectangleLines", "ImageDrawRectangleLines_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDrawTriangle", "ImageDrawTriangle_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'imageDrawTriangleEx", "ImageDrawTriangleEx_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> Ptr Color -> Ptr Color -> IO ()|], False),-       ("c'imageDrawTriangleLines", "ImageDrawTriangleLines_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'imageDrawTriangleFan", "ImageDrawTriangleFan_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDrawTriangleStrip", "ImageDrawTriangleStrip_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDraw", "ImageDraw_", "rl_bindings.h", [t|Ptr Image -> Ptr Image -> Ptr Rectangle -> Ptr Rectangle -> Ptr Color -> IO ()|], False),-       ("c'imageDrawText", "ImageDrawText_", "rl_bindings.h", [t|Ptr Image -> CString -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'imageDrawTextEx", "ImageDrawTextEx_", "rl_bindings.h", [t|Ptr Image -> Ptr Font -> CString -> Ptr Vector2 -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'loadTexture", "LoadTexture_", "rl_bindings.h", [t|CString -> IO (Ptr Texture)|], False),-       ("c'loadTextureFromImage", "LoadTextureFromImage_", "rl_bindings.h", [t|Ptr Image -> IO (Ptr Texture)|], False),-       ("c'loadTextureCubemap", "LoadTextureCubemap_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO (Ptr Texture)|], False),-       ("c'loadRenderTexture", "LoadRenderTexture_", "rl_bindings.h", [t|CInt -> CInt -> IO (Ptr RenderTexture)|], False),-       ("c'isTextureReady", "IsTextureReady_", "rl_bindings.h", [t|Ptr Texture -> IO CBool|], False),-       ("c'unloadTexture", "UnloadTexture_", "rl_bindings.h", [t|Ptr Texture -> IO ()|], False),-       ("c'isRenderTextureReady", "IsRenderTextureReady_", "rl_bindings.h", [t|Ptr RenderTexture -> IO CBool|], False),-       ("c'unloadRenderTexture", "UnloadRenderTexture_", "rl_bindings.h", [t|Ptr RenderTexture -> IO ()|], False),-       ("c'updateTexture", "UpdateTexture_", "rl_bindings.h", [t|Ptr Texture -> Ptr () -> IO ()|], False),-       ("c'updateTextureRec", "UpdateTextureRec_", "rl_bindings.h", [t|Ptr Texture -> Ptr Rectangle -> Ptr () -> IO ()|], False),-       ("c'genTextureMipmaps", "GenTextureMipmaps_", "rl_bindings.h", [t|Ptr Texture -> IO ()|], False),-       ("c'setTextureFilter", "SetTextureFilter_", "rl_bindings.h", [t|Ptr Texture -> CInt -> IO ()|], False),-       ("c'setTextureWrap", "SetTextureWrap_", "rl_bindings.h", [t|Ptr Texture -> CInt -> IO ()|], False),-       ("c'drawTexture", "DrawTexture_", "rl_bindings.h", [t|Ptr Texture -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'drawTextureV", "DrawTextureV_", "rl_bindings.h", [t|Ptr Texture -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'drawTextureEx", "DrawTextureEx_", "rl_bindings.h", [t|Ptr Texture -> Ptr Vector2 -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawTextureRec", "DrawTextureRec_", "rl_bindings.h", [t|Ptr Texture -> Ptr Rectangle -> Ptr Vector2 -> Ptr Color -> IO ()|], False),-       ("c'drawTexturePro", "DrawTexturePro_", "rl_bindings.h", [t|Ptr Texture -> Ptr Rectangle -> Ptr Rectangle -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'drawTextureNPatch", "DrawTextureNPatch_", "rl_bindings.h", [t|Ptr Texture -> Ptr NPatchInfo -> Ptr Rectangle -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|], False),-       ("c'fade", "Fade_", "rl_bindings.h", [t|Ptr Color -> CFloat -> IO (Ptr Color)|], False),-       ("c'colorToInt", "ColorToInt_", "rl_bindings.h", [t|Ptr Color -> IO CInt|], False),-       ("c'colorNormalize", "ColorNormalize_", "rl_bindings.h", [t|Ptr Color -> IO (Ptr Vector4)|], False),-       ("c'colorFromNormalized", "ColorFromNormalized_", "rl_bindings.h", [t|Ptr Vector4 -> IO (Ptr Color)|], False),-       ("c'colorToHSV", "ColorToHSV_", "rl_bindings.h", [t|Ptr Color -> IO (Ptr Vector3)|], False),-       ("c'colorFromHSV", "ColorFromHSV_", "rl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO (Ptr Color)|], False),-       ("c'colorTint", "ColorTint_", "rl_bindings.h", [t|Ptr Color -> Ptr Color -> IO (Ptr Color)|], False),-       ("c'colorBrightness", "ColorBrightness_", "rl_bindings.h", [t|Ptr Color -> CFloat -> IO (Ptr Color)|], False),-       ("c'colorContrast", "ColorContrast_", "rl_bindings.h", [t|Ptr Color -> CFloat -> IO (Ptr Color)|], False),-       ("c'colorAlpha", "ColorAlpha_", "rl_bindings.h", [t|Ptr Color -> CFloat -> IO (Ptr Color)|], False),-       ("c'colorAlphaBlend", "ColorAlphaBlend_", "rl_bindings.h", [t|Ptr Color -> Ptr Color -> Ptr Color -> IO (Ptr Color)|], False),-       ("c'getColor", "GetColor_", "rl_bindings.h", [t|CUInt -> IO (Ptr Color)|], False),-       ("c'getPixelColor", "GetPixelColor_", "rl_bindings.h", [t|Ptr () -> CInt -> IO (Ptr Color)|], False),-       ("c'setPixelColor", "SetPixelColor_", "rl_bindings.h", [t|Ptr () -> Ptr Color -> CInt -> IO ()|], False)+     [ ("c'loadImage", "LoadImage_", "rl_bindings.h", [t|CString -> IO (Ptr Image)|]),+       ("c'loadImageRaw", "LoadImageRaw_", "rl_bindings.h", [t|CString -> CInt -> CInt -> CInt -> CInt -> IO (Ptr Image)|]),+       ("c'loadImageAnim", "LoadImageAnim_", "rl_bindings.h", [t|CString -> Ptr CInt -> IO (Ptr Image)|]),+       ("c'loadImageAnimFromMemory", "LoadImageAnimFromMemory_", "rl_bindings.h", [t|CString -> Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr Image)|]),+       ("c'loadImageFromMemory", "LoadImageFromMemory_", "rl_bindings.h", [t|CString -> Ptr CUChar -> CInt -> IO (Ptr Image)|]),+       ("c'loadImageFromTexture", "LoadImageFromTexture_", "rl_bindings.h", [t|Ptr Texture -> IO (Ptr Image)|]),+       ("c'loadImageFromScreen", "LoadImageFromScreen_", "rl_bindings.h", [t|IO (Ptr Image)|]),+       ("c'isImageReady", "IsImageReady_", "rl_bindings.h", [t|Ptr Image -> IO CBool|]),+       ("c'unloadImage", "UnloadImage_", "rl_bindings.h", [t|Ptr Image -> IO ()|]),+       ("c'exportImage", "ExportImage_", "rl_bindings.h", [t|Ptr Image -> CString -> IO CBool|]),+       ("c'exportImageToMemory", "ExportImageToMemory_", "rl_bindings.h", [t|Ptr Image -> CString -> Ptr CInt -> IO (Ptr CUChar)|]),+       ("c'exportImageAsCode", "ExportImageAsCode_", "rl_bindings.h", [t|Ptr Image -> CString -> IO CBool|]),+       ("c'genImageColor", "GenImageColor_", "rl_bindings.h", [t|CInt -> CInt -> Ptr Color -> IO (Ptr Image)|]),+       ("c'genImageGradientLinear", "GenImageGradientLinear_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> Ptr Color -> Ptr Color -> IO (Ptr Image)|]),+       ("c'genImageGradientRadial", "GenImageGradientRadial_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> Ptr Color -> Ptr Color -> IO (Ptr Image)|]),+       ("c'genImageGradientSquare", "GenImageGradientSquare_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> Ptr Color -> Ptr Color -> IO (Ptr Image)|]),+       ("c'genImageChecked", "GenImageChecked_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> Ptr Color -> IO (Ptr Image)|]),+       ("c'genImageWhiteNoise", "GenImageWhiteNoise_", "rl_bindings.h", [t|CInt -> CInt -> CFloat -> IO (Ptr Image)|]),+       ("c'genImagePerlinNoise", "GenImagePerlinNoise_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> CFloat -> IO (Ptr Image)|]),+       ("c'genImageCellular", "GenImageCellular_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> IO (Ptr Image)|]),+       ("c'genImageText", "GenImageText_", "rl_bindings.h", [t|CInt -> CInt -> CString -> IO (Ptr Image)|]),+       ("c'imageCopy", "ImageCopy_", "rl_bindings.h", [t|Ptr Image -> IO (Ptr Image)|]),+       ("c'imageFromImage", "ImageFromImage_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> IO (Ptr Image)|]),+       ("c'imageFromChannel", "ImageFromChannel_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO (Ptr Image)|]),+       ("c'imageText", "ImageText_", "rl_bindings.h", [t|CString -> CInt -> Ptr Color -> IO (Ptr Image)|]),+       ("c'imageTextEx", "ImageTextEx_", "rl_bindings.h", [t|Ptr Font -> CString -> CFloat -> CFloat -> Ptr Color -> IO (Ptr Image)|]),+       ("c'imageFormat", "ImageFormat_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|]),+       ("c'imageToPOT", "ImageToPOT_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> IO ()|]),+       ("c'imageCrop", "ImageCrop_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> IO ()|]),+       ("c'imageAlphaCrop", "ImageAlphaCrop_", "rl_bindings.h", [t|Ptr Image -> CFloat -> IO ()|]),+       ("c'imageAlphaClear", "ImageAlphaClear_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> CFloat -> IO ()|]),+       ("c'imageAlphaMask", "ImageAlphaMask_", "rl_bindings.h", [t|Ptr Image -> Ptr Image -> IO ()|]),+       ("c'imageAlphaPremultiply", "ImageAlphaPremultiply_", "rl_bindings.h", [t|Ptr Image -> IO ()|]),+       ("c'imageBlurGaussian", "ImageBlurGaussian_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|]),+       ("c'imageKernelConvolution", "ImageKernelConvolution_", "rl_bindings.h", [t|Ptr Image -> Ptr CFloat -> CInt -> IO ()|]),+       ("c'imageResize", "ImageResize_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> IO ()|]),+       ("c'imageResizeNN", "ImageResizeNN_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> IO ()|]),+       ("c'imageResizeCanvas", "ImageResizeCanvas_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageMipmaps", "ImageMipmaps_", "rl_bindings.h", [t|Ptr Image -> IO ()|]),+       ("c'imageDither", "ImageDither_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> CInt -> IO ()|]),+       ("c'imageFlipVertical", "ImageFlipVertical_", "rl_bindings.h", [t|Ptr Image -> IO ()|]),+       ("c'imageFlipHorizontal", "ImageFlipHorizontal_", "rl_bindings.h", [t|Ptr Image -> IO ()|]),+       ("c'imageRotate", "ImageRotate_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|]),+       ("c'imageRotateCW", "ImageRotateCW_", "rl_bindings.h", [t|Ptr Image -> IO ()|]),+       ("c'imageRotateCCW", "ImageRotateCCW_", "rl_bindings.h", [t|Ptr Image -> IO ()|]),+       ("c'imageColorTint", "ImageColorTint_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> IO ()|]),+       ("c'imageColorInvert", "ImageColorInvert_", "rl_bindings.h", [t|Ptr Image -> IO ()|]),+       ("c'imageColorGrayscale", "ImageColorGrayscale_", "rl_bindings.h", [t|Ptr Image -> IO ()|]),+       ("c'imageColorContrast", "ImageColorContrast_", "rl_bindings.h", [t|Ptr Image -> CFloat -> IO ()|]),+       ("c'imageColorBrightness", "ImageColorBrightness_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|]),+       ("c'imageColorReplace", "ImageColorReplace_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> Ptr Color -> IO ()|]),+       ("c'loadImageColors", "LoadImageColors_", "rl_bindings.h", [t|Ptr Image -> IO (Ptr Color)|]),+       ("c'loadImagePalette", "LoadImagePalette_", "rl_bindings.h", [t|Ptr Image -> CInt -> Ptr CInt -> IO (Ptr Color)|]),+       ("c'getImageAlphaBorder", "GetImageAlphaBorder_", "rl_bindings.h", [t|Ptr Image -> CFloat -> IO (Ptr Rectangle)|]),+       ("c'getImageColor", "GetImageColor_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> IO (Ptr Color)|]),+       ("c'imageClearBackground", "ImageClearBackground_", "rl_bindings.h", [t|Ptr Image -> Ptr Color -> IO ()|]),+       ("c'imageDrawPixel", "ImageDrawPixel_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDrawPixelV", "ImageDrawPixelV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'imageDrawLine", "ImageDrawLine_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDrawLineV", "ImageDrawLineV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'imageDrawCircle", "ImageDrawCircle_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDrawCircleV", "ImageDrawCircleV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDrawCircleLines", "ImageDrawCircleLines_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDrawCircleLinesV", "ImageDrawCircleLinesV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDrawRectangle", "ImageDrawRectangle_", "rl_bindings.h", [t|Ptr Image -> CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDrawRectangleV", "ImageDrawRectangleV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'imageDrawRectangleRec", "ImageDrawRectangleRec_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> Ptr Color -> IO ()|]),+       ("c'imageDrawRectangleLines", "ImageDrawRectangleLines_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDrawTriangle", "ImageDrawTriangle_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'imageDrawTriangleEx", "ImageDrawTriangleEx_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> Ptr Color -> Ptr Color -> IO ()|]),+       ("c'imageDrawTriangleLines", "ImageDrawTriangleLines_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'imageDrawTriangleFan", "ImageDrawTriangleFan_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDrawTriangleStrip", "ImageDrawTriangleStrip_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDraw", "ImageDraw_", "rl_bindings.h", [t|Ptr Image -> Ptr Image -> Ptr Rectangle -> Ptr Rectangle -> Ptr Color -> IO ()|]),+       ("c'imageDrawText", "ImageDrawText_", "rl_bindings.h", [t|Ptr Image -> CString -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'imageDrawTextEx", "ImageDrawTextEx_", "rl_bindings.h", [t|Ptr Image -> Ptr Font -> CString -> Ptr Vector2 -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'loadTexture", "LoadTexture_", "rl_bindings.h", [t|CString -> IO (Ptr Texture)|]),+       ("c'loadTextureFromImage", "LoadTextureFromImage_", "rl_bindings.h", [t|Ptr Image -> IO (Ptr Texture)|]),+       ("c'loadTextureCubemap", "LoadTextureCubemap_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO (Ptr Texture)|]),+       ("c'loadRenderTexture", "LoadRenderTexture_", "rl_bindings.h", [t|CInt -> CInt -> IO (Ptr RenderTexture)|]),+       ("c'isTextureReady", "IsTextureReady_", "rl_bindings.h", [t|Ptr Texture -> IO CBool|]),+       ("c'unloadTexture", "UnloadTexture_", "rl_bindings.h", [t|Ptr Texture -> IO ()|]),+       ("c'isRenderTextureReady", "IsRenderTextureReady_", "rl_bindings.h", [t|Ptr RenderTexture -> IO CBool|]),+       ("c'unloadRenderTexture", "UnloadRenderTexture_", "rl_bindings.h", [t|Ptr RenderTexture -> IO ()|]),+       ("c'updateTexture", "UpdateTexture_", "rl_bindings.h", [t|Ptr Texture -> Ptr () -> IO ()|]),+       ("c'updateTextureRec", "UpdateTextureRec_", "rl_bindings.h", [t|Ptr Texture -> Ptr Rectangle -> Ptr () -> IO ()|]),+       ("c'genTextureMipmaps", "GenTextureMipmaps_", "rl_bindings.h", [t|Ptr Texture -> IO ()|]),+       ("c'setTextureFilter", "SetTextureFilter_", "rl_bindings.h", [t|Ptr Texture -> CInt -> IO ()|]),+       ("c'setTextureWrap", "SetTextureWrap_", "rl_bindings.h", [t|Ptr Texture -> CInt -> IO ()|]),+       ("c'drawTexture", "DrawTexture_", "rl_bindings.h", [t|Ptr Texture -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'drawTextureV", "DrawTextureV_", "rl_bindings.h", [t|Ptr Texture -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'drawTextureEx", "DrawTextureEx_", "rl_bindings.h", [t|Ptr Texture -> Ptr Vector2 -> CFloat -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawTextureRec", "DrawTextureRec_", "rl_bindings.h", [t|Ptr Texture -> Ptr Rectangle -> Ptr Vector2 -> Ptr Color -> IO ()|]),+       ("c'drawTexturePro", "DrawTexturePro_", "rl_bindings.h", [t|Ptr Texture -> Ptr Rectangle -> Ptr Rectangle -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'drawTextureNPatch", "DrawTextureNPatch_", "rl_bindings.h", [t|Ptr Texture -> Ptr NPatchInfo -> Ptr Rectangle -> Ptr Vector2 -> CFloat -> Ptr Color -> IO ()|]),+       ("c'fade", "Fade_", "rl_bindings.h", [t|Ptr Color -> CFloat -> IO (Ptr Color)|]),+       ("c'colorToInt", "ColorToInt_", "rl_bindings.h", [t|Ptr Color -> IO CInt|]),+       ("c'colorNormalize", "ColorNormalize_", "rl_bindings.h", [t|Ptr Color -> IO (Ptr Vector4)|]),+       ("c'colorFromNormalized", "ColorFromNormalized_", "rl_bindings.h", [t|Ptr Vector4 -> IO (Ptr Color)|]),+       ("c'colorToHSV", "ColorToHSV_", "rl_bindings.h", [t|Ptr Color -> IO (Ptr Vector3)|]),+       ("c'colorFromHSV", "ColorFromHSV_", "rl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO (Ptr Color)|]),+       ("c'colorTint", "ColorTint_", "rl_bindings.h", [t|Ptr Color -> Ptr Color -> IO (Ptr Color)|]),+       ("c'colorBrightness", "ColorBrightness_", "rl_bindings.h", [t|Ptr Color -> CFloat -> IO (Ptr Color)|]),+       ("c'colorContrast", "ColorContrast_", "rl_bindings.h", [t|Ptr Color -> CFloat -> IO (Ptr Color)|]),+       ("c'colorAlpha", "ColorAlpha_", "rl_bindings.h", [t|Ptr Color -> CFloat -> IO (Ptr Color)|]),+       ("c'colorAlphaBlend", "ColorAlphaBlend_", "rl_bindings.h", [t|Ptr Color -> Ptr Color -> Ptr Color -> IO (Ptr Color)|]),+       ("c'colorLerp", "ColorLerp_", "rl_bindings.h", [t|Ptr Color -> Ptr Color -> CFloat -> IO (Ptr Color)|]),+       ("c'getColor", "GetColor_", "rl_bindings.h", [t|CUInt -> IO (Ptr Color)|]),+       ("c'getPixelColor", "GetPixelColor_", "rl_bindings.h", [t|Ptr () -> CInt -> IO (Ptr Color)|]),+       ("c'setPixelColor", "SetPixelColor_", "rl_bindings.h", [t|Ptr () -> Ptr Color -> CInt -> IO ()|])      ]  ) @@ -392,9 +392,6 @@ loadImageRaw fileName width height format headerSize =   withCString fileName (\str -> c'loadImageRaw str (fromIntegral width) (fromIntegral height) (fromIntegral $ fromEnum format) (fromIntegral headerSize)) >>= pop -loadImageSvg :: String -> Int -> Int -> IO Image-loadImageSvg fileNameOrString width height = withCString fileNameOrString (\s -> c'loadImageSvg s (fromIntegral width) (fromIntegral height)) >>= pop- -- | Returns the animation and the number of frames in a tuple loadImageAnim :: String -> IO (Image, Int) loadImageAnim fileName =@@ -775,6 +772,9 @@  colorAlphaBlend :: Color -> Color -> Color -> Color colorAlphaBlend dst src tint = unsafePerformIO $ withFreeable dst (\d -> withFreeable src (withFreeable tint . c'colorAlphaBlend d)) >>= pop++colorLerp :: Color -> Color -> Float -> Color+colorLerp color1 color2 factor = unsafePerformIO $ withFreeable color1 (\c1 -> withFreeable color2 (\c2 -> c'colorLerp c1 c2 (realToFrac factor))) >>= pop  getColor :: Integer -> Color getColor hexValue = unsafePerformIO $ c'getColor (fromIntegral hexValue) >>= pop
src/Raylib/Internal.hs view
@@ -150,16 +150,16 @@       }  $( genNative-     [ ("c'rlGetShaderIdDefault", "rlGetShaderIdDefault_", "rlgl_bindings.h", [t|IO CUInt|], False),-       ("c'rlUnloadShaderProgram", "rlUnloadShaderProgram_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlUnloadTexture", "rlUnloadTexture_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlUnloadFramebuffer", "rlUnloadFramebuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlUnloadVertexArray", "rlUnloadVertexArray_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlUnloadVertexBuffer", "rlUnloadVertexBuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'unloadMusicStreamData", "UnloadMusicStreamData", "rl_internal.h", [t|CInt -> Ptr () -> IO ()|], False),-       ("c'unloadAudioBuffer", "UnloadAudioBuffer_", "rl_internal.h", [t|Ptr () -> IO ()|], False),-       ("c'unloadAudioBufferAlias", "UnloadAudioBufferAlias", "rl_internal.h", [t|Ptr () -> IO ()|], False),-       ("c'getPixelDataSize", "GetPixelDataSize_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> IO CInt|], False)+     [ ("c'rlGetShaderIdDefault", "rlGetShaderIdDefault_", "rlgl_bindings.h", [t|IO CUInt|]),+       ("c'rlUnloadShaderProgram", "rlUnloadShaderProgram_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlUnloadTexture", "rlUnloadTexture_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlUnloadFramebuffer", "rlUnloadFramebuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlUnloadVertexArray", "rlUnloadVertexArray_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlUnloadVertexBuffer", "rlUnloadVertexBuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'unloadMusicStreamData", "UnloadMusicStreamData", "rl_internal.h", [t|CInt -> Ptr () -> IO ()|]),+       ("c'unloadAudioBuffer", "UnloadAudioBuffer_", "rl_internal.h", [t|Ptr () -> IO ()|]),+       ("c'unloadAudioBufferAlias", "UnloadAudioBufferAlias", "rl_internal.h", [t|Ptr () -> IO ()|]),+       ("c'getPixelDataSize", "GetPixelDataSize_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> IO CInt|])      ]  ) 
src/Raylib/Internal/TH.hs view
@@ -38,7 +38,7 @@     TypeQ,     mkName,     nameBase,-    reify, Foreign (ImportF), Callconv (CCall), Safety (Safe, Unsafe),+    reify, Foreign (ImportF), Callconv (CCall), Safety (Safe),   )  #endif@@ -60,16 +60,16 @@ --   means @foreign import@ statements. On web platforms, this means --   `callRaylibFunction` calls. genNative ::-  -- | (@hsName@, @cName@, @cFile@, @funType@, @isSafe@)-  [(String, String, String, TypeQ, Bool)] ->+  -- | (@hsName@, @cName@, @cFile@, @funType@)+  [(String, String, String, TypeQ)] ->   DecsQ genNative funs = do-  funs' <- mapM (\(a, b, c, d, e) -> (a,b,c,,e) <$> d) funs+  funs' <- mapM (\(a, b, c, d) -> (a,b,c,) <$> d) funs   return (genNative' funs')   where     genNative' [] = [] #ifdef WEB_FFI-    genNative' ((hsName, cName, _, funType, _) : xs) =+    genNative' ((hsName, cName, _, funType) : xs) =       [ -- hsName :: funType         SigD name funType,         -- hsName = callRaylibFunction "_cName"@@ -80,7 +80,7 @@       where         name = mkName hsName #else-    genNative' ((hsName, cName, cFile, funType, isSafe) : xs) =+    genNative' ((hsName, cName, cFile, funType) : xs) =       -- foreign import ccall safe/unsafe "cFile cName" hsName :: funType-      ForeignD (ImportF CCall (if isSafe then Safe else Unsafe) (cFile ++ " " ++ cName) (mkName hsName) funType) : genNative' xs+      ForeignD (ImportF CCall Safe (cFile ++ " " ++ cName) (mkName hsName) funType) : genNative' xs #endif
src/Raylib/Types/Core.hs view
@@ -106,10 +106,12 @@     p'automationEventList'events,      -- * Callbacks+    TraceLogCallback,     LoadFileDataCallback,     SaveFileDataCallback,     LoadFileTextCallback,     SaveFileTextCallback,+    C'TraceLogCallback,     C'LoadFileDataCallback,     C'SaveFileDataCallback,     C'LoadFileTextCallback,@@ -1153,6 +1155,8 @@ -- core callbacks --------------------- --------------------------------------- +type TraceLogCallback = TraceLogLevel -> String -> IO ()+ type LoadFileDataCallback = String -> IO [Integer]  type SaveFileDataCallback a = String -> Ptr a -> Integer -> IO Bool@@ -1160,6 +1164,8 @@ type LoadFileTextCallback = String -> IO String  type SaveFileTextCallback = String -> String -> IO Bool++type C'TraceLogCallback = FunPtr (CInt -> CString -> IO ())  type C'LoadFileDataCallback = FunPtr (CString -> Ptr CUInt -> IO (Ptr CUChar)) 
src/Raylib/Types/Core/Models.hs view
@@ -5,6 +5,7 @@ module Raylib.Types.Core.Models   ( -- * Enumerations     MaterialMapIndex (..),+    DefaultShaderAttributeLocation (..),     ShaderLocationIndex (..),     ShaderUniformDataType (..),     ShaderUniformData (..),@@ -134,6 +135,18 @@   | MaterialMapBrdf   deriving (Eq, Show, Enum) +data DefaultShaderAttributeLocation+  = DefaultShaderAttribLocationPosition+  | DefaultShaderAttribLocationTexcoord+  | DefaultShaderAttribLocationNormal+  | DefaultShaderAttribLocationColor+  | DefaultShaderAttribLocationTangent+  | DefaultShaderAttribLocationTexcoord2+  | DefaultShaderAttribLocationIndices+  | DefaultShaderAttribLocationBoneIds+  | DefaultShaderAttribLocationBoneWeights+  deriving (Eq, Show, Enum)+ data ShaderLocationIndex   = ShaderLocVertexPosition   | ShaderLocVertexTexcoord01@@ -161,6 +174,9 @@   | ShaderLocMapIrradiance   | ShaderLocMapPrefilter   | ShaderLocMapBrdf+  | ShaderLocVertexBoneIds+  | ShaderLocVertexBoneWeights+  | ShaderLocBoneMatrices   deriving (Eq, Show, Enum)  data ShaderUniformDataType@@ -325,13 +341,16 @@     mesh'animNormals :: Maybe [Vector3],     mesh'boneIds :: Maybe [Word8],     mesh'boneWeights :: Maybe [Float],+    mesh'boneMatrices :: Maybe [Matrix],+    mesh'boneCount :: Int,     mesh'vaoId :: Integer,+    -- | Use `toEnum` on `DefaultShaderAttributeLocation` for indices     mesh'vboId :: Maybe [Integer]   }   deriving (Eq, Show)  instance Storable Mesh where-  sizeOf _ = 112+  sizeOf _ = 120   alignment _ = 8   peek _p = do     vertexCount <- fromIntegral <$> peek (p'mesh'vertexCount _p)@@ -345,12 +364,14 @@     indices <- (map fromIntegral <$>) <$> (peekMaybeArray vertexCount =<< peek (p'mesh'indices _p))     animVertices <- peekMaybeArray vertexCount =<< peek (p'mesh'animVertices _p)     animNormals <- peekMaybeArray vertexCount =<< peek (p'mesh'animNormals _p)-    boneIds <- (map fromIntegral <$>) <$> (peekMaybeArray (vertexCount * 4) =<< peek (p'mesh'boneIds _p))-    boneWeights <- (map realToFrac <$>) <$> (peekMaybeArray (vertexCount * 4) =<< peek (p'mesh'boneWeights _p))+    boneCount <- fromIntegral <$> peek (p'mesh'boneCount _p)+    boneIds <- (map fromIntegral <$>) <$> (peekMaybeArray boneCount =<< peek (p'mesh'boneIds _p))+    boneWeights <- (map realToFrac <$>) <$> (peekMaybeArray boneCount =<< peek (p'mesh'boneWeights _p))+    boneMatrices <- peekMaybeArray boneCount =<< peek (p'mesh'boneMatrices _p)     vaoId <- fromIntegral <$> peek (p'mesh'vaoId _p)-    vboId <- (map fromIntegral <$>) <$> (peekMaybeArray 7 =<< peek (p'mesh'vboId _p))-    return $ Mesh vertexCount triangleCount vertices texcoords texcoords2 normals tangents colors indices animVertices animNormals boneIds boneWeights vaoId vboId-  poke _p (Mesh vertexCount triangleCount vertices texcoords texcoords2 normals tangents colors indices animVertices animNormals boneIds boneWeights vaoId vboId) = do+    vboId <- (map fromIntegral <$>) <$> (peekMaybeArray 9 =<< peek (p'mesh'vboId _p))+    return $ Mesh vertexCount triangleCount vertices texcoords texcoords2 normals tangents colors indices animVertices animNormals boneIds boneWeights boneMatrices boneCount vaoId vboId+  poke _p (Mesh vertexCount triangleCount vertices texcoords texcoords2 normals tangents colors indices animVertices animNormals boneIds boneWeights boneMatrices boneCount vaoId vboId) = do     poke (p'mesh'vertexCount _p) (fromIntegral vertexCount)     poke (p'mesh'triangleCount _p) (fromIntegral triangleCount)     poke (p'mesh'vertices _p) =<< newArray vertices@@ -364,6 +385,8 @@     poke (p'mesh'animNormals _p) =<< newMaybeArray animNormals     poke (p'mesh'boneIds _p) =<< newMaybeArray (map fromIntegral <$> boneIds)     poke (p'mesh'boneWeights _p) =<< newMaybeArray (map realToFrac <$> boneWeights)+    poke (p'mesh'boneMatrices _p) =<< newMaybeArray boneMatrices+    poke (p'mesh'boneCount _p) (fromIntegral boneCount)     poke (p'mesh'vaoId _p) (fromIntegral vaoId)     poke (p'mesh'vboId _p) =<< newMaybeArray (map fromIntegral <$> vboId)     return ()@@ -420,20 +443,27 @@ p'mesh'animNormals :: Ptr Mesh -> Ptr (Ptr Vector3) p'mesh'animNormals = (`plusPtr` 72) --- maybe array (mesh'vertexCount * 4)+-- maybe array (mesh'boneCount) p'mesh'boneIds :: Ptr Mesh -> Ptr (Ptr CUChar) p'mesh'boneIds = (`plusPtr` 80) --- maybe array (mesh'vertexCount * 4)+-- maybe array (mesh'boneCount) p'mesh'boneWeights :: Ptr Mesh -> Ptr (Ptr CFloat) p'mesh'boneWeights = (`plusPtr` 88) +-- maybe array (mesh'boneCount)+p'mesh'boneMatrices :: Ptr Mesh -> Ptr (Ptr Matrix)+p'mesh'boneMatrices = (`plusPtr` 96)++p'mesh'boneCount :: Ptr Mesh -> Ptr CInt+p'mesh'boneCount = (`plusPtr` 104)+ p'mesh'vaoId :: Ptr Mesh -> Ptr CUInt-p'mesh'vaoId = (`plusPtr` 96)+p'mesh'vaoId = (`plusPtr` 108) --- maybe array (7)+-- maybe array (9) p'mesh'vboId :: Ptr Mesh -> Ptr (Ptr CUInt)-p'mesh'vboId = (`plusPtr` 104)+p'mesh'vboId = (`plusPtr` 112)  instance Freeable Mesh where   rlFreeDependents _ ptr = do
src/Raylib/Types/Util/GUI.hs view
@@ -511,6 +511,8 @@     DropdownItemsSpacing   | -- | DropdownBox arrow hidden     DropdownArrowHidden+  | -- | DropdownBox roll up flag (default rolls down)+    DropdownRollUp   deriving (Eq, Show)  instance Enum GuiDropdownBoxProperty where@@ -518,10 +520,12 @@     ArrowPadding -> 16     DropdownItemsSpacing -> 17     DropdownArrowHidden -> 18+    DropdownRollUp -> 19   toEnum x = case x of     16 -> ArrowPadding     17 -> DropdownItemsSpacing     18 -> DropdownArrowHidden+    19 -> DropdownRollUp     n -> error $ "(GuiDropdownBoxProperty.toEnum) Invalid value: " ++ show n  instance Storable GuiDropdownBoxProperty where@@ -880,7 +884,7 @@   | IconLayers2   | IconMLayers   | IconMaps-  | Icon228+  | IconHot   | Icon229   | Icon230   | Icon231@@ -1140,7 +1144,7 @@     IconLayers2 -> 225     IconMLayers -> 226     IconMaps -> 227-    Icon228 -> 228+    IconHot -> 228     Icon229 -> 229     Icon230 -> 230     Icon231 -> 231@@ -1397,7 +1401,7 @@     225 -> IconLayers2     226 -> IconMLayers     227 -> IconMaps-    228 -> Icon228+    228 -> IconHot     229 -> Icon229     230 -> Icon230     231 -> Icon231
src/Raylib/Types/Util/RLGL.hs view
@@ -384,6 +384,14 @@     RLShaderUniformIVec3   | -- | Shader uniform type: ivec4 (4 int)     RLShaderUniformIVec4+  | -- | Shader uniform type: unsigned int+    RLShaderUniformUInt+  | -- | Shader uniform type: uivec2 (2 unsigned int)+    RLShaderUniformUIVec2+  | -- | Shader uniform type: uivec3 (3 unsigned int)+    RLShaderUniformUIVec3+  | -- | Shader uniform type: uivec4 (4 unsigned int)+    RLShaderUniformUIVec4   | -- | Shader uniform type: sampler2d     RLShaderUniformSampler2D   deriving (Eq, Show, Enum)
src/Raylib/Util/GUI.hs view
@@ -236,63 +236,63 @@ import Raylib.Internal.TH (genNative) import Raylib.Types (Color (Color), Font, GuiControl (Default), GuiControlProperty (..), GuiDefaultProperty (..), GuiIconName, GuiState, GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode, Rectangle (Rectangle), Vector2, pattern Vector2, Vector3, pattern Vector3) $( genNative-     [ ("c'guiEnable", "GuiEnable_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiDisable", "GuiDisable_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLock", "GuiLock_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiUnlock", "GuiUnlock_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiIsLocked", "GuiIsLocked_", "rgui_bindings.h", [t|IO CBool|], False),-       ("c'guiSetAlpha", "GuiSetAlpha_", "rgui_bindings.h", [t|CFloat -> IO ()|], False),-       ("c'guiSetState", "GuiSetState_", "rgui_bindings.h", [t|CInt -> IO ()|], False),-       ("c'guiGetState", "GuiGetState_", "rgui_bindings.h", [t|IO CInt|], False),-       ("c'guiSetFont", "GuiSetFont_", "rgui_bindings.h", [t|Ptr Font -> IO ()|], False),-       ("c'guiGetFont", "GuiGetFont_", "rgui_bindings.h", [t|IO (Ptr Font)|], False),-       ("c'guiSetStyle", "GuiSetStyle_", "rgui_bindings.h", [t|CInt -> CInt -> CInt -> IO ()|], False),-       ("c'guiGetStyle", "GuiGetStyle_", "rgui_bindings.h", [t|CInt -> CInt -> IO CInt|], False),-       ("c'guiLoadStyle", "GuiLoadStyle_", "rgui_bindings.h", [t|CString -> IO ()|], False),-       ("c'guiLoadStyleDefault", "GuiLoadStyleDefault_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiEnableTooltip", "GuiEnableTooltip_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiDisableTooltip", "GuiDisableTooltip_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiSetTooltip", "GuiSetTooltip_", "rgui_bindings.h", [t|CString -> IO ()|], False),-       ("c'guiIconText", "GuiIconText_", "rgui_bindings.h", [t|CInt -> CString -> IO CString|], False),-       ("c'guiSetIconScale", "GuiSetIconScale_", "rgui_bindings.h", [t|CInt -> IO ()|], False),-       ("c'guiGetIcons", "GuiGetIcons_", "rgui_bindings.h", [t|IO (Ptr CUInt)|], False),-       ("c'guiLoadIcons", "GuiLoadIcons_", "rgui_bindings.h", [t|CString -> CBool -> IO (Ptr CString)|], False),-       ("c'guiDrawIcon", "GuiDrawIcon_", "rgui_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False),-       ("c'guiWindowBox", "GuiWindowBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|], False),-       ("c'guiGroupBox", "GuiGroupBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|], False),-       ("c'guiLine", "GuiLine_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|], False),-       ("c'guiPanel", "GuiPanel_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|], False),-       ("c'guiTabBar", "GuiTabBar_", "rgui_bindings.h", [t|Ptr Rectangle -> Ptr CString -> CInt -> Ptr CInt -> IO CInt|], False),-       ("c'guiScrollPanel", "GuiScrollPanel_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr Rectangle -> Ptr Vector2 -> Ptr Rectangle -> IO CInt|], False),-       ("c'guiLabel", "GuiLabel_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|], False),-       ("c'guiButton", "GuiButton_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|], False),-       ("c'guiLabelButton", "GuiLabelButton_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|], False),-       ("c'guiToggle", "GuiToggle_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CBool -> IO CInt|], False),-       ("c'guiToggleGroup", "GuiToggleGroup_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> IO CInt|], False),-       ("c'guiToggleSlider", "GuiToggleSlider_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> IO CInt|], False),-       ("c'guiCheckBox", "GuiCheckBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CBool -> IO CInt|], False),-       ("c'guiComboBox", "GuiComboBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> IO CInt|], False),-       ("c'guiDropdownBox", "GuiDropdownBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> CBool -> IO CInt|], False),-       ("c'guiSpinner", "GuiSpinner_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> CInt -> CInt -> CBool -> IO CInt|], False),-       ("c'guiValueBox", "GuiValueBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> CInt -> CInt -> CBool -> IO CInt|], False),-       ("c'guiValueBoxFloat", "GuiValueBoxFloat_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CBool -> IO CInt|], False),-       ("c'guiTextBox", "GuiTextBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CInt -> CBool -> IO CInt|], False),-       ("c'guiSlider", "GuiSlider_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CFloat -> CFloat -> IO CInt|], False),-       ("c'guiSliderBar", "GuiSliderBar_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CFloat -> CFloat -> IO CInt|], False),-       ("c'guiProgressBar", "GuiProgressBar_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CFloat -> CFloat -> IO CInt|], False),-       ("c'guiStatusBar", "GuiStatusBar_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|], False),-       ("c'guiDummyRec", "GuiDummyRec_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|], False),-       ("c'guiGrid", "GuiGrid_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CFloat -> CInt -> Ptr Vector2 -> IO CInt|], False),-       ("c'guiListView", "GuiListView_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> Ptr CInt -> IO CInt|], False),-       ("c'guiListViewEx", "GuiListViewEx_", "rgui_bindings.h", [t|Ptr Rectangle -> Ptr CString -> CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt -> IO CInt|], False),-       ("c'guiMessageBox", "GuiMessageBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> CString -> IO CInt|], False),-       ("c'guiTextInputBox", "GuiTextInputBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> CString -> CString -> CInt -> Ptr CBool -> IO CInt|], False),-       ("c'guiColorPicker", "GuiColorPicker_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr Color -> IO CInt|], False),-       ("c'guiColorPanel", "GuiColorPanel_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr Color -> IO CInt|], False),-       ("c'guiColorBarAlpha", "GuiColorBarAlpha_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CFloat -> IO CInt|], False),-       ("c'guiColorBarHue", "GuiColorBarHue_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CFloat -> IO CInt|], False),-       ("c'guiColorPickerHSV", "GuiColorPickerHSV_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr Vector3 -> IO CInt|], False),-       ("c'guiColorPanelHSV", "GuiColorPanelHSV_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr Vector3 -> IO CInt|], False)+     [ ("c'guiEnable", "GuiEnable_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiDisable", "GuiDisable_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLock", "GuiLock_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiUnlock", "GuiUnlock_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiIsLocked", "GuiIsLocked_", "rgui_bindings.h", [t|IO CBool|]),+       ("c'guiSetAlpha", "GuiSetAlpha_", "rgui_bindings.h", [t|CFloat -> IO ()|]),+       ("c'guiSetState", "GuiSetState_", "rgui_bindings.h", [t|CInt -> IO ()|]),+       ("c'guiGetState", "GuiGetState_", "rgui_bindings.h", [t|IO CInt|]),+       ("c'guiSetFont", "GuiSetFont_", "rgui_bindings.h", [t|Ptr Font -> IO ()|]),+       ("c'guiGetFont", "GuiGetFont_", "rgui_bindings.h", [t|IO (Ptr Font)|]),+       ("c'guiSetStyle", "GuiSetStyle_", "rgui_bindings.h", [t|CInt -> CInt -> CInt -> IO ()|]),+       ("c'guiGetStyle", "GuiGetStyle_", "rgui_bindings.h", [t|CInt -> CInt -> IO CInt|]),+       ("c'guiLoadStyle", "GuiLoadStyle_", "rgui_bindings.h", [t|CString -> IO ()|]),+       ("c'guiLoadStyleDefault", "GuiLoadStyleDefault_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiEnableTooltip", "GuiEnableTooltip_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiDisableTooltip", "GuiDisableTooltip_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiSetTooltip", "GuiSetTooltip_", "rgui_bindings.h", [t|CString -> IO ()|]),+       ("c'guiIconText", "GuiIconText_", "rgui_bindings.h", [t|CInt -> CString -> IO CString|]),+       ("c'guiSetIconScale", "GuiSetIconScale_", "rgui_bindings.h", [t|CInt -> IO ()|]),+       ("c'guiGetIcons", "GuiGetIcons_", "rgui_bindings.h", [t|IO (Ptr CUInt)|]),+       ("c'guiLoadIcons", "GuiLoadIcons_", "rgui_bindings.h", [t|CString -> CBool -> IO (Ptr CString)|]),+       ("c'guiDrawIcon", "GuiDrawIcon_", "rgui_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|]),+       ("c'guiWindowBox", "GuiWindowBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|]),+       ("c'guiGroupBox", "GuiGroupBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|]),+       ("c'guiLine", "GuiLine_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|]),+       ("c'guiPanel", "GuiPanel_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|]),+       ("c'guiTabBar", "GuiTabBar_", "rgui_bindings.h", [t|Ptr Rectangle -> Ptr CString -> CInt -> Ptr CInt -> IO CInt|]),+       ("c'guiScrollPanel", "GuiScrollPanel_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr Rectangle -> Ptr Vector2 -> Ptr Rectangle -> IO CInt|]),+       ("c'guiLabel", "GuiLabel_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|]),+       ("c'guiButton", "GuiButton_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|]),+       ("c'guiLabelButton", "GuiLabelButton_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|]),+       ("c'guiToggle", "GuiToggle_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CBool -> IO CInt|]),+       ("c'guiToggleGroup", "GuiToggleGroup_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> IO CInt|]),+       ("c'guiToggleSlider", "GuiToggleSlider_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> IO CInt|]),+       ("c'guiCheckBox", "GuiCheckBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CBool -> IO CInt|]),+       ("c'guiComboBox", "GuiComboBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> IO CInt|]),+       ("c'guiDropdownBox", "GuiDropdownBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> CBool -> IO CInt|]),+       ("c'guiSpinner", "GuiSpinner_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> CInt -> CInt -> CBool -> IO CInt|]),+       ("c'guiValueBox", "GuiValueBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> CInt -> CInt -> CBool -> IO CInt|]),+       ("c'guiValueBoxFloat", "GuiValueBoxFloat_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CBool -> IO CInt|]),+       ("c'guiTextBox", "GuiTextBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CInt -> CBool -> IO CInt|]),+       ("c'guiSlider", "GuiSlider_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CFloat -> CFloat -> IO CInt|]),+       ("c'guiSliderBar", "GuiSliderBar_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CFloat -> CFloat -> IO CInt|]),+       ("c'guiProgressBar", "GuiProgressBar_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CFloat -> CFloat -> IO CInt|]),+       ("c'guiStatusBar", "GuiStatusBar_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|]),+       ("c'guiDummyRec", "GuiDummyRec_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> IO CInt|]),+       ("c'guiGrid", "GuiGrid_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CFloat -> CInt -> Ptr Vector2 -> IO CInt|]),+       ("c'guiListView", "GuiListView_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> Ptr CInt -> IO CInt|]),+       ("c'guiListViewEx", "GuiListViewEx_", "rgui_bindings.h", [t|Ptr Rectangle -> Ptr CString -> CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt -> IO CInt|]),+       ("c'guiMessageBox", "GuiMessageBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> CString -> IO CInt|]),+       ("c'guiTextInputBox", "GuiTextInputBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> CString -> CString -> CInt -> Ptr CBool -> IO CInt|]),+       ("c'guiColorPicker", "GuiColorPicker_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr Color -> IO CInt|]),+       ("c'guiColorPanel", "GuiColorPanel_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr Color -> IO CInt|]),+       ("c'guiColorBarAlpha", "GuiColorBarAlpha_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CFloat -> IO CInt|]),+       ("c'guiColorBarHue", "GuiColorBarHue_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CFloat -> IO CInt|]),+       ("c'guiColorPickerHSV", "GuiColorPickerHSV_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr Vector3 -> IO CInt|]),+       ("c'guiColorPanelHSV", "GuiColorPanelHSV_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr Vector3 -> IO CInt|])      ]  ) 
src/Raylib/Util/GUI/Styles.hs view
@@ -22,18 +22,18 @@ import Raylib.Internal.TH (genNative)  $( genNative-     [ ("c'guiLoadStyleAmber", "GuiLoadStyleAmber_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleAshes", "GuiLoadStyleAshes_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleBluish", "GuiLoadStyleBluish_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleCandy", "GuiLoadStyleCandy_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleCherry", "GuiLoadStyleCherry_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleCyber", "GuiLoadStyleCyber_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleDark", "GuiLoadStyleDark_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleEnefete", "GuiLoadStyleEnefete_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleJungle", "GuiLoadStyleJungle_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleLavanda", "GuiLoadStyleLavanda_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleSunny", "GuiLoadStyleSunny_", "rgui_bindings.h", [t|IO ()|], False),-       ("c'guiLoadStyleTerminal", "GuiLoadStyleTerminal_", "rgui_bindings.h", [t|IO ()|], False)+     [ ("c'guiLoadStyleAmber", "GuiLoadStyleAmber_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleAshes", "GuiLoadStyleAshes_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleBluish", "GuiLoadStyleBluish_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleCandy", "GuiLoadStyleCandy_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleCherry", "GuiLoadStyleCherry_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleCyber", "GuiLoadStyleCyber_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleDark", "GuiLoadStyleDark_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleEnefete", "GuiLoadStyleEnefete_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleJungle", "GuiLoadStyleJungle_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleLavanda", "GuiLoadStyleLavanda_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleSunny", "GuiLoadStyleSunny_", "rgui_bindings.h", [t|IO ()|]),+       ("c'guiLoadStyleTerminal", "GuiLoadStyleTerminal_", "rgui_bindings.h", [t|IO ()|])      ]  ) 
src/Raylib/Util/RLGL.hs view
@@ -169,6 +169,7 @@     rlGetLocationAttrib,     rlSetUniform,     rlSetUniformMatrix,+    rlSetUniformMatrices,     rlSetUniformSampler,     rlSetShader, @@ -300,6 +301,7 @@     c'rlGetLocationAttrib,     c'rlSetUniform,     c'rlSetUniformMatrix,+    c'rlSetUniformMatrices,     c'rlSetUniformSampler,     c'rlSetShader,     c'rlLoadComputeShaderProgram,@@ -412,160 +414,161 @@   )  $( genNative-     [ ("c'rlMatrixMode", "rlMatrixMode_", "rlgl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'rlTranslatef", "rlTranslatef_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO ()|], False),-       ("c'rlRotatef", "rlRotatef_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> CFloat -> IO ()|], False),-       ("c'rlScalef", "rlScalef_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO ()|], False),-       ("c'rlMultMatrixf", "rlMultMatrixf_", "rlgl_bindings.h", [t|Ptr CFloat -> IO ()|], False),-       ("c'rlFrustum", "rlFrustum_", "rlgl_bindings.h", [t|CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> IO ()|], False),-       ("c'rlOrtho", "rlOrtho_", "rlgl_bindings.h", [t|CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> IO ()|], False),-       ("c'rlViewport", "rlViewport_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> IO ()|], False),-       ("c'rlSetClipPlanes", "rlSetClipPlanes_", "rlgl_bindings.h", [t|CDouble -> CDouble -> IO ()|], False),-       ("c'rlGetCullDistanceNear", "rlGetCullDistanceNear", "rlgl_bindings.h", [t|IO CDouble|], False),-       ("c'rlGetCullDistanceFar", "rlGetCullDistanceFar", "rlgl_bindings.h", [t|IO CDouble|], False),-       ("c'rlBegin", "rlBegin_", "rlgl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'rlVertex2i", "rlVertex2i_", "rlgl_bindings.h", [t|CInt -> CInt -> IO ()|], False),-       ("c'rlVertex2f", "rlVertex2f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> IO ()|], False),-       ("c'rlVertex3f", "rlVertex3f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO ()|], False),-       ("c'rlTexCoord2f", "rlTexCoord2f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> IO ()|], False),-       ("c'rlNormal3f", "rlNormal3f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO ()|], False),-       ("c'rlColor4ub", "rlColor4ub_", "rlgl_bindings.h", [t|CUChar -> CUChar -> CUChar -> CUChar -> IO ()|], False),-       ("c'rlColor3f", "rlColor3f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO ()|], False),-       ("c'rlColor4f", "rlColor4f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> CFloat -> IO ()|], False),-       ("c'rlEnableVertexArray", "rlEnableVertexArray_", "rlgl_bindings.h", [t|CUInt -> IO CBool|], False),-       ("c'rlEnableVertexBuffer", "rlEnableVertexBuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlEnableVertexBufferElement", "rlEnableVertexBufferElement_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlEnableVertexAttribute", "rlEnableVertexAttribute_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlDisableVertexAttribute", "rlDisableVertexAttribute_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlActiveTextureSlot", "rlActiveTextureSlot_", "rlgl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'rlEnableTexture", "rlEnableTexture_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlEnableTextureCubemap", "rlEnableTextureCubemap_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlTextureParameters", "rlTextureParameters_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> IO ()|], False),-       ("c'rlCubemapParameters", "rlCubemapParameters_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> IO ()|], False),-       ("c'rlEnableShader", "rlEnableShader_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlEnableFramebuffer", "rlEnableFramebuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlActiveDrawBuffers", "rlActiveDrawBuffers_", "rlgl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'rlBlitFramebuffer", "rlBlitFramebuffer_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> IO ()|], False),-       ("c'rlBindFramebuffer", "rlBindFramebuffer_", "rlgl_bindings.h", [t|CUInt -> CUInt -> IO ()|], False),-       ("c'rlColorMask", "rlColorMask_", "rlgl_bindings.h", [t|CBool -> CBool -> CBool -> CBool -> IO ()|], False),-       ("c'rlSetCullFace", "rlSetCullFace_", "rlgl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'rlScissor", "rlScissor_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> IO ()|], False),-       ("c'rlSetLineWidth", "rlSetLineWidth_", "rlgl_bindings.h", [t|CFloat -> IO ()|], False),-       ("c'rlGetLineWidth", "rlGetLineWidth_", "rlgl_bindings.h", [t|IO CFloat|], False),-       ("c'rlIsStereoRenderEnabled", "rlIsStereoRenderEnabled_", "rlgl_bindings.h", [t|IO CBool|], False),-       ("c'rlClearColor", "rlClearColor_", "rlgl_bindings.h", [t|CUChar -> CUChar -> CUChar -> CUChar -> IO ()|], False),-       ("c'rlSetBlendMode", "rlSetBlendMode_", "rlgl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'rlSetBlendFactors", "rlSetBlendFactors_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> IO ()|], False),-       ("c'rlSetBlendFactorsSeparate", "rlSetBlendFactorsSeparate_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> IO ()|], False),-       ("c'rlglInit", "rlglInit_", "rlgl_bindings.h", [t|CInt -> CInt -> IO ()|], False),-       ("c'rlLoadExtensions", "rlLoadExtensions_", "rlgl_bindings.h", [t|Ptr () -> IO ()|], False),-       ("c'rlGetVersion", "rlGetVersion_", "rlgl_bindings.h", [t|IO CInt|], False),-       ("c'rlSetFramebufferWidth", "rlSetFramebufferWidth_", "rlgl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'rlGetFramebufferWidth", "rlGetFramebufferWidth_", "rlgl_bindings.h", [t|IO CInt|], False),-       ("c'rlSetFramebufferHeight", "rlSetFramebufferHeight_", "rlgl_bindings.h", [t|CInt -> IO ()|], False),-       ("c'rlGetFramebufferHeight", "rlGetFramebufferHeight_", "rlgl_bindings.h", [t|IO CInt|], False),-       ("c'rlGetTextureIdDefault", "rlGetTextureIdDefault_", "rlgl_bindings.h", [t|IO CUInt|], False),-       ("c'rlGetShaderIdDefault", "rlGetShaderIdDefault_", "rlgl_bindings.h", [t|IO CUInt|], False),-       ("c'rlGetShaderLocsDefault", "rlGetShaderLocsDefault_", "rlgl_bindings.h", [t|IO (Ptr CInt)|], False),-       ("c'rlLoadRenderBatch", "rlLoadRenderBatch_", "rlgl_bindings.h", [t|CInt -> CInt -> IO (Ptr RLRenderBatch)|], False),-       ("c'rlUnloadRenderBatch", "rlUnloadRenderBatch_", "rlgl_bindings.h", [t|Ptr RLRenderBatch -> IO ()|], False),-       ("c'rlDrawRenderBatch", "rlDrawRenderBatch_", "rlgl_bindings.h", [t|Ptr RLRenderBatch -> IO ()|], False),-       ("c'rlSetRenderBatchActive", "rlSetRenderBatchActive_", "rlgl_bindings.h", [t|Ptr RLRenderBatch -> IO ()|], False),-       ("c'rlCheckRenderBatchLimit", "rlCheckRenderBatchLimit_", "rlgl_bindings.h", [t|CInt -> IO CBool|], False),-       ("c'rlSetTexture", "rlSetTexture_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlLoadVertexArray", "rlLoadVertexArray_", "rlgl_bindings.h", [t|IO CUInt|], False),-       ("c'rlLoadVertexBuffer", "rlLoadVertexBuffer_", "rlgl_bindings.h", [t|Ptr () -> CInt -> CBool -> IO CUInt|], False),-       ("c'rlLoadVertexBufferElement", "rlLoadVertexBufferElement_", "rlgl_bindings.h", [t|Ptr () -> CInt -> CBool -> IO CUInt|], False),-       ("c'rlUpdateVertexBuffer", "rlUpdateVertexBuffer_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CInt -> CInt -> IO ()|], False),-       ("c'rlUpdateVertexBufferElements", "rlUpdateVertexBufferElements_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CInt -> CInt -> IO ()|], False),-       ("c'rlUnloadVertexArray", "rlUnloadVertexArray_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlUnloadVertexBuffer", "rlUnloadVertexBuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlSetVertexAttribute", "rlSetVertexAttribute_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> CBool -> CInt -> CInt -> IO ()|], False),-       ("c'rlSetVertexAttributeDivisor", "rlSetVertexAttributeDivisor_", "rlgl_bindings.h", [t|CUInt -> CInt -> IO ()|], False),-       ("c'rlSetVertexAttributeDefault", "rlSetVertexAttributeDefault_", "rlgl_bindings.h", [t|CInt -> Ptr () -> CInt -> CInt -> IO ()|], False),-       ("c'rlDrawVertexArray", "rlDrawVertexArray_", "rlgl_bindings.h", [t|CInt -> CInt -> IO ()|], False),-       ("c'rlDrawVertexArrayElements", "rlDrawVertexArrayElements_", "rlgl_bindings.h", [t|CInt -> CInt -> Ptr () -> IO ()|], False),-       ("c'rlDrawVertexArrayInstanced", "rlDrawVertexArrayInstanced_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> IO ()|], False),-       ("c'rlDrawVertexArrayElementsInstanced", "rlDrawVertexArrayElementsInstanced_", "rlgl_bindings.h", [t|CInt -> CInt -> Ptr () -> CInt -> IO ()|], False),-       ("c'rlLoadTexture", "rlLoadTexture_", "rlgl_bindings.h", [t|Ptr () -> CInt -> CInt -> CInt -> CInt -> IO CUInt|], False),-       ("c'rlLoadTextureDepth", "rlLoadTextureDepth_", "rlgl_bindings.h", [t|CInt -> CInt -> CBool -> IO CUInt|], False),-       ("c'rlLoadTextureCubemap", "rlLoadTextureCubemap_", "rlgl_bindings.h", [t|Ptr () -> CInt -> CInt -> IO CUInt|], False),-       ("c'rlUpdateTexture", "rlUpdateTexture_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> CInt -> CInt -> CInt -> Ptr () -> IO ()|], False),-       ("c'rlGetGlTextureFormats", "rlGetGlTextureFormats_", "rlgl_bindings.h", [t|CInt -> Ptr CUInt -> Ptr CUInt -> Ptr CUInt -> IO ()|], False),-       ("c'rlGetPixelFormatName", "rlGetPixelFormatName_", "rlgl_bindings.h", [t|CUInt -> IO CString|], False),-       ("c'rlUnloadTexture", "rlUnloadTexture_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlGenTextureMipmaps", "rlGenTextureMipmaps_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> CInt -> Ptr CInt -> IO ()|], False),-       ("c'rlReadTexturePixels", "rlReadTexturePixels_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> CInt -> IO (Ptr ())|], False),-       ("c'rlReadScreenPixels", "rlReadScreenPixels_", "rlgl_bindings.h", [t|CInt -> CInt -> IO (Ptr CUChar)|], False),-       ("c'rlLoadFramebuffer", "rlLoadFramebuffer_", "rlgl_bindings.h", [t|IO CUInt|], False),-       ("c'rlFramebufferAttach", "rlFramebufferAttach_", "rlgl_bindings.h", [t|CUInt -> CUInt -> CInt -> CInt -> CInt -> IO ()|], False),-       ("c'rlFramebufferComplete", "rlFramebufferComplete_", "rlgl_bindings.h", [t|CUInt -> IO CBool|], False),-       ("c'rlUnloadFramebuffer", "rlUnloadFramebuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlLoadShaderCode", "rlLoadShaderCode_", "rlgl_bindings.h", [t|CString -> CString -> IO CUInt|], False),-       ("c'rlCompileShader", "rlCompileShader_", "rlgl_bindings.h", [t|CString -> CInt -> IO CUInt|], False),-       ("c'rlLoadShaderProgram", "rlLoadShaderProgram_", "rlgl_bindings.h", [t|CUInt -> CUInt -> IO CUInt|], False),-       ("c'rlUnloadShaderProgram", "rlUnloadShaderProgram_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlGetLocationUniform", "rlGetLocationUniform_", "rlgl_bindings.h", [t|CUInt -> CString -> IO CInt|], False),-       ("c'rlGetLocationAttrib", "rlGetLocationAttrib_", "rlgl_bindings.h", [t|CUInt -> CString -> IO CInt|], False),-       ("c'rlSetUniform", "rlSetUniform_", "rlgl_bindings.h", [t|CInt -> Ptr () -> CInt -> CInt -> IO ()|], False),-       ("c'rlSetUniformMatrix", "rlSetUniformMatrix_", "rlgl_bindings.h", [t|CInt -> Ptr Matrix -> IO ()|], False),-       ("c'rlSetUniformSampler", "rlSetUniformSampler_", "rlgl_bindings.h", [t|CInt -> CUInt -> IO ()|], False),-       ("c'rlSetShader", "rlSetShader_", "rlgl_bindings.h", [t|CUInt -> Ptr CInt -> IO ()|], False),-       ("c'rlLoadComputeShaderProgram", "rlLoadComputeShaderProgram_", "rlgl_bindings.h", [t|CUInt -> IO CUInt|], False),-       ("c'rlComputeShaderDispatch", "rlComputeShaderDispatch_", "rlgl_bindings.h", [t|CUInt -> CUInt -> CUInt -> IO ()|], False),-       ("c'rlLoadShaderBuffer", "rlLoadShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CInt -> IO CUInt|], False),-       ("c'rlUnloadShaderBuffer", "rlUnloadShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),-       ("c'rlUpdateShaderBuffer", "rlUpdateShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CUInt -> CUInt -> IO ()|], False),-       ("c'rlBindShaderBuffer", "rlBindShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> CUInt -> IO ()|], False),-       ("c'rlReadShaderBuffer", "rlReadShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CUInt -> CUInt -> IO ()|], False),-       ("c'rlCopyShaderBuffer", "rlCopyShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> CUInt -> CUInt -> CUInt -> CUInt -> IO ()|], False),-       ("c'rlGetShaderBufferSize", "rlGetShaderBufferSize_", "rlgl_bindings.h", [t|CUInt -> IO CUInt|], False),-       ("c'rlBindImageTexture", "rlBindImageTexture_", "rlgl_bindings.h", [t|CUInt -> CUInt -> CInt -> CBool -> IO ()|], False),-       ("c'rlGetMatrixModelview", "rlGetMatrixModelview_", "rlgl_bindings.h", [t|IO (Ptr Matrix)|], False),-       ("c'rlGetMatrixProjection", "rlGetMatrixProjection_", "rlgl_bindings.h", [t|IO (Ptr Matrix)|], False),-       ("c'rlGetMatrixTransform", "rlGetMatrixTransform_", "rlgl_bindings.h", [t|IO (Ptr Matrix)|], False),-       ("c'rlGetMatrixProjectionStereo", "rlGetMatrixProjectionStereo_", "rlgl_bindings.h", [t|CInt -> IO (Ptr Matrix)|], False),-       ("c'rlGetMatrixViewOffsetStereo", "rlGetMatrixViewOffsetStereo_", "rlgl_bindings.h", [t|CInt -> IO (Ptr Matrix)|], False),-       ("c'rlSetMatrixProjection", "rlSetMatrixProjection_", "rlgl_bindings.h", [t|Ptr Matrix -> IO ()|], False),-       ("c'rlSetMatrixModelview", "rlSetMatrixModelview_", "rlgl_bindings.h", [t|Ptr Matrix -> IO ()|], False),-       ("c'rlSetMatrixProjectionStereo", "rlSetMatrixProjectionStereo_", "rlgl_bindings.h", [t|Ptr Matrix -> Ptr Matrix -> IO ()|], False),-       ("c'rlSetMatrixViewOffsetStereo", "rlSetMatrixViewOffsetStereo_", "rlgl_bindings.h", [t|Ptr Matrix -> Ptr Matrix -> IO ()|], False),-       ("c'rlGetPixelDataSize", "rlGetPixelDataSize", "rl_internal.h", [t|CInt -> CInt -> CInt -> IO CInt|], False),-       ("c'rlPushMatrix", "rlPushMatrix_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlPopMatrix", "rlPopMatrix_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlLoadIdentity", "rlLoadIdentity_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlEnd", "rlEnd_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableVertexArray", "rlDisableVertexArray_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableVertexBuffer", "rlDisableVertexBuffer_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableVertexBufferElement", "rlDisableVertexBufferElement_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableTexture", "rlDisableTexture_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableTextureCubemap", "rlDisableTextureCubemap_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableShader", "rlDisableShader_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableFramebuffer", "rlDisableFramebuffer_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlGetActiveFramebuffer", "rlGetActiveFramebuffer_", "rlgl_bindings.h", [t|IO CUInt|], False),-       ("c'rlEnableColorBlend", "rlEnableColorBlend_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableColorBlend", "rlDisableColorBlend_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlEnableDepthTest", "rlEnableDepthTest_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableDepthTest", "rlDisableDepthTest_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlEnableDepthMask", "rlEnableDepthMask_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableDepthMask", "rlDisableDepthMask_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlEnableBackfaceCulling", "rlEnableBackfaceCulling_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableBackfaceCulling", "rlDisableBackfaceCulling_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlEnableScissorTest", "rlEnableScissorTest_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableScissorTest", "rlDisableScissorTest_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlEnableWireMode", "rlEnableWireMode_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlEnablePointMode", "rlEnablePointMode_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableWireMode", "rlDisableWireMode_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlEnableSmoothLines", "rlEnableSmoothLines_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableSmoothLines", "rlDisableSmoothLines_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlEnableStereoRender", "rlEnableStereoRender_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDisableStereoRender", "rlDisableStereoRender_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlClearScreenBuffers", "rlClearScreenBuffers_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlCheckErrors", "rlCheckErrors_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlglClose", "rlglClose_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlDrawRenderBatchActive", "rlDrawRenderBatchActive_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlLoadDrawCube", "rlLoadDrawCube_", "rlgl_bindings.h", [t|IO ()|], False),-       ("c'rlLoadDrawQuad", "rlLoadDrawQuad_", "rlgl_bindings.h", [t|IO ()|], False)+     [ ("c'rlMatrixMode", "rlMatrixMode_", "rlgl_bindings.h", [t|CInt -> IO ()|]),+       ("c'rlTranslatef", "rlTranslatef_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO ()|]),+       ("c'rlRotatef", "rlRotatef_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> CFloat -> IO ()|]),+       ("c'rlScalef", "rlScalef_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO ()|]),+       ("c'rlMultMatrixf", "rlMultMatrixf_", "rlgl_bindings.h", [t|Ptr CFloat -> IO ()|]),+       ("c'rlFrustum", "rlFrustum_", "rlgl_bindings.h", [t|CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> IO ()|]),+       ("c'rlOrtho", "rlOrtho_", "rlgl_bindings.h", [t|CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> IO ()|]),+       ("c'rlViewport", "rlViewport_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> IO ()|]),+       ("c'rlSetClipPlanes", "rlSetClipPlanes_", "rlgl_bindings.h", [t|CDouble -> CDouble -> IO ()|]),+       ("c'rlGetCullDistanceNear", "rlGetCullDistanceNear", "rlgl_bindings.h", [t|IO CDouble|]),+       ("c'rlGetCullDistanceFar", "rlGetCullDistanceFar", "rlgl_bindings.h", [t|IO CDouble|]),+       ("c'rlBegin", "rlBegin_", "rlgl_bindings.h", [t|CInt -> IO ()|]),+       ("c'rlVertex2i", "rlVertex2i_", "rlgl_bindings.h", [t|CInt -> CInt -> IO ()|]),+       ("c'rlVertex2f", "rlVertex2f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> IO ()|]),+       ("c'rlVertex3f", "rlVertex3f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO ()|]),+       ("c'rlTexCoord2f", "rlTexCoord2f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> IO ()|]),+       ("c'rlNormal3f", "rlNormal3f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO ()|]),+       ("c'rlColor4ub", "rlColor4ub_", "rlgl_bindings.h", [t|CUChar -> CUChar -> CUChar -> CUChar -> IO ()|]),+       ("c'rlColor3f", "rlColor3f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> IO ()|]),+       ("c'rlColor4f", "rlColor4f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> CFloat -> CFloat -> IO ()|]),+       ("c'rlEnableVertexArray", "rlEnableVertexArray_", "rlgl_bindings.h", [t|CUInt -> IO CBool|]),+       ("c'rlEnableVertexBuffer", "rlEnableVertexBuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlEnableVertexBufferElement", "rlEnableVertexBufferElement_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlEnableVertexAttribute", "rlEnableVertexAttribute_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlDisableVertexAttribute", "rlDisableVertexAttribute_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlActiveTextureSlot", "rlActiveTextureSlot_", "rlgl_bindings.h", [t|CInt -> IO ()|]),+       ("c'rlEnableTexture", "rlEnableTexture_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlEnableTextureCubemap", "rlEnableTextureCubemap_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlTextureParameters", "rlTextureParameters_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> IO ()|]),+       ("c'rlCubemapParameters", "rlCubemapParameters_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> IO ()|]),+       ("c'rlEnableShader", "rlEnableShader_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlEnableFramebuffer", "rlEnableFramebuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlActiveDrawBuffers", "rlActiveDrawBuffers_", "rlgl_bindings.h", [t|CInt -> IO ()|]),+       ("c'rlBlitFramebuffer", "rlBlitFramebuffer_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> IO ()|]),+       ("c'rlBindFramebuffer", "rlBindFramebuffer_", "rlgl_bindings.h", [t|CUInt -> CUInt -> IO ()|]),+       ("c'rlColorMask", "rlColorMask_", "rlgl_bindings.h", [t|CBool -> CBool -> CBool -> CBool -> IO ()|]),+       ("c'rlSetCullFace", "rlSetCullFace_", "rlgl_bindings.h", [t|CInt -> IO ()|]),+       ("c'rlScissor", "rlScissor_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> IO ()|]),+       ("c'rlSetLineWidth", "rlSetLineWidth_", "rlgl_bindings.h", [t|CFloat -> IO ()|]),+       ("c'rlGetLineWidth", "rlGetLineWidth_", "rlgl_bindings.h", [t|IO CFloat|]),+       ("c'rlIsStereoRenderEnabled", "rlIsStereoRenderEnabled_", "rlgl_bindings.h", [t|IO CBool|]),+       ("c'rlClearColor", "rlClearColor_", "rlgl_bindings.h", [t|CUChar -> CUChar -> CUChar -> CUChar -> IO ()|]),+       ("c'rlSetBlendMode", "rlSetBlendMode_", "rlgl_bindings.h", [t|CInt -> IO ()|]),+       ("c'rlSetBlendFactors", "rlSetBlendFactors_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> IO ()|]),+       ("c'rlSetBlendFactorsSeparate", "rlSetBlendFactorsSeparate_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> IO ()|]),+       ("c'rlglInit", "rlglInit_", "rlgl_bindings.h", [t|CInt -> CInt -> IO ()|]),+       ("c'rlLoadExtensions", "rlLoadExtensions_", "rlgl_bindings.h", [t|Ptr () -> IO ()|]),+       ("c'rlGetVersion", "rlGetVersion_", "rlgl_bindings.h", [t|IO CInt|]),+       ("c'rlSetFramebufferWidth", "rlSetFramebufferWidth_", "rlgl_bindings.h", [t|CInt -> IO ()|]),+       ("c'rlGetFramebufferWidth", "rlGetFramebufferWidth_", "rlgl_bindings.h", [t|IO CInt|]),+       ("c'rlSetFramebufferHeight", "rlSetFramebufferHeight_", "rlgl_bindings.h", [t|CInt -> IO ()|]),+       ("c'rlGetFramebufferHeight", "rlGetFramebufferHeight_", "rlgl_bindings.h", [t|IO CInt|]),+       ("c'rlGetTextureIdDefault", "rlGetTextureIdDefault_", "rlgl_bindings.h", [t|IO CUInt|]),+       ("c'rlGetShaderIdDefault", "rlGetShaderIdDefault_", "rlgl_bindings.h", [t|IO CUInt|]),+       ("c'rlGetShaderLocsDefault", "rlGetShaderLocsDefault_", "rlgl_bindings.h", [t|IO (Ptr CInt)|]),+       ("c'rlLoadRenderBatch", "rlLoadRenderBatch_", "rlgl_bindings.h", [t|CInt -> CInt -> IO (Ptr RLRenderBatch)|]),+       ("c'rlUnloadRenderBatch", "rlUnloadRenderBatch_", "rlgl_bindings.h", [t|Ptr RLRenderBatch -> IO ()|]),+       ("c'rlDrawRenderBatch", "rlDrawRenderBatch_", "rlgl_bindings.h", [t|Ptr RLRenderBatch -> IO ()|]),+       ("c'rlSetRenderBatchActive", "rlSetRenderBatchActive_", "rlgl_bindings.h", [t|Ptr RLRenderBatch -> IO ()|]),+       ("c'rlCheckRenderBatchLimit", "rlCheckRenderBatchLimit_", "rlgl_bindings.h", [t|CInt -> IO CBool|]),+       ("c'rlSetTexture", "rlSetTexture_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlLoadVertexArray", "rlLoadVertexArray_", "rlgl_bindings.h", [t|IO CUInt|]),+       ("c'rlLoadVertexBuffer", "rlLoadVertexBuffer_", "rlgl_bindings.h", [t|Ptr () -> CInt -> CBool -> IO CUInt|]),+       ("c'rlLoadVertexBufferElement", "rlLoadVertexBufferElement_", "rlgl_bindings.h", [t|Ptr () -> CInt -> CBool -> IO CUInt|]),+       ("c'rlUpdateVertexBuffer", "rlUpdateVertexBuffer_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CInt -> CInt -> IO ()|]),+       ("c'rlUpdateVertexBufferElements", "rlUpdateVertexBufferElements_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CInt -> CInt -> IO ()|]),+       ("c'rlUnloadVertexArray", "rlUnloadVertexArray_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlUnloadVertexBuffer", "rlUnloadVertexBuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlSetVertexAttribute", "rlSetVertexAttribute_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> CBool -> CInt -> CInt -> IO ()|]),+       ("c'rlSetVertexAttributeDivisor", "rlSetVertexAttributeDivisor_", "rlgl_bindings.h", [t|CUInt -> CInt -> IO ()|]),+       ("c'rlSetVertexAttributeDefault", "rlSetVertexAttributeDefault_", "rlgl_bindings.h", [t|CInt -> Ptr () -> CInt -> CInt -> IO ()|]),+       ("c'rlDrawVertexArray", "rlDrawVertexArray_", "rlgl_bindings.h", [t|CInt -> CInt -> IO ()|]),+       ("c'rlDrawVertexArrayElements", "rlDrawVertexArrayElements_", "rlgl_bindings.h", [t|CInt -> CInt -> Ptr () -> IO ()|]),+       ("c'rlDrawVertexArrayInstanced", "rlDrawVertexArrayInstanced_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> IO ()|]),+       ("c'rlDrawVertexArrayElementsInstanced", "rlDrawVertexArrayElementsInstanced_", "rlgl_bindings.h", [t|CInt -> CInt -> Ptr () -> CInt -> IO ()|]),+       ("c'rlLoadTexture", "rlLoadTexture_", "rlgl_bindings.h", [t|Ptr () -> CInt -> CInt -> CInt -> CInt -> IO CUInt|]),+       ("c'rlLoadTextureDepth", "rlLoadTextureDepth_", "rlgl_bindings.h", [t|CInt -> CInt -> CBool -> IO CUInt|]),+       ("c'rlLoadTextureCubemap", "rlLoadTextureCubemap_", "rlgl_bindings.h", [t|Ptr () -> CInt -> CInt -> IO CUInt|]),+       ("c'rlUpdateTexture", "rlUpdateTexture_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> CInt -> CInt -> CInt -> Ptr () -> IO ()|]),+       ("c'rlGetGlTextureFormats", "rlGetGlTextureFormats_", "rlgl_bindings.h", [t|CInt -> Ptr CUInt -> Ptr CUInt -> Ptr CUInt -> IO ()|]),+       ("c'rlGetPixelFormatName", "rlGetPixelFormatName_", "rlgl_bindings.h", [t|CUInt -> IO CString|]),+       ("c'rlUnloadTexture", "rlUnloadTexture_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlGenTextureMipmaps", "rlGenTextureMipmaps_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> CInt -> Ptr CInt -> IO ()|]),+       ("c'rlReadTexturePixels", "rlReadTexturePixels_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> CInt -> IO (Ptr ())|]),+       ("c'rlReadScreenPixels", "rlReadScreenPixels_", "rlgl_bindings.h", [t|CInt -> CInt -> IO (Ptr CUChar)|]),+       ("c'rlLoadFramebuffer", "rlLoadFramebuffer_", "rlgl_bindings.h", [t|IO CUInt|]),+       ("c'rlFramebufferAttach", "rlFramebufferAttach_", "rlgl_bindings.h", [t|CUInt -> CUInt -> CInt -> CInt -> CInt -> IO ()|]),+       ("c'rlFramebufferComplete", "rlFramebufferComplete_", "rlgl_bindings.h", [t|CUInt -> IO CBool|]),+       ("c'rlUnloadFramebuffer", "rlUnloadFramebuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlLoadShaderCode", "rlLoadShaderCode_", "rlgl_bindings.h", [t|CString -> CString -> IO CUInt|]),+       ("c'rlCompileShader", "rlCompileShader_", "rlgl_bindings.h", [t|CString -> CInt -> IO CUInt|]),+       ("c'rlLoadShaderProgram", "rlLoadShaderProgram_", "rlgl_bindings.h", [t|CUInt -> CUInt -> IO CUInt|]),+       ("c'rlUnloadShaderProgram", "rlUnloadShaderProgram_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlGetLocationUniform", "rlGetLocationUniform_", "rlgl_bindings.h", [t|CUInt -> CString -> IO CInt|]),+       ("c'rlGetLocationAttrib", "rlGetLocationAttrib_", "rlgl_bindings.h", [t|CUInt -> CString -> IO CInt|]),+       ("c'rlSetUniform", "rlSetUniform_", "rlgl_bindings.h", [t|CInt -> Ptr () -> CInt -> CInt -> IO ()|]),+       ("c'rlSetUniformMatrix", "rlSetUniformMatrix_", "rlgl_bindings.h", [t|CInt -> Ptr Matrix -> IO ()|]),+       ("c'rlSetUniformMatrices", "rlSetUniformMatrices_", "rlgl_bindings.h", [t|CInt -> Ptr Matrix -> CInt -> IO ()|]),+       ("c'rlSetUniformSampler", "rlSetUniformSampler_", "rlgl_bindings.h", [t|CInt -> CUInt -> IO ()|]),+       ("c'rlSetShader", "rlSetShader_", "rlgl_bindings.h", [t|CUInt -> Ptr CInt -> IO ()|]),+       ("c'rlLoadComputeShaderProgram", "rlLoadComputeShaderProgram_", "rlgl_bindings.h", [t|CUInt -> IO CUInt|]),+       ("c'rlComputeShaderDispatch", "rlComputeShaderDispatch_", "rlgl_bindings.h", [t|CUInt -> CUInt -> CUInt -> IO ()|]),+       ("c'rlLoadShaderBuffer", "rlLoadShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CInt -> IO CUInt|]),+       ("c'rlUnloadShaderBuffer", "rlUnloadShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|]),+       ("c'rlUpdateShaderBuffer", "rlUpdateShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CUInt -> CUInt -> IO ()|]),+       ("c'rlBindShaderBuffer", "rlBindShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> CUInt -> IO ()|]),+       ("c'rlReadShaderBuffer", "rlReadShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CUInt -> CUInt -> IO ()|]),+       ("c'rlCopyShaderBuffer", "rlCopyShaderBuffer_", "rlgl_bindings.h", [t|CUInt -> CUInt -> CUInt -> CUInt -> CUInt -> IO ()|]),+       ("c'rlGetShaderBufferSize", "rlGetShaderBufferSize_", "rlgl_bindings.h", [t|CUInt -> IO CUInt|]),+       ("c'rlBindImageTexture", "rlBindImageTexture_", "rlgl_bindings.h", [t|CUInt -> CUInt -> CInt -> CBool -> IO ()|]),+       ("c'rlGetMatrixModelview", "rlGetMatrixModelview_", "rlgl_bindings.h", [t|IO (Ptr Matrix)|]),+       ("c'rlGetMatrixProjection", "rlGetMatrixProjection_", "rlgl_bindings.h", [t|IO (Ptr Matrix)|]),+       ("c'rlGetMatrixTransform", "rlGetMatrixTransform_", "rlgl_bindings.h", [t|IO (Ptr Matrix)|]),+       ("c'rlGetMatrixProjectionStereo", "rlGetMatrixProjectionStereo_", "rlgl_bindings.h", [t|CInt -> IO (Ptr Matrix)|]),+       ("c'rlGetMatrixViewOffsetStereo", "rlGetMatrixViewOffsetStereo_", "rlgl_bindings.h", [t|CInt -> IO (Ptr Matrix)|]),+       ("c'rlSetMatrixProjection", "rlSetMatrixProjection_", "rlgl_bindings.h", [t|Ptr Matrix -> IO ()|]),+       ("c'rlSetMatrixModelview", "rlSetMatrixModelview_", "rlgl_bindings.h", [t|Ptr Matrix -> IO ()|]),+       ("c'rlSetMatrixProjectionStereo", "rlSetMatrixProjectionStereo_", "rlgl_bindings.h", [t|Ptr Matrix -> Ptr Matrix -> IO ()|]),+       ("c'rlSetMatrixViewOffsetStereo", "rlSetMatrixViewOffsetStereo_", "rlgl_bindings.h", [t|Ptr Matrix -> Ptr Matrix -> IO ()|]),+       ("c'rlGetPixelDataSize", "rlGetPixelDataSize", "rl_internal.h", [t|CInt -> CInt -> CInt -> IO CInt|]),+       ("c'rlPushMatrix", "rlPushMatrix_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlPopMatrix", "rlPopMatrix_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlLoadIdentity", "rlLoadIdentity_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlEnd", "rlEnd_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableVertexArray", "rlDisableVertexArray_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableVertexBuffer", "rlDisableVertexBuffer_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableVertexBufferElement", "rlDisableVertexBufferElement_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableTexture", "rlDisableTexture_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableTextureCubemap", "rlDisableTextureCubemap_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableShader", "rlDisableShader_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableFramebuffer", "rlDisableFramebuffer_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlGetActiveFramebuffer", "rlGetActiveFramebuffer_", "rlgl_bindings.h", [t|IO CUInt|]),+       ("c'rlEnableColorBlend", "rlEnableColorBlend_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableColorBlend", "rlDisableColorBlend_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlEnableDepthTest", "rlEnableDepthTest_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableDepthTest", "rlDisableDepthTest_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlEnableDepthMask", "rlEnableDepthMask_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableDepthMask", "rlDisableDepthMask_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlEnableBackfaceCulling", "rlEnableBackfaceCulling_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableBackfaceCulling", "rlDisableBackfaceCulling_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlEnableScissorTest", "rlEnableScissorTest_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableScissorTest", "rlDisableScissorTest_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlEnableWireMode", "rlEnableWireMode_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlEnablePointMode", "rlEnablePointMode_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableWireMode", "rlDisableWireMode_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlEnableSmoothLines", "rlEnableSmoothLines_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableSmoothLines", "rlDisableSmoothLines_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlEnableStereoRender", "rlEnableStereoRender_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDisableStereoRender", "rlDisableStereoRender_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlClearScreenBuffers", "rlClearScreenBuffers_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlCheckErrors", "rlCheckErrors_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlglClose", "rlglClose_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlDrawRenderBatchActive", "rlDrawRenderBatchActive_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlLoadDrawCube", "rlLoadDrawCube_", "rlgl_bindings.h", [t|IO ()|]),+       ("c'rlLoadDrawQuad", "rlLoadDrawQuad_", "rlgl_bindings.h", [t|IO ()|])      ]  ) @@ -1191,6 +1194,10 @@ -- | Set shader value matrix rlSetUniformMatrix :: Int -> Matrix -> IO () rlSetUniformMatrix locIndex mat = withFreeable mat (c'rlSetUniformMatrix (fromIntegral locIndex))++-- | Set shader value matrices+rlSetUniformMatrices :: Int -> [Matrix] -> IO ()+rlSetUniformMatrices locIndex mats = withFreeableArrayLen mats (\c m -> c'rlSetUniformMatrices (fromIntegral locIndex) m (fromIntegral c))  -- | Set shader value sampler rlSetUniformSampler :: Int -> Integer -> IO ()