├── test ├── noto.ttf ├── LICENSE_noto └── test.c ├── .gitignore ├── src ├── shader │ ├── to_texture.frag │ └── to_texture.vert ├── fond_internal.h ├── fond_windows.h ├── fond_buffer.c ├── fond_common.c ├── fond_windows.c ├── fond.c ├── fond.h ├── stb_rect_pack.h ├── utf8.h └── GL │ └── wglext.h ├── LICENSE ├── README.md ├── CMakeLists.txt └── FindGLFW.cmake /test/noto.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shirakumo/libfond/HEAD/test/noto.ttf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | src/shader/*.h 3 | CMakeFiles/ 4 | CMakeCache.txt 5 | cmake_install.cmake 6 | Makefile 7 | -------------------------------------------------------------------------------- /src/shader/to_texture.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | uniform sampler2D tex_image; 4 | uniform vec4 text_color = vec4(1.0, 1.0, 1.0, 1.0); 5 | 6 | in vec2 tex_coord; 7 | out vec4 color; 8 | 9 | void main(){ 10 | float intensity = texture(tex_image, tex_coord).r; 11 | color = vec4(intensity)*text_color; 12 | } 13 | -------------------------------------------------------------------------------- /src/shader/to_texture.vert: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | uniform vec4 extent = vec4(1.0); 3 | 4 | layout(location = 0) in vec2 position; 5 | layout(location = 1) in vec2 in_tex_coord; 6 | out vec2 tex_coord; 7 | 8 | void main(){ 9 | gl_Position = vec4(2*(position.x+extent.x)/extent.z-1.0, 10 | 2*(position.y-extent.y)/extent.w+1.0, 11 | 0.0, 1.0); 12 | tex_coord = in_tex_coord; 13 | } 14 | -------------------------------------------------------------------------------- /src/fond_internal.h: -------------------------------------------------------------------------------- 1 | #include "fond.h" 2 | #include 3 | #if defined(WIN32) || defined(_WIN32) 4 | # define FOND_WIN 5 | # include 6 | # include 7 | # include "fond_windows.h" 8 | #endif 9 | #if defined(__APPLE__) 10 | # define FOND_MAC 11 | # define GL_GLEXT_PROTOTYPES 12 | # include 13 | # include 14 | #endif 15 | #if defined(__linux__) 16 | # define FOND_LIN 17 | # define GL_GLEXT_PROTOTYPES 18 | # include 19 | # include 20 | #endif 21 | 22 | extern int errorcode; 23 | void fond_err(int code); 24 | int fond_check_glerror(); 25 | int fond_check_shader(GLuint shader); 26 | int fond_check_program(GLuint program); 27 | 28 | int fond_load_file(char *file, void **content); 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Nicolas Hafner 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## About Libfond 2 | This is a library for font rendering, allowing you to easily and quickly render TrueType font text to OpenGL. 3 | 4 | ## API 5 | The API is documented in [fond.h](src/fond.h). 6 | 7 | ## Building It 8 | Requirements: 9 | 10 | * CMake 3.1+ 11 | * A C99 compiler 12 | * OpenGL 13 | 14 | Steps: 15 | 16 | * `mkdir build` 17 | * `cd build` 18 | * `cmake ..` 19 | * `make` 20 | 21 | If GLEW and GLFW are installed on the system as well, a quick demo application is compiled as well. 22 | 23 | ## Included Sources 24 | * [stb_rect_pack.h](https://github.com/nothings/stb/blob/master/stb_rect_pack.h) 25 | * [stb_truetype.h](https://github.com/nothings/stb/blob/master/stb_truetype.h) 26 | * [utf8.h](https://github.com/sheredom/utf8.h/blob/master/utf8.h) 27 | * [GL/glext.h](https://www.khronos.org/registry/OpenGL/api/GL/glext.h) 28 | * [GL/wglext.h](https://www.khronos.org/registry/OpenGL/api/GL/wglext.h) 29 | -------------------------------------------------------------------------------- /src/fond_windows.h: -------------------------------------------------------------------------------- 1 | #ifdef FOND_WIN 2 | #pragma comment(lib,"opengl32.lib") 3 | #include 4 | 5 | extern PFNGLTEXSTORAGE2DPROC glTexStorage2D; 6 | extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap; 7 | extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; 8 | extern PFNGLGENBUFFERSPROC glGenBuffers; 9 | extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; 10 | extern PFNGLBINDBUFFERPROC glBindBuffer; 11 | extern PFNGLBUFFERDATAPROC glBufferData; 12 | extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; 13 | extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; 14 | extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; 15 | extern PFNGLDELETEBUFFERSPROC glDeleteBuffers; 16 | extern PFNGLDELETEPROGRAMPROC glDeleteProgram; 17 | extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; 18 | extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; 19 | extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; 20 | extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; 21 | extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; 22 | extern PFNGLCREATESHADERPROC glCreateShader; 23 | extern PFNGLSHADERSOURCEPROC glShaderSource; 24 | extern PFNGLCOMPILESHADERPROC glCompileShader; 25 | extern PFNGLGETSHADERIVPROC glGetShaderiv; 26 | extern PFNGLCREATEPROGRAMPROC glCreateProgram; 27 | extern PFNGLATTACHSHADERPROC glAttachShader; 28 | extern PFNGLLINKPROGRAMPROC glLinkProgram; 29 | extern PFNGLGETPROGRAMIVPROC glGetProgramiv; 30 | extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; 31 | extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; 32 | extern PFNGLDELETESHADERPROC glDeleteShader; 33 | extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; 34 | extern PFNGLUSEPROGRAMPROC glUseProgram; 35 | extern PFNGLUNIFORM4FPROC glUniform4f; 36 | 37 | void fond_load_glext(); 38 | #endif 39 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(fond) 3 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") 4 | 5 | find_package(OpenGL REQUIRED) 6 | find_package(GLEW) 7 | find_package(GLFW) 8 | 9 | ## Generate Shader Headers 10 | add_custom_target(shaders ALL) 11 | file(GLOB shaders "src/shader/*.vert" "src/shader/*.frag") 12 | foreach(shader_s ${shaders}) 13 | set(shader_h ${shader_s}.h) 14 | get_filename_component(shader_hf ${shader_h} NAME) 15 | get_filename_component(shader_sf ${shader_s} NAME) 16 | get_filename_component(shader_dir ${shader_h} DIRECTORY) 17 | set_source_files_properties(${shader_h} PROPERTIES GENERATED TRUE) 18 | add_custom_command( 19 | TARGET shaders 20 | COMMAND xxd -i ${shader_sf} ${shader_hf} 21 | COMMAND sed -i.bak 's/unsigned char/const GLchar/g' ${shader_hf} 22 | COMMAND sed -i.bak 's/}\;/, 0x00}\;/g' ${shader_hf} 23 | DEPENDS ${shader_s} 24 | WORKING_DIRECTORY ${shader_dir} 25 | COMMENT "Generating header for ${shader_s}") 26 | endforeach() 27 | 28 | ## Main Library 29 | include_directories("src/") 30 | include_directories(${OPENGL_INCLUDE_DIRS}) 31 | file(GLOB lib_src "src/*.c") 32 | add_library(fond SHARED ${lib_src}) 33 | add_dependencies(fond shaders) 34 | set_property(TARGET fond PROPERTY C_STANDARD 99) 35 | target_link_libraries(fond ${OPENGL_LIBRARIES}) 36 | 37 | if(WIN32) 38 | set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc -static-libstdc++") 39 | endif() 40 | 41 | ## Test Program 42 | if(GLFW_FOUND AND GLEW_FOUND) 43 | include_directories(${GLEW_INCLUDE_DIRS}) 44 | include_directories(${GLFW_INCLUDE_DIRS}) 45 | file(GLOB test_src "test/*.c") 46 | add_executable(fond_test ${test_src}) 47 | add_dependencies(fond_test fond) 48 | set_property(TARGET fond_test PROPERTY C_STANDARD 99) 49 | target_link_libraries(fond_test fond ${GLFW_LIBRARIES} ${GLEW_LIBRARIES}) 50 | endif() 51 | 52 | ## Warnings 53 | if(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)") 54 | add_definitions(/W2) 55 | elseif(CMAKE_BUILD_TOOL MATCHES "(gcc|clang)") 56 | add_definitions(-W -Wall -Wextra -pedantic) 57 | endif() 58 | 59 | install(TARGETS fond DESTINATION /usr/local/lib) 60 | -------------------------------------------------------------------------------- /test/LICENSE_noto: -------------------------------------------------------------------------------- 1 | This Font Software is licensed under the SIL Open Font License, 2 | Version 1.1. 3 | 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | ----------------------------------------------------------- 8 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 9 | ----------------------------------------------------------- 10 | 11 | PREAMBLE 12 | The goals of the Open Font License (OFL) are to stimulate worldwide 13 | development of collaborative font projects, to support the font 14 | creation efforts of academic and linguistic communities, and to 15 | provide a free and open framework in which fonts may be shared and 16 | improved in partnership with others. 17 | 18 | The OFL allows the licensed fonts to be used, studied, modified and 19 | redistributed freely as long as they are not sold by themselves. The 20 | fonts, including any derivative works, can be bundled, embedded, 21 | redistributed and/or sold with any software provided that any reserved 22 | names are not used by derivative works. The fonts and derivatives, 23 | however, cannot be released under any other type of license. The 24 | requirement for fonts to remain under this license does not apply to 25 | any document created using the fonts or their derivatives. 26 | 27 | DEFINITIONS 28 | "Font Software" refers to the set of files released by the Copyright 29 | Holder(s) under this license and clearly marked as such. This may 30 | include source files, build scripts and documentation. 31 | 32 | "Reserved Font Name" refers to any names specified as such after the 33 | copyright statement(s). 34 | 35 | "Original Version" refers to the collection of Font Software 36 | components as distributed by the Copyright Holder(s). 37 | 38 | "Modified Version" refers to any derivative made by adding to, 39 | deleting, or substituting -- in part or in whole -- any of the 40 | components of the Original Version, by changing formats or by porting 41 | the Font Software to a new environment. 42 | 43 | "Author" refers to any designer, engineer, programmer, technical 44 | writer or other person who contributed to the Font Software. 45 | 46 | PERMISSION & CONDITIONS 47 | Permission is hereby granted, free of charge, to any person obtaining 48 | a copy of the Font Software, to use, study, copy, merge, embed, 49 | modify, redistribute, and sell modified and unmodified copies of the 50 | Font Software, subject to the following conditions: 51 | 52 | 1) Neither the Font Software nor any of its individual components, in 53 | Original or Modified Versions, may be sold by itself. 54 | 55 | 2) Original or Modified Versions of the Font Software may be bundled, 56 | redistributed and/or sold with any software, provided that each copy 57 | contains the above copyright notice and this license. These can be 58 | included either as stand-alone text files, human-readable headers or 59 | in the appropriate machine-readable metadata fields within text or 60 | binary files as long as those fields can be easily viewed by the user. 61 | 62 | 3) No Modified Version of the Font Software may use the Reserved Font 63 | Name(s) unless explicit written permission is granted by the 64 | corresponding Copyright Holder. This restriction only applies to the 65 | primary font name as presented to the users. 66 | 67 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 68 | Software shall not be used to promote, endorse or advertise any 69 | Modified Version, except to acknowledge the contribution(s) of the 70 | Copyright Holder(s) and the Author(s) or with their explicit written 71 | permission. 72 | 73 | 5) The Font Software, modified or unmodified, in part or in whole, 74 | must be distributed entirely under this license, and must not be 75 | distributed under any other license. The requirement for fonts to 76 | remain under this license does not apply to any document created using 77 | the Font Software. 78 | 79 | TERMINATION 80 | This license becomes null and void if any of the above conditions are 81 | not met. 82 | 83 | DISCLAIMER 84 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 85 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 86 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 87 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 88 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 89 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 90 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 91 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 92 | OTHER DEALINGS IN THE FONT SOFTWARE. 93 | -------------------------------------------------------------------------------- /src/fond_buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fond_internal.h" 3 | #include "shader/to_texture.vert.h" 4 | #include "shader/to_texture.frag.h" 5 | 6 | const GLchar *to_texture_vert_src = to_texture_vert; 7 | const GLchar *to_texture_frag_src = to_texture_frag; 8 | 9 | FOND_EXPORT void fond_free_buffer(struct fond_buffer *buffer){ 10 | if(buffer->texture) 11 | glDeleteTextures(1, &buffer->texture); 12 | buffer->texture = 0; 13 | 14 | if(buffer->program) 15 | glDeleteProgram(buffer->program); 16 | buffer->program = 0; 17 | 18 | if(buffer->framebuffer) 19 | glDeleteFramebuffers(1, &buffer->framebuffer); 20 | buffer->framebuffer = 0; 21 | } 22 | 23 | FOND_EXPORT int fond_load_buffer(struct fond_buffer *buffer){ 24 | GLuint vert = 0, frag = 0; 25 | 26 | if(buffer->width == 0) 27 | buffer->width = 512; 28 | if(buffer->height == 0) 29 | buffer->height = 64; 30 | 31 | glGenTextures(1, &buffer->texture); 32 | glBindTexture(GL_TEXTURE_2D, buffer->texture); 33 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.65); 34 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 35 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 36 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 37 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 38 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 39 | glGenerateMipmap(GL_TEXTURE_2D); 40 | glBindTexture(GL_TEXTURE_2D, 0); 41 | if(!fond_check_glerror()){ 42 | fond_err(FOND_OPENGL_ERROR); 43 | goto fond_load_buffer_cleanup; 44 | } 45 | 46 | glGenFramebuffers(1, &buffer->framebuffer); 47 | glBindFramebuffer(GL_FRAMEBUFFER, buffer->framebuffer); 48 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer->texture, 0); 49 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 50 | if(!fond_check_glerror() 51 | || glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){ 52 | fond_err(FOND_OPENGL_ERROR); 53 | goto fond_load_buffer_cleanup; 54 | } 55 | 56 | vert = glCreateShader(GL_VERTEX_SHADER); 57 | glShaderSource(vert, 1, &to_texture_vert_src, 0); 58 | glCompileShader(vert); 59 | if(!fond_check_shader(vert)){ 60 | fond_err(FOND_OPENGL_ERROR); 61 | goto fond_load_buffer_cleanup; 62 | } 63 | 64 | frag = glCreateShader(GL_FRAGMENT_SHADER); 65 | glShaderSource(frag, 1, &to_texture_frag_src, 0); 66 | glCompileShader(frag); 67 | if(!fond_check_shader(frag)){ 68 | fond_err(FOND_OPENGL_ERROR); 69 | goto fond_load_buffer_cleanup; 70 | } 71 | 72 | buffer->program = glCreateProgram(); 73 | glAttachShader(buffer->program, vert); 74 | glAttachShader(buffer->program, frag); 75 | glLinkProgram(buffer->program); 76 | if(!fond_check_program(buffer->program)){ 77 | fond_err(FOND_OPENGL_ERROR); 78 | goto fond_load_buffer_cleanup; 79 | } 80 | 81 | glGenVertexArrays(1, &buffer->vao); 82 | glGenBuffers(1, &buffer->vbo); 83 | glGenBuffers(1, &buffer->ebo); 84 | 85 | glBindVertexArray(buffer->vao); 86 | 87 | glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo); 88 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (GLvoid*)0); 89 | glEnableVertexAttribArray(0); 90 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (GLvoid*)(2*sizeof(float))); 91 | glEnableVertexAttribArray(1); 92 | 93 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->ebo); 94 | 95 | glBindVertexArray(0); 96 | glBindBuffer(GL_ARRAY_BUFFER, 0); 97 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 98 | 99 | if(!fond_check_glerror()){ 100 | fond_err(FOND_OPENGL_ERROR); 101 | goto fond_load_buffer_cleanup; 102 | } 103 | 104 | fond_err(FOND_NO_ERROR); 105 | glDeleteShader(vert); 106 | glDeleteShader(frag); 107 | return 1; 108 | 109 | fond_load_buffer_cleanup: 110 | if(buffer->texture) 111 | glDeleteTextures(1, &buffer->texture); 112 | buffer->texture = 0; 113 | 114 | if(buffer->framebuffer) 115 | glDeleteFramebuffers(1, &buffer->framebuffer); 116 | buffer->framebuffer = 0; 117 | 118 | if(vert) 119 | glDeleteShader(vert); 120 | 121 | if(frag) 122 | glDeleteShader(frag); 123 | 124 | if(buffer->program) 125 | glDeleteProgram(buffer->program); 126 | buffer->program = 0; 127 | 128 | if(buffer->ebo) 129 | glDeleteBuffers(1, &buffer->ebo); 130 | 131 | if(buffer->vbo) 132 | glDeleteBuffers(1, &buffer->vbo); 133 | 134 | if(buffer->vao) 135 | glDeleteVertexArrays(1, &buffer->vao); 136 | return 0; 137 | } 138 | 139 | FOND_EXPORT int fond_render_u(struct fond_buffer *buffer, int32_t *text, size_t size, float x, float y, float *color){ 140 | size_t n; 141 | GLuint extent_u = 0, color_u = 0; 142 | 143 | if(!fond_update_u(buffer->font, text, size, &n, buffer->vbo, buffer->ebo)){ 144 | return 0; 145 | } 146 | 147 | extent_u = glGetUniformLocation(buffer->program, "extent"); 148 | color_u = glGetUniformLocation(buffer->program, "text_color"); 149 | 150 | glBindFramebuffer(GL_FRAMEBUFFER, buffer->framebuffer); 151 | glViewport(0, 0, buffer->width, buffer->height); 152 | glUseProgram(buffer->program); 153 | glBindVertexArray(buffer->vao); 154 | glBindTexture(GL_TEXTURE_2D, buffer->font->atlas); 155 | glUniform4f(extent_u, x, y, buffer->width, buffer->height); 156 | if(color) glUniform4f(color_u, color[0], color[1], color[2], color[3]); 157 | { 158 | glClearColor(0.0, 0.0, 0.0, 0.0); 159 | glClear(GL_COLOR_BUFFER_BIT); 160 | glDrawElements(GL_TRIANGLES, n, GL_UNSIGNED_INT, 0); 161 | } 162 | glBindTexture(GL_TEXTURE_2D, buffer->texture); 163 | glGenerateMipmap(GL_TEXTURE_2D); 164 | glBindTexture(GL_TEXTURE_2D, 0); 165 | glBindVertexArray(0); 166 | glUseProgram(0); 167 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 168 | 169 | if(!fond_check_glerror()){ 170 | fond_err(FOND_OPENGL_ERROR); 171 | return 0; 172 | } 173 | 174 | fond_err(FOND_NO_ERROR); 175 | return 1; 176 | } 177 | -------------------------------------------------------------------------------- /src/fond_common.c: -------------------------------------------------------------------------------- 1 | #include "fond_internal.h" 2 | #include "utf8.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int errorcode = 0; 10 | 11 | FOND_EXPORT int fond_decode_utf8(void *string, int32_t **_decoded, size_t *_size){ 12 | if(utf8valid(string)){ 13 | fond_err(FOND_UTF8_CONVERSION_ERROR); 14 | return 0; 15 | } 16 | 17 | size_t size = utf8len(string); 18 | int32_t *decoded = calloc(size+1, sizeof(uint32_t)); 19 | if(!decoded){ 20 | fond_err(FOND_OUT_OF_MEMORY); 21 | return 0; 22 | } 23 | 24 | for(int i=0; i 3 | #include 4 | #include 5 | #include "../src/fond.h" 6 | 7 | const GLchar *vertex_shader = "#version 330 core\n" 8 | "layout (location = 0) in vec3 position;\n" 9 | "layout (location = 1) in vec2 in_texcoord;\n" 10 | "out vec2 texcoord;\n" 11 | "\n" 12 | "void main(){\n" 13 | " gl_Position = vec4(position, 1.0);\n" 14 | " texcoord = in_texcoord;\n" 15 | "}"; 16 | 17 | const GLchar *fragment_shader = "#version 330 core\n" 18 | "uniform sampler2D tex_image;\n" 19 | "in vec2 texcoord;\n" 20 | "out vec4 color;\n" 21 | "\n" 22 | "void main(){\n" 23 | " color = texture(tex_image, texcoord);\n" 24 | "}\n"; 25 | 26 | struct data{ 27 | struct fond_buffer *buffer; 28 | int32_t text[500]; 29 | size_t pos; 30 | }; 31 | 32 | int load_stuff(char *file, struct data *data){ 33 | struct fond_buffer *buffer = data->buffer; 34 | struct fond_font *font = buffer->font; 35 | 36 | font->file = file; 37 | font->size = 100.0; 38 | font->oversample = 2; 39 | font->characters = 40 | "abcdefghijklmnopqrstuvwxyz" 41 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 42 | "0123456789 \n\t.,-;:?!/()*+^_\\\"'"; 43 | 44 | printf("Loading font... "); 45 | GLint max_size = 0; 46 | glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size); 47 | if(!fond_load_fit(font, max_size)) 48 | return 0; 49 | printf("DONE (Atlas %ix%i)\n", font->width, font->height); 50 | 51 | buffer->font = font; 52 | buffer->width = 800; 53 | buffer->height = 600; 54 | printf("Loading buffer... "); 55 | if(!fond_load_buffer(buffer)) 56 | return 0; 57 | printf("DONE\n"); 58 | 59 | printf("Rendering buffer... "); 60 | if(!fond_render(buffer, "Type it", 0, 100, 0)) 61 | return 0; 62 | printf("DONE\n"); 63 | 64 | return 1; 65 | } 66 | 67 | int render_text(struct data *data){ 68 | struct fond_extent extent = {0}; 69 | fond_compute_extent_u(data->buffer->font, 0, 0, &extent); 70 | if(!fond_render_u(data->buffer, data->text, data->pos, 0, extent.t, 0)){ 71 | printf("Failed to render: %s\n", fond_error_string(fond_error())); 72 | return 0; 73 | } 74 | return 1; 75 | } 76 | 77 | void character_callback(GLFWwindow* window, unsigned int codepoint){ 78 | struct data *data = glfwGetWindowUserPointer(window); 79 | if(data->pos < 500){ 80 | data->text[data->pos] = (int32_t)codepoint; 81 | data->pos++; 82 | if(!render_text(data)) 83 | data->pos--; 84 | } 85 | } 86 | 87 | void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode){ 88 | struct data *data = glfwGetWindowUserPointer(window); 89 | if(action == GLFW_RELEASE){ 90 | switch(key){ 91 | case GLFW_KEY_BACKSPACE: 92 | if(0 < data->pos){ 93 | data->pos--; 94 | if(!render_text(data)) 95 | data->pos++; 96 | } 97 | break; 98 | case GLFW_KEY_ENTER: 99 | character_callback(window, '\n'); 100 | break; 101 | case GLFW_KEY_ESCAPE: 102 | glfwSetWindowShouldClose(window, GL_TRUE); 103 | break; 104 | } 105 | } 106 | } 107 | 108 | void render(GLuint program, GLuint vao, struct fond_buffer *buffer){ 109 | glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 110 | glClear(GL_COLOR_BUFFER_BIT); 111 | 112 | glBindTexture(GL_TEXTURE_2D, buffer->texture); 113 | glUseProgram(program); 114 | glBindVertexArray(vao); 115 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 116 | glBindVertexArray(0); 117 | } 118 | 119 | int main(int argc, char **argv){ 120 | if(argc == 1){ 121 | printf("Please specify a TTF file to load.\n"); 122 | return 0; 123 | } 124 | 125 | printf("Initializing GL... "); 126 | 127 | glfwInit(); 128 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 129 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 130 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 131 | glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); 132 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 133 | 134 | GLFWwindow* window = glfwCreateWindow(800, 600, "Fond Test", 0, 0); 135 | if(window == 0){ 136 | printf("Failed to create GLFW window\n"); 137 | goto main_cleanup; 138 | } 139 | glfwMakeContextCurrent(window); 140 | glfwSetKeyCallback(window, key_callback); 141 | glfwSetCharCallback(window, character_callback); 142 | 143 | glewExperimental = GL_TRUE; 144 | if(glewInit() != GLEW_OK){ 145 | printf("Failed to initialize GLEW\n"); 146 | goto main_cleanup; 147 | } 148 | 149 | //glEnable(GL_CULL_FACE); 150 | glFrontFace(GL_CCW); 151 | glEnable(GL_BLEND); 152 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 153 | 154 | GLuint vert, frag, program, vbo, ebo, vao; 155 | vert = glCreateShader(GL_VERTEX_SHADER); 156 | glShaderSource(vert, 1, &vertex_shader, 0); 157 | glCompileShader(vert); 158 | 159 | frag = glCreateShader(GL_FRAGMENT_SHADER); 160 | glShaderSource(frag, 1, &fragment_shader, 0); 161 | glCompileShader(frag); 162 | 163 | program = glCreateProgram(); 164 | glAttachShader(program, vert); 165 | glAttachShader(program, frag); 166 | glLinkProgram(program); 167 | 168 | GLfloat vertices[] = { 169 | 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 170 | 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 171 | -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 172 | -1.0f, 1.0f, 0.0f, 0.0f, 1.0f 173 | }; 174 | GLuint indices[] = { 175 | 0, 3, 1, 176 | 1, 3, 2 177 | }; 178 | 179 | glGenVertexArrays(1, &vao); 180 | glBindVertexArray(vao); 181 | 182 | glGenBuffers(1, &vbo); 183 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 184 | glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 185 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (GLvoid *)0); 186 | glEnableVertexAttribArray(0); 187 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (GLvoid *)(3*sizeof(float))); 188 | glEnableVertexAttribArray(1); 189 | 190 | glGenBuffers(1, &ebo); 191 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); 192 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); 193 | 194 | glBindVertexArray(0); 195 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 196 | glBindBuffer(GL_ARRAY_BUFFER, 0); 197 | 198 | if(glGetError() != GL_NO_ERROR){ 199 | printf("FAILED\n"); 200 | goto main_cleanup; 201 | } 202 | printf("DONE\n"); 203 | 204 | // Construct data and tie it. 205 | struct data data = {0}; 206 | struct fond_font font = {0}; 207 | struct fond_buffer buffer = {0}; 208 | data.buffer = &buffer; 209 | buffer.font = &font; 210 | 211 | glfwSetWindowUserPointer(window, &data); 212 | 213 | if(!load_stuff(argv[1], &data)){ 214 | printf("Error: %s\n", fond_error_string(fond_error())); 215 | goto main_cleanup; 216 | } 217 | 218 | int width, height; 219 | glfwGetFramebufferSize(window, &width, &height); 220 | glViewport(0, 0, width, height); 221 | 222 | while(!glfwWindowShouldClose(window)){ 223 | glfwPollEvents(); 224 | 225 | render(program, vao, &buffer); 226 | 227 | glfwSwapBuffers(window); 228 | } 229 | 230 | fond_free(&font); 231 | fond_free_buffer(&buffer); 232 | 233 | main_cleanup: 234 | glfwTerminate(); 235 | return 0; 236 | } 237 | -------------------------------------------------------------------------------- /FindGLFW.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2013 Pixar 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "Apache License") 5 | # with the following modification; you may not use this file except in 6 | # compliance with the Apache License and the following modification to it: 7 | # Section 6. Trademarks. is deleted and replaced with: 8 | # 9 | # 6. Trademarks. This License does not grant permission to use the trade 10 | # names, trademarks, service marks, or product names of the Licensor 11 | # and its affiliates, except as required to comply with Section 4(c) of 12 | # the License and to reproduce the content of the NOTICE file. 13 | # 14 | # You may obtain a copy of the Apache License at 15 | # 16 | # http://www.apache.org/licenses/LICENSE-2.0 17 | # 18 | # Unless required by applicable law or agreed to in writing, software 19 | # distributed under the Apache License with the above modification is 20 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 | # KIND, either express or implied. See the Apache License for the specific 22 | # language governing permissions and limitations under the Apache License. 23 | # 24 | 25 | # Try to find GLFW library and include path. 26 | # Once done this will define 27 | # 28 | # GLFW_FOUND 29 | # GLFW_INCLUDE_DIR 30 | # GLFW_LIBRARIES 31 | # 32 | 33 | find_path( GLFW_INCLUDE_DIR 34 | NAMES 35 | GLFW/glfw3.h 36 | HINTS 37 | "${GLFW_LOCATION}/include" 38 | "$ENV{GLFW_LOCATION}/include" 39 | PATHS 40 | "$ENV{PROGRAMFILES}/GLFW/include" 41 | "${OPENGL_INCLUDE_DIR}" 42 | /usr/openwin/share/include 43 | /usr/openwin/include 44 | /usr/X11R6/include 45 | /usr/include/X11 46 | /opt/graphics/OpenGL/include 47 | /opt/graphics/OpenGL/contrib/libglfw 48 | /usr/local/include 49 | /usr/include/GL 50 | /usr/include 51 | DOC 52 | "The directory where GLFW/glfw3.h resides" 53 | ) 54 | 55 | # 56 | # XXX: Do we still need to search for GL/glfw.h? 57 | # 58 | find_path( GLFW_INCLUDE_DIR 59 | NAMES 60 | GL/glfw.h 61 | HINTS 62 | "${GLFW_LOCATION}/include" 63 | "$ENV{GLFW_LOCATION}/include" 64 | PATHS 65 | "$ENV{PROGRAMFILES}/GLFW/include" 66 | "${OPENGL_INCLUDE_DIR}" 67 | /usr/openwin/share/include 68 | /usr/openwin/include 69 | /usr/X11R6/include 70 | /usr/include/X11 71 | /opt/graphics/OpenGL/include 72 | /opt/graphics/OpenGL/contrib/libglfw 73 | /usr/local/include 74 | /usr/include/GL 75 | /usr/include 76 | DOC 77 | "The directory where GL/glfw.h resides" 78 | ) 79 | 80 | if (WIN32) 81 | if(CYGWIN) 82 | find_library( GLFW_glfw_LIBRARY 83 | NAMES 84 | glfw32 85 | HINTS 86 | "${GLFW_LOCATION}/lib" 87 | "${GLFW_LOCATION}/lib/x64" 88 | "$ENV{GLFW_LOCATION}/lib" 89 | PATHS 90 | "${OPENGL_LIBRARY_DIR}" 91 | /usr/lib 92 | /usr/lib/w32api 93 | /usr/local/lib 94 | /usr/X11R6/lib 95 | DOC 96 | "The GLFW library" 97 | ) 98 | else() 99 | find_library( GLFW_glfw_LIBRARY 100 | NAMES 101 | glfw32 102 | glfw32s 103 | glfw 104 | glfw3 105 | HINTS 106 | "${GLFW_LOCATION}/lib" 107 | "${GLFW_LOCATION}/lib/x64" 108 | "${GLFW_LOCATION}/lib-msvc110" 109 | "${GLFW_LOCATION}/lib-vc2012" 110 | "$ENV{GLFW_LOCATION}/lib" 111 | "$ENV{GLFW_LOCATION}/lib/x64" 112 | "$ENV{GLFW_LOCATION}/lib-msvc110" 113 | "$ENV{GLFW_LOCATION}/lib-vc2012" 114 | PATHS 115 | "$ENV{PROGRAMFILES}/GLFW/lib" 116 | "${OPENGL_LIBRARY_DIR}" 117 | DOC 118 | "The GLFW library" 119 | ) 120 | endif() 121 | else () 122 | if (APPLE) 123 | find_library( GLFW_glfw_LIBRARY glfw 124 | NAMES 125 | glfw 126 | glfw3 127 | HINTS 128 | "${GLFW_LOCATION}/lib" 129 | "${GLFW_LOCATION}/lib/cocoa" 130 | "$ENV{GLFW_LOCATION}/lib" 131 | "$ENV{GLFW_LOCATION}/lib/cocoa" 132 | PATHS 133 | /usr/local/lib 134 | ) 135 | set(GLFW_cocoa_LIBRARY "-framework Cocoa" CACHE STRING "Cocoa framework for OSX") 136 | set(GLFW_corevideo_LIBRARY "-framework CoreVideo" CACHE STRING "CoreVideo framework for OSX") 137 | set(GLFW_iokit_LIBRARY "-framework IOKit" CACHE STRING "IOKit framework for OSX") 138 | else () 139 | # (*)NIX 140 | 141 | find_package(Threads REQUIRED) 142 | 143 | find_package(X11 REQUIRED) 144 | 145 | if(NOT X11_Xrandr_FOUND) 146 | message(FATAL_ERROR "Xrandr library not found - required for GLFW") 147 | endif() 148 | 149 | if(NOT X11_xf86vmode_FOUND) 150 | message(FATAL_ERROR "xf86vmode library not found - required for GLFW") 151 | endif() 152 | 153 | if(NOT X11_Xcursor_FOUND) 154 | message(FATAL_ERROR "Xcursor library not found - required for GLFW") 155 | endif() 156 | 157 | if(NOT X11_Xinerama_FOUND) 158 | message(FATAL_ERROR "Xinerama library not found - required for GLFW") 159 | endif() 160 | 161 | if(NOT X11_Xi_FOUND) 162 | message(FATAL_ERROR "Xi library not found - required for GLFW") 163 | endif() 164 | 165 | list(APPEND GLFW_x11_LIBRARY "${X11_Xrandr_LIB}" "${X11_Xxf86vm_LIB}" "${X11_Xcursor_LIB}" "${X11_Xinerama_LIB}" "${X11_Xi_LIB}" "${X11_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}" -lrt -ldl) 166 | 167 | find_library( GLFW_glfw_LIBRARY 168 | NAMES 169 | glfw 170 | glfw3 171 | HINTS 172 | "${GLFW_LOCATION}/lib" 173 | "$ENV{GLFW_LOCATION}/lib" 174 | "${GLFW_LOCATION}/lib/x11" 175 | "$ENV{GLFW_LOCATION}/lib/x11" 176 | PATHS 177 | /usr/lib64 178 | /usr/lib 179 | /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} 180 | /usr/local/lib64 181 | /usr/local/lib 182 | /usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE} 183 | /usr/openwin/lib 184 | /usr/X11R6/lib 185 | DOC 186 | "The GLFW library" 187 | ) 188 | endif (APPLE) 189 | endif (WIN32) 190 | 191 | set( GLFW_FOUND "NO" ) 192 | 193 | if(GLFW_INCLUDE_DIR) 194 | 195 | if(GLFW_glfw_LIBRARY) 196 | set( GLFW_LIBRARIES "${GLFW_glfw_LIBRARY}" 197 | "${GLFW_x11_LIBRARY}" 198 | "${GLFW_cocoa_LIBRARY}" 199 | "${GLFW_iokit_LIBRARY}" 200 | "${GLFW_corevideo_LIBRARY}" ) 201 | set( GLFW_FOUND "YES" ) 202 | set (GLFW_LIBRARY "${GLFW_LIBRARIES}") 203 | set (GLFW_INCLUDE_PATH "${GLFW_INCLUDE_DIR}") 204 | endif(GLFW_glfw_LIBRARY) 205 | 206 | 207 | # Tease the GLFW_VERSION numbers from the lib headers 208 | function(parseVersion FILENAME VARNAME) 209 | 210 | set(PATTERN "^#define ${VARNAME}.*$") 211 | 212 | file(STRINGS "${GLFW_INCLUDE_DIR}/${FILENAME}" TMP REGEX ${PATTERN}) 213 | 214 | string(REGEX MATCHALL "[0-9]+" TMP ${TMP}) 215 | 216 | set(${VARNAME} ${TMP} PARENT_SCOPE) 217 | 218 | endfunction() 219 | 220 | 221 | if(EXISTS "${GLFW_INCLUDE_DIR}/GL/glfw.h") 222 | 223 | parseVersion(GL/glfw.h GLFW_VERSION_MAJOR) 224 | parseVersion(GL/glfw.h GLFW_VERSION_MINOR) 225 | parseVersion(GL/glfw.h GLFW_VERSION_REVISION) 226 | 227 | elseif(EXISTS "${GLFW_INCLUDE_DIR}/GLFW/glfw3.h") 228 | 229 | parseVersion(GLFW/glfw3.h GLFW_VERSION_MAJOR) 230 | parseVersion(GLFW/glfw3.h GLFW_VERSION_MINOR) 231 | parseVersion(GLFW/glfw3.h GLFW_VERSION_REVISION) 232 | 233 | endif() 234 | 235 | if(${GLFW_VERSION_MAJOR} OR ${GLFW_VERSION_MINOR} OR ${GLFW_VERSION_REVISION}) 236 | set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}.${GLFW_VERSION_REVISION}") 237 | set(GLFW_VERSION_STRING "${GLFW_VERSION}") 238 | mark_as_advanced(GLFW_VERSION) 239 | endif() 240 | 241 | endif(GLFW_INCLUDE_DIR) 242 | 243 | include(FindPackageHandleStandardArgs) 244 | 245 | find_package_handle_standard_args(GLFW 246 | REQUIRED_VARS 247 | GLFW_INCLUDE_DIR 248 | GLFW_LIBRARIES 249 | VERSION_VAR 250 | GLFW_VERSION 251 | ) 252 | 253 | mark_as_advanced( 254 | GLFW_INCLUDE_DIR 255 | GLFW_LIBRARIES 256 | GLFW_glfw_LIBRARY 257 | GLFW_cocoa_LIBRARY 258 | ) 259 | -------------------------------------------------------------------------------- /src/fond.c: -------------------------------------------------------------------------------- 1 | #define STB_TRUETYPE_IMPLEMENTATION 2 | #define STB_RECT_PACK_IMPLEMENTATION 3 | #define STBTT_STATIC 4 | #define STBRP_STATIC 5 | #define LINEFEED 0x000A 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "fond_internal.h" 12 | #include "stb_rect_pack.h" 13 | #include "stb_truetype.h" 14 | 15 | FOND_EXPORT void fond_free(struct fond_font *font){ 16 | if(font->allocated_atlas && font->atlas) 17 | glDeleteTextures(1, &font->atlas); 18 | font->atlas = 0; 19 | font->allocated_atlas = 0; 20 | 21 | if(font->converted_codepoints && font->codepoints) 22 | free(font->codepoints); 23 | font->codepoints = 0; 24 | font->converted_codepoints = 0; 25 | 26 | if(font->chardata) 27 | free(font->chardata); 28 | font->chardata = 0; 29 | 30 | if(font->fontdata) 31 | free(font->fontdata); 32 | font->fontdata = 0; 33 | } 34 | 35 | int fond_pack_range(struct fond_font *font, stbtt_pack_range *range){ 36 | size_t size = 0; 37 | 38 | if(font->codepoints){ 39 | for(; font->codepoints[size]; ++size); 40 | }else if(font->characters){ 41 | if(!fond_decode_utf8((void *)font->characters, &font->codepoints, &size)){ 42 | return 0; 43 | } 44 | 45 | font->converted_codepoints = 1; 46 | }else{ 47 | fond_err(FOND_NO_CHARACTERS_OR_CODEPOINTS); 48 | return 0; 49 | } 50 | 51 | font->chardata = calloc(size, sizeof(stbtt_packedchar)); 52 | if(!font->chardata){ 53 | if(font->chardata) 54 | free(font->chardata); 55 | font->chardata = 0; 56 | fond_err(FOND_OUT_OF_MEMORY); 57 | return 0; 58 | } 59 | 60 | fond_err(FOND_NO_ERROR); 61 | range->font_size = font->size; 62 | range->array_of_unicode_codepoints = (int *)font->codepoints; 63 | range->num_chars = size; 64 | range->chardata_for_range = font->chardata; 65 | return 1; 66 | } 67 | 68 | int fond_load_internal(struct fond_font *font, stbtt_pack_range *range){ 69 | stbtt_pack_context context = {0}; 70 | unsigned char *atlasdata = calloc(font->width*font->height, sizeof(char)); 71 | 72 | #ifdef FOND_WIN 73 | fond_load_glext(); 74 | #endif 75 | 76 | if(!atlasdata){ 77 | fond_err(FOND_OUT_OF_MEMORY); 78 | goto fond_load_internal_cleanup; 79 | } 80 | 81 | font->fontinfo = calloc(1, sizeof(stbtt_fontinfo)); 82 | 83 | if(!stbtt_InitFont(font->fontinfo, font->fontdata, stbtt_GetFontOffsetForIndex(font->fontdata, font->index))){ 84 | fond_err(FOND_FONT_INIT_FAILED); 85 | goto fond_load_internal_cleanup; 86 | } 87 | 88 | if(!stbtt_PackBegin(&context, atlasdata, font->width, font->height, 0, 1, 0)){ 89 | fond_err(FOND_FONT_PACK_FAILED); 90 | goto fond_load_internal_cleanup; 91 | } 92 | 93 | if(0 < font->oversample) 94 | stbtt_PackSetOversampling(&context, font->oversample, font->oversample); 95 | 96 | if(!stbtt_PackFontRanges(&context, font->fontdata, font->index, range, 1)){ 97 | fond_err(FOND_FONT_PACK_FAILED); 98 | goto fond_load_internal_cleanup; 99 | } 100 | 101 | stbtt_PackEnd(&context); 102 | 103 | if(font->atlas == 0){ 104 | font->allocated_atlas = 1; 105 | glGenTextures(1, &font->atlas); 106 | glBindTexture(GL_TEXTURE_2D, font->atlas); 107 | glTexStorage2D(GL_TEXTURE_2D, 8, GL_R8, font->width, font->height); 108 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.65); 109 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 110 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 111 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 112 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 113 | }else{ 114 | glBindTexture(GL_TEXTURE_2D, font->atlas); 115 | } 116 | 117 | GLint unpack; 118 | glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack); 119 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 120 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, font->width, font->height, GL_RED, GL_UNSIGNED_BYTE, atlasdata); 121 | glGenerateMipmap(GL_TEXTURE_2D); 122 | glBindTexture(GL_TEXTURE_2D, 0); 123 | glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); 124 | 125 | if(!fond_check_glerror()){ 126 | fond_err(FOND_OPENGL_ERROR); 127 | goto fond_load_internal_cleanup; 128 | } 129 | 130 | fond_err(FOND_NO_ERROR); 131 | return 1; 132 | 133 | fond_load_internal_cleanup: 134 | if(atlasdata) 135 | free(atlasdata); 136 | 137 | if(font->fontinfo) 138 | free(font->fontinfo); 139 | font->fontinfo = 0; 140 | 141 | if(font->allocated_atlas && font->atlas){ 142 | glDeleteTextures(1, &font->atlas); 143 | font->atlas = 0; 144 | } 145 | font->allocated_atlas = 0; 146 | return 0; 147 | } 148 | 149 | FOND_EXPORT int fond_load(struct fond_font *font){ 150 | stbtt_pack_range range = {0}; 151 | 152 | if(!fond_load_file(font->file, &font->fontdata)){ 153 | fond_err(FOND_FILE_LOAD_FAILED); 154 | goto fond_load_cleanup; 155 | } 156 | 157 | if(!fond_pack_range(font, &range)){ 158 | goto fond_load_cleanup; 159 | } 160 | 161 | if(!fond_load_internal(font, &range)){ 162 | goto fond_load_cleanup; 163 | } 164 | 165 | return 1; 166 | 167 | fond_load_cleanup: 168 | if(font->chardata) 169 | free(font->chardata); 170 | font->chardata = 0; 171 | 172 | if(font->fontdata) 173 | free(font->fontdata); 174 | font->fontdata = 0; 175 | 176 | return 0; 177 | } 178 | 179 | FOND_EXPORT int fond_load_fit(struct fond_font *font, unsigned int max_size){ 180 | stbtt_pack_range range = {0}; 181 | 182 | if(!fond_load_file(font->file, &font->fontdata)){ 183 | fond_err(FOND_FILE_LOAD_FAILED); 184 | goto fond_load_fit_cleanup; 185 | } 186 | 187 | if(!fond_pack_range(font, &range)){ 188 | goto fond_load_fit_cleanup; 189 | } 190 | 191 | if(font->width == 0) font->width = 64; 192 | if(font->height == 0) font->height = 64; 193 | 194 | while(font->width <= max_size 195 | && font->height <= max_size){ 196 | if(fond_load_internal(font, &range)){ 197 | return 1; 198 | } 199 | 200 | switch(errorcode){ 201 | case FOND_FONT_INIT_FAILED: 202 | case FOND_OPENGL_ERROR: 203 | case FOND_OUT_OF_MEMORY: 204 | goto fond_load_fit_cleanup; 205 | case FOND_FONT_PACK_FAILED: 206 | font->width *= 2; 207 | font->height *= 2; 208 | } 209 | } 210 | 211 | fond_err(FOND_SIZE_EXCEEDED); 212 | 213 | fond_load_fit_cleanup: 214 | if(font->chardata) 215 | free(font->chardata); 216 | font->chardata = 0; 217 | 218 | if(font->fontdata) 219 | free(font->fontdata); 220 | font->fontdata = 0; 221 | 222 | return 0; 223 | } 224 | 225 | int fond_codepoint_index(struct fond_font *font, uint32_t glyph){ 226 | for(size_t i=0; font->codepoints[i]; ++i){ 227 | if(font->codepoints[i] == glyph) 228 | return i; 229 | } 230 | return -1; 231 | } 232 | 233 | FOND_EXPORT int fond_compute_u(struct fond_font *font, int32_t *text, size_t size, size_t *_n, GLuint *_vao){ 234 | GLuint vao = 0, vbo = 0, ebo = 0; 235 | 236 | glGenVertexArrays(1, &vao); 237 | glGenBuffers(1, &vbo); 238 | glGenBuffers(1, &ebo); 239 | 240 | glBindVertexArray(vao); 241 | 242 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 243 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (GLvoid*)0); 244 | glEnableVertexAttribArray(0); 245 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (GLvoid*)(2*sizeof(float))); 246 | glEnableVertexAttribArray(1); 247 | 248 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); 249 | 250 | glBindVertexArray(0); 251 | glBindBuffer(GL_ARRAY_BUFFER, 0); 252 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 253 | 254 | if(!fond_check_glerror()){ 255 | glDeleteVertexArrays(1, &vao); 256 | fond_err(FOND_OPENGL_ERROR); 257 | goto fond_compute_cleanup; 258 | } 259 | 260 | if(!fond_update_u(font, text, size, _n, vbo, ebo)){ 261 | goto fond_compute_cleanup; 262 | } 263 | 264 | *_vao = vao; 265 | 266 | fond_compute_cleanup: 267 | if(vbo) 268 | glDeleteBuffers(1, &vbo); 269 | 270 | if(ebo) 271 | glDeleteBuffers(1, &ebo); 272 | 273 | return (errorcode == FOND_NO_ERROR); 274 | } 275 | 276 | FOND_EXPORT int fond_update_u(struct fond_font *font, int32_t *text, size_t size, size_t *_n, GLuint vbo, GLuint ebo){ 277 | GLfloat *vert = 0; 278 | GLuint *ind = 0; 279 | float x = 0.0, y = 0.0; 280 | 281 | if(!font->chardata){ 282 | fond_err(FOND_NOT_LOADED); 283 | goto fond_update_cleanup; 284 | } 285 | 286 | vert = calloc(4*4*size, sizeof(GLfloat)); 287 | ind = calloc(2*3*size, sizeof(GLuint)); 288 | if(!vert || !ind){ 289 | fond_err(FOND_OUT_OF_MEMORY); 290 | goto fond_update_cleanup; 291 | } 292 | 293 | int ascent, descent, linegap; 294 | stbtt_GetFontVMetrics(font->fontinfo, &ascent, &descent, &linegap); 295 | float scale = font->size / (ascent - descent); 296 | float vskip = scale*(linegap+ascent); 297 | 298 | for(size_t i=0; i0) 308 | x += stbtt_GetCodepointKernAdvance(font->fontinfo, text[i-1], text[i]) * scale; 309 | stbtt_GetPackedQuad((stbtt_packedchar *)font->chardata, font->width, font->height, index, &x, &y, &quad, 1); 310 | int vi = 4*4*i; 311 | if(text[i] == LINEFEED){ 312 | vert[vi++] = quad.x0; vert[vi++] = -quad.y1; vert[vi++] = 0; vert[vi++] = 0; 313 | vert[vi++] = quad.x0; vert[vi++] = -quad.y0; vert[vi++] = 0; vert[vi++] = 0; 314 | vert[vi++] = quad.x1; vert[vi++] = -quad.y0; vert[vi++] = 0; vert[vi++] = 0; 315 | vert[vi++] = quad.x1; vert[vi++] = -quad.y1; vert[vi++] = 0; vert[vi++] = 0; 316 | y += vskip; 317 | x = 0; 318 | }else{ 319 | vert[vi++] = quad.x0; vert[vi++] = -quad.y1; vert[vi++] = quad.s0; vert[vi++] = quad.t1; 320 | vert[vi++] = quad.x0; vert[vi++] = -quad.y0; vert[vi++] = quad.s0; vert[vi++] = quad.t0; 321 | vert[vi++] = quad.x1; vert[vi++] = -quad.y0; vert[vi++] = quad.s1; vert[vi++] = quad.t0; 322 | vert[vi++] = quad.x1; vert[vi++] = -quad.y1; vert[vi++] = quad.s1; vert[vi++] = quad.t1; 323 | } 324 | 325 | int ii = 2*3*i; 326 | ind[ii++] = i*4+0; ind[ii++] = i*4+3; ind[ii++] = i*4+1; 327 | ind[ii++] = i*4+1; ind[ii++] = i*4+3; ind[ii++] = i*4+2; 328 | } 329 | 330 | // This is done as a sanity option, as otherwise we might rebind the 331 | // buffers of a bound VAO in the outermost scope. Properly doing this 332 | // would require getting the currently bound values and restoring and 333 | // all that, but I think it's fine to not do that here. 334 | glBindVertexArray(0); 335 | 336 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 337 | glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*size, vert, GL_DYNAMIC_DRAW); 338 | glBindBuffer(GL_ARRAY_BUFFER, 0); 339 | 340 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); 341 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*size, ind, GL_DYNAMIC_DRAW); 342 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 343 | 344 | if(!fond_check_glerror()){ 345 | fond_err(FOND_OPENGL_ERROR); 346 | goto fond_update_cleanup; 347 | } 348 | 349 | fond_err(FOND_NO_ERROR); 350 | *_n = 2*3*size; 351 | 352 | fond_update_cleanup: 353 | if(vert) 354 | free(vert); 355 | 356 | if(ind) 357 | free(ind); 358 | 359 | return (errorcode == FOND_NO_ERROR); 360 | } 361 | 362 | FOND_EXPORT int fond_compute_extent_u(struct fond_font *font, int32_t *text, size_t size, struct fond_extent *extent){ 363 | int ascent, descent, linegap, advance, bearing; 364 | float x = 0.0, y = 0.0; 365 | stbtt_GetFontVMetrics(font->fontinfo, &ascent, &descent, &linegap); 366 | float scale = font->size / (ascent - descent); 367 | float vskip = linegap+ascent; 368 | // FIXME: left extent is currently incorrect. 369 | extent->l = 0; 370 | extent->r = 0; 371 | extent->t = ascent; 372 | extent->b = -descent; 373 | extent->gap = linegap; 374 | 375 | stbtt_aligned_quad quad = {0}; 376 | for(size_t i=0; i0) 385 | x += stbtt_GetCodepointKernAdvance(font->fontinfo, text[i-1], text[i]) * scale; 386 | stbtt_GetPackedQuad((stbtt_packedchar *)font->chardata, font->width, font->height, index, &x, &y, &quad, 0); 387 | 388 | if(text[i] == LINEFEED){ 389 | extent->b -= vskip; 390 | if(extent->r < x) extent->r = x; 391 | x = 0; 392 | } 393 | } 394 | if(x < quad.x0) x = quad.x0; 395 | if(x < quad.x1) x = quad.x1; 396 | if(extent->r < x) extent->r = x; 397 | 398 | fond_err(FOND_NO_ERROR); 399 | extent->t *= scale; 400 | extent->b *= scale; 401 | extent->gap *= scale; 402 | return 1; 403 | } 404 | -------------------------------------------------------------------------------- /src/fond.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBFOND_H__ 2 | #define __LIBFOND_H__ 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #ifdef _MSC_VER 8 | # ifdef FOND_STATIC_DEFINE 9 | # define FOND_EXPORT 10 | # else 11 | # ifndef FOND_EXPORT 12 | # define FOND_EXPORT __declspec(dllexport) 13 | # endif 14 | # endif 15 | #else 16 | # define FOND_EXPORT 17 | #endif 18 | #include 19 | #include 20 | 21 | // This enum contains all possible error codes 22 | // that libfond can produce. 23 | // 24 | // See fond_error 25 | // See fond_error_string 26 | FOND_EXPORT enum fond_error{ 27 | // Everything is OK. 28 | FOND_NO_ERROR, 29 | // The font file could not be read. Most likely 30 | // it doesn't exist or the permission is denied. 31 | FOND_FILE_LOAD_FAILED, 32 | // An allocation failed, probably due to OOM. 33 | FOND_OUT_OF_MEMORY, 34 | // Failed to pack the font into an atlas. 35 | // This most likely means that the atlas' size 36 | // is too small. 37 | FOND_FONT_PACK_FAILED, 38 | // Failed to parse the font file's information. 39 | // It's likely that the file you gave was not 40 | // a TTF. 41 | FOND_FONT_INIT_FAILED, 42 | // OpenGL signalled an error. Check stderr for 43 | // more information. 44 | FOND_OPENGL_ERROR, 45 | // The maximum size on fond_load_fit was reached. 46 | FOND_SIZE_EXCEEDED, 47 | // A render or compute function was called when 48 | // the font was not properly loaded yet. 49 | FOND_NOT_LOADED, 50 | // The UTF8 string could not be converted as it 51 | // is malformatted. 52 | FOND_UTF8_CONVERSION_ERROR, 53 | // An attempt was made to render/compute a glyph 54 | // that was not included in the list of glyphs 55 | // when the font was loaded. 56 | FOND_UNLOADED_GLYPH, 57 | // The fond_font struct did contain neither a 58 | // list of characters nor a list of codepoints. 59 | FOND_NO_CHARACTERS_OR_CODEPOINTS 60 | }; 61 | 62 | // This is the primary struct that contains all 63 | // relevant information about a font. You must 64 | // allocate this struct yourself and make sure 65 | // that it is zeroed out before you do anything 66 | // with it. 67 | // Either stack allocate it with ={0}, or use 68 | // calloc. Not zeroing out will land you in a 69 | // world of pain. 70 | // 71 | // See fond_free 72 | // See fond_load 73 | // See fond_load_fit 74 | // See fond_compute 75 | // See fond_compute_u 76 | // See fond_compute_extent 77 | // See fond_compute_extent_u 78 | FOND_EXPORT struct fond_font{ 79 | // Path to the TTF file. 80 | char *file; 81 | // The index of the font within the TTF file. 82 | // You probably don't need to set this. 83 | int index; 84 | // The vertical font size in pixels. If you 85 | // render it above this resolution, you'll 86 | // get a blurry mess. 87 | float size; 88 | // A UTF8 encoded string of characters that 89 | // this font instance will be able to render. 90 | // Must be null-terminated. 91 | char *characters; 92 | // An array of Unicode codepoints that this 93 | // font instance will be able to render. Must 94 | // be null-terminated. This is automatically 95 | // filled in for you, if it is NULL and the 96 | // characters field is provided instead. 97 | int32_t *codepoints; 98 | // The width of the glyph texture atlas. 99 | unsigned int width; 100 | // The height of the glyph texture atlas. 101 | unsigned int height; 102 | // How much oversampling should be done. 103 | // Higher oversampling might improve the 104 | // quality of the rendering, but will need 105 | // a much bigger atlas size: 106 | // width*oversampling,height*oversampling 107 | unsigned int oversample; 108 | // The OpenGL texture ID for the atlas. 109 | unsigned int atlas; 110 | // Internal data. 111 | void *fontdata; 112 | void *chardata; 113 | void *fontinfo; 114 | int converted_codepoints; 115 | int allocated_atlas; 116 | }; 117 | 118 | // This struct allows for convenience in 119 | // rendering, as it will render text for you 120 | // into a texture, which you can then render 121 | // like any other. Thus you won't need to 122 | // handle the actual rendering logic yourself. 123 | // 124 | // See fond_free_buffer 125 | // See fond_load_buffer 126 | // See fond_render 127 | // See fond_render_u 128 | FOND_EXPORT struct fond_buffer{ 129 | // Pointer to the font that it renders. 130 | struct fond_font *font; 131 | // The OpenGL texture ID to which this 132 | // buffer renders to. 133 | unsigned int texture; 134 | // The width of the texture. 135 | unsigned int width; 136 | // The height of the texture. 137 | unsigned int height; 138 | // Internal data. 139 | unsigned int program; 140 | unsigned int framebuffer; 141 | unsigned int vao; 142 | unsigned int vbo; 143 | unsigned int ebo; 144 | }; 145 | 146 | // This struct contains information about 147 | // the extents of a text. 148 | // 149 | // See fond_compute_extent 150 | // See fond_compute_extent_u 151 | FOND_EXPORT struct fond_extent{ 152 | // How far to the left the text extends 153 | // from zero. 154 | float l; 155 | // How far to the right the text extends 156 | // from zero. 157 | float r; 158 | // How far up the text extends from its 159 | // baseline. 160 | float t; 161 | // How far down the text extends from 162 | // its baseline. 163 | float b; 164 | // The gap between lines of the text. 165 | float gap; 166 | }; 167 | 168 | // Most functions in this API return an int, 169 | // which can be ither 1 or 0, with the former 170 | // representing success and the latter 171 | // failure. On failure, you should check 172 | // fond_error to see what went wrong. 173 | 174 | // Free all the data that was allocated 175 | // into the struct by fond_load*. This 176 | // will /not/ free the characters array, 177 | // the file array, or the codepoints array 178 | // if the codepoints array was not computed 179 | // by fond_load*. It will also not free the 180 | // texture atlas if it was not alloced by 181 | // fond_load*. 182 | FOND_EXPORT void fond_free(struct fond_font *font); 183 | 184 | // Load the font struct and allocate the 185 | // necessary OpenGL data. The texture atlas 186 | // is not allocated if the font's atlas field 187 | // is already set. It is however always filled 188 | // via glSubImage2D. The bit depth of the pixel 189 | // values is only 255, and only the red channel 190 | // is filled, so a texture with internal format 191 | // of GL_R8 will be created for you if you 192 | // don't specify your own. 193 | // The following fields must be set in the 194 | // struct: 195 | // file 196 | // size 197 | // width 198 | // height 199 | // characters or codepoints 200 | FOND_EXPORT int fond_load(struct fond_font *font); 201 | 202 | // Load the font struct, attempting to fit 203 | // an atlas automatically. This may not 204 | // result in the most compact atlas possible. 205 | // max_size is the maximum size of the width 206 | // or height that can be reached before it 207 | // gives up. The following fields must be set 208 | // in the struct: 209 | // file 210 | // size 211 | // characters or codepoints 212 | FOND_EXPORT int fond_load_fit(struct fond_font *font, unsigned int max_size); 213 | 214 | // Compute the Vertex Array Object to render 215 | // the given text. Here, n and vao are output 216 | // arguments, containing the number of elements 217 | // and the OpenGL VAO ID respectively. 218 | // The text must be UTF8 encoded and null- 219 | // terminated. The VAO packs two arrays, one 220 | // at location 0 and one at 1, with both being 221 | // vec2s. The first being the vertex coordinates 222 | // and the second being the texture coordinates. 223 | // The vertex coordinates start at 0 and increase 224 | // in x and y as per the font's size. You are 225 | // responsible for scaling it as appropriate 226 | // for your display. 227 | // The texture coordinates are for the font's 228 | // atlas texture. 229 | // The triangles are defined with their vertices 230 | // in counter-clockwise (CCW) order, meaning 231 | // that if you apply cull-face, you need to have 232 | // front-faces be set to CCW, which should be 233 | // the default. 234 | // If the text contains a Linefeed character 235 | // (U+000A) a new line is started automatically 236 | // by resetting X to 0 and decreasing Y by the 237 | // necessary height for a new line. 238 | // 239 | // The VAO and necessary VBOs are allocated 240 | // automatically for you and then filled in as 241 | // per fond_update. 242 | FOND_EXPORT int fond_compute(struct fond_font *font, char *text, size_t *n, unsigned int *vao); 243 | 244 | // Same as fond_compute, but taking an UTF32 245 | // encoded string of codepoints and its size. 246 | FOND_EXPORT int fond_compute_u(struct fond_font *font, int32_t *text, size_t size, size_t *n, unsigned int *vao); 247 | 248 | // Update the given vertex buffer and element 249 | // buffers to contain the necessary data to draw 250 | // the given text. 251 | // The EBO must be bound to a VAO as a 252 | // GL_ELEMENT_ARRAY_BUFFER and the VBO as a 253 | // GL_ARRAY_BUFFER. The VBO contains GLfloats and 254 | // the EBO contains GLuints. The VBO packs two 255 | // distinct values as described in fond_compute. 256 | // They are stored alternatingly in the buffer, 257 | // meaning that you should bind the buffer to a 258 | // VAO like this: 259 | // 260 | // glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (GLvoid*)0); 261 | // glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (GLvoid*)(2*sizeof(float))); 262 | // 263 | // The data is stored in the buffers using 264 | // DYNAMIC_DRAW, meaning they should be able to 265 | // be updated frequently enough. 266 | // 267 | // Note that the GL buffer and vertex array 268 | // bindings are modified by this function. You 269 | // should thus not expect previously bound values 270 | // to still be the same after this function 271 | // returns. 272 | FOND_EXPORT int fond_update(struct fond_font *font, char *text, size_t *n, unsigned int vbo, unsigned int ebo); 273 | 274 | // Same as fond_update, but taking an UTF32 275 | // encoded string of codepoints and its size. 276 | FOND_EXPORT int fond_update_u(struct fond_font *font, int32_t *text, size_t size, size_t *n, unsigned int vbo, unsigned int ebo); 277 | 278 | // Compute the extent of the given text. 279 | // You must allocate the extent struct yourself 280 | // and make sure it is zeroed out. 281 | FOND_EXPORT int fond_compute_extent(struct fond_font *font, char *text, struct fond_extent *extent); 282 | 283 | // Same as fond_compute_extent, but taking an 284 | // UTF32 encoded string of codepoints and its 285 | // size. 286 | FOND_EXPORT int fond_compute_extent_u(struct fond_font *font, int32_t *text, size_t size, struct fond_extent *extent); 287 | 288 | // Free all the data that was allocated 289 | // into the struct by fond_load_buffer. This 290 | // will /not/ free the font struct. 291 | FOND_EXPORT void fond_free_buffer(struct fond_buffer *buffer); 292 | 293 | // Load the buffer struct and allocate the 294 | // necessary OpenGL data. 295 | // The following fields must be set in the 296 | // struct: 297 | // font 298 | // width 299 | // height 300 | FOND_EXPORT int fond_load_buffer(struct fond_buffer *buffer); 301 | 302 | // Render the given text to the buffer's 303 | // texture. The text will be rendered at the 304 | // given offset, with x and y being in pixels. 305 | // color can be either 0 for white text, or 306 | // an array of four floats, representing RGBA 307 | // of the text's colour in that order. 308 | FOND_EXPORT int fond_render(struct fond_buffer *buffer, char *text, float x, float y, float *color); 309 | 310 | // Same as fond_render, but taking an UTF32 311 | // encoded string of codepoints and its size. 312 | FOND_EXPORT int fond_render_u(struct fond_buffer *buffer, int32_t *text, size_t size, float x, float y, float *color); 313 | 314 | // Decode the given UTF8 string into an UTF32 315 | // string. The resulting string is put into 316 | // decoded, and its size is put into size. 317 | // This is used by the non _u functions to 318 | // decode the string. You may want to use this 319 | // internally, if you need to re-use the same 320 | // string often and don't wnat to pay the 321 | // conversion cost. 322 | FOND_EXPORT int fond_decode_utf8(void *string, int32_t **decoded, size_t *size); 323 | 324 | // Return the current error code. 325 | FOND_EXPORT enum fond_error fond_error(); 326 | 327 | // Return a string for a human-readable error 328 | // message of the given error code. 329 | FOND_EXPORT char *fond_error_string(enum fond_error error); 330 | 331 | #ifdef __cplusplus 332 | } 333 | #endif 334 | #endif 335 | -------------------------------------------------------------------------------- /src/stb_rect_pack.h: -------------------------------------------------------------------------------- 1 | // stb_rect_pack.h - v0.11 - public domain - rectangle packing 2 | // Sean Barrett 2014 3 | // 4 | // Useful for e.g. packing rectangular textures into an atlas. 5 | // Does not do rotation. 6 | // 7 | // Not necessarily the awesomest packing method, but better than 8 | // the totally naive one in stb_truetype (which is primarily what 9 | // this is meant to replace). 10 | // 11 | // Has only had a few tests run, may have issues. 12 | // 13 | // More docs to come. 14 | // 15 | // No memory allocations; uses qsort() and assert() from stdlib. 16 | // Can override those by defining STBRP_SORT and STBRP_ASSERT. 17 | // 18 | // This library currently uses the Skyline Bottom-Left algorithm. 19 | // 20 | // Please note: better rectangle packers are welcome! Please 21 | // implement them to the same API, but with a different init 22 | // function. 23 | // 24 | // Credits 25 | // 26 | // Library 27 | // Sean Barrett 28 | // Minor features 29 | // Martins Mozeiko 30 | // github:IntellectualKitty 31 | // 32 | // Bugfixes / warning fixes 33 | // Jeremy Jaussaud 34 | // 35 | // Version history: 36 | // 37 | // 0.11 (2017-03-03) return packing success/fail result 38 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings 39 | // 0.09 (2016-08-27) fix compiler warnings 40 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) 41 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) 42 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort 43 | // 0.05: added STBRP_ASSERT to allow replacing assert 44 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support 45 | // 0.01: initial release 46 | // 47 | // LICENSE 48 | // 49 | // See end of file for license information. 50 | 51 | ////////////////////////////////////////////////////////////////////////////// 52 | // 53 | // INCLUDE SECTION 54 | // 55 | 56 | #ifndef STB_INCLUDE_STB_RECT_PACK_H 57 | #define STB_INCLUDE_STB_RECT_PACK_H 58 | 59 | #define STB_RECT_PACK_VERSION 1 60 | 61 | #ifdef STBRP_STATIC 62 | #define STBRP_DEF static 63 | #else 64 | #define STBRP_DEF extern 65 | #endif 66 | 67 | #ifdef __cplusplus 68 | extern "C" { 69 | #endif 70 | 71 | typedef struct stbrp_context stbrp_context; 72 | typedef struct stbrp_node stbrp_node; 73 | typedef struct stbrp_rect stbrp_rect; 74 | 75 | #ifdef STBRP_LARGE_RECTS 76 | typedef int stbrp_coord; 77 | #else 78 | typedef unsigned short stbrp_coord; 79 | #endif 80 | 81 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); 82 | // Assign packed locations to rectangles. The rectangles are of type 83 | // 'stbrp_rect' defined below, stored in the array 'rects', and there 84 | // are 'num_rects' many of them. 85 | // 86 | // Rectangles which are successfully packed have the 'was_packed' flag 87 | // set to a non-zero value and 'x' and 'y' store the minimum location 88 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left 89 | // if you imagine y increasing downwards). Rectangles which do not fit 90 | // have the 'was_packed' flag set to 0. 91 | // 92 | // You should not try to access the 'rects' array from another thread 93 | // while this function is running, as the function temporarily reorders 94 | // the array while it executes. 95 | // 96 | // To pack into another rectangle, you need to call stbrp_init_target 97 | // again. To continue packing into the same rectangle, you can call 98 | // this function again. Calling this multiple times with multiple rect 99 | // arrays will probably produce worse packing results than calling it 100 | // a single time with the full rectangle array, but the option is 101 | // available. 102 | // 103 | // The function returns 1 if all of the rectangles were successfully 104 | // packed and 0 otherwise. 105 | 106 | struct stbrp_rect 107 | { 108 | // reserved for your use: 109 | int id; 110 | 111 | // input: 112 | stbrp_coord w, h; 113 | 114 | // output: 115 | stbrp_coord x, y; 116 | int was_packed; // non-zero if valid packing 117 | 118 | }; // 16 bytes, nominally 119 | 120 | 121 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); 122 | // Initialize a rectangle packer to: 123 | // pack a rectangle that is 'width' by 'height' in dimensions 124 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long 125 | // 126 | // You must call this function every time you start packing into a new target. 127 | // 128 | // There is no "shutdown" function. The 'nodes' memory must stay valid for 129 | // the following stbrp_pack_rects() call (or calls), but can be freed after 130 | // the call (or calls) finish. 131 | // 132 | // Note: to guarantee best results, either: 133 | // 1. make sure 'num_nodes' >= 'width' 134 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' 135 | // 136 | // If you don't do either of the above things, widths will be quantized to multiples 137 | // of small integers to guarantee the algorithm doesn't run out of temporary storage. 138 | // 139 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm 140 | // may run out of temporary storage and be unable to pack some rectangles. 141 | 142 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); 143 | // Optionally call this function after init but before doing any packing to 144 | // change the handling of the out-of-temp-memory scenario, described above. 145 | // If you call init again, this will be reset to the default (false). 146 | 147 | 148 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); 149 | // Optionally select which packing heuristic the library should use. Different 150 | // heuristics will produce better/worse results for different data sets. 151 | // If you call init again, this will be reset to the default. 152 | 153 | enum 154 | { 155 | STBRP_HEURISTIC_Skyline_default=0, 156 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, 157 | STBRP_HEURISTIC_Skyline_BF_sortHeight 158 | }; 159 | 160 | 161 | ////////////////////////////////////////////////////////////////////////////// 162 | // 163 | // the details of the following structures don't matter to you, but they must 164 | // be visible so you can handle the memory allocations for them 165 | 166 | struct stbrp_node 167 | { 168 | stbrp_coord x,y; 169 | stbrp_node *next; 170 | }; 171 | 172 | struct stbrp_context 173 | { 174 | int width; 175 | int height; 176 | int align; 177 | int init_mode; 178 | int heuristic; 179 | int num_nodes; 180 | stbrp_node *active_head; 181 | stbrp_node *free_head; 182 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' 183 | }; 184 | 185 | #ifdef __cplusplus 186 | } 187 | #endif 188 | 189 | #endif 190 | 191 | ////////////////////////////////////////////////////////////////////////////// 192 | // 193 | // IMPLEMENTATION SECTION 194 | // 195 | 196 | #ifdef STB_RECT_PACK_IMPLEMENTATION 197 | #ifndef STBRP_SORT 198 | #include 199 | #define STBRP_SORT qsort 200 | #endif 201 | 202 | #ifndef STBRP_ASSERT 203 | #include 204 | #define STBRP_ASSERT assert 205 | #endif 206 | 207 | #ifdef _MSC_VER 208 | #define STBRP__NOTUSED(v) (void)(v) 209 | #else 210 | #define STBRP__NOTUSED(v) (void)sizeof(v) 211 | #endif 212 | 213 | enum 214 | { 215 | STBRP__INIT_skyline = 1 216 | }; 217 | 218 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) 219 | { 220 | switch (context->init_mode) { 221 | case STBRP__INIT_skyline: 222 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); 223 | context->heuristic = heuristic; 224 | break; 225 | default: 226 | STBRP_ASSERT(0); 227 | } 228 | } 229 | 230 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) 231 | { 232 | if (allow_out_of_mem) 233 | // if it's ok to run out of memory, then don't bother aligning them; 234 | // this gives better packing, but may fail due to OOM (even though 235 | // the rectangles easily fit). @TODO a smarter approach would be to only 236 | // quantize once we've hit OOM, then we could get rid of this parameter. 237 | context->align = 1; 238 | else { 239 | // if it's not ok to run out of memory, then quantize the widths 240 | // so that num_nodes is always enough nodes. 241 | // 242 | // I.e. num_nodes * align >= width 243 | // align >= width / num_nodes 244 | // align = ceil(width/num_nodes) 245 | 246 | context->align = (context->width + context->num_nodes-1) / context->num_nodes; 247 | } 248 | } 249 | 250 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) 251 | { 252 | int i; 253 | #ifndef STBRP_LARGE_RECTS 254 | STBRP_ASSERT(width <= 0xffff && height <= 0xffff); 255 | #endif 256 | 257 | for (i=0; i < num_nodes-1; ++i) 258 | nodes[i].next = &nodes[i+1]; 259 | nodes[i].next = NULL; 260 | context->init_mode = STBRP__INIT_skyline; 261 | context->heuristic = STBRP_HEURISTIC_Skyline_default; 262 | context->free_head = &nodes[0]; 263 | context->active_head = &context->extra[0]; 264 | context->width = width; 265 | context->height = height; 266 | context->num_nodes = num_nodes; 267 | stbrp_setup_allow_out_of_mem(context, 0); 268 | 269 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) 270 | context->extra[0].x = 0; 271 | context->extra[0].y = 0; 272 | context->extra[0].next = &context->extra[1]; 273 | context->extra[1].x = (stbrp_coord) width; 274 | #ifdef STBRP_LARGE_RECTS 275 | context->extra[1].y = (1<<30); 276 | #else 277 | context->extra[1].y = 65535; 278 | #endif 279 | context->extra[1].next = NULL; 280 | } 281 | 282 | // find minimum y position if it starts at x1 283 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) 284 | { 285 | stbrp_node *node = first; 286 | int x1 = x0 + width; 287 | int min_y, visited_width, waste_area; 288 | 289 | STBRP__NOTUSED(c); 290 | 291 | STBRP_ASSERT(first->x <= x0); 292 | 293 | #if 0 294 | // skip in case we're past the node 295 | while (node->next->x <= x0) 296 | ++node; 297 | #else 298 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency 299 | #endif 300 | 301 | STBRP_ASSERT(node->x <= x0); 302 | 303 | min_y = 0; 304 | waste_area = 0; 305 | visited_width = 0; 306 | while (node->x < x1) { 307 | if (node->y > min_y) { 308 | // raise min_y higher. 309 | // we've accounted for all waste up to min_y, 310 | // but we'll now add more waste for everything we've visted 311 | waste_area += visited_width * (node->y - min_y); 312 | min_y = node->y; 313 | // the first time through, visited_width might be reduced 314 | if (node->x < x0) 315 | visited_width += node->next->x - x0; 316 | else 317 | visited_width += node->next->x - node->x; 318 | } else { 319 | // add waste area 320 | int under_width = node->next->x - node->x; 321 | if (under_width + visited_width > width) 322 | under_width = width - visited_width; 323 | waste_area += under_width * (min_y - node->y); 324 | visited_width += under_width; 325 | } 326 | node = node->next; 327 | } 328 | 329 | *pwaste = waste_area; 330 | return min_y; 331 | } 332 | 333 | typedef struct 334 | { 335 | int x,y; 336 | stbrp_node **prev_link; 337 | } stbrp__findresult; 338 | 339 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) 340 | { 341 | int best_waste = (1<<30), best_x, best_y = (1 << 30); 342 | stbrp__findresult fr; 343 | stbrp_node **prev, *node, *tail, **best = NULL; 344 | 345 | // align to multiple of c->align 346 | width = (width + c->align - 1); 347 | width -= width % c->align; 348 | STBRP_ASSERT(width % c->align == 0); 349 | 350 | node = c->active_head; 351 | prev = &c->active_head; 352 | while (node->x + width <= c->width) { 353 | int y,waste; 354 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); 355 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL 356 | // bottom left 357 | if (y < best_y) { 358 | best_y = y; 359 | best = prev; 360 | } 361 | } else { 362 | // best-fit 363 | if (y + height <= c->height) { 364 | // can only use it if it first vertically 365 | if (y < best_y || (y == best_y && waste < best_waste)) { 366 | best_y = y; 367 | best_waste = waste; 368 | best = prev; 369 | } 370 | } 371 | } 372 | prev = &node->next; 373 | node = node->next; 374 | } 375 | 376 | best_x = (best == NULL) ? 0 : (*best)->x; 377 | 378 | // if doing best-fit (BF), we also have to try aligning right edge to each node position 379 | // 380 | // e.g, if fitting 381 | // 382 | // ____________________ 383 | // |____________________| 384 | // 385 | // into 386 | // 387 | // | | 388 | // | ____________| 389 | // |____________| 390 | // 391 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned 392 | // 393 | // This makes BF take about 2x the time 394 | 395 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { 396 | tail = c->active_head; 397 | node = c->active_head; 398 | prev = &c->active_head; 399 | // find first node that's admissible 400 | while (tail->x < width) 401 | tail = tail->next; 402 | while (tail) { 403 | int xpos = tail->x - width; 404 | int y,waste; 405 | STBRP_ASSERT(xpos >= 0); 406 | // find the left position that matches this 407 | while (node->next->x <= xpos) { 408 | prev = &node->next; 409 | node = node->next; 410 | } 411 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); 412 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); 413 | if (y + height < c->height) { 414 | if (y <= best_y) { 415 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 416 | best_x = xpos; 417 | STBRP_ASSERT(y <= best_y); 418 | best_y = y; 419 | best_waste = waste; 420 | best = prev; 421 | } 422 | } 423 | } 424 | tail = tail->next; 425 | } 426 | } 427 | 428 | fr.prev_link = best; 429 | fr.x = best_x; 430 | fr.y = best_y; 431 | return fr; 432 | } 433 | 434 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) 435 | { 436 | // find best position according to heuristic 437 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); 438 | stbrp_node *node, *cur; 439 | 440 | // bail if: 441 | // 1. it failed 442 | // 2. the best node doesn't fit (we don't always check this) 443 | // 3. we're out of memory 444 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { 445 | res.prev_link = NULL; 446 | return res; 447 | } 448 | 449 | // on success, create new node 450 | node = context->free_head; 451 | node->x = (stbrp_coord) res.x; 452 | node->y = (stbrp_coord) (res.y + height); 453 | 454 | context->free_head = node->next; 455 | 456 | // insert the new node into the right starting point, and 457 | // let 'cur' point to the remaining nodes needing to be 458 | // stiched back in 459 | 460 | cur = *res.prev_link; 461 | if (cur->x < res.x) { 462 | // preserve the existing one, so start testing with the next one 463 | stbrp_node *next = cur->next; 464 | cur->next = node; 465 | cur = next; 466 | } else { 467 | *res.prev_link = node; 468 | } 469 | 470 | // from here, traverse cur and free the nodes, until we get to one 471 | // that shouldn't be freed 472 | while (cur->next && cur->next->x <= res.x + width) { 473 | stbrp_node *next = cur->next; 474 | // move the current node to the free list 475 | cur->next = context->free_head; 476 | context->free_head = cur; 477 | cur = next; 478 | } 479 | 480 | // stitch the list back in 481 | node->next = cur; 482 | 483 | if (cur->x < res.x + width) 484 | cur->x = (stbrp_coord) (res.x + width); 485 | 486 | #ifdef _DEBUG 487 | cur = context->active_head; 488 | while (cur->x < context->width) { 489 | STBRP_ASSERT(cur->x < cur->next->x); 490 | cur = cur->next; 491 | } 492 | STBRP_ASSERT(cur->next == NULL); 493 | 494 | { 495 | stbrp_node *L1 = NULL, *L2 = NULL; 496 | int count=0; 497 | cur = context->active_head; 498 | while (cur) { 499 | L1 = cur; 500 | cur = cur->next; 501 | ++count; 502 | } 503 | cur = context->free_head; 504 | while (cur) { 505 | L2 = cur; 506 | cur = cur->next; 507 | ++count; 508 | } 509 | STBRP_ASSERT(count == context->num_nodes+2); 510 | } 511 | #endif 512 | 513 | return res; 514 | } 515 | 516 | static int rect_height_compare(const void *a, const void *b) 517 | { 518 | const stbrp_rect *p = (const stbrp_rect *) a; 519 | const stbrp_rect *q = (const stbrp_rect *) b; 520 | if (p->h > q->h) 521 | return -1; 522 | if (p->h < q->h) 523 | return 1; 524 | return (p->w > q->w) ? -1 : (p->w < q->w); 525 | } 526 | 527 | static int rect_original_order(const void *a, const void *b) 528 | { 529 | const stbrp_rect *p = (const stbrp_rect *) a; 530 | const stbrp_rect *q = (const stbrp_rect *) b; 531 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 532 | } 533 | 534 | #ifdef STBRP_LARGE_RECTS 535 | #define STBRP__MAXVAL 0xffffffff 536 | #else 537 | #define STBRP__MAXVAL 0xffff 538 | #endif 539 | 540 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) 541 | { 542 | int i, all_rects_packed = 1; 543 | 544 | // we use the 'was_packed' field internally to allow sorting/unsorting 545 | for (i=0; i < num_rects; ++i) { 546 | rects[i].was_packed = i; 547 | #ifndef STBRP_LARGE_RECTS 548 | STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff); 549 | #endif 550 | } 551 | 552 | // sort according to heuristic 553 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); 554 | 555 | for (i=0; i < num_rects; ++i) { 556 | if (rects[i].w == 0 || rects[i].h == 0) { 557 | rects[i].x = rects[i].y = 0; // empty rect needs no space 558 | } else { 559 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 560 | if (fr.prev_link) { 561 | rects[i].x = (stbrp_coord) fr.x; 562 | rects[i].y = (stbrp_coord) fr.y; 563 | } else { 564 | rects[i].x = rects[i].y = STBRP__MAXVAL; 565 | } 566 | } 567 | } 568 | 569 | // unsort 570 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); 571 | 572 | // set was_packed flags and all_rects_packed status 573 | for (i=0; i < num_rects; ++i) { 574 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); 575 | if (!rects[i].was_packed) 576 | all_rects_packed = 0; 577 | } 578 | 579 | // return the all_rects_packed status 580 | return all_rects_packed; 581 | } 582 | #endif 583 | 584 | /* 585 | ------------------------------------------------------------------------------ 586 | This software is available under 2 licenses -- choose whichever you prefer. 587 | ------------------------------------------------------------------------------ 588 | ALTERNATIVE A - MIT License 589 | Copyright (c) 2017 Sean Barrett 590 | Permission is hereby granted, free of charge, to any person obtaining a copy of 591 | this software and associated documentation files (the "Software"), to deal in 592 | the Software without restriction, including without limitation the rights to 593 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 594 | of the Software, and to permit persons to whom the Software is furnished to do 595 | so, subject to the following conditions: 596 | The above copyright notice and this permission notice shall be included in all 597 | copies or substantial portions of the Software. 598 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 599 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 600 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 601 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 602 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 603 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 604 | SOFTWARE. 605 | ------------------------------------------------------------------------------ 606 | ALTERNATIVE B - Public Domain (www.unlicense.org) 607 | This is free and unencumbered software released into the public domain. 608 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 609 | software, either in source code form or as a compiled binary, for any purpose, 610 | commercial or non-commercial, and by any means. 611 | In jurisdictions that recognize copyright laws, the author or authors of this 612 | software dedicate any and all copyright interest in the software to the public 613 | domain. We make this dedication for the benefit of the public at large and to 614 | the detriment of our heirs and successors. We intend this dedication to be an 615 | overt act of relinquishment in perpetuity of all present and future rights to 616 | this software under copyright law. 617 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 618 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 619 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 620 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 621 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 622 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 623 | ------------------------------------------------------------------------------ 624 | */ 625 | -------------------------------------------------------------------------------- /src/utf8.h: -------------------------------------------------------------------------------- 1 | // This is free and unencumbered software released into the public domain. 2 | // 3 | // Anyone is free to copy, modify, publish, use, compile, sell, or 4 | // distribute this software, either in source code form or as a compiled 5 | // binary, for any purpose, commercial or non-commercial, and by any 6 | // means. 7 | // 8 | // In jurisdictions that recognize copyright laws, the author or authors 9 | // of this software dedicate any and all copyright interest in the 10 | // software to the public domain. We make this dedication for the benefit 11 | // of the public at large and to the detriment of our heirs and 12 | // successors. We intend this dedication to be an overt act of 13 | // relinquishment in perpetuity of all present and future rights to this 14 | // software under copyright law. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | // OTHER DEALINGS IN THE SOFTWARE. 23 | // 24 | // For more information, please refer to 25 | 26 | #ifndef SHEREDOM_UTF8_H_INCLUDED 27 | #define SHEREDOM_UTF8_H_INCLUDED 28 | 29 | #if defined(_MSC_VER) 30 | #pragma warning(push) 31 | 32 | // disable 'bytes padding added after construct' warning 33 | #pragma warning(disable : 4820) 34 | #endif 35 | 36 | #include 37 | #include 38 | 39 | #if defined(_MSC_VER) 40 | #pragma warning(pop) 41 | #endif 42 | 43 | #if defined(_MSC_VER) 44 | #define int32_t __int32 45 | #define uint32_t __uint32 46 | #else 47 | #include 48 | #endif 49 | 50 | #if defined(__clang__) 51 | #pragma clang diagnostic push 52 | #pragma clang diagnostic ignored "-Wold-style-cast" 53 | #pragma clang diagnostic ignored "-Wcast-qual" 54 | #endif 55 | 56 | #ifdef __cplusplus 57 | extern "C" { 58 | #endif 59 | 60 | #if defined(__clang__) || defined(__GNUC__) 61 | #define utf8_nonnull __attribute__((nonnull)) 62 | #define utf8_pure __attribute__((pure)) 63 | #define utf8_restrict __restrict__ 64 | #define utf8_weak __attribute__((weak)) 65 | #elif defined(_MSC_VER) 66 | #define utf8_nonnull 67 | #define utf8_pure 68 | #define utf8_restrict __restrict 69 | #define utf8_weak __inline 70 | #else 71 | #error Non clang, non gcc, non MSVC compiler found! 72 | #endif 73 | 74 | // While ignoring the case of ASCII characters, return less 75 | // than 0, 0, greater than 0 if src1 < src2, src1 == src2, 76 | // src1 > src2 respectively. 77 | utf8_nonnull utf8_pure utf8_weak int utf8casecmp(const void *src1, 78 | const void *src2); 79 | 80 | // Append the utf8 string src onto the utf8 string dst. 81 | utf8_nonnull utf8_weak void *utf8cat(void *utf8_restrict dst, 82 | const void *utf8_restrict src); 83 | 84 | // Find the first match of the utf8 codepoint chr in the utf8 string src. 85 | utf8_nonnull utf8_pure utf8_weak void *utf8chr(const void *src, int32_t chr); 86 | 87 | // Return less than 0, 0, greater than 0 if src1 < src2, 88 | // src1 == src2, src1 > src2 respectively. 89 | utf8_nonnull utf8_pure utf8_weak int utf8cmp(const void *src1, 90 | const void *src2); 91 | 92 | // Copy the utf8 string src onto the memory allocated in dst. 93 | utf8_nonnull utf8_weak void *utf8cpy(void *utf8_restrict dst, 94 | const void *utf8_restrict src); 95 | 96 | // Number of utf8 codepoints in the utf8 string src that consists entirely 97 | // of utf8 codepoints not from the utf8 string reject. 98 | utf8_nonnull utf8_pure utf8_weak size_t utf8cspn(const void *src, 99 | const void *reject); 100 | 101 | // Duplicate the utf8 string src by getting its size, malloc'ing a new buffer 102 | // copying over the data, and returning that. Or 0 if malloc failed. 103 | utf8_nonnull utf8_weak void *utf8dup(const void *src); 104 | 105 | // Number of utf8 codepoints in the utf8 string str, 106 | // excluding the null terminating byte. 107 | utf8_nonnull utf8_pure utf8_weak size_t utf8len(const void *str); 108 | 109 | // While ignoring the case of ASCII characters, return less 110 | // than 0, 0, greater than 0 if src1 < src2, src1 == src2, 111 | // src1 > src2 respectively. Checking at most n 112 | // bytes of each utf8 string. 113 | utf8_nonnull utf8_pure utf8_weak int utf8ncasecmp(const void *src1, 114 | const void *src2, size_t n); 115 | 116 | // Append the utf8 string src onto the utf8 string dst, 117 | // writing at most n+1 bytes. Can produce an invalid utf8 118 | // string if n falls partway through a utf8 codepoint. 119 | utf8_nonnull utf8_weak void *utf8ncat(void *utf8_restrict dst, 120 | const void *utf8_restrict src, size_t n); 121 | 122 | // Return less than 0, 0, greater than 0 if src1 < src2, 123 | // src1 == src2, src1 > src2 respectively. Checking at most n 124 | // bytes of each utf8 string. 125 | utf8_nonnull utf8_pure utf8_weak int utf8ncmp(const void *src1, 126 | const void *src2, size_t n); 127 | 128 | // Copy the utf8 string src onto the memory allocated in dst. 129 | // Copies at most n bytes. If there is no terminating null byte in 130 | // the first n bytes of src, the string placed into dst will not be 131 | // null-terminated. If the size (in bytes) of src is less than n, 132 | // extra null terminating bytes are appended to dst such that at 133 | // total of n bytes are written. Can produce an invalid utf8 134 | // string if n falls partway through a utf8 codepoint. 135 | utf8_nonnull utf8_weak void *utf8ncpy(void *utf8_restrict dst, 136 | const void *utf8_restrict src, size_t n); 137 | 138 | // Locates the first occurence in the utf8 string str of any byte in the 139 | // utf8 string accept, or 0 if no match was found. 140 | utf8_nonnull utf8_pure utf8_weak void *utf8pbrk(const void *str, 141 | const void *accept); 142 | 143 | // Find the last match of the utf8 codepoint chr in the utf8 string src. 144 | utf8_nonnull utf8_pure utf8_weak void *utf8rchr(const void *src, int chr); 145 | 146 | // Number of bytes in the utf8 string str, 147 | // including the null terminating byte. 148 | utf8_nonnull utf8_pure utf8_weak size_t utf8size(const void *str); 149 | 150 | // Number of utf8 codepoints in the utf8 string src that consists entirely 151 | // of utf8 codepoints from the utf8 string accept. 152 | utf8_nonnull utf8_pure utf8_weak size_t utf8spn(const void *src, 153 | const void *accept); 154 | 155 | // The position of the utf8 string needle in the utf8 string haystack. 156 | utf8_nonnull utf8_pure utf8_weak void *utf8str(const void *haystack, 157 | const void *needle); 158 | 159 | // The position of the utf8 string needle in the utf8 string haystack, case 160 | // instensitive. 161 | utf8_nonnull utf8_pure utf8_weak void *utf8casestr(const void *haystack, 162 | const void *needle); 163 | 164 | // Return 0 on success, or the position of the invalid 165 | // utf8 codepoint on failure. 166 | utf8_nonnull utf8_pure utf8_weak void *utf8valid(const void *str); 167 | 168 | // Sets out_codepoint to the next utf8 codepoint in str, and returns the address 169 | // of the utf8 codepoint after the current one in str. 170 | utf8_nonnull utf8_weak void *utf8codepoint(const void *utf8_restrict str, 171 | int32_t *utf8_restrict out_codepoint); 172 | 173 | // Returns the size of the given codepoint in bytes. 174 | utf8_weak size_t utf8codepointsize(int32_t chr); 175 | 176 | // Write a codepoint to the given string, and return the address to the next place 177 | // after the written codepoint. Pass how many bytes left in the buffer to n. If there 178 | // is not enough space for the codepoint, this function returns null. 179 | utf8_nonnull utf8_weak void *utf8catcodepoint(void *utf8_restrict str, int32_t chr, size_t n); 180 | 181 | // Returns 1 if the given character is lowercase, or 0 if it is not. 182 | utf8_weak int utf8islower(int32_t chr); 183 | 184 | // Returns 1 if the given character is uppercase, or 0 if it is not. 185 | utf8_weak int utf8isupper(int32_t chr); 186 | 187 | // Transform the given string into all lowercase codepoints. 188 | utf8_nonnull utf8_weak void utf8lwr(void *utf8_restrict str); 189 | 190 | // Transform the given string into all uppercase codepoints. 191 | utf8_nonnull utf8_weak void utf8upr(void *utf8_restrict str); 192 | 193 | #undef utf8_weak 194 | #undef utf8_pure 195 | #undef utf8_nonnull 196 | 197 | int utf8casecmp(const void *src1, const void *src2) { 198 | const unsigned char *s1 = (const unsigned char *)src1; 199 | const unsigned char *s2 = (const unsigned char *)src2; 200 | 201 | while (('\0' != *s1) || ('\0' != *s2)) { 202 | unsigned char a = *s1; 203 | unsigned char b = *s2; 204 | 205 | if (('A' <= a) && ('Z' >= a)) { 206 | a |= 0x20; // make a lowercase 207 | } 208 | 209 | if (('A' <= b) && ('Z' >= b)) { 210 | b |= 0x20; // make b lowercase 211 | } 212 | 213 | if (a < b) { 214 | return -1; 215 | } else if (a > b) { 216 | return 1; 217 | } 218 | 219 | s1++; 220 | s2++; 221 | } 222 | 223 | // both utf8 strings matched 224 | return 0; 225 | } 226 | 227 | void *utf8cat(void *utf8_restrict dst, const void *utf8_restrict src) { 228 | char *d = (char *)dst; 229 | const char *s = (const char *)src; 230 | 231 | // find the null terminating byte in dst 232 | while ('\0' != *d) { 233 | d++; 234 | } 235 | 236 | // overwriting the null terminating byte in dst, append src byte-by-byte 237 | while ('\0' != *s) { 238 | *d++ = *s++; 239 | } 240 | 241 | // write out a new null terminating byte into dst 242 | *d = '\0'; 243 | 244 | return dst; 245 | } 246 | 247 | void *utf8chr(const void *src, int32_t chr) { 248 | char c[5] = {'\0', '\0', '\0', '\0', '\0'}; 249 | 250 | if (0 == chr) { 251 | // being asked to return position of null terminating byte, so 252 | // just run s to the end, and return! 253 | const char *s = (const char *)src; 254 | while ('\0' != *s) { 255 | s++; 256 | } 257 | return (void *)s; 258 | } else if (0 == ((int32_t)0xffffff80 & chr)) { 259 | // 1-byte/7-bit ascii 260 | // (0b0xxxxxxx) 261 | c[0] = (char)chr; 262 | } else if (0 == ((int32_t)0xfffff800 & chr)) { 263 | // 2-byte/11-bit utf8 code point 264 | // (0b110xxxxx 0b10xxxxxx) 265 | c[0] = 0xc0 | (char)(chr >> 6); 266 | c[1] = 0x80 | (char)(chr & 0x3f); 267 | } else if (0 == ((int32_t)0xffff0000 & chr)) { 268 | // 3-byte/16-bit utf8 code point 269 | // (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) 270 | c[0] = 0xe0 | (char)(chr >> 12); 271 | c[1] = 0x80 | (char)((chr >> 6) & 0x3f); 272 | c[2] = 0x80 | (char)(chr & 0x3f); 273 | } else { // if (0 == ((int)0xffe00000 & chr)) { 274 | // 4-byte/21-bit utf8 code point 275 | // (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) 276 | c[0] = 0xf0 | (char)(chr >> 18); 277 | c[1] = 0x80 | (char)((chr >> 12) & 0x3f); 278 | c[2] = 0x80 | (char)((chr >> 6) & 0x3f); 279 | c[3] = 0x80 | (char)(chr & 0x3f); 280 | } 281 | 282 | // we've made c into a 2 utf8 codepoint string, one for the chr we are 283 | // seeking, another for the null terminating byte. Now use utf8str to 284 | // search 285 | return utf8str(src, c); 286 | } 287 | 288 | int utf8cmp(const void *src1, const void *src2) { 289 | const unsigned char *s1 = (const unsigned char *)src1; 290 | const unsigned char *s2 = (const unsigned char *)src2; 291 | 292 | while (('\0' != *s1) || ('\0' != *s2)) { 293 | if (*s1 < *s2) { 294 | return -1; 295 | } else if (*s1 > *s2) { 296 | return 1; 297 | } 298 | 299 | s1++; 300 | s2++; 301 | } 302 | 303 | // both utf8 strings matched 304 | return 0; 305 | } 306 | 307 | int utf8coll(const void *src1, const void *src2); 308 | 309 | void *utf8cpy(void *utf8_restrict dst, const void *utf8_restrict src) { 310 | char *d = (char *)dst; 311 | const char *s = (const char *)src; 312 | 313 | // overwriting anything previously in dst, write byte-by-byte 314 | // from src 315 | while ('\0' != *s) { 316 | *d++ = *s++; 317 | } 318 | 319 | // append null terminating byte 320 | *d = '\0'; 321 | 322 | return dst; 323 | } 324 | 325 | size_t utf8cspn(const void *src, const void *reject) { 326 | const char *s = (const char *)src; 327 | size_t chars = 0; 328 | 329 | while ('\0' != *s) { 330 | const char *r = (const char *)reject; 331 | size_t offset = 0; 332 | 333 | while ('\0' != *r) { 334 | // checking that if *r is the start of a utf8 codepoint 335 | // (it is not 0b10xxxxxx) and we have successfully matched 336 | // a previous character (0 < offset) - we found a match 337 | if ((0x80 != (0xc0 & *r)) && (0 < offset)) { 338 | return chars; 339 | } else { 340 | if (*r == s[offset]) { 341 | // part of a utf8 codepoint matched, so move our checking 342 | // onwards to the next byte 343 | offset++; 344 | r++; 345 | } else { 346 | // r could be in the middle of an unmatching utf8 code point, 347 | // so we need to march it on to the next character beginning, 348 | 349 | do { 350 | r++; 351 | } while (0x80 == (0xc0 & *r)); 352 | 353 | // reset offset too as we found a mismatch 354 | offset = 0; 355 | } 356 | } 357 | } 358 | 359 | // the current utf8 codepoint in src did not match reject, but src 360 | // could have been partway through a utf8 codepoint, so we need to 361 | // march it onto the next utf8 codepoint starting byte 362 | do { 363 | s++; 364 | } while ((0x80 == (0xc0 & *s))); 365 | chars++; 366 | } 367 | 368 | return chars; 369 | } 370 | 371 | size_t utf8size(const void *str); 372 | 373 | void *utf8dup(const void *src) { 374 | const char *s = (const char *)src; 375 | char *n = 0; 376 | 377 | // figure out how many bytes (including the terminator) we need to copy first 378 | size_t bytes = utf8size(src); 379 | 380 | n = (char *)malloc(bytes); 381 | 382 | if (0 == n) { 383 | // out of memory so we bail 384 | return 0; 385 | } else { 386 | bytes = 0; 387 | 388 | // copy src byte-by-byte into our new utf8 string 389 | while ('\0' != s[bytes]) { 390 | n[bytes] = s[bytes]; 391 | bytes++; 392 | } 393 | 394 | // append null terminating byte 395 | n[bytes] = '\0'; 396 | return n; 397 | } 398 | } 399 | 400 | void *utf8fry(const void *str); 401 | 402 | size_t utf8len(const void *str) { 403 | const unsigned char *s = (const unsigned char *)str; 404 | size_t length = 0; 405 | 406 | while ('\0' != *s) { 407 | if (0xf0 == (0xf8 & *s)) { 408 | // 4-byte utf8 code point (began with 0b11110xxx) 409 | s += 4; 410 | } else if (0xe0 == (0xf0 & *s)) { 411 | // 3-byte utf8 code point (began with 0b1110xxxx) 412 | s += 3; 413 | } else if (0xc0 == (0xe0 & *s)) { 414 | // 2-byte utf8 code point (began with 0b110xxxxx) 415 | s += 2; 416 | } else { // if (0x00 == (0x80 & *s)) { 417 | // 1-byte ascii (began with 0b0xxxxxxx) 418 | s += 1; 419 | } 420 | 421 | // no matter the bytes we marched s forward by, it was 422 | // only 1 utf8 codepoint 423 | length++; 424 | } 425 | 426 | return length; 427 | } 428 | 429 | int utf8ncasecmp(const void *src1, const void *src2, size_t n) { 430 | const unsigned char *s1 = (const unsigned char *)src1; 431 | const unsigned char *s2 = (const unsigned char *)src2; 432 | 433 | while ((('\0' != *s1) || ('\0' != *s2)) && (0 != n--)) { 434 | unsigned char a = *s1; 435 | unsigned char b = *s2; 436 | 437 | if (('A' <= a) && ('Z' >= a)) { 438 | a |= 0x20; // make a lowercase 439 | } 440 | 441 | if (('A' <= b) && ('Z' >= b)) { 442 | b |= 0x20; // make b lowercase 443 | } 444 | 445 | if (a < b) { 446 | return -1; 447 | } else if (a > b) { 448 | return 1; 449 | } 450 | 451 | s1++; 452 | s2++; 453 | } 454 | 455 | // both utf8 strings matched 456 | return 0; 457 | } 458 | 459 | void *utf8ncat(void *utf8_restrict dst, const void *utf8_restrict src, 460 | size_t n) { 461 | char *d = (char *)dst; 462 | const char *s = (const char *)src; 463 | 464 | // find the null terminating byte in dst 465 | while ('\0' != *d) { 466 | d++; 467 | } 468 | 469 | // overwriting the null terminating byte in dst, append src byte-by-byte 470 | // stopping if we run out of space 471 | do { 472 | *d++ = *s++; 473 | } while (('\0' != *s) && (0 != --n)); 474 | 475 | // write out a new null terminating byte into dst 476 | *d = '\0'; 477 | 478 | return dst; 479 | } 480 | 481 | int utf8ncmp(const void *src1, const void *src2, size_t n) { 482 | const unsigned char *s1 = (const unsigned char *)src1; 483 | const unsigned char *s2 = (const unsigned char *)src2; 484 | 485 | while ((('\0' != *s1) || ('\0' != *s2)) && (0 != n--)) { 486 | if (*s1 < *s2) { 487 | return -1; 488 | } else if (*s1 > *s2) { 489 | return 1; 490 | } 491 | 492 | s1++; 493 | s2++; 494 | } 495 | 496 | // both utf8 strings matched 497 | return 0; 498 | } 499 | 500 | void *utf8ncpy(void *utf8_restrict dst, const void *utf8_restrict src, 501 | size_t n) { 502 | char *d = (char *)dst; 503 | const char *s = (const char *)src; 504 | 505 | // overwriting anything previously in dst, write byte-by-byte 506 | // from src 507 | do { 508 | *d++ = *s++; 509 | } while (('\0' != *s) && (0 != --n)); 510 | 511 | // append null terminating byte 512 | while (0 != n) { 513 | *d++ = '\0'; 514 | n--; 515 | } 516 | 517 | return dst; 518 | } 519 | 520 | void *utf8rchr(const void *src, int chr) { 521 | const char *s = (const char *)src; 522 | const char *match = 0; 523 | char c[5] = {'\0', '\0', '\0', '\0', '\0'}; 524 | 525 | if (0 == chr) { 526 | // being asked to return position of null terminating byte, so 527 | // just run s to the end, and return! 528 | while ('\0' != *s) { 529 | s++; 530 | } 531 | return (void *)s; 532 | } else if (0 == ((int)0xffffff80 & chr)) { 533 | // 1-byte/7-bit ascii 534 | // (0b0xxxxxxx) 535 | c[0] = (char)chr; 536 | } else if (0 == ((int)0xfffff800 & chr)) { 537 | // 2-byte/11-bit utf8 code point 538 | // (0b110xxxxx 0b10xxxxxx) 539 | c[0] = 0xc0 | (char)(chr >> 6); 540 | c[1] = 0x80 | (char)(chr & 0x3f); 541 | } else if (0 == ((int)0xffff0000 & chr)) { 542 | // 3-byte/16-bit utf8 code point 543 | // (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) 544 | c[0] = 0xe0 | (char)(chr >> 12); 545 | c[1] = 0x80 | (char)((chr >> 6) & 0x3f); 546 | c[2] = 0x80 | (char)(chr & 0x3f); 547 | } else { // if (0 == ((int)0xffe00000 & chr)) { 548 | // 4-byte/21-bit utf8 code point 549 | // (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) 550 | c[0] = 0xf0 | (char)(chr >> 18); 551 | c[1] = 0x80 | (char)((chr >> 12) & 0x3f); 552 | c[2] = 0x80 | (char)((chr >> 6) & 0x3f); 553 | c[3] = 0x80 | (char)(chr & 0x3f); 554 | } 555 | 556 | // we've created a 2 utf8 codepoint string in c that is 557 | // the utf8 character asked for by chr, and a null 558 | // terminating byte 559 | 560 | while ('\0' != *s) { 561 | size_t offset = 0; 562 | 563 | while (s[offset] == c[offset]) { 564 | offset++; 565 | } 566 | 567 | if ('\0' == c[offset]) { 568 | // we found a matching utf8 code point 569 | match = s; 570 | s += offset; 571 | } else { 572 | s += offset; 573 | 574 | // need to march s along to next utf8 codepoint start 575 | // (the next byte that doesn't match 0b10xxxxxx) 576 | if ('\0' != *s) { 577 | do { 578 | s++; 579 | } while (0x80 == (0xc0 & *s)); 580 | } 581 | } 582 | } 583 | 584 | // return the last match we found (or 0 if no match was found) 585 | return (void *)match; 586 | } 587 | 588 | void *utf8pbrk(const void *str, const void *accept) { 589 | const char *s = (const char *)str; 590 | 591 | while ('\0' != *s) { 592 | const char *a = (const char *)accept; 593 | size_t offset = 0; 594 | 595 | while ('\0' != *a) { 596 | // checking that if *a is the start of a utf8 codepoint 597 | // (it is not 0b10xxxxxx) and we have successfully matched 598 | // a previous character (0 < offset) - we found a match 599 | if ((0x80 != (0xc0 & *a)) && (0 < offset)) { 600 | return (void *)s; 601 | } else { 602 | if (*a == s[offset]) { 603 | // part of a utf8 codepoint matched, so move our checking 604 | // onwards to the next byte 605 | offset++; 606 | a++; 607 | } else { 608 | // r could be in the middle of an unmatching utf8 code point, 609 | // so we need to march it on to the next character beginning, 610 | 611 | do { 612 | a++; 613 | } while (0x80 == (0xc0 & *a)); 614 | 615 | // reset offset too as we found a mismatch 616 | offset = 0; 617 | } 618 | } 619 | } 620 | 621 | // we found a match on the last utf8 codepoint 622 | if (0 < offset) { 623 | return (void *)s; 624 | } 625 | 626 | // the current utf8 codepoint in src did not match accept, but src 627 | // could have been partway through a utf8 codepoint, so we need to 628 | // march it onto the next utf8 codepoint starting byte 629 | do { 630 | s++; 631 | } while ((0x80 == (0xc0 & *s))); 632 | } 633 | 634 | return 0; 635 | } 636 | 637 | size_t utf8size(const void *str) { 638 | const char *s = (const char *)str; 639 | size_t size = 0; 640 | while ('\0' != s[size]) { 641 | size++; 642 | } 643 | 644 | // we are including the null terminating byte in the size calculation 645 | size++; 646 | return size; 647 | } 648 | 649 | size_t utf8spn(const void *src, const void *accept) { 650 | const char *s = (const char *)src; 651 | size_t chars = 0; 652 | 653 | while ('\0' != *s) { 654 | const char *a = (const char *)accept; 655 | size_t offset = 0; 656 | 657 | while ('\0' != *a) { 658 | // checking that if *r is the start of a utf8 codepoint 659 | // (it is not 0b10xxxxxx) and we have successfully matched 660 | // a previous character (0 < offset) - we found a match 661 | if ((0x80 != (0xc0 & *a)) && (0 < offset)) { 662 | // found a match, so increment the number of utf8 codepoints 663 | // that have matched and stop checking whether any other utf8 664 | // codepoints in a match 665 | chars++; 666 | s += offset; 667 | break; 668 | } else { 669 | if (*a == s[offset]) { 670 | offset++; 671 | a++; 672 | } else { 673 | // a could be in the middle of an unmatching utf8 codepoint, 674 | // so we need to march it on to the next character beginning, 675 | do { 676 | a++; 677 | } while (0x80 == (0xc0 & *a)); 678 | 679 | // reset offset too as we found a mismatch 680 | offset = 0; 681 | } 682 | } 683 | } 684 | 685 | // if a got to its terminating null byte, then we didn't find a match. 686 | // Return the current number of matched utf8 codepoints 687 | if ('\0' == *a) { 688 | return chars; 689 | } 690 | } 691 | 692 | return chars; 693 | } 694 | 695 | void *utf8str(const void *haystack, const void *needle) { 696 | const char *h = (const char *)haystack; 697 | 698 | // if needle has no utf8 codepoints before the null terminating 699 | // byte then return haystack 700 | if ('\0' == *((const char *)needle)) { 701 | return (void *)haystack; 702 | } 703 | 704 | while ('\0' != *h) { 705 | const char *maybeMatch = h; 706 | const char *n = (const char *)needle; 707 | 708 | while (*h == *n && (*h != '\0' && *n != '\0')) { 709 | n++; 710 | h++; 711 | } 712 | 713 | if ('\0' == *n) { 714 | // we found the whole utf8 string for needle in haystack at 715 | // maybeMatch, so return it 716 | return (void *)maybeMatch; 717 | } else { 718 | // h could be in the middle of an unmatching utf8 codepoint, 719 | // so we need to march it on to the next character beginning, 720 | if ('\0' != *h) { 721 | do { 722 | h++; 723 | } while (0x80 == (0xc0 & *h)); 724 | } 725 | } 726 | } 727 | 728 | // no match 729 | return 0; 730 | } 731 | 732 | void *utf8casestr(const void *haystack, const void *needle) { 733 | const char *h = (const char *)haystack; 734 | 735 | // if needle has no utf8 codepoints before the null terminating 736 | // byte then return haystack 737 | if ('\0' == *((const char *)needle)) { 738 | return (void *)haystack; 739 | } 740 | 741 | while ('\0' != *h) { 742 | const char *maybeMatch = h; 743 | const char *n = (const char *)needle; 744 | 745 | for (;;) { 746 | char a = *h; 747 | char b = *n; 748 | // not entirely correct, but good enough 749 | if (('A' <= a) && ('Z' >= a)) { 750 | a |= 0x20; // make a lowercase 751 | } 752 | 753 | if (('A' <= b) && ('Z' >= b)) { 754 | b |= 0x20; // make b lowercase 755 | } 756 | 757 | // if we find a mismatch, bail out! 758 | if (a != b) { 759 | break; 760 | } 761 | 762 | n++; 763 | h++; 764 | } 765 | 766 | if ('\0' == *n) { 767 | // we found the whole utf8 string for needle in haystack at 768 | // maybeMatch, so return it 769 | return (void *)maybeMatch; 770 | } else { 771 | // h could be in the middle of an unmatching utf8 codepoint, 772 | // so we need to march it on to the next character beginning, 773 | if ('\0' != *h) { 774 | do { 775 | h++; 776 | } while (0x80 == (0xc0 & *h)); 777 | } 778 | } 779 | } 780 | 781 | // no match 782 | return 0; 783 | } 784 | 785 | void *utf8valid(const void *str) { 786 | const char *s = (const char *)str; 787 | 788 | while ('\0' != *s) { 789 | if (0xf0 == (0xf8 & *s)) { 790 | // ensure each of the 3 following bytes in this 4-byte 791 | // utf8 codepoint began with 0b10xxxxxx 792 | if ((0x80 != (0xc0 & s[1])) || (0x80 != (0xc0 & s[2])) || 793 | (0x80 != (0xc0 & s[3]))) { 794 | return (void *)s; 795 | } 796 | 797 | // ensure that our utf8 codepoint ended after 4 bytes 798 | if (0x80 == (0xc0 & s[4])) { 799 | return (void *)s; 800 | } 801 | 802 | // ensure that the top 5 bits of this 4-byte utf8 803 | // codepoint were not 0, as then we could have used 804 | // one of the smaller encodings 805 | if ((0 == (0x07 & s[0])) && (0 == (0x30 & s[1]))) { 806 | return (void *)s; 807 | } 808 | 809 | // 4-byte utf8 code point (began with 0b11110xxx) 810 | s += 4; 811 | } else if (0xe0 == (0xf0 & *s)) { 812 | // ensure each of the 2 following bytes in this 3-byte 813 | // utf8 codepoint began with 0b10xxxxxx 814 | if ((0x80 != (0xc0 & s[1])) || (0x80 != (0xc0 & s[2]))) { 815 | return (void *)s; 816 | } 817 | 818 | // ensure that our utf8 codepoint ended after 3 bytes 819 | if (0x80 == (0xc0 & s[3])) { 820 | return (void *)s; 821 | } 822 | 823 | // ensure that the top 5 bits of this 3-byte utf8 824 | // codepoint were not 0, as then we could have used 825 | // one of the smaller encodings 826 | if ((0 == (0x0f & s[0])) && (0 == (0x20 & s[1]))) { 827 | return (void *)s; 828 | } 829 | 830 | // 3-byte utf8 code point (began with 0b1110xxxx) 831 | s += 3; 832 | } else if (0xc0 == (0xe0 & *s)) { 833 | // ensure the 1 following byte in this 2-byte 834 | // utf8 codepoint began with 0b10xxxxxx 835 | if (0x80 != (0xc0 & s[1])) { 836 | return (void *)s; 837 | } 838 | 839 | // ensure that our utf8 codepoint ended after 2 bytes 840 | if (0x80 == (0xc0 & s[2])) { 841 | return (void *)s; 842 | } 843 | 844 | // ensure that the top 4 bits of this 2-byte utf8 845 | // codepoint were not 0, as then we could have used 846 | // one of the smaller encodings 847 | if (0 == (0x1e & s[0])) { 848 | return (void *)s; 849 | } 850 | 851 | // 2-byte utf8 code point (began with 0b110xxxxx) 852 | s += 2; 853 | } else if (0x00 == (0x80 & *s)) { 854 | // 1-byte ascii (began with 0b0xxxxxxx) 855 | s += 1; 856 | } else { 857 | // we have an invalid 0b1xxxxxxx utf8 code point entry 858 | return (void *)s; 859 | } 860 | } 861 | 862 | return 0; 863 | } 864 | 865 | void *utf8codepoint(const void *utf8_restrict str, 866 | int32_t *utf8_restrict out_codepoint) { 867 | const char *s = (const char *)str; 868 | 869 | if (0xf0 == (0xf8 & s[0])) { 870 | // 4 byte utf8 codepoint 871 | *out_codepoint = ((0x07 & s[0]) << 18) | ((0x3f & s[1]) << 12) | 872 | ((0x3f & s[2]) << 6) | (0x3f & s[3]); 873 | s += 4; 874 | } else if (0xe0 == (0xf0 & s[0])) { 875 | // 3 byte utf8 codepoint 876 | *out_codepoint = 877 | ((0x0f & s[0]) << 12) | ((0x3f & s[1]) << 6) | (0x3f & s[2]); 878 | s += 3; 879 | } else if (0xc0 == (0xe0 & s[0])) { 880 | // 2 byte utf8 codepoint 881 | *out_codepoint = ((0x1f & s[0]) << 6) | (0x3f & s[1]); 882 | s += 2; 883 | } else { 884 | // 1 byte utf8 codepoint otherwise 885 | *out_codepoint = s[0]; 886 | s += 1; 887 | } 888 | 889 | return (void *)s; 890 | } 891 | 892 | size_t utf8codepointsize(int32_t chr) { 893 | if (0 == ((int32_t)0xffffff80 & chr)) { 894 | return 1; 895 | } else if (0 == ((int32_t)0xfffff800 & chr)) { 896 | return 2; 897 | } else if (0 == ((int32_t)0xffff0000 & chr)) { 898 | return 3; 899 | } else { // if (0 == ((int)0xffe00000 & chr)) { 900 | return 4; 901 | } 902 | } 903 | 904 | void *utf8catcodepoint(void *utf8_restrict str, int32_t chr, size_t n) { 905 | char *s = (char *)str; 906 | 907 | if (0 == ((int32_t)0xffffff80 & chr)) { 908 | // 1-byte/7-bit ascii 909 | // (0b0xxxxxxx) 910 | if (n < 1) { 911 | return 0; 912 | } 913 | s[0] = (char)chr; 914 | s += 1; 915 | } else if (0 == ((int32_t)0xfffff800 & chr)) { 916 | // 2-byte/11-bit utf8 code point 917 | // (0b110xxxxx 0b10xxxxxx) 918 | if (n < 2) { 919 | return 0; 920 | } 921 | s[0] = 0xc0 | (char)(chr >> 6); 922 | s[1] = 0x80 | (char)(chr & 0x3f); 923 | s += 2; 924 | } else if (0 == ((int32_t)0xffff0000 & chr)) { 925 | // 3-byte/16-bit utf8 code point 926 | // (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) 927 | if (n < 3) { 928 | return 0; 929 | } 930 | s[0] = 0xe0 | (char)(chr >> 12); 931 | s[1] = 0x80 | (char)((chr >> 6) & 0x3f); 932 | s[2] = 0x80 | (char)(chr & 0x3f); 933 | s += 3; 934 | } else { // if (0 == ((int)0xffe00000 & chr)) { 935 | // 4-byte/21-bit utf8 code point 936 | // (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) 937 | if (n < 4) { 938 | return 0; 939 | } 940 | s[0] = 0xf0 | (char)(chr >> 18); 941 | s[1] = 0x80 | (char)((chr >> 12) & 0x3f); 942 | s[2] = 0x80 | (char)((chr >> 6) & 0x3f); 943 | s[3] = 0x80 | (char)(chr & 0x3f); 944 | s += 4; 945 | } 946 | 947 | return s; 948 | } 949 | 950 | int utf8islower(int32_t chr) 951 | { 952 | if (('A' <= chr) && ('Z' >= chr)) { 953 | return 0; 954 | } 955 | // Because we're not all-inclusive, assume everything else is lowercase 956 | return 1; 957 | } 958 | 959 | int utf8isupper(int32_t chr) 960 | { 961 | if (('A' <= chr) && ('Z' >= chr)) { 962 | return 1; 963 | } 964 | return 0; 965 | } 966 | 967 | void utf8lwr(void *utf8_restrict str) 968 | { 969 | void *p, *pn; 970 | int cp; 971 | 972 | p = (char *)str; 973 | pn = utf8codepoint(p, &cp); 974 | 975 | while (cp != 0) { 976 | if (('A' <= cp) && ('Z' >= cp)) { 977 | cp |= 0x20; 978 | utf8catcodepoint(p, cp, 1); 979 | } 980 | p = pn; 981 | pn = utf8codepoint(p, &cp); 982 | } 983 | } 984 | 985 | void utf8upr(void *utf8_restrict str) 986 | { 987 | void *p, *pn; 988 | int cp; 989 | 990 | p = (char *)str; 991 | pn = utf8codepoint(p, &cp); 992 | 993 | while (cp != 0) { 994 | if (('a' <= cp) && ('z' >= cp)) { 995 | cp &= ~0x20; 996 | utf8catcodepoint(p, cp, 1); 997 | } 998 | p = pn; 999 | pn = utf8codepoint(p, &cp); 1000 | } 1001 | } 1002 | 1003 | #undef utf8_restrict 1004 | 1005 | #ifdef __cplusplus 1006 | } // extern "C" 1007 | #endif 1008 | 1009 | #if defined(__clang__) 1010 | #pragma clang diagnostic pop 1011 | #endif 1012 | 1013 | #endif // SHEREDOM_UTF8_H_INCLUDED 1014 | -------------------------------------------------------------------------------- /src/GL/wglext.h: -------------------------------------------------------------------------------- 1 | #ifndef __wglext_h_ 2 | #define __wglext_h_ 1 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* 9 | ** Copyright (c) 2013-2017 The Khronos Group Inc. 10 | ** 11 | ** Permission is hereby granted, free of charge, to any person obtaining a 12 | ** copy of this software and/or associated documentation files (the 13 | ** "Materials"), to deal in the Materials without restriction, including 14 | ** without limitation the rights to use, copy, modify, merge, publish, 15 | ** distribute, sublicense, and/or sell copies of the Materials, and to 16 | ** permit persons to whom the Materials are furnished to do so, subject to 17 | ** the following conditions: 18 | ** 19 | ** The above copyright notice and this permission notice shall be included 20 | ** in all copies or substantial portions of the Materials. 21 | ** 22 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 26 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 27 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 28 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 29 | */ 30 | /* 31 | ** This header is generated from the Khronos OpenGL / OpenGL ES XML 32 | ** API Registry. The current version of the Registry, generator scripts 33 | ** used to make the header, and the header can be found at 34 | ** https://github.com/KhronosGroup/OpenGL-Registry 35 | */ 36 | 37 | #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) 38 | #define WIN32_LEAN_AND_MEAN 1 39 | #include 40 | #endif 41 | 42 | #define WGL_WGLEXT_VERSION 20170221 43 | 44 | /* Generated C header for: 45 | * API: wgl 46 | * Versions considered: .* 47 | * Versions emitted: _nomatch_^ 48 | * Default extensions included: wgl 49 | * Additional extensions included: _nomatch_^ 50 | * Extensions removed: _nomatch_^ 51 | */ 52 | 53 | #ifndef WGL_ARB_buffer_region 54 | #define WGL_ARB_buffer_region 1 55 | #define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 56 | #define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 57 | #define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 58 | #define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 59 | typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); 60 | typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); 61 | typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); 62 | typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); 63 | #ifdef WGL_WGLEXT_PROTOTYPES 64 | HANDLE WINAPI wglCreateBufferRegionARB (HDC hDC, int iLayerPlane, UINT uType); 65 | VOID WINAPI wglDeleteBufferRegionARB (HANDLE hRegion); 66 | BOOL WINAPI wglSaveBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height); 67 | BOOL WINAPI wglRestoreBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); 68 | #endif 69 | #endif /* WGL_ARB_buffer_region */ 70 | 71 | #ifndef WGL_ARB_context_flush_control 72 | #define WGL_ARB_context_flush_control 1 73 | #define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 74 | #define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 75 | #define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 76 | #endif /* WGL_ARB_context_flush_control */ 77 | 78 | #ifndef WGL_ARB_create_context 79 | #define WGL_ARB_create_context 1 80 | #define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 81 | #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 82 | #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 83 | #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 84 | #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 85 | #define WGL_CONTEXT_FLAGS_ARB 0x2094 86 | #define ERROR_INVALID_VERSION_ARB 0x2095 87 | typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList); 88 | #ifdef WGL_WGLEXT_PROTOTYPES 89 | HGLRC WINAPI wglCreateContextAttribsARB (HDC hDC, HGLRC hShareContext, const int *attribList); 90 | #endif 91 | #endif /* WGL_ARB_create_context */ 92 | 93 | #ifndef WGL_ARB_create_context_profile 94 | #define WGL_ARB_create_context_profile 1 95 | #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 96 | #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 97 | #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 98 | #define ERROR_INVALID_PROFILE_ARB 0x2096 99 | #endif /* WGL_ARB_create_context_profile */ 100 | 101 | #ifndef WGL_ARB_create_context_robustness 102 | #define WGL_ARB_create_context_robustness 1 103 | #define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 104 | #define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 105 | #define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 106 | #define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 107 | #endif /* WGL_ARB_create_context_robustness */ 108 | 109 | #ifndef WGL_ARB_extensions_string 110 | #define WGL_ARB_extensions_string 1 111 | typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); 112 | #ifdef WGL_WGLEXT_PROTOTYPES 113 | const char *WINAPI wglGetExtensionsStringARB (HDC hdc); 114 | #endif 115 | #endif /* WGL_ARB_extensions_string */ 116 | 117 | #ifndef WGL_ARB_framebuffer_sRGB 118 | #define WGL_ARB_framebuffer_sRGB 1 119 | #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 120 | #endif /* WGL_ARB_framebuffer_sRGB */ 121 | 122 | #ifndef WGL_ARB_make_current_read 123 | #define WGL_ARB_make_current_read 1 124 | #define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 125 | #define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 126 | typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 127 | typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); 128 | #ifdef WGL_WGLEXT_PROTOTYPES 129 | BOOL WINAPI wglMakeContextCurrentARB (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 130 | HDC WINAPI wglGetCurrentReadDCARB (void); 131 | #endif 132 | #endif /* WGL_ARB_make_current_read */ 133 | 134 | #ifndef WGL_ARB_multisample 135 | #define WGL_ARB_multisample 1 136 | #define WGL_SAMPLE_BUFFERS_ARB 0x2041 137 | #define WGL_SAMPLES_ARB 0x2042 138 | #endif /* WGL_ARB_multisample */ 139 | 140 | #ifndef WGL_ARB_pbuffer 141 | #define WGL_ARB_pbuffer 1 142 | DECLARE_HANDLE(HPBUFFERARB); 143 | #define WGL_DRAW_TO_PBUFFER_ARB 0x202D 144 | #define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E 145 | #define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F 146 | #define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 147 | #define WGL_PBUFFER_LARGEST_ARB 0x2033 148 | #define WGL_PBUFFER_WIDTH_ARB 0x2034 149 | #define WGL_PBUFFER_HEIGHT_ARB 0x2035 150 | #define WGL_PBUFFER_LOST_ARB 0x2036 151 | typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); 152 | typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); 153 | typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); 154 | typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); 155 | typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); 156 | #ifdef WGL_WGLEXT_PROTOTYPES 157 | HPBUFFERARB WINAPI wglCreatePbufferARB (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); 158 | HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB hPbuffer); 159 | int WINAPI wglReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC); 160 | BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB hPbuffer); 161 | BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); 162 | #endif 163 | #endif /* WGL_ARB_pbuffer */ 164 | 165 | #ifndef WGL_ARB_pixel_format 166 | #define WGL_ARB_pixel_format 1 167 | #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 168 | #define WGL_DRAW_TO_WINDOW_ARB 0x2001 169 | #define WGL_DRAW_TO_BITMAP_ARB 0x2002 170 | #define WGL_ACCELERATION_ARB 0x2003 171 | #define WGL_NEED_PALETTE_ARB 0x2004 172 | #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 173 | #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 174 | #define WGL_SWAP_METHOD_ARB 0x2007 175 | #define WGL_NUMBER_OVERLAYS_ARB 0x2008 176 | #define WGL_NUMBER_UNDERLAYS_ARB 0x2009 177 | #define WGL_TRANSPARENT_ARB 0x200A 178 | #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 179 | #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 180 | #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 181 | #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A 182 | #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B 183 | #define WGL_SHARE_DEPTH_ARB 0x200C 184 | #define WGL_SHARE_STENCIL_ARB 0x200D 185 | #define WGL_SHARE_ACCUM_ARB 0x200E 186 | #define WGL_SUPPORT_GDI_ARB 0x200F 187 | #define WGL_SUPPORT_OPENGL_ARB 0x2010 188 | #define WGL_DOUBLE_BUFFER_ARB 0x2011 189 | #define WGL_STEREO_ARB 0x2012 190 | #define WGL_PIXEL_TYPE_ARB 0x2013 191 | #define WGL_COLOR_BITS_ARB 0x2014 192 | #define WGL_RED_BITS_ARB 0x2015 193 | #define WGL_RED_SHIFT_ARB 0x2016 194 | #define WGL_GREEN_BITS_ARB 0x2017 195 | #define WGL_GREEN_SHIFT_ARB 0x2018 196 | #define WGL_BLUE_BITS_ARB 0x2019 197 | #define WGL_BLUE_SHIFT_ARB 0x201A 198 | #define WGL_ALPHA_BITS_ARB 0x201B 199 | #define WGL_ALPHA_SHIFT_ARB 0x201C 200 | #define WGL_ACCUM_BITS_ARB 0x201D 201 | #define WGL_ACCUM_RED_BITS_ARB 0x201E 202 | #define WGL_ACCUM_GREEN_BITS_ARB 0x201F 203 | #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 204 | #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 205 | #define WGL_DEPTH_BITS_ARB 0x2022 206 | #define WGL_STENCIL_BITS_ARB 0x2023 207 | #define WGL_AUX_BUFFERS_ARB 0x2024 208 | #define WGL_NO_ACCELERATION_ARB 0x2025 209 | #define WGL_GENERIC_ACCELERATION_ARB 0x2026 210 | #define WGL_FULL_ACCELERATION_ARB 0x2027 211 | #define WGL_SWAP_EXCHANGE_ARB 0x2028 212 | #define WGL_SWAP_COPY_ARB 0x2029 213 | #define WGL_SWAP_UNDEFINED_ARB 0x202A 214 | #define WGL_TYPE_RGBA_ARB 0x202B 215 | #define WGL_TYPE_COLORINDEX_ARB 0x202C 216 | typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); 217 | typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); 218 | typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); 219 | #ifdef WGL_WGLEXT_PROTOTYPES 220 | BOOL WINAPI wglGetPixelFormatAttribivARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); 221 | BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); 222 | BOOL WINAPI wglChoosePixelFormatARB (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); 223 | #endif 224 | #endif /* WGL_ARB_pixel_format */ 225 | 226 | #ifndef WGL_ARB_pixel_format_float 227 | #define WGL_ARB_pixel_format_float 1 228 | #define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 229 | #endif /* WGL_ARB_pixel_format_float */ 230 | 231 | #ifndef WGL_ARB_render_texture 232 | #define WGL_ARB_render_texture 1 233 | #define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 234 | #define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 235 | #define WGL_TEXTURE_FORMAT_ARB 0x2072 236 | #define WGL_TEXTURE_TARGET_ARB 0x2073 237 | #define WGL_MIPMAP_TEXTURE_ARB 0x2074 238 | #define WGL_TEXTURE_RGB_ARB 0x2075 239 | #define WGL_TEXTURE_RGBA_ARB 0x2076 240 | #define WGL_NO_TEXTURE_ARB 0x2077 241 | #define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 242 | #define WGL_TEXTURE_1D_ARB 0x2079 243 | #define WGL_TEXTURE_2D_ARB 0x207A 244 | #define WGL_MIPMAP_LEVEL_ARB 0x207B 245 | #define WGL_CUBE_MAP_FACE_ARB 0x207C 246 | #define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D 247 | #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E 248 | #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F 249 | #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 250 | #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 251 | #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 252 | #define WGL_FRONT_LEFT_ARB 0x2083 253 | #define WGL_FRONT_RIGHT_ARB 0x2084 254 | #define WGL_BACK_LEFT_ARB 0x2085 255 | #define WGL_BACK_RIGHT_ARB 0x2086 256 | #define WGL_AUX0_ARB 0x2087 257 | #define WGL_AUX1_ARB 0x2088 258 | #define WGL_AUX2_ARB 0x2089 259 | #define WGL_AUX3_ARB 0x208A 260 | #define WGL_AUX4_ARB 0x208B 261 | #define WGL_AUX5_ARB 0x208C 262 | #define WGL_AUX6_ARB 0x208D 263 | #define WGL_AUX7_ARB 0x208E 264 | #define WGL_AUX8_ARB 0x208F 265 | #define WGL_AUX9_ARB 0x2090 266 | typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); 267 | typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); 268 | typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList); 269 | #ifdef WGL_WGLEXT_PROTOTYPES 270 | BOOL WINAPI wglBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer); 271 | BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer); 272 | BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB hPbuffer, const int *piAttribList); 273 | #endif 274 | #endif /* WGL_ARB_render_texture */ 275 | 276 | #ifndef WGL_ARB_robustness_application_isolation 277 | #define WGL_ARB_robustness_application_isolation 1 278 | #define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008 279 | #endif /* WGL_ARB_robustness_application_isolation */ 280 | 281 | #ifndef WGL_ARB_robustness_share_group_isolation 282 | #define WGL_ARB_robustness_share_group_isolation 1 283 | #endif /* WGL_ARB_robustness_share_group_isolation */ 284 | 285 | #ifndef WGL_3DFX_multisample 286 | #define WGL_3DFX_multisample 1 287 | #define WGL_SAMPLE_BUFFERS_3DFX 0x2060 288 | #define WGL_SAMPLES_3DFX 0x2061 289 | #endif /* WGL_3DFX_multisample */ 290 | 291 | #ifndef WGL_3DL_stereo_control 292 | #define WGL_3DL_stereo_control 1 293 | #define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 294 | #define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 295 | #define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 296 | #define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 297 | typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState); 298 | #ifdef WGL_WGLEXT_PROTOTYPES 299 | BOOL WINAPI wglSetStereoEmitterState3DL (HDC hDC, UINT uState); 300 | #endif 301 | #endif /* WGL_3DL_stereo_control */ 302 | 303 | #ifndef WGL_AMD_gpu_association 304 | #define WGL_AMD_gpu_association 1 305 | #define WGL_GPU_VENDOR_AMD 0x1F00 306 | #define WGL_GPU_RENDERER_STRING_AMD 0x1F01 307 | #define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 308 | #define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 309 | #define WGL_GPU_RAM_AMD 0x21A3 310 | #define WGL_GPU_CLOCK_AMD 0x21A4 311 | #define WGL_GPU_NUM_PIPES_AMD 0x21A5 312 | #define WGL_GPU_NUM_SIMD_AMD 0x21A6 313 | #define WGL_GPU_NUM_RB_AMD 0x21A7 314 | #define WGL_GPU_NUM_SPI_AMD 0x21A8 315 | typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT *ids); 316 | typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, int property, GLenum dataType, UINT size, void *data); 317 | typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc); 318 | typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id); 319 | typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int *attribList); 320 | typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc); 321 | typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc); 322 | typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void); 323 | typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); 324 | #ifdef WGL_WGLEXT_PROTOTYPES 325 | UINT WINAPI wglGetGPUIDsAMD (UINT maxCount, UINT *ids); 326 | INT WINAPI wglGetGPUInfoAMD (UINT id, int property, GLenum dataType, UINT size, void *data); 327 | UINT WINAPI wglGetContextGPUIDAMD (HGLRC hglrc); 328 | HGLRC WINAPI wglCreateAssociatedContextAMD (UINT id); 329 | HGLRC WINAPI wglCreateAssociatedContextAttribsAMD (UINT id, HGLRC hShareContext, const int *attribList); 330 | BOOL WINAPI wglDeleteAssociatedContextAMD (HGLRC hglrc); 331 | BOOL WINAPI wglMakeAssociatedContextCurrentAMD (HGLRC hglrc); 332 | HGLRC WINAPI wglGetCurrentAssociatedContextAMD (void); 333 | VOID WINAPI wglBlitContextFramebufferAMD (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); 334 | #endif 335 | #endif /* WGL_AMD_gpu_association */ 336 | 337 | #ifndef WGL_ATI_pixel_format_float 338 | #define WGL_ATI_pixel_format_float 1 339 | #define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 340 | #endif /* WGL_ATI_pixel_format_float */ 341 | 342 | #ifndef WGL_EXT_colorspace 343 | #define WGL_EXT_colorspace 1 344 | #define WGL_COLORSPACE_EXT 0x3087 345 | #define WGL_COLORSPACE_SRGB_EXT 0x3089 346 | #define WGL_COLORSPACE_LINEAR_EXT 0x308A 347 | #endif /* WGL_EXT_colorspace */ 348 | 349 | #ifndef WGL_EXT_create_context_es2_profile 350 | #define WGL_EXT_create_context_es2_profile 1 351 | #define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 352 | #endif /* WGL_EXT_create_context_es2_profile */ 353 | 354 | #ifndef WGL_EXT_create_context_es_profile 355 | #define WGL_EXT_create_context_es_profile 1 356 | #define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004 357 | #endif /* WGL_EXT_create_context_es_profile */ 358 | 359 | #ifndef WGL_EXT_depth_float 360 | #define WGL_EXT_depth_float 1 361 | #define WGL_DEPTH_FLOAT_EXT 0x2040 362 | #endif /* WGL_EXT_depth_float */ 363 | 364 | #ifndef WGL_EXT_display_color_table 365 | #define WGL_EXT_display_color_table 1 366 | typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); 367 | typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); 368 | typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); 369 | typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); 370 | #ifdef WGL_WGLEXT_PROTOTYPES 371 | GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort id); 372 | GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *table, GLuint length); 373 | GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort id); 374 | VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort id); 375 | #endif 376 | #endif /* WGL_EXT_display_color_table */ 377 | 378 | #ifndef WGL_EXT_extensions_string 379 | #define WGL_EXT_extensions_string 1 380 | typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); 381 | #ifdef WGL_WGLEXT_PROTOTYPES 382 | const char *WINAPI wglGetExtensionsStringEXT (void); 383 | #endif 384 | #endif /* WGL_EXT_extensions_string */ 385 | 386 | #ifndef WGL_EXT_framebuffer_sRGB 387 | #define WGL_EXT_framebuffer_sRGB 1 388 | #define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 389 | #endif /* WGL_EXT_framebuffer_sRGB */ 390 | 391 | #ifndef WGL_EXT_make_current_read 392 | #define WGL_EXT_make_current_read 1 393 | #define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 394 | typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 395 | typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); 396 | #ifdef WGL_WGLEXT_PROTOTYPES 397 | BOOL WINAPI wglMakeContextCurrentEXT (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 398 | HDC WINAPI wglGetCurrentReadDCEXT (void); 399 | #endif 400 | #endif /* WGL_EXT_make_current_read */ 401 | 402 | #ifndef WGL_EXT_multisample 403 | #define WGL_EXT_multisample 1 404 | #define WGL_SAMPLE_BUFFERS_EXT 0x2041 405 | #define WGL_SAMPLES_EXT 0x2042 406 | #endif /* WGL_EXT_multisample */ 407 | 408 | #ifndef WGL_EXT_pbuffer 409 | #define WGL_EXT_pbuffer 1 410 | DECLARE_HANDLE(HPBUFFEREXT); 411 | #define WGL_DRAW_TO_PBUFFER_EXT 0x202D 412 | #define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E 413 | #define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F 414 | #define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 415 | #define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 416 | #define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 417 | #define WGL_PBUFFER_LARGEST_EXT 0x2033 418 | #define WGL_PBUFFER_WIDTH_EXT 0x2034 419 | #define WGL_PBUFFER_HEIGHT_EXT 0x2035 420 | typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); 421 | typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); 422 | typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); 423 | typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); 424 | typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); 425 | #ifdef WGL_WGLEXT_PROTOTYPES 426 | HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); 427 | HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT hPbuffer); 428 | int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT hPbuffer, HDC hDC); 429 | BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT hPbuffer); 430 | BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); 431 | #endif 432 | #endif /* WGL_EXT_pbuffer */ 433 | 434 | #ifndef WGL_EXT_pixel_format 435 | #define WGL_EXT_pixel_format 1 436 | #define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 437 | #define WGL_DRAW_TO_WINDOW_EXT 0x2001 438 | #define WGL_DRAW_TO_BITMAP_EXT 0x2002 439 | #define WGL_ACCELERATION_EXT 0x2003 440 | #define WGL_NEED_PALETTE_EXT 0x2004 441 | #define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 442 | #define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 443 | #define WGL_SWAP_METHOD_EXT 0x2007 444 | #define WGL_NUMBER_OVERLAYS_EXT 0x2008 445 | #define WGL_NUMBER_UNDERLAYS_EXT 0x2009 446 | #define WGL_TRANSPARENT_EXT 0x200A 447 | #define WGL_TRANSPARENT_VALUE_EXT 0x200B 448 | #define WGL_SHARE_DEPTH_EXT 0x200C 449 | #define WGL_SHARE_STENCIL_EXT 0x200D 450 | #define WGL_SHARE_ACCUM_EXT 0x200E 451 | #define WGL_SUPPORT_GDI_EXT 0x200F 452 | #define WGL_SUPPORT_OPENGL_EXT 0x2010 453 | #define WGL_DOUBLE_BUFFER_EXT 0x2011 454 | #define WGL_STEREO_EXT 0x2012 455 | #define WGL_PIXEL_TYPE_EXT 0x2013 456 | #define WGL_COLOR_BITS_EXT 0x2014 457 | #define WGL_RED_BITS_EXT 0x2015 458 | #define WGL_RED_SHIFT_EXT 0x2016 459 | #define WGL_GREEN_BITS_EXT 0x2017 460 | #define WGL_GREEN_SHIFT_EXT 0x2018 461 | #define WGL_BLUE_BITS_EXT 0x2019 462 | #define WGL_BLUE_SHIFT_EXT 0x201A 463 | #define WGL_ALPHA_BITS_EXT 0x201B 464 | #define WGL_ALPHA_SHIFT_EXT 0x201C 465 | #define WGL_ACCUM_BITS_EXT 0x201D 466 | #define WGL_ACCUM_RED_BITS_EXT 0x201E 467 | #define WGL_ACCUM_GREEN_BITS_EXT 0x201F 468 | #define WGL_ACCUM_BLUE_BITS_EXT 0x2020 469 | #define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 470 | #define WGL_DEPTH_BITS_EXT 0x2022 471 | #define WGL_STENCIL_BITS_EXT 0x2023 472 | #define WGL_AUX_BUFFERS_EXT 0x2024 473 | #define WGL_NO_ACCELERATION_EXT 0x2025 474 | #define WGL_GENERIC_ACCELERATION_EXT 0x2026 475 | #define WGL_FULL_ACCELERATION_EXT 0x2027 476 | #define WGL_SWAP_EXCHANGE_EXT 0x2028 477 | #define WGL_SWAP_COPY_EXT 0x2029 478 | #define WGL_SWAP_UNDEFINED_EXT 0x202A 479 | #define WGL_TYPE_RGBA_EXT 0x202B 480 | #define WGL_TYPE_COLORINDEX_EXT 0x202C 481 | typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); 482 | typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); 483 | typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); 484 | #ifdef WGL_WGLEXT_PROTOTYPES 485 | BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); 486 | BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); 487 | BOOL WINAPI wglChoosePixelFormatEXT (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); 488 | #endif 489 | #endif /* WGL_EXT_pixel_format */ 490 | 491 | #ifndef WGL_EXT_pixel_format_packed_float 492 | #define WGL_EXT_pixel_format_packed_float 1 493 | #define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 494 | #endif /* WGL_EXT_pixel_format_packed_float */ 495 | 496 | #ifndef WGL_EXT_swap_control 497 | #define WGL_EXT_swap_control 1 498 | typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); 499 | typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); 500 | #ifdef WGL_WGLEXT_PROTOTYPES 501 | BOOL WINAPI wglSwapIntervalEXT (int interval); 502 | int WINAPI wglGetSwapIntervalEXT (void); 503 | #endif 504 | #endif /* WGL_EXT_swap_control */ 505 | 506 | #ifndef WGL_EXT_swap_control_tear 507 | #define WGL_EXT_swap_control_tear 1 508 | #endif /* WGL_EXT_swap_control_tear */ 509 | 510 | #ifndef WGL_I3D_digital_video_control 511 | #define WGL_I3D_digital_video_control 1 512 | #define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 513 | #define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 514 | #define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 515 | #define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 516 | typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); 517 | typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); 518 | #ifdef WGL_WGLEXT_PROTOTYPES 519 | BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC hDC, int iAttribute, int *piValue); 520 | BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC hDC, int iAttribute, const int *piValue); 521 | #endif 522 | #endif /* WGL_I3D_digital_video_control */ 523 | 524 | #ifndef WGL_I3D_gamma 525 | #define WGL_I3D_gamma 1 526 | #define WGL_GAMMA_TABLE_SIZE_I3D 0x204E 527 | #define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F 528 | typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); 529 | typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); 530 | typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); 531 | typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); 532 | #ifdef WGL_WGLEXT_PROTOTYPES 533 | BOOL WINAPI wglGetGammaTableParametersI3D (HDC hDC, int iAttribute, int *piValue); 534 | BOOL WINAPI wglSetGammaTableParametersI3D (HDC hDC, int iAttribute, const int *piValue); 535 | BOOL WINAPI wglGetGammaTableI3D (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); 536 | BOOL WINAPI wglSetGammaTableI3D (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); 537 | #endif 538 | #endif /* WGL_I3D_gamma */ 539 | 540 | #ifndef WGL_I3D_genlock 541 | #define WGL_I3D_genlock 1 542 | #define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 543 | #define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045 544 | #define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046 545 | #define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047 546 | #define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 547 | #define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 548 | #define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A 549 | #define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B 550 | #define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C 551 | typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); 552 | typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); 553 | typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag); 554 | typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); 555 | typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource); 556 | typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); 557 | typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge); 558 | typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); 559 | typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate); 560 | typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); 561 | typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay); 562 | typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); 563 | #ifdef WGL_WGLEXT_PROTOTYPES 564 | BOOL WINAPI wglEnableGenlockI3D (HDC hDC); 565 | BOOL WINAPI wglDisableGenlockI3D (HDC hDC); 566 | BOOL WINAPI wglIsEnabledGenlockI3D (HDC hDC, BOOL *pFlag); 567 | BOOL WINAPI wglGenlockSourceI3D (HDC hDC, UINT uSource); 568 | BOOL WINAPI wglGetGenlockSourceI3D (HDC hDC, UINT *uSource); 569 | BOOL WINAPI wglGenlockSourceEdgeI3D (HDC hDC, UINT uEdge); 570 | BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC hDC, UINT *uEdge); 571 | BOOL WINAPI wglGenlockSampleRateI3D (HDC hDC, UINT uRate); 572 | BOOL WINAPI wglGetGenlockSampleRateI3D (HDC hDC, UINT *uRate); 573 | BOOL WINAPI wglGenlockSourceDelayI3D (HDC hDC, UINT uDelay); 574 | BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC hDC, UINT *uDelay); 575 | BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); 576 | #endif 577 | #endif /* WGL_I3D_genlock */ 578 | 579 | #ifndef WGL_I3D_image_buffer 580 | #define WGL_I3D_image_buffer 1 581 | #define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 582 | #define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 583 | typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); 584 | typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); 585 | typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); 586 | typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count); 587 | #ifdef WGL_WGLEXT_PROTOTYPES 588 | LPVOID WINAPI wglCreateImageBufferI3D (HDC hDC, DWORD dwSize, UINT uFlags); 589 | BOOL WINAPI wglDestroyImageBufferI3D (HDC hDC, LPVOID pAddress); 590 | BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); 591 | BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC hDC, const LPVOID *pAddress, UINT count); 592 | #endif 593 | #endif /* WGL_I3D_image_buffer */ 594 | 595 | #ifndef WGL_I3D_swap_frame_lock 596 | #define WGL_I3D_swap_frame_lock 1 597 | typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void); 598 | typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void); 599 | typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag); 600 | typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag); 601 | #ifdef WGL_WGLEXT_PROTOTYPES 602 | BOOL WINAPI wglEnableFrameLockI3D (void); 603 | BOOL WINAPI wglDisableFrameLockI3D (void); 604 | BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *pFlag); 605 | BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *pFlag); 606 | #endif 607 | #endif /* WGL_I3D_swap_frame_lock */ 608 | 609 | #ifndef WGL_I3D_swap_frame_usage 610 | #define WGL_I3D_swap_frame_usage 1 611 | typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage); 612 | typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); 613 | typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); 614 | typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); 615 | #ifdef WGL_WGLEXT_PROTOTYPES 616 | BOOL WINAPI wglGetFrameUsageI3D (float *pUsage); 617 | BOOL WINAPI wglBeginFrameTrackingI3D (void); 618 | BOOL WINAPI wglEndFrameTrackingI3D (void); 619 | BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); 620 | #endif 621 | #endif /* WGL_I3D_swap_frame_usage */ 622 | 623 | #ifndef WGL_NV_DX_interop 624 | #define WGL_NV_DX_interop 1 625 | #define WGL_ACCESS_READ_ONLY_NV 0x00000000 626 | #define WGL_ACCESS_READ_WRITE_NV 0x00000001 627 | #define WGL_ACCESS_WRITE_DISCARD_NV 0x00000002 628 | typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void *dxObject, HANDLE shareHandle); 629 | typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void *dxDevice); 630 | typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice); 631 | typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access); 632 | typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject); 633 | typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access); 634 | typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects); 635 | typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects); 636 | #ifdef WGL_WGLEXT_PROTOTYPES 637 | BOOL WINAPI wglDXSetResourceShareHandleNV (void *dxObject, HANDLE shareHandle); 638 | HANDLE WINAPI wglDXOpenDeviceNV (void *dxDevice); 639 | BOOL WINAPI wglDXCloseDeviceNV (HANDLE hDevice); 640 | HANDLE WINAPI wglDXRegisterObjectNV (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access); 641 | BOOL WINAPI wglDXUnregisterObjectNV (HANDLE hDevice, HANDLE hObject); 642 | BOOL WINAPI wglDXObjectAccessNV (HANDLE hObject, GLenum access); 643 | BOOL WINAPI wglDXLockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects); 644 | BOOL WINAPI wglDXUnlockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects); 645 | #endif 646 | #endif /* WGL_NV_DX_interop */ 647 | 648 | #ifndef WGL_NV_DX_interop2 649 | #define WGL_NV_DX_interop2 1 650 | #endif /* WGL_NV_DX_interop2 */ 651 | 652 | #ifndef WGL_NV_copy_image 653 | #define WGL_NV_copy_image 1 654 | typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); 655 | #ifdef WGL_WGLEXT_PROTOTYPES 656 | BOOL WINAPI wglCopyImageSubDataNV (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); 657 | #endif 658 | #endif /* WGL_NV_copy_image */ 659 | 660 | #ifndef WGL_NV_delay_before_swap 661 | #define WGL_NV_delay_before_swap 1 662 | typedef BOOL (WINAPI * PFNWGLDELAYBEFORESWAPNVPROC) (HDC hDC, GLfloat seconds); 663 | #ifdef WGL_WGLEXT_PROTOTYPES 664 | BOOL WINAPI wglDelayBeforeSwapNV (HDC hDC, GLfloat seconds); 665 | #endif 666 | #endif /* WGL_NV_delay_before_swap */ 667 | 668 | #ifndef WGL_NV_float_buffer 669 | #define WGL_NV_float_buffer 1 670 | #define WGL_FLOAT_COMPONENTS_NV 0x20B0 671 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 672 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 673 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 674 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 675 | #define WGL_TEXTURE_FLOAT_R_NV 0x20B5 676 | #define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 677 | #define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 678 | #define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 679 | #endif /* WGL_NV_float_buffer */ 680 | 681 | #ifndef WGL_NV_gpu_affinity 682 | #define WGL_NV_gpu_affinity 1 683 | DECLARE_HANDLE(HGPUNV); 684 | struct _GPU_DEVICE { 685 | DWORD cb; 686 | CHAR DeviceName[32]; 687 | CHAR DeviceString[128]; 688 | DWORD Flags; 689 | RECT rcVirtualScreen; 690 | }; 691 | typedef struct _GPU_DEVICE *PGPU_DEVICE; 692 | #define ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 693 | #define ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 694 | typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu); 695 | typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); 696 | typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList); 697 | typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); 698 | typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc); 699 | #ifdef WGL_WGLEXT_PROTOTYPES 700 | BOOL WINAPI wglEnumGpusNV (UINT iGpuIndex, HGPUNV *phGpu); 701 | BOOL WINAPI wglEnumGpuDevicesNV (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); 702 | HDC WINAPI wglCreateAffinityDCNV (const HGPUNV *phGpuList); 703 | BOOL WINAPI wglEnumGpusFromAffinityDCNV (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); 704 | BOOL WINAPI wglDeleteDCNV (HDC hdc); 705 | #endif 706 | #endif /* WGL_NV_gpu_affinity */ 707 | 708 | #ifndef WGL_NV_multisample_coverage 709 | #define WGL_NV_multisample_coverage 1 710 | #define WGL_COVERAGE_SAMPLES_NV 0x2042 711 | #define WGL_COLOR_SAMPLES_NV 0x20B9 712 | #endif /* WGL_NV_multisample_coverage */ 713 | 714 | #ifndef WGL_NV_present_video 715 | #define WGL_NV_present_video 1 716 | DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); 717 | #define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 718 | typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList); 719 | typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList); 720 | typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int *piValue); 721 | #ifdef WGL_WGLEXT_PROTOTYPES 722 | int WINAPI wglEnumerateVideoDevicesNV (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList); 723 | BOOL WINAPI wglBindVideoDeviceNV (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList); 724 | BOOL WINAPI wglQueryCurrentContextNV (int iAttribute, int *piValue); 725 | #endif 726 | #endif /* WGL_NV_present_video */ 727 | 728 | #ifndef WGL_NV_render_depth_texture 729 | #define WGL_NV_render_depth_texture 1 730 | #define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 731 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 732 | #define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 733 | #define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 734 | #define WGL_DEPTH_COMPONENT_NV 0x20A7 735 | #endif /* WGL_NV_render_depth_texture */ 736 | 737 | #ifndef WGL_NV_render_texture_rectangle 738 | #define WGL_NV_render_texture_rectangle 1 739 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 740 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 741 | #define WGL_TEXTURE_RECTANGLE_NV 0x20A2 742 | #endif /* WGL_NV_render_texture_rectangle */ 743 | 744 | #ifndef WGL_NV_swap_group 745 | #define WGL_NV_swap_group 1 746 | typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); 747 | typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); 748 | typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier); 749 | typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers); 750 | typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count); 751 | typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); 752 | #ifdef WGL_WGLEXT_PROTOTYPES 753 | BOOL WINAPI wglJoinSwapGroupNV (HDC hDC, GLuint group); 754 | BOOL WINAPI wglBindSwapBarrierNV (GLuint group, GLuint barrier); 755 | BOOL WINAPI wglQuerySwapGroupNV (HDC hDC, GLuint *group, GLuint *barrier); 756 | BOOL WINAPI wglQueryMaxSwapGroupsNV (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers); 757 | BOOL WINAPI wglQueryFrameCountNV (HDC hDC, GLuint *count); 758 | BOOL WINAPI wglResetFrameCountNV (HDC hDC); 759 | #endif 760 | #endif /* WGL_NV_swap_group */ 761 | 762 | #ifndef WGL_NV_vertex_array_range 763 | #define WGL_NV_vertex_array_range 1 764 | typedef void *(WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); 765 | typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); 766 | #ifdef WGL_WGLEXT_PROTOTYPES 767 | void *WINAPI wglAllocateMemoryNV (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); 768 | void WINAPI wglFreeMemoryNV (void *pointer); 769 | #endif 770 | #endif /* WGL_NV_vertex_array_range */ 771 | 772 | #ifndef WGL_NV_video_capture 773 | #define WGL_NV_video_capture 1 774 | DECLARE_HANDLE(HVIDEOINPUTDEVICENV); 775 | #define WGL_UNIQUE_ID_NV 0x20CE 776 | #define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF 777 | typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice); 778 | typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList); 779 | typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); 780 | typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue); 781 | typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); 782 | #ifdef WGL_WGLEXT_PROTOTYPES 783 | BOOL WINAPI wglBindVideoCaptureDeviceNV (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice); 784 | UINT WINAPI wglEnumerateVideoCaptureDevicesNV (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList); 785 | BOOL WINAPI wglLockVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice); 786 | BOOL WINAPI wglQueryVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue); 787 | BOOL WINAPI wglReleaseVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice); 788 | #endif 789 | #endif /* WGL_NV_video_capture */ 790 | 791 | #ifndef WGL_NV_video_output 792 | #define WGL_NV_video_output 1 793 | DECLARE_HANDLE(HPVIDEODEV); 794 | #define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 795 | #define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 796 | #define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 797 | #define WGL_VIDEO_OUT_COLOR_NV 0x20C3 798 | #define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 799 | #define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 800 | #define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 801 | #define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 802 | #define WGL_VIDEO_OUT_FRAME 0x20C8 803 | #define WGL_VIDEO_OUT_FIELD_1 0x20C9 804 | #define WGL_VIDEO_OUT_FIELD_2 0x20CA 805 | #define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB 806 | #define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC 807 | typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice); 808 | typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); 809 | typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); 810 | typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); 811 | typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock); 812 | typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); 813 | #ifdef WGL_WGLEXT_PROTOTYPES 814 | BOOL WINAPI wglGetVideoDeviceNV (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice); 815 | BOOL WINAPI wglReleaseVideoDeviceNV (HPVIDEODEV hVideoDevice); 816 | BOOL WINAPI wglBindVideoImageNV (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); 817 | BOOL WINAPI wglReleaseVideoImageNV (HPBUFFERARB hPbuffer, int iVideoBuffer); 818 | BOOL WINAPI wglSendPbufferToVideoNV (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock); 819 | BOOL WINAPI wglGetVideoInfoNV (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); 820 | #endif 821 | #endif /* WGL_NV_video_output */ 822 | 823 | #ifndef WGL_OML_sync_control 824 | #define WGL_OML_sync_control 1 825 | typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); 826 | typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator); 827 | typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); 828 | typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); 829 | typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); 830 | typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); 831 | #ifdef WGL_WGLEXT_PROTOTYPES 832 | BOOL WINAPI wglGetSyncValuesOML (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); 833 | BOOL WINAPI wglGetMscRateOML (HDC hdc, INT32 *numerator, INT32 *denominator); 834 | INT64 WINAPI wglSwapBuffersMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); 835 | INT64 WINAPI wglSwapLayerBuffersMscOML (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); 836 | BOOL WINAPI wglWaitForMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); 837 | BOOL WINAPI wglWaitForSbcOML (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); 838 | #endif 839 | #endif /* WGL_OML_sync_control */ 840 | 841 | #ifdef __cplusplus 842 | } 843 | #endif 844 | 845 | #endif 846 | --------------------------------------------------------------------------------