Update C sources
This commit is contained in:
parent
9d258bad65
commit
c1525b67af
68 changed files with 34056 additions and 25957 deletions
1618
raylib/external/cgltf.h
vendored
1618
raylib/external/cgltf.h
vendored
File diff suppressed because it is too large
Load diff
8530
raylib/external/dr_flac.h
vendored
8530
raylib/external/dr_flac.h
vendored
File diff suppressed because it is too large
Load diff
2453
raylib/external/dr_mp3.h
vendored
2453
raylib/external/dr_mp3.h
vendored
File diff suppressed because it is too large
Load diff
1048
raylib/external/dr_wav.h
vendored
1048
raylib/external/dr_wav.h
vendored
File diff suppressed because it is too large
Load diff
171
raylib/external/glfw/include/GLFW/glfw3.h
vendored
171
raylib/external/glfw/include/GLFW/glfw3.h
vendored
|
@ -52,7 +52,7 @@ extern "C" {
|
|||
* This is the reference documentation for OpenGL and OpenGL ES context related
|
||||
* functions. For more task-oriented information, see the @ref context_guide.
|
||||
*/
|
||||
/*! @defgroup vulkan Vulkan reference
|
||||
/*! @defgroup vulkan Vulkan support reference
|
||||
* @brief Functions and types related to Vulkan.
|
||||
*
|
||||
* This is the reference documentation for Vulkan related functions and types.
|
||||
|
@ -193,7 +193,38 @@ extern "C" {
|
|||
|
||||
#endif /*__APPLE__*/
|
||||
|
||||
#elif !defined(GLFW_INCLUDE_NONE)
|
||||
#elif defined(GLFW_INCLUDE_GLU)
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#if defined(GLFW_INCLUDE_GLU)
|
||||
#include <OpenGL/glu.h>
|
||||
#endif
|
||||
|
||||
#else /*__APPLE__*/
|
||||
|
||||
#if defined(GLFW_INCLUDE_GLU)
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#endif /*__APPLE__*/
|
||||
|
||||
#elif !defined(GLFW_INCLUDE_NONE) && \
|
||||
!defined(__gl_h_) && \
|
||||
!defined(__gles1_gl_h_) && \
|
||||
!defined(__gles2_gl2_h_) && \
|
||||
!defined(__gles2_gl3_h_) && \
|
||||
!defined(__gles2_gl31_h_) && \
|
||||
!defined(__gles2_gl32_h_) && \
|
||||
!defined(__gl_glcorearb_h_) && \
|
||||
!defined(__gl2_h_) /*legacy*/ && \
|
||||
!defined(__gl3_h_) /*legacy*/ && \
|
||||
!defined(__gl31_h_) /*legacy*/ && \
|
||||
!defined(__gl32_h_) /*legacy*/ && \
|
||||
!defined(__glcorearb_h_) /*legacy*/ && \
|
||||
!defined(__GL_H__) /*non-standard*/ && \
|
||||
!defined(__gltypes_h_) /*non-standard*/ && \
|
||||
!defined(__glee_h_) /*non-standard*/
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
|
@ -201,9 +232,6 @@ extern "C" {
|
|||
#define GL_GLEXT_LEGACY
|
||||
#endif
|
||||
#include <OpenGL/gl.h>
|
||||
#if defined(GLFW_INCLUDE_GLU)
|
||||
#include <OpenGL/glu.h>
|
||||
#endif
|
||||
|
||||
#else /*__APPLE__*/
|
||||
|
||||
|
@ -211,9 +239,6 @@ extern "C" {
|
|||
#if defined(GLFW_INCLUDE_GLEXT)
|
||||
#include <GL/glext.h>
|
||||
#endif
|
||||
#if defined(GLFW_INCLUDE_GLU)
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#endif /*__APPLE__*/
|
||||
|
||||
|
@ -768,6 +793,33 @@ extern "C" {
|
|||
* [custom cursor](@ref cursor_custom).
|
||||
*/
|
||||
#define GLFW_CURSOR_UNAVAILABLE 0x0001000B
|
||||
/*! @brief The requested feature is not provided by the platform.
|
||||
*
|
||||
* The requested feature is not provided by the platform, so GLFW is unable to
|
||||
* implement it. The documentation for each function notes if it could emit
|
||||
* this error.
|
||||
*
|
||||
* @analysis Platform or platform version limitation. The error can be ignored
|
||||
* unless the feature is critical to the application.
|
||||
*
|
||||
* @par
|
||||
* A function call that emits this error has no effect other than the error and
|
||||
* updating any existing out parameters.
|
||||
*/
|
||||
#define GLFW_FEATURE_UNAVAILABLE 0x0001000C
|
||||
/*! @brief The requested feature is not implemented for the platform.
|
||||
*
|
||||
* The requested feature has not yet been implemented in GLFW for this platform.
|
||||
*
|
||||
* @analysis An incomplete implementation of GLFW for this platform, hopefully
|
||||
* fixed in a future release. The error can be ignored unless the feature is
|
||||
* critical to the application.
|
||||
*
|
||||
* @par
|
||||
* A function call that emits this error has no effect other than the error and
|
||||
* updating any existing out parameters.
|
||||
*/
|
||||
#define GLFW_FEATURE_UNIMPLEMENTED 0x0001000D
|
||||
/*! @} */
|
||||
|
||||
/*! @addtogroup window
|
||||
|
@ -843,6 +895,13 @@ extern "C" {
|
|||
*/
|
||||
#define GLFW_FOCUS_ON_SHOW 0x0002000C
|
||||
|
||||
/*! @brief Mouse input transparency window hint and attribute
|
||||
*
|
||||
* Mouse input transparency [window hint](@ref GLFW_MOUSE_PASSTHROUGH_hint) or
|
||||
* [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib).
|
||||
*/
|
||||
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D
|
||||
|
||||
/*! @brief Framebuffer bit depth hint.
|
||||
*
|
||||
* Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
|
||||
|
@ -960,12 +1019,17 @@ extern "C" {
|
|||
* and [attribute](@ref GLFW_OPENGL_FORWARD_COMPAT_attrib).
|
||||
*/
|
||||
#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006
|
||||
/*! @brief OpenGL debug context hint and attribute.
|
||||
/*! @brief Debug mode context hint and attribute.
|
||||
*
|
||||
* OpenGL debug context [hint](@ref GLFW_OPENGL_DEBUG_CONTEXT_hint) and
|
||||
* [attribute](@ref GLFW_OPENGL_DEBUG_CONTEXT_attrib).
|
||||
* Debug mode context [hint](@ref GLFW_CONTEXT_DEBUG_hint) and
|
||||
* [attribute](@ref GLFW_CONTEXT_DEBUG_attrib).
|
||||
*/
|
||||
#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007
|
||||
#define GLFW_CONTEXT_DEBUG 0x00022007
|
||||
/*! @brief Legacy name for compatibility.
|
||||
*
|
||||
* This is an alias for compatibility with earlier versions.
|
||||
*/
|
||||
#define GLFW_OPENGL_DEBUG_CONTEXT GLFW_CONTEXT_DEBUG
|
||||
/*! @brief OpenGL profile hint and attribute.
|
||||
*
|
||||
* OpenGL profile [hint](@ref GLFW_OPENGL_PROFILE_hint) and
|
||||
|
@ -1047,6 +1111,14 @@ extern "C" {
|
|||
#define GLFW_EGL_CONTEXT_API 0x00036002
|
||||
#define GLFW_OSMESA_CONTEXT_API 0x00036003
|
||||
|
||||
#define GLFW_ANGLE_PLATFORM_TYPE_NONE 0x00037001
|
||||
#define GLFW_ANGLE_PLATFORM_TYPE_OPENGL 0x00037002
|
||||
#define GLFW_ANGLE_PLATFORM_TYPE_OPENGLES 0x00037003
|
||||
#define GLFW_ANGLE_PLATFORM_TYPE_D3D9 0x00037004
|
||||
#define GLFW_ANGLE_PLATFORM_TYPE_D3D11 0x00037005
|
||||
#define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007
|
||||
#define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008
|
||||
|
||||
/*! @defgroup shapes Standard cursor shapes
|
||||
* @brief Standard system cursor shapes.
|
||||
*
|
||||
|
@ -1163,6 +1235,11 @@ extern "C" {
|
|||
* Joystick hat buttons [init hint](@ref GLFW_JOYSTICK_HAT_BUTTONS).
|
||||
*/
|
||||
#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001
|
||||
/*! @brief ANGLE rendering backend init hint.
|
||||
*
|
||||
* ANGLE rendering backend [init hint](@ref GLFW_ANGLE_PLATFORM_TYPE_hint).
|
||||
*/
|
||||
#define GLFW_ANGLE_PLATFORM_TYPE 0x00050002
|
||||
/*! @brief macOS specific init hint.
|
||||
*
|
||||
* macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint).
|
||||
|
@ -1406,7 +1483,7 @@ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
|
|||
* @endcode
|
||||
*
|
||||
* @param[in] window The window that was maximized or restored.
|
||||
* @param[in] iconified `GLFW_TRUE` if the window was maximized, or
|
||||
* @param[in] maximized `GLFW_TRUE` if the window was maximized, or
|
||||
* `GLFW_FALSE` if it was restored.
|
||||
*
|
||||
* @sa @ref window_maximize
|
||||
|
@ -1831,6 +1908,18 @@ typedef struct GLFWgamepadstate
|
|||
* bundle, if present. This can be disabled with the @ref
|
||||
* GLFW_COCOA_CHDIR_RESOURCES init hint.
|
||||
*
|
||||
* @remark @macos This function will create the main menu and dock icon for the
|
||||
* application. If GLFW finds a `MainMenu.nib` it is loaded and assumed to
|
||||
* contain a menu bar. Otherwise a minimal menu bar is created manually with
|
||||
* common commands like Hide, Quit and About. The About entry opens a minimal
|
||||
* about dialog with information from the application's bundle. The menu bar
|
||||
* and dock icon can be disabled entirely with the @ref GLFW_COCOA_MENUBAR init
|
||||
* hint.
|
||||
*
|
||||
* @remark @x11 This function will set the `LC_CTYPE` category of the
|
||||
* application locale according to the current environment if that category is
|
||||
* still "C". This is because the "C" locale breaks Unicode text input.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref intro_init
|
||||
|
@ -1854,6 +1943,8 @@ GLFWAPI int glfwInit(void);
|
|||
* call this function, as it is called by @ref glfwInit before it returns
|
||||
* failure.
|
||||
*
|
||||
* This function has no effect if GLFW is not initialized.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark This function may be called before @ref glfwInit.
|
||||
|
@ -2670,13 +2761,6 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
|
|||
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
||||
* in the Mac Developer Library.
|
||||
*
|
||||
* @remark @macos The first time a window is created the menu bar is created.
|
||||
* If GLFW finds a `MainMenu.nib` it is loaded and assumed to contain a menu
|
||||
* bar. Otherwise a minimal menu bar is created manually with common commands
|
||||
* like Hide, Quit and About. The About entry opens a minimal about dialog
|
||||
* with information from the application's bundle. Menu bar creation can be
|
||||
* disabled entirely with the @ref GLFW_COCOA_MENUBAR init hint.
|
||||
*
|
||||
* @remark @macos On OS X 10.10 and later the window frame will not be rendered
|
||||
* at full resolution on Retina displays unless the
|
||||
* [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
|
||||
|
@ -2849,21 +2933,21 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
|
|||
* @param[in] images The images to create the icon from. This is ignored if
|
||||
* count is zero.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
*
|
||||
* @pointer_lifetime The specified image data is copied before this function
|
||||
* returns.
|
||||
*
|
||||
* @remark @macos The GLFW window has no icon, as it is not a document
|
||||
* window, so this function does nothing. The dock icon will be the same as
|
||||
* @remark @macos Regular windows do not have icons on macOS. This function
|
||||
* will emit @ref GLFW_FEATURE_UNAVAILABLE. The dock icon will be the same as
|
||||
* the application bundle's icon. For more information on bundles, see the
|
||||
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
||||
* in the Mac Developer Library.
|
||||
*
|
||||
* @remark @wayland There is no existing protocol to change an icon, the
|
||||
* window will thus inherit the one defined in the application's desktop file.
|
||||
* This function always emits @ref GLFW_PLATFORM_ERROR.
|
||||
* This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
|
@ -2889,12 +2973,12 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i
|
|||
* @param[out] ypos Where to store the y-coordinate of the upper-left corner of
|
||||
* the content area, or `NULL`.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
*
|
||||
* @remark @wayland There is no way for an application to retrieve the global
|
||||
* position of its windows, this function will always emit @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* position of its windows. This function will emit @ref
|
||||
* GLFW_FEATURE_UNAVAILABLE.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
|
@ -2923,12 +3007,12 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
|
|||
* @param[in] xpos The x-coordinate of the upper-left corner of the content area.
|
||||
* @param[in] ypos The y-coordinate of the upper-left corner of the content area.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
*
|
||||
* @remark @wayland There is no way for an application to set the global
|
||||
* position of its windows, this function will always emit @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* position of its windows. This function will emit @ref
|
||||
* GLFW_FEATURE_UNAVAILABLE.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
|
@ -3240,8 +3324,11 @@ GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window);
|
|||
* @param[in] window The window to set the opacity for.
|
||||
* @param[in] opacity The desired opacity of the specified window.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
*
|
||||
* @remark @wayland There is no way to set an opacity factor for a window.
|
||||
* This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
|
@ -3408,11 +3495,11 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
|
|||
*
|
||||
* @param[in] window The window to give input focus.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
*
|
||||
* @remark @wayland It is not possible for an application to bring its windows
|
||||
* to front, this function will always emit @ref GLFW_PLATFORM_ERROR.
|
||||
* @remark @wayland It is not possible for an application to set the input
|
||||
* focus. This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
|
@ -3576,6 +3663,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
|
|||
* [GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
|
||||
* [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
|
||||
* [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib).
|
||||
* [GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_attrib)
|
||||
*
|
||||
* Some of these attributes are ignored for full screen windows. The new
|
||||
* value will take effect if the window is later made windowed.
|
||||
|
@ -4164,7 +4252,7 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
|
|||
* If the mode is `GLFW_RAW_MOUSE_MOTION`, the value must be either `GLFW_TRUE`
|
||||
* to enable raw (unscaled and unaccelerated) mouse motion when the cursor is
|
||||
* disabled, or `GLFW_FALSE` to disable it. If raw motion is not supported,
|
||||
* attempting to set this will emit @ref GLFW_PLATFORM_ERROR. Call @ref
|
||||
* attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE. Call @ref
|
||||
* glfwRawMouseMotionSupported to check for support.
|
||||
*
|
||||
* @param[in] window The window whose input mode to set.
|
||||
|
@ -4174,7 +4262,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
|
|||
* @param[in] value The new value of the specified input mode.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
|
||||
* GLFW_INVALID_ENUM, @ref GLFW_PLATFORM_ERROR and @ref
|
||||
* GLFW_FEATURE_UNAVAILABLE (see above).
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
|
|
10
raylib/external/glfw/src/cocoa_init.m
vendored
10
raylib/external/glfw/src/cocoa_init.m
vendored
|
@ -447,7 +447,6 @@ static GLFWbool initializeTIS(void)
|
|||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||
{
|
||||
_glfw.ns.finishedLaunching = GLFW_TRUE;
|
||||
_glfwPlatformPostEmptyEvent();
|
||||
[NSApp stop:nil];
|
||||
}
|
||||
|
@ -503,9 +502,6 @@ int _glfwPlatformInit(void)
|
|||
toTarget:_glfw.ns.helper
|
||||
withObject:nil];
|
||||
|
||||
if (NSApp)
|
||||
_glfw.ns.finishedLaunching = GLFW_TRUE;
|
||||
|
||||
[NSApplication sharedApplication];
|
||||
|
||||
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
|
||||
|
@ -555,9 +551,12 @@ int _glfwPlatformInit(void)
|
|||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitTimerNS();
|
||||
_glfwInitJoysticksNS();
|
||||
|
||||
_glfwPollMonitorsNS();
|
||||
|
||||
if (![[NSRunningApplication currentApplication] isFinishedLaunching])
|
||||
[NSApp run];
|
||||
|
||||
return GLFW_TRUE;
|
||||
|
||||
} // autoreleasepool
|
||||
|
@ -605,7 +604,6 @@ void _glfwPlatformTerminate(void)
|
|||
free(_glfw.ns.clipboardString);
|
||||
|
||||
_glfwTerminateNSGL();
|
||||
_glfwTerminateJoysticksNS();
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
|
4
raylib/external/glfw/src/cocoa_joystick.h
vendored
4
raylib/external/glfw/src/cocoa_joystick.h
vendored
|
@ -44,7 +44,3 @@ typedef struct _GLFWjoystickNS
|
|||
CFMutableArrayRef hats;
|
||||
} _GLFWjoystickNS;
|
||||
|
||||
|
||||
void _glfwInitJoysticksNS(void);
|
||||
void _glfwTerminateJoysticksNS(void);
|
||||
|
||||
|
|
24
raylib/external/glfw/src/cocoa_joystick.m
vendored
24
raylib/external/glfw/src/cocoa_joystick.m
vendored
|
@ -304,12 +304,10 @@ static void removeCallback(void* context,
|
|||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Initialize joystick interface
|
||||
//
|
||||
void _glfwInitJoysticksNS(void)
|
||||
GLFWbool _glfwPlatformInitJoysticks(void)
|
||||
{
|
||||
CFMutableArrayRef matching;
|
||||
const long usages[] =
|
||||
|
@ -328,7 +326,7 @@ void _glfwInitJoysticksNS(void)
|
|||
if (!matching)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array");
|
||||
return;
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(usages) / sizeof(long); i++)
|
||||
|
@ -383,26 +381,24 @@ void _glfwInitJoysticksNS(void)
|
|||
// Execute the run loop once in order to register any initially-attached
|
||||
// joysticks
|
||||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Close all opened joystick handles
|
||||
//
|
||||
void _glfwTerminateJoysticksNS(void)
|
||||
void _glfwPlatformTerminateJoysticks(void)
|
||||
{
|
||||
int jid;
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
|
||||
CFRelease(_glfw.ns.hidManager);
|
||||
_glfw.ns.hidManager = NULL;
|
||||
if (_glfw.ns.hidManager)
|
||||
{
|
||||
CFRelease(_glfw.ns.hidManager);
|
||||
_glfw.ns.hidManager = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
if (mode & _GLFW_POLL_AXES)
|
||||
|
|
18
raylib/external/glfw/src/cocoa_monitor.m
vendored
18
raylib/external/glfw/src/cocoa_monitor.m
vendored
|
@ -277,14 +277,20 @@ static double getFallbackRefreshRate(CGDirectDisplayID displayID)
|
|||
CFSTR("IOFBCurrentPixelCount"),
|
||||
kCFAllocatorDefault,
|
||||
kNilOptions);
|
||||
if (!clockRef || !countRef)
|
||||
break;
|
||||
|
||||
uint32_t clock = 0, count = 0;
|
||||
CFNumberGetValue(clockRef, kCFNumberIntType, &clock);
|
||||
CFNumberGetValue(countRef, kCFNumberIntType, &count);
|
||||
CFRelease(clockRef);
|
||||
CFRelease(countRef);
|
||||
|
||||
if (clockRef)
|
||||
{
|
||||
CFNumberGetValue(clockRef, kCFNumberIntType, &clock);
|
||||
CFRelease(clockRef);
|
||||
}
|
||||
|
||||
if (countRef)
|
||||
{
|
||||
CFNumberGetValue(countRef, kCFNumberIntType, &count);
|
||||
CFRelease(countRef);
|
||||
}
|
||||
|
||||
if (clock > 0 && count > 0)
|
||||
refreshRate = clock / (double) count;
|
||||
|
|
7
raylib/external/glfw/src/cocoa_platform.h
vendored
7
raylib/external/glfw/src/cocoa_platform.h
vendored
|
@ -85,16 +85,11 @@ typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMeta
|
|||
#include "posix_thread.h"
|
||||
#include "cocoa_joystick.h"
|
||||
#include "nsgl_context.h"
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->ns.view)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerNS ns
|
||||
|
@ -121,6 +116,7 @@ typedef struct _GLFWwindowNS
|
|||
id layer;
|
||||
|
||||
GLFWbool maximized;
|
||||
GLFWbool occluded;
|
||||
GLFWbool retina;
|
||||
|
||||
// Cached window properties to filter out duplicate events
|
||||
|
@ -141,7 +137,6 @@ typedef struct _GLFWlibraryNS
|
|||
{
|
||||
CGEventSourceRef eventSource;
|
||||
id delegate;
|
||||
GLFWbool finishedLaunching;
|
||||
GLFWbool cursorHidden;
|
||||
TISInputSourceRef inputSource;
|
||||
IOHIDManagerRef hidManager;
|
||||
|
|
103
raylib/external/glfw/src/cocoa_window.m
vendored
103
raylib/external/glfw/src/cocoa_window.m
vendored
|
@ -322,6 +322,14 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||
}
|
||||
|
||||
- (void)windowDidChangeOcclusionState:(NSNotification* )notification
|
||||
{
|
||||
if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
|
||||
window->ns.occluded = GLFW_FALSE;
|
||||
else
|
||||
window->ns.occluded = GLFW_TRUE;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -723,14 +731,24 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||
else
|
||||
characters = (NSString*) string;
|
||||
|
||||
const NSUInteger length = [characters length];
|
||||
for (NSUInteger i = 0; i < length; i++)
|
||||
NSRange range = NSMakeRange(0, [characters length]);
|
||||
while (range.length)
|
||||
{
|
||||
const unichar codepoint = [characters characterAtIndex:i];
|
||||
if ((codepoint & 0xff00) == 0xf700)
|
||||
continue;
|
||||
uint32_t codepoint = 0;
|
||||
|
||||
_glfwInputChar(window, codepoint, mods, plain);
|
||||
if ([characters getBytes:&codepoint
|
||||
maxLength:sizeof(codepoint)
|
||||
usedLength:NULL
|
||||
encoding:NSUTF32StringEncoding
|
||||
options:0
|
||||
range:range
|
||||
remainingRange:&range])
|
||||
{
|
||||
if (codepoint >= 0xf700 && codepoint <= 0xf7ff)
|
||||
continue;
|
||||
|
||||
_glfwInputChar(window, codepoint, mods, plain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -884,9 +902,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (!_glfw.ns.finishedLaunching)
|
||||
[NSApp run];
|
||||
|
||||
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
|
@ -901,6 +916,11 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||
}
|
||||
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||
{
|
||||
// EGL implementation on macOS use CALayer* EGLNativeWindowType so we
|
||||
// need to get the layer for EGL window surface creation.
|
||||
[window->ns.view setWantsLayer:YES];
|
||||
window->ns.layer = [window->ns.view layer];
|
||||
|
||||
if (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
|
@ -972,7 +992,8 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
|||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
int count, const GLFWimage* images)
|
||||
{
|
||||
// Regular windows do not have icons
|
||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||
"Cocoa: Regular windows do not have icons on macOS");
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
|
@ -1350,6 +1371,13 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
|||
} // autoreleasepool
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
@autoreleasepool {
|
||||
[window->ns.object setIgnoresMouseEvents:enabled];
|
||||
}
|
||||
}
|
||||
|
||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
@ -1366,6 +1394,8 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
|||
|
||||
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
|
||||
{
|
||||
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||
"Cocoa: Raw mouse motion not yet implemented");
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformRawMouseMotionSupported(void)
|
||||
|
@ -1377,9 +1407,6 @@ void _glfwPlatformPollEvents(void)
|
|||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (!_glfw.ns.finishedLaunching)
|
||||
[NSApp run];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
|
@ -1399,9 +1426,6 @@ void _glfwPlatformWaitEvents(void)
|
|||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (!_glfw.ns.finishedLaunching)
|
||||
[NSApp run];
|
||||
|
||||
// I wanted to pass NO to dequeue:, and rely on PollEvents to
|
||||
// dequeue and send. For reasons not at all clear to me, passing
|
||||
// NO to dequeue: causes this method never to return.
|
||||
|
@ -1420,9 +1444,6 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
|||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (!_glfw.ns.finishedLaunching)
|
||||
[NSApp run];
|
||||
|
||||
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
untilDate:date
|
||||
|
@ -1440,9 +1461,6 @@ void _glfwPlatformPostEmptyEvent(void)
|
|||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (!_glfw.ns.finishedLaunching)
|
||||
[NSApp run];
|
||||
|
||||
NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
|
||||
location:NSMakePoint(0, 0)
|
||||
modifierFlags:0
|
||||
|
@ -1720,6 +1738,47 @@ const char* _glfwPlatformGetClipboardString(void)
|
|||
} // autoreleasepool
|
||||
}
|
||||
|
||||
EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs)
|
||||
{
|
||||
if (_glfw.egl.ANGLE_platform_angle)
|
||||
{
|
||||
int type = 0;
|
||||
|
||||
if (_glfw.egl.ANGLE_platform_angle_opengl)
|
||||
{
|
||||
if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_OPENGL)
|
||||
type = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
|
||||
}
|
||||
|
||||
if (_glfw.egl.ANGLE_platform_angle_metal)
|
||||
{
|
||||
if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_METAL)
|
||||
type = EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
|
||||
}
|
||||
|
||||
if (type)
|
||||
{
|
||||
*attribs = calloc(3, sizeof(EGLint));
|
||||
(*attribs)[0] = EGL_PLATFORM_ANGLE_TYPE_ANGLE;
|
||||
(*attribs)[1] = type;
|
||||
(*attribs)[2] = EGL_NONE;
|
||||
return EGL_PLATFORM_ANGLE_ANGLE;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void)
|
||||
{
|
||||
return EGL_DEFAULT_DISPLAY;
|
||||
}
|
||||
|
||||
EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window)
|
||||
{
|
||||
return window->ns.layer;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
if (_glfw.vk.KHR_surface && _glfw.vk.EXT_metal_surface)
|
||||
|
|
84
raylib/external/glfw/src/egl_context.c
vendored
84
raylib/external/glfw/src/egl_context.c
vendored
|
@ -303,6 +303,8 @@ static void destroyContextEGL(_GLFWwindow* window)
|
|||
GLFWbool _glfwInitEGL(void)
|
||||
{
|
||||
int i;
|
||||
EGLint* attribs = NULL;
|
||||
const char* extensions;
|
||||
const char* sonames[] =
|
||||
{
|
||||
#if defined(_GLFW_EGL_LIBRARY)
|
||||
|
@ -395,7 +397,51 @@ GLFWbool _glfwInitEGL(void)
|
|||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
|
||||
extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
||||
if (extensions && eglGetError() == EGL_SUCCESS)
|
||||
_glfw.egl.EXT_client_extensions = GLFW_TRUE;
|
||||
|
||||
if (_glfw.egl.EXT_client_extensions)
|
||||
{
|
||||
_glfw.egl.EXT_platform_base =
|
||||
_glfwStringInExtensionString("EGL_EXT_platform_base", extensions);
|
||||
_glfw.egl.EXT_platform_x11 =
|
||||
_glfwStringInExtensionString("EGL_EXT_platform_x11", extensions);
|
||||
_glfw.egl.EXT_platform_wayland =
|
||||
_glfwStringInExtensionString("EGL_EXT_platform_wayland", extensions);
|
||||
_glfw.egl.ANGLE_platform_angle =
|
||||
_glfwStringInExtensionString("EGL_ANGLE_platform_angle", extensions);
|
||||
_glfw.egl.ANGLE_platform_angle_opengl =
|
||||
_glfwStringInExtensionString("EGL_ANGLE_platform_angle_opengl", extensions);
|
||||
_glfw.egl.ANGLE_platform_angle_d3d =
|
||||
_glfwStringInExtensionString("EGL_ANGLE_platform_angle_d3d", extensions);
|
||||
_glfw.egl.ANGLE_platform_angle_vulkan =
|
||||
_glfwStringInExtensionString("EGL_ANGLE_platform_angle_vulkan", extensions);
|
||||
_glfw.egl.ANGLE_platform_angle_metal =
|
||||
_glfwStringInExtensionString("EGL_ANGLE_platform_angle_metal", extensions);
|
||||
}
|
||||
|
||||
if (_glfw.egl.EXT_platform_base)
|
||||
{
|
||||
_glfw.egl.GetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)
|
||||
eglGetProcAddress("eglGetPlatformDisplayEXT");
|
||||
_glfw.egl.CreatePlatformWindowSurfaceEXT = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)
|
||||
eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
|
||||
}
|
||||
|
||||
_glfw.egl.platform = _glfwPlatformGetEGLPlatform(&attribs);
|
||||
if (_glfw.egl.platform)
|
||||
{
|
||||
_glfw.egl.display =
|
||||
eglGetPlatformDisplayEXT(_glfw.egl.platform,
|
||||
_glfwPlatformGetEGLNativeDisplay(),
|
||||
attribs);
|
||||
}
|
||||
else
|
||||
_glfw.egl.display = eglGetDisplay(_glfwPlatformGetEGLNativeDisplay());
|
||||
|
||||
free(attribs);
|
||||
|
||||
if (_glfw.egl.display == EGL_NO_DISPLAY)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
|
@ -463,6 +509,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
EGLint attribs[40];
|
||||
EGLConfig config;
|
||||
EGLContext share = NULL;
|
||||
EGLNativeWindowType native;
|
||||
int index = 0;
|
||||
|
||||
if (!_glfw.egl.display)
|
||||
|
@ -588,23 +635,30 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
}
|
||||
|
||||
// Set up attributes for surface creation
|
||||
index = 0;
|
||||
|
||||
if (fbconfig->sRGB)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (fbconfig->sRGB)
|
||||
{
|
||||
if (_glfw.egl.KHR_gl_colorspace)
|
||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
if (_glfw.egl.KHR_gl_colorspace)
|
||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
|
||||
native = _glfwPlatformGetEGLNativeWindow(window);
|
||||
// HACK: ANGLE does not implement eglCreatePlatformWindowSurfaceEXT
|
||||
// despite reporting EGL_EXT_platform_base
|
||||
if (_glfw.egl.platform && _glfw.egl.platform != EGL_PLATFORM_ANGLE_ANGLE)
|
||||
{
|
||||
window->context.egl.surface =
|
||||
eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, config, native, attribs);
|
||||
}
|
||||
else
|
||||
{
|
||||
window->context.egl.surface =
|
||||
eglCreateWindowSurface(_glfw.egl.display, config, native, attribs);
|
||||
}
|
||||
|
||||
window->context.egl.surface =
|
||||
eglCreateWindowSurface(_glfw.egl.display,
|
||||
config,
|
||||
_GLFW_EGL_NATIVE_WINDOW,
|
||||
attribs);
|
||||
if (window->context.egl.surface == EGL_NO_SURFACE)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
|
|
54
raylib/external/glfw/src/egl_context.h
vendored
54
raylib/external/glfw/src/egl_context.h
vendored
|
@ -25,26 +25,10 @@
|
|||
//
|
||||
//========================================================================
|
||||
|
||||
#if defined(_GLFW_USE_EGLPLATFORM_H)
|
||||
#include <EGL/eglplatform.h>
|
||||
#elif defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_WIN32)
|
||||
#define EGLAPIENTRY __stdcall
|
||||
typedef HDC EGLNativeDisplayType;
|
||||
typedef HWND EGLNativeWindowType;
|
||||
#elif defined(_GLFW_COCOA)
|
||||
#define EGLAPIENTRY
|
||||
typedef void* EGLNativeDisplayType;
|
||||
typedef id EGLNativeWindowType;
|
||||
#elif defined(_GLFW_X11)
|
||||
#define EGLAPIENTRY
|
||||
typedef Display* EGLNativeDisplayType;
|
||||
typedef Window EGLNativeWindowType;
|
||||
#elif defined(_GLFW_WAYLAND)
|
||||
#define EGLAPIENTRY
|
||||
typedef struct wl_display* EGLNativeDisplayType;
|
||||
typedef struct wl_egl_window* EGLNativeWindowType;
|
||||
#else
|
||||
#error "No supported EGL platform selected"
|
||||
#define EGLAPIENTRY
|
||||
#endif
|
||||
|
||||
#define EGL_SUCCESS 0x3000
|
||||
|
@ -106,6 +90,17 @@ typedef struct wl_egl_window* EGLNativeWindowType;
|
|||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
|
||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
|
||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
|
||||
#define EGL_PLATFORM_X11_EXT 0x31d5
|
||||
#define EGL_PLATFORM_WAYLAND_EXT 0x31d8
|
||||
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320d
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320e
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489
|
||||
#define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348f
|
||||
|
||||
typedef int EGLint;
|
||||
typedef unsigned int EGLBoolean;
|
||||
|
@ -115,6 +110,9 @@ typedef void* EGLContext;
|
|||
typedef void* EGLDisplay;
|
||||
typedef void* EGLSurface;
|
||||
|
||||
typedef void* EGLNativeDisplayType;
|
||||
typedef void* EGLNativeWindowType;
|
||||
|
||||
// EGL function pointer typedefs
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
|
||||
|
@ -149,9 +147,10 @@ typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
|
|||
#define eglQueryString _glfw.egl.QueryString
|
||||
#define eglGetProcAddress _glfw.egl.GetProcAddress
|
||||
|
||||
#define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl
|
||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl
|
||||
|
||||
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*);
|
||||
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)(EGLDisplay,EGLConfig,void*,const EGLint*);
|
||||
#define eglGetPlatformDisplayEXT _glfw.egl.GetPlatformDisplayEXT
|
||||
#define eglCreatePlatformWindowSurfaceEXT _glfw.egl.CreatePlatformWindowSurfaceEXT
|
||||
|
||||
// EGL-specific per-context data
|
||||
//
|
||||
|
@ -169,6 +168,7 @@ typedef struct _GLFWcontextEGL
|
|||
//
|
||||
typedef struct _GLFWlibraryEGL
|
||||
{
|
||||
EGLenum platform;
|
||||
EGLDisplay display;
|
||||
EGLint major, minor;
|
||||
GLFWbool prefix;
|
||||
|
@ -178,6 +178,15 @@ typedef struct _GLFWlibraryEGL
|
|||
GLFWbool KHR_gl_colorspace;
|
||||
GLFWbool KHR_get_all_proc_addresses;
|
||||
GLFWbool KHR_context_flush_control;
|
||||
GLFWbool EXT_client_extensions;
|
||||
GLFWbool EXT_platform_base;
|
||||
GLFWbool EXT_platform_x11;
|
||||
GLFWbool EXT_platform_wayland;
|
||||
GLFWbool ANGLE_platform_angle;
|
||||
GLFWbool ANGLE_platform_angle_opengl;
|
||||
GLFWbool ANGLE_platform_angle_d3d;
|
||||
GLFWbool ANGLE_platform_angle_vulkan;
|
||||
GLFWbool ANGLE_platform_angle_metal;
|
||||
|
||||
void* handle;
|
||||
|
||||
|
@ -198,6 +207,9 @@ typedef struct _GLFWlibraryEGL
|
|||
PFN_eglQueryString QueryString;
|
||||
PFN_eglGetProcAddress GetProcAddress;
|
||||
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT;
|
||||
PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC CreatePlatformWindowSurfaceEXT;
|
||||
|
||||
} _GLFWlibraryEGL;
|
||||
|
||||
|
||||
|
|
9
raylib/external/glfw/src/init.c
vendored
9
raylib/external/glfw/src/init.c
vendored
|
@ -53,6 +53,7 @@ static GLFWerrorfun _glfwErrorCallback;
|
|||
static _GLFWinitconfig _glfwInitHints =
|
||||
{
|
||||
GLFW_TRUE, // hat buttons
|
||||
GLFW_ANGLE_PLATFORM_TYPE_NONE, // ANGLE backend
|
||||
{
|
||||
GLFW_TRUE, // macOS menu bar
|
||||
GLFW_TRUE // macOS bundle chdir
|
||||
|
@ -90,6 +91,7 @@ static void terminate(void)
|
|||
_glfw.mappingCount = 0;
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
_glfwPlatformTerminateJoysticks();
|
||||
_glfwPlatformTerminate();
|
||||
|
||||
_glfw.initialized = GLFW_FALSE;
|
||||
|
@ -191,6 +193,10 @@ void _glfwInputError(int code, const char* format, ...)
|
|||
strcpy(description, "The specified window has no context");
|
||||
else if (code == GLFW_CURSOR_UNAVAILABLE)
|
||||
strcpy(description, "The specified cursor shape is unavailable");
|
||||
else if (code == GLFW_FEATURE_UNAVAILABLE)
|
||||
strcpy(description, "The requested feature cannot be implemented for this platform");
|
||||
else if (code == GLFW_FEATURE_UNIMPLEMENTED)
|
||||
strcpy(description, "The requested feature has not yet been implemented for this platform");
|
||||
else
|
||||
strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
|
||||
}
|
||||
|
@ -283,6 +289,9 @@ GLFWAPI void glfwInitHint(int hint, int value)
|
|||
case GLFW_JOYSTICK_HAT_BUTTONS:
|
||||
_glfwInitHints.hatButtons = value;
|
||||
return;
|
||||
case GLFW_ANGLE_PLATFORM_TYPE:
|
||||
_glfwInitHints.angleType = value;
|
||||
return;
|
||||
case GLFW_COCOA_CHDIR_RESOURCES:
|
||||
_glfwInitHints.ns.chdir = value;
|
||||
return;
|
||||
|
|
47
raylib/external/glfw/src/input.c
vendored
47
raylib/external/glfw/src/input.c
vendored
|
@ -43,6 +43,22 @@
|
|||
#define _GLFW_JOYSTICK_BUTTON 2
|
||||
#define _GLFW_JOYSTICK_HATBIT 3
|
||||
|
||||
// Initializes the platform joystick API if it has not been already
|
||||
//
|
||||
static GLFWbool initJoysticks(void)
|
||||
{
|
||||
if (!_glfw.joysticksInitialized)
|
||||
{
|
||||
if (!_glfwPlatformInitJoysticks())
|
||||
{
|
||||
_glfwPlatformTerminateJoysticks();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return _glfw.joysticksInitialized = GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Finds a mapping based on joystick GUID
|
||||
//
|
||||
static _GLFWmapping* findMapping(const char* guid)
|
||||
|
@ -929,6 +945,9 @@ GLFWAPI int glfwJoystickPresent(int jid)
|
|||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!initJoysticks())
|
||||
return GLFW_FALSE;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
@ -954,6 +973,9 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!initJoysticks())
|
||||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
@ -983,6 +1005,9 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!initJoysticks())
|
||||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
@ -1016,6 +1041,9 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!initJoysticks())
|
||||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
@ -1042,6 +1070,9 @@ GLFWAPI const char* glfwGetJoystickName(int jid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!initJoysticks())
|
||||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
@ -1067,6 +1098,9 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!initJoysticks())
|
||||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
@ -1112,6 +1146,10 @@ GLFWAPI void* glfwGetJoystickUserPointer(int jid)
|
|||
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (!initJoysticks())
|
||||
return NULL;
|
||||
|
||||
_GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
@ -1191,6 +1229,9 @@ GLFWAPI int glfwJoystickIsGamepad(int jid)
|
|||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!initJoysticks())
|
||||
return GLFW_FALSE;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
@ -1216,6 +1257,9 @@ GLFWAPI const char* glfwGetGamepadName(int jid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!initJoysticks())
|
||||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
@ -1248,6 +1292,9 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
|||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!initJoysticks())
|
||||
return GLFW_FALSE;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
|
22
raylib/external/glfw/src/internal.h
vendored
22
raylib/external/glfw/src/internal.h
vendored
|
@ -194,6 +194,9 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
|||
#error "No supported window creation API selected"
|
||||
#endif
|
||||
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
// Constructs a version number string from the public header macros
|
||||
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
|
||||
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
|
||||
|
@ -240,6 +243,7 @@ struct _GLFWerror
|
|||
struct _GLFWinitconfig
|
||||
{
|
||||
GLFWbool hatButtons;
|
||||
int angleType;
|
||||
struct {
|
||||
GLFWbool menubar;
|
||||
GLFWbool chdir;
|
||||
|
@ -266,6 +270,7 @@ struct _GLFWwndconfig
|
|||
GLFWbool maximized;
|
||||
GLFWbool centerCursor;
|
||||
GLFWbool focusOnShow;
|
||||
GLFWbool mousePassthrough;
|
||||
GLFWbool scaleToMonitor;
|
||||
struct {
|
||||
GLFWbool retina;
|
||||
|
@ -359,9 +364,9 @@ struct _GLFWcontext
|
|||
// This is defined in the context API's context.h
|
||||
_GLFW_PLATFORM_CONTEXT_STATE;
|
||||
// This is defined in egl_context.h
|
||||
_GLFW_EGL_CONTEXT_STATE;
|
||||
_GLFWcontextEGL egl;
|
||||
// This is defined in osmesa_context.h
|
||||
_GLFW_OSMESA_CONTEXT_STATE;
|
||||
_GLFWcontextOSMesa osmesa;
|
||||
};
|
||||
|
||||
// Window and context structure
|
||||
|
@ -376,6 +381,7 @@ struct _GLFWwindow
|
|||
GLFWbool autoIconify;
|
||||
GLFWbool floating;
|
||||
GLFWbool focusOnShow;
|
||||
GLFWbool mousePassthrough;
|
||||
GLFWbool shouldClose;
|
||||
void* userPointer;
|
||||
GLFWvidmode videoMode;
|
||||
|
@ -533,6 +539,7 @@ struct _GLFWlibrary
|
|||
_GLFWmonitor** monitors;
|
||||
int monitorCount;
|
||||
|
||||
GLFWbool joysticksInitialized;
|
||||
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
||||
_GLFWmapping* mappings;
|
||||
int mappingCount;
|
||||
|
@ -581,9 +588,9 @@ struct _GLFWlibrary
|
|||
// This is defined in the platform's joystick.h
|
||||
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
|
||||
// This is defined in egl_context.h
|
||||
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
|
||||
_GLFWlibraryEGL egl;
|
||||
// This is defined in osmesa_context.h
|
||||
_GLFW_OSMESA_LIBRARY_CONTEXT_STATE;
|
||||
_GLFWlibraryOSMesa osmesa;
|
||||
};
|
||||
|
||||
// Global state shared between compilation units of GLFW
|
||||
|
@ -626,6 +633,8 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
|||
void _glfwPlatformSetClipboardString(const char* string);
|
||||
const char* _glfwPlatformGetClipboardString(void);
|
||||
|
||||
GLFWbool _glfwPlatformInitJoysticks(void);
|
||||
void _glfwPlatformTerminateJoysticks(void);
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid);
|
||||
|
||||
|
@ -674,6 +683,7 @@ float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
|
|||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);
|
||||
|
||||
void _glfwPlatformPollEvents(void);
|
||||
|
@ -681,6 +691,10 @@ void _glfwPlatformWaitEvents(void);
|
|||
void _glfwPlatformWaitEventsTimeout(double timeout);
|
||||
void _glfwPlatformPostEmptyEvent(void);
|
||||
|
||||
EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs);
|
||||
EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void);
|
||||
EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window);
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
|
|
97
raylib/external/glfw/src/linux_joystick.c
vendored
97
raylib/external/glfw/src/linux_joystick.c
vendored
|
@ -264,9 +264,50 @@ static int compareJoysticks(const void* fp, const void* sp)
|
|||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Initialize joystick interface
|
||||
//
|
||||
GLFWbool _glfwInitJoysticksLinux(void)
|
||||
void _glfwDetectJoystickConnectionLinux(void)
|
||||
{
|
||||
if (_glfw.linjs.inotify <= 0)
|
||||
return;
|
||||
|
||||
ssize_t offset = 0;
|
||||
char buffer[16384];
|
||||
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
|
||||
|
||||
while (size > offset)
|
||||
{
|
||||
regmatch_t match;
|
||||
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
|
||||
|
||||
offset += sizeof(struct inotify_event) + e->len;
|
||||
|
||||
if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
|
||||
continue;
|
||||
|
||||
char path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
|
||||
|
||||
if (e->mask & (IN_CREATE | IN_ATTRIB))
|
||||
openJoystickDevice(path);
|
||||
else if (e->mask & IN_DELETE)
|
||||
{
|
||||
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||
{
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwPlatformInitJoysticks(void)
|
||||
{
|
||||
const char* dirname = "/dev/input";
|
||||
|
||||
|
@ -320,9 +361,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Close all opened joystick handles
|
||||
//
|
||||
void _glfwTerminateJoysticksLinux(void)
|
||||
void _glfwPlatformTerminateJoysticks(void)
|
||||
{
|
||||
int jid;
|
||||
|
||||
|
@ -333,60 +372,16 @@ void _glfwTerminateJoysticksLinux(void)
|
|||
closeJoystick(js);
|
||||
}
|
||||
|
||||
regfree(&_glfw.linjs.regex);
|
||||
|
||||
if (_glfw.linjs.inotify > 0)
|
||||
{
|
||||
if (_glfw.linjs.watch > 0)
|
||||
inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch);
|
||||
|
||||
close(_glfw.linjs.inotify);
|
||||
regfree(&_glfw.linjs.regex);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwDetectJoystickConnectionLinux(void)
|
||||
{
|
||||
if (_glfw.linjs.inotify <= 0)
|
||||
return;
|
||||
|
||||
ssize_t offset = 0;
|
||||
char buffer[16384];
|
||||
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
|
||||
|
||||
while (size > offset)
|
||||
{
|
||||
regmatch_t match;
|
||||
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
|
||||
|
||||
offset += sizeof(struct inotify_event) + e->len;
|
||||
|
||||
if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
|
||||
continue;
|
||||
|
||||
char path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
|
||||
|
||||
if (e->mask & (IN_CREATE | IN_ATTRIB))
|
||||
openJoystickDevice(path);
|
||||
else if (e->mask & IN_DELETE)
|
||||
{
|
||||
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||
{
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
// Read all queued events (non-blocking)
|
||||
|
|
3
raylib/external/glfw/src/linux_joystick.h
vendored
3
raylib/external/glfw/src/linux_joystick.h
vendored
|
@ -55,8 +55,5 @@ typedef struct _GLFWlibraryLinux
|
|||
GLFWbool dropped;
|
||||
} _GLFWlibraryLinux;
|
||||
|
||||
|
||||
GLFWbool _glfwInitJoysticksLinux(void);
|
||||
void _glfwTerminateJoysticksLinux(void);
|
||||
void _glfwDetectJoystickConnectionLinux(void);
|
||||
|
||||
|
|
670
raylib/external/glfw/src/mappings.h
vendored
670
raylib/external/glfw/src/mappings.h
vendored
File diff suppressed because it is too large
Load diff
2
raylib/external/glfw/src/nsgl_context.m
vendored
2
raylib/external/glfw/src/nsgl_context.m
vendored
|
@ -51,7 +51,7 @@ static void swapBuffersNSGL(_GLFWwindow* window)
|
|||
|
||||
// HACK: Simulate vsync with usleep as NSGL swap interval does not apply to
|
||||
// windows with a non-visible occlusion state
|
||||
if (!([window->ns.object occlusionState] & NSWindowOcclusionStateVisible))
|
||||
if (window->ns.occluded)
|
||||
{
|
||||
int interval = 0;
|
||||
[window->context.nsgl.object getValues:&interval
|
||||
|
|
5
raylib/external/glfw/src/null_init.c
vendored
5
raylib/external/glfw/src/null_init.c
vendored
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
|
@ -37,11 +39,14 @@
|
|||
int _glfwPlatformInit(void)
|
||||
{
|
||||
_glfwInitTimerPOSIX();
|
||||
_glfwPollMonitorsNull();
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
free(_glfw.null.clipboardString);
|
||||
_glfwTerminateOSMesa();
|
||||
}
|
||||
|
||||
|
|
9
raylib/external/glfw/src/null_joystick.c
vendored
9
raylib/external/glfw/src/null_joystick.c
vendored
|
@ -33,6 +33,15 @@
|
|||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwPlatformInitJoysticks(void)
|
||||
{
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminateJoysticks(void)
|
||||
{
|
||||
}
|
||||
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
|
|
86
raylib/external/glfw/src/null_monitor.c
vendored
86
raylib/external/glfw/src/null_monitor.c
vendored
|
@ -29,6 +29,37 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
// The the sole (fake) video mode of our (sole) fake monitor
|
||||
//
|
||||
static GLFWvidmode getVideoMode(void)
|
||||
{
|
||||
GLFWvidmode mode;
|
||||
mode.width = 1920;
|
||||
mode.height = 1080;
|
||||
mode.redBits = 8;
|
||||
mode.greenBits = 8;
|
||||
mode.blueBits = 8;
|
||||
mode.refreshRate = 60;
|
||||
return mode;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPollMonitorsNull(void)
|
||||
{
|
||||
const float dpi = 141.f;
|
||||
const GLFWvidmode mode = getVideoMode();
|
||||
_GLFWmonitor* monitor = _glfwAllocMonitor("Null SuperNoop 0",
|
||||
(int) (mode.width * 25.4f / dpi),
|
||||
(int) (mode.height * 25.4f / dpi));
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_FIRST);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
|
@ -36,10 +67,15 @@
|
|||
|
||||
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
||||
{
|
||||
_glfwFreeGammaArrays(&monitor->null.ramp);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
if (xpos)
|
||||
*xpos = 0;
|
||||
if (ypos)
|
||||
*ypos = 0;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
|
@ -55,23 +91,69 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
|
|||
int* xpos, int* ypos,
|
||||
int* width, int* height)
|
||||
{
|
||||
const GLFWvidmode mode = getVideoMode();
|
||||
|
||||
if (xpos)
|
||||
*xpos = 0;
|
||||
if (ypos)
|
||||
*ypos = 10;
|
||||
if (width)
|
||||
*width = mode.width;
|
||||
if (height)
|
||||
*height = mode.height - 10;
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
return NULL;
|
||||
GLFWvidmode* mode = calloc(1, sizeof(GLFWvidmode));
|
||||
*mode = getVideoMode();
|
||||
*found = 1;
|
||||
return mode;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
*mode = getVideoMode();
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
if (!monitor->null.ramp.size)
|
||||
{
|
||||
_glfwAllocGammaArrays(&monitor->null.ramp, 256);
|
||||
|
||||
for (unsigned int i = 0; i < monitor->null.ramp.size; i++)
|
||||
{
|
||||
const float gamma = 2.2f;
|
||||
float value;
|
||||
value = i / (float) (monitor->null.ramp.size - 1);
|
||||
value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
|
||||
value = _glfw_fminf(value, 65535.f);
|
||||
|
||||
monitor->null.ramp.red[i] = (unsigned short) value;
|
||||
monitor->null.ramp.green[i] = (unsigned short) value;
|
||||
monitor->null.ramp.blue[i] = (unsigned short) value;
|
||||
}
|
||||
}
|
||||
|
||||
_glfwAllocGammaArrays(ramp, monitor->null.ramp.size);
|
||||
memcpy(ramp->red, monitor->null.ramp.red, sizeof(short) * ramp->size);
|
||||
memcpy(ramp->green, monitor->null.ramp.green, sizeof(short) * ramp->size);
|
||||
memcpy(ramp->blue, monitor->null.ramp.blue, sizeof(short) * ramp->size);
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
{
|
||||
if (monitor->null.ramp.size != ramp->size)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Null: Gamma ramp size must match current ramp size");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(monitor->null.ramp.red, ramp->red, sizeof(short) * ramp->size);
|
||||
memcpy(monitor->null.ramp.green, ramp->green, sizeof(short) * ramp->size);
|
||||
memcpy(monitor->null.ramp.blue, ramp->blue, sizeof(short) * ramp->size);
|
||||
}
|
||||
|
||||
|
|
43
raylib/external/glfw/src/null_platform.h
vendored
43
raylib/external/glfw/src/null_platform.h
vendored
|
@ -27,17 +27,14 @@
|
|||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNull null
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNull null
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE struct { int dummyContext; }
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE struct { int dummyMonitor; }
|
||||
#define _GLFW_PLATFORM_CURSOR_STATE struct { int dummyCursor; }
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE struct { int dummyLibraryWindow; }
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; }
|
||||
#define _GLFW_EGL_CONTEXT_STATE struct { int dummyEGLContext; }
|
||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE struct { int dummyEGLLibraryContext; }
|
||||
|
||||
#include "osmesa_context.h"
|
||||
#include "posix_time.h"
|
||||
#include "posix_thread.h"
|
||||
#include "null_joystick.h"
|
||||
|
@ -56,7 +53,37 @@
|
|||
//
|
||||
typedef struct _GLFWwindowNull
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int xpos;
|
||||
int ypos;
|
||||
int width;
|
||||
int height;
|
||||
char* title;
|
||||
GLFWbool visible;
|
||||
GLFWbool iconified;
|
||||
GLFWbool maximized;
|
||||
GLFWbool resizable;
|
||||
GLFWbool decorated;
|
||||
GLFWbool floating;
|
||||
GLFWbool transparent;
|
||||
float opacity;
|
||||
} _GLFWwindowNull;
|
||||
|
||||
// Null-specific per-monitor data
|
||||
//
|
||||
typedef struct _GLFWmonitorNull
|
||||
{
|
||||
GLFWgammaramp ramp;
|
||||
} _GLFWmonitorNull;
|
||||
|
||||
// Null-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryNull
|
||||
{
|
||||
int xcursor;
|
||||
int ycursor;
|
||||
char* clipboardString;
|
||||
_GLFWwindow* focusedWindow;
|
||||
} _GLFWlibraryNull;
|
||||
|
||||
void _glfwPollMonitorsNull(void);
|
||||
|
||||
|
|
384
raylib/external/glfw/src/null_window.c
vendored
384
raylib/external/glfw/src/null_window.c
vendored
|
@ -29,12 +29,71 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static void applySizeLimits(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
|
||||
{
|
||||
const float ratio = (float) window->numer / (float) window->denom;
|
||||
*height = (int) (*width / ratio);
|
||||
}
|
||||
|
||||
if (window->minwidth != GLFW_DONT_CARE && *width < window->minwidth)
|
||||
*width = window->minwidth;
|
||||
else if (window->maxwidth != GLFW_DONT_CARE && *width > window->maxwidth)
|
||||
*width = window->maxwidth;
|
||||
|
||||
if (window->minheight != GLFW_DONT_CARE && *height < window->minheight)
|
||||
*height = window->minheight;
|
||||
else if (window->maxheight != GLFW_DONT_CARE && *height > window->maxheight)
|
||||
*height = window->maxheight;
|
||||
}
|
||||
|
||||
static void fitToMonitor(_GLFWwindow* window)
|
||||
{
|
||||
GLFWvidmode mode;
|
||||
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||
_glfwPlatformGetMonitorPos(window->monitor,
|
||||
&window->null.xpos,
|
||||
&window->null.ypos);
|
||||
window->null.width = mode.width;
|
||||
window->null.height = mode.height;
|
||||
}
|
||||
|
||||
static void acquireMonitor(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputMonitorWindow(window->monitor, window);
|
||||
}
|
||||
|
||||
static void releaseMonitor(_GLFWwindow* window)
|
||||
{
|
||||
if (window->monitor->window != window)
|
||||
return;
|
||||
|
||||
_glfwInputMonitorWindow(window->monitor, NULL);
|
||||
}
|
||||
|
||||
static int createNativeWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig)
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
window->null.width = wndconfig->width;
|
||||
window->null.height = wndconfig->height;
|
||||
if (window->monitor)
|
||||
fitToMonitor(window);
|
||||
else
|
||||
{
|
||||
window->null.xpos = 17;
|
||||
window->null.ypos = 17;
|
||||
window->null.width = wndconfig->width;
|
||||
window->null.height = wndconfig->height;
|
||||
}
|
||||
|
||||
window->null.visible = wndconfig->visible;
|
||||
window->null.decorated = wndconfig->decorated;
|
||||
window->null.maximized = wndconfig->maximized;
|
||||
window->null.floating = wndconfig->floating;
|
||||
window->null.transparent = fbconfig->transparent;
|
||||
window->null.opacity = 1.f;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
@ -49,7 +108,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
if (!createNativeWindow(window, wndconfig))
|
||||
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
|
@ -69,11 +128,24 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||
}
|
||||
}
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
_glfwPlatformShowWindow(window);
|
||||
_glfwPlatformFocusWindow(window);
|
||||
acquireMonitor(window);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (window->monitor)
|
||||
releaseMonitor(window);
|
||||
|
||||
if (_glfw.null.focusedWindow == window)
|
||||
_glfw.null.focusedWindow = NULL;
|
||||
|
||||
if (window->context.destroy)
|
||||
window->context.destroy(window);
|
||||
}
|
||||
|
@ -93,14 +165,54 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||
int width, int height,
|
||||
int refreshRate)
|
||||
{
|
||||
if (window->monitor == monitor)
|
||||
{
|
||||
if (!monitor)
|
||||
{
|
||||
_glfwPlatformSetWindowPos(window, xpos, ypos);
|
||||
_glfwPlatformSetWindowSize(window, width, height);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->monitor)
|
||||
releaseMonitor(window);
|
||||
|
||||
_glfwInputWindowMonitor(window, monitor);
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
window->null.visible = GLFW_TRUE;
|
||||
acquireMonitor(window);
|
||||
fitToMonitor(window);
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwPlatformSetWindowPos(window, xpos, ypos);
|
||||
_glfwPlatformSetWindowSize(window, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
{
|
||||
if (xpos)
|
||||
*xpos = window->null.xpos;
|
||||
if (ypos)
|
||||
*ypos = window->null.ypos;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||
{
|
||||
if (window->monitor)
|
||||
return;
|
||||
|
||||
if (window->null.xpos != xpos || window->null.ypos != ypos)
|
||||
{
|
||||
window->null.xpos = xpos;
|
||||
window->null.ypos = ypos;
|
||||
_glfwInputWindowPos(window, xpos, ypos);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||
|
@ -113,18 +225,34 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
|||
|
||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
window->null.width = width;
|
||||
window->null.height = height;
|
||||
if (window->monitor)
|
||||
return;
|
||||
|
||||
if (window->null.width != width || window->null.height != height)
|
||||
{
|
||||
window->null.width = width;
|
||||
window->null.height = height;
|
||||
_glfwInputWindowSize(window, width, height);
|
||||
_glfwInputFramebufferSize(window, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
int minwidth, int minheight,
|
||||
int maxwidth, int maxheight)
|
||||
{
|
||||
int width = window->null.width;
|
||||
int height = window->null.height;
|
||||
applySizeLimits(window, &width, &height);
|
||||
_glfwPlatformSetWindowSize(window, width, height);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
|
||||
{
|
||||
int width = window->null.width;
|
||||
int height = window->null.height;
|
||||
applySizeLimits(window, &width, &height);
|
||||
_glfwPlatformSetWindowSize(window, width, height);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
|
||||
|
@ -139,6 +267,28 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||
int* left, int* top,
|
||||
int* right, int* bottom)
|
||||
{
|
||||
if (window->null.decorated && !window->monitor)
|
||||
{
|
||||
if (left)
|
||||
*left = 1;
|
||||
if (top)
|
||||
*top = 10;
|
||||
if (right)
|
||||
*right = 1;
|
||||
if (bottom)
|
||||
*bottom = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (left)
|
||||
*left = 0;
|
||||
if (top)
|
||||
*top = 0;
|
||||
if (right)
|
||||
*right = 0;
|
||||
if (bottom)
|
||||
*bottom = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||
|
@ -152,50 +302,93 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
|||
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (_glfw.null.focusedWindow == window)
|
||||
{
|
||||
_glfw.null.focusedWindow = NULL;
|
||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||
}
|
||||
|
||||
if (!window->null.iconified)
|
||||
{
|
||||
window->null.iconified = GLFW_TRUE;
|
||||
_glfwInputWindowIconify(window, GLFW_TRUE);
|
||||
|
||||
if (window->monitor)
|
||||
releaseMonitor(window);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (window->null.iconified)
|
||||
{
|
||||
window->null.iconified = GLFW_FALSE;
|
||||
_glfwInputWindowIconify(window, GLFW_FALSE);
|
||||
|
||||
if (window->monitor)
|
||||
acquireMonitor(window);
|
||||
}
|
||||
else if (window->null.maximized)
|
||||
{
|
||||
window->null.maximized = GLFW_FALSE;
|
||||
_glfwInputWindowMaximize(window, GLFW_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (!window->null.maximized)
|
||||
{
|
||||
window->null.maximized = GLFW_TRUE;
|
||||
_glfwInputWindowMaximize(window, GLFW_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return window->null.maximized;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return _glfw.null.xcursor >= window->null.xpos &&
|
||||
_glfw.null.ycursor >= window->null.ypos &&
|
||||
_glfw.null.xcursor <= window->null.xpos + window->null.width - 1 &&
|
||||
_glfw.null.ycursor <= window->null.ypos + window->null.height - 1;
|
||||
}
|
||||
|
||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return window->null.transparent;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
window->null.resizable = enabled;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
window->null.decorated = enabled;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
window->null.floating = enabled;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||
{
|
||||
return 1.f;
|
||||
return window->null.opacity;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||
{
|
||||
window->null.opacity = opacity;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
|
||||
|
@ -204,43 +397,63 @@ void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
|
|||
|
||||
GLFWbool _glfwPlatformRawMouseMotionSupported(void)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
window->null.visible = GLFW_TRUE;
|
||||
}
|
||||
|
||||
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (_glfw.null.focusedWindow == window)
|
||||
{
|
||||
_glfw.null.focusedWindow = NULL;
|
||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||
}
|
||||
|
||||
window->null.visible = GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (_glfw.null.focusedWindow == window)
|
||||
return;
|
||||
|
||||
if (!window->null.visible)
|
||||
return;
|
||||
|
||||
_GLFWwindow* previous = _glfw.null.focusedWindow;
|
||||
_glfw.null.focusedWindow = window;
|
||||
|
||||
if (previous)
|
||||
{
|
||||
_glfwInputWindowFocus(previous, GLFW_FALSE);
|
||||
if (previous->monitor && previous->autoIconify)
|
||||
_glfwPlatformIconifyWindow(previous);
|
||||
}
|
||||
|
||||
_glfwInputWindowFocus(window, GLFW_TRUE);
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return _glfw.null.focusedWindow == window;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return window->null.iconified;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return window->null.visible;
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
|
@ -261,10 +474,16 @@ void _glfwPlatformPostEmptyEvent(void)
|
|||
|
||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
{
|
||||
if (xpos)
|
||||
*xpos = _glfw.null.xcursor - window->null.xpos;
|
||||
if (ypos)
|
||||
*ypos = _glfw.null.ycursor - window->null.ypos;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
||||
{
|
||||
_glfw.null.xcursor = window->null.xpos + (int) x;
|
||||
_glfw.null.ycursor = window->null.ypos + (int) y;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
|
@ -293,21 +512,140 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||
|
||||
void _glfwPlatformSetClipboardString(const char* string)
|
||||
{
|
||||
char* copy = _glfw_strdup(string);
|
||||
free(_glfw.null.clipboardString);
|
||||
_glfw.null.clipboardString = copy;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetClipboardString(void)
|
||||
{
|
||||
return NULL;
|
||||
return _glfw.null.clipboardString;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
return "";
|
||||
switch (scancode)
|
||||
{
|
||||
case GLFW_KEY_APOSTROPHE:
|
||||
return "'";
|
||||
case GLFW_KEY_COMMA:
|
||||
return ",";
|
||||
case GLFW_KEY_MINUS:
|
||||
case GLFW_KEY_KP_SUBTRACT:
|
||||
return "-";
|
||||
case GLFW_KEY_PERIOD:
|
||||
case GLFW_KEY_KP_DECIMAL:
|
||||
return ".";
|
||||
case GLFW_KEY_SLASH:
|
||||
case GLFW_KEY_KP_DIVIDE:
|
||||
return "/";
|
||||
case GLFW_KEY_SEMICOLON:
|
||||
return ";";
|
||||
case GLFW_KEY_EQUAL:
|
||||
case GLFW_KEY_KP_EQUAL:
|
||||
return "=";
|
||||
case GLFW_KEY_LEFT_BRACKET:
|
||||
return "[";
|
||||
case GLFW_KEY_RIGHT_BRACKET:
|
||||
return "]";
|
||||
case GLFW_KEY_KP_MULTIPLY:
|
||||
return "*";
|
||||
case GLFW_KEY_KP_ADD:
|
||||
return "+";
|
||||
case GLFW_KEY_BACKSLASH:
|
||||
case GLFW_KEY_WORLD_1:
|
||||
case GLFW_KEY_WORLD_2:
|
||||
return "\\";
|
||||
case GLFW_KEY_0:
|
||||
case GLFW_KEY_KP_0:
|
||||
return "0";
|
||||
case GLFW_KEY_1:
|
||||
case GLFW_KEY_KP_1:
|
||||
return "1";
|
||||
case GLFW_KEY_2:
|
||||
case GLFW_KEY_KP_2:
|
||||
return "2";
|
||||
case GLFW_KEY_3:
|
||||
case GLFW_KEY_KP_3:
|
||||
return "3";
|
||||
case GLFW_KEY_4:
|
||||
case GLFW_KEY_KP_4:
|
||||
return "4";
|
||||
case GLFW_KEY_5:
|
||||
case GLFW_KEY_KP_5:
|
||||
return "5";
|
||||
case GLFW_KEY_6:
|
||||
case GLFW_KEY_KP_6:
|
||||
return "6";
|
||||
case GLFW_KEY_7:
|
||||
case GLFW_KEY_KP_7:
|
||||
return "7";
|
||||
case GLFW_KEY_8:
|
||||
case GLFW_KEY_KP_8:
|
||||
return "8";
|
||||
case GLFW_KEY_9:
|
||||
case GLFW_KEY_KP_9:
|
||||
return "9";
|
||||
case GLFW_KEY_A:
|
||||
return "a";
|
||||
case GLFW_KEY_B:
|
||||
return "b";
|
||||
case GLFW_KEY_C:
|
||||
return "c";
|
||||
case GLFW_KEY_D:
|
||||
return "d";
|
||||
case GLFW_KEY_E:
|
||||
return "e";
|
||||
case GLFW_KEY_F:
|
||||
return "f";
|
||||
case GLFW_KEY_G:
|
||||
return "g";
|
||||
case GLFW_KEY_H:
|
||||
return "h";
|
||||
case GLFW_KEY_I:
|
||||
return "i";
|
||||
case GLFW_KEY_J:
|
||||
return "j";
|
||||
case GLFW_KEY_K:
|
||||
return "k";
|
||||
case GLFW_KEY_L:
|
||||
return "l";
|
||||
case GLFW_KEY_M:
|
||||
return "m";
|
||||
case GLFW_KEY_N:
|
||||
return "n";
|
||||
case GLFW_KEY_O:
|
||||
return "o";
|
||||
case GLFW_KEY_P:
|
||||
return "p";
|
||||
case GLFW_KEY_Q:
|
||||
return "q";
|
||||
case GLFW_KEY_R:
|
||||
return "r";
|
||||
case GLFW_KEY_S:
|
||||
return "s";
|
||||
case GLFW_KEY_T:
|
||||
return "t";
|
||||
case GLFW_KEY_U:
|
||||
return "u";
|
||||
case GLFW_KEY_V:
|
||||
return "v";
|
||||
case GLFW_KEY_W:
|
||||
return "w";
|
||||
case GLFW_KEY_X:
|
||||
return "x";
|
||||
case GLFW_KEY_Y:
|
||||
return "y";
|
||||
case GLFW_KEY_Z:
|
||||
return "z";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _glfwPlatformGetKeyScancode(int key)
|
||||
{
|
||||
return -1;
|
||||
return key;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
|
@ -327,6 +665,6 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||
VkSurfaceKHR* surface)
|
||||
{
|
||||
// This seems like the most appropriate error to return here
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
|
|
4
raylib/external/glfw/src/osmesa_context.h
vendored
4
raylib/external/glfw/src/osmesa_context.h
vendored
|
@ -54,10 +54,6 @@ typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*);
|
|||
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
|
||||
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
|
||||
|
||||
#define _GLFW_OSMESA_CONTEXT_STATE _GLFWcontextOSMesa osmesa
|
||||
#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
|
||||
|
||||
|
||||
// OSMesa-specific per-context data
|
||||
//
|
||||
typedef struct _GLFWcontextOSMesa
|
||||
|
|
4
raylib/external/glfw/src/wgl_context.h
vendored
4
raylib/external/glfw/src/wgl_context.h
vendored
|
@ -104,10 +104,6 @@ typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
|
|||
#define wglMakeCurrent _glfw.wgl.MakeCurrent
|
||||
#define wglShareLists _glfw.wgl.ShareLists
|
||||
|
||||
#define _GLFW_RECREATION_NOT_NEEDED 0
|
||||
#define _GLFW_RECREATION_REQUIRED 1
|
||||
#define _GLFW_RECREATION_IMPOSSIBLE 2
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
|
||||
|
||||
|
|
5
raylib/external/glfw/src/win32_init.c
vendored
5
raylib/external/glfw/src/win32_init.c
vendored
|
@ -143,6 +143,8 @@ static GLFWbool loadLibraries(void)
|
|||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
||||
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
|
||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
|
||||
_glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor)
|
||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor");
|
||||
}
|
||||
|
||||
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
||||
|
@ -580,7 +582,6 @@ int _glfwPlatformInit(void)
|
|||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitTimerWin32();
|
||||
_glfwInitJoysticksWin32();
|
||||
|
||||
_glfwPollMonitorsWin32();
|
||||
return GLFW_TRUE;
|
||||
|
@ -607,8 +608,6 @@ void _glfwPlatformTerminate(void)
|
|||
_glfwTerminateWGL();
|
||||
_glfwTerminateEGL();
|
||||
|
||||
_glfwTerminateJoysticksWin32();
|
||||
|
||||
freeLibraries();
|
||||
}
|
||||
|
||||
|
|
74
raylib/external/glfw/src/win32_joystick.c
vendored
74
raylib/external/glfw/src/win32_joystick.c
vendored
|
@ -356,7 +356,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
{
|
||||
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
|
@ -491,39 +491,6 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Initialize joystick interface
|
||||
//
|
||||
void _glfwInitJoysticksWin32(void)
|
||||
{
|
||||
if (_glfw.win32.dinput8.instance)
|
||||
{
|
||||
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
||||
DIRECTINPUT_VERSION,
|
||||
&IID_IDirectInput8W,
|
||||
(void**) &_glfw.win32.dinput8.api,
|
||||
NULL)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create interface");
|
||||
}
|
||||
}
|
||||
|
||||
_glfwDetectJoystickConnectionWin32();
|
||||
}
|
||||
|
||||
// Close all opened joystick handles
|
||||
//
|
||||
void _glfwTerminateJoysticksWin32(void)
|
||||
{
|
||||
int jid;
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
|
||||
if (_glfw.win32.dinput8.api)
|
||||
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||
}
|
||||
|
||||
// Checks for new joysticks after DBT_DEVICEARRIVAL
|
||||
//
|
||||
void _glfwDetectJoystickConnectionWin32(void)
|
||||
|
@ -603,6 +570,37 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
|||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwPlatformInitJoysticks(void)
|
||||
{
|
||||
if (_glfw.win32.dinput8.instance)
|
||||
{
|
||||
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
||||
DIRECTINPUT_VERSION,
|
||||
&IID_IDirectInput8W,
|
||||
(void**) &_glfw.win32.dinput8.api,
|
||||
NULL)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create interface");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
_glfwDetectJoystickConnectionWin32();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminateJoysticks(void)
|
||||
{
|
||||
int jid;
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
|
||||
if (_glfw.win32.dinput8.api)
|
||||
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||
}
|
||||
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
if (js->win32.device)
|
||||
|
@ -672,11 +670,11 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
|||
};
|
||||
|
||||
// Screams of horror are appropriate at this point
|
||||
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||
if (state < 0 || state > 8)
|
||||
state = 8;
|
||||
int stateIndex = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||
if (stateIndex < 0 || stateIndex > 8)
|
||||
stateIndex = 8;
|
||||
|
||||
_glfwInputJoystickHat(js, pi, states[state]);
|
||||
_glfwInputJoystickHat(js, pi, states[stateIndex]);
|
||||
pi++;
|
||||
break;
|
||||
}
|
||||
|
|
3
raylib/external/glfw/src/win32_joystick.h
vendored
3
raylib/external/glfw/src/win32_joystick.h
vendored
|
@ -48,9 +48,6 @@ typedef struct _GLFWjoystickWin32
|
|||
GUID guid;
|
||||
} _GLFWjoystickWin32;
|
||||
|
||||
|
||||
void _glfwInitJoysticksWin32(void);
|
||||
void _glfwTerminateJoysticksWin32(void);
|
||||
void _glfwDetectJoystickConnectionWin32(void);
|
||||
void _glfwDetectJoystickDisconnectionWin32(void);
|
||||
|
||||
|
|
2
raylib/external/glfw/src/win32_monitor.c
vendored
2
raylib/external/glfw/src/win32_monitor.c
vendored
|
@ -185,6 +185,8 @@ void _glfwPollMonitorsWin32(void)
|
|||
display.DeviceName) == 0)
|
||||
{
|
||||
disconnected[i] = NULL;
|
||||
// handle may have changed, update
|
||||
EnumDisplayMonitors(NULL, NULL, monitorCallback, (LPARAM) _glfw.monitors[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
18
raylib/external/glfw/src/win32_platform.h
vendored
18
raylib/external/glfw/src/win32_platform.h
vendored
|
@ -77,6 +77,9 @@
|
|||
#ifndef WM_DWMCOMPOSITIONCHANGED
|
||||
#define WM_DWMCOMPOSITIONCHANGED 0x031E
|
||||
#endif
|
||||
#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
|
||||
#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
|
||||
#endif
|
||||
#ifndef WM_COPYGLOBALDATA
|
||||
#define WM_COPYGLOBALDATA 0x0049
|
||||
#endif
|
||||
|
@ -99,7 +102,7 @@
|
|||
#define DISPLAY_DEVICE_ACTIVE 0x00000001
|
||||
#endif
|
||||
#ifndef _WIN32_WINNT_WINBLUE
|
||||
#define _WIN32_WINNT_WINBLUE 0x0602
|
||||
#define _WIN32_WINNT_WINBLUE 0x0603
|
||||
#endif
|
||||
#ifndef _WIN32_WINNT_WIN8
|
||||
#define _WIN32_WINNT_WIN8 0x0602
|
||||
|
@ -160,9 +163,6 @@ typedef enum
|
|||
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
|
||||
|
||||
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
||||
#define IsWindowsXPOrGreater() \
|
||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
|
||||
LOBYTE(_WIN32_WINNT_WINXP), 0)
|
||||
#define IsWindowsVistaOrGreater() \
|
||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
|
||||
LOBYTE(_WIN32_WINNT_VISTA), 0)
|
||||
|
@ -247,9 +247,11 @@ typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UIN
|
|||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
||||
typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
|
||||
typedef HRESULT (WINAPI * PFN_DwmGetColorizationColor)(DWORD*,BOOL*);
|
||||
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
||||
#define DwmFlush _glfw.win32.dwmapi.Flush
|
||||
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
|
||||
#define DwmGetColorizationColor _glfw.win32.dwmapi.GetColorizationColor
|
||||
|
||||
// shcore.dll function pointer typedefs
|
||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
||||
|
@ -277,8 +279,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
|
|||
|
||||
#include "win32_joystick.h"
|
||||
#include "wgl_context.h"
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
#if !defined(_GLFW_WNDCLASSNAME)
|
||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||
|
@ -288,9 +288,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
|
|||
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
||||
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
|
||||
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32
|
||||
|
@ -319,6 +316,8 @@ typedef struct _GLFWwindowWin32
|
|||
|
||||
// The last received cursor position, regardless of source
|
||||
int lastCursorPosX, lastCursorPosY;
|
||||
// The last recevied high surrogate when decoding pairs of UTF-16 messages
|
||||
WCHAR highSurrogate;
|
||||
|
||||
} _GLFWwindowWin32;
|
||||
|
||||
|
@ -374,6 +373,7 @@ typedef struct _GLFWlibraryWin32
|
|||
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
||||
PFN_DwmFlush Flush;
|
||||
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
|
||||
PFN_DwmGetColorizationColor GetColorizationColor;
|
||||
} dwmapi;
|
||||
|
||||
struct {
|
||||
|
|
213
raylib/external/glfw/src/win32_window.c
vendored
213
raylib/external/glfw/src/win32_window.c
vendored
|
@ -377,12 +377,17 @@ static void updateWindowStyles(const _GLFWwindow* window)
|
|||
//
|
||||
static void updateFramebufferTransparency(const _GLFWwindow* window)
|
||||
{
|
||||
BOOL enabled;
|
||||
BOOL composition, opaque;
|
||||
DWORD color;
|
||||
|
||||
if (!IsWindowsVistaOrGreater())
|
||||
return;
|
||||
|
||||
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
|
||||
if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
|
||||
return;
|
||||
|
||||
if (IsWindows8OrGreater() ||
|
||||
(SUCCEEDED(DwmGetColorizationColor(&color, &opaque)) && !opaque))
|
||||
{
|
||||
HRGN region = CreateRectRgn(0, 0, -1, -1);
|
||||
DWM_BLURBEHIND bb = {0};
|
||||
|
@ -390,37 +395,18 @@ static void updateFramebufferTransparency(const _GLFWwindow* window)
|
|||
bb.hRgnBlur = region;
|
||||
bb.fEnable = TRUE;
|
||||
|
||||
if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb)))
|
||||
{
|
||||
// Decorated windows don't repaint the transparent background
|
||||
// leaving a trail behind animations
|
||||
// HACK: Making the window layered with a transparency color key
|
||||
// seems to fix this. Normally, when specifying
|
||||
// a transparency color key to be used when composing the
|
||||
// layered window, all pixels painted by the window in this
|
||||
// color will be transparent. That doesn't seem to be the
|
||||
// case anymore, at least when used with blur behind window
|
||||
// plus negative region.
|
||||
LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||
exStyle |= WS_EX_LAYERED;
|
||||
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
|
||||
|
||||
// Using a color key not equal to black to fix the trailing
|
||||
// issue. When set to black, something is making the hit test
|
||||
// not resize with the window frame.
|
||||
SetLayeredWindowAttributes(window->win32.handle,
|
||||
RGB(255, 0, 255), 255, LWA_COLORKEY);
|
||||
}
|
||||
|
||||
DwmEnableBlurBehindWindow(window->win32.handle, &bb);
|
||||
DeleteObject(region);
|
||||
}
|
||||
else
|
||||
{
|
||||
LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||
exStyle &= ~WS_EX_LAYERED;
|
||||
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
|
||||
RedrawWindow(window->win32.handle, NULL, NULL,
|
||||
RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
|
||||
// HACK: Disable framebuffer transparency on Windows 7 when the
|
||||
// colorization color is opaque, because otherwise the window
|
||||
// contents is blended additively with the previous frame instead
|
||||
// of replacing it
|
||||
DWM_BLURBEHIND bb = {0};
|
||||
bb.dwFlags = DWM_BB_ENABLE;
|
||||
DwmEnableBlurBehindWindow(window->win32.handle, &bb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,11 +454,8 @@ static void acquireMonitor(_GLFWwindow* window)
|
|||
|
||||
// HACK: When mouse trails are enabled the cursor becomes invisible when
|
||||
// the OpenGL ICD switches to page flipping
|
||||
if (IsWindowsXPOrGreater())
|
||||
{
|
||||
SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
|
||||
SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
|
||||
}
|
||||
SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
|
||||
SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (!window->monitor->window)
|
||||
|
@ -495,8 +478,7 @@ static void releaseMonitor(_GLFWwindow* window)
|
|||
SetThreadExecutionState(ES_CONTINUOUS);
|
||||
|
||||
// HACK: Restore mouse trail length saved in acquireMonitor
|
||||
if (IsWindowsXPOrGreater())
|
||||
SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
|
||||
SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
|
||||
}
|
||||
|
||||
_glfwInputMonitorWindow(window->monitor, NULL);
|
||||
|
@ -530,6 +512,9 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
|
||||
case WM_DEVICECHANGE:
|
||||
{
|
||||
if (!_glfw.joysticksInitialized)
|
||||
break;
|
||||
|
||||
if (wParam == DBT_DEVICEARRIVAL)
|
||||
{
|
||||
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||
|
@ -650,11 +635,38 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
|
||||
case WM_CHAR:
|
||||
case WM_SYSCHAR:
|
||||
{
|
||||
if (wParam >= 0xd800 && wParam <= 0xdbff)
|
||||
window->win32.highSurrogate = (WCHAR) wParam;
|
||||
else
|
||||
{
|
||||
unsigned int codepoint = 0;
|
||||
|
||||
if (wParam >= 0xdc00 && wParam <= 0xdfff)
|
||||
{
|
||||
if (window->win32.highSurrogate)
|
||||
{
|
||||
codepoint += (window->win32.highSurrogate - 0xd800) << 10;
|
||||
codepoint += (WCHAR) wParam - 0xdc00;
|
||||
codepoint += 0x10000;
|
||||
}
|
||||
}
|
||||
else
|
||||
codepoint = (WCHAR) wParam;
|
||||
|
||||
window->win32.highSurrogate = 0;
|
||||
_glfwInputChar(window, codepoint, getKeyMods(), uMsg != WM_SYSCHAR);
|
||||
}
|
||||
|
||||
if (uMsg == WM_SYSCHAR && window->win32.keymenu)
|
||||
break;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_UNICHAR:
|
||||
{
|
||||
const GLFWbool plain = (uMsg != WM_SYSCHAR);
|
||||
|
||||
if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR)
|
||||
if (wParam == UNICODE_NOCHAR)
|
||||
{
|
||||
// WM_UNICHAR is not sent by Windows, but is sent by some
|
||||
// third-party input method engine
|
||||
|
@ -662,11 +674,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
_glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain);
|
||||
|
||||
if (uMsg == WM_SYSCHAR && window->win32.keymenu)
|
||||
break;
|
||||
|
||||
_glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GLFW_TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1082,6 +1090,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
}
|
||||
|
||||
case WM_DWMCOMPOSITIONCHANGED:
|
||||
case WM_DWMCOLORIZATIONCOLORCHANGED:
|
||||
{
|
||||
if (window->win32.transparent)
|
||||
updateFramebufferTransparency(window);
|
||||
|
@ -1807,7 +1816,8 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
|||
|
||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||
{
|
||||
BOOL enabled;
|
||||
BOOL composition, opaque;
|
||||
DWORD color;
|
||||
|
||||
if (!window->win32.transparent)
|
||||
return GLFW_FALSE;
|
||||
|
@ -1815,7 +1825,20 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
|||
if (!IsWindowsVistaOrGreater())
|
||||
return GLFW_FALSE;
|
||||
|
||||
return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
|
||||
if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!IsWindows8OrGreater())
|
||||
{
|
||||
// HACK: Disable framebuffer transparency on Windows 7 when the
|
||||
// colorization color is opaque, because otherwise the window
|
||||
// contents is blended additively with the previous frame instead
|
||||
// of replacing it
|
||||
if (FAILED(DwmGetColorizationColor(&color, &opaque)) || opaque)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
|
@ -1835,6 +1858,36 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
|||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
COLORREF key = 0;
|
||||
BYTE alpha = 0;
|
||||
DWORD flags = 0;
|
||||
DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||
|
||||
if (exStyle & WS_EX_LAYERED)
|
||||
GetLayeredWindowAttributes(window->win32.handle, &key, &alpha, &flags);
|
||||
|
||||
if (enabled)
|
||||
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(window->win32.handle, GWL_EXSTYLE, exStyle);
|
||||
|
||||
if (enabled)
|
||||
SetLayeredWindowAttributes(window->win32.handle, key, alpha, flags);
|
||||
}
|
||||
|
||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||
{
|
||||
BYTE alpha;
|
||||
|
@ -1852,19 +1905,22 @@ float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
|||
|
||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||
{
|
||||
if (opacity < 1.f)
|
||||
LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||
if (opacity < 1.f || (exStyle & WS_EX_TRANSPARENT))
|
||||
{
|
||||
const BYTE alpha = (BYTE) (255 * opacity);
|
||||
DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||
style |= WS_EX_LAYERED;
|
||||
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
|
||||
exStyle |= WS_EX_LAYERED;
|
||||
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
|
||||
SetLayeredWindowAttributes(window->win32.handle, 0, alpha, LWA_ALPHA);
|
||||
}
|
||||
else if (exStyle & WS_EX_TRANSPARENT)
|
||||
{
|
||||
SetLayeredWindowAttributes(window->win32.handle, 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||
style &= ~WS_EX_LAYERED;
|
||||
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
|
||||
exStyle &= ~WS_EX_LAYERED;
|
||||
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2190,6 +2246,57 @@ const char* _glfwPlatformGetClipboardString(void)
|
|||
return _glfw.win32.clipboardString;
|
||||
}
|
||||
|
||||
EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs)
|
||||
{
|
||||
if (_glfw.egl.ANGLE_platform_angle)
|
||||
{
|
||||
int type = 0;
|
||||
|
||||
if (_glfw.egl.ANGLE_platform_angle_opengl)
|
||||
{
|
||||
if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_OPENGL)
|
||||
type = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
|
||||
else if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_OPENGLES)
|
||||
type = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
|
||||
}
|
||||
|
||||
if (_glfw.egl.ANGLE_platform_angle_d3d)
|
||||
{
|
||||
if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_D3D9)
|
||||
type = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
|
||||
else if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_D3D11)
|
||||
type = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
|
||||
}
|
||||
|
||||
if (_glfw.egl.ANGLE_platform_angle_vulkan)
|
||||
{
|
||||
if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_VULKAN)
|
||||
type = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
|
||||
}
|
||||
|
||||
if (type)
|
||||
{
|
||||
*attribs = calloc(3, sizeof(EGLint));
|
||||
(*attribs)[0] = EGL_PLATFORM_ANGLE_TYPE_ANGLE;
|
||||
(*attribs)[1] = type;
|
||||
(*attribs)[2] = EGL_NONE;
|
||||
return EGL_PLATFORM_ANGLE_ANGLE;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void)
|
||||
{
|
||||
return GetDC(_glfw.win32.helperWindowHandle);
|
||||
}
|
||||
|
||||
EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window)
|
||||
{
|
||||
return window->win32.handle;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_win32_surface)
|
||||
|
|
36
raylib/external/glfw/src/window.c
vendored
36
raylib/external/glfw/src/window.c
vendored
|
@ -197,13 +197,14 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||
window->videoMode.blueBits = fbconfig.blueBits;
|
||||
window->videoMode.refreshRate = _glfw.hints.refreshRate;
|
||||
|
||||
window->monitor = (_GLFWmonitor*) monitor;
|
||||
window->resizable = wndconfig.resizable;
|
||||
window->decorated = wndconfig.decorated;
|
||||
window->autoIconify = wndconfig.autoIconify;
|
||||
window->floating = wndconfig.floating;
|
||||
window->focusOnShow = wndconfig.focusOnShow;
|
||||
window->cursorMode = GLFW_CURSOR_NORMAL;
|
||||
window->monitor = (_GLFWmonitor*) monitor;
|
||||
window->resizable = wndconfig.resizable;
|
||||
window->decorated = wndconfig.decorated;
|
||||
window->autoIconify = wndconfig.autoIconify;
|
||||
window->floating = wndconfig.floating;
|
||||
window->focusOnShow = wndconfig.focusOnShow;
|
||||
window->mousePassthrough = wndconfig.mousePassthrough;
|
||||
window->cursorMode = GLFW_CURSOR_NORMAL;
|
||||
|
||||
window->minwidth = GLFW_DONT_CARE;
|
||||
window->minheight = GLFW_DONT_CARE;
|
||||
|
@ -228,6 +229,9 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||
}
|
||||
}
|
||||
|
||||
if (wndconfig.mousePassthrough)
|
||||
_glfwPlatformSetWindowMousePassthrough(window, GLFW_TRUE);
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
if (wndconfig.centerCursor)
|
||||
|
@ -378,6 +382,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
|||
case GLFW_FOCUS_ON_SHOW:
|
||||
_glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
case GLFW_MOUSE_PASSTHROUGH:
|
||||
_glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
case GLFW_CLIENT_API:
|
||||
_glfw.hints.context.client = value;
|
||||
return;
|
||||
|
@ -396,7 +403,7 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
|||
case GLFW_OPENGL_FORWARD_COMPAT:
|
||||
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
case GLFW_OPENGL_DEBUG_CONTEXT:
|
||||
case GLFW_CONTEXT_DEBUG:
|
||||
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
case GLFW_CONTEXT_NO_ERROR:
|
||||
|
@ -822,6 +829,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
|||
return _glfwPlatformWindowHovered(window);
|
||||
case GLFW_FOCUS_ON_SHOW:
|
||||
return window->focusOnShow;
|
||||
case GLFW_MOUSE_PASSTHROUGH:
|
||||
return window->mousePassthrough;
|
||||
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||
return _glfwPlatformFramebufferTransparent(window);
|
||||
case GLFW_RESIZABLE:
|
||||
|
@ -846,7 +855,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
|||
return window->context.robustness;
|
||||
case GLFW_OPENGL_FORWARD_COMPAT:
|
||||
return window->context.forward;
|
||||
case GLFW_OPENGL_DEBUG_CONTEXT:
|
||||
case GLFW_CONTEXT_DEBUG:
|
||||
return window->context.debug;
|
||||
case GLFW_OPENGL_PROFILE:
|
||||
return window->context.profile;
|
||||
|
@ -900,6 +909,14 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
|
|||
}
|
||||
else if (attrib == GLFW_FOCUS_ON_SHOW)
|
||||
window->focusOnShow = value;
|
||||
else if (attrib == GLFW_MOUSE_PASSTHROUGH)
|
||||
{
|
||||
if (window->mousePassthrough == value)
|
||||
return;
|
||||
|
||||
window->mousePassthrough = value;
|
||||
_glfwPlatformSetWindowMousePassthrough(window, value);
|
||||
}
|
||||
else
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
|
||||
}
|
||||
|
@ -1102,3 +1119,4 @@ GLFWAPI void glfwPostEmptyEvent(void)
|
|||
_GLFW_REQUIRE_INIT();
|
||||
_glfwPlatformPostEmptyEvent();
|
||||
}
|
||||
|
||||
|
|
25
raylib/external/glfw/src/wl_init.c
vendored
25
raylib/external/glfw/src/wl_init.c
vendored
|
@ -26,7 +26,7 @@
|
|||
// It is fine to use C99 in this file because it will not be built with VS
|
||||
//========================================================================
|
||||
|
||||
//#define _POSIX_C_SOURCE 199309L
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
@ -341,9 +341,9 @@ static void pointerHandleAxis(void* data,
|
|||
axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
|
||||
|
||||
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
|
||||
x = wl_fixed_to_double(value) * scrollFactor;
|
||||
x = -wl_fixed_to_double(value) * scrollFactor;
|
||||
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||
y = wl_fixed_to_double(value) * scrollFactor;
|
||||
y = -wl_fixed_to_double(value) * scrollFactor;
|
||||
|
||||
_glfwInputScroll(window, x, y);
|
||||
}
|
||||
|
@ -1038,6 +1038,8 @@ int _glfwPlatformInit(void)
|
|||
char *cursorSizeEnd;
|
||||
long cursorSizeLong;
|
||||
int cursorSize;
|
||||
int i;
|
||||
_GLFWmonitor* monitor;
|
||||
|
||||
_glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
|
||||
if (!_glfw.wl.cursor.handle)
|
||||
|
@ -1146,10 +1148,16 @@ int _glfwPlatformInit(void)
|
|||
// Sync so we got all initial output events
|
||||
wl_display_roundtrip(_glfw.wl.display);
|
||||
|
||||
#ifdef __linux__
|
||||
if (!_glfwInitJoysticksLinux())
|
||||
return GLFW_FALSE;
|
||||
#endif
|
||||
for (i = 0; i < _glfw.monitorCount; ++i)
|
||||
{
|
||||
monitor = _glfw.monitors[i];
|
||||
if (monitor->widthMM <= 0 || monitor->heightMM <= 0)
|
||||
{
|
||||
// If Wayland does not provide a physical size, assume the default 96 DPI
|
||||
monitor->widthMM = (int) (monitor->modes[monitor->wl.currentMode].width * 25.4f / 96.f);
|
||||
monitor->heightMM = (int) (monitor->modes[monitor->wl.currentMode].height * 25.4f / 96.f);
|
||||
}
|
||||
}
|
||||
|
||||
_glfwInitTimerPOSIX();
|
||||
|
||||
|
@ -1213,9 +1221,6 @@ int _glfwPlatformInit(void)
|
|||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
#ifdef __linux__
|
||||
_glfwTerminateJoysticksLinux();
|
||||
#endif
|
||||
_glfwTerminateEGL();
|
||||
if (_glfw.wl.egl.handle)
|
||||
{
|
||||
|
|
4
raylib/external/glfw/src/wl_monitor.c
vendored
4
raylib/external/glfw/src/wl_monitor.c
vendored
|
@ -199,7 +199,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|||
|
||||
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||
"Wayland: Gamma ramp access is not available");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
|||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor,
|
||||
const GLFWgammaramp* ramp)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||
"Wayland: Gamma ramp access is not available");
|
||||
}
|
||||
|
||||
|
|
5
raylib/external/glfw/src/wl_platform.h
vendored
5
raylib/external/glfw/src/wl_platform.h
vendored
|
@ -53,8 +53,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
|||
#include "null_joystick.h"
|
||||
#endif
|
||||
#include "xkb_unicode.h"
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
#include "wayland-xdg-shell-client-protocol.h"
|
||||
#include "wayland-xdg-decoration-client-protocol.h"
|
||||
|
@ -67,9 +65,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
|||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->wl.native)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.wl.display)
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWayland wl
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWayland wl
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl
|
||||
|
|
86
raylib/external/glfw/src/wl_window.c
vendored
86
raylib/external/glfw/src/wl_window.c
vendored
|
@ -142,8 +142,8 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
|
|||
if (fd < 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Creating a buffer file for %d B failed: %m",
|
||||
length);
|
||||
"Wayland: Creating a buffer file for %d B failed: %s",
|
||||
length, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
|
|||
if (data == MAP_FAILED)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: mmap failed: %m");
|
||||
"Wayland: mmap failed: %s", strerror(errno));
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -749,10 +749,17 @@ static void handleEvents(int timeout)
|
|||
if (read_ret != 8)
|
||||
return;
|
||||
|
||||
for (i = 0; i < repeats; ++i)
|
||||
_glfwInputKey(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastKey,
|
||||
_glfw.wl.keyboardLastScancode, GLFW_REPEAT,
|
||||
_glfw.wl.xkb.modifiers);
|
||||
if (_glfw.wl.keyboardFocus)
|
||||
{
|
||||
for (i = 0; i < repeats; ++i)
|
||||
{
|
||||
_glfwInputKey(_glfw.wl.keyboardFocus,
|
||||
_glfw.wl.keyboardLastKey,
|
||||
_glfw.wl.keyboardLastScancode,
|
||||
GLFW_REPEAT,
|
||||
_glfw.wl.xkb.modifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fds[2].revents & POLLIN)
|
||||
|
@ -883,8 +890,8 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
|||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
int count, const GLFWimage* images)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Setting window icon not supported");
|
||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||
"Wayland: The platform does not support setting the window icon");
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
|
@ -892,16 +899,16 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
|||
// A Wayland client is not aware of its position, so just warn and leave it
|
||||
// as (0, 0)
|
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Window position retrieval not supported");
|
||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||
"Wayland: The platform does not provide the window position");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||
{
|
||||
// A Wayland client can not set its position, so just warn
|
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Window position setting not supported");
|
||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||
"Wayland: The platform does not support setting the window position");
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||
|
@ -940,14 +947,18 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window,
|
|||
{
|
||||
// TODO: find out how to trigger a resize.
|
||||
// The actual limits are checked in the xdg_toplevel::configure handler.
|
||||
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||
"Wayland: Window aspect ratio not yet implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window,
|
||||
int* width, int* height)
|
||||
{
|
||||
_glfwPlatformGetWindowSize(window, width, height);
|
||||
*width *= window->wl.scale;
|
||||
*height *= window->wl.scale;
|
||||
if (width)
|
||||
*width *= window->wl.scale;
|
||||
if (height)
|
||||
*height *= window->wl.scale;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
|
@ -1030,14 +1041,14 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
|
|||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
{
|
||||
// TODO
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||
"Wayland: Window attention request not implemented yet");
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Focusing a window requires user interaction");
|
||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||
"Wayland: The platform does not support setting the input focus");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
|
@ -1096,7 +1107,7 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
|||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
// TODO
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||
"Wayland: Window attribute setting not implemented yet");
|
||||
}
|
||||
|
||||
|
@ -1114,10 +1125,23 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
|||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
// TODO
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||
"Wayland: Window attribute setting not implemented yet");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
struct wl_region* region = wl_compositor_create_region(_glfw.wl.compositor);
|
||||
wl_surface_set_input_region(window->wl.surface, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
else
|
||||
wl_surface_set_input_region(window->wl.surface, 0);
|
||||
wl_surface_commit(window->wl.surface);
|
||||
}
|
||||
|
||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||
{
|
||||
return 1.f;
|
||||
|
@ -1125,6 +1149,8 @@ float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
|||
|
||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||
{
|
||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||
"Wayland: The platform does not support setting the window opacity");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
|
||||
|
@ -1186,6 +1212,8 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
|||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
// TODO
|
||||
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||
"Wayland: Key names not yet implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1671,6 +1699,24 @@ const char* _glfwPlatformGetClipboardString(void)
|
|||
return _glfw.wl.clipboardString;
|
||||
}
|
||||
|
||||
EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs)
|
||||
{
|
||||
if (_glfw.egl.EXT_platform_base && _glfw.egl.EXT_platform_wayland)
|
||||
return EGL_PLATFORM_WAYLAND_EXT;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void)
|
||||
{
|
||||
return _glfw.wl.display;
|
||||
}
|
||||
|
||||
EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window)
|
||||
{
|
||||
return window->wl.native;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_wayland_surface)
|
||||
|
|
665
raylib/external/glfw/src/x11_init.c
vendored
665
raylib/external/glfw/src/x11_init.c
vendored
|
@ -29,8 +29,6 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#include <X11/Xresource.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
@ -39,24 +37,15 @@
|
|||
#include <unistd.h>
|
||||
|
||||
|
||||
// Translate an X11 key code to a GLFW key code.
|
||||
// Translate the X11 KeySyms for a key to a GLFW key code
|
||||
// NOTE: This is only used as a fallback, in case the XKB method fails
|
||||
// It is layout-dependent and will fail partially on most non-US layouts
|
||||
//
|
||||
static int translateKeyCode(int scancode)
|
||||
static int translateKeySyms(const KeySym* keysyms, int width)
|
||||
{
|
||||
int keySym;
|
||||
|
||||
// Valid key code range is [8,255], according to the Xlib manual
|
||||
if (scancode < 8 || scancode > 255)
|
||||
return GLFW_KEY_UNKNOWN;
|
||||
|
||||
if (_glfw.x11.xkb.available)
|
||||
if (width > 1)
|
||||
{
|
||||
// Try secondary keysym, for numeric keypad keys
|
||||
// Note: This way we always force "NumLock = ON", which is intentional
|
||||
// since the returned key code should correspond to a physical
|
||||
// location.
|
||||
keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 1);
|
||||
switch (keySym)
|
||||
switch (keysyms[1])
|
||||
{
|
||||
case XK_KP_0: return GLFW_KEY_KP_0;
|
||||
case XK_KP_1: return GLFW_KEY_KP_1;
|
||||
|
@ -74,22 +63,9 @@ static int translateKeyCode(int scancode)
|
|||
case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Now try primary keysym for function keys (non-printable keys)
|
||||
// These should not depend on the current keyboard layout
|
||||
keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int dummy;
|
||||
KeySym* keySyms;
|
||||
|
||||
keySyms = XGetKeyboardMapping(_glfw.x11.display, scancode, 1, &dummy);
|
||||
keySym = keySyms[0];
|
||||
XFree(keySyms);
|
||||
}
|
||||
|
||||
switch (keySym)
|
||||
switch (keysyms[0])
|
||||
{
|
||||
case XK_Escape: return GLFW_KEY_ESCAPE;
|
||||
case XK_Tab: return GLFW_KEY_TAB;
|
||||
|
@ -233,7 +209,7 @@ static int translateKeyCode(int scancode)
|
|||
//
|
||||
static void createKeyTables(void)
|
||||
{
|
||||
int scancode, key;
|
||||
int scancode, scancodeMin, scancodeMax;
|
||||
|
||||
memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes));
|
||||
memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes));
|
||||
|
@ -243,89 +219,217 @@ static void createKeyTables(void)
|
|||
// Use XKB to determine physical key locations independently of the
|
||||
// current keyboard layout
|
||||
|
||||
char name[XkbKeyNameLength + 1];
|
||||
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
|
||||
XkbGetNames(_glfw.x11.display, XkbKeyNamesMask, desc);
|
||||
XkbGetNames(_glfw.x11.display, XkbKeyNamesMask | XkbKeyAliasesMask, desc);
|
||||
|
||||
scancodeMin = desc->min_key_code;
|
||||
scancodeMax = desc->max_key_code;
|
||||
|
||||
const struct
|
||||
{
|
||||
int key;
|
||||
char* name;
|
||||
} keymap[] =
|
||||
{
|
||||
{ GLFW_KEY_GRAVE_ACCENT, "TLDE" },
|
||||
{ GLFW_KEY_1, "AE01" },
|
||||
{ GLFW_KEY_2, "AE02" },
|
||||
{ GLFW_KEY_3, "AE03" },
|
||||
{ GLFW_KEY_4, "AE04" },
|
||||
{ GLFW_KEY_5, "AE05" },
|
||||
{ GLFW_KEY_6, "AE06" },
|
||||
{ GLFW_KEY_7, "AE07" },
|
||||
{ GLFW_KEY_8, "AE08" },
|
||||
{ GLFW_KEY_9, "AE09" },
|
||||
{ GLFW_KEY_0, "AE10" },
|
||||
{ GLFW_KEY_MINUS, "AE11" },
|
||||
{ GLFW_KEY_EQUAL, "AE12" },
|
||||
{ GLFW_KEY_Q, "AD01" },
|
||||
{ GLFW_KEY_W, "AD02" },
|
||||
{ GLFW_KEY_E, "AD03" },
|
||||
{ GLFW_KEY_R, "AD04" },
|
||||
{ GLFW_KEY_T, "AD05" },
|
||||
{ GLFW_KEY_Y, "AD06" },
|
||||
{ GLFW_KEY_U, "AD07" },
|
||||
{ GLFW_KEY_I, "AD08" },
|
||||
{ GLFW_KEY_O, "AD09" },
|
||||
{ GLFW_KEY_P, "AD10" },
|
||||
{ GLFW_KEY_LEFT_BRACKET, "AD11" },
|
||||
{ GLFW_KEY_RIGHT_BRACKET, "AD12" },
|
||||
{ GLFW_KEY_A, "AC01" },
|
||||
{ GLFW_KEY_S, "AC02" },
|
||||
{ GLFW_KEY_D, "AC03" },
|
||||
{ GLFW_KEY_F, "AC04" },
|
||||
{ GLFW_KEY_G, "AC05" },
|
||||
{ GLFW_KEY_H, "AC06" },
|
||||
{ GLFW_KEY_J, "AC07" },
|
||||
{ GLFW_KEY_K, "AC08" },
|
||||
{ GLFW_KEY_L, "AC09" },
|
||||
{ GLFW_KEY_SEMICOLON, "AC10" },
|
||||
{ GLFW_KEY_APOSTROPHE, "AC11" },
|
||||
{ GLFW_KEY_Z, "AB01" },
|
||||
{ GLFW_KEY_X, "AB02" },
|
||||
{ GLFW_KEY_C, "AB03" },
|
||||
{ GLFW_KEY_V, "AB04" },
|
||||
{ GLFW_KEY_B, "AB05" },
|
||||
{ GLFW_KEY_N, "AB06" },
|
||||
{ GLFW_KEY_M, "AB07" },
|
||||
{ GLFW_KEY_COMMA, "AB08" },
|
||||
{ GLFW_KEY_PERIOD, "AB09" },
|
||||
{ GLFW_KEY_SLASH, "AB10" },
|
||||
{ GLFW_KEY_BACKSLASH, "BKSL" },
|
||||
{ GLFW_KEY_WORLD_1, "LSGT" },
|
||||
{ GLFW_KEY_SPACE, "SPCE" },
|
||||
{ GLFW_KEY_ESCAPE, "ESC" },
|
||||
{ GLFW_KEY_ENTER, "RTRN" },
|
||||
{ GLFW_KEY_TAB, "TAB" },
|
||||
{ GLFW_KEY_BACKSPACE, "BKSP" },
|
||||
{ GLFW_KEY_INSERT, "INS" },
|
||||
{ GLFW_KEY_DELETE, "DELE" },
|
||||
{ GLFW_KEY_RIGHT, "RGHT" },
|
||||
{ GLFW_KEY_LEFT, "LEFT" },
|
||||
{ GLFW_KEY_DOWN, "DOWN" },
|
||||
{ GLFW_KEY_UP, "UP" },
|
||||
{ GLFW_KEY_PAGE_UP, "PGUP" },
|
||||
{ GLFW_KEY_PAGE_DOWN, "PGDN" },
|
||||
{ GLFW_KEY_HOME, "HOME" },
|
||||
{ GLFW_KEY_END, "END" },
|
||||
{ GLFW_KEY_CAPS_LOCK, "CAPS" },
|
||||
{ GLFW_KEY_SCROLL_LOCK, "SCLK" },
|
||||
{ GLFW_KEY_NUM_LOCK, "NMLK" },
|
||||
{ GLFW_KEY_PRINT_SCREEN, "PRSC" },
|
||||
{ GLFW_KEY_PAUSE, "PAUS" },
|
||||
{ GLFW_KEY_F1, "FK01" },
|
||||
{ GLFW_KEY_F2, "FK02" },
|
||||
{ GLFW_KEY_F3, "FK03" },
|
||||
{ GLFW_KEY_F4, "FK04" },
|
||||
{ GLFW_KEY_F5, "FK05" },
|
||||
{ GLFW_KEY_F6, "FK06" },
|
||||
{ GLFW_KEY_F7, "FK07" },
|
||||
{ GLFW_KEY_F8, "FK08" },
|
||||
{ GLFW_KEY_F9, "FK09" },
|
||||
{ GLFW_KEY_F10, "FK10" },
|
||||
{ GLFW_KEY_F11, "FK11" },
|
||||
{ GLFW_KEY_F12, "FK12" },
|
||||
{ GLFW_KEY_F13, "FK13" },
|
||||
{ GLFW_KEY_F14, "FK14" },
|
||||
{ GLFW_KEY_F15, "FK15" },
|
||||
{ GLFW_KEY_F16, "FK16" },
|
||||
{ GLFW_KEY_F17, "FK17" },
|
||||
{ GLFW_KEY_F18, "FK18" },
|
||||
{ GLFW_KEY_F19, "FK19" },
|
||||
{ GLFW_KEY_F20, "FK20" },
|
||||
{ GLFW_KEY_F21, "FK21" },
|
||||
{ GLFW_KEY_F22, "FK22" },
|
||||
{ GLFW_KEY_F23, "FK23" },
|
||||
{ GLFW_KEY_F24, "FK24" },
|
||||
{ GLFW_KEY_F25, "FK25" },
|
||||
{ GLFW_KEY_KP_0, "KP0" },
|
||||
{ GLFW_KEY_KP_1, "KP1" },
|
||||
{ GLFW_KEY_KP_2, "KP2" },
|
||||
{ GLFW_KEY_KP_3, "KP3" },
|
||||
{ GLFW_KEY_KP_4, "KP4" },
|
||||
{ GLFW_KEY_KP_5, "KP5" },
|
||||
{ GLFW_KEY_KP_6, "KP6" },
|
||||
{ GLFW_KEY_KP_7, "KP7" },
|
||||
{ GLFW_KEY_KP_8, "KP8" },
|
||||
{ GLFW_KEY_KP_9, "KP9" },
|
||||
{ GLFW_KEY_KP_DECIMAL, "KPDL" },
|
||||
{ GLFW_KEY_KP_DIVIDE, "KPDV" },
|
||||
{ GLFW_KEY_KP_MULTIPLY, "KPMU" },
|
||||
{ GLFW_KEY_KP_SUBTRACT, "KPSU" },
|
||||
{ GLFW_KEY_KP_ADD, "KPAD" },
|
||||
{ GLFW_KEY_KP_ENTER, "KPEN" },
|
||||
{ GLFW_KEY_KP_EQUAL, "KPEQ" },
|
||||
{ GLFW_KEY_LEFT_SHIFT, "LFSH" },
|
||||
{ GLFW_KEY_LEFT_CONTROL, "LCTL" },
|
||||
{ GLFW_KEY_LEFT_ALT, "LALT" },
|
||||
{ GLFW_KEY_LEFT_SUPER, "LWIN" },
|
||||
{ GLFW_KEY_RIGHT_SHIFT, "RTSH" },
|
||||
{ GLFW_KEY_RIGHT_CONTROL, "RCTL" },
|
||||
{ GLFW_KEY_RIGHT_ALT, "RALT" },
|
||||
{ GLFW_KEY_RIGHT_ALT, "LVL3" },
|
||||
{ GLFW_KEY_RIGHT_ALT, "MDSW" },
|
||||
{ GLFW_KEY_RIGHT_SUPER, "RWIN" },
|
||||
{ GLFW_KEY_MENU, "MENU" }
|
||||
};
|
||||
|
||||
// Find the X11 key code -> GLFW key code mapping
|
||||
for (scancode = desc->min_key_code; scancode <= desc->max_key_code; scancode++)
|
||||
for (scancode = scancodeMin; scancode <= scancodeMax; scancode++)
|
||||
{
|
||||
memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength);
|
||||
name[XkbKeyNameLength] = '\0';
|
||||
int key = GLFW_KEY_UNKNOWN;
|
||||
|
||||
// Map the key name to a GLFW key code. Note: We only map printable
|
||||
// keys here, and we use the US keyboard layout. The rest of the
|
||||
// keys (function keys) are mapped using traditional KeySym
|
||||
// translations.
|
||||
if (strcmp(name, "TLDE") == 0) key = GLFW_KEY_GRAVE_ACCENT;
|
||||
else if (strcmp(name, "AE01") == 0) key = GLFW_KEY_1;
|
||||
else if (strcmp(name, "AE02") == 0) key = GLFW_KEY_2;
|
||||
else if (strcmp(name, "AE03") == 0) key = GLFW_KEY_3;
|
||||
else if (strcmp(name, "AE04") == 0) key = GLFW_KEY_4;
|
||||
else if (strcmp(name, "AE05") == 0) key = GLFW_KEY_5;
|
||||
else if (strcmp(name, "AE06") == 0) key = GLFW_KEY_6;
|
||||
else if (strcmp(name, "AE07") == 0) key = GLFW_KEY_7;
|
||||
else if (strcmp(name, "AE08") == 0) key = GLFW_KEY_8;
|
||||
else if (strcmp(name, "AE09") == 0) key = GLFW_KEY_9;
|
||||
else if (strcmp(name, "AE10") == 0) key = GLFW_KEY_0;
|
||||
else if (strcmp(name, "AE11") == 0) key = GLFW_KEY_MINUS;
|
||||
else if (strcmp(name, "AE12") == 0) key = GLFW_KEY_EQUAL;
|
||||
else if (strcmp(name, "AD01") == 0) key = GLFW_KEY_Q;
|
||||
else if (strcmp(name, "AD02") == 0) key = GLFW_KEY_W;
|
||||
else if (strcmp(name, "AD03") == 0) key = GLFW_KEY_E;
|
||||
else if (strcmp(name, "AD04") == 0) key = GLFW_KEY_R;
|
||||
else if (strcmp(name, "AD05") == 0) key = GLFW_KEY_T;
|
||||
else if (strcmp(name, "AD06") == 0) key = GLFW_KEY_Y;
|
||||
else if (strcmp(name, "AD07") == 0) key = GLFW_KEY_U;
|
||||
else if (strcmp(name, "AD08") == 0) key = GLFW_KEY_I;
|
||||
else if (strcmp(name, "AD09") == 0) key = GLFW_KEY_O;
|
||||
else if (strcmp(name, "AD10") == 0) key = GLFW_KEY_P;
|
||||
else if (strcmp(name, "AD11") == 0) key = GLFW_KEY_LEFT_BRACKET;
|
||||
else if (strcmp(name, "AD12") == 0) key = GLFW_KEY_RIGHT_BRACKET;
|
||||
else if (strcmp(name, "AC01") == 0) key = GLFW_KEY_A;
|
||||
else if (strcmp(name, "AC02") == 0) key = GLFW_KEY_S;
|
||||
else if (strcmp(name, "AC03") == 0) key = GLFW_KEY_D;
|
||||
else if (strcmp(name, "AC04") == 0) key = GLFW_KEY_F;
|
||||
else if (strcmp(name, "AC05") == 0) key = GLFW_KEY_G;
|
||||
else if (strcmp(name, "AC06") == 0) key = GLFW_KEY_H;
|
||||
else if (strcmp(name, "AC07") == 0) key = GLFW_KEY_J;
|
||||
else if (strcmp(name, "AC08") == 0) key = GLFW_KEY_K;
|
||||
else if (strcmp(name, "AC09") == 0) key = GLFW_KEY_L;
|
||||
else if (strcmp(name, "AC10") == 0) key = GLFW_KEY_SEMICOLON;
|
||||
else if (strcmp(name, "AC11") == 0) key = GLFW_KEY_APOSTROPHE;
|
||||
else if (strcmp(name, "AB01") == 0) key = GLFW_KEY_Z;
|
||||
else if (strcmp(name, "AB02") == 0) key = GLFW_KEY_X;
|
||||
else if (strcmp(name, "AB03") == 0) key = GLFW_KEY_C;
|
||||
else if (strcmp(name, "AB04") == 0) key = GLFW_KEY_V;
|
||||
else if (strcmp(name, "AB05") == 0) key = GLFW_KEY_B;
|
||||
else if (strcmp(name, "AB06") == 0) key = GLFW_KEY_N;
|
||||
else if (strcmp(name, "AB07") == 0) key = GLFW_KEY_M;
|
||||
else if (strcmp(name, "AB08") == 0) key = GLFW_KEY_COMMA;
|
||||
else if (strcmp(name, "AB09") == 0) key = GLFW_KEY_PERIOD;
|
||||
else if (strcmp(name, "AB10") == 0) key = GLFW_KEY_SLASH;
|
||||
else if (strcmp(name, "BKSL") == 0) key = GLFW_KEY_BACKSLASH;
|
||||
else if (strcmp(name, "LSGT") == 0) key = GLFW_KEY_WORLD_1;
|
||||
else key = GLFW_KEY_UNKNOWN;
|
||||
// Map the key name to a GLFW key code. Note: We use the US
|
||||
// keyboard layout. Because function keys aren't mapped correctly
|
||||
// when using traditional KeySym translations, they are mapped
|
||||
// here instead.
|
||||
for (int i = 0; i < sizeof(keymap) / sizeof(keymap[0]); i++)
|
||||
{
|
||||
if (strncmp(desc->names->keys[scancode].name,
|
||||
keymap[i].name,
|
||||
XkbKeyNameLength) == 0)
|
||||
{
|
||||
key = keymap[i].key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((scancode >= 0) && (scancode < 256))
|
||||
_glfw.x11.keycodes[scancode] = key;
|
||||
// Fall back to key aliases in case the key name did not match
|
||||
for (int i = 0; i < desc->names->num_key_aliases; i++)
|
||||
{
|
||||
if (key != GLFW_KEY_UNKNOWN)
|
||||
break;
|
||||
|
||||
if (strncmp(desc->names->key_aliases[i].real,
|
||||
desc->names->keys[scancode].name,
|
||||
XkbKeyNameLength) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < sizeof(keymap) / sizeof(keymap[0]); j++)
|
||||
{
|
||||
if (strncmp(desc->names->key_aliases[i].alias,
|
||||
keymap[j].name,
|
||||
XkbKeyNameLength) == 0)
|
||||
{
|
||||
key = keymap[j].key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_glfw.x11.keycodes[scancode] = key;
|
||||
}
|
||||
|
||||
XkbFreeNames(desc, XkbKeyNamesMask, True);
|
||||
XkbFreeKeyboard(desc, 0, True);
|
||||
}
|
||||
else
|
||||
XDisplayKeycodes(_glfw.x11.display, &scancodeMin, &scancodeMax);
|
||||
|
||||
for (scancode = 0; scancode < 256; scancode++)
|
||||
int width;
|
||||
KeySym* keysyms = XGetKeyboardMapping(_glfw.x11.display,
|
||||
scancodeMin,
|
||||
scancodeMax - scancodeMin + 1,
|
||||
&width);
|
||||
|
||||
for (scancode = scancodeMin; scancode <= scancodeMax; scancode++)
|
||||
{
|
||||
// Translate the un-translated key codes using traditional X11 KeySym
|
||||
// lookups
|
||||
if (_glfw.x11.keycodes[scancode] < 0)
|
||||
_glfw.x11.keycodes[scancode] = translateKeyCode(scancode);
|
||||
{
|
||||
const size_t base = (scancode - scancodeMin) * width;
|
||||
_glfw.x11.keycodes[scancode] = translateKeySyms(&keysyms[base], width);
|
||||
}
|
||||
|
||||
// Store the reverse translation for faster key name lookup
|
||||
if (_glfw.x11.keycodes[scancode] > 0)
|
||||
_glfw.x11.scancodes[_glfw.x11.keycodes[scancode]] = scancode;
|
||||
}
|
||||
|
||||
XFree(keysyms);
|
||||
}
|
||||
|
||||
// Check whether the IM has a usable style
|
||||
|
@ -351,15 +455,49 @@ static GLFWbool hasUsableInputMethodStyle(void)
|
|||
return found;
|
||||
}
|
||||
|
||||
// Check whether the specified atom is supported
|
||||
static void inputMethodDestroyCallback(XIM im, XPointer clientData, XPointer callData)
|
||||
{
|
||||
_glfw.x11.im = NULL;
|
||||
}
|
||||
|
||||
static void inputMethodInstantiateCallback(Display* display,
|
||||
XPointer clientData,
|
||||
XPointer callData)
|
||||
{
|
||||
if (_glfw.x11.im)
|
||||
return;
|
||||
|
||||
_glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL);
|
||||
if (_glfw.x11.im)
|
||||
{
|
||||
if (!hasUsableInputMethodStyle())
|
||||
{
|
||||
XCloseIM(_glfw.x11.im);
|
||||
_glfw.x11.im = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.x11.im)
|
||||
{
|
||||
XIMCallback callback;
|
||||
callback.callback = (XIMProc) inputMethodDestroyCallback;
|
||||
callback.client_data = NULL;
|
||||
XSetIMValues(_glfw.x11.im, XNDestroyCallback, &callback, NULL);
|
||||
|
||||
for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next)
|
||||
_glfwCreateInputContextX11(window);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the atom ID only if it is listed in the specified array
|
||||
//
|
||||
static Atom getSupportedAtom(Atom* supportedAtoms,
|
||||
unsigned long atomCount,
|
||||
const char* atomName)
|
||||
static Atom getAtomIfSupported(Atom* supportedAtoms,
|
||||
unsigned long atomCount,
|
||||
const char* atomName)
|
||||
{
|
||||
const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
|
||||
|
||||
for (unsigned int i = 0; i < atomCount; i++)
|
||||
for (unsigned long i = 0; i < atomCount; i++)
|
||||
{
|
||||
if (supportedAtoms[i] == atom)
|
||||
return atom;
|
||||
|
@ -427,33 +565,33 @@ static void detectEWMH(void)
|
|||
// See which of the atoms we support that are supported by the WM
|
||||
|
||||
_glfw.x11.NET_WM_STATE =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE");
|
||||
_glfw.x11.NET_WM_STATE_ABOVE =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");
|
||||
_glfw.x11.NET_WM_STATE_FULLSCREEN =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
|
||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
|
||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");
|
||||
_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
|
||||
_glfw.x11.NET_WM_FULLSCREEN_MONITORS =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
|
||||
_glfw.x11.NET_WM_WINDOW_TYPE =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
|
||||
_glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
|
||||
_glfw.x11.NET_WORKAREA =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WORKAREA");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WORKAREA");
|
||||
_glfw.x11.NET_CURRENT_DESKTOP =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
|
||||
_glfw.x11.NET_ACTIVE_WINDOW =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
|
||||
_glfw.x11.NET_FRAME_EXTENTS =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");
|
||||
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
||||
|
||||
if (supportedAtoms)
|
||||
XFree(supportedAtoms);
|
||||
|
@ -667,13 +805,12 @@ static GLFWbool initExtensions(void)
|
|||
_glfw.x11.xkb.detectable = GLFW_TRUE;
|
||||
}
|
||||
|
||||
_glfw.x11.xkb.group = 0;
|
||||
XkbStateRec state;
|
||||
if (XkbGetState(_glfw.x11.display, XkbUseCoreKbd, &state) == Success)
|
||||
{
|
||||
XkbSelectEventDetails(_glfw.x11.display, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask);
|
||||
_glfw.x11.xkb.group = (unsigned int)state.group;
|
||||
}
|
||||
|
||||
XkbSelectEventDetails(_glfw.x11.display, XkbUseCoreKbd, XkbStateNotify,
|
||||
XkbGroupStateMask, XkbGroupStateMask);
|
||||
}
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
|
@ -714,6 +851,35 @@ static GLFWbool initExtensions(void)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xshape.handle = _glfw_dlopen("libXext-6.so");
|
||||
#else
|
||||
_glfw.x11.xshape.handle = _glfw_dlopen("libXext.so.6");
|
||||
#endif
|
||||
if (_glfw.x11.xshape.handle)
|
||||
{
|
||||
_glfw.x11.xshape.QueryExtension = (PFN_XShapeQueryExtension)
|
||||
_glfw_dlsym(_glfw.x11.xshape.handle, "XShapeQueryExtension");
|
||||
_glfw.x11.xshape.ShapeCombineRegion = (PFN_XShapeCombineRegion)
|
||||
_glfw_dlsym(_glfw.x11.xshape.handle, "XShapeCombineRegion");
|
||||
_glfw.x11.xshape.QueryVersion = (PFN_XShapeQueryVersion)
|
||||
_glfw_dlsym(_glfw.x11.xshape.handle, "XShapeQueryVersion");
|
||||
_glfw.x11.xshape.ShapeCombineMask = (PFN_XShapeCombineMask)
|
||||
_glfw_dlsym(_glfw.x11.xshape.handle, "XShapeCombineMask");
|
||||
|
||||
if (XShapeQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.xshape.errorBase,
|
||||
&_glfw.x11.xshape.eventBase))
|
||||
{
|
||||
if (XShapeQueryVersion(_glfw.x11.display,
|
||||
&_glfw.x11.xshape.major,
|
||||
&_glfw.x11.xshape.minor))
|
||||
{
|
||||
_glfw.x11.xshape.available = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the key code LUT
|
||||
// FIXME: We should listen to XkbMapNotify events to track changes to
|
||||
// the keyboard mapping.
|
||||
|
@ -858,6 +1024,9 @@ static Window createHelperWindow(void)
|
|||
//
|
||||
static int errorHandler(Display *display, XErrorEvent* event)
|
||||
{
|
||||
if (_glfw.x11.display != display)
|
||||
return 0;
|
||||
|
||||
_glfw.x11.errorCode = event->error_code;
|
||||
return 0;
|
||||
}
|
||||
|
@ -938,15 +1107,231 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
|
|||
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
#if !defined(X_HAVE_UTF8_STRING)
|
||||
// HACK: If the current locale is "C" and the Xlib UTF-8 functions are
|
||||
// unavailable, apply the environment's locale in the hope that it's
|
||||
// both available and not "C"
|
||||
// This is done because the "C" locale breaks wide character input,
|
||||
// which is what we fall back on when UTF-8 support is missing
|
||||
// HACK: If the application has left the locale as "C" then both wide
|
||||
// character text input and explicit UTF-8 input via XIM will break
|
||||
// This sets the CTYPE part of the current locale from the environment
|
||||
// in the hope that it is set to something more sane than "C"
|
||||
if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xlib.handle = _glfw_dlopen("libX11-6.so");
|
||||
#else
|
||||
_glfw.x11.xlib.handle = _glfw_dlopen("libX11.so.6");
|
||||
#endif
|
||||
if (!_glfw.x11.xlib.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to load Xlib");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.x11.xlib.AllocClassHint = (PFN_XAllocClassHint)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XAllocClassHint");
|
||||
_glfw.x11.xlib.AllocSizeHints = (PFN_XAllocSizeHints)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XAllocSizeHints");
|
||||
_glfw.x11.xlib.AllocWMHints = (PFN_XAllocWMHints)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XAllocWMHints");
|
||||
_glfw.x11.xlib.ChangeProperty = (PFN_XChangeProperty)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XChangeProperty");
|
||||
_glfw.x11.xlib.ChangeWindowAttributes = (PFN_XChangeWindowAttributes)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XChangeWindowAttributes");
|
||||
_glfw.x11.xlib.CheckIfEvent = (PFN_XCheckIfEvent)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XCheckIfEvent");
|
||||
_glfw.x11.xlib.CheckTypedWindowEvent = (PFN_XCheckTypedWindowEvent)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XCheckTypedWindowEvent");
|
||||
_glfw.x11.xlib.CloseDisplay = (PFN_XCloseDisplay)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XCloseDisplay");
|
||||
_glfw.x11.xlib.CloseIM = (PFN_XCloseIM)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XCloseIM");
|
||||
_glfw.x11.xlib.ConvertSelection = (PFN_XConvertSelection)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XConvertSelection");
|
||||
_glfw.x11.xlib.CreateColormap = (PFN_XCreateColormap)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateColormap");
|
||||
_glfw.x11.xlib.CreateFontCursor = (PFN_XCreateFontCursor)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateFontCursor");
|
||||
_glfw.x11.xlib.CreateIC = (PFN_XCreateIC)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateIC");
|
||||
_glfw.x11.xlib.CreateRegion = (PFN_XCreateRegion)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateRegion");
|
||||
_glfw.x11.xlib.CreateWindow = (PFN_XCreateWindow)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateWindow");
|
||||
_glfw.x11.xlib.DefineCursor = (PFN_XDefineCursor)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XDefineCursor");
|
||||
_glfw.x11.xlib.DeleteContext = (PFN_XDeleteContext)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XDeleteContext");
|
||||
_glfw.x11.xlib.DeleteProperty = (PFN_XDeleteProperty)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XDeleteProperty");
|
||||
_glfw.x11.xlib.DestroyIC = (PFN_XDestroyIC)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyIC");
|
||||
_glfw.x11.xlib.DestroyRegion = (PFN_XDestroyRegion)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyRegion");
|
||||
_glfw.x11.xlib.DestroyWindow = (PFN_XDestroyWindow)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyWindow");
|
||||
_glfw.x11.xlib.DisplayKeycodes = (PFN_XDisplayKeycodes)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XDisplayKeycodes");
|
||||
_glfw.x11.xlib.EventsQueued = (PFN_XEventsQueued)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XEventsQueued");
|
||||
_glfw.x11.xlib.FilterEvent = (PFN_XFilterEvent)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XFilterEvent");
|
||||
_glfw.x11.xlib.FindContext = (PFN_XFindContext)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XFindContext");
|
||||
_glfw.x11.xlib.Flush = (PFN_XFlush)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XFlush");
|
||||
_glfw.x11.xlib.Free = (PFN_XFree)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XFree");
|
||||
_glfw.x11.xlib.FreeColormap = (PFN_XFreeColormap)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XFreeColormap");
|
||||
_glfw.x11.xlib.FreeCursor = (PFN_XFreeCursor)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XFreeCursor");
|
||||
_glfw.x11.xlib.FreeEventData = (PFN_XFreeEventData)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XFreeEventData");
|
||||
_glfw.x11.xlib.GetErrorText = (PFN_XGetErrorText)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetErrorText");
|
||||
_glfw.x11.xlib.GetEventData = (PFN_XGetEventData)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetEventData");
|
||||
_glfw.x11.xlib.GetICValues = (PFN_XGetICValues)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetICValues");
|
||||
_glfw.x11.xlib.GetIMValues = (PFN_XGetIMValues)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetIMValues");
|
||||
_glfw.x11.xlib.GetInputFocus = (PFN_XGetInputFocus)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetInputFocus");
|
||||
_glfw.x11.xlib.GetKeyboardMapping = (PFN_XGetKeyboardMapping)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetKeyboardMapping");
|
||||
_glfw.x11.xlib.GetScreenSaver = (PFN_XGetScreenSaver)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetScreenSaver");
|
||||
_glfw.x11.xlib.GetSelectionOwner = (PFN_XGetSelectionOwner)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetSelectionOwner");
|
||||
_glfw.x11.xlib.GetVisualInfo = (PFN_XGetVisualInfo)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetVisualInfo");
|
||||
_glfw.x11.xlib.GetWMNormalHints = (PFN_XGetWMNormalHints)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetWMNormalHints");
|
||||
_glfw.x11.xlib.GetWindowAttributes = (PFN_XGetWindowAttributes)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetWindowAttributes");
|
||||
_glfw.x11.xlib.GetWindowProperty = (PFN_XGetWindowProperty)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetWindowProperty");
|
||||
_glfw.x11.xlib.GrabPointer = (PFN_XGrabPointer)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XGrabPointer");
|
||||
_glfw.x11.xlib.IconifyWindow = (PFN_XIconifyWindow)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XIconifyWindow");
|
||||
_glfw.x11.xlib.InitThreads = (PFN_XInitThreads)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XInitThreads");
|
||||
_glfw.x11.xlib.InternAtom = (PFN_XInternAtom)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XInternAtom");
|
||||
_glfw.x11.xlib.LookupString = (PFN_XLookupString)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XLookupString");
|
||||
_glfw.x11.xlib.MapRaised = (PFN_XMapRaised)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XMapRaised");
|
||||
_glfw.x11.xlib.MapWindow = (PFN_XMapWindow)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XMapWindow");
|
||||
_glfw.x11.xlib.MoveResizeWindow = (PFN_XMoveResizeWindow)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XMoveResizeWindow");
|
||||
_glfw.x11.xlib.MoveWindow = (PFN_XMoveWindow)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XMoveWindow");
|
||||
_glfw.x11.xlib.NextEvent = (PFN_XNextEvent)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XNextEvent");
|
||||
_glfw.x11.xlib.OpenDisplay = (PFN_XOpenDisplay)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XOpenDisplay");
|
||||
_glfw.x11.xlib.OpenIM = (PFN_XOpenIM)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XOpenIM");
|
||||
_glfw.x11.xlib.PeekEvent = (PFN_XPeekEvent)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XPeekEvent");
|
||||
_glfw.x11.xlib.Pending = (PFN_XPending)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XPending");
|
||||
_glfw.x11.xlib.QueryExtension = (PFN_XQueryExtension)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XQueryExtension");
|
||||
_glfw.x11.xlib.QueryPointer = (PFN_XQueryPointer)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XQueryPointer");
|
||||
_glfw.x11.xlib.RaiseWindow = (PFN_XRaiseWindow)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XRaiseWindow");
|
||||
_glfw.x11.xlib.RegisterIMInstantiateCallback = (PFN_XRegisterIMInstantiateCallback)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XRegisterIMInstantiateCallback");
|
||||
_glfw.x11.xlib.ResizeWindow = (PFN_XResizeWindow)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XResizeWindow");
|
||||
_glfw.x11.xlib.ResourceManagerString = (PFN_XResourceManagerString)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XResourceManagerString");
|
||||
_glfw.x11.xlib.SaveContext = (PFN_XSaveContext)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSaveContext");
|
||||
_glfw.x11.xlib.SelectInput = (PFN_XSelectInput)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSelectInput");
|
||||
_glfw.x11.xlib.SendEvent = (PFN_XSendEvent)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSendEvent");
|
||||
_glfw.x11.xlib.SetClassHint = (PFN_XSetClassHint)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetClassHint");
|
||||
_glfw.x11.xlib.SetErrorHandler = (PFN_XSetErrorHandler)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetErrorHandler");
|
||||
_glfw.x11.xlib.SetICFocus = (PFN_XSetICFocus)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetICFocus");
|
||||
_glfw.x11.xlib.SetIMValues = (PFN_XSetIMValues)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetIMValues");
|
||||
_glfw.x11.xlib.SetInputFocus = (PFN_XSetInputFocus)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetInputFocus");
|
||||
_glfw.x11.xlib.SetLocaleModifiers = (PFN_XSetLocaleModifiers)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetLocaleModifiers");
|
||||
_glfw.x11.xlib.SetScreenSaver = (PFN_XSetScreenSaver)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetScreenSaver");
|
||||
_glfw.x11.xlib.SetSelectionOwner = (PFN_XSetSelectionOwner)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetSelectionOwner");
|
||||
_glfw.x11.xlib.SetWMHints = (PFN_XSetWMHints)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetWMHints");
|
||||
_glfw.x11.xlib.SetWMNormalHints = (PFN_XSetWMNormalHints)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetWMNormalHints");
|
||||
_glfw.x11.xlib.SetWMProtocols = (PFN_XSetWMProtocols)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetWMProtocols");
|
||||
_glfw.x11.xlib.SupportsLocale = (PFN_XSupportsLocale)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSupportsLocale");
|
||||
_glfw.x11.xlib.Sync = (PFN_XSync)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XSync");
|
||||
_glfw.x11.xlib.TranslateCoordinates = (PFN_XTranslateCoordinates)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XTranslateCoordinates");
|
||||
_glfw.x11.xlib.UndefineCursor = (PFN_XUndefineCursor)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XUndefineCursor");
|
||||
_glfw.x11.xlib.UngrabPointer = (PFN_XUngrabPointer)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XUngrabPointer");
|
||||
_glfw.x11.xlib.UnmapWindow = (PFN_XUnmapWindow)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XUnmapWindow");
|
||||
_glfw.x11.xlib.UnsetICFocus = (PFN_XUnsetICFocus)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XUnsetICFocus");
|
||||
_glfw.x11.xlib.VisualIDFromVisual = (PFN_XVisualIDFromVisual)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XVisualIDFromVisual");
|
||||
_glfw.x11.xlib.WarpPointer = (PFN_XWarpPointer)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XWarpPointer");
|
||||
_glfw.x11.xkb.FreeKeyboard = (PFN_XkbFreeKeyboard)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbFreeKeyboard");
|
||||
_glfw.x11.xkb.FreeNames = (PFN_XkbFreeNames)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbFreeNames");
|
||||
_glfw.x11.xkb.GetMap = (PFN_XkbGetMap)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbGetMap");
|
||||
_glfw.x11.xkb.GetNames = (PFN_XkbGetNames)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbGetNames");
|
||||
_glfw.x11.xkb.GetState = (PFN_XkbGetState)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbGetState");
|
||||
_glfw.x11.xkb.KeycodeToKeysym = (PFN_XkbKeycodeToKeysym)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbKeycodeToKeysym");
|
||||
_glfw.x11.xkb.QueryExtension = (PFN_XkbQueryExtension)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbQueryExtension");
|
||||
_glfw.x11.xkb.SelectEventDetails = (PFN_XkbSelectEventDetails)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbSelectEventDetails");
|
||||
_glfw.x11.xkb.SetDetectableAutoRepeat = (PFN_XkbSetDetectableAutoRepeat)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbSetDetectableAutoRepeat");
|
||||
_glfw.x11.xrm.DestroyDatabase = (PFN_XrmDestroyDatabase)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XrmDestroyDatabase");
|
||||
_glfw.x11.xrm.GetResource = (PFN_XrmGetResource)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XrmGetResource");
|
||||
_glfw.x11.xrm.GetStringDatabase = (PFN_XrmGetStringDatabase)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XrmGetStringDatabase");
|
||||
_glfw.x11.xrm.Initialize = (PFN_XrmInitialize)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XrmInitialize");
|
||||
_glfw.x11.xrm.UniqueQuark = (PFN_XrmUniqueQuark)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XrmUniqueQuark");
|
||||
_glfw.x11.xlib.UnregisterIMInstantiateCallback = (PFN_XUnregisterIMInstantiateCallback)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "XUnregisterIMInstantiateCallback");
|
||||
_glfw.x11.xlib.utf8LookupString = (PFN_Xutf8LookupString)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "Xutf8LookupString");
|
||||
_glfw.x11.xlib.utf8SetWMProperties = (PFN_Xutf8SetWMProperties)
|
||||
_glfw_dlsym(_glfw.x11.xlib.handle, "Xutf8SetWMProperties");
|
||||
|
||||
if (_glfw.x11.xlib.utf8LookupString && _glfw.x11.xlib.utf8SetWMProperties)
|
||||
_glfw.x11.xlib.utf8 = GLFW_TRUE;
|
||||
|
||||
XInitThreads();
|
||||
XrmInitialize();
|
||||
|
@ -981,26 +1366,17 @@ int _glfwPlatformInit(void)
|
|||
_glfw.x11.helperWindowHandle = createHelperWindow();
|
||||
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
||||
|
||||
if (XSupportsLocale())
|
||||
if (XSupportsLocale() && _glfw.x11.xlib.utf8)
|
||||
{
|
||||
XSetLocaleModifiers("");
|
||||
|
||||
_glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL);
|
||||
if (_glfw.x11.im)
|
||||
{
|
||||
if (!hasUsableInputMethodStyle())
|
||||
{
|
||||
XCloseIM(_glfw.x11.im);
|
||||
_glfw.x11.im = NULL;
|
||||
}
|
||||
}
|
||||
// If an IM is already present our callback will be called right away
|
||||
XRegisterIMInstantiateCallback(_glfw.x11.display,
|
||||
NULL, NULL, NULL,
|
||||
inputMethodInstantiateCallback,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
if (!_glfwInitJoysticksLinux())
|
||||
return GLFW_FALSE;
|
||||
#endif
|
||||
|
||||
_glfwInitTimerPOSIX();
|
||||
|
||||
_glfwPollMonitorsX11();
|
||||
|
@ -1030,6 +1406,11 @@ void _glfwPlatformTerminate(void)
|
|||
free(_glfw.x11.primarySelectionString);
|
||||
free(_glfw.x11.clipboardString);
|
||||
|
||||
XUnregisterIMInstantiateCallback(_glfw.x11.display,
|
||||
NULL, NULL, NULL,
|
||||
inputMethodInstantiateCallback,
|
||||
NULL);
|
||||
|
||||
if (_glfw.x11.im)
|
||||
{
|
||||
XCloseIM(_glfw.x11.im);
|
||||
|
@ -1089,9 +1470,11 @@ void _glfwPlatformTerminate(void)
|
|||
_glfwTerminateEGL();
|
||||
_glfwTerminateGLX();
|
||||
|
||||
#if defined(__linux__)
|
||||
_glfwTerminateJoysticksLinux();
|
||||
#endif
|
||||
if (_glfw.x11.xlib.handle)
|
||||
{
|
||||
_glfw_dlclose(_glfw.x11.xlib.handle);
|
||||
_glfw.x11.xlib.handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
|
|
2
raylib/external/glfw/src/x11_monitor.c
vendored
2
raylib/external/glfw/src/x11_monitor.c
vendored
|
@ -164,7 +164,7 @@ void _glfwPollMonitorsX11(void)
|
|||
if (widthMM <= 0 || heightMM <= 0)
|
||||
{
|
||||
// HACK: If RandR does not provide a physical size, assume the
|
||||
// X11 default 96 DPI and calcuate from the CRTC viewport
|
||||
// X11 default 96 DPI and calculate from the CRTC viewport
|
||||
// NOTE: These members are affected by rotation, unlike the mode
|
||||
// info and output info members
|
||||
widthMM = (int) (ci->width * 25.4f / 96.f);
|
||||
|
|
353
raylib/external/glfw/src/x11_platform.h
vendored
353
raylib/external/glfw/src/x11_platform.h
vendored
|
@ -33,6 +33,7 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xresource.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
// The XRandR extension provides mode setting and gamma control
|
||||
|
@ -47,6 +48,214 @@
|
|||
// The XInput extension provides raw mouse motion input
|
||||
#include <X11/extensions/XInput2.h>
|
||||
|
||||
// The Shape extension provides custom window shapes
|
||||
#include <X11/extensions/shape.h>
|
||||
|
||||
typedef XClassHint* (* PFN_XAllocClassHint)(void);
|
||||
typedef XSizeHints* (* PFN_XAllocSizeHints)(void);
|
||||
typedef XWMHints* (* PFN_XAllocWMHints)(void);
|
||||
typedef int (* PFN_XChangeProperty)(Display*,Window,Atom,Atom,int,int,const unsigned char*,int);
|
||||
typedef int (* PFN_XChangeWindowAttributes)(Display*,Window,unsigned long,XSetWindowAttributes*);
|
||||
typedef Bool (* PFN_XCheckIfEvent)(Display*,XEvent*,Bool(*)(Display*,XEvent*,XPointer),XPointer);
|
||||
typedef Bool (* PFN_XCheckTypedWindowEvent)(Display*,Window,int,XEvent*);
|
||||
typedef int (* PFN_XCloseDisplay)(Display*);
|
||||
typedef Status (* PFN_XCloseIM)(XIM);
|
||||
typedef int (* PFN_XConvertSelection)(Display*,Atom,Atom,Atom,Window,Time);
|
||||
typedef Colormap (* PFN_XCreateColormap)(Display*,Window,Visual*,int);
|
||||
typedef Cursor (* PFN_XCreateFontCursor)(Display*,unsigned int);
|
||||
typedef XIC (* PFN_XCreateIC)(XIM,...);
|
||||
typedef Region (* PFN_XCreateRegion)(void);
|
||||
typedef Window (* PFN_XCreateWindow)(Display*,Window,int,int,unsigned int,unsigned int,unsigned int,int,unsigned int,Visual*,unsigned long,XSetWindowAttributes*);
|
||||
typedef int (* PFN_XDefineCursor)(Display*,Window,Cursor);
|
||||
typedef int (* PFN_XDeleteContext)(Display*,XID,XContext);
|
||||
typedef int (* PFN_XDeleteProperty)(Display*,Window,Atom);
|
||||
typedef void (* PFN_XDestroyIC)(XIC);
|
||||
typedef int (* PFN_XDestroyRegion)(Region);
|
||||
typedef int (* PFN_XDestroyWindow)(Display*,Window);
|
||||
typedef int (* PFN_XDisplayKeycodes)(Display*,int*,int*);
|
||||
typedef int (* PFN_XEventsQueued)(Display*,int);
|
||||
typedef Bool (* PFN_XFilterEvent)(XEvent*,Window);
|
||||
typedef int (* PFN_XFindContext)(Display*,XID,XContext,XPointer*);
|
||||
typedef int (* PFN_XFlush)(Display*);
|
||||
typedef int (* PFN_XFree)(void*);
|
||||
typedef int (* PFN_XFreeColormap)(Display*,Colormap);
|
||||
typedef int (* PFN_XFreeCursor)(Display*,Cursor);
|
||||
typedef void (* PFN_XFreeEventData)(Display*,XGenericEventCookie*);
|
||||
typedef int (* PFN_XGetErrorText)(Display*,int,char*,int);
|
||||
typedef Bool (* PFN_XGetEventData)(Display*,XGenericEventCookie*);
|
||||
typedef char* (* PFN_XGetICValues)(XIC,...);
|
||||
typedef char* (* PFN_XGetIMValues)(XIM,...);
|
||||
typedef int (* PFN_XGetInputFocus)(Display*,Window*,int*);
|
||||
typedef KeySym* (* PFN_XGetKeyboardMapping)(Display*,KeyCode,int,int*);
|
||||
typedef int (* PFN_XGetScreenSaver)(Display*,int*,int*,int*,int*);
|
||||
typedef Window (* PFN_XGetSelectionOwner)(Display*,Atom);
|
||||
typedef XVisualInfo* (* PFN_XGetVisualInfo)(Display*,long,XVisualInfo*,int*);
|
||||
typedef Status (* PFN_XGetWMNormalHints)(Display*,Window,XSizeHints*,long*);
|
||||
typedef Status (* PFN_XGetWindowAttributes)(Display*,Window,XWindowAttributes*);
|
||||
typedef int (* PFN_XGetWindowProperty)(Display*,Window,Atom,long,long,Bool,Atom,Atom*,int*,unsigned long*,unsigned long*,unsigned char**);
|
||||
typedef int (* PFN_XGrabPointer)(Display*,Window,Bool,unsigned int,int,int,Window,Cursor,Time);
|
||||
typedef Status (* PFN_XIconifyWindow)(Display*,Window,int);
|
||||
typedef Status (* PFN_XInitThreads)(void);
|
||||
typedef Atom (* PFN_XInternAtom)(Display*,const char*,Bool);
|
||||
typedef int (* PFN_XLookupString)(XKeyEvent*,char*,int,KeySym*,XComposeStatus*);
|
||||
typedef int (* PFN_XMapRaised)(Display*,Window);
|
||||
typedef int (* PFN_XMapWindow)(Display*,Window);
|
||||
typedef int (* PFN_XMoveResizeWindow)(Display*,Window,int,int,unsigned int,unsigned int);
|
||||
typedef int (* PFN_XMoveWindow)(Display*,Window,int,int);
|
||||
typedef int (* PFN_XNextEvent)(Display*,XEvent*);
|
||||
typedef Display* (* PFN_XOpenDisplay)(const char*);
|
||||
typedef XIM (* PFN_XOpenIM)(Display*,XrmDatabase*,char*,char*);
|
||||
typedef int (* PFN_XPeekEvent)(Display*,XEvent*);
|
||||
typedef int (* PFN_XPending)(Display*);
|
||||
typedef Bool (* PFN_XQueryExtension)(Display*,const char*,int*,int*,int*);
|
||||
typedef Bool (* PFN_XQueryPointer)(Display*,Window,Window*,Window*,int*,int*,int*,int*,unsigned int*);
|
||||
typedef int (* PFN_XRaiseWindow)(Display*,Window);
|
||||
typedef Bool (* PFN_XRegisterIMInstantiateCallback)(Display*,void*,char*,char*,XIDProc,XPointer);
|
||||
typedef int (* PFN_XResizeWindow)(Display*,Window,unsigned int,unsigned int);
|
||||
typedef char* (* PFN_XResourceManagerString)(Display*);
|
||||
typedef int (* PFN_XSaveContext)(Display*,XID,XContext,const char*);
|
||||
typedef int (* PFN_XSelectInput)(Display*,Window,long);
|
||||
typedef Status (* PFN_XSendEvent)(Display*,Window,Bool,long,XEvent*);
|
||||
typedef int (* PFN_XSetClassHint)(Display*,Window,XClassHint*);
|
||||
typedef XErrorHandler (* PFN_XSetErrorHandler)(XErrorHandler);
|
||||
typedef void (* PFN_XSetICFocus)(XIC);
|
||||
typedef char* (* PFN_XSetIMValues)(XIM,...);
|
||||
typedef int (* PFN_XSetInputFocus)(Display*,Window,int,Time);
|
||||
typedef char* (* PFN_XSetLocaleModifiers)(const char*);
|
||||
typedef int (* PFN_XSetScreenSaver)(Display*,int,int,int,int);
|
||||
typedef int (* PFN_XSetSelectionOwner)(Display*,Atom,Window,Time);
|
||||
typedef int (* PFN_XSetWMHints)(Display*,Window,XWMHints*);
|
||||
typedef void (* PFN_XSetWMNormalHints)(Display*,Window,XSizeHints*);
|
||||
typedef Status (* PFN_XSetWMProtocols)(Display*,Window,Atom*,int);
|
||||
typedef Bool (* PFN_XSupportsLocale)(void);
|
||||
typedef int (* PFN_XSync)(Display*,Bool);
|
||||
typedef Bool (* PFN_XTranslateCoordinates)(Display*,Window,Window,int,int,int*,int*,Window*);
|
||||
typedef int (* PFN_XUndefineCursor)(Display*,Window);
|
||||
typedef int (* PFN_XUngrabPointer)(Display*,Time);
|
||||
typedef int (* PFN_XUnmapWindow)(Display*,Window);
|
||||
typedef void (* PFN_XUnsetICFocus)(XIC);
|
||||
typedef VisualID (* PFN_XVisualIDFromVisual)(Visual*);
|
||||
typedef int (* PFN_XWarpPointer)(Display*,Window,Window,int,int,unsigned int,unsigned int,int,int);
|
||||
typedef void (* PFN_XkbFreeKeyboard)(XkbDescPtr,unsigned int,Bool);
|
||||
typedef void (* PFN_XkbFreeNames)(XkbDescPtr,unsigned int,Bool);
|
||||
typedef XkbDescPtr (* PFN_XkbGetMap)(Display*,unsigned int,unsigned int);
|
||||
typedef Status (* PFN_XkbGetNames)(Display*,unsigned int,XkbDescPtr);
|
||||
typedef Status (* PFN_XkbGetState)(Display*,unsigned int,XkbStatePtr);
|
||||
typedef KeySym (* PFN_XkbKeycodeToKeysym)(Display*,KeyCode,int,int);
|
||||
typedef Bool (* PFN_XkbQueryExtension)(Display*,int*,int*,int*,int*,int*);
|
||||
typedef Bool (* PFN_XkbSelectEventDetails)(Display*,unsigned int,unsigned int,unsigned long,unsigned long);
|
||||
typedef Bool (* PFN_XkbSetDetectableAutoRepeat)(Display*,Bool,Bool*);
|
||||
typedef void (* PFN_XrmDestroyDatabase)(XrmDatabase);
|
||||
typedef Bool (* PFN_XrmGetResource)(XrmDatabase,const char*,const char*,char**,XrmValue*);
|
||||
typedef XrmDatabase (* PFN_XrmGetStringDatabase)(const char*);
|
||||
typedef void (* PFN_XrmInitialize)(void);
|
||||
typedef XrmQuark (* PFN_XrmUniqueQuark)(void);
|
||||
typedef Bool (* PFN_XUnregisterIMInstantiateCallback)(Display*,void*,char*,char*,XIDProc,XPointer);
|
||||
typedef int (* PFN_Xutf8LookupString)(XIC,XKeyPressedEvent*,char*,int,KeySym*,Status*);
|
||||
typedef void (* PFN_Xutf8SetWMProperties)(Display*,Window,const char*,const char*,char**,int,XSizeHints*,XWMHints*,XClassHint*);
|
||||
#define XAllocClassHint _glfw.x11.xlib.AllocClassHint
|
||||
#define XAllocSizeHints _glfw.x11.xlib.AllocSizeHints
|
||||
#define XAllocWMHints _glfw.x11.xlib.AllocWMHints
|
||||
#define XChangeProperty _glfw.x11.xlib.ChangeProperty
|
||||
#define XChangeWindowAttributes _glfw.x11.xlib.ChangeWindowAttributes
|
||||
#define XCheckIfEvent _glfw.x11.xlib.CheckIfEvent
|
||||
#define XCheckTypedWindowEvent _glfw.x11.xlib.CheckTypedWindowEvent
|
||||
#define XCloseDisplay _glfw.x11.xlib.CloseDisplay
|
||||
#define XCloseIM _glfw.x11.xlib.CloseIM
|
||||
#define XConvertSelection _glfw.x11.xlib.ConvertSelection
|
||||
#define XCreateColormap _glfw.x11.xlib.CreateColormap
|
||||
#define XCreateFontCursor _glfw.x11.xlib.CreateFontCursor
|
||||
#define XCreateIC _glfw.x11.xlib.CreateIC
|
||||
#define XCreateRegion _glfw.x11.xlib.CreateRegion
|
||||
#define XCreateWindow _glfw.x11.xlib.CreateWindow
|
||||
#define XDefineCursor _glfw.x11.xlib.DefineCursor
|
||||
#define XDeleteContext _glfw.x11.xlib.DeleteContext
|
||||
#define XDeleteProperty _glfw.x11.xlib.DeleteProperty
|
||||
#define XDestroyIC _glfw.x11.xlib.DestroyIC
|
||||
#define XDestroyRegion _glfw.x11.xlib.DestroyRegion
|
||||
#define XDestroyWindow _glfw.x11.xlib.DestroyWindow
|
||||
#define XDisplayKeycodes _glfw.x11.xlib.DisplayKeycodes
|
||||
#define XEventsQueued _glfw.x11.xlib.EventsQueued
|
||||
#define XFilterEvent _glfw.x11.xlib.FilterEvent
|
||||
#define XFindContext _glfw.x11.xlib.FindContext
|
||||
#define XFlush _glfw.x11.xlib.Flush
|
||||
#define XFree _glfw.x11.xlib.Free
|
||||
#define XFreeColormap _glfw.x11.xlib.FreeColormap
|
||||
#define XFreeCursor _glfw.x11.xlib.FreeCursor
|
||||
#define XFreeEventData _glfw.x11.xlib.FreeEventData
|
||||
#define XGetErrorText _glfw.x11.xlib.GetErrorText
|
||||
#define XGetEventData _glfw.x11.xlib.GetEventData
|
||||
#define XGetICValues _glfw.x11.xlib.GetICValues
|
||||
#define XGetIMValues _glfw.x11.xlib.GetIMValues
|
||||
#define XGetInputFocus _glfw.x11.xlib.GetInputFocus
|
||||
#define XGetKeyboardMapping _glfw.x11.xlib.GetKeyboardMapping
|
||||
#define XGetScreenSaver _glfw.x11.xlib.GetScreenSaver
|
||||
#define XGetSelectionOwner _glfw.x11.xlib.GetSelectionOwner
|
||||
#define XGetVisualInfo _glfw.x11.xlib.GetVisualInfo
|
||||
#define XGetWMNormalHints _glfw.x11.xlib.GetWMNormalHints
|
||||
#define XGetWindowAttributes _glfw.x11.xlib.GetWindowAttributes
|
||||
#define XGetWindowProperty _glfw.x11.xlib.GetWindowProperty
|
||||
#define XGrabPointer _glfw.x11.xlib.GrabPointer
|
||||
#define XIconifyWindow _glfw.x11.xlib.IconifyWindow
|
||||
#define XInitThreads _glfw.x11.xlib.InitThreads
|
||||
#define XInternAtom _glfw.x11.xlib.InternAtom
|
||||
#define XLookupString _glfw.x11.xlib.LookupString
|
||||
#define XMapRaised _glfw.x11.xlib.MapRaised
|
||||
#define XMapWindow _glfw.x11.xlib.MapWindow
|
||||
#define XMoveResizeWindow _glfw.x11.xlib.MoveResizeWindow
|
||||
#define XMoveWindow _glfw.x11.xlib.MoveWindow
|
||||
#define XNextEvent _glfw.x11.xlib.NextEvent
|
||||
#define XOpenDisplay _glfw.x11.xlib.OpenDisplay
|
||||
#define XOpenIM _glfw.x11.xlib.OpenIM
|
||||
#define XPeekEvent _glfw.x11.xlib.PeekEvent
|
||||
#define XPending _glfw.x11.xlib.Pending
|
||||
#define XQueryExtension _glfw.x11.xlib.QueryExtension
|
||||
#define XQueryPointer _glfw.x11.xlib.QueryPointer
|
||||
#define XRaiseWindow _glfw.x11.xlib.RaiseWindow
|
||||
#define XRegisterIMInstantiateCallback _glfw.x11.xlib.RegisterIMInstantiateCallback
|
||||
#define XResizeWindow _glfw.x11.xlib.ResizeWindow
|
||||
#define XResourceManagerString _glfw.x11.xlib.ResourceManagerString
|
||||
#define XSaveContext _glfw.x11.xlib.SaveContext
|
||||
#define XSelectInput _glfw.x11.xlib.SelectInput
|
||||
#define XSendEvent _glfw.x11.xlib.SendEvent
|
||||
#define XSetClassHint _glfw.x11.xlib.SetClassHint
|
||||
#define XSetErrorHandler _glfw.x11.xlib.SetErrorHandler
|
||||
#define XSetICFocus _glfw.x11.xlib.SetICFocus
|
||||
#define XSetIMValues _glfw.x11.xlib.SetIMValues
|
||||
#define XSetInputFocus _glfw.x11.xlib.SetInputFocus
|
||||
#define XSetLocaleModifiers _glfw.x11.xlib.SetLocaleModifiers
|
||||
#define XSetScreenSaver _glfw.x11.xlib.SetScreenSaver
|
||||
#define XSetSelectionOwner _glfw.x11.xlib.SetSelectionOwner
|
||||
#define XSetWMHints _glfw.x11.xlib.SetWMHints
|
||||
#define XSetWMNormalHints _glfw.x11.xlib.SetWMNormalHints
|
||||
#define XSetWMProtocols _glfw.x11.xlib.SetWMProtocols
|
||||
#define XSupportsLocale _glfw.x11.xlib.SupportsLocale
|
||||
#define XSync _glfw.x11.xlib.Sync
|
||||
#define XTranslateCoordinates _glfw.x11.xlib.TranslateCoordinates
|
||||
#define XUndefineCursor _glfw.x11.xlib.UndefineCursor
|
||||
#define XUngrabPointer _glfw.x11.xlib.UngrabPointer
|
||||
#define XUnmapWindow _glfw.x11.xlib.UnmapWindow
|
||||
#define XUnsetICFocus _glfw.x11.xlib.UnsetICFocus
|
||||
#define XVisualIDFromVisual _glfw.x11.xlib.VisualIDFromVisual
|
||||
#define XWarpPointer _glfw.x11.xlib.WarpPointer
|
||||
#define XkbFreeKeyboard _glfw.x11.xkb.FreeKeyboard
|
||||
#define XkbFreeNames _glfw.x11.xkb.FreeNames
|
||||
#define XkbGetMap _glfw.x11.xkb.GetMap
|
||||
#define XkbGetNames _glfw.x11.xkb.GetNames
|
||||
#define XkbGetState _glfw.x11.xkb.GetState
|
||||
#define XkbKeycodeToKeysym _glfw.x11.xkb.KeycodeToKeysym
|
||||
#define XkbQueryExtension _glfw.x11.xkb.QueryExtension
|
||||
#define XkbSelectEventDetails _glfw.x11.xkb.SelectEventDetails
|
||||
#define XkbSetDetectableAutoRepeat _glfw.x11.xkb.SetDetectableAutoRepeat
|
||||
#define XrmDestroyDatabase _glfw.x11.xrm.DestroyDatabase
|
||||
#define XrmGetResource _glfw.x11.xrm.GetResource
|
||||
#define XrmGetStringDatabase _glfw.x11.xrm.GetStringDatabase
|
||||
#define XrmInitialize _glfw.x11.xrm.Initialize
|
||||
#define XrmUniqueQuark _glfw.x11.xrm.UniqueQuark
|
||||
#define XUnregisterIMInstantiateCallback _glfw.x11.xlib.UnregisterIMInstantiateCallback
|
||||
#define Xutf8LookupString _glfw.x11.xlib.utf8LookupString
|
||||
#define Xutf8SetWMProperties _glfw.x11.xlib.utf8SetWMProperties
|
||||
|
||||
typedef XRRCrtcGamma* (* PFN_XRRAllocGamma)(int);
|
||||
typedef void (* PFN_XRRFreeCrtcInfo)(XRRCrtcInfo*);
|
||||
typedef void (* PFN_XRRFreeGamma)(XRRCrtcGamma*);
|
||||
|
@ -129,6 +338,16 @@ typedef XRenderPictFormat* (* PFN_XRenderFindVisualFormat)(Display*,Visual const
|
|||
#define XRenderQueryVersion _glfw.x11.xrender.QueryVersion
|
||||
#define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat
|
||||
|
||||
typedef Bool (* PFN_XShapeQueryExtension)(Display*,int*,int*);
|
||||
typedef Status (* PFN_XShapeQueryVersion)(Display*dpy,int*,int*);
|
||||
typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int);
|
||||
typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int);
|
||||
|
||||
#define XShapeQueryExtension _glfw.x11.xshape.QueryExtension
|
||||
#define XShapeQueryVersion _glfw.x11.xshape.QueryVersion
|
||||
#define XShapeCombineRegion _glfw.x11.xshape.ShapeCombineRegion
|
||||
#define XShapeCombineMask _glfw.x11.xshape.ShapeCombineMask
|
||||
|
||||
typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
|
||||
typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
|
||||
|
||||
|
@ -159,8 +378,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk
|
|||
#include "posix_time.h"
|
||||
#include "xkb_unicode.h"
|
||||
#include "glx_context.h"
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
#if defined(__linux__)
|
||||
#include "linux_joystick.h"
|
||||
#else
|
||||
|
@ -171,9 +388,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk
|
|||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->x11.handle)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
|
||||
|
@ -205,8 +419,9 @@ typedef struct _GLFWwindowX11
|
|||
// The last position the cursor was warped to by GLFW
|
||||
int warpCursorPosX, warpCursorPosY;
|
||||
|
||||
// The time of the last KeyPress event
|
||||
Time lastKeyTime;
|
||||
// The time of the last KeyPress event per keycode, for discarding
|
||||
// duplicate key events generated for some keys by ibus
|
||||
Time keyPressTimes[256];
|
||||
|
||||
} _GLFWwindowX11;
|
||||
|
||||
|
@ -301,6 +516,107 @@ typedef struct _GLFWlibraryX11
|
|||
Atom ATOM_PAIR;
|
||||
Atom GLFW_SELECTION;
|
||||
|
||||
struct {
|
||||
void* handle;
|
||||
GLFWbool utf8;
|
||||
PFN_XAllocClassHint AllocClassHint;
|
||||
PFN_XAllocSizeHints AllocSizeHints;
|
||||
PFN_XAllocWMHints AllocWMHints;
|
||||
PFN_XChangeProperty ChangeProperty;
|
||||
PFN_XChangeWindowAttributes ChangeWindowAttributes;
|
||||
PFN_XCheckIfEvent CheckIfEvent;
|
||||
PFN_XCheckTypedWindowEvent CheckTypedWindowEvent;
|
||||
PFN_XCloseDisplay CloseDisplay;
|
||||
PFN_XCloseIM CloseIM;
|
||||
PFN_XConvertSelection ConvertSelection;
|
||||
PFN_XCreateColormap CreateColormap;
|
||||
PFN_XCreateFontCursor CreateFontCursor;
|
||||
PFN_XCreateIC CreateIC;
|
||||
PFN_XCreateRegion CreateRegion;
|
||||
PFN_XCreateWindow CreateWindow;
|
||||
PFN_XDefineCursor DefineCursor;
|
||||
PFN_XDeleteContext DeleteContext;
|
||||
PFN_XDeleteProperty DeleteProperty;
|
||||
PFN_XDestroyIC DestroyIC;
|
||||
PFN_XDestroyRegion DestroyRegion;
|
||||
PFN_XDestroyWindow DestroyWindow;
|
||||
PFN_XDisplayKeycodes DisplayKeycodes;
|
||||
PFN_XEventsQueued EventsQueued;
|
||||
PFN_XFilterEvent FilterEvent;
|
||||
PFN_XFindContext FindContext;
|
||||
PFN_XFlush Flush;
|
||||
PFN_XFree Free;
|
||||
PFN_XFreeColormap FreeColormap;
|
||||
PFN_XFreeCursor FreeCursor;
|
||||
PFN_XFreeEventData FreeEventData;
|
||||
PFN_XGetErrorText GetErrorText;
|
||||
PFN_XGetEventData GetEventData;
|
||||
PFN_XGetICValues GetICValues;
|
||||
PFN_XGetIMValues GetIMValues;
|
||||
PFN_XGetInputFocus GetInputFocus;
|
||||
PFN_XGetKeyboardMapping GetKeyboardMapping;
|
||||
PFN_XGetScreenSaver GetScreenSaver;
|
||||
PFN_XGetSelectionOwner GetSelectionOwner;
|
||||
PFN_XGetVisualInfo GetVisualInfo;
|
||||
PFN_XGetWMNormalHints GetWMNormalHints;
|
||||
PFN_XGetWindowAttributes GetWindowAttributes;
|
||||
PFN_XGetWindowProperty GetWindowProperty;
|
||||
PFN_XGrabPointer GrabPointer;
|
||||
PFN_XIconifyWindow IconifyWindow;
|
||||
PFN_XInitThreads InitThreads;
|
||||
PFN_XInternAtom InternAtom;
|
||||
PFN_XLookupString LookupString;
|
||||
PFN_XMapRaised MapRaised;
|
||||
PFN_XMapWindow MapWindow;
|
||||
PFN_XMoveResizeWindow MoveResizeWindow;
|
||||
PFN_XMoveWindow MoveWindow;
|
||||
PFN_XNextEvent NextEvent;
|
||||
PFN_XOpenDisplay OpenDisplay;
|
||||
PFN_XOpenIM OpenIM;
|
||||
PFN_XPeekEvent PeekEvent;
|
||||
PFN_XPending Pending;
|
||||
PFN_XQueryExtension QueryExtension;
|
||||
PFN_XQueryPointer QueryPointer;
|
||||
PFN_XRaiseWindow RaiseWindow;
|
||||
PFN_XRegisterIMInstantiateCallback RegisterIMInstantiateCallback;
|
||||
PFN_XResizeWindow ResizeWindow;
|
||||
PFN_XResourceManagerString ResourceManagerString;
|
||||
PFN_XSaveContext SaveContext;
|
||||
PFN_XSelectInput SelectInput;
|
||||
PFN_XSendEvent SendEvent;
|
||||
PFN_XSetClassHint SetClassHint;
|
||||
PFN_XSetErrorHandler SetErrorHandler;
|
||||
PFN_XSetICFocus SetICFocus;
|
||||
PFN_XSetIMValues SetIMValues;
|
||||
PFN_XSetInputFocus SetInputFocus;
|
||||
PFN_XSetLocaleModifiers SetLocaleModifiers;
|
||||
PFN_XSetScreenSaver SetScreenSaver;
|
||||
PFN_XSetSelectionOwner SetSelectionOwner;
|
||||
PFN_XSetWMHints SetWMHints;
|
||||
PFN_XSetWMNormalHints SetWMNormalHints;
|
||||
PFN_XSetWMProtocols SetWMProtocols;
|
||||
PFN_XSupportsLocale SupportsLocale;
|
||||
PFN_XSync Sync;
|
||||
PFN_XTranslateCoordinates TranslateCoordinates;
|
||||
PFN_XUndefineCursor UndefineCursor;
|
||||
PFN_XUngrabPointer UngrabPointer;
|
||||
PFN_XUnmapWindow UnmapWindow;
|
||||
PFN_XUnsetICFocus UnsetICFocus;
|
||||
PFN_XVisualIDFromVisual VisualIDFromVisual;
|
||||
PFN_XWarpPointer WarpPointer;
|
||||
PFN_XUnregisterIMInstantiateCallback UnregisterIMInstantiateCallback;
|
||||
PFN_Xutf8LookupString utf8LookupString;
|
||||
PFN_Xutf8SetWMProperties utf8SetWMProperties;
|
||||
} xlib;
|
||||
|
||||
struct {
|
||||
PFN_XrmDestroyDatabase DestroyDatabase;
|
||||
PFN_XrmGetResource GetResource;
|
||||
PFN_XrmGetStringDatabase GetStringDatabase;
|
||||
PFN_XrmInitialize Initialize;
|
||||
PFN_XrmUniqueQuark UniqueQuark;
|
||||
} xrm;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
void* handle;
|
||||
|
@ -338,6 +654,15 @@ typedef struct _GLFWlibraryX11
|
|||
int major;
|
||||
int minor;
|
||||
unsigned int group;
|
||||
PFN_XkbFreeKeyboard FreeKeyboard;
|
||||
PFN_XkbFreeNames FreeNames;
|
||||
PFN_XkbGetMap GetMap;
|
||||
PFN_XkbGetNames GetNames;
|
||||
PFN_XkbGetState GetState;
|
||||
PFN_XkbKeycodeToKeysym KeycodeToKeysym;
|
||||
PFN_XkbQueryExtension QueryExtension;
|
||||
PFN_XkbSelectEventDetails SelectEventDetails;
|
||||
PFN_XkbSetDetectableAutoRepeat SetDetectableAutoRepeat;
|
||||
} xkb;
|
||||
|
||||
struct {
|
||||
|
@ -414,6 +739,19 @@ typedef struct _GLFWlibraryX11
|
|||
PFN_XRenderFindVisualFormat FindVisualFormat;
|
||||
} xrender;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
void* handle;
|
||||
int major;
|
||||
int minor;
|
||||
int eventBase;
|
||||
int errorBase;
|
||||
PFN_XShapeQueryExtension QueryExtension;
|
||||
PFN_XShapeCombineRegion ShapeCombineRegion;
|
||||
PFN_XShapeQueryVersion QueryVersion;
|
||||
PFN_XShapeCombineMask ShapeCombineMask;
|
||||
} xshape;
|
||||
|
||||
} _GLFWlibraryX11;
|
||||
|
||||
// X11-specific per-monitor data
|
||||
|
@ -456,4 +794,5 @@ void _glfwReleaseErrorHandlerX11(void);
|
|||
void _glfwInputErrorX11(int error, const char* message);
|
||||
|
||||
void _glfwPushSelectionToManagerX11(void);
|
||||
void _glfwCreateInputContextX11(_GLFWwindow* window);
|
||||
|
||||
|
|
240
raylib/external/glfw/src/x11_window.c
vendored
240
raylib/external/glfw/src/x11_window.c
vendored
|
@ -463,7 +463,6 @@ static size_t encodeUTF8(char* s, unsigned int ch)
|
|||
// Decode a Unicode code point from a UTF-8 stream
|
||||
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
||||
//
|
||||
#if defined(X_HAVE_UTF8_STRING)
|
||||
static unsigned int decodeUTF8(const char** s)
|
||||
{
|
||||
unsigned int ch = 0, count = 0;
|
||||
|
@ -483,7 +482,6 @@ static unsigned int decodeUTF8(const char** s)
|
|||
assert(count <= 6);
|
||||
return ch - offsets[count - 1];
|
||||
}
|
||||
#endif /*X_HAVE_UTF8_STRING*/
|
||||
|
||||
// Convert the specified Latin-1 string to UTF-8
|
||||
//
|
||||
|
@ -590,6 +588,14 @@ static void enableCursor(_GLFWwindow* window)
|
|||
updateCursorImage(window);
|
||||
}
|
||||
|
||||
// Clear its handle when the input context has been destroyed
|
||||
//
|
||||
static void inputContextDestroyCallback(XIC ic, XPointer clientData, XPointer callData)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) clientData;
|
||||
window->x11.ic = NULL;
|
||||
}
|
||||
|
||||
// Create the X11 window (and its colormap)
|
||||
//
|
||||
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
|
@ -768,27 +774,10 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||
PropModeReplace, (unsigned char*) &version, 1);
|
||||
}
|
||||
|
||||
_glfwPlatformSetWindowTitle(window, wndconfig->title);
|
||||
|
||||
if (_glfw.x11.im)
|
||||
{
|
||||
window->x11.ic = XCreateIC(_glfw.x11.im,
|
||||
XNInputStyle,
|
||||
XIMPreeditNothing | XIMStatusNothing,
|
||||
XNClientWindow,
|
||||
window->x11.handle,
|
||||
XNFocusWindow,
|
||||
window->x11.handle,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (window->x11.ic)
|
||||
{
|
||||
unsigned long filter = 0;
|
||||
if (XGetICValues(window->x11.ic, XNFilterEvents, &filter, NULL) == NULL)
|
||||
XSelectInput(_glfw.x11.display, window->x11.handle, wa.event_mask | filter);
|
||||
}
|
||||
_glfwCreateInputContextX11(window);
|
||||
|
||||
_glfwPlatformSetWindowTitle(window, wndconfig->title);
|
||||
_glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);
|
||||
_glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);
|
||||
|
||||
|
@ -1173,8 +1162,7 @@ static void processEvent(XEvent *event)
|
|||
if (event->type == KeyPress || event->type == KeyRelease)
|
||||
keycode = event->xkey.keycode;
|
||||
|
||||
if (_glfw.x11.im)
|
||||
filtered = XFilterEvent(event, None);
|
||||
filtered = XFilterEvent(event, None);
|
||||
|
||||
if (_glfw.x11.randr.available)
|
||||
{
|
||||
|
@ -1195,6 +1183,8 @@ static void processEvent(XEvent *event)
|
|||
{
|
||||
_glfw.x11.xkb.group = ((XkbEvent*) event)->state.group;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1273,23 +1263,26 @@ static void processEvent(XEvent *event)
|
|||
|
||||
if (window->x11.ic)
|
||||
{
|
||||
// HACK: Ignore duplicate key press events generated by ibus
|
||||
// These have the same timestamp as the original event
|
||||
// Corresponding release events are filtered out
|
||||
// implicitly by the GLFW key repeat logic
|
||||
if (window->x11.lastKeyTime < event->xkey.time)
|
||||
// HACK: Do not report the key press events duplicated by XIM
|
||||
// Duplicate key releases are filtered out implicitly by
|
||||
// the GLFW key repeat logic in _glfwInputKey
|
||||
// A timestamp per key is used to handle simultaneous keys
|
||||
// NOTE: Always allow the first event for each key through
|
||||
// (the server never sends a timestamp of zero)
|
||||
// NOTE: Timestamp difference is compared to handle wrap-around
|
||||
Time diff = event->xkey.time - window->x11.keyPressTimes[keycode];
|
||||
if (diff == event->xkey.time || (diff > 0 && diff < (1 << 31)))
|
||||
{
|
||||
if (keycode)
|
||||
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||
|
||||
window->x11.lastKeyTime = event->xkey.time;
|
||||
window->x11.keyPressTimes[keycode] = event->xkey.time;
|
||||
}
|
||||
|
||||
if (!filtered)
|
||||
{
|
||||
int count;
|
||||
Status status;
|
||||
#if defined(X_HAVE_UTF8_STRING)
|
||||
char buffer[100];
|
||||
char* chars = buffer;
|
||||
|
||||
|
@ -1314,33 +1307,6 @@ static void processEvent(XEvent *event)
|
|||
while (c - chars < count)
|
||||
_glfwInputChar(window, decodeUTF8(&c), mods, plain);
|
||||
}
|
||||
#else /*X_HAVE_UTF8_STRING*/
|
||||
wchar_t buffer[16];
|
||||
wchar_t* chars = buffer;
|
||||
|
||||
count = XwcLookupString(window->x11.ic,
|
||||
&event->xkey,
|
||||
buffer,
|
||||
sizeof(buffer) / sizeof(wchar_t),
|
||||
NULL,
|
||||
&status);
|
||||
|
||||
if (status == XBufferOverflow)
|
||||
{
|
||||
chars = calloc(count, sizeof(wchar_t));
|
||||
count = XwcLookupString(window->x11.ic,
|
||||
&event->xkey,
|
||||
chars, count,
|
||||
NULL, &status);
|
||||
}
|
||||
|
||||
if (status == XLookupChars || status == XLookupBoth)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
_glfwInputChar(window, chars[i], mods, plain);
|
||||
}
|
||||
#endif /*X_HAVE_UTF8_STRING*/
|
||||
|
||||
if (chars != buffer)
|
||||
free(chars);
|
||||
|
@ -1557,6 +1523,8 @@ static void processEvent(XEvent *event)
|
|||
// the position into root (screen) coordinates
|
||||
if (!event->xany.send_event && window->x11.parent != _glfw.x11.root)
|
||||
{
|
||||
_glfwGrabErrorHandlerX11();
|
||||
|
||||
Window dummy;
|
||||
XTranslateCoordinates(_glfw.x11.display,
|
||||
window->x11.parent,
|
||||
|
@ -1564,6 +1532,10 @@ static void processEvent(XEvent *event)
|
|||
xpos, ypos,
|
||||
&xpos, &ypos,
|
||||
&dummy);
|
||||
|
||||
_glfwReleaseErrorHandlerX11();
|
||||
if (_glfw.x11.errorCode == BadWindow)
|
||||
return;
|
||||
}
|
||||
|
||||
if (xpos != window->x11.xpos || ypos != window->x11.ypos)
|
||||
|
@ -1961,6 +1933,38 @@ void _glfwPushSelectionToManagerX11(void)
|
|||
}
|
||||
}
|
||||
|
||||
void _glfwCreateInputContextX11(_GLFWwindow* window)
|
||||
{
|
||||
XIMCallback callback;
|
||||
callback.callback = (XIMProc) inputContextDestroyCallback;
|
||||
callback.client_data = (XPointer) window;
|
||||
|
||||
window->x11.ic = XCreateIC(_glfw.x11.im,
|
||||
XNInputStyle,
|
||||
XIMPreeditNothing | XIMStatusNothing,
|
||||
XNClientWindow,
|
||||
window->x11.handle,
|
||||
XNFocusWindow,
|
||||
window->x11.handle,
|
||||
XNDestroyCallback,
|
||||
&callback,
|
||||
NULL);
|
||||
|
||||
if (window->x11.ic)
|
||||
{
|
||||
XWindowAttributes attribs;
|
||||
XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &attribs);
|
||||
|
||||
unsigned long filter = 0;
|
||||
if (XGetICValues(window->x11.ic, XNFilterEvents, &filter, NULL) == NULL)
|
||||
{
|
||||
XSelectInput(_glfw.x11.display,
|
||||
window->x11.handle,
|
||||
attribs.your_event_mask | filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
|
@ -1971,7 +1975,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
Visual* visual;
|
||||
Visual* visual = NULL;
|
||||
int depth;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
|
@ -1997,8 +2001,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->client == GLFW_NO_API ||
|
||||
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||
if (!visual)
|
||||
{
|
||||
visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);
|
||||
depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);
|
||||
|
@ -2073,21 +2076,14 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||
|
||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
{
|
||||
#if defined(X_HAVE_UTF8_STRING)
|
||||
Xutf8SetWMProperties(_glfw.x11.display,
|
||||
window->x11.handle,
|
||||
title, title,
|
||||
NULL, 0,
|
||||
NULL, NULL, NULL);
|
||||
#else
|
||||
// This may be a slightly better fallback than using XStoreName and
|
||||
// XSetIconName, which always store their arguments using STRING
|
||||
XmbSetWMProperties(_glfw.x11.display,
|
||||
window->x11.handle,
|
||||
title, title,
|
||||
NULL, 0,
|
||||
NULL, NULL, NULL);
|
||||
#endif
|
||||
if (_glfw.x11.xlib.utf8)
|
||||
{
|
||||
Xutf8SetWMProperties(_glfw.x11.display,
|
||||
window->x11.handle,
|
||||
title, title,
|
||||
NULL, 0,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||
_glfw.x11.NET_WM_NAME, _glfw.x11.UTF8_STRING, 8,
|
||||
|
@ -2580,13 +2576,19 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
|||
int rootX, rootY, childX, childY;
|
||||
unsigned int mask;
|
||||
|
||||
if (!XQueryPointer(_glfw.x11.display, w,
|
||||
&root, &w, &rootX, &rootY, &childX, &childY, &mask))
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
_glfwGrabErrorHandlerX11();
|
||||
|
||||
if (w == window->x11.handle)
|
||||
const Bool result = XQueryPointer(_glfw.x11.display, w,
|
||||
&root, &w, &rootX, &rootY,
|
||||
&childX, &childY, &mask);
|
||||
|
||||
_glfwReleaseErrorHandlerX11();
|
||||
|
||||
if (_glfw.x11.errorCode == BadWindow)
|
||||
w = _glfw.x11.root;
|
||||
else if (!result)
|
||||
return GLFW_FALSE;
|
||||
else if (w == window->x11.handle)
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
|
@ -2700,6 +2702,25 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
|||
XFlush(_glfw.x11.display);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
if (!_glfw.x11.xshape.available)
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
Region region = XCreateRegion();
|
||||
XShapeCombineRegion(_glfw.x11.display, window->x11.handle,
|
||||
ShapeInput, 0, 0, region, ShapeSet);
|
||||
XDestroyRegion(region);
|
||||
}
|
||||
else
|
||||
{
|
||||
XShapeCombineMask(_glfw.x11.display, window->x11.handle,
|
||||
ShapeInput, 0, 0, None, ShapeSet);
|
||||
}
|
||||
}
|
||||
|
||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||
{
|
||||
float opacity = 1.f;
|
||||
|
@ -2755,11 +2776,12 @@ void _glfwPlatformPollEvents(void)
|
|||
_GLFWwindow* window;
|
||||
|
||||
#if defined(__linux__)
|
||||
_glfwDetectJoystickConnectionLinux();
|
||||
if (_glfw.joysticksInitialized)
|
||||
_glfwDetectJoystickConnectionLinux();
|
||||
#endif
|
||||
XPending(_glfw.x11.display);
|
||||
|
||||
while (XQLength(_glfw.x11.display))
|
||||
while (QLength(_glfw.x11.display))
|
||||
{
|
||||
XEvent event;
|
||||
XNextEvent(_glfw.x11.display, &event);
|
||||
|
@ -2997,8 +3019,9 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||
|
||||
void _glfwPlatformSetClipboardString(const char* string)
|
||||
{
|
||||
char* copy = _glfw_strdup(string);
|
||||
free(_glfw.x11.clipboardString);
|
||||
_glfw.x11.clipboardString = _glfw_strdup(string);
|
||||
_glfw.x11.clipboardString = copy;
|
||||
|
||||
XSetSelectionOwner(_glfw.x11.display,
|
||||
_glfw.x11.CLIPBOARD,
|
||||
|
@ -3018,6 +3041,55 @@ const char* _glfwPlatformGetClipboardString(void)
|
|||
return getSelectionString(_glfw.x11.CLIPBOARD);
|
||||
}
|
||||
|
||||
EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs)
|
||||
{
|
||||
if (_glfw.egl.ANGLE_platform_angle)
|
||||
{
|
||||
int type = 0;
|
||||
|
||||
if (_glfw.egl.ANGLE_platform_angle_opengl)
|
||||
{
|
||||
if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_OPENGL)
|
||||
type = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
|
||||
}
|
||||
|
||||
if (_glfw.egl.ANGLE_platform_angle_vulkan)
|
||||
{
|
||||
if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_VULKAN)
|
||||
type = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
|
||||
}
|
||||
|
||||
if (type)
|
||||
{
|
||||
*attribs = calloc(5, sizeof(EGLint));
|
||||
(*attribs)[0] = EGL_PLATFORM_ANGLE_TYPE_ANGLE;
|
||||
(*attribs)[1] = type;
|
||||
(*attribs)[2] = EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE;
|
||||
(*attribs)[3] = EGL_PLATFORM_X11_EXT;
|
||||
(*attribs)[4] = EGL_NONE;
|
||||
return EGL_PLATFORM_ANGLE_ANGLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.egl.EXT_platform_base && _glfw.egl.EXT_platform_x11)
|
||||
return EGL_PLATFORM_X11_EXT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void)
|
||||
{
|
||||
return _glfw.x11.display;
|
||||
}
|
||||
|
||||
EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (_glfw.egl.platform)
|
||||
return &window->x11.handle;
|
||||
else
|
||||
return (EGLNativeWindowType) window->x11.handle;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
if (!_glfw.vk.KHR_surface)
|
||||
|
|
1950
raylib/external/jar_xm.h
vendored
1950
raylib/external/jar_xm.h
vendored
File diff suppressed because it is too large
Load diff
17309
raylib/external/miniaudio.h
vendored
17309
raylib/external/miniaudio.h
vendored
File diff suppressed because it is too large
Load diff
608
raylib/external/msf_gif.h
vendored
Normal file
608
raylib/external/msf_gif.h
vendored
Normal file
|
@ -0,0 +1,608 @@
|
|||
/*
|
||||
HOW TO USE:
|
||||
|
||||
In exactly one translation unit (.c or .cpp file), #define MSF_GIF_IMPL before including the header, like so:
|
||||
|
||||
#define MSF_GIF_IMPL
|
||||
#include "msf_gif.h"
|
||||
|
||||
Everywhere else, just include the header like normal.
|
||||
|
||||
|
||||
USAGE EXAMPLE:
|
||||
|
||||
int width = 480, height = 320, centisecondsPerFrame = 5, bitDepth = 16;
|
||||
MsfGifState gifState = {};
|
||||
msf_gif_begin(&gifState, width, height);
|
||||
msf_gif_frame(&gifState, ..., centisecondsPerFrame, bitDepth, width * 4); //frame 1
|
||||
msf_gif_frame(&gifState, ..., centisecondsPerFrame, bitDepth, width * 4); //frame 2
|
||||
msf_gif_frame(&gifState, ..., centisecondsPerFrame, bitDepth, width * 4); //frame 3, etc...
|
||||
MsfGifResult result = msf_gif_end(&gifState);
|
||||
FILE * fp = fopen("MyGif.gif", "wb");
|
||||
fwrite(result.data, result.dataSize, 1, fp);
|
||||
fclose(fp);
|
||||
msf_gif_free(result);
|
||||
|
||||
Detailed function documentation can be found in the header section below.
|
||||
|
||||
|
||||
REPLACING MALLOC:
|
||||
|
||||
This library uses malloc+realloc+free internally for memory allocation.
|
||||
To facilitate integration with custom memory allocators, these calls go through macros, which can be redefined.
|
||||
The expected function signature equivalents of the macros are as follows:
|
||||
|
||||
void * MSF_GIF_MALLOC(void * context, size_t newSize)
|
||||
void * MSF_GIF_REALLOC(void * context, void * oldMemory, size_t oldSize, size_t newSize)
|
||||
void MSF_GIF_FREE(void * context, void * oldMemory, size_t oldSize)
|
||||
|
||||
If your allocator needs a context pointer, you can set the `customAllocatorContext` field of the MsfGifState struct
|
||||
before calling msf_gif_begin(), and it will be passed to all subsequent allocator macro calls.
|
||||
|
||||
See end of file for license information.
|
||||
*/
|
||||
|
||||
//version 2.1
|
||||
|
||||
#ifndef MSF_GIF_H
|
||||
#define MSF_GIF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct {
|
||||
void * data;
|
||||
size_t dataSize;
|
||||
|
||||
size_t allocSize; //internal use
|
||||
void * contextPointer; //internal use
|
||||
} MsfGifResult;
|
||||
|
||||
typedef struct { //internal use
|
||||
uint32_t * pixels;
|
||||
int depth, count, rbits, gbits, bbits;
|
||||
} MsfCookedFrame;
|
||||
|
||||
typedef struct {
|
||||
MsfCookedFrame previousFrame;
|
||||
uint8_t * listHead;
|
||||
uint8_t * listTail;
|
||||
int width, height;
|
||||
void * customAllocatorContext;
|
||||
} MsfGifState;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif //__cplusplus
|
||||
|
||||
/**
|
||||
* @param width Image width in pixels.
|
||||
* @param height Image height in pixels.
|
||||
* @return Non-zero on success, 0 on error.
|
||||
*/
|
||||
int msf_gif_begin(MsfGifState * handle, int width, int height);
|
||||
|
||||
/**
|
||||
* @param pixelData Pointer to raw framebuffer data. Rows must be contiguous in memory, in RGBA8 format.
|
||||
* Note: This function does NOT free `pixelData`. You must free it yourself afterwards.
|
||||
* @param centiSecondsPerFrame How many hundredths of a second this frame should be displayed for.
|
||||
* Note: This being specified in centiseconds is a limitation of the GIF format.
|
||||
* @param maxBitDepth Limits how many bits per pixel can be used when quantizing the gif.
|
||||
* The actual bit depth chosen for a given frame will be less than or equal to
|
||||
* the supplied maximum, depending on the variety of colors used in the frame.
|
||||
* `maxBitDepth` will be clamped between 1 and 16. The recommended default is 16.
|
||||
* Lowering this value can result in faster exports and smaller gifs,
|
||||
* but the quality may suffer.
|
||||
* Please experiment with this value to find what works best for your application.
|
||||
* @param pitchInBytes The number of bytes from the beginning of one row of pixels to the beginning of the next.
|
||||
* If you want to flip the image, just pass in a negative pitch.
|
||||
* @return Non-zero on success, 0 on error.
|
||||
*/
|
||||
int msf_gif_frame(MsfGifState * handle, uint8_t * pixelData, int centiSecondsPerFame, int maxBitDepth, int pitchInBytes);
|
||||
|
||||
/**
|
||||
* @return A block of memory containing the gif file data, or NULL on error.
|
||||
* You are responsible for freeing this via `msf_gif_free()`.
|
||||
*/
|
||||
MsfGifResult msf_gif_end(MsfGifState * handle);
|
||||
|
||||
/**
|
||||
* @param result The MsfGifResult struct, verbatim as it was returned from `msf_gif_end()`.
|
||||
*/
|
||||
void msf_gif_free(MsfGifResult result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif //__cplusplus
|
||||
|
||||
#endif //MSF_GIF_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// IMPLEMENTATION ///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef MSF_GIF_IMPL
|
||||
#ifndef MSF_GIF_ALREADY_IMPLEMENTED_IN_THIS_TRANSLATION_UNIT
|
||||
#define MSF_GIF_ALREADY_IMPLEMENTED_IN_THIS_TRANSLATION_UNIT
|
||||
|
||||
#ifndef MSF_GIF_BUFFER_INIT_SIZE
|
||||
#define MSF_GIF_BUFFER_INIT_SIZE 1024 * 1024 * 4 //4MB by default, you can increase this if you want to realloc less
|
||||
#endif
|
||||
|
||||
//ensure the library user has either defined all of malloc/realloc/free, or none
|
||||
#if defined(MSF_GIF_MALLOC) && defined(MSF_GIF_REALLOC) && defined(MSF_GIF_FREE) //ok
|
||||
#elif !defined(MSF_GIF_MALLOC) && !defined(MSF_GIF_REALLOC) && !defined(MSF_GIF_FREE) //ok
|
||||
#else
|
||||
#error "You must either define all of MSF_GIF_MALLOC, MSF_GIF_REALLOC, and MSF_GIF_FREE, or define none of them"
|
||||
#endif
|
||||
|
||||
//provide default allocator definitions that redirect to the standard global allocator
|
||||
#if !defined(MSF_GIF_MALLOC)
|
||||
#include <stdlib.h> //malloc, etc.
|
||||
#define MSF_GIF_MALLOC(contextPointer, newSize) malloc(newSize)
|
||||
#define MSF_GIF_REALLOC(contextPointer, oldMemory, oldSize, newSize) realloc(oldMemory, newSize)
|
||||
#define MSF_GIF_FREE(contextPointer, oldMemory, oldSize) free(oldMemory)
|
||||
#endif
|
||||
|
||||
//instrumentation for capturing profiling traces (useless for the library user, but useful for the library author)
|
||||
#ifdef MSF_GIF_ENABLE_TRACING
|
||||
#define MsfTimeFunc TimeFunc
|
||||
#define MsfTimeLoop TimeLoop
|
||||
#define msf_init_profiling_thread init_profiling_thread
|
||||
#else
|
||||
#define MsfTimeFunc
|
||||
#define MsfTimeLoop(name)
|
||||
#define msf_init_profiling_thread()
|
||||
#endif //MSF_GIF_ENABLE_TRACING
|
||||
|
||||
#include <string.h> //memcpy
|
||||
|
||||
//TODO: use compiler-specific notation to force-inline functions currently marked inline
|
||||
#if defined(__GNUC__) //gcc, clang
|
||||
static inline int msf_bit_log(int i) { return 32 - __builtin_clz(i); }
|
||||
#elif defined(_MSC_VER) //msvc
|
||||
#include <intrin.h>
|
||||
static inline int msf_bit_log(int i) { unsigned long idx; _BitScanReverse(&idx, i); return idx + 1; }
|
||||
#else //fallback implementation for other compilers
|
||||
//from https://stackoverflow.com/a/31718095/3064745 - thanks!
|
||||
static inline int msf_bit_log(int i) {
|
||||
static const int MultiplyDeBruijnBitPosition[32] = {
|
||||
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
||||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31,
|
||||
};
|
||||
i |= i >> 1;
|
||||
i |= i >> 2;
|
||||
i |= i >> 4;
|
||||
i |= i >> 8;
|
||||
i |= i >> 16;
|
||||
return MultiplyDeBruijnBitPosition[(uint32_t)(i * 0x07C4ACDDU) >> 27] + 1;
|
||||
}
|
||||
#endif
|
||||
static inline int msf_imin(int a, int b) { return a < b? a : b; }
|
||||
static inline int msf_imax(int a, int b) { return b < a? a : b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Frame Cooking ///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if (defined (__SSE2__) || defined (_M_X64) || _M_IX86_FP == 2) && !defined(MSF_GIF_NO_SSE2)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
static MsfCookedFrame msf_cook_frame(void * allocContext, uint8_t * raw, uint8_t * used,
|
||||
int width, int height, int pitch, int depth)
|
||||
{ MsfTimeFunc
|
||||
//bit depth for each channel
|
||||
const static int rdepths[17] = { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
|
||||
const static int gdepths[17] = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6 };
|
||||
const static int bdepths[17] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5 };
|
||||
|
||||
const static int ditherKernel[16] = {
|
||||
0 << 12, 8 << 12, 2 << 12, 10 << 12,
|
||||
12 << 12, 4 << 12, 14 << 12, 6 << 12,
|
||||
3 << 12, 11 << 12, 1 << 12, 9 << 12,
|
||||
15 << 12, 7 << 12, 13 << 12, 5 << 12,
|
||||
};
|
||||
|
||||
uint32_t * cooked = (uint32_t *) MSF_GIF_MALLOC(allocContext, width * height * sizeof(uint32_t));
|
||||
if (!cooked) { MsfCookedFrame blank = {0}; return blank; }
|
||||
|
||||
int count = 0;
|
||||
MsfTimeLoop("do") do {
|
||||
int rbits = rdepths[depth], gbits = gdepths[depth], bbits = bdepths[depth];
|
||||
int paletteSize = 1 << (rbits + gbits + bbits);
|
||||
memset(used, 0, paletteSize * sizeof(uint8_t));
|
||||
|
||||
//TODO: document what this math does and why it's correct
|
||||
int rdiff = (1 << (8 - rbits)) - 1;
|
||||
int gdiff = (1 << (8 - gbits)) - 1;
|
||||
int bdiff = (1 << (8 - bbits)) - 1;
|
||||
short rmul = (short) ((255.0f - rdiff) / 255.0f * 257);
|
||||
short gmul = (short) ((255.0f - gdiff) / 255.0f * 257);
|
||||
short bmul = (short) ((255.0f - bdiff) / 255.0f * 257);
|
||||
|
||||
int gmask = ((1 << gbits) - 1) << rbits;
|
||||
int bmask = ((1 << bbits) - 1) << rbits << gbits;
|
||||
|
||||
MsfTimeLoop("cook") for (int y = 0; y < height; ++y) {
|
||||
int x = 0;
|
||||
|
||||
#if (defined (__SSE2__) || defined (_M_X64) || _M_IX86_FP == 2) && !defined(MSF_GIF_NO_SSE2)
|
||||
__m128i k = _mm_loadu_si128((__m128i *) &ditherKernel[(y & 3) * 4]);
|
||||
__m128i k2 = _mm_or_si128(_mm_srli_epi32(k, rbits), _mm_slli_epi32(_mm_srli_epi32(k, bbits), 16));
|
||||
// MsfTimeLoop("SIMD")
|
||||
for (; x < width - 3; x += 4) {
|
||||
uint8_t * pixels = &raw[y * pitch + x * 4];
|
||||
__m128i p = _mm_loadu_si128((__m128i *) pixels);
|
||||
|
||||
__m128i rb = _mm_and_si128(p, _mm_set1_epi32(0x00FF00FF));
|
||||
__m128i rb1 = _mm_mullo_epi16(rb, _mm_set_epi16(bmul, rmul, bmul, rmul, bmul, rmul, bmul, rmul));
|
||||
__m128i rb2 = _mm_adds_epu16(rb1, k2);
|
||||
__m128i r3 = _mm_srli_epi32(_mm_and_si128(rb2, _mm_set1_epi32(0x0000FFFF)), 16 - rbits);
|
||||
__m128i b3 = _mm_and_si128(_mm_srli_epi32(rb2, 32 - rbits - gbits - bbits), _mm_set1_epi32(bmask));
|
||||
|
||||
__m128i g = _mm_and_si128(_mm_srli_epi32(p, 8), _mm_set1_epi32(0x000000FF));
|
||||
__m128i g1 = _mm_mullo_epi16(g, _mm_set1_epi32(gmul));
|
||||
__m128i g2 = _mm_adds_epu16(g1, _mm_srli_epi32(k, gbits));
|
||||
__m128i g3 = _mm_and_si128(_mm_srli_epi32(g2, 16 - rbits - gbits), _mm_set1_epi32(gmask));
|
||||
|
||||
//TODO: does storing this as a __m128i then reading it back as a uint32_t violate strict aliasing?
|
||||
uint32_t * c = &cooked[y * width + x];
|
||||
__m128i out = _mm_or_si128(_mm_or_si128(r3, g3), b3);
|
||||
_mm_storeu_si128((__m128i *) c, out);
|
||||
}
|
||||
#endif
|
||||
|
||||
//scalar cleanup loop
|
||||
// MsfTimeLoop("scalar")
|
||||
for (; x < width; ++x) {
|
||||
uint8_t * p = &raw[y * pitch + x * 4];
|
||||
int dx = x & 3, dy = y & 3;
|
||||
int k = ditherKernel[dy * 4 + dx];
|
||||
cooked[y * width + x] =
|
||||
(msf_imin(65535, p[2] * bmul + (k >> bbits)) >> (16 - rbits - gbits - bbits) & bmask) |
|
||||
(msf_imin(65535, p[1] * gmul + (k >> gbits)) >> (16 - rbits - gbits ) & gmask) |
|
||||
msf_imin(65535, p[0] * rmul + (k >> rbits)) >> (16 - rbits );
|
||||
}
|
||||
}
|
||||
|
||||
count = 0;
|
||||
MsfTimeLoop("mark and count") for (int i = 0; i < width * height; ++i) {
|
||||
used[cooked[i]] = 1;
|
||||
}
|
||||
|
||||
//count used colors
|
||||
MsfTimeLoop("count") for (int j = 0; j < paletteSize; ++j) {
|
||||
count += used[j];
|
||||
}
|
||||
} while (count >= 256 && --depth);
|
||||
|
||||
MsfCookedFrame ret = { cooked, depth, count, rdepths[depth], gdepths[depth], bdepths[depth] };
|
||||
return ret;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Frame Compression ///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct {
|
||||
uint8_t * next;
|
||||
size_t size;
|
||||
} MsfBufferHeader;
|
||||
|
||||
static inline int msf_put_code(uint8_t * * writeHead, uint32_t * blockBits, int len, uint32_t code) {
|
||||
//insert new code into block buffer
|
||||
int idx = *blockBits / 8;
|
||||
int bit = *blockBits % 8;
|
||||
(*writeHead)[idx + 0] |= code << bit ;
|
||||
(*writeHead)[idx + 1] |= code >> ( 8 - bit);
|
||||
(*writeHead)[idx + 2] |= code >> (16 - bit);
|
||||
*blockBits += len;
|
||||
|
||||
//prep the next block buffer if the current one is full
|
||||
if (*blockBits >= 256 * 8) {
|
||||
*blockBits -= 255 * 8;
|
||||
(*writeHead) += 256;
|
||||
(*writeHead)[2] = (*writeHead)[1];
|
||||
(*writeHead)[1] = (*writeHead)[0];
|
||||
(*writeHead)[0] = 255;
|
||||
memset((*writeHead) + 4, 0, 256);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int16_t * data;
|
||||
int len;
|
||||
int stride;
|
||||
} MsfStridedList;
|
||||
|
||||
static inline void msf_lzw_reset(MsfStridedList * lzw, int tableSize, int stride) { MsfTimeFunc
|
||||
memset(lzw->data, 0xFF, 4096 * stride * sizeof(int16_t));
|
||||
lzw->len = tableSize + 2;
|
||||
lzw->stride = stride;
|
||||
}
|
||||
|
||||
static uint8_t * msf_compress_frame(void * allocContext, int width, int height, int centiSeconds,
|
||||
MsfCookedFrame frame, MsfCookedFrame previous, uint8_t * used)
|
||||
{ MsfTimeFunc
|
||||
//NOTE: we reserve enough memory for theoretical the worst case upfront because it's a reasonable amount,
|
||||
// and prevents us from ever having to check size or realloc during compression
|
||||
int maxBufSize = sizeof(MsfBufferHeader) + 32 + 256 * 3 + width * height * 3 / 2; //headers + color table + data
|
||||
uint8_t * allocation = (uint8_t *) MSF_GIF_MALLOC(allocContext, maxBufSize);
|
||||
if (!allocation) { return NULL; }
|
||||
uint8_t * writeBase = allocation + sizeof(MsfBufferHeader);
|
||||
uint8_t * writeHead = writeBase;
|
||||
int lzwAllocSize = 4096 * (frame.count + 1) * sizeof(int16_t);
|
||||
MsfStridedList lzw = { (int16_t *) MSF_GIF_MALLOC(allocContext, lzwAllocSize) };
|
||||
if (!lzw.data) { MSF_GIF_FREE(allocContext, allocation, maxBufSize); return NULL; }
|
||||
|
||||
//allocate tlb
|
||||
int totalBits = frame.rbits + frame.gbits + frame.bbits;
|
||||
int tlbSize = 1 << totalBits;
|
||||
uint8_t tlb[1 << 16]; //only 64k, so stack allocating is fine
|
||||
|
||||
//generate palette
|
||||
typedef struct { uint8_t r, g, b; } Color3;
|
||||
Color3 table[256] = { {0} };
|
||||
int tableIdx = 1; //we start counting at 1 because 0 is the transparent color
|
||||
MsfTimeLoop("table") for (int i = 0; i < tlbSize; ++i) {
|
||||
if (used[i]) {
|
||||
tlb[i] = tableIdx;
|
||||
int rmask = (1 << frame.rbits) - 1;
|
||||
int gmask = (1 << frame.gbits) - 1;
|
||||
//isolate components
|
||||
int r = i & rmask;
|
||||
int g = i >> frame.rbits & gmask;
|
||||
int b = i >> (frame.rbits + frame.gbits);
|
||||
//shift into highest bits
|
||||
r <<= 8 - frame.rbits;
|
||||
g <<= 8 - frame.gbits;
|
||||
b <<= 8 - frame.bbits;
|
||||
table[tableIdx].r = r | r >> frame.rbits | r >> (frame.rbits * 2) | r >> (frame.rbits * 3);
|
||||
table[tableIdx].g = g | g >> frame.gbits | g >> (frame.gbits * 2) | g >> (frame.gbits * 3);
|
||||
table[tableIdx].b = b | b >> frame.bbits | b >> (frame.bbits * 2) | b >> (frame.bbits * 3);
|
||||
++tableIdx;
|
||||
}
|
||||
}
|
||||
|
||||
//SPEC: "Because of some algorithmic constraints however, black & white images which have one color bit
|
||||
// must be indicated as having a code size of 2."
|
||||
int tableBits = msf_imax(2, msf_bit_log(tableIdx - 1));
|
||||
int tableSize = 1 << tableBits;
|
||||
//NOTE: we don't just compare `depth` field here because it will be wrong for the first frame and we will segfault
|
||||
int hasSamePal = frame.rbits == previous.rbits && frame.gbits == previous.gbits && frame.bbits == previous.bbits;
|
||||
|
||||
//NOTE: because __attribute__((__packed__)) is annoyingly compiler-specific, we do this unreadable weirdness
|
||||
char headerBytes[19] = "\x21\xF9\x04\x05\0\0\0\0" "\x2C\0\0\0\0\0\0\0\0\x80";
|
||||
memcpy(&headerBytes[4], ¢iSeconds, 2);
|
||||
memcpy(&headerBytes[13], &width, 2);
|
||||
memcpy(&headerBytes[15], &height, 2);
|
||||
headerBytes[17] |= tableBits - 1;
|
||||
memcpy(writeHead, headerBytes, 18);
|
||||
writeHead += 18;
|
||||
|
||||
//local color table
|
||||
memcpy(writeHead, table, tableSize * sizeof(Color3));
|
||||
writeHead += tableSize * sizeof(Color3);
|
||||
*writeHead++ = tableBits;
|
||||
|
||||
//prep block
|
||||
memset(writeHead, 0, 260);
|
||||
writeHead[0] = 255;
|
||||
uint32_t blockBits = 8; //relative to block.head
|
||||
|
||||
//SPEC: "Encoders should output a Clear code as the first code of each image data stream."
|
||||
msf_lzw_reset(&lzw, tableSize, tableIdx);
|
||||
msf_put_code(&writeHead, &blockBits, msf_bit_log(lzw.len - 1), tableSize);
|
||||
|
||||
int lastCode = hasSamePal && frame.pixels[0] == previous.pixels[0]? 0 : tlb[frame.pixels[0]];
|
||||
MsfTimeLoop("compress") for (int i = 1; i < width * height; ++i) {
|
||||
//PERF: branching vs. branchless version of this line is observed to have no discernable impact on speed
|
||||
int color = hasSamePal && frame.pixels[i] == previous.pixels[i]? 0 : tlb[frame.pixels[i]];
|
||||
//PERF: branchless version must use && otherwise it will segfault on frame 1, but it's well-predicted so OK
|
||||
// int color = (!(hasSamePal && frame.pixels[i] == previous.pixels[i])) * tlb[frame.pixels[i]];
|
||||
int code = (&lzw.data[lastCode * lzw.stride])[color];
|
||||
if (code < 0) {
|
||||
//write to code stream
|
||||
int codeBits = msf_bit_log(lzw.len - 1);
|
||||
msf_put_code(&writeHead, &blockBits, codeBits, lastCode);
|
||||
|
||||
if (lzw.len > 4095) {
|
||||
//reset buffer code table
|
||||
msf_put_code(&writeHead, &blockBits, codeBits, tableSize);
|
||||
msf_lzw_reset(&lzw, tableSize, tableIdx);
|
||||
} else {
|
||||
(&lzw.data[lastCode * lzw.stride])[color] = lzw.len;
|
||||
++lzw.len;
|
||||
}
|
||||
|
||||
lastCode = color;
|
||||
} else {
|
||||
lastCode = code;
|
||||
}
|
||||
}
|
||||
|
||||
MSF_GIF_FREE(allocContext, lzw.data, lzwAllocSize);
|
||||
MSF_GIF_FREE(allocContext, previous.pixels, width * height * sizeof(uint32_t));
|
||||
|
||||
//write code for leftover index buffer contents, then the end code
|
||||
msf_put_code(&writeHead, &blockBits, msf_imin(12, msf_bit_log(lzw.len - 1)), lastCode);
|
||||
msf_put_code(&writeHead, &blockBits, msf_imin(12, msf_bit_log(lzw.len)), tableSize + 1);
|
||||
|
||||
//flush remaining data
|
||||
if (blockBits > 8) {
|
||||
int bytes = (blockBits + 7) / 8; //round up
|
||||
writeHead[0] = bytes - 1;
|
||||
writeHead += bytes;
|
||||
}
|
||||
*writeHead++ = 0; //terminating block
|
||||
|
||||
//filling in buffer header and shrink buffer to fit data
|
||||
MsfBufferHeader * header = (MsfBufferHeader *) allocation;
|
||||
header->next = NULL;
|
||||
header->size = writeHead - writeBase;
|
||||
uint8_t * moved = (uint8_t *) MSF_GIF_REALLOC(allocContext, allocation, maxBufSize, writeHead - allocation);
|
||||
if (!moved) { MSF_GIF_FREE(allocContext, allocation, maxBufSize); return NULL; }
|
||||
return moved;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Incremental API ///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int msf_gif_begin(MsfGifState * handle, int width, int height) { MsfTimeFunc
|
||||
MsfCookedFrame empty = {0}; //god I hate MSVC...
|
||||
handle->previousFrame = empty;
|
||||
handle->width = width;
|
||||
handle->height = height;
|
||||
|
||||
//setup header buffer header (lol)
|
||||
handle->listHead = (uint8_t *) MSF_GIF_MALLOC(handle->customAllocatorContext, sizeof(MsfBufferHeader) + 32);
|
||||
if (!handle->listHead) { return 0; }
|
||||
handle->listTail = handle->listHead;
|
||||
MsfBufferHeader * header = (MsfBufferHeader *) handle->listHead;
|
||||
header->next = NULL;
|
||||
header->size = 32;
|
||||
|
||||
//NOTE: because __attribute__((__packed__)) is annoyingly compiler-specific, we do this unreadable weirdness
|
||||
char headerBytes[33] = "GIF89a\0\0\0\0\x10\0\0" "\x21\xFF\x0BNETSCAPE2.0\x03\x01\0\0\0";
|
||||
memcpy(&headerBytes[6], &width, 2);
|
||||
memcpy(&headerBytes[8], &height, 2);
|
||||
memcpy(handle->listHead + sizeof(MsfBufferHeader), headerBytes, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int msf_gif_frame(MsfGifState * handle, uint8_t * pixelData, int centiSecondsPerFame, int maxBitDepth, int pitchInBytes)
|
||||
{ MsfTimeFunc
|
||||
if (!handle->listHead) { return 0; }
|
||||
|
||||
maxBitDepth = msf_imax(1, msf_imin(16, maxBitDepth));
|
||||
if (pitchInBytes == 0) pitchInBytes = handle->width * 4;
|
||||
if (pitchInBytes < 0) pixelData -= pitchInBytes * (handle->height - 1);
|
||||
|
||||
uint8_t used[1 << 16]; //only 64k, so stack allocating is fine
|
||||
MsfCookedFrame frame =
|
||||
msf_cook_frame(handle->customAllocatorContext, pixelData, used, handle->width, handle->height, pitchInBytes,
|
||||
msf_imin(maxBitDepth, handle->previousFrame.depth + 160 / msf_imax(1, handle->previousFrame.count)));
|
||||
//TODO: de-duplicate cleanup code
|
||||
if (!frame.pixels) {
|
||||
MSF_GIF_FREE(handle->customAllocatorContext,
|
||||
handle->previousFrame.pixels, handle->width * handle->height * sizeof(uint32_t));
|
||||
for (uint8_t * node = handle->listHead; node;) {
|
||||
MsfBufferHeader * header = (MsfBufferHeader *) node;
|
||||
node = header->next;
|
||||
MSF_GIF_FREE(handle->customAllocatorContext, header, sizeof(MsfBufferHeader) + header->size);
|
||||
}
|
||||
handle->listHead = handle->listTail = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t * buffer = msf_compress_frame(handle->customAllocatorContext,
|
||||
handle->width, handle->height, centiSecondsPerFame, frame, handle->previousFrame, used);
|
||||
((MsfBufferHeader *) handle->listTail)->next = buffer;
|
||||
handle->listTail = buffer;
|
||||
if (!buffer) {
|
||||
MSF_GIF_FREE(handle->customAllocatorContext, frame.pixels, handle->width * handle->height * sizeof(uint32_t));
|
||||
MSF_GIF_FREE(handle->customAllocatorContext,
|
||||
handle->previousFrame.pixels, handle->width * handle->height * sizeof(uint32_t));
|
||||
for (uint8_t * node = handle->listHead; node;) {
|
||||
MsfBufferHeader * header = (MsfBufferHeader *) node;
|
||||
node = header->next;
|
||||
MSF_GIF_FREE(handle->customAllocatorContext, header, sizeof(MsfBufferHeader) + header->size);
|
||||
}
|
||||
handle->listHead = handle->listTail = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
handle->previousFrame = frame;
|
||||
return 1;
|
||||
}
|
||||
|
||||
MsfGifResult msf_gif_end(MsfGifState * handle) { MsfTimeFunc
|
||||
if (!handle->listHead) { MsfGifResult empty = {0}; return empty; }
|
||||
|
||||
MSF_GIF_FREE(handle->customAllocatorContext,
|
||||
handle->previousFrame.pixels, handle->width * handle->height * sizeof(uint32_t));
|
||||
|
||||
//first pass: determine total size
|
||||
size_t total = 1; //1 byte for trailing marker
|
||||
for (uint8_t * node = handle->listHead; node;) {
|
||||
MsfBufferHeader * header = (MsfBufferHeader *) node;
|
||||
node = header->next;
|
||||
total += header->size;
|
||||
}
|
||||
|
||||
//second pass: write data
|
||||
uint8_t * buffer = (uint8_t *) MSF_GIF_MALLOC(handle->customAllocatorContext, total);
|
||||
if (buffer) {
|
||||
uint8_t * writeHead = buffer;
|
||||
for (uint8_t * node = handle->listHead; node;) {
|
||||
MsfBufferHeader * header = (MsfBufferHeader *) node;
|
||||
memcpy(writeHead, node + sizeof(MsfBufferHeader), header->size);
|
||||
writeHead += header->size;
|
||||
node = header->next;
|
||||
}
|
||||
*writeHead++ = 0x3B;
|
||||
}
|
||||
|
||||
//third pass: free buffers
|
||||
for (uint8_t * node = handle->listHead; node;) {
|
||||
MsfBufferHeader * header = (MsfBufferHeader *) node;
|
||||
node = header->next;
|
||||
MSF_GIF_FREE(handle->customAllocatorContext, header, sizeof(MsfBufferHeader) + header->size);
|
||||
}
|
||||
|
||||
MsfGifResult ret = { buffer, total, total, handle->customAllocatorContext };
|
||||
return ret;
|
||||
}
|
||||
|
||||
void msf_gif_free(MsfGifResult result) {
|
||||
if (result.data) { MSF_GIF_FREE(result.contextPointer, result.data, result.allocSize); }
|
||||
}
|
||||
|
||||
#endif //MSF_GIF_ALREADY_IMPLEMENTED_IN_THIS_TRANSLATION_UNIT
|
||||
#endif //MSF_GIF_IMPL
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------------
|
||||
This software is available under 2 licenses -- choose whichever you prefer.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2020 Miles Fogle
|
||||
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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
930
raylib/external/rgif.h
vendored
930
raylib/external/rgif.h
vendored
|
@ -1,930 +0,0 @@
|
|||
/**********************************************************************************************
|
||||
*
|
||||
* rgif.h v0.5
|
||||
*
|
||||
* Original implementation (gif.h) by Charlie Tangora [ctangora -at- gmail -dot- com]
|
||||
* adapted to C99, reformatted and renamed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This file offers a simple, very limited way to create animated GIFs directly in code.
|
||||
*
|
||||
* Those looking for particular cleverness are likely to be disappointed; it's pretty
|
||||
* much a straight-ahead implementation of the GIF format with optional Floyd-Steinberg
|
||||
* dithering. (It does at least use delta encoding - only the changed portions of each
|
||||
* frame are saved.)
|
||||
*
|
||||
* So resulting files are often quite large. The hope is that it will be handy nonetheless
|
||||
* as a quick and easily-integrated way for programs to spit out animations.
|
||||
*
|
||||
* Only RGBA8 is currently supported as an input format. (The alpha is ignored.)
|
||||
*
|
||||
* CONFIGURATION:
|
||||
*
|
||||
* #define RGIF_IMPLEMENTATION
|
||||
* Generates the implementation of the library into the included file.
|
||||
* If not defined, the library is in header only mode and can be included in other headers
|
||||
* or source files without problems. But only ONE file should hold the implementation.
|
||||
*
|
||||
* USAGE:
|
||||
* 1) Create a GifWriter struct. Pass it to GifBegin() to initialize and write the header.
|
||||
* 2) Pass subsequent frames to GifWriteFrame().
|
||||
* 3) Finally, call GifEnd() to close the file handle and free memory.
|
||||
*
|
||||
*
|
||||
* LICENSE: This software is available under 2 licenses -- choose whichever you prefer
|
||||
*
|
||||
* ALTERNATIVE A - MIT License
|
||||
*
|
||||
* Copyright (c) 2017-2019 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
**********************************************************************************************/
|
||||
|
||||
#ifndef RGIF_H
|
||||
#define RGIF_H
|
||||
|
||||
#include <stdio.h> // Required for: FILE
|
||||
|
||||
//#define RGIF_STATIC
|
||||
#ifdef RGIF_STATIC
|
||||
#define RGIFDEF static // Functions just visible to module including this file
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
#define RGIFDEF extern "C" // Functions visible from other files (no name mangling of functions in C++)
|
||||
#else
|
||||
#define RGIFDEF extern // Functions visible from other files
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// NOTE: By default use bitDepth = 8, dither = false
|
||||
RGIFDEF bool GifBegin(const char *filename, unsigned int width, unsigned int height, unsigned int delay, unsigned int bitDepth, bool dither);
|
||||
RGIFDEF bool GifWriteFrame(const unsigned char *image, unsigned int width, unsigned int height, unsigned int delay, int bitDepth, bool dither);
|
||||
RGIFDEF bool GifEnd();
|
||||
|
||||
#endif // RGIF_H
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
*
|
||||
* GIF IMPLEMENTATION
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#if defined(RGIF_IMPLEMENTATION)
|
||||
|
||||
#include <stdio.h> // Required for: FILE, fopen(), fclose()
|
||||
#include <string.h> // Required for: memcpy()
|
||||
|
||||
// Check if custom malloc/free functions defined, if not, using standard ones
|
||||
// RGIF_MALLOC and RGIF_FREE are used only by GifBegin and GifEnd respectively,
|
||||
// to allocate a buffer the size of the image, which is used to find changed pixels for delta-encoding.
|
||||
#if !defined(RGIF_MALLOC)
|
||||
#include <stdlib.h> // Required for: malloc(), free()
|
||||
|
||||
#define RGIF_MALLOC(size) malloc(size)
|
||||
#define RGIF_FREE(ptr) free(ptr)
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
//----------------------------------------------------------------------------------
|
||||
#define GIFMIN(a, b) (((a)<(b))?(a):(b))
|
||||
#define GIFMAX(a, b) (((a)>(b))?(a):(b))
|
||||
#define GIFABS(x) ((x)<0?-(x):(x))
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Gif palette structure
|
||||
typedef struct GifPalette {
|
||||
int bitDepth;
|
||||
|
||||
unsigned char r[256];
|
||||
unsigned char g[256];
|
||||
unsigned char b[256];
|
||||
|
||||
// k-d tree over RGB space, organized in heap fashion
|
||||
// i.e. left child of node i is node i*2, right child is node i*2 + 1
|
||||
// nodes 256-511 are implicitly the leaves, containing a color
|
||||
unsigned char treeSplitElt[255];
|
||||
unsigned char treeSplit[255];
|
||||
} GifPalette;
|
||||
|
||||
|
||||
// Simple structure to write out the LZW-compressed
|
||||
// portion of the imageone bit at a time
|
||||
typedef struct GifBitStatus {
|
||||
unsigned char bitIndex; // how many bits in the partial byte written so far
|
||||
unsigned char byte; // current partial byte
|
||||
|
||||
unsigned int chunkIndex;
|
||||
unsigned char chunk[256]; // bytes are written in here until we have 256 of them, then written to the file
|
||||
} GifBitStatus;
|
||||
|
||||
// The LZW dictionary is a 256-ary tree constructed
|
||||
// as the file is encoded, this is one node
|
||||
typedef struct GifLzwNode {
|
||||
unsigned short m_next[256];
|
||||
} GifLzwNode;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
const int gifTransparentIndex = 0; // Transparent color index
|
||||
|
||||
static FILE *gifFile = NULL;
|
||||
unsigned char *gifFrame;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static void GifGetClosestPaletteColor(GifPalette *pPal, int r, int g, int b, int *bestInd, int *bestDiff, int treeRoot);
|
||||
static void GifSwapPixels(unsigned char *image, int pixA, int pixB);
|
||||
static int GifPartition(unsigned char *image, const int left, const int right, const int elt, int pivotIndex);
|
||||
static void GifPartitionByMedian(unsigned char *image, int left, int right, int com, int neededCenter);
|
||||
static void GifSplitPalette(unsigned char *image, int numPixels, int firstElt, int lastElt, int splitElt, int splitDist, int treeNode, bool buildForDither, GifPalette *pal);
|
||||
static int GifPickChangedPixels(const unsigned char *lastFrame, unsigned char *frame, int numPixels);
|
||||
static void GifMakePalette(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned int width, unsigned int height, int bitDepth, bool buildForDither, GifPalette *pPal);
|
||||
static void GifDitherImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal);
|
||||
static void GifThresholdImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal);
|
||||
static void GifWriteBit(GifBitStatus *stat, unsigned int bit);
|
||||
|
||||
static void GifWriteChunk(FILE *f, GifBitStatus *stat);
|
||||
static void GifWritePalette(FILE *f, const GifPalette *pPal);
|
||||
static void GifWriteCode(FILE *f, GifBitStatus *stat, unsigned int code, unsigned int length);
|
||||
static void GifWriteLzwImage(FILE *f, unsigned char *image, unsigned int left, unsigned int top, unsigned int width, unsigned int height, unsigned int delay, GifPalette *pPal);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Creates a gif file
|
||||
// NOTE: Initializes internal file pointer (only one gif recording at a time)
|
||||
// The delay value is the time between frames in hundredths of a second - note that not all viewers pay much attention to this value.
|
||||
RGIFDEF bool GifBegin(const char *filename, unsigned int width, unsigned int height, unsigned int delay, unsigned int bitDepth, bool dither)
|
||||
{
|
||||
#if _MSC_VER >= 1400
|
||||
gifFile = 0;
|
||||
fopen_s(&gifFile, filename, "wb");
|
||||
#else
|
||||
gifFile = fopen(filename, "wb");
|
||||
#endif
|
||||
|
||||
if (!gifFile) return false;
|
||||
|
||||
// Allocate space for one gif frame
|
||||
gifFrame = (unsigned char *)RGIF_MALLOC(width*height*4);
|
||||
|
||||
// GIF Header
|
||||
fputs("GIF89a",gifFile);
|
||||
|
||||
// Reference: http://www.onicos.com/staff/iz/formats/gif.html
|
||||
|
||||
// GIF Screen Descriptor
|
||||
fputc(width & 0xff, gifFile);
|
||||
fputc((width >> 8) & 0xff, gifFile); // Screen width (2 byte)
|
||||
fputc(height & 0xff, gifFile);
|
||||
fputc((height >> 8) & 0xff, gifFile); // Screen height (2 byte)
|
||||
|
||||
fputc(0xf0, gifFile); // Color table flags: unsorted global color table of 2 entries (1 byte, bit-flags)
|
||||
fputc(0, gifFile); // Background color index
|
||||
fputc(0, gifFile); // Pixel Aspect Ratio (square, we need to specify this because it's 1989)
|
||||
|
||||
// GIF Global Color table (just a dummy palette)
|
||||
// Color 0: black
|
||||
fputc(0, gifFile);
|
||||
fputc(0, gifFile);
|
||||
fputc(0, gifFile);
|
||||
// Color 1: also black
|
||||
fputc(0, gifFile);
|
||||
fputc(0, gifFile);
|
||||
fputc(0, gifFile);
|
||||
|
||||
if (delay != 0)
|
||||
{
|
||||
// Application Extension Block (19 bytes long)
|
||||
fputc(0x21, gifFile); // GIF Extension code
|
||||
fputc(0xff, gifFile); // Application Extension Label
|
||||
fputc(11, gifFile); // Length of Application Block (11 byte)
|
||||
fputs("NETSCAPE2.0", gifFile); // Application Identifier (Netscape 2.0 block)
|
||||
|
||||
fputc(0x03, gifFile); // Length of Data Sub-Block (3 bytes)
|
||||
fputc(0x01, gifFile); // 0x01
|
||||
fputc(0x00, gifFile); // This specifies the number of times,
|
||||
fputc(0x00, gifFile); // the loop should be executed (infinitely)
|
||||
|
||||
fputc(0x00, gifFile); // Data Sub-Block Terminator.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Writes out a new frame to a GIF in progress.
|
||||
// NOTE: gifFile should have been initialized with GifBegin()
|
||||
// AFAIK, it is legal to use different bit depths for different frames of an image -
|
||||
// this may be handy to save bits in animations that don't change much.
|
||||
RGIFDEF bool GifWriteFrame(const unsigned char *image, unsigned int width, unsigned int height, unsigned int delay, int bitDepth, bool dither)
|
||||
{
|
||||
if (!gifFile) return false;
|
||||
|
||||
const unsigned char *oldImage = gifFrame;
|
||||
|
||||
GifPalette pal;
|
||||
GifMakePalette((dither ? NULL : oldImage), image, width, height, bitDepth, dither, &pal);
|
||||
|
||||
if (dither) GifDitherImage(oldImage, image, gifFrame, width, height, &pal);
|
||||
else GifThresholdImage(oldImage, image, gifFrame, width, height, &pal);
|
||||
|
||||
GifWriteLzwImage(gifFile, gifFrame, 0, 0, width, height, delay, &pal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Writes the EOF code, closes the file handle, and frees temp memory used by a GIF.
|
||||
// Many if not most viewers will still display a GIF properly if the EOF code is missing,
|
||||
// but it's still a good idea to write it out.
|
||||
RGIFDEF bool GifEnd()
|
||||
{
|
||||
if (!gifFile) return false;
|
||||
|
||||
fputc(0x3b, gifFile); // Trailer (end of file)
|
||||
fclose(gifFile);
|
||||
|
||||
RGIF_FREE(gifFrame);
|
||||
|
||||
gifFile = NULL;
|
||||
gifFrame = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// walks the k-d tree to pick the palette entry for a desired color.
|
||||
// Takes as in/out parameters the current best color and its error -
|
||||
// only changes them if it finds a better color in its subtree.
|
||||
// this is the major hotspot in the code at the moment.
|
||||
static void GifGetClosestPaletteColor(GifPalette *pPal, int r, int g, int b, int *bestInd, int *bestDiff, int treeRoot)
|
||||
{
|
||||
// base case, reached the bottom of the tree
|
||||
if (treeRoot > (1<<pPal->bitDepth)-1)
|
||||
{
|
||||
int ind = treeRoot-(1<<pPal->bitDepth);
|
||||
if (ind == gifTransparentIndex) return;
|
||||
|
||||
// check whether this color is better than the current winner
|
||||
int r_err = r - ((int)pPal->r[ind]);
|
||||
int g_err = g - ((int)pPal->g[ind]);
|
||||
int b_err = b - ((int)pPal->b[ind]);
|
||||
int diff = GIFABS(r_err)+GIFABS(g_err)+GIFABS(b_err);
|
||||
|
||||
if (diff < *bestDiff)
|
||||
{
|
||||
*bestInd = ind;
|
||||
*bestDiff = diff;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// take the appropriate color (r, g, or b) for this node of the k-d tree
|
||||
int comps[3]; comps[0] = r; comps[1] = g; comps[2] = b;
|
||||
int splitComp = comps[pPal->treeSplitElt[treeRoot]];
|
||||
|
||||
int splitPos = pPal->treeSplit[treeRoot];
|
||||
if (splitPos > splitComp)
|
||||
{
|
||||
// check the left subtree
|
||||
GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2);
|
||||
|
||||
if (*bestDiff > (splitPos - splitComp))
|
||||
{
|
||||
// cannot prove there's not a better value in the right subtree, check that too
|
||||
GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2 + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2 + 1);
|
||||
|
||||
if (*bestDiff > splitComp - splitPos)
|
||||
{
|
||||
GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GifSwapPixels(unsigned char *image, int pixA, int pixB)
|
||||
{
|
||||
unsigned char rA = image[pixA*4];
|
||||
unsigned char gA = image[pixA*4 + 1];
|
||||
unsigned char bA = image[pixA*4+2];
|
||||
unsigned char aA = image[pixA*4+3];
|
||||
|
||||
unsigned char rB = image[pixB*4];
|
||||
unsigned char gB = image[pixB*4 + 1];
|
||||
unsigned char bB = image[pixB*4+2];
|
||||
unsigned char aB = image[pixA*4+3];
|
||||
|
||||
image[pixA*4] = rB;
|
||||
image[pixA*4 + 1] = gB;
|
||||
image[pixA*4+2] = bB;
|
||||
image[pixA*4+3] = aB;
|
||||
|
||||
image[pixB*4] = rA;
|
||||
image[pixB*4 + 1] = gA;
|
||||
image[pixB*4+2] = bA;
|
||||
image[pixB*4+3] = aA;
|
||||
}
|
||||
|
||||
// just the partition operation from quicksort
|
||||
static int GifPartition(unsigned char *image, const int left, const int right, const int elt, int pivotIndex)
|
||||
{
|
||||
const int pivotValue = image[(pivotIndex)*4+elt];
|
||||
GifSwapPixels(image, pivotIndex, right-1);
|
||||
int storeIndex = left;
|
||||
bool split = 0;
|
||||
for (int ii=left; ii<right-1; ++ii)
|
||||
{
|
||||
int arrayVal = image[ii*4+elt];
|
||||
if (arrayVal < pivotValue)
|
||||
{
|
||||
GifSwapPixels(image, ii, storeIndex);
|
||||
++storeIndex;
|
||||
}
|
||||
else if (arrayVal == pivotValue)
|
||||
{
|
||||
if (split)
|
||||
{
|
||||
GifSwapPixels(image, ii, storeIndex);
|
||||
++storeIndex;
|
||||
}
|
||||
split = !split;
|
||||
}
|
||||
}
|
||||
GifSwapPixels(image, storeIndex, right-1);
|
||||
return storeIndex;
|
||||
}
|
||||
|
||||
// Perform an incomplete sort, finding all elements above and below the desired median
|
||||
static void GifPartitionByMedian(unsigned char *image, int left, int right, int com, int neededCenter)
|
||||
{
|
||||
if (left < right-1)
|
||||
{
|
||||
int pivotIndex = left + (right-left)/2;
|
||||
|
||||
pivotIndex = GifPartition(image, left, right, com, pivotIndex);
|
||||
|
||||
// Only "sort" the section of the array that contains the median
|
||||
if (pivotIndex > neededCenter)
|
||||
GifPartitionByMedian(image, left, pivotIndex, com, neededCenter);
|
||||
|
||||
if (pivotIndex < neededCenter)
|
||||
GifPartitionByMedian(image, pivotIndex + 1, right, com, neededCenter);
|
||||
}
|
||||
}
|
||||
|
||||
// Builds a palette by creating a balanced k-d tree of all pixels in the image
|
||||
static void GifSplitPalette(unsigned char *image, int numPixels, int firstElt, int lastElt, int splitElt, int splitDist,
|
||||
int treeNode, bool buildForDither, GifPalette *pal)
|
||||
{
|
||||
if (lastElt <= firstElt || numPixels == 0)
|
||||
return;
|
||||
|
||||
// base case, bottom of the tree
|
||||
if (lastElt == firstElt + 1)
|
||||
{
|
||||
if (buildForDither)
|
||||
{
|
||||
// Dithering needs at least one color as dark as anything
|
||||
// in the image and at least one brightest color -
|
||||
// otherwise it builds up error and produces strange artifacts
|
||||
if (firstElt == 1)
|
||||
{
|
||||
// special case: the darkest color in the image
|
||||
unsigned int r=255, g=255, b=255;
|
||||
for (int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
r = GIFMIN(r, image[ii*4+0]);
|
||||
g = GIFMIN(g, image[ii*4 + 1]);
|
||||
b = GIFMIN(b, image[ii*4+2]);
|
||||
}
|
||||
|
||||
pal->r[firstElt] = r;
|
||||
pal->g[firstElt] = g;
|
||||
pal->b[firstElt] = b;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstElt == (1 << pal->bitDepth)-1)
|
||||
{
|
||||
// special case: the lightest color in the image
|
||||
unsigned int r=0, g=0, b=0;
|
||||
for (int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
r = GIFMAX(r, image[ii*4+0]);
|
||||
g = GIFMAX(g, image[ii*4 + 1]);
|
||||
b = GIFMAX(b, image[ii*4+2]);
|
||||
}
|
||||
|
||||
pal->r[firstElt] = r;
|
||||
pal->g[firstElt] = g;
|
||||
pal->b[firstElt] = b;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise, take the average of all colors in this subcube
|
||||
unsigned long long r=0, g=0, b=0;
|
||||
for (int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
r += image[ii*4+0];
|
||||
g += image[ii*4 + 1];
|
||||
b += image[ii*4+2];
|
||||
}
|
||||
|
||||
r += numPixels / 2; // round to nearest
|
||||
g += numPixels / 2;
|
||||
b += numPixels / 2;
|
||||
|
||||
r /= numPixels;
|
||||
g /= numPixels;
|
||||
b /= numPixels;
|
||||
|
||||
pal->r[firstElt] = (unsigned char)r;
|
||||
pal->g[firstElt] = (unsigned char)g;
|
||||
pal->b[firstElt] = (unsigned char)b;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the axis with the largest range
|
||||
int minR = 255, maxR = 0;
|
||||
int minG = 255, maxG = 0;
|
||||
int minB = 255, maxB = 0;
|
||||
for (int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
int r = image[ii*4+0];
|
||||
int g = image[ii*4 + 1];
|
||||
int b = image[ii*4+2];
|
||||
|
||||
if (r > maxR) maxR = r;
|
||||
if (r < minR) minR = r;
|
||||
|
||||
if (g > maxG) maxG = g;
|
||||
if (g < minG) minG = g;
|
||||
|
||||
if (b > maxB) maxB = b;
|
||||
if (b < minB) minB = b;
|
||||
}
|
||||
|
||||
int rRange = maxR - minR;
|
||||
int gRange = maxG - minG;
|
||||
int bRange = maxB - minB;
|
||||
|
||||
// and split along that axis. (incidentally, this means this isn't a "proper" k-d tree but I don't know what else to call it)
|
||||
int splitCom = 1;
|
||||
if (bRange > gRange) splitCom = 2;
|
||||
if (rRange > bRange && rRange > gRange) splitCom = 0;
|
||||
|
||||
int subPixelsA = numPixels *(splitElt - firstElt) / (lastElt - firstElt);
|
||||
int subPixelsB = numPixels-subPixelsA;
|
||||
|
||||
GifPartitionByMedian(image, 0, numPixels, splitCom, subPixelsA);
|
||||
|
||||
pal->treeSplitElt[treeNode] = splitCom;
|
||||
pal->treeSplit[treeNode] = image[subPixelsA*4+splitCom];
|
||||
|
||||
GifSplitPalette(image, subPixelsA, firstElt, splitElt, splitElt-splitDist, splitDist/2, treeNode*2, buildForDither, pal);
|
||||
GifSplitPalette(image+subPixelsA*4, subPixelsB, splitElt, lastElt, splitElt+splitDist, splitDist/2, treeNode*2 + 1, buildForDither, pal);
|
||||
}
|
||||
|
||||
// Finds all pixels that have changed from the previous image and
|
||||
// moves them to the fromt of th buffer.
|
||||
// This allows us to build a palette optimized for the colors of the
|
||||
// changed pixels only.
|
||||
static int GifPickChangedPixels(const unsigned char *lastFrame, unsigned char *frame, int numPixels)
|
||||
{
|
||||
int numChanged = 0;
|
||||
unsigned char *writeIter = frame;
|
||||
|
||||
for (int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
if (lastFrame[0] != frame[0] ||
|
||||
lastFrame[1] != frame[1] ||
|
||||
lastFrame[2] != frame[2])
|
||||
{
|
||||
writeIter[0] = frame[0];
|
||||
writeIter[1] = frame[1];
|
||||
writeIter[2] = frame[2];
|
||||
++numChanged;
|
||||
writeIter += 4;
|
||||
}
|
||||
lastFrame += 4;
|
||||
frame += 4;
|
||||
}
|
||||
|
||||
return numChanged;
|
||||
}
|
||||
|
||||
// Creates a palette by placing all the image pixels in a k-d tree and then averaging the blocks at the bottom.
|
||||
// This is known as the "modified median split" technique
|
||||
static void GifMakePalette(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned int width, unsigned int height, int bitDepth, bool buildForDither, GifPalette *pPal)
|
||||
{
|
||||
pPal->bitDepth = bitDepth;
|
||||
|
||||
// SplitPalette is destructive (it sorts the pixels by color) so
|
||||
// we must create a copy of the image for it to destroy
|
||||
int imageSize = width*height*4*sizeof(unsigned char);
|
||||
unsigned char *destroyableImage = (unsigned char*)RGIF_MALLOC(imageSize);
|
||||
memcpy(destroyableImage, nextFrame, imageSize);
|
||||
|
||||
int numPixels = width*height;
|
||||
if (lastFrame)
|
||||
numPixels = GifPickChangedPixels(lastFrame, destroyableImage, numPixels);
|
||||
|
||||
const int lastElt = 1 << bitDepth;
|
||||
const int splitElt = lastElt/2;
|
||||
const int splitDist = splitElt/2;
|
||||
|
||||
GifSplitPalette(destroyableImage, numPixels, 1, lastElt, splitElt, splitDist, 1, buildForDither, pPal);
|
||||
|
||||
RGIF_FREE(destroyableImage);
|
||||
|
||||
// add the bottom node for the transparency index
|
||||
pPal->treeSplit[1 << (bitDepth-1)] = 0;
|
||||
pPal->treeSplitElt[1 << (bitDepth-1)] = 0;
|
||||
|
||||
pPal->r[0] = pPal->g[0] = pPal->b[0] = 0;
|
||||
}
|
||||
|
||||
// Implements Floyd-Steinberg dithering, writes palette value to alpha
|
||||
static void GifDitherImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal)
|
||||
{
|
||||
int numPixels = width*height;
|
||||
|
||||
// quantPixels initially holds color*256 for all pixels
|
||||
// The extra 8 bits of precision allow for sub-single-color error values
|
||||
// to be propagated
|
||||
int *quantPixels = (int*)RGIF_MALLOC(sizeof(int)*numPixels*4);
|
||||
|
||||
for (int ii=0; ii<numPixels*4; ++ii)
|
||||
{
|
||||
unsigned char pix = nextFrame[ii];
|
||||
int pix16 = (int)pix*256;
|
||||
quantPixels[ii] = pix16;
|
||||
}
|
||||
|
||||
for (unsigned int yy=0; yy<height; ++yy)
|
||||
{
|
||||
for (unsigned int xx=0; xx<width; ++xx)
|
||||
{
|
||||
int *nextPix = quantPixels + 4*(yy*width+xx);
|
||||
const unsigned char *lastPix = lastFrame? lastFrame + 4*(yy*width+xx) : NULL;
|
||||
|
||||
// Compute the colors we want (rounding to nearest)
|
||||
int rr = (nextPix[0] + 127) / 256;
|
||||
int gg = (nextPix[1] + 127) / 256;
|
||||
int bb = (nextPix[2] + 127) / 256;
|
||||
|
||||
// if it happens that we want the color from last frame, then just write out
|
||||
// a transparent pixel
|
||||
if (lastFrame &&
|
||||
lastPix[0] == rr &&
|
||||
lastPix[1] == gg &&
|
||||
lastPix[2] == bb)
|
||||
{
|
||||
nextPix[0] = rr;
|
||||
nextPix[1] = gg;
|
||||
nextPix[2] = bb;
|
||||
nextPix[3] = gifTransparentIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
int bestDiff = 1000000;
|
||||
int bestInd = gifTransparentIndex;
|
||||
|
||||
// Search the palete
|
||||
GifGetClosestPaletteColor(pPal, rr, gg, bb, &bestInd, &bestDiff, 1);
|
||||
|
||||
// Write the result to the temp buffer
|
||||
int r_err = nextPix[0] - (int)(pPal->r[bestInd])*256;
|
||||
int g_err = nextPix[1] - (int)(pPal->g[bestInd])*256;
|
||||
int b_err = nextPix[2] - (int)(pPal->b[bestInd])*256;
|
||||
|
||||
nextPix[0] = pPal->r[bestInd];
|
||||
nextPix[1] = pPal->g[bestInd];
|
||||
nextPix[2] = pPal->b[bestInd];
|
||||
nextPix[3] = bestInd;
|
||||
|
||||
// Propagate the error to the four adjacent locations
|
||||
// that we haven't touched yet
|
||||
int quantloc_7 = (yy*width+xx + 1);
|
||||
int quantloc_3 = (yy*width+width+xx-1);
|
||||
int quantloc_5 = (yy*width+width+xx);
|
||||
int quantloc_1 = (yy*width+width+xx + 1);
|
||||
|
||||
if (quantloc_7 < numPixels)
|
||||
{
|
||||
int *pix7 = quantPixels+4*quantloc_7;
|
||||
pix7[0] += GIFMAX(-pix7[0], r_err*7 / 16);
|
||||
pix7[1] += GIFMAX(-pix7[1], g_err*7 / 16);
|
||||
pix7[2] += GIFMAX(-pix7[2], b_err*7 / 16);
|
||||
}
|
||||
|
||||
if (quantloc_3 < numPixels)
|
||||
{
|
||||
int *pix3 = quantPixels+4*quantloc_3;
|
||||
pix3[0] += GIFMAX(-pix3[0], r_err*3 / 16);
|
||||
pix3[1] += GIFMAX(-pix3[1], g_err*3 / 16);
|
||||
pix3[2] += GIFMAX(-pix3[2], b_err*3 / 16);
|
||||
}
|
||||
|
||||
if (quantloc_5 < numPixels)
|
||||
{
|
||||
int *pix5 = quantPixels+4*quantloc_5;
|
||||
pix5[0] += GIFMAX(-pix5[0], r_err*5 / 16);
|
||||
pix5[1] += GIFMAX(-pix5[1], g_err*5 / 16);
|
||||
pix5[2] += GIFMAX(-pix5[2], b_err*5 / 16);
|
||||
}
|
||||
|
||||
if (quantloc_1 < numPixels)
|
||||
{
|
||||
int *pix1 = quantPixels+4*quantloc_1;
|
||||
pix1[0] += GIFMAX(-pix1[0], r_err / 16);
|
||||
pix1[1] += GIFMAX(-pix1[1], g_err / 16);
|
||||
pix1[2] += GIFMAX(-pix1[2], b_err / 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the palettized result to the output buffer
|
||||
for (int ii=0; ii<numPixels*4; ++ii)
|
||||
{
|
||||
outFrame[ii] = quantPixels[ii];
|
||||
}
|
||||
|
||||
RGIF_FREE(quantPixels);
|
||||
}
|
||||
|
||||
// Picks palette colors for the image using simple thresholding, no dithering
|
||||
static void GifThresholdImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal)
|
||||
{
|
||||
unsigned int numPixels = width*height;
|
||||
for (unsigned int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
// if a previous color is available, and it matches the current color,
|
||||
// set the pixel to transparent
|
||||
if (lastFrame &&
|
||||
lastFrame[0] == nextFrame[0] &&
|
||||
lastFrame[1] == nextFrame[1] &&
|
||||
lastFrame[2] == nextFrame[2])
|
||||
{
|
||||
outFrame[0] = lastFrame[0];
|
||||
outFrame[1] = lastFrame[1];
|
||||
outFrame[2] = lastFrame[2];
|
||||
outFrame[3] = gifTransparentIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// palettize the pixel
|
||||
int bestDiff = 1000000;
|
||||
int bestInd = 1;
|
||||
GifGetClosestPaletteColor(pPal, nextFrame[0], nextFrame[1], nextFrame[2], &bestInd, &bestDiff, 1);
|
||||
|
||||
// Write the resulting color to the output buffer
|
||||
outFrame[0] = pPal->r[bestInd];
|
||||
outFrame[1] = pPal->g[bestInd];
|
||||
outFrame[2] = pPal->b[bestInd];
|
||||
outFrame[3] = bestInd;
|
||||
}
|
||||
|
||||
if (lastFrame) lastFrame += 4;
|
||||
outFrame += 4;
|
||||
nextFrame += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// insert a single bit
|
||||
static void GifWriteBit(GifBitStatus *stat, unsigned int bit)
|
||||
{
|
||||
bit = bit & 1;
|
||||
bit = bit << stat->bitIndex;
|
||||
stat->byte |= bit;
|
||||
|
||||
++stat->bitIndex;
|
||||
if (stat->bitIndex > 7)
|
||||
{
|
||||
// move the newly-finished byte to the chunk buffer
|
||||
stat->chunk[stat->chunkIndex++] = stat->byte;
|
||||
// and start a new byte
|
||||
stat->bitIndex = 0;
|
||||
stat->byte = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// write all bytes so far to the file
|
||||
static void GifWriteChunk(FILE *f, GifBitStatus *stat)
|
||||
{
|
||||
fputc(stat->chunkIndex, f);
|
||||
fwrite(stat->chunk, 1, stat->chunkIndex, f);
|
||||
|
||||
stat->bitIndex = 0;
|
||||
stat->byte = 0;
|
||||
stat->chunkIndex = 0;
|
||||
}
|
||||
|
||||
static void GifWriteCode(FILE *f, GifBitStatus *stat, unsigned int code, unsigned int length)
|
||||
{
|
||||
for (unsigned int ii=0; ii<length; ++ii)
|
||||
{
|
||||
GifWriteBit(stat, code);
|
||||
code = code >> 1;
|
||||
|
||||
if (stat->chunkIndex == 255)
|
||||
{
|
||||
GifWriteChunk(f, stat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write a 256-color (8-bit) image palette to the file
|
||||
static void GifWritePalette(FILE *f, const GifPalette *pPal)
|
||||
{
|
||||
fputc(0, f); // first color: transparency
|
||||
fputc(0, f);
|
||||
fputc(0, f);
|
||||
|
||||
for (int ii=1; ii<(1 << pPal->bitDepth); ++ii)
|
||||
{
|
||||
unsigned int r = pPal->r[ii];
|
||||
unsigned int g = pPal->g[ii];
|
||||
unsigned int b = pPal->b[ii];
|
||||
|
||||
fputc(r, f);
|
||||
fputc(g, f);
|
||||
fputc(b, f);
|
||||
}
|
||||
}
|
||||
|
||||
// write the image header, LZW-compress and write out the image
|
||||
static void GifWriteLzwImage(FILE *f, unsigned char *image, unsigned int left, unsigned int top, unsigned int width, unsigned int height, unsigned int delay, GifPalette *pPal)
|
||||
{
|
||||
// graphics control extension
|
||||
fputc(0x21, f);
|
||||
fputc(0xf9, f);
|
||||
fputc(0x04, f);
|
||||
fputc(0x05, f); // leave prev frame in place, this frame has transparency
|
||||
fputc(delay & 0xff, f);
|
||||
fputc((delay >> 8) & 0xff, f);
|
||||
fputc(gifTransparentIndex, f); // transparent color index
|
||||
fputc(0, f);
|
||||
|
||||
fputc(0x2c, f); // image descriptor block
|
||||
|
||||
fputc(left & 0xff, f); // corner of image in canvas space
|
||||
fputc((left >> 8) & 0xff, f);
|
||||
fputc(top & 0xff, f);
|
||||
fputc((top >> 8) & 0xff, f);
|
||||
|
||||
fputc(width & 0xff, f); // width and height of image
|
||||
fputc((width >> 8) & 0xff, f);
|
||||
fputc(height & 0xff, f);
|
||||
fputc((height >> 8) & 0xff, f);
|
||||
|
||||
//fputc(0, f); // no local color table, no transparency
|
||||
//fputc(0x80, f); // no local color table, but transparency
|
||||
|
||||
fputc(0x80 + pPal->bitDepth-1, f); // local color table present, 2 ^ bitDepth entries
|
||||
GifWritePalette(f, pPal);
|
||||
|
||||
const int minCodeSize = pPal->bitDepth;
|
||||
const unsigned int clearCode = 1 << pPal->bitDepth;
|
||||
|
||||
fputc(minCodeSize, f); // min code size 8 bits
|
||||
|
||||
GifLzwNode *codetree = (GifLzwNode *)RGIF_MALLOC(sizeof(GifLzwNode)*4096);
|
||||
|
||||
memset(codetree, 0, sizeof(GifLzwNode)*4096);
|
||||
int curCode = -1;
|
||||
unsigned int codeSize = minCodeSize + 1;
|
||||
unsigned int maxCode = clearCode + 1;
|
||||
|
||||
GifBitStatus stat;
|
||||
stat.byte = 0;
|
||||
stat.bitIndex = 0;
|
||||
stat.chunkIndex = 0;
|
||||
|
||||
GifWriteCode(f, &stat, clearCode, codeSize); // start with a fresh LZW dictionary
|
||||
|
||||
for (unsigned int yy=0; yy<height; ++yy)
|
||||
{
|
||||
for (unsigned int xx=0; xx<width; ++xx)
|
||||
{
|
||||
unsigned char nextValue = image[(yy*width+xx)*4+3];
|
||||
|
||||
// "loser mode" - no compression, every single code is followed immediately by a clear
|
||||
//WriteCode(f, stat, nextValue, codeSize);
|
||||
//WriteCode(f, stat, 256, codeSize);
|
||||
|
||||
if (curCode < 0)
|
||||
{
|
||||
// first value in a new run
|
||||
curCode = nextValue;
|
||||
}
|
||||
else if (codetree[curCode].m_next[nextValue])
|
||||
{
|
||||
// current run already in the dictionary
|
||||
curCode = codetree[curCode].m_next[nextValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
// finish the current run, write a code
|
||||
GifWriteCode(f, &stat, curCode, codeSize);
|
||||
|
||||
// insert the new run into the dictionary
|
||||
codetree[curCode].m_next[nextValue] = ++maxCode;
|
||||
|
||||
if (maxCode >= (1ul << codeSize))
|
||||
{
|
||||
// dictionary entry count has broken a size barrier,
|
||||
// we need more bits for codes
|
||||
codeSize++;
|
||||
}
|
||||
if (maxCode == 4095)
|
||||
{
|
||||
// the dictionary is full, clear it out and begin anew
|
||||
GifWriteCode(f, &stat, clearCode, codeSize); // clear tree
|
||||
|
||||
memset(codetree, 0, sizeof(GifLzwNode)*4096);
|
||||
codeSize = minCodeSize + 1;
|
||||
maxCode = clearCode + 1;
|
||||
}
|
||||
|
||||
curCode = nextValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compression footer
|
||||
GifWriteCode(f, &stat, curCode, codeSize);
|
||||
GifWriteCode(f, &stat, clearCode, codeSize);
|
||||
GifWriteCode(f, &stat, clearCode + 1, minCodeSize + 1);
|
||||
|
||||
// write out the last partial chunk
|
||||
while (stat.bitIndex) GifWriteBit(&stat, 0);
|
||||
if (stat.chunkIndex) GifWriteChunk(f, &stat);
|
||||
|
||||
fputc(0, f); // image block terminator
|
||||
|
||||
RGIF_FREE(codetree);
|
||||
}
|
||||
|
||||
#endif // RGIF_IMPLEMENTATION
|
697
raylib/external/sdefl.h
vendored
Normal file
697
raylib/external/sdefl.h
vendored
Normal file
|
@ -0,0 +1,697 @@
|
|||
/*
|
||||
# Small Deflate
|
||||
`sdefl` is a small bare bone lossless compression library in ANSI C (ISO C90)
|
||||
which implements the Deflate (RFC 1951) compressed data format specification standard.
|
||||
It is mainly tuned to get as much speed and compression ratio from as little code
|
||||
as needed to keep the implementation as concise as possible.
|
||||
|
||||
## Features
|
||||
- Portable single header and source file duo written in ANSI C (ISO C90)
|
||||
- Dual license with either MIT or public domain
|
||||
- Small implementation
|
||||
- Deflate: 525 LoC
|
||||
- Inflate: 320 LoC
|
||||
- Webassembly:
|
||||
- Deflate ~3.7 KB (~2.2KB compressed)
|
||||
- Inflate ~3.6 KB (~2.2KB compressed)
|
||||
|
||||
## Usage:
|
||||
This file behaves differently depending on what symbols you define
|
||||
before including it.
|
||||
|
||||
Header-File mode:
|
||||
If you do not define `SDEFL_IMPLEMENTATION` before including this file, it
|
||||
will operate in header only mode. In this mode it declares all used structs
|
||||
and the API of the library without including the implementation of the library.
|
||||
|
||||
Implementation mode:
|
||||
If you define `SDEFL_IMPLEMENTATION` before including this file, it will
|
||||
compile the implementation . Make sure that you only include
|
||||
this file implementation in *one* C or C++ file to prevent collisions.
|
||||
|
||||
### Benchmark
|
||||
|
||||
| Compressor name | Compression| Decompress.| Compr. size | Ratio |
|
||||
| ------------------------| -----------| -----------| ----------- | ----- |
|
||||
| sdefl 1.0 -0 | 127 MB/s | 233 MB/s | 40004116 | 39.88 |
|
||||
| sdefl 1.0 -1 | 111 MB/s | 259 MB/s | 38940674 | 38.82 |
|
||||
| sdefl 1.0 -5 | 45 MB/s | 275 MB/s | 36577183 | 36.46 |
|
||||
| sdefl 1.0 -7 | 38 MB/s | 276 MB/s | 36523781 | 36.41 |
|
||||
| zlib 1.2.11 -1 | 72 MB/s | 307 MB/s | 42298774 | 42.30 |
|
||||
| zlib 1.2.11 -6 | 24 MB/s | 313 MB/s | 36548921 | 36.55 |
|
||||
| zlib 1.2.11 -9 | 20 MB/s | 314 MB/s | 36475792 | 36.48 |
|
||||
| miniz 1.0 -1 | 122 MB/s | 208 MB/s | 48510028 | 48.51 |
|
||||
| miniz 1.0 -6 | 27 MB/s | 260 MB/s | 36513697 | 36.51 |
|
||||
| miniz 1.0 -9 | 23 MB/s | 261 MB/s | 36460101 | 36.46 |
|
||||
| libdeflate 1.3 -1 | 147 MB/s | 667 MB/s | 39597378 | 39.60 |
|
||||
| libdeflate 1.3 -6 | 69 MB/s | 689 MB/s | 36648318 | 36.65 |
|
||||
| libdeflate 1.3 -9 | 13 MB/s | 672 MB/s | 35197141 | 35.20 |
|
||||
| libdeflate 1.3 -12 | 8.13 MB/s | 670 MB/s | 35100568 | 35.10 |
|
||||
|
||||
### Compression
|
||||
Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia):
|
||||
|
||||
| File | Original | `sdefl 0` | `sdefl 5` | `sdefl 7` |
|
||||
| :------ | ---------: | -----------------: | ---------: | ----------: |
|
||||
| dickens | 10.192.446 | 4,260,187| 3,845,261| 3,833,657 |
|
||||
| mozilla | 51.220.480 | 20,774,706 | 19,607,009 | 19,565,867 |
|
||||
| mr | 9.970.564 | 3,860,531 | 3,673,460 | 3,665,627 |
|
||||
| nci | 33.553.445 | 4,030,283 | 3,094,526 | 3,006,075 |
|
||||
| ooffice | 6.152.192 | 3,320,063 | 3,186,373 | 3,183,815 |
|
||||
| osdb | 10.085.684 | 3,919,646 | 3,649,510 | 3,649,477 |
|
||||
| reymont | 6.627.202 | 2,263,378 | 1,857,588 | 1,827,237 |
|
||||
| samba | 21.606.400 | 6,121,797 | 5,462,670 | 5,450,762 |
|
||||
| sao | 7.251.944 | 5,612,421 | 5,485,380 | 5,481,765 |
|
||||
| webster | 41.458.703 | 13,972,648 | 12,059,432 | 11,991,421 |
|
||||
| xml | 5.345.280 | 886,620| 674,009 | 662,141 |
|
||||
| x-ray | 8.474.240 | 6,304,655 | 6,244,779 | 6,244,779 |
|
||||
|
||||
## License
|
||||
```
|
||||
------------------------------------------------------------------------------
|
||||
This software is available under 2 licenses -- choose whichever you prefer.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2020 Micha Mettke
|
||||
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.
|
||||
------------------------------------------------------------------------------
|
||||
```
|
||||
*/
|
||||
#ifndef SDEFL_H_INCLUDED
|
||||
#define SDEFL_H_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SDEFL_MAX_OFF (1 << 15)
|
||||
#define SDEFL_WIN_SIZ SDEFL_MAX_OFF
|
||||
#define SDEFL_WIN_MSK (SDEFL_WIN_SIZ-1)
|
||||
|
||||
#define SDEFL_HASH_BITS 15
|
||||
#define SDEFL_HASH_SIZ (1 << SDEFL_HASH_BITS)
|
||||
#define SDEFL_HASH_MSK (SDEFL_HASH_SIZ-1)
|
||||
|
||||
#define SDEFL_MIN_MATCH 4
|
||||
#define SDEFL_BLK_MAX (256*1024)
|
||||
#define SDEFL_SEQ_SIZ ((SDEFL_BLK_MAX + SDEFL_MIN_MATCH)/SDEFL_MIN_MATCH)
|
||||
|
||||
#define SDEFL_SYM_MAX (288)
|
||||
#define SDEFL_OFF_MAX (32)
|
||||
#define SDEFL_PRE_MAX (19)
|
||||
|
||||
#define SDEFL_LVL_MIN 0
|
||||
#define SDEFL_LVL_DEF 5
|
||||
#define SDEFL_LVL_MAX 8
|
||||
|
||||
struct sdefl_freq {
|
||||
unsigned lit[SDEFL_SYM_MAX];
|
||||
unsigned off[SDEFL_OFF_MAX];
|
||||
};
|
||||
struct sdefl_code_words {
|
||||
unsigned lit[SDEFL_SYM_MAX];
|
||||
unsigned off[SDEFL_OFF_MAX];
|
||||
};
|
||||
struct sdefl_lens {
|
||||
unsigned char lit[SDEFL_SYM_MAX];
|
||||
unsigned char off[SDEFL_OFF_MAX];
|
||||
};
|
||||
struct sdefl_codes {
|
||||
struct sdefl_code_words word;
|
||||
struct sdefl_lens len;
|
||||
};
|
||||
struct sdefl_seqt {
|
||||
int off, len;
|
||||
};
|
||||
struct sdefl {
|
||||
int bits, bitcnt;
|
||||
int tbl[SDEFL_HASH_SIZ];
|
||||
int prv[SDEFL_WIN_SIZ];
|
||||
|
||||
int seq_cnt;
|
||||
struct sdefl_seqt seq[SDEFL_SEQ_SIZ];
|
||||
struct sdefl_freq freq;
|
||||
struct sdefl_codes cod;
|
||||
};
|
||||
extern int sdefl_bound(int in_len);
|
||||
extern int sdeflate(struct sdefl *s, void *o, const void *i, int n, int lvl);
|
||||
extern int zsdeflate(struct sdefl *s, void *o, const void *i, int n, int lvl);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SDEFL_H_INCLUDED */
|
||||
|
||||
#ifdef SDEFL_IMPLEMENTATION
|
||||
|
||||
#include <assert.h> /* assert */
|
||||
#include <string.h> /* memcpy */
|
||||
#include <limits.h> /* CHAR_BIT */
|
||||
|
||||
#define SDEFL_NIL (-1)
|
||||
#define SDEFL_MAX_MATCH 258
|
||||
#define SDEFL_MAX_CODE_LEN (15)
|
||||
#define SDEFL_SYM_BITS (10u)
|
||||
#define SDEFL_SYM_MSK ((1u << SDEFL_SYM_BITS)-1u)
|
||||
#define SDEFL_LIT_LEN_CODES (14)
|
||||
#define SDEFL_OFF_CODES (15)
|
||||
#define SDEFL_PRE_CODES (7)
|
||||
#define SDEFL_CNT_NUM(n) ((((n)+3u/4u)+3u)&~3u)
|
||||
#define SDEFL_EOB (256)
|
||||
|
||||
#define sdefl_npow2(n) (1 << (sdefl_ilog2((n)-1) + 1))
|
||||
|
||||
static int
|
||||
sdefl_ilog2(int n) {
|
||||
if (!n) return 0;
|
||||
#ifdef _MSC_VER
|
||||
unsigned long msbp = 0;
|
||||
_BitScanReverse(&msbp, (unsigned long)n);
|
||||
return (int)msbp;
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
return (int)sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl((unsigned long)n);
|
||||
#else
|
||||
#define lt(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
|
||||
static const char tbl[256] = {
|
||||
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,lt(4), lt(5), lt(5), lt(6), lt(6), lt(6), lt(6),
|
||||
lt(7), lt(7), lt(7), lt(7), lt(7), lt(7), lt(7), lt(7)};
|
||||
int tt, t;
|
||||
if ((tt = (n >> 16))) {
|
||||
return (t = (tt >> 8)) ? 24 + tbl[t] : 16 + tbl[tt];
|
||||
} else {
|
||||
return (t = (n >> 8)) ? 8 + tbl[t] : tbl[n];
|
||||
}
|
||||
#undef lt
|
||||
#endif
|
||||
}
|
||||
static unsigned
|
||||
sdefl_uload32(const void *p) {
|
||||
/* hopefully will be optimized to an unaligned read */
|
||||
unsigned n = 0;
|
||||
memcpy(&n, p, sizeof(n));
|
||||
return n;
|
||||
}
|
||||
static unsigned
|
||||
sdefl_hash32(const void *p) {
|
||||
unsigned n = sdefl_uload32(p);
|
||||
return (n * 0x9E377989) >> (32 - SDEFL_HASH_BITS);
|
||||
}
|
||||
static void
|
||||
sdefl_put(unsigned char **dst, struct sdefl *s, int code, int bitcnt) {
|
||||
s->bits |= (code << s->bitcnt);
|
||||
s->bitcnt += bitcnt;
|
||||
while (s->bitcnt >= 8) {
|
||||
unsigned char *tar = *dst;
|
||||
*tar = (unsigned char)(s->bits & 0xFF);
|
||||
s->bits >>= 8;
|
||||
s->bitcnt -= 8;
|
||||
*dst = *dst + 1;
|
||||
}
|
||||
}
|
||||
static void
|
||||
sdefl_heap_sub(unsigned A[], unsigned len, unsigned sub) {
|
||||
unsigned c, p = sub;
|
||||
unsigned v = A[sub];
|
||||
while ((c = p << 1) <= len) {
|
||||
if (c < len && A[c + 1] > A[c]) c++;
|
||||
if (v >= A[c]) break;
|
||||
A[p] = A[c], p = c;
|
||||
}
|
||||
A[p] = v;
|
||||
}
|
||||
static void
|
||||
sdefl_heap_array(unsigned *A, unsigned len) {
|
||||
unsigned sub;
|
||||
for (sub = len >> 1; sub >= 1; sub--)
|
||||
sdefl_heap_sub(A, len, sub);
|
||||
}
|
||||
static void
|
||||
sdefl_heap_sort(unsigned *A, unsigned n) {
|
||||
A--;
|
||||
sdefl_heap_array(A, n);
|
||||
while (n >= 2) {
|
||||
unsigned tmp = A[n];
|
||||
A[n--] = A[1];
|
||||
A[1] = tmp;
|
||||
sdefl_heap_sub(A, n, 1);
|
||||
}
|
||||
}
|
||||
static unsigned
|
||||
sdefl_sort_sym(unsigned sym_cnt, unsigned *freqs,
|
||||
unsigned char *lens, unsigned *sym_out) {
|
||||
unsigned cnts[SDEFL_CNT_NUM(SDEFL_SYM_MAX)] = {0};
|
||||
unsigned cnt_num = SDEFL_CNT_NUM(sym_cnt);
|
||||
unsigned used_sym = 0;
|
||||
unsigned sym, i;
|
||||
for (sym = 0; sym < sym_cnt; sym++)
|
||||
cnts[freqs[sym] < cnt_num-1 ? freqs[sym]: cnt_num-1]++;
|
||||
for (i = 1; i < cnt_num; i++) {
|
||||
unsigned cnt = cnts[i];
|
||||
cnts[i] = used_sym;
|
||||
used_sym += cnt;
|
||||
}
|
||||
for (sym = 0; sym < sym_cnt; sym++) {
|
||||
unsigned freq = freqs[sym];
|
||||
if (freq) {
|
||||
unsigned idx = freq < cnt_num-1 ? freq : cnt_num-1;
|
||||
sym_out[cnts[idx]++] = sym | (freq << SDEFL_SYM_BITS);
|
||||
} else lens[sym] = 0;
|
||||
}
|
||||
sdefl_heap_sort(sym_out + cnts[cnt_num-2], cnts[cnt_num-1] - cnts[cnt_num-2]);
|
||||
return used_sym;
|
||||
}
|
||||
static void
|
||||
sdefl_build_tree(unsigned *A, unsigned sym_cnt) {
|
||||
unsigned i = 0, b = 0, e = 0;
|
||||
do {
|
||||
unsigned m, n, freq_shift;
|
||||
if (i != sym_cnt && (b == e || (A[i] >> SDEFL_SYM_BITS) <= (A[b] >> SDEFL_SYM_BITS)))
|
||||
m = i++;
|
||||
else m = b++;
|
||||
if (i != sym_cnt && (b == e || (A[i] >> SDEFL_SYM_BITS) <= (A[b] >> SDEFL_SYM_BITS)))
|
||||
n = i++;
|
||||
else n = b++;
|
||||
|
||||
freq_shift = (A[m] & ~SDEFL_SYM_MSK) + (A[n] & ~SDEFL_SYM_MSK);
|
||||
A[m] = (A[m] & SDEFL_SYM_MSK) | (e << SDEFL_SYM_BITS);
|
||||
A[n] = (A[n] & SDEFL_SYM_MSK) | (e << SDEFL_SYM_BITS);
|
||||
A[e] = (A[e] & SDEFL_SYM_MSK) | freq_shift;
|
||||
} while (sym_cnt - ++e > 1);
|
||||
}
|
||||
static void
|
||||
sdefl_gen_len_cnt(unsigned *A, unsigned root, unsigned *len_cnt,
|
||||
unsigned max_code_len) {
|
||||
int n;
|
||||
unsigned i;
|
||||
for (i = 0; i <= max_code_len; i++)
|
||||
len_cnt[i] = 0;
|
||||
len_cnt[1] = 2;
|
||||
|
||||
A[root] &= SDEFL_SYM_MSK;
|
||||
for (n = (int)root - 1; n >= 0; n--) {
|
||||
unsigned p = A[n] >> SDEFL_SYM_BITS;
|
||||
unsigned pdepth = A[p] >> SDEFL_SYM_BITS;
|
||||
unsigned depth = pdepth + 1;
|
||||
unsigned len = depth;
|
||||
|
||||
A[n] = (A[n] & SDEFL_SYM_MSK) | (depth << SDEFL_SYM_BITS);
|
||||
if (len >= max_code_len) {
|
||||
len = max_code_len;
|
||||
do len--; while (!len_cnt[len]);
|
||||
}
|
||||
len_cnt[len]--;
|
||||
len_cnt[len+1] += 2;
|
||||
}
|
||||
}
|
||||
static void
|
||||
sdefl_gen_codes(unsigned *A, unsigned char *lens, const unsigned *len_cnt,
|
||||
unsigned max_code_word_len, unsigned sym_cnt) {
|
||||
unsigned i, sym, len, nxt[SDEFL_MAX_CODE_LEN + 1];
|
||||
for (i = 0, len = max_code_word_len; len >= 1; len--) {
|
||||
unsigned cnt = len_cnt[len];
|
||||
while (cnt--) lens[A[i++] & SDEFL_SYM_MSK] = (unsigned char)len;
|
||||
}
|
||||
nxt[0] = nxt[1] = 0;
|
||||
for (len = 2; len <= max_code_word_len; len++)
|
||||
nxt[len] = (nxt[len-1] + len_cnt[len-1]) << 1;
|
||||
for (sym = 0; sym < sym_cnt; sym++)
|
||||
A[sym] = nxt[lens[sym]]++;
|
||||
}
|
||||
static unsigned
|
||||
sdefl_rev(unsigned c, unsigned char n) {
|
||||
c = ((c & 0x5555) << 1) | ((c & 0xAAAA) >> 1);
|
||||
c = ((c & 0x3333) << 2) | ((c & 0xCCCC) >> 2);
|
||||
c = ((c & 0x0F0F) << 4) | ((c & 0xF0F0) >> 4);
|
||||
c = ((c & 0x00FF) << 8) | ((c & 0xFF00) >> 8);
|
||||
return c >> (16-n);
|
||||
}
|
||||
static void
|
||||
sdefl_huff(unsigned char *lens, unsigned *codes, unsigned *freqs,
|
||||
unsigned num_syms, unsigned max_code_len) {
|
||||
unsigned c, *A = codes;
|
||||
unsigned len_cnt[SDEFL_MAX_CODE_LEN + 1];
|
||||
unsigned used_syms = sdefl_sort_sym(num_syms, freqs, lens, A);
|
||||
if (!used_syms) return;
|
||||
if (used_syms == 1) {
|
||||
unsigned s = A[0] & SDEFL_SYM_MSK;
|
||||
unsigned i = s ? s : 1;
|
||||
codes[0] = 0, lens[0] = 1;
|
||||
codes[i] = 1, lens[i] = 1;
|
||||
return;
|
||||
}
|
||||
sdefl_build_tree(A, used_syms);
|
||||
sdefl_gen_len_cnt(A, used_syms-2, len_cnt, max_code_len);
|
||||
sdefl_gen_codes(A, lens, len_cnt, max_code_len, num_syms);
|
||||
for (c = 0; c < num_syms; c++) {
|
||||
codes[c] = sdefl_rev(codes[c], lens[c]);
|
||||
}
|
||||
}
|
||||
struct sdefl_symcnt {
|
||||
int items;
|
||||
int lit;
|
||||
int off;
|
||||
};
|
||||
static void
|
||||
sdefl_precode(struct sdefl_symcnt *cnt, unsigned *freqs, unsigned *items,
|
||||
const unsigned char *litlen, const unsigned char *offlen) {
|
||||
unsigned *at = items;
|
||||
unsigned run_start = 0;
|
||||
|
||||
unsigned total = 0;
|
||||
unsigned char lens[SDEFL_SYM_MAX + SDEFL_OFF_MAX];
|
||||
for (cnt->lit = SDEFL_SYM_MAX; cnt->lit > 257; cnt->lit--)
|
||||
if (litlen[cnt->lit - 1]) break;
|
||||
for (cnt->off = SDEFL_OFF_MAX; cnt->off > 1; cnt->off--)
|
||||
if (offlen[cnt->off - 1]) break;
|
||||
|
||||
total = (unsigned)(cnt->lit + cnt->off);
|
||||
memcpy(lens, litlen, sizeof(unsigned char) * cnt->lit);
|
||||
memcpy(lens + cnt->lit, offlen, sizeof(unsigned char) * cnt->off);
|
||||
do {
|
||||
unsigned len = lens[run_start];
|
||||
unsigned run_end = run_start;
|
||||
do run_end++; while (run_end != total && len == lens[run_end]);
|
||||
if (!len) {
|
||||
while ((run_end - run_start) >= 11) {
|
||||
unsigned n = (run_end - run_start) - 11;
|
||||
unsigned xbits = n < 0x7f ? n : 0x7f;
|
||||
freqs[18]++;
|
||||
*at++ = 18u | (xbits << 5u);
|
||||
run_start += 11 + xbits;
|
||||
}
|
||||
if ((run_end - run_start) >= 3) {
|
||||
unsigned n = (run_end - run_start) - 3;
|
||||
unsigned xbits = n < 0x7 ? n : 0x7;
|
||||
freqs[17]++;
|
||||
*at++ = 17u | (xbits << 5u);
|
||||
run_start += 3 + xbits;
|
||||
}
|
||||
} else if ((run_end - run_start) >= 4) {
|
||||
freqs[len]++;
|
||||
*at++ = len;
|
||||
run_start++;
|
||||
do {
|
||||
unsigned xbits = (run_end - run_start) - 3;
|
||||
xbits = xbits < 0x03 ? xbits : 0x03;
|
||||
*at++ = 16 | (xbits << 5);
|
||||
run_start += 3 + xbits;
|
||||
freqs[16]++;
|
||||
} while ((run_end - run_start) >= 3);
|
||||
}
|
||||
while (run_start != run_end) {
|
||||
freqs[len]++;
|
||||
*at++ = len;
|
||||
run_start++;
|
||||
}
|
||||
} while (run_start != total);
|
||||
cnt->items = (int)(at - items);
|
||||
}
|
||||
struct sdefl_match_codes {
|
||||
int ls, lc;
|
||||
int dc, dx;
|
||||
};
|
||||
static void
|
||||
sdefl_match_codes(struct sdefl_match_codes *cod, int dist, int len) {
|
||||
static const short dxmax[] = {0,6,12,24,48,96,192,384,768,1536,3072,6144,12288,24576};
|
||||
static const unsigned char lslot[258+1] = {
|
||||
0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12,
|
||||
12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
||||
20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 28
|
||||
};
|
||||
cod->ls = lslot[len];
|
||||
cod->lc = 257 + cod->ls;
|
||||
cod->dx = sdefl_ilog2(sdefl_npow2(dist) >> 2);
|
||||
cod->dc = cod->dx ? ((cod->dx + 1) << 1) + (dist > dxmax[cod->dx]) : dist-1;
|
||||
}
|
||||
static void
|
||||
sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) {
|
||||
static const char lxn[] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
|
||||
static const short lmin[] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,
|
||||
51,59,67,83,99,115,131,163,195,227,258};
|
||||
static const short dmin[] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,
|
||||
385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
|
||||
|
||||
struct sdefl_match_codes cod;
|
||||
sdefl_match_codes(&cod, dist, len);
|
||||
sdefl_put(dst, s, (int)s->cod.word.lit[cod.lc], s->cod.len.lit[cod.lc]);
|
||||
sdefl_put(dst, s, len - lmin[cod.ls], lxn[cod.ls]);
|
||||
sdefl_put(dst, s, (int)s->cod.word.off[cod.dc], s->cod.len.off[cod.dc]);
|
||||
sdefl_put(dst, s, dist - dmin[cod.dc], cod.dx);
|
||||
}
|
||||
static void
|
||||
sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
|
||||
const unsigned char *in) {
|
||||
int j, i = 0, item_cnt = 0;
|
||||
struct sdefl_symcnt symcnt = {0};
|
||||
unsigned codes[SDEFL_PRE_MAX];
|
||||
unsigned char lens[SDEFL_PRE_MAX];
|
||||
unsigned freqs[SDEFL_PRE_MAX] = {0};
|
||||
unsigned items[SDEFL_SYM_MAX + SDEFL_OFF_MAX];
|
||||
static const unsigned char perm[SDEFL_PRE_MAX] = {16,17,18,0,8,7,9,6,10,5,11,
|
||||
4,12,3,13,2,14,1,15};
|
||||
|
||||
/* huffman codes */
|
||||
s->freq.lit[SDEFL_EOB]++;
|
||||
sdefl_huff(s->cod.len.lit, s->cod.word.lit, s->freq.lit, SDEFL_SYM_MAX, SDEFL_LIT_LEN_CODES);
|
||||
sdefl_huff(s->cod.len.off, s->cod.word.off, s->freq.off, SDEFL_OFF_MAX, SDEFL_OFF_CODES);
|
||||
sdefl_precode(&symcnt, freqs, items, s->cod.len.lit, s->cod.len.off);
|
||||
sdefl_huff(lens, codes, freqs, SDEFL_PRE_MAX, SDEFL_PRE_CODES);
|
||||
for (item_cnt = SDEFL_PRE_MAX; item_cnt > 4; item_cnt--) {
|
||||
if (lens[perm[item_cnt - 1]]) break;
|
||||
}
|
||||
/* block header */
|
||||
sdefl_put(dst, s, is_last ? 0x01 : 0x00, 1); /* block */
|
||||
sdefl_put(dst, s, 0x02, 2); /* dynamic huffman */
|
||||
sdefl_put(dst, s, symcnt.lit - 257, 5);
|
||||
sdefl_put(dst, s, symcnt.off - 1, 5);
|
||||
sdefl_put(dst, s, item_cnt - 4, 4);
|
||||
for (i = 0; i < item_cnt; ++i)
|
||||
sdefl_put(dst, s, lens[perm[i]], 3);
|
||||
for (i = 0; i < symcnt.items; ++i) {
|
||||
unsigned sym = items[i] & 0x1F;
|
||||
sdefl_put(dst, s, (int)codes[sym], lens[sym]);
|
||||
if (sym < 16) continue;
|
||||
if (sym == 16) sdefl_put(dst, s, items[i] >> 5, 2);
|
||||
else if(sym == 17) sdefl_put(dst, s, items[i] >> 5, 3);
|
||||
else sdefl_put(dst, s, items[i] >> 5, 7);
|
||||
}
|
||||
/* block sequences */
|
||||
for (i = 0; i < s->seq_cnt; ++i) {
|
||||
if (s->seq[i].off >= 0)
|
||||
for (j = 0; j < s->seq[i].len; ++j) {
|
||||
int c = in[s->seq[i].off + j];
|
||||
sdefl_put(dst, s, (int)s->cod.word.lit[c], s->cod.len.lit[c]);
|
||||
}
|
||||
else sdefl_match(dst, s, -s->seq[i].off, s->seq[i].len);
|
||||
}
|
||||
sdefl_put(dst, s, (int)(s)->cod.word.lit[SDEFL_EOB], (s)->cod.len.lit[SDEFL_EOB]);
|
||||
memset(&s->freq, 0, sizeof(s->freq));
|
||||
s->seq_cnt = 0;
|
||||
}
|
||||
static void
|
||||
sdefl_seq(struct sdefl *s, int off, int len) {
|
||||
assert(s->seq_cnt + 2 < SDEFL_SEQ_SIZ);
|
||||
s->seq[s->seq_cnt].off = off;
|
||||
s->seq[s->seq_cnt].len = len;
|
||||
s->seq_cnt++;
|
||||
}
|
||||
static void
|
||||
sdefl_reg_match(struct sdefl *s, int off, int len) {
|
||||
struct sdefl_match_codes cod;
|
||||
sdefl_match_codes(&cod, off, len);
|
||||
s->freq.lit[cod.lc]++;
|
||||
s->freq.off[cod.dc]++;
|
||||
}
|
||||
struct sdefl_match {
|
||||
int off;
|
||||
int len;
|
||||
};
|
||||
static void
|
||||
sdefl_fnd(struct sdefl_match *m, const struct sdefl *s,
|
||||
int chain_len, int max_match, const unsigned char *in, int p) {
|
||||
int i = s->tbl[sdefl_hash32(&in[p])];
|
||||
int limit = ((p-SDEFL_WIN_SIZ)<SDEFL_NIL)?SDEFL_NIL:(p-SDEFL_WIN_SIZ);
|
||||
while (i > limit) {
|
||||
if (in[i+m->len] == in[p+m->len] &&
|
||||
(sdefl_uload32(&in[i]) == sdefl_uload32(&in[p]))){
|
||||
int n = SDEFL_MIN_MATCH;
|
||||
while (n < max_match && in[i+n] == in[p+n]) n++;
|
||||
if (n > m->len) {
|
||||
m->len = n, m->off = p - i;
|
||||
if (n == max_match) break;
|
||||
}
|
||||
}
|
||||
if (!(--chain_len)) break;
|
||||
i = s->prv[i&SDEFL_WIN_MSK];
|
||||
}
|
||||
}
|
||||
static int
|
||||
sdefl_compr(struct sdefl *s, unsigned char *out, const unsigned char *in,
|
||||
int in_len, int lvl) {
|
||||
unsigned char *q = out;
|
||||
static const unsigned char pref[] = {8,10,14,24,30,48,65,96,130};
|
||||
int max_chain = (lvl < 8) ? (1 << (lvl + 1)): (1 << 13);
|
||||
int n, i = 0, litlen = 0;
|
||||
for (n = 0; n < SDEFL_HASH_SIZ; ++n) {
|
||||
s->tbl[n] = SDEFL_NIL;
|
||||
}
|
||||
do {int blk_end = i + SDEFL_BLK_MAX < in_len ? i + SDEFL_BLK_MAX : in_len;
|
||||
while (i < blk_end) {
|
||||
struct sdefl_match m = {0};
|
||||
int max_match = ((in_len-i)>SDEFL_MAX_MATCH) ? SDEFL_MAX_MATCH:(in_len-i);
|
||||
int nice_match = pref[lvl] < max_match ? pref[lvl] : max_match;
|
||||
int run = 1, inc = 1, run_inc;
|
||||
if (max_match > SDEFL_MIN_MATCH) {
|
||||
sdefl_fnd(&m, s, max_chain, max_match, in, i);
|
||||
}
|
||||
if (lvl >= 5 && m.len >= SDEFL_MIN_MATCH && m.len < nice_match){
|
||||
struct sdefl_match m2 = {0};
|
||||
sdefl_fnd(&m2, s, max_chain, m.len+1, in, i+1);
|
||||
m.len = (m2.len > m.len) ? 0 : m.len;
|
||||
}
|
||||
if (m.len >= SDEFL_MIN_MATCH) {
|
||||
if (litlen) {
|
||||
sdefl_seq(s, i - litlen, litlen);
|
||||
litlen = 0;
|
||||
}
|
||||
sdefl_seq(s, -m.off, m.len);
|
||||
sdefl_reg_match(s, m.off, m.len);
|
||||
if (lvl < 2 && m.len >= nice_match) {
|
||||
inc = m.len;
|
||||
} else {
|
||||
run = m.len;
|
||||
}
|
||||
} else {
|
||||
s->freq.lit[in[i]]++;
|
||||
litlen++;
|
||||
}
|
||||
run_inc = run * inc;
|
||||
if (in_len - (i + run_inc) > SDEFL_MIN_MATCH) {
|
||||
while (run-- > 0) {
|
||||
unsigned h = sdefl_hash32(&in[i]);
|
||||
s->prv[i&SDEFL_WIN_MSK] = s->tbl[h];
|
||||
s->tbl[h] = i, i += inc;
|
||||
}
|
||||
} else {
|
||||
i += run_inc;
|
||||
}
|
||||
}
|
||||
if (litlen) {
|
||||
sdefl_seq(s, i - litlen, litlen);
|
||||
litlen = 0;
|
||||
}
|
||||
sdefl_flush(&q, s, blk_end == in_len, in);
|
||||
} while (i < in_len);
|
||||
|
||||
if (s->bitcnt)
|
||||
sdefl_put(&q, s, 0x00, 8 - s->bitcnt);
|
||||
return (int)(q - out);
|
||||
}
|
||||
extern int
|
||||
sdeflate(struct sdefl *s, void *out, const void *in, int n, int lvl) {
|
||||
s->bits = s->bitcnt = 0;
|
||||
return sdefl_compr(s, (unsigned char*)out, (const unsigned char*)in, n, lvl);
|
||||
}
|
||||
static unsigned
|
||||
sdefl_adler32(unsigned adler32, const unsigned char *in, int in_len) {
|
||||
#define SDEFL_ADLER_INIT (1)
|
||||
const unsigned ADLER_MOD = 65521;
|
||||
unsigned s1 = adler32 & 0xffff;
|
||||
unsigned s2 = adler32 >> 16;
|
||||
unsigned blk_len, i;
|
||||
|
||||
blk_len = in_len % 5552;
|
||||
while (in_len) {
|
||||
for (i = 0; i + 7 < blk_len; i += 8) {
|
||||
s1 += in[0]; s2 += s1;
|
||||
s1 += in[1]; s2 += s1;
|
||||
s1 += in[2]; s2 += s1;
|
||||
s1 += in[3]; s2 += s1;
|
||||
s1 += in[4]; s2 += s1;
|
||||
s1 += in[5]; s2 += s1;
|
||||
s1 += in[6]; s2 += s1;
|
||||
s1 += in[7]; s2 += s1;
|
||||
in += 8;
|
||||
}
|
||||
for (; i < blk_len; ++i) {
|
||||
s1 += *in++, s2 += s1;
|
||||
}
|
||||
s1 %= ADLER_MOD;
|
||||
s2 %= ADLER_MOD;
|
||||
in_len -= blk_len;
|
||||
blk_len = 5552;
|
||||
}
|
||||
return (unsigned)(s2 << 16) + (unsigned)s1;
|
||||
}
|
||||
extern int
|
||||
zsdeflate(struct sdefl *s, void *out, const void *in, int n, int lvl) {
|
||||
int p = 0;
|
||||
unsigned a = 0;
|
||||
unsigned char *q = (unsigned char*)out;
|
||||
|
||||
s->bits = s->bitcnt = 0;
|
||||
sdefl_put(&q, s, 0x78, 8); /* deflate, 32k window */
|
||||
sdefl_put(&q, s, 0x01, 8); /* fast compression */
|
||||
q += sdefl_compr(s, q, (const unsigned char*)in, n, lvl);
|
||||
|
||||
/* append adler checksum */
|
||||
a = sdefl_adler32(SDEFL_ADLER_INIT, (const unsigned char*)in, n);
|
||||
for (p = 0; p < 4; ++p) {
|
||||
sdefl_put(&q, s, (a >> 24) & 0xFF, 8);
|
||||
a <<= 8;
|
||||
}
|
||||
return (int)(q - (unsigned char*)out);
|
||||
}
|
||||
extern int
|
||||
sdefl_bound(int len) {
|
||||
int a = 128 + (len * 110) / 100;
|
||||
int b = 128 + len + ((len / (31 * 1024)) + 1) * 5;
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
#endif /* SDEFL_IMPLEMENTATION */
|
||||
|
464
raylib/external/sinfl.h
vendored
Normal file
464
raylib/external/sinfl.h
vendored
Normal file
|
@ -0,0 +1,464 @@
|
|||
/*
|
||||
# Small Deflate
|
||||
`sdefl` is a small bare bone lossless compression library in ANSI C (ISO C90)
|
||||
which implements the Deflate (RFC 1951) compressed data format specification standard.
|
||||
It is mainly tuned to get as much speed and compression ratio from as little code
|
||||
as needed to keep the implementation as concise as possible.
|
||||
|
||||
## Features
|
||||
- Portable single header and source file duo written in ANSI C (ISO C90)
|
||||
- Dual license with either MIT or public domain
|
||||
- Small implementation
|
||||
- Deflate: 525 LoC
|
||||
- Inflate: 320 LoC
|
||||
- Webassembly:
|
||||
- Deflate ~3.7 KB (~2.2KB compressed)
|
||||
- Inflate ~3.6 KB (~2.2KB compressed)
|
||||
|
||||
## Usage:
|
||||
This file behaves differently depending on what symbols you define
|
||||
before including it.
|
||||
|
||||
Header-File mode:
|
||||
If you do not define `SINFL_IMPLEMENTATION` before including this file, it
|
||||
will operate in header only mode. In this mode it declares all used structs
|
||||
and the API of the library without including the implementation of the library.
|
||||
|
||||
Implementation mode:
|
||||
If you define `SINFL_IMPLEMENTATION` before including this file, it will
|
||||
compile the implementation. Make sure that you only include
|
||||
this file implementation in *one* C or C++ file to prevent collisions.
|
||||
|
||||
### Benchmark
|
||||
|
||||
| Compressor name | Compression| Decompress.| Compr. size | Ratio |
|
||||
| ------------------------| -----------| -----------| ----------- | ----- |
|
||||
| sdefl 1.0 -0 | 127 MB/s | 233 MB/s | 40004116 | 39.88 |
|
||||
| sdefl 1.0 -1 | 111 MB/s | 259 MB/s | 38940674 | 38.82 |
|
||||
| sdefl 1.0 -5 | 45 MB/s | 275 MB/s | 36577183 | 36.46 |
|
||||
| sdefl 1.0 -7 | 38 MB/s | 276 MB/s | 36523781 | 36.41 |
|
||||
| zlib 1.2.11 -1 | 72 MB/s | 307 MB/s | 42298774 | 42.30 |
|
||||
| zlib 1.2.11 -6 | 24 MB/s | 313 MB/s | 36548921 | 36.55 |
|
||||
| zlib 1.2.11 -9 | 20 MB/s | 314 MB/s | 36475792 | 36.48 |
|
||||
| miniz 1.0 -1 | 122 MB/s | 208 MB/s | 48510028 | 48.51 |
|
||||
| miniz 1.0 -6 | 27 MB/s | 260 MB/s | 36513697 | 36.51 |
|
||||
| miniz 1.0 -9 | 23 MB/s | 261 MB/s | 36460101 | 36.46 |
|
||||
| libdeflate 1.3 -1 | 147 MB/s | 667 MB/s | 39597378 | 39.60 |
|
||||
| libdeflate 1.3 -6 | 69 MB/s | 689 MB/s | 36648318 | 36.65 |
|
||||
| libdeflate 1.3 -9 | 13 MB/s | 672 MB/s | 35197141 | 35.20 |
|
||||
| libdeflate 1.3 -12 | 8.13 MB/s | 670 MB/s | 35100568 | 35.10 |
|
||||
|
||||
### Compression
|
||||
Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia):
|
||||
|
||||
| File | Original | `sdefl 0` | `sdefl 5` | `sdefl 7` |
|
||||
| :------ | ---------: | -----------------: | ---------: | ----------: |
|
||||
| dickens | 10.192.446 | 4,260,187| 3,845,261| 3,833,657 |
|
||||
| mozilla | 51.220.480 | 20,774,706 | 19,607,009 | 19,565,867 |
|
||||
| mr | 9.970.564 | 3,860,531 | 3,673,460 | 3,665,627 |
|
||||
| nci | 33.553.445 | 4,030,283 | 3,094,526 | 3,006,075 |
|
||||
| ooffice | 6.152.192 | 3,320,063 | 3,186,373 | 3,183,815 |
|
||||
| osdb | 10.085.684 | 3,919,646 | 3,649,510 | 3,649,477 |
|
||||
| reymont | 6.627.202 | 2,263,378 | 1,857,588 | 1,827,237 |
|
||||
| samba | 21.606.400 | 6,121,797 | 5,462,670 | 5,450,762 |
|
||||
| sao | 7.251.944 | 5,612,421 | 5,485,380 | 5,481,765 |
|
||||
| webster | 41.458.703 | 13,972,648 | 12,059,432 | 11,991,421 |
|
||||
| xml | 5.345.280 | 886,620| 674,009 | 662,141 |
|
||||
| x-ray | 8.474.240 | 6,304,655 | 6,244,779 | 6,244,779 |
|
||||
|
||||
## License
|
||||
```
|
||||
------------------------------------------------------------------------------
|
||||
This software is available under 2 licenses -- choose whichever you prefer.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2020 Micha Mettke
|
||||
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.
|
||||
------------------------------------------------------------------------------
|
||||
```
|
||||
*/
|
||||
#ifndef SINFL_H_INCLUDED
|
||||
#define SINFL_H_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SINFL_PRE_TBL_SIZE 128
|
||||
#define SINFL_LIT_TBL_SIZE 1334
|
||||
#define SINFL_OFF_TBL_SIZE 402
|
||||
|
||||
struct sinfl {
|
||||
int bits, bitcnt;
|
||||
unsigned lits[SINFL_LIT_TBL_SIZE];
|
||||
unsigned dsts[SINFL_OFF_TBL_SIZE];
|
||||
};
|
||||
extern int sinflate(void *out, const void *in, int size);
|
||||
extern int zsinflate(void *out, const void *in, int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SINFL_H_INCLUDED */
|
||||
|
||||
#ifdef SINFL_IMPLEMENTATION
|
||||
|
||||
#include <string.h> /* memcpy, memset */
|
||||
|
||||
static int
|
||||
sinfl_bsr(unsigned n) {
|
||||
#ifdef _MSC_VER
|
||||
_BitScanReverse(&n, n);
|
||||
return n;
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
return 31 - __builtin_clz(n);
|
||||
#endif
|
||||
}
|
||||
static int
|
||||
sinfl_get(const unsigned char **src, const unsigned char *end, struct sinfl *s,
|
||||
int n) {
|
||||
const unsigned char *in = *src;
|
||||
int v = s->bits & ((1 << n)-1);
|
||||
s->bits >>= n;
|
||||
s->bitcnt = s->bitcnt - n;
|
||||
s->bitcnt = s->bitcnt < 0 ? 0 : s->bitcnt;
|
||||
while (s->bitcnt < 16 && in < end) {
|
||||
s->bits |= (*in++) << s->bitcnt;
|
||||
s->bitcnt += 8;
|
||||
}
|
||||
*src = in;
|
||||
return v;
|
||||
}
|
||||
struct sinfl_gen {
|
||||
int len;
|
||||
int cnt;
|
||||
int word;
|
||||
short* sorted;
|
||||
};
|
||||
static int
|
||||
sinfl_build_tbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits,
|
||||
const int *cnt) {
|
||||
int tbl_end = 0;
|
||||
while (!(gen->cnt = cnt[gen->len])) {
|
||||
++gen->len;
|
||||
}
|
||||
tbl_end = 1 << gen->len;
|
||||
while (gen->len <= tbl_bits) {
|
||||
do {unsigned bit = 0;
|
||||
tbl[gen->word] = (*gen->sorted++ << 16) | gen->len;
|
||||
if (gen->word == tbl_end - 1) {
|
||||
for (; gen->len < tbl_bits; gen->len++) {
|
||||
memcpy(&tbl[tbl_end], tbl, (size_t)tbl_end * sizeof(tbl[0]));
|
||||
tbl_end <<= 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
bit = 1 << sinfl_bsr((unsigned)(gen->word ^ (tbl_end - 1)));
|
||||
gen->word &= bit - 1;
|
||||
gen->word |= bit;
|
||||
} while (--gen->cnt);
|
||||
do {
|
||||
if (++gen->len <= tbl_bits) {
|
||||
memcpy(&tbl[tbl_end], tbl, (size_t)tbl_end * sizeof(tbl[0]));
|
||||
tbl_end <<= 1;
|
||||
}
|
||||
} while (!(gen->cnt = cnt[gen->len]));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static void
|
||||
sinfl_build_subtbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits,
|
||||
const int *cnt) {
|
||||
int sub_bits = 0;
|
||||
int sub_start = 0;
|
||||
int sub_prefix = -1;
|
||||
int tbl_end = 1 << tbl_bits;
|
||||
while (1) {
|
||||
unsigned entry;
|
||||
int bit, stride, i;
|
||||
/* start new subtable */
|
||||
if ((gen->word & ((1 << tbl_bits)-1)) != sub_prefix) {
|
||||
int used = 0;
|
||||
sub_prefix = gen->word & ((1 << tbl_bits)-1);
|
||||
sub_start = tbl_end;
|
||||
sub_bits = gen->len - tbl_bits;
|
||||
used = gen->cnt;
|
||||
while (used < (1 << sub_bits)) {
|
||||
sub_bits++;
|
||||
used = (used << 1) + cnt[tbl_bits + sub_bits];
|
||||
}
|
||||
tbl_end = sub_start + (1 << sub_bits);
|
||||
tbl[sub_prefix] = (sub_start << 16) | 0x10 | (sub_bits & 0xf);
|
||||
}
|
||||
/* fill subtable */
|
||||
entry = (*gen->sorted << 16) | ((gen->len - tbl_bits) & 0xf);
|
||||
gen->sorted++;
|
||||
i = sub_start + (gen->word >> tbl_bits);
|
||||
stride = 1 << (gen->len - tbl_bits);
|
||||
do {
|
||||
tbl[i] = entry;
|
||||
i += stride;
|
||||
} while (i < tbl_end);
|
||||
if (gen->word == (1 << gen->len)-1) {
|
||||
return;
|
||||
}
|
||||
bit = 1 << sinfl_bsr(gen->word ^ ((1 << gen->len) - 1));
|
||||
gen->word &= bit - 1;
|
||||
gen->word |= bit;
|
||||
gen->cnt--;
|
||||
while (!gen->cnt) {
|
||||
gen->cnt = cnt[++gen->len];
|
||||
}
|
||||
}
|
||||
}
|
||||
static void
|
||||
sinfl_build(unsigned *tbl, unsigned char *lens, int tbl_bits, int maxlen,
|
||||
int symcnt) {
|
||||
int i, used = 0;
|
||||
short sort[288];
|
||||
int cnt[16] = {0}, off[16]= {0};
|
||||
struct sinfl_gen gen = {0};
|
||||
gen.sorted = sort;
|
||||
gen.len = 1;
|
||||
|
||||
for (i = 0; i < symcnt; ++i)
|
||||
cnt[lens[i]]++;
|
||||
off[1] = cnt[0];
|
||||
for (i = 1; i < maxlen; ++i) {
|
||||
off[i + 1] = off[i] + cnt[i];
|
||||
used = (used << 1) + cnt[i];
|
||||
}
|
||||
used = (used << 1) + cnt[i];
|
||||
for (i = 0; i < symcnt; ++i)
|
||||
gen.sorted[off[lens[i]]++] = (short)i;
|
||||
gen.sorted += off[0];
|
||||
|
||||
if (used < (1 << maxlen)){
|
||||
for (i = 0; i < 1 << tbl_bits; ++i)
|
||||
tbl[i] = (0 << 16u) | 1;
|
||||
return;
|
||||
}
|
||||
if (!sinfl_build_tbl(&gen, tbl, tbl_bits, cnt)){
|
||||
sinfl_build_subtbl(&gen, tbl, tbl_bits, cnt);
|
||||
}
|
||||
}
|
||||
static int
|
||||
sinfl_decode(const unsigned char **in, const unsigned char *end,
|
||||
struct sinfl *s, const unsigned *tbl, int bit_len) {
|
||||
int idx = s->bits & ((1 << bit_len) - 1);
|
||||
unsigned key = tbl[idx];
|
||||
if (key & 0x10) {
|
||||
/* sub-table lookup */
|
||||
int len = key & 0x0f;
|
||||
sinfl_get(in, end, s, bit_len);
|
||||
idx = s->bits & ((1 << len)-1);
|
||||
key = tbl[((key >> 16) & 0xffff) + (unsigned)idx];
|
||||
}
|
||||
sinfl_get(in, end, s, key & 0x0f);
|
||||
return (key >> 16) & 0x0fff;
|
||||
}
|
||||
static int
|
||||
sinfl_decompress(unsigned char *out, const unsigned char *in, int size) {
|
||||
static const unsigned char order[] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
|
||||
static const short dbase[30+2] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,
|
||||
257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
|
||||
static const unsigned char dbits[30+2] = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,
|
||||
10,10,11,11,12,12,13,13,0,0};
|
||||
static const short lbase[29+2] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,
|
||||
43,51,59,67,83,99,115,131,163,195,227,258,0,0};
|
||||
static const unsigned char lbits[29+2] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,
|
||||
4,4,4,5,5,5,5,0,0,0};
|
||||
|
||||
const unsigned char *e = in + size, *o = out;
|
||||
enum sinfl_states {hdr,stored,fixed,dyn,blk};
|
||||
enum sinfl_states state = hdr;
|
||||
struct sinfl s = {0};
|
||||
int last = 0;
|
||||
|
||||
sinfl_get(&in,e,&s,0); /* buffer input */
|
||||
while (in < e || s.bitcnt) {
|
||||
switch (state) {
|
||||
case hdr: {
|
||||
int type = 0; /* block header */
|
||||
last = sinfl_get(&in,e,&s,1);
|
||||
type = sinfl_get(&in,e,&s,2);
|
||||
|
||||
switch (type) {default: return (int)(out-o);
|
||||
case 0x00: state = stored; break;
|
||||
case 0x01: state = fixed; break;
|
||||
case 0x02: state = dyn; break;}
|
||||
} break;
|
||||
case stored: {
|
||||
int len; /* uncompressed block */
|
||||
sinfl_get(&in,e,&s,s.bitcnt & 7);
|
||||
len = sinfl_get(&in,e,&s,16);
|
||||
//int nlen = sinfl_get(&in,e,&s,16);
|
||||
in -= 2; s.bitcnt = 0;
|
||||
|
||||
if (len > (e-in) || !len)
|
||||
return (int)(out-o);
|
||||
memcpy(out, in, (size_t)len);
|
||||
in += len, out += len;
|
||||
state = hdr;
|
||||
} break;
|
||||
case fixed: {
|
||||
/* fixed huffman codes */
|
||||
int n; unsigned char lens[288+32];
|
||||
for (n = 0; n <= 143; n++) lens[n] = 8;
|
||||
for (n = 144; n <= 255; n++) lens[n] = 9;
|
||||
for (n = 256; n <= 279; n++) lens[n] = 7;
|
||||
for (n = 280; n <= 287; n++) lens[n] = 8;
|
||||
for (n = 0; n < 32; n++) lens[288+n] = 5;
|
||||
|
||||
/* build lit/dist tables */
|
||||
sinfl_build(s.lits, lens, 10, 15, 288);
|
||||
sinfl_build(s.dsts, lens + 288, 8, 15, 32);
|
||||
state = blk;
|
||||
} break;
|
||||
case dyn: {
|
||||
/* dynamic huffman codes */
|
||||
int n, i;
|
||||
unsigned hlens[SINFL_PRE_TBL_SIZE];
|
||||
unsigned char nlens[19] = {0}, lens[288+32];
|
||||
int nlit = 257 + sinfl_get(&in,e,&s,5);
|
||||
int ndist = 1 + sinfl_get(&in,e,&s,5);
|
||||
int nlen = 4 + sinfl_get(&in,e,&s,4);
|
||||
for (n = 0; n < nlen; n++)
|
||||
nlens[order[n]] = (unsigned char)sinfl_get(&in,e,&s,3);
|
||||
sinfl_build(hlens, nlens, 7, 7, 19);
|
||||
|
||||
/* decode code lengths */
|
||||
for (n = 0; n < nlit + ndist;) {
|
||||
int sym = sinfl_decode(&in, e, &s, hlens, 7);
|
||||
switch (sym) {default: lens[n++] = (unsigned char)sym; break;
|
||||
case 16: for (i=3+sinfl_get(&in,e,&s,2);i;i--,n++) lens[n]=lens[n-1]; break;
|
||||
case 17: for (i=3+sinfl_get(&in,e,&s,3);i;i--,n++) lens[n]=0; break;
|
||||
case 18: for (i=11+sinfl_get(&in,e,&s,7);i;i--,n++) lens[n]=0; break;}
|
||||
}
|
||||
/* build lit/dist tables */
|
||||
sinfl_build(s.lits, lens, 10, 15, nlit);
|
||||
sinfl_build(s.dsts, lens + nlit, 8, 15, ndist);
|
||||
state = blk;
|
||||
} break;
|
||||
case blk: {
|
||||
/* decompress block */
|
||||
int i, sym = sinfl_decode(&in, e, &s, s.lits, 10);
|
||||
if (sym > 256) {sym -= 257; /* match symbol */
|
||||
{int len = sinfl_get(&in, e, &s, lbits[sym]) + lbase[sym];
|
||||
int dsym = sinfl_decode(&in, e, &s, s.dsts, 8);
|
||||
int offs = sinfl_get(&in, e, &s, dbits[dsym]) + dbase[dsym];
|
||||
if (offs > (int)(out-o)) {
|
||||
return (int)(out-o);
|
||||
} else if (offs == 1) {
|
||||
/* rle match copying */
|
||||
unsigned char c = *(out - offs);
|
||||
unsigned long w = (c << 24) | (c << 16) | (c << 8) | c;
|
||||
for (i = 0; i < len >> 2; ++i) {
|
||||
memcpy(out, &w, 4);
|
||||
out += 4;
|
||||
}
|
||||
len = len & 3;
|
||||
} else if (offs >= 4) {
|
||||
/* copy match */
|
||||
int wcnt = len >> 2;
|
||||
for (i = 0; i < wcnt; ++i) {
|
||||
unsigned long w = 0;
|
||||
memcpy(&w, out - offs, 4);
|
||||
memcpy(out, &w, 4);
|
||||
out += 4;
|
||||
}
|
||||
len = len & 3;
|
||||
}
|
||||
for (i = 0; i < len; ++i)
|
||||
{*out = *(out-offs), out++;}
|
||||
}
|
||||
} else if (sym == 256) {
|
||||
/* end of block */
|
||||
if (last) return (int)(out-o);
|
||||
state = hdr;
|
||||
break;
|
||||
/* literal */
|
||||
} else *out++ = (unsigned char)sym;
|
||||
} break;}
|
||||
}
|
||||
return (int)(out-o);
|
||||
}
|
||||
extern int
|
||||
sinflate(void *out, const void *in, int size) {
|
||||
return sinfl_decompress((unsigned char*)out, (const unsigned char*)in, size);
|
||||
}
|
||||
static unsigned
|
||||
sinfl_adler32(unsigned adler32, const unsigned char *in, int in_len) {
|
||||
const unsigned ADLER_MOD = 65521;
|
||||
unsigned s1 = adler32 & 0xffff;
|
||||
unsigned s2 = adler32 >> 16;
|
||||
unsigned blk_len, i;
|
||||
|
||||
blk_len = in_len % 5552;
|
||||
while (in_len) {
|
||||
for (i=0; i + 7 < blk_len; i += 8) {
|
||||
s1 += in[0]; s2 += s1;
|
||||
s1 += in[1]; s2 += s1;
|
||||
s1 += in[2]; s2 += s1;
|
||||
s1 += in[3]; s2 += s1;
|
||||
s1 += in[4]; s2 += s1;
|
||||
s1 += in[5]; s2 += s1;
|
||||
s1 += in[6]; s2 += s1;
|
||||
s1 += in[7]; s2 += s1;
|
||||
in += 8;
|
||||
}
|
||||
for (; i < blk_len; ++i)
|
||||
s1 += *in++, s2 += s1;
|
||||
s1 %= ADLER_MOD; s2 %= ADLER_MOD;
|
||||
in_len -= blk_len;
|
||||
blk_len = 5552;
|
||||
} return (unsigned)(s2 << 16) + (unsigned)s1;
|
||||
}
|
||||
extern int
|
||||
zsinflate(void *out, const void *mem, int size) {
|
||||
const unsigned char *in = (const unsigned char*)mem;
|
||||
if (size >= 6) {
|
||||
const unsigned char *eob = in + size - 4;
|
||||
int n = sinfl_decompress((unsigned char*)out, in + 2u, size);
|
||||
unsigned a = sinfl_adler32(1u, (unsigned char*)out, n);
|
||||
unsigned h = eob[0] << 24 | eob[1] << 16 | eob[2] << 8 | eob[3] << 0;
|
||||
return a == h ? n : -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
214
raylib/external/stb_image.h
vendored
214
raylib/external/stb_image.h
vendored
|
@ -1,4 +1,4 @@
|
|||
/* stb_image - v2.25 - public domain image loader - http://nothings.org/stb
|
||||
/* stb_image - v2.26 - public domain image loader - http://nothings.org/stb
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
Do this:
|
||||
|
@ -48,6 +48,7 @@ LICENSE
|
|||
|
||||
RECENT REVISION HISTORY:
|
||||
|
||||
2.26 (2020-07-13) many minor fixes
|
||||
2.25 (2020-02-02) fix warnings
|
||||
2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically
|
||||
2.23 (2019-08-11) fix clang static analysis warning
|
||||
|
@ -93,22 +94,30 @@ RECENT REVISION HISTORY:
|
|||
Carmelo J Fdez-Aguera
|
||||
|
||||
Bug & warning fixes
|
||||
Marc LeBlanc David Woo Guillaume George Martins Mozeiko
|
||||
Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan
|
||||
Dave Moore Roy Eltham Hayaki Saito Nathan Reed
|
||||
Won Chun Luke Graham Johan Duparc Nick Verigakis
|
||||
the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh
|
||||
Janez Zemva John Bartholomew Michal Cichon github:romigrou
|
||||
Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
|
||||
Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar
|
||||
Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex
|
||||
Ryamond Barbiero Paul Du Bois Engin Manap github:grim210
|
||||
Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw
|
||||
Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus
|
||||
Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo
|
||||
Christian Floisand Kevin Schmidt JR Smith github:darealshinji
|
||||
Brad Weinberger Matvey Cherevko github:Michaelangel007
|
||||
Blazej Dariusz Roszkowski Alexander Veselov
|
||||
Marc LeBlanc David Woo Guillaume George Martins Mozeiko
|
||||
Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski
|
||||
Phil Jordan Dave Moore Roy Eltham
|
||||
Hayaki Saito Nathan Reed Won Chun
|
||||
Luke Graham Johan Duparc Nick Verigakis the Horde3D community
|
||||
Thomas Ruf Ronny Chevalier github:rlyeh
|
||||
Janez Zemva John Bartholomew Michal Cichon github:romigrou
|
||||
Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
|
||||
Laurent Gomila Cort Stratton github:snagar
|
||||
Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex
|
||||
Cass Everitt Ryamond Barbiero github:grim210
|
||||
Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw
|
||||
Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus
|
||||
Josh Tobin Matthew Gregan github:poppolopoppo
|
||||
Julian Raschke Gregory Mullen Christian Floisand github:darealshinji
|
||||
Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007
|
||||
Brad Weinberger Matvey Cherevko [reserved]
|
||||
Luca Sas Alexander Veselov Zack Middleton [reserved]
|
||||
Ryan C. Gordon [reserved] [reserved]
|
||||
DO NOT ADD YOUR NAME HERE
|
||||
|
||||
To add your name to the credits, pick a random blank space in the middle and fill it.
|
||||
80% of merge conflicts on stb PRs are due to people adding their name at the end
|
||||
of the credits.
|
||||
*/
|
||||
|
||||
#ifndef STBI_INCLUDE_STB_IMAGE_H
|
||||
|
@ -318,7 +327,14 @@ RECENT REVISION HISTORY:
|
|||
// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
|
||||
// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
|
||||
//
|
||||
|
||||
// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater
|
||||
// than that size (in either width or height) without further processing.
|
||||
// This is to let programs in the wild set an upper bound to prevent
|
||||
// denial-of-service attacks on untrusted data, as one could generate a
|
||||
// valid image of gigantic dimensions and force stb_image to allocate a
|
||||
// huge block of memory and spend disproportionate time decoding it. By
|
||||
// default this is set to (1 << 24), which is 16777216, but that's still
|
||||
// very big.
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
#include <stdio.h>
|
||||
|
@ -574,13 +590,19 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
|
|||
#ifndef STBI_NO_THREAD_LOCALS
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#define STBI_THREAD_LOCAL thread_local
|
||||
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||
#define STBI_THREAD_LOCAL _Thread_local
|
||||
#elif defined(__GNUC__)
|
||||
#elif defined(__GNUC__) && __GNUC__ < 5
|
||||
#define STBI_THREAD_LOCAL __thread
|
||||
#elif defined(_MSC_VER)
|
||||
#define STBI_THREAD_LOCAL __declspec(thread)
|
||||
#endif
|
||||
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
|
||||
#define STBI_THREAD_LOCAL _Thread_local
|
||||
#endif
|
||||
|
||||
#ifndef STBI_THREAD_LOCAL
|
||||
#if defined(__GNUC__)
|
||||
#define STBI_THREAD_LOCAL __thread
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -734,6 +756,10 @@ static int stbi__sse2_available(void)
|
|||
#define STBI_SIMD_ALIGN(type, name) type name
|
||||
#endif
|
||||
|
||||
#ifndef STBI_MAX_DIMENSIONS
|
||||
#define STBI_MAX_DIMENSIONS (1 << 24)
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////
|
||||
//
|
||||
// stbi__context struct and start_xxx functions
|
||||
|
@ -751,6 +777,7 @@ typedef struct
|
|||
int read_from_callbacks;
|
||||
int buflen;
|
||||
stbi_uc buffer_start[128];
|
||||
int callback_already_read;
|
||||
|
||||
stbi_uc *img_buffer, *img_buffer_end;
|
||||
stbi_uc *img_buffer_original, *img_buffer_original_end;
|
||||
|
@ -764,6 +791,7 @@ static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
|
|||
{
|
||||
s->io.read = NULL;
|
||||
s->read_from_callbacks = 0;
|
||||
s->callback_already_read = 0;
|
||||
s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
|
||||
s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
|
||||
}
|
||||
|
@ -775,7 +803,8 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *
|
|||
s->io_user_data = user;
|
||||
s->buflen = sizeof(s->buffer_start);
|
||||
s->read_from_callbacks = 1;
|
||||
s->img_buffer_original = s->buffer_start;
|
||||
s->callback_already_read = 0;
|
||||
s->img_buffer = s->img_buffer_original = s->buffer_start;
|
||||
stbi__refill_buffer(s);
|
||||
s->img_buffer_original_end = s->img_buffer_end;
|
||||
}
|
||||
|
@ -789,12 +818,17 @@ static int stbi__stdio_read(void *user, char *data, int size)
|
|||
|
||||
static void stbi__stdio_skip(void *user, int n)
|
||||
{
|
||||
int ch;
|
||||
fseek((FILE*) user, n, SEEK_CUR);
|
||||
ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */
|
||||
if (ch != EOF) {
|
||||
ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */
|
||||
}
|
||||
}
|
||||
|
||||
static int stbi__stdio_eof(void *user)
|
||||
{
|
||||
return feof((FILE*) user);
|
||||
return feof((FILE*) user) || ferror((FILE *) user);
|
||||
}
|
||||
|
||||
static stbi_io_callbacks stbi__stdio_callbacks =
|
||||
|
@ -1171,8 +1205,10 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x,
|
|||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
// it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
|
||||
STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
|
||||
|
||||
if (ri.bits_per_channel != 8) {
|
||||
STBI_ASSERT(ri.bits_per_channel == 16);
|
||||
result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
|
||||
ri.bits_per_channel = 8;
|
||||
}
|
||||
|
@ -1195,8 +1231,10 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x,
|
|||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
// it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
|
||||
STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
|
||||
|
||||
if (ri.bits_per_channel != 16) {
|
||||
STBI_ASSERT(ri.bits_per_channel == 8);
|
||||
result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
|
||||
ri.bits_per_channel = 16;
|
||||
}
|
||||
|
@ -1499,6 +1537,7 @@ enum
|
|||
static void stbi__refill_buffer(stbi__context *s)
|
||||
{
|
||||
int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
|
||||
s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original);
|
||||
if (n == 0) {
|
||||
// at end of file, treat same as if from memory, but need to handle case
|
||||
// where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
|
||||
|
@ -1544,6 +1583,7 @@ stbi_inline static int stbi__at_eof(stbi__context *s)
|
|||
#else
|
||||
static void stbi__skip(stbi__context *s, int n)
|
||||
{
|
||||
if (n == 0) return; // already there!
|
||||
if (n < 0) {
|
||||
s->img_buffer = s->img_buffer_end;
|
||||
return;
|
||||
|
@ -1686,7 +1726,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
|
|||
STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
|
||||
STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break;
|
||||
STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;
|
||||
default: STBI_ASSERT(0);
|
||||
default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion");
|
||||
}
|
||||
#undef STBI__CASE
|
||||
}
|
||||
|
@ -1743,7 +1783,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r
|
|||
STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
|
||||
STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break;
|
||||
STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;
|
||||
default: STBI_ASSERT(0);
|
||||
default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion");
|
||||
}
|
||||
#undef STBI__CASE
|
||||
}
|
||||
|
@ -2052,7 +2092,7 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
|
|||
|
||||
sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
|
||||
k = stbi_lrot(j->code_buffer, n);
|
||||
STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask)));
|
||||
if (n < 0 || n >= (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))) return 0;
|
||||
j->code_buffer = k & ~stbi__bmask[n];
|
||||
k &= stbi__bmask[n];
|
||||
j->code_bits -= n;
|
||||
|
@ -2163,6 +2203,7 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__
|
|||
// first scan for DC coefficient, must be first
|
||||
memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
|
||||
t = stbi__jpeg_huff_decode(j, hdc);
|
||||
if (t == -1) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
|
||||
diff = t ? stbi__extend_receive(j, t) : 0;
|
||||
|
||||
dc = j->img_comp[b].dc_pred + diff;
|
||||
|
@ -3153,6 +3194,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
|
|||
p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline
|
||||
s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
|
||||
s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires
|
||||
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
c = stbi__get8(s);
|
||||
if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");
|
||||
s->img_n = c;
|
||||
|
@ -4033,16 +4076,23 @@ typedef struct
|
|||
stbi__zhuffman z_length, z_distance;
|
||||
} stbi__zbuf;
|
||||
|
||||
stbi_inline static int stbi__zeof(stbi__zbuf *z)
|
||||
{
|
||||
return (z->zbuffer >= z->zbuffer_end);
|
||||
}
|
||||
|
||||
stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
|
||||
{
|
||||
if (z->zbuffer >= z->zbuffer_end) return 0;
|
||||
return *z->zbuffer++;
|
||||
return stbi__zeof(z) ? 0 : *z->zbuffer++;
|
||||
}
|
||||
|
||||
static void stbi__fill_bits(stbi__zbuf *z)
|
||||
{
|
||||
do {
|
||||
STBI_ASSERT(z->code_buffer < (1U << z->num_bits));
|
||||
if (z->code_buffer >= (1U << z->num_bits)) {
|
||||
z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */
|
||||
return;
|
||||
}
|
||||
z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
|
||||
z->num_bits += 8;
|
||||
} while (z->num_bits <= 24);
|
||||
|
@ -4067,10 +4117,11 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
|
|||
for (s=STBI__ZFAST_BITS+1; ; ++s)
|
||||
if (k < z->maxcode[s])
|
||||
break;
|
||||
if (s == 16) return -1; // invalid code!
|
||||
if (s >= 16) return -1; // invalid code!
|
||||
// code size is s, so:
|
||||
b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
|
||||
STBI_ASSERT(z->size[b] == s);
|
||||
if (b >= sizeof (z->size)) return -1; // some data was corrupt somewhere!
|
||||
if (z->size[b] != s) return -1; // was originally an assert, but report failure instead.
|
||||
a->code_buffer >>= s;
|
||||
a->num_bits -= s;
|
||||
return z->value[b];
|
||||
|
@ -4079,7 +4130,12 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
|
|||
stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
|
||||
{
|
||||
int b,s;
|
||||
if (a->num_bits < 16) stbi__fill_bits(a);
|
||||
if (a->num_bits < 16) {
|
||||
if (stbi__zeof(a)) {
|
||||
return -1; /* report error for unexpected end of data. */
|
||||
}
|
||||
stbi__fill_bits(a);
|
||||
}
|
||||
b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
|
||||
if (b) {
|
||||
s = b >> 9;
|
||||
|
@ -4093,13 +4149,16 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
|
|||
static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes
|
||||
{
|
||||
char *q;
|
||||
int cur, limit, old_limit;
|
||||
unsigned int cur, limit, old_limit;
|
||||
z->zout = zout;
|
||||
if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
|
||||
cur = (int) (z->zout - z->zout_start);
|
||||
limit = old_limit = (int) (z->zout_end - z->zout_start);
|
||||
while (cur + n > limit)
|
||||
cur = (unsigned int) (z->zout - z->zout_start);
|
||||
limit = old_limit = (unsigned) (z->zout_end - z->zout_start);
|
||||
if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory");
|
||||
while (cur + n > limit) {
|
||||
if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory");
|
||||
limit *= 2;
|
||||
}
|
||||
q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
|
||||
STBI_NOTUSED(old_limit);
|
||||
if (q == NULL) return stbi__err("outofmem", "Out of memory");
|
||||
|
@ -4197,11 +4256,12 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
|
|||
c = stbi__zreceive(a,2)+3;
|
||||
if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
|
||||
fill = lencodes[n-1];
|
||||
} else if (c == 17)
|
||||
} else if (c == 17) {
|
||||
c = stbi__zreceive(a,3)+3;
|
||||
else {
|
||||
STBI_ASSERT(c == 18);
|
||||
} else if (c == 18) {
|
||||
c = stbi__zreceive(a,7)+11;
|
||||
} else {
|
||||
return stbi__err("bad codelengths", "Corrupt PNG");
|
||||
}
|
||||
if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
|
||||
memset(lencodes+n, fill, c);
|
||||
|
@ -4227,7 +4287,7 @@ static int stbi__parse_uncompressed_block(stbi__zbuf *a)
|
|||
a->code_buffer >>= 8;
|
||||
a->num_bits -= 8;
|
||||
}
|
||||
STBI_ASSERT(a->num_bits == 0);
|
||||
if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG");
|
||||
// now fill header the normal way
|
||||
while (k < 4)
|
||||
header[k++] = stbi__zget8(a);
|
||||
|
@ -4249,6 +4309,7 @@ static int stbi__parse_zlib_header(stbi__zbuf *a)
|
|||
int cm = cmf & 15;
|
||||
/* int cinfo = cmf >> 4; */
|
||||
int flg = stbi__zget8(a);
|
||||
if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
|
||||
if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
|
||||
if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png
|
||||
if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png
|
||||
|
@ -4510,7 +4571,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|||
return stbi__err("invalid filter","Corrupt PNG");
|
||||
|
||||
if (depth < 8) {
|
||||
STBI_ASSERT(img_width_bytes <= x);
|
||||
if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
|
||||
cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
|
||||
filter_bytes = 1;
|
||||
width = img_width_bytes;
|
||||
|
@ -4905,8 +4966,10 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|||
if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
|
||||
first = 0;
|
||||
if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
|
||||
s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
||||
s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
||||
s->img_x = stbi__get32be(s);
|
||||
s->img_y = stbi__get32be(s);
|
||||
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
|
||||
color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");
|
||||
if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG");
|
||||
|
@ -5055,10 +5118,12 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st
|
|||
void *result=NULL;
|
||||
if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
|
||||
if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
|
||||
if (p->depth < 8)
|
||||
if (p->depth <= 8)
|
||||
ri->bits_per_channel = 8;
|
||||
else if (p->depth == 16)
|
||||
ri->bits_per_channel = 16;
|
||||
else
|
||||
ri->bits_per_channel = p->depth;
|
||||
return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth");
|
||||
result = p->out;
|
||||
p->out = NULL;
|
||||
if (req_comp && req_comp != p->s->img_out_n) {
|
||||
|
@ -5219,6 +5284,8 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
|
|||
info->mr = info->mg = info->mb = info->ma = 0;
|
||||
info->extra_read = 14;
|
||||
|
||||
if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP");
|
||||
|
||||
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
|
||||
if (hsz == 12) {
|
||||
s->img_x = stbi__get16le(s);
|
||||
|
@ -5310,6 +5377,9 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
flip_vertically = ((int) s->img_y) > 0;
|
||||
s->img_y = abs((int) s->img_y);
|
||||
|
||||
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
|
||||
mr = info.mr;
|
||||
mg = info.mg;
|
||||
mb = info.mb;
|
||||
|
@ -5324,7 +5394,10 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
psize = (info.offset - info.extra_read - info.hsz) >> 2;
|
||||
}
|
||||
if (psize == 0) {
|
||||
STBI_ASSERT(info.offset == (s->img_buffer - s->buffer_start));
|
||||
STBI_ASSERT(info.offset == s->callback_already_read + (int) (s->img_buffer - s->img_buffer_original));
|
||||
if (info.offset != s->callback_already_read + (s->img_buffer - s->buffer_start)) {
|
||||
return stbi__errpuc("bad offset", "Corrupt BMP");
|
||||
}
|
||||
}
|
||||
|
||||
if (info.bpp == 24 && ma == 0xff000000)
|
||||
|
@ -5419,6 +5492,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg);
|
||||
bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb);
|
||||
ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma);
|
||||
if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
|
||||
}
|
||||
for (j=0; j < (int) s->img_y; ++j) {
|
||||
if (easy) {
|
||||
|
@ -5643,6 +5717,9 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
STBI_NOTUSED(tga_x_origin); // @TODO
|
||||
STBI_NOTUSED(tga_y_origin); // @TODO
|
||||
|
||||
if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
|
||||
// do a tiny bit of precessing
|
||||
if ( tga_image_type >= 8 )
|
||||
{
|
||||
|
@ -5682,6 +5759,11 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
// do I need to load a palette?
|
||||
if ( tga_indexed)
|
||||
{
|
||||
if (tga_palette_len == 0) { /* you have to have at least one entry! */
|
||||
STBI_FREE(tga_data);
|
||||
return stbi__errpuc("bad palette", "Corrupt TGA");
|
||||
}
|
||||
|
||||
// any data to skip? (offset usually = 0)
|
||||
stbi__skip(s, tga_palette_start );
|
||||
// load the palette
|
||||
|
@ -5890,6 +5972,9 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
h = stbi__get32be(s);
|
||||
w = stbi__get32be(s);
|
||||
|
||||
if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
|
||||
// Make sure the depth is 8 bits.
|
||||
bitdepth = stbi__get16be(s);
|
||||
if (bitdepth != 8 && bitdepth != 16)
|
||||
|
@ -6244,6 +6329,10 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c
|
|||
|
||||
x = stbi__get16be(s);
|
||||
y = stbi__get16be(s);
|
||||
|
||||
if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
|
||||
if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)");
|
||||
if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
|
||||
|
||||
|
@ -6352,6 +6441,9 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in
|
|||
g->ratio = stbi__get8(s);
|
||||
g->transparent = -1;
|
||||
|
||||
if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
|
||||
if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments
|
||||
|
||||
if (is_info) return 1;
|
||||
|
@ -6529,7 +6621,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
|
|||
memset(g->history, 0x00, pcount); // pixels that were affected previous frame
|
||||
first_frame = 1;
|
||||
} else {
|
||||
// second frame - how do we dispoase of the previous one?
|
||||
// second frame - how do we dispose of the previous one?
|
||||
dispose = (g->eflags & 0x1C) >> 2;
|
||||
pcount = g->w * g->h;
|
||||
|
||||
|
@ -6683,6 +6775,8 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
|
|||
stbi_uc *two_back = 0;
|
||||
stbi__gif g;
|
||||
int stride;
|
||||
int out_size = 0;
|
||||
int delays_size = 0;
|
||||
memset(&g, 0, sizeof(g));
|
||||
if (delays) {
|
||||
*delays = 0;
|
||||
|
@ -6699,22 +6793,28 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
|
|||
stride = g.w * g.h * 4;
|
||||
|
||||
if (out) {
|
||||
void *tmp = (stbi_uc*) STBI_REALLOC( out, layers * stride );
|
||||
void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
|
||||
if (NULL == tmp) {
|
||||
STBI_FREE(g.out);
|
||||
STBI_FREE(g.history);
|
||||
STBI_FREE(g.background);
|
||||
return stbi__errpuc("outofmem", "Out of memory");
|
||||
}
|
||||
else
|
||||
out = (stbi_uc*) tmp;
|
||||
else {
|
||||
out = (stbi_uc*) tmp;
|
||||
out_size = layers * stride;
|
||||
}
|
||||
|
||||
if (delays) {
|
||||
*delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers );
|
||||
*delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );
|
||||
delays_size = layers * sizeof(int);
|
||||
}
|
||||
} else {
|
||||
out = (stbi_uc*)stbi__malloc( layers * stride );
|
||||
out_size = layers * stride;
|
||||
if (delays) {
|
||||
*delays = (int*) stbi__malloc( layers * sizeof(int) );
|
||||
delays_size = layers * sizeof(int);
|
||||
}
|
||||
}
|
||||
memcpy( out + ((layers - 1) * stride), u, stride );
|
||||
|
@ -6893,6 +6993,9 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
|
|||
token += 3;
|
||||
width = (int) strtol(token, NULL, 10);
|
||||
|
||||
if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
|
||||
if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
|
||||
|
||||
*x = width;
|
||||
*y = height;
|
||||
|
||||
|
@ -7207,6 +7310,9 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
|
||||
return 0;
|
||||
|
||||
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
|
||||
*x = s->img_x;
|
||||
*y = s->img_y;
|
||||
if (comp) *comp = s->img_n;
|
||||
|
|
58
raylib/external/stb_image_write.h
vendored
58
raylib/external/stb_image_write.h
vendored
|
@ -1,4 +1,4 @@
|
|||
/* stb_image_write - v1.14 - public domain - http://nothings.org/stb
|
||||
/* stb_image_write - v1.15 - public domain - http://nothings.org/stb
|
||||
writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
|
@ -267,6 +267,8 @@ typedef struct
|
|||
{
|
||||
stbi_write_func *func;
|
||||
void *context;
|
||||
unsigned char buffer[64];
|
||||
int buf_used;
|
||||
} stbi__write_context;
|
||||
|
||||
// initialize a callback-based context
|
||||
|
@ -380,16 +382,36 @@ static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
|
|||
va_end(v);
|
||||
}
|
||||
|
||||
static void stbiw__write_flush(stbi__write_context *s)
|
||||
{
|
||||
if (s->buf_used) {
|
||||
s->func(s->context, &s->buffer, s->buf_used);
|
||||
s->buf_used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void stbiw__putc(stbi__write_context *s, unsigned char c)
|
||||
{
|
||||
s->func(s->context, &c, 1);
|
||||
}
|
||||
|
||||
static void stbiw__write1(stbi__write_context *s, unsigned char a)
|
||||
{
|
||||
if (s->buf_used + 1 > sizeof(s->buffer))
|
||||
stbiw__write_flush(s);
|
||||
s->buffer[s->buf_used++] = a;
|
||||
}
|
||||
|
||||
static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
|
||||
{
|
||||
unsigned char arr[3];
|
||||
arr[0] = a; arr[1] = b; arr[2] = c;
|
||||
s->func(s->context, arr, 3);
|
||||
int n;
|
||||
if (s->buf_used + 3 > sizeof(s->buffer))
|
||||
stbiw__write_flush(s);
|
||||
n = s->buf_used;
|
||||
s->buf_used = n+3;
|
||||
s->buffer[n+0] = a;
|
||||
s->buffer[n+1] = b;
|
||||
s->buffer[n+2] = c;
|
||||
}
|
||||
|
||||
static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
|
||||
|
@ -398,7 +420,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
|
|||
int k;
|
||||
|
||||
if (write_alpha < 0)
|
||||
s->func(s->context, &d[comp - 1], 1);
|
||||
stbiw__write1(s, d[comp - 1]);
|
||||
|
||||
switch (comp) {
|
||||
case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
|
||||
|
@ -406,7 +428,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
|
|||
if (expand_mono)
|
||||
stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
|
||||
else
|
||||
s->func(s->context, d, 1); // monochrome TGA
|
||||
stbiw__write1(s, d[0]); // monochrome TGA
|
||||
break;
|
||||
case 4:
|
||||
if (!write_alpha) {
|
||||
|
@ -422,7 +444,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
|
|||
break;
|
||||
}
|
||||
if (write_alpha > 0)
|
||||
s->func(s->context, &d[comp - 1], 1);
|
||||
stbiw__write1(s, d[comp - 1]);
|
||||
}
|
||||
|
||||
static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
|
||||
|
@ -447,6 +469,7 @@ static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, i
|
|||
unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
|
||||
stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
|
||||
}
|
||||
stbiw__write_flush(s);
|
||||
s->func(s->context, &zero, scanline_pad);
|
||||
}
|
||||
}
|
||||
|
@ -476,7 +499,7 @@ static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, c
|
|||
|
||||
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_bmp_core(&s, x, y, comp, data);
|
||||
}
|
||||
|
@ -484,7 +507,7 @@ STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_bmp_core(&s, x, y, comp, data);
|
||||
stbi__end_write_file(&s);
|
||||
|
@ -557,24 +580,25 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v
|
|||
|
||||
if (diff) {
|
||||
unsigned char header = STBIW_UCHAR(len - 1);
|
||||
s->func(s->context, &header, 1);
|
||||
stbiw__write1(s, header);
|
||||
for (k = 0; k < len; ++k) {
|
||||
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
|
||||
}
|
||||
} else {
|
||||
unsigned char header = STBIW_UCHAR(len - 129);
|
||||
s->func(s->context, &header, 1);
|
||||
stbiw__write1(s, header);
|
||||
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
|
||||
}
|
||||
}
|
||||
}
|
||||
stbiw__write_flush(s);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_tga_core(&s, x, y, comp, (void *) data);
|
||||
}
|
||||
|
@ -582,7 +606,7 @@ STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
|
||||
stbi__end_write_file(&s);
|
||||
|
@ -748,7 +772,7 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
|
|||
|
||||
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
|
||||
}
|
||||
|
@ -756,7 +780,7 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
|
||||
stbi__end_write_file(&s);
|
||||
|
@ -1552,7 +1576,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
|
|||
|
||||
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
|
||||
}
|
||||
|
@ -1561,7 +1585,7 @@ STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
|
||||
stbi__end_write_file(&s);
|
||||
|
|
5077
raylib/external/stb_vorbis.c
vendored
5077
raylib/external/stb_vorbis.c
vendored
File diff suppressed because it is too large
Load diff
2
raylib/external/stb_vorbis.h
vendored
2
raylib/external/stb_vorbis.h
vendored
|
@ -570,7 +570,7 @@ enum STBVorbisError
|
|||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__)
|
||||
#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) || defined(__APPLE__)
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
#else // STB_VORBIS_NO_CRT
|
||||
|
|
6
raylib/external/tinyobj_loader_c.h
vendored
6
raylib/external/tinyobj_loader_c.h
vendored
|
@ -748,7 +748,7 @@ static int tinyobj_parse_and_index_mtl_file(tinyobj_material_t **materials_out,
|
|||
|
||||
fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
//fprintf(stderr, "TINYOBJ: Error reading file '%s': %s (%d)\n", filename, strerror(errno), errno); // @raysan5: commented
|
||||
fprintf(stderr, "TINYOBJ: Error reading file '%s': %s (%d)\n", filename, strerror(errno), errno);
|
||||
return TINYOBJ_ERROR_FILE_OPERATION;
|
||||
}
|
||||
|
||||
|
@ -1321,7 +1321,7 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes,
|
|||
|
||||
if (ret != TINYOBJ_SUCCESS) {
|
||||
/* warning. */
|
||||
//fprintf(stderr, "TINYOBJ: Failed to parse material file '%s': %d\n", filename, ret); // @raysan5: commented
|
||||
fprintf(stderr, "TINYOBJ: Failed to parse material file '%s': %d\n", filename, ret);
|
||||
}
|
||||
|
||||
TINYOBJ_FREE(filename);
|
||||
|
@ -1377,7 +1377,7 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes,
|
|||
/* Create a null terminated string */
|
||||
char* material_name_null_term = (char*) TINYOBJ_MALLOC(commands[i].material_name_len + 1);
|
||||
memcpy((void*) material_name_null_term, (const void*) commands[i].material_name, commands[i].material_name_len);
|
||||
material_name_null_term[commands[i].material_name_len - 1] = 0;
|
||||
material_name_null_term[commands[i].material_name_len] = 0;
|
||||
|
||||
if (hash_table_exists(material_name_null_term, &material_table))
|
||||
material_id = (int)hash_table_get(material_name_null_term, &material_table);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue