diff --git a/examples/opengl_various_bindings/ImImpl_Binding_Glfw3.h b/examples/opengl_various_bindings/ImImpl_Binding_Glfw3.h new file mode 100644 index 000000000..22164a734 --- /dev/null +++ b/examples/opengl_various_bindings/ImImpl_Binding_Glfw3.h @@ -0,0 +1,310 @@ +#ifndef IMIMPL_BINDING_H +#define IMIMPL_BINDING_H + +#ifdef _WIN32 +#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#include +#include +#endif +#include + + +// glew (optional) & glfw +#ifdef IMIMPL_USE_GLEW +//#define GLEW_STATIC // Optional, depending on which glew lib you want to use +#ifdef __APPLE__ // or __MACOSX__ ? +# include // guessing... +#else //__APPLE +# include +#endif //__APPLE +#else //IMIMPL_USE_GLEW +#define GL_GLEXT_PROTOTYPES +#endif //IMIMPL_USE_GLEW +//#define GLFW_STATIC +#include +#ifdef _WIN32 +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include +#endif + +#include "ImImpl_RenderDrawLists.h" + + + + +static GLFWwindow* window; +//static bool mousePressed[2] = { false, false }; +static ImVec2 mousePosScale(1.0f, 1.0f); + + +// NB: ImGui already provide OS clipboard support for Windows so this isn't needed if you are using Windows only. +static const char* ImImpl_GetClipboardTextFn() +{ + return glfwGetClipboardString(window); +} + +static void ImImpl_SetClipboardTextFn(const char* text) +{ + glfwSetClipboardString(window, text); +} + +#ifdef _WIN32 +// Notify OS Input Method Editor of text input position (e.g. when using Japanese/Chinese inputs, otherwise this isn't needed) +static void ImImpl_ImeSetInputScreenPosFn(int x, int y) +{ + HWND hwnd = glfwGetWin32Window(window); + if (HIMC himc = ImmGetContext(hwnd)) + { + COMPOSITIONFORM cf; + cf.ptCurrentPos.x = x; + cf.ptCurrentPos.y = y; + cf.dwStyle = CFS_FORCE_POSITION; + ImmSetCompositionWindow(himc, &cf); + } +} +#endif + +// GLFW callbacks to get events +static void glfw_error_callback(int error, const char* description) { + fputs(description, stderr); +} +static bool gImGuiAppIsIconified = false; +static void glfw_window_iconify_callback(GLFWwindow* window,int iconified) { + gImGuiAppIsIconified = iconified == GL_TRUE; +} +static void glfw_framebuffer_size_callback(GLFWwindow* window,int fb_w,int fb_h) { + int w, h;glfwGetWindowSize(window, &w, &h); + mousePosScale.x = (float)fb_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates. + mousePosScale.y = (float)fb_h / h; + + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2((float)fb_w, (float)fb_h); +} +static void glfw_window_size_callback(GLFWwindow* window,int w,int h) { + int fb_w, fb_h;glfwGetFramebufferSize(window, &fb_w, &fb_h); + mousePosScale.x = (float)fb_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates. + mousePosScale.y = (float)fb_h / h; + ResizeGL(w,h); +} +static bool gImGuiBindingMouseDblClicked[5]={false,false,false,false,false}; +static void glfw_mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { + ImGuiIO& io = ImGui::GetIO(); + if (button >= 0 && button < 5) { + io.MouseDown[button] = (action == GLFW_PRESS); + // Manual double click handling: + static double dblClickTimes[6]={-FLT_MAX,-FLT_MAX,-FLT_MAX,-FLT_MAX,-FLT_MAX,-FLT_MAX}; // seconds + if (action == GLFW_PRESS) { + double time = glfwGetTime(); + double& oldTime = dblClickTimes[button]; + bool& mouseDoubleClicked = gImGuiBindingMouseDblClicked[button]; + if (time - oldTime < io.MouseDoubleClickTime) { + mouseDoubleClicked = true; + oldTime = -FLT_MAX; + //fprintf(stderr,"Double Clicked button %d\n",button); + } + else { + //fprintf(stderr,"Not Double Clicked button %d (%1.4f < %1.4f)\n",button,(float)time-(float)oldTime,io.MouseDoubleClickTime); + mouseDoubleClicked = false; + oldTime = time; + } + } + } + io.KeyCtrl = (mods & GLFW_MOD_CONTROL); + io.KeyShift = (mods & GLFW_MOD_SHIFT); + +} +static void glfw_scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { + ImGuiIO& io = ImGui::GetIO(); + io.MouseWheel = (yoffset != 0.0f) ? yoffset > 0.0f ? 1 : - 1 : 0; // Mouse wheel: -1,0,+1 +} +static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { + ImGuiIO& io = ImGui::GetIO(); + if (action == GLFW_PRESS) io.KeysDown[key] = true; + if (action == GLFW_RELEASE) io.KeysDown[key] = false; + io.KeyCtrl = (mods & GLFW_MOD_CONTROL); + io.KeyShift = (mods & GLFW_MOD_SHIFT); +} +static void glfw_char_callback(GLFWwindow* window, unsigned int c) { + if (c > 0 && c < 0x10000) + ImGui::GetIO().AddInputCharacter((unsigned short)c); +} +static void glfw_mouse_enter_leave_callback(GLFWwindow* window, int entered) { + if (entered==GL_FALSE) { + ImGuiIO& io = ImGui::GetIO(); + io.MousePos.x=io.MousePos.y=-1.f; + } +} +static void glfw_mouse_move_callback(GLFWwindow* window, double x,double y) { + ImGuiIO& io = ImGui::GetIO(); + io.MousePos = ImVec2((float)x * mousePosScale.x, (float)y * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) +} +static void InitImGui(const ImImpl_InitParams* pOptionalInitParams=NULL) { + int w, h; + int fb_w, fb_h; + glfwGetWindowSize(window, &w, &h); + glfwGetFramebufferSize(window, &fb_w, &fb_h); + mousePosScale.x = (float)fb_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates. + mousePosScale.y = (float)fb_h / h; + + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2((float)fb_w, (float)fb_h); // Display size, in pixels. For clamping windows positions. + io.DeltaTime = 1.0f/60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable) + io.PixelCenterOffset = 0.0f; // Align OpenGL texels + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; + io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; + io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; + io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; + io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; + io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; + io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; + io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + + io.RenderDrawListsFn = ImImpl_RenderDrawLists; + io.SetClipboardTextFn = ImImpl_SetClipboardTextFn; + io.GetClipboardTextFn = ImImpl_GetClipboardTextFn; +#ifdef _WIN32 + io.ImeSetInputScreenPosFn = ImImpl_ImeSetInputScreenPosFn; +#endif + + // 3 common init steps + InitImGuiFontTexture(pOptionalInitParams); + InitImGuiProgram(); + InitImGuiBuffer(); +} + +static bool InitBinding(const ImImpl_InitParams* pOptionalInitParams=NULL,int argc=0, char** argv=NULL) { + glfwSetErrorCallback(glfw_error_callback); + + if (!glfwInit()) { + fprintf(stderr, "Could not call glfwInit(...) successfully.\n"); + return false; + } + +//-ENABLE-OPENGLES COMPATIBILITY PROFILES---------------------------------- +#ifndef IMIMPL_SHADER_NONE +#ifdef IMIMPL_SHADER_GLES +# ifndef IMIMPL_SHADER_GL3 + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); // 1 => ES1.1 2 => ES2.0 3 => ES3.0 +# else //IMIMPL_SHADER_GL3 + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); +# endif //MIMPL_SHADER_GL3 + glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); +#endif // IMIMPL_SHADER_GLES +#endif //IMIMPL_SHADER_NONE +//-------------------------------------------------------------------------- + //glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE); + + if (pOptionalInitParams && pOptionalInitParams->gWindowTitle[0]!='\0') window = glfwCreateWindow(pOptionalInitParams ? pOptionalInitParams->gWindowSize.x : 1270, pOptionalInitParams ? pOptionalInitParams->gWindowSize.y : 720,(const char*) &pOptionalInitParams->gWindowTitle[0], NULL, NULL); + else window = glfwCreateWindow(pOptionalInitParams ? pOptionalInitParams->gWindowSize.x : 1270, pOptionalInitParams ? pOptionalInitParams->gWindowSize.y : 720, "ImGui Glfw3 OpenGL example", NULL, NULL); + if (!window) { + fprintf(stderr, "Could not call glfwCreateWindow(...) successfully.\n"); + return false; + } + glfwMakeContextCurrent(window); + glfwSetKeyCallback(window, glfw_key_callback); + glfwSetMouseButtonCallback(window, glfw_mouse_button_callback); + glfwSetScrollCallback(window, glfw_scroll_callback); + glfwSetCharCallback(window, glfw_char_callback); + glfwSetCursorPosCallback(window, glfw_mouse_move_callback); + glfwSetCursorEnterCallback(window, glfw_mouse_enter_leave_callback); + + glfwSetWindowSizeCallback(window, glfw_window_size_callback); + glfwSetFramebufferSizeCallback(window, glfw_framebuffer_size_callback); + glfwSetWindowIconifyCallback(window, glfw_window_iconify_callback); + + //OpenGL info + { + printf("GL Vendor: %s\n", glGetString( GL_VENDOR )); + printf("GL Renderer : %s\n", glGetString( GL_RENDERER )); + printf("GL Version (string) : %s\n", glGetString( GL_VERSION )); + printf("GLSL Version : %s\n", glGetString( GL_SHADING_LANGUAGE_VERSION )); + //printf("GL Extensions:\n%s\n",(char *) glGetString(GL_EXTENSIONS)); + } + +#ifdef IMIMPL_USE_GLEW + GLenum err = glewInit(); + if( GLEW_OK != err ) + { + fprintf(stderr, "Error initializing GLEW: %s\n", + glewGetErrorString(err) ); + return false; + } +#endif //IMIMPL_USE_GLEW + + return true; +} + +// Application code +int ImImpl_Main(const ImImpl_InitParams* pOptionalInitParams=NULL,int argc=0, char** argv=NULL) +{ + if (!InitBinding(pOptionalInitParams,argc,argv)) return -1; + InitImGui(pOptionalInitParams); + ImGuiIO& io = ImGui::GetIO(); + + InitGL(); + ResizeGL(io.DisplaySize.x,io.DisplaySize.y); + + static double time = 0.0f; + + gImGuiInverseFPSClamp = pOptionalInitParams ? ((pOptionalInitParams->gFpsClamp!=0) ? (1.0f/pOptionalInitParams->gFpsClamp) : 1.0f) : -1.0f; + + while (!glfwWindowShouldClose(window)) + { + if (!gImGuiPaused) for (size_t i = 0; i < 5; i++) gImGuiBindingMouseDblClicked[i] = false; // We manually set it (otherwise it won't work with low frame rates) + if (gImGuiAppIsIconified) { + //fprintf(stderr,"glfwWaitEvents() Start %1.4f\n",glfwGetTime()); + glfwWaitEvents(); + //fprintf(stderr,"glfwWaitEvents() End %1.4f\n",glfwGetTime()); + } + else glfwPollEvents(); + + // Setup timestep + const double current_time = glfwGetTime(); + io.DeltaTime = (float)(current_time - time); + time = current_time; + + // If needed we must wait (inverseFPSClamp-io.DeltaTime) seconds (=> honestly I shouldn't add the * 2.0f factor at the end, but ImGui tells me the wrong FPS otherwise... why? <=) + if (gImGuiInverseFPSClamp>0 && io.DeltaTime < gImGuiInverseFPSClamp) WaitFor((unsigned int) ((gImGuiInverseFPSClamp-io.DeltaTime)*1000.f * 2.0f) ); + + if (!gImGuiPaused) { + // Start the frame + ImGui::NewFrame(); + for (size_t i = 0; i < 5; i++) { + io.MouseDoubleClicked[i]=gImGuiBindingMouseDblClicked[i]; // We manually set it (otherwise it won't work with low frame rates) + } + } + + DrawGL(); + + if (!gImGuiPaused) { + // Rendering + glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); + //glClearColor(0.8f, 0.6f, 0.6f, 1.0f); + //glClear(GL_COLOR_BUFFER_BIT); + ImGui::Render(); + } + + glfwSwapBuffers(window); + } + + DestroyGL(); + ImGui::Shutdown(); + DestroyImGuiFontTexture(); + DestroyImGuiProgram(); + DestroyImGuiBuffer(); + glfwTerminate(); + return 0; +} + +#endif //#ifndef IMIMPL_BINDING_H + diff --git a/examples/opengl_various_bindings/ImImpl_Binding_Glut.h b/examples/opengl_various_bindings/ImImpl_Binding_Glut.h new file mode 100644 index 000000000..ad56d045e --- /dev/null +++ b/examples/opengl_various_bindings/ImImpl_Binding_Glut.h @@ -0,0 +1,429 @@ +#ifndef IMIMPL_BINDING_H +#define IMIMPL_BINDING_H + +#ifdef _WIN32 +#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#include +#include +#endif +#include + + +// glew (optional) & glut +#ifdef IMIMPL_USE_GLEW +#ifdef __APPLE__ // or __MACOSX__ ? +# include // guessing... +#else //__APPLE +# include +#endif //__APPLE +#else //IMIMPL_USE_GLEW +#define GL_GLEXT_PROTOTYPES +#endif //IMIMPL_USE_GLEW +#ifdef __APPLE__ // or __MACOSX__ ? +# include // guessing... +#else //__APPLE +# include +#endif //__APPLE +#ifdef __FREEGLUT_STD_H__ +#ifdef __APPLE__ // or __MACOSX__ ? +# include // guessing... +#else //__APPLE +# include +#endif //__APPLE +#endif //__FREEGLUT_STD_H__ + +#include "ImImpl_RenderDrawLists.h" + + + +static ImVec2 mousePosScale(1.0f, 1.0f); + +// NB: ImGui already provide OS clipboard support for Windows so this isn't needed if you are using Windows only. +#ifndef _WIN32 +// If somebody implements these, in InitImGui(...) these callbacks MUST be set (they're currently detached). +// The default fallback on non-Windows OS is a "private" clipboard. +static const char* ImImpl_GetClipboardTextFn() +{ + //fprintf(stderr,"ImImpl_GetClipboardTextFn()\n"); + static char* txt = "copy and paste not implemented in the glut backend!"; + //return SDL_GetClipboardText(); + return txt; +} +static void ImImpl_SetClipboardTextFn(const char* text) +{ + //fprintf(stderr,"ImImpl_SetClipboardTextFn()\n"); + //SDL_SetClipboardText(text); +} +#endif //_WIN32 + +// TODO: once we can extract the HWND from glut... +/* +#ifdef _WIN32 +// Notify OS Input Method Editor of text input position (e.g. when using Japanese/Chinese inputs, otherwise this isn't needed) +static void ImImpl_ImeSetInputScreenPosFn(int x, int y) +{ + HWND hwnd = glfwGetWin32Window(window); + if (HIMC himc = ImmGetContext(hwnd)) + { + COMPOSITIONFORM cf; + cf.ptCurrentPos.x = x; + cf.ptCurrentPos.y = y; + cf.dwStyle = CFS_FORCE_POSITION; + ImmSetCompositionWindow(himc, &cf); + } +} +#endif +*/ + +static void GlutReshapeFunc(int w,int h) { + int fb_w, fb_h; + fb_w = w; + fb_h = h; + //glfwGetFramebufferSize(window, &fb_w, &fb_h); + mousePosScale.x = 1.f;//(float)fb_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates. + mousePosScale.y = 1.f;//(float)fb_h / h; + + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2((float)fb_w, (float)fb_h); // Display size, in pixels. For clamping windows positions. + + ResizeGL(w,h); +} +static void GlutEntryFunc(int a) { + //fprintf(stderr,"GlutEntryFunc %d\n",a); + if (a==0){ + ImGuiIO& io = ImGui::GetIO(); + io.MousePos.x = io.MousePos.y = -1; + } +} +static bool gImGuiAppIconized = false; // stays always false (I'm not able to detect when the user minimizes a window) +/* +// This method gets never called on my system: +static void GlutVisibilityFunc(int a) { + fprintf(stderr,"GlutVisibilityFunc %d\n",a); + gImGuiAppIconized = a == GL_TRUE; +} +// This gets called, but does not provide the info I'm looking for +static void GlutWindowStatusFunc(int a) { + fprintf(stderr,"GlutWindowStatusFunc %d\n",a); + //gImGuiAppIconized = a == GL_TRUE; +}*/ +static inline void GlutSpecialUpDown(int key,int x,int y,bool down) { + + ImGuiIO& io = ImGui::GetIO(); + + const int mods = glutGetModifiers(); + io.KeyCtrl = (mods&GLUT_ACTIVE_CTRL) != 0; + io.KeyShift = (mods&GLUT_ACTIVE_SHIFT) != 0; + io.MousePos.x = x;io.MousePos.y = y; + + if (key>=0 && key<512) io.KeysDown[key] = down; +} +static void GlutSpecial(int key,int x,int y) { + GlutSpecialUpDown(key,x,y,true); +} +static void GlutSpecialUp(int key,int x,int y) { + GlutSpecialUpDown(key,x,y,false); +} +static inline void GlutKeyboardUpDown(unsigned char key,int x,int y,bool down) { + + ImGuiIO& io = ImGui::GetIO(); + + const int mods = glutGetModifiers(); + io.KeyCtrl = (mods&GLUT_ACTIVE_CTRL) != 0; + io.KeyShift = (mods&GLUT_ACTIVE_SHIFT) != 0; + io.MousePos.x = x;io.MousePos.y = y; + + if ( key!=GLUT_KEY_LEFT && key!=GLUT_KEY_RIGHT && + key!=GLUT_KEY_UP && key!=GLUT_KEY_DOWN && + key!=GLUT_KEY_HOME && key!=GLUT_KEY_END + ) { + io.KeysDown[key] = down; + } + + if (down) io.AddInputCharacter(key); +} +static void GlutKeyboard(unsigned char key,int x,int y) { + GlutKeyboardUpDown(key,x,y,true); +} +static void GlutKeyboardUp(unsigned char key,int x,int y) { + GlutKeyboardUpDown(key,x,y,false); +} +static bool gImGuiBindingMouseDblClicked[5]={false,false,false,false,false}; +static void GlutMouse(int b,int s,int x,int y) { + //fprintf(stderr,"GlutMouse(%d,%d,%d,%d);\n",b,s,x,y); + ImGuiIO& io = ImGui::GetIO(); + const int mods = glutGetModifiers(); + io.KeyCtrl = (mods&GLUT_ACTIVE_CTRL) != 0; + io.KeyShift = (mods&GLUT_ACTIVE_SHIFT) != 0; + io.MousePos.x = x;io.MousePos.y = y; + if (b>=0 && b<5) { + io.MouseDown[b] = (s==0); +# ifndef _WIN32 + if (s==0) io.MouseWheel = b==3 ? 1 : b==4 ? -1 : 0; +# endif //_WIN32 + // Manual double click handling: + static double dblClickTimes[6]={-FLT_MAX,-FLT_MAX,-FLT_MAX,-FLT_MAX,-FLT_MAX,-FLT_MAX}; // seconds + if (s == 0) { + double time = glutGet(GLUT_ELAPSED_TIME); + double& oldTime = dblClickTimes[b]; + bool& mouseDoubleClicked = gImGuiBindingMouseDblClicked[b]; + if (time - oldTime < io.MouseDoubleClickTime*1000.f) { + mouseDoubleClicked = true; + oldTime = -FLT_MAX; + //fprintf(stderr,"Double Clicked button %d\n",button); + } + else { + //fprintf(stderr,"Not Double Clicked button %d (%1.4f < %1.4f)\n",button,(float)time-(float)oldTime,io.MouseDoubleClickTime); + mouseDoubleClicked = false; + oldTime = time; + } + } + } +} +#ifdef _WIN32 +static void GlutMouseWheel(int b,int s,int x,int y) { + //fprintf(stderr,"GlutMouseWheel(%d,%d,%d,%d);\n",b,s,x,y); + ImGuiIO& io = ImGui::GetIO(); + const int mods = glutGetModifiers(); + io.KeyCtrl = (mods&GLUT_ACTIVE_CTRL) != 0; + io.KeyShift = (mods&GLUT_ACTIVE_SHIFT) != 0; + io.MousePos.x = x;io.MousePos.y = y; + // NEVER TESTED !!!!!!!! + if (s==0) io.MouseWheel = b==0 ? 1 : b==1 ? -1 : 0; +} +#endif //_WIN32 + +static void GlutMotion(int x,int y) { + ImGuiIO& io = ImGui::GetIO(); + //const int mods = glutGetModifiers(); + //io.KeyCtrl = (mods&GLUT_ACTIVE_CTRL) != 0; + //io.KeyShift = (mods&GLUT_ACTIVE_SHIFT) != 0; + io.MousePos.x = x;io.MousePos.y = y; +} +static void GlutPassiveMotion(int x,int y) { + ImGuiIO& io = ImGui::GetIO(); + //const int mods = glutGetModifiers(); + //io.KeyCtrl = (mods&GLUT_ACTIVE_CTRL) != 0; + //io.KeyShift = (mods&GLUT_ACTIVE_SHIFT) != 0; + io.MousePos.x = x;io.MousePos.y = y; +} +static void GlutDrawGL() { + ImGuiIO& io = ImGui::GetIO(); + if (gImGuiAppIconized) WaitFor(1000); + + // Setup timestep + static double time = 0.0f; + const double current_time = (double) glutGet(GLUT_ELAPSED_TIME); + io.DeltaTime = (float) ((current_time - time)*0.001); + time = current_time; + if (io.DeltaTime<=0) io.DeltaTime = (1.0f/60.0f); + + // If needed we must wait (gImGuiInverseFPSClamp-io.DeltaTime) seconds (=> honestly I shouldn't add the * 2.0f factor at the end, but ImGui tells me the wrong FPS otherwise... why? <=) + if (gImGuiInverseFPSClamp>0 && io.DeltaTime < gImGuiInverseFPSClamp) WaitFor((unsigned int) ((gImGuiInverseFPSClamp-io.DeltaTime)*1000.f * 2.0f) ); + + if (!gImGuiPaused) { + // Start the frame + ImGui::NewFrame(); + for (size_t i = 0; i < 5; i++) { + io.MouseDoubleClicked[i]=gImGuiBindingMouseDblClicked[i]; // We manually set it (otherwise it won't work with low frame rates) + } + } + + DrawGL(); + + if (!gImGuiPaused) { + // Rendering + glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); + //glClearColor(0.8f, 0.6f, 0.6f, 1.0f); + //glClear(GL_COLOR_BUFFER_BIT); + ImGui::Render(); + } + + glutSwapBuffers(); + if (!gImGuiPaused) for (size_t i = 0; i < 5; i++) gImGuiBindingMouseDblClicked[i] = false; // We manually set it (otherwise it won't work with low frame rates) +} +static void GlutIdle(void) { + glutPostRedisplay(); // TODO: Well, we could sleep a bit here if we detect that the window is minimized... +} +static void GlutFakeDrawGL() { + glutDisplayFunc(GlutDrawGL); +} + + +static void InitImGui(const ImImpl_InitParams* pOptionalInitParams=NULL) { + //fprintf(stderr,"InitImGui(%d,%d);\n",w,h); + //int w, h; + int fb_w, fb_h; + fb_w = glutGet(GLUT_WINDOW_WIDTH); + fb_h = glutGet(GLUT_WINDOW_HEIGHT); + //glfwGetFramebufferSize(window, &fb_w, &fb_h); + mousePosScale.x = 1.f;//(float)fb_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates. + mousePosScale.y = 1.f;//(float)fb_h / h; + + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2((float)fb_w, (float)fb_h); // Display size, in pixels. For clamping windows positions. + io.DeltaTime = 1.0f/60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable) + io.PixelCenterOffset = 0.0f; // Align OpenGL texels + + // Set up ImGui + io.KeyMap[ImGuiKey_Tab] = 9; // tab (ascii) + + io.KeyMap[ImGuiKey_LeftArrow] = GLUT_KEY_LEFT; // Left + io.KeyMap[ImGuiKey_RightArrow] = GLUT_KEY_RIGHT; // Right + io.KeyMap[ImGuiKey_UpArrow] = GLUT_KEY_UP; // Up + io.KeyMap[ImGuiKey_DownArrow] = GLUT_KEY_DOWN; // Down + io.KeyMap[ImGuiKey_Home] = GLUT_KEY_HOME; // Home + io.KeyMap[ImGuiKey_End] = GLUT_KEY_END; // End + + io.KeyMap[ImGuiKey_Delete] = 127; // Delete (ascii) (0x006F) + io.KeyMap[ImGuiKey_Backspace] = 8; // Backspace (ascii) + io.KeyMap[ImGuiKey_Enter] = 13; // Enter (ascii) + io.KeyMap[ImGuiKey_Escape] = 27; // Escape (ascii) + io.KeyMap[ImGuiKey_A] = 1; + io.KeyMap[ImGuiKey_C] = 3; + io.KeyMap[ImGuiKey_V] = 22; + io.KeyMap[ImGuiKey_X] = 24; + io.KeyMap[ImGuiKey_Y] = 25; + io.KeyMap[ImGuiKey_Z] = 26; + + io.RenderDrawListsFn = ImImpl_RenderDrawLists; +#ifndef _WIN32 + //io.SetClipboardTextFn = ImImpl_SetClipboardTextFn; + //io.GetClipboardTextFn = ImImpl_GetClipboardTextFn; +#endif +#ifdef _WIN32 + //io.ImeSetInputScreenPosFn = ImImpl_ImeSetInputScreenPosFn; +#endif + + // 3 common init steps + InitImGuiFontTexture(pOptionalInitParams); + InitImGuiProgram(); + InitImGuiBuffer(); +} + +static bool InitBinding(const ImImpl_InitParams* pOptionalInitParams=NULL,int argc=0, char** argv=NULL) { + +//-ENABLE-OPENGLES COMPATIBILITY PROFILES---------------------------------- +/* // Don't know how to make this work... for sure, + * // "custom" freeglut compiled with -legl -lglesv2 can do it, + * // but otherwie it seems that the required profile definition is missing ATM. + * // Moreover, I'm not sure that the glutInitContextMethods (defined in freeglut_ext.h) + * // can be called at this point... +*/ +/* +#ifndef IMIMPL_SHADER_NONE +#ifdef IMIMPL_SHADER_GLES +# ifndef IMIMPL_SHADER_GL3 + glutInitContextVersion( 2, 0); +# else //IMIMPL_SHADER_GL3 + glutInitContextVersion( 3, 0); +# endif //MIMPL_SHADER_GL3 + //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); // GLFW3 can do it! + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_ES); // SDL2 can do it too! + + // What about freeglut? + glutInitContextProfile( GLUT_ES_PROFILE ); //GLUT_CORE_PROFILE GLUT_COMPATIBILITY_PROFILE + //glutInitContextVersion( int majorVersion, int minorVersion ); + //glutInitContextFlags( int flags ); //GLUT_DEBUG GLUT_FORWARD_COMPATIBLE + //glutInitContextProfile( int profile ); //GLUT_CORE_PROFILE GLUT_COMPATIBILITY_PROFILE +#endif // IMIMPL_SHADER_GLES +#endif //IMIMPL_SHADER_NONE +*/ +//-------------------------------------------------------------------------- + + + glutInitDisplayMode(GLUT_RGB | GLUT_ALPHA | GLUT_DEPTH | GLUT_DOUBLE);// | GLUT_MULTISAMPLE | GLUT_SRGB); // The latter is defined in freeglut_ext.h + glutInitWindowSize(pOptionalInitParams ? pOptionalInitParams->gWindowSize.x : 1270, pOptionalInitParams ? pOptionalInitParams->gWindowSize.y : 720); + //int screenWidth = glutGet(GLUT_SCREEN_WIDTH); + //glutInitWindowPosition(5 * screenWidth/ 12, 0); + glutInit(&argc, argv); + if (!glutCreateWindow((pOptionalInitParams && pOptionalInitParams->gWindowTitle[0]!='\0') ? (const char*) &pOptionalInitParams->gWindowTitle[0] : "ImGui Glut OpenGL example")) + { + fprintf(stderr, "Could not call glutCreateWindow(...) successfully.\n"); + return false; + } + + //OpenGL info + { + printf("GL Vendor: %s\n", glGetString( GL_VENDOR )); + printf("GL Renderer : %s\n", glGetString( GL_RENDERER )); + printf("GL Version (string) : %s\n", glGetString( GL_VERSION )); + printf("GLSL Version : %s\n", glGetString( GL_SHADING_LANGUAGE_VERSION )); + //printf("GL Extensions:\n%s\n",(char *) glGetString(GL_EXTENSIONS)); + } + +#ifdef IMIMPL_USE_GLEW + GLenum err = glewInit(); + if( GLEW_OK != err ) + { + fprintf(stderr, "Error initializing GLEW: %s\n", + glewGetErrorString(err) ); + return false; + } +#endif //IMIMPL_USE_GLEW + + + // Set up glut callbacks + glutIdleFunc(GlutIdle); + glutReshapeFunc(GlutReshapeFunc); + //glutDisplayFunc(GlutDrawGL); + + //glutInitContextFunc(InitGL); // freeglut3 only: call order: ResizeGL() - InitGL() - DrawGL() + //InitGL(); // call order: InitGL() - DrawGL() - ResizeGL() + + //But I prefer call order: InitGL() - ResizeGL() - DrawGL(): + // this can be achieved by skipping the first DrawGL call this way: + glutDisplayFunc(GlutFakeDrawGL); + + glutKeyboardFunc(GlutKeyboard); + glutKeyboardUpFunc(GlutKeyboardUp); + glutSpecialFunc(GlutSpecial); + glutSpecialUpFunc(GlutSpecialUp); + glutMouseFunc(GlutMouse); // This handles mouse wheel as well on non-Windows systems + glutMotionFunc(GlutMotion); + glutPassiveMotionFunc(GlutPassiveMotion); + + glutEntryFunc(GlutEntryFunc); + + // Apparently, there's no way to detect when the user minimizes a window using glut (at least on my system these callbacks don't provide this info) + //glutVisibilityFunc(GlutVisibilityFunc); // never called + //glutWindowStatusFunc(GlutWindowStatusFunc); // called on resizing too + +#ifdef _WIN32 + glutMouseWheelFunc(GlutMouseWheel); +#endif //_WIN32 + + return true; +} + +// Application code +int ImImpl_Main(const ImImpl_InitParams* pOptionalInitParams=NULL,int argc=0, char** argv=NULL) +{ + if (!InitBinding(pOptionalInitParams,argc,argv)) return -1; + InitImGui(pOptionalInitParams); + ImGuiIO& io = ImGui::GetIO(); + + gImGuiInverseFPSClamp = pOptionalInitParams ? ((pOptionalInitParams->gFpsClamp!=0) ? (1.0f/pOptionalInitParams->gFpsClamp) : 1.0f) : -1.0f; + + InitGL(); + ResizeGL((int)io.DisplaySize.x,(int)io.DisplaySize.y); + + + +#ifdef __FREEGLUT_EXT_H__ + glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ; +#endif //__FREEGLUT_STD_H__ + + glutMainLoop(); // GLUT has its own main loop, which calls display(); + + ImGui::Shutdown(); + DestroyGL(); + DestroyImGuiFontTexture(); + DestroyImGuiProgram(); + DestroyImGuiBuffer(); + + return 0; +} + +#endif //#ifndef IMIMPL_BINDING_H + diff --git a/examples/opengl_various_bindings/ImImpl_Binding_SDL2.h b/examples/opengl_various_bindings/ImImpl_Binding_SDL2.h new file mode 100644 index 000000000..be5a43abb --- /dev/null +++ b/examples/opengl_various_bindings/ImImpl_Binding_SDL2.h @@ -0,0 +1,359 @@ +#ifndef IMIMPL_BINDING_H +#define IMIMPL_BINDING_H + +#ifdef _WIN32 +#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#include +#include +#endif +#include + + +// glew (optional) & glfw +#ifdef IMIMPL_USE_GLEW +//#define GLEW_STATIC // Optional, depending on which glew lib you want to use +#ifdef __APPLE__ // or __MACOSX__ ? +# include // guessing... +#else //__APPLE +# include +#endif //__APPLE +#else //IMIMPL_USE_GLEW +#define GL_GLEXT_PROTOTYPES +#if (!defined(IMIMPL_SHADER_GLES) || defined (IMIMPL_SHADER_NONE)) +#include +#else //IMIMPL_SHADER_GLES +#include +#endif //IMIMPL_SHADER_GLES +#endif //IMIMPL_USE_GLEW +#include + +#define IMIMPL_SDL2_USE_STL // Different handling of SDL_KEYDOWN/SDL_KEYUP events +#ifdef IMIMPL_SDL2_USE_STL +#include // we could work around this dependency if needed +static std::map specialKeyMap; +#endif //IMIMPL_SDL2_USE_STL + +#include "ImImpl_RenderDrawLists.h" + +static SDL_Window* window = NULL; +static ImVec2 mousePosScale(1.0f, 1.0f); + + +// NB: ImGui already provide OS clipboard support for Windows so this isn't needed if you are using Windows only. +static const char* ImImpl_GetClipboardTextFn() +{ + return SDL_GetClipboardText(); +} + +static void ImImpl_SetClipboardTextFn(const char* text) +{ + SDL_SetClipboardText(text); +} +// TODO: once we can find out how to get a HWND from SDL2 +/* +#ifdef _WIN32 +// Notify OS Input Method Editor of text input position (e.g. when using Japanese/Chinese inputs, otherwise this isn't needed) +static void ImImpl_ImeSetInputScreenPosFn(int x, int y) +{ + HWND hwnd = glfwGetWin32Window(window); + if (HIMC himc = ImmGetContext(hwnd)) + { + COMPOSITIONFORM cf; + cf.ptCurrentPos.x = x; + cf.ptCurrentPos.y = y; + cf.dwStyle = CFS_FORCE_POSITION; + ImmSetCompositionWindow(himc, &cf); + } +} +#endif +*/ + + +static void InitImGui(const ImImpl_InitParams* pOptionalInitParams=NULL) { + //int w, h; + int fb_w, fb_h; + SDL_GetWindowSize(window, &fb_w, &fb_h); + //glfwGetFramebufferSize(window, &fb_w, &fb_h); + mousePosScale.x = 1.f;//(float)fb_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates. + mousePosScale.y = 1.f;//(float)fb_h / h; + + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2((float)fb_w, (float)fb_h); // Display size, in pixels. For clamping windows positions. + io.DeltaTime = 1.0f/60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable) + io.PixelCenterOffset = 0.0f; // Align OpenGL texels + +# ifdef IMIMPL_SDL2_USE_STL + specialKeyMap.clear();const int numKeyMaps = 512; + int cnt = 1; + io.KeyMap[ImGuiKey_Tab] = specialKeyMap[SDLK_TAB] = numKeyMaps - cnt++; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = specialKeyMap[SDLK_LEFT] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_RightArrow] = specialKeyMap[SDLK_RIGHT] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_UpArrow] = specialKeyMap[SDLK_UP] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_DownArrow] = specialKeyMap[SDLK_DOWN] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_Home] = specialKeyMap[SDLK_HOME] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_End] = specialKeyMap[SDLK_END] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_Delete] = specialKeyMap[SDLK_DELETE] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_Backspace] = specialKeyMap[SDLK_BACKSPACE] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_Enter] = specialKeyMap[SDLK_RETURN] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_Escape] = specialKeyMap[SDLK_ESCAPE] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_A] = specialKeyMap[SDLK_a] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_C] = specialKeyMap[SDLK_c] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_V] = specialKeyMap[SDLK_v] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_X] = specialKeyMap[SDLK_x] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_Y] = specialKeyMap[SDLK_y] = numKeyMaps - cnt++; + io.KeyMap[ImGuiKey_Z] = specialKeyMap[SDLK_z] = numKeyMaps - cnt++; +# else //IMIMPL_SDL2_USE_STL + // thanks to mattiasljungstrom: + io.KeyMap[ImGuiKey_Tab] = SDL_GetScancodeFromKey( SDLK_TAB ); + io.KeyMap[ImGuiKey_LeftArrow] = SDL_GetScancodeFromKey( SDLK_LEFT ); + io.KeyMap[ImGuiKey_RightArrow] = SDL_GetScancodeFromKey( SDLK_RIGHT ); + io.KeyMap[ImGuiKey_UpArrow] = SDL_GetScancodeFromKey( SDLK_UP ); + io.KeyMap[ImGuiKey_DownArrow] = SDL_GetScancodeFromKey( SDLK_DOWN ); + io.KeyMap[ImGuiKey_Home] = SDL_GetScancodeFromKey( SDLK_HOME ); + io.KeyMap[ImGuiKey_End] = SDL_GetScancodeFromKey( SDLK_END ); + io.KeyMap[ImGuiKey_Delete] = SDL_GetScancodeFromKey( SDLK_DELETE ); + io.KeyMap[ImGuiKey_Backspace] = SDL_GetScancodeFromKey( SDLK_BACKSPACE ); + io.KeyMap[ImGuiKey_Enter] = SDL_GetScancodeFromKey( SDLK_RETURN ); + io.KeyMap[ImGuiKey_Escape] = SDL_GetScancodeFromKey( SDLK_ESCAPE ); + io.KeyMap[ImGuiKey_A] = SDLK_a; + io.KeyMap[ImGuiKey_C] = SDLK_c; + io.KeyMap[ImGuiKey_V] = SDLK_v; + io.KeyMap[ImGuiKey_X] = SDLK_x; + io.KeyMap[ImGuiKey_Y] = SDLK_y; + io.KeyMap[ImGuiKey_Z] = SDLK_z; +# endif //IMIMPL_SDL2_USE_STL + + io.RenderDrawListsFn = ImImpl_RenderDrawLists; + io.SetClipboardTextFn = ImImpl_SetClipboardTextFn; + io.GetClipboardTextFn = ImImpl_GetClipboardTextFn; +#ifdef _MSC_VER + //io.ImeSetInputScreenPosFn = ImImpl_ImeSetInputScreenPosFn; +#endif + + // 3 common init steps + InitImGuiFontTexture(pOptionalInitParams); + InitImGuiProgram(); + InitImGuiBuffer(); +} + +static bool InitBinding(const ImImpl_InitParams* pOptionalInitParams=NULL,int argc=0, char** argv=NULL) { + + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { + fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return false; + } + + // Init OpenGL + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + +//-ENABLE-OPENGLES COMPATIBILITY PROFILES---------------------------------- +#ifndef IMIMPL_SHADER_NONE +#ifdef IMIMPL_SHADER_GLES +# ifndef IMIMPL_SHADER_GL3 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); // 1 => ES1.1 2 => ES2.0 3 => ES3.0 +# else //IMIMPL_SHADER_GL3 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); +# endif //MIMPL_SHADER_GL3 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_ES); +#endif // IMIMPL_SHADER_GLES +#endif //IMIMPL_SHADER_NONE +//-------------------------------------------------------------------------- + + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS,); + //SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE,1); + + window = SDL_CreateWindow((pOptionalInitParams && pOptionalInitParams->gWindowTitle[0]!='\0') ? (const char*) &pOptionalInitParams->gWindowTitle[0] : "ImGui SDL2 OpenGL example", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + pOptionalInitParams ? pOptionalInitParams->gWindowSize.x : 1270, + pOptionalInitParams ? pOptionalInitParams->gWindowSize.y : 720, + SDL_WINDOW_RESIZABLE | + SDL_WINDOW_OPENGL + ); + if (!window) + { + fprintf(stderr, "Could not call SDL_CreateWindow(...) successfully.\n"); + return false; + } + + SDL_GL_CreateContext(window); + + //OpenGL info + { + printf("GL Vendor: %s\n", glGetString( GL_VENDOR )); + printf("GL Renderer : %s\n", glGetString( GL_RENDERER )); + printf("GL Version (string) : %s\n", glGetString( GL_VERSION )); + printf("GLSL Version : %s\n", glGetString( GL_SHADING_LANGUAGE_VERSION )); + //printf("GL Extensions:\n%s\n",(char *) glGetString(GL_EXTENSIONS)); + } + +#ifdef IMIMPL_USE_GLEW + GLenum err = glewInit(); + if( GLEW_OK != err ) + { + fprintf(stderr, "Error initializing GLEW: %s\n", + glewGetErrorString(err) ); + return false; + } +#endif //IMIMPL_USE_GLEW + + return true; +} + +// Application code +int ImImpl_Main(const ImImpl_InitParams* pOptionalInitParams=NULL,int argc=0, char** argv=NULL) +{ + if (!InitBinding(pOptionalInitParams,argc,argv)) return -1; + InitImGui(pOptionalInitParams); + ImGuiIO& io = ImGui::GetIO(); + + InitGL(); + ResizeGL((int) io.DisplaySize.x,(int) io.DisplaySize.y); + + gImGuiInverseFPSClamp = pOptionalInitParams ? ((pOptionalInitParams->gFpsClamp!=0) ? (1.0f/pOptionalInitParams->gFpsClamp) : 1.0f) : -1.0f; + + static bool gImGuiBindingMouseDblClicked[5]={false,false,false,false,false}; + + int done = 0; + SDL_Event event; + while (!done) + { + if (!gImGuiPaused) for (size_t i = 0; i < 5; i++) gImGuiBindingMouseDblClicked[i] = false; // We manually set it (otherwise it won't work with low frame rates) + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_WINDOWEVENT: { + switch (event.window.event) { + case SDL_WINDOWEVENT_RESIZED: + { + int width = event.window.data1; + int height = event.window.data2; + int fb_w, fb_h; + fb_w = width;fb_h = height; + mousePosScale.x = 1.f;//(float)fb_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates. + mousePosScale.y = 1.f;//(float)fb_h / h; + io.DisplaySize = ImVec2((float)fb_w, (float)fb_h); // Display size, in pixels. For clamping windows positions. + + ResizeGL(width,height); + } + break; + } + } + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + { + SDL_Keymod mod; + //mod = event.key.keysym.mod; // event.key.keysym.mod == 0 always! + mod = SDL_GetModState(); + io.KeyCtrl = (mod & (KMOD_LCTRL|KMOD_RCTRL)) != 0; + io.KeyShift = (mod & (KMOD_LSHIFT|KMOD_RSHIFT)) != 0; + // SDLK_UNKNOWN enums... + //io.KeysDown[event.key.keysym.sym] = event.key.type == SDL_KEYDOWN; +# ifdef IMIMPL_SDL2_USE_STL + std::map::const_iterator it = specialKeyMap.find(event.key.keysym.sym); + if ( it!=specialKeyMap.end() ) { + io.KeysDown[it->second] = (event.key.type == SDL_KEYDOWN); + } + // Must I set the other io.KeysDown[...] here too ? +# else //IMIMPL_SDL2_USE_STL + // thanks to mattiasljungstrom: + const SDL_Scancode key = event.key.keysym.scancode; + if (key>=0 && key<512) io.KeysDown[key] = (event.key.type == SDL_KEYDOWN); +# endif //IMIMPL_SDL2_USE_STL + + } + break; + //case SDL_TEXTEDITING: break; + case SDL_TEXTINPUT: + { + size_t i=0;char c; + while ((c = event.text.text[i])!='\0') { + if (c > 0 && c < 0x10000) ImGui::GetIO().AddInputCharacter((unsigned short)c); + if (++i==SDL_TEXTINPUTEVENT_TEXT_SIZE) break; + } + + } + break; + case SDL_MOUSEBUTTONDOWN: /**< Mouse button pressed */ + case SDL_MOUSEBUTTONUP: { + SDL_Keymod mod = SDL_GetModState(); + io.KeyCtrl = (mod & (KMOD_LCTRL|KMOD_RCTRL)) != 0; + io.KeyShift = (mod & (KMOD_LSHIFT|KMOD_RSHIFT)) != 0; + if (event.button.button>0 && event.button.button<6) { + io.MouseDown[event.button.button-1] = (event.button.type == SDL_MOUSEBUTTONDOWN); + if (event.button.clicks==2 && event.button.type == SDL_MOUSEBUTTONDOWN) gImGuiBindingMouseDblClicked[event.button.button-1] = true; + //else gImGuiBindingMouseDblClicked[event.button.button-1] = false; + } + //fprintf(stderr,"mousePressed[%d] = %s\n",event.button.button-1,(event.button.type == SDL_MOUSEBUTTONDOWN)?"true":"false"); + } + break; + break; + case SDL_MOUSEWHEEL: + // positive away from the user and negative toward the user + io.MouseWheel = (event.wheel.y != 0) ? event.wheel.y > 0 ? 1 : - 1 : 0; // Mouse wheel: -1,0,+1 + //fprintf(stderr,"io.MouseWheel = %d (%d,%d)\n",io.MouseWheel,event.wheel.x,event.wheel.y); // set correctly, but why it does not seem to work ? + break; + case SDL_MOUSEMOTION: + io.MousePos = ImVec2((float)event.motion.x * mousePosScale.x, (float)event.motion.y * mousePosScale.y); + //fprintf(stderr,"io.MousePos (%1.2f,%1.2f)\n",io.MousePos.x,io.MousePos.y); + break; + case SDL_QUIT: + done = 1; + break; + default: + break; + } + } + + // Setup io.DeltaTime + static Uint32 time = SDL_GetTicks(); + const Uint32 current_time = SDL_GetTicks(); + io.DeltaTime = (float)(0.001*(double)(current_time - time)); + if (io.DeltaTime<=0) io.DeltaTime=1.0f/60.0f; + time = current_time; + + // If needed we must wait (gImGuiInverseFPSClamp-io.DeltaTime) seconds (=> honestly I shouldn't add the * 2.0f factor at the end, but ImGui tells me the wrong FPS otherwise... why? <=) + if (gImGuiInverseFPSClamp>0 && io.DeltaTime < gImGuiInverseFPSClamp) WaitFor((unsigned int) ((gImGuiInverseFPSClamp-io.DeltaTime)*1000.f * 2.0f) ); + + if (!gImGuiPaused) { + ImGui::NewFrame(); + for (size_t i = 0; i < 5; i++) { + io.MouseDoubleClicked[i]=gImGuiBindingMouseDblClicked[i]; // We manually set it (otherwise it won't work with low frame rates) + } + } + + + DrawGL(); + + + if (!gImGuiPaused) { + glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); + //glClearColor(0.8f, 0.6f, 0.6f, 1.0f); + //glClear(GL_COLOR_BUFFER_BIT); + + ImGui::Render(); + } + + SDL_GL_SwapWindow(window); + + } + + DestroyGL(); + ImGui::Shutdown(); + DestroyImGuiFontTexture(); + DestroyImGuiProgram(); + DestroyImGuiBuffer(); + SDL_Quit(); + return 0; +} + +#endif //#ifndef IMIMPL_BINDING_H + diff --git a/examples/opengl_various_bindings/ImImpl_Binding_WinAPI.h b/examples/opengl_various_bindings/ImImpl_Binding_WinAPI.h new file mode 100644 index 000000000..b95e841fe --- /dev/null +++ b/examples/opengl_various_bindings/ImImpl_Binding_WinAPI.h @@ -0,0 +1,395 @@ +#ifndef IMIMPL_BINDING_H +#define IMIMPL_BINDING_H + + +#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#include +#include +#include + + +// glew (optional) & gl +#ifdef IMIMPL_USE_GLEW +//#define GLEW_STATIC // Optional, depending on which glew lib you want to use +#ifdef __APPLE__ // or __MACOSX__ ? +# include // guessing... +#else //__APPLE +# include +#endif //__APPLE +#else //IMIMPL_USE_GLEW +// I've never managed to make this branch work => when using Windows, ALWAYS use glew (on Linux it's much easier) +#define GL_GLEXT_PROTOTYPES +#ifdef __APPLE__ // or __MACOSX__ ? +# include // guessing... +#else //__APPLE +# include +#endif //__APPLE +#endif // IMIMPL_USE_GLEW +#ifdef __APPLE__ // or __MACOSX__ ? +# include // guessing... +#else //__APPLE +# include +#endif //__APPLE + + + +#include "ImImpl_RenderDrawLists.h" + + + +static HWND window = NULL; +static ImVec2 mousePosScale(1.0f, 1.0f); + + + +// Notify OS Input Method Editor of text input position (e.g. when using Japanese/Chinese inputs, otherwise this isn't needed) +static void ImImpl_ImeSetInputScreenPosFn(int x, int y) +{ + HWND hwnd = window; + if (HIMC himc = ImmGetContext(hwnd)) + { + COMPOSITIONFORM cf; + cf.ptCurrentPos.x = x; + cf.ptCurrentPos.y = y; + cf.dwStyle = CFS_FORCE_POSITION; + ImmSetCompositionWindow(himc, &cf); + } +} + +static bool gImGuiBindingMouseDblClicked[5]={false,false,false,false,false}; +static bool gImGuiAppIconized = false; + +// Window Procedure +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + ImGuiIO& io = ImGui::GetIO(); + + switch (message) + { + case WM_SIZE: + + switch (wParam) + { + case SIZE_MINIMIZED: + //fprintf(stderr,"SIZE_MINIMIZED %d %d\n",wParam,lParam); + return 0; + } + ResizeGL(LOWORD (lParam),HIWORD (lParam)); + break; + + case WM_CREATE: + return 0; + + case WM_CLOSE: + PostQuitMessage( 0 ); + return 0; + + case WM_DESTROY: + return 0; + case WM_ACTIVATE: + gImGuiAppIconized = (HIWORD(wParam) == SIZE_MINIMIZED); // SIZE_MINIMIZED == 1 + //fprintf(stderr,"WM_ACTIVATE %d %d %d gImGuiAppIconized=%d\n",wParam,LOWORD(wParam),HIWORD(wParam),gImGuiAppIconized); + return 0; + case WM_CHAR: + // You can also use ToAscii()+GetKeyboardState() to retrieve characters. + if (wParam>=0 && wParam<0x10000) io.AddInputCharacter((unsigned short)wParam); + return 0; + case WM_MOUSEMOVE: + io.MousePos = ImVec2((float)LOWORD(lParam) * mousePosScale.x, (float)HIWORD(lParam) * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + return 0; + case WM_MOUSELEAVE: + io.MousePos.x = io.MousePos.y = -1.0f; + return 0; + case WM_MOUSEWHEEL: + io.KeyCtrl = (wParam&MK_CONTROL); + io.KeyShift = (wParam&MK_SHIFT); + io.MouseDown[0] = (wParam&MK_LBUTTON); + io.MouseDown[1] = (wParam&MK_MBUTTON); + io.MouseDown[2] = (wParam&MK_RBUTTON); + io.MouseWheel = GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? 1 : -1; // it's 120 or -120 + return 0; + case WM_LBUTTONDBLCLK: + io.KeyCtrl = (wParam&MK_CONTROL); + io.KeyShift = (wParam&MK_SHIFT); + gImGuiBindingMouseDblClicked[0] = true; + io.MousePos = ImVec2((float)LOWORD(lParam) * mousePosScale.x, (float)HIWORD(lParam) * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + return 0; + case WM_MBUTTONDBLCLK: + io.KeyCtrl = (wParam&MK_CONTROL); + io.KeyShift = (wParam&MK_SHIFT); + gImGuiBindingMouseDblClicked[1] = true; + io.MousePos = ImVec2((float)LOWORD(lParam) * mousePosScale.x, (float)HIWORD(lParam) * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + return 0; + case WM_RBUTTONDBLCLK: + io.KeyCtrl = (wParam&MK_CONTROL); + io.KeyShift = (wParam&MK_SHIFT); + gImGuiBindingMouseDblClicked[2] = true; + io.MousePos = ImVec2((float)LOWORD(lParam) * mousePosScale.x, (float)HIWORD(lParam) * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + return 0; + case WM_LBUTTONDOWN: + io.KeyCtrl = (wParam&MK_CONTROL); + io.KeyShift = (wParam&MK_SHIFT); + io.MouseDown[0] = true; + io.MousePos = ImVec2((float)LOWORD(lParam) * mousePosScale.x, (float)HIWORD(lParam) * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + return 0; + case WM_LBUTTONUP: + io.KeyCtrl = (wParam&MK_CONTROL); + io.KeyShift = (wParam&MK_SHIFT); + io.MouseDown[0] = false; + io.MousePos = ImVec2((float)LOWORD(lParam) * mousePosScale.x, (float)HIWORD(lParam) * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + return 0; + case WM_MBUTTONDOWN: + io.KeyCtrl = (wParam&MK_CONTROL); + io.KeyShift = (wParam&MK_SHIFT); + io.MouseDown[1] = true; + io.MousePos = ImVec2((float)LOWORD(lParam) * mousePosScale.x, (float)HIWORD(lParam) * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + return 0; + case WM_MBUTTONUP: + io.KeyCtrl = (wParam&MK_CONTROL); + io.KeyShift = (wParam&MK_SHIFT); + io.MouseDown[2] = false; + io.MousePos = ImVec2((float)LOWORD(lParam) * mousePosScale.x, (float)HIWORD(lParam) * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + return 0; + case WM_RBUTTONDOWN: + io.KeyCtrl = (wParam&MK_CONTROL); + io.KeyShift = (wParam&MK_SHIFT); + io.MouseDown[2] = true; + io.MousePos = ImVec2((float)LOWORD(lParam) * mousePosScale.x, (float)HIWORD(lParam) * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + return 0; + case WM_RBUTTONUP: + io.KeyCtrl = (wParam&MK_CONTROL); + io.KeyShift = (wParam&MK_SHIFT); + io.MouseDown[2] = false; + io.MousePos = ImVec2((float)LOWORD(lParam) * mousePosScale.x, (float)HIWORD(lParam) * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + return 0; + default: + return DefWindowProc( hWnd, message, wParam, lParam ); + + } + return 0; +} + + + + +static void InitImGui(const ImImpl_InitParams* pOptionalInitParams=NULL) { + //int w, h; + int fb_w, fb_h; + //glfwGetWindowSize(window, &w, &h); + //glfwGetFramebufferSize(window, &fb_w, &fb_h); + mousePosScale.x = 1.f;//(float)fb_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates. + mousePosScale.y = 1.f;//(float)fb_h / h; + RECT rect = {0};::GetClientRect(window,&rect); + fb_w = rect.right - rect.left; + fb_h = rect.bottom - rect.top; + + + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2((float)fb_w, (float)fb_h); // Display size, in pixels. For clamping windows positions. + io.DeltaTime = 1.0f/60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable) + io.PixelCenterOffset = 0.0f; // Align OpenGL texels + + io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = VK_UP; + io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; + io.KeyMap[ImGuiKey_Home] = VK_HOME; + io.KeyMap[ImGuiKey_End] = VK_END; + io.KeyMap[ImGuiKey_Delete] = VK_DELETE; + io.KeyMap[ImGuiKey_Backspace] = VK_BACK; + io.KeyMap[ImGuiKey_Enter] = VK_RETURN; + io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; + + io.KeyMap[ImGuiKey_A] = 'A'; + io.KeyMap[ImGuiKey_C] = 'C'; + io.KeyMap[ImGuiKey_V] = 'V'; + io.KeyMap[ImGuiKey_X] = 'X'; + io.KeyMap[ImGuiKey_Y] = 'Y'; + io.KeyMap[ImGuiKey_Z] = 'Z'; + + io.RenderDrawListsFn = ImImpl_RenderDrawLists; + io.ImeSetInputScreenPosFn = ImImpl_ImeSetInputScreenPosFn; + + // 3 common init steps + InitImGuiFontTexture(pOptionalInitParams); + InitImGuiProgram(); + InitImGuiBuffer(); +} + + + + + +// Application code +int ImImpl_WinMain(const ImImpl_InitParams* pOptionalInitParams,HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int iCmdShow) +{ + WNDCLASS wc; + HWND hWnd; + HDC hDC; + HGLRC hRC; + MSG msg; + BOOL quit = FALSE; + + + // register window class + wc.style = CS_OWNDC | CS_DBLCLKS; + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); + wc.lpszMenuName = NULL; + wc.lpszClassName = "ImGuiApp"; + RegisterClass( &wc ); + + const int width = pOptionalInitParams ? pOptionalInitParams->gWindowSize.x : 1270; + const int height = pOptionalInitParams ? pOptionalInitParams->gWindowSize.y : 720; + + // create main window + window = hWnd = CreateWindow( + "ImGuiApp", + (pOptionalInitParams && pOptionalInitParams->gWindowTitle[0]!='\0') ? (const char*) &pOptionalInitParams->gWindowTitle[0] : "ImGui WinApi OpenGL Example", + WS_CAPTION | WS_VISIBLE | WS_OVERLAPPEDWINDOW, + 0, 0, + width, + height, + NULL, NULL, hInstance, NULL ); + + // enable OpenGL for the window------------------------------------------------- + PIXELFORMATDESCRIPTOR pfd; + int format; + + // get the device context (DC) + hDC = GetDC( hWnd ); + + // set the pixel format for the DC + ZeroMemory( &pfd, sizeof( pfd ) ); + pfd.nSize = sizeof( pfd ); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.cDepthBits = 16; + pfd.cStencilBits = 1; + pfd.iLayerType = PFD_MAIN_PLANE; + format = ChoosePixelFormat( hDC, &pfd ); + SetPixelFormat( hDC, format, &pfd ); + + // create and enable the render context (RC) + hRC = wglCreateContext( hDC ); + wglMakeCurrent( hDC, hRC ); + //---------------------------------------------------------------------------------- + + //OpenGL info + { + printf("GL Vendor: %s\n", glGetString( GL_VENDOR )); + printf("GL Renderer : %s\n", glGetString( GL_RENDERER )); + printf("GL Version (string) : %s\n", glGetString( GL_VERSION )); + printf("GLSL Version : %s\n", glGetString( GL_SHADING_LANGUAGE_VERSION )); + //printf("GL Extensions:\n%s\n",(char *) glGetString(GL_EXTENSIONS)); + } + +#ifdef IMIMPL_USE_GLEW + GLenum err = glewInit(); + if( GLEW_OK != err ) + { + fprintf(stderr, "Error initializing GLEW: %s\n", + glewGetErrorString(err) ); + } +#endif //IMIMPL_USE_GLEW + + static double time = 0.0f; + gImGuiInverseFPSClamp = pOptionalInitParams ? ((pOptionalInitParams->gFpsClamp!=0) ? (1.0f/pOptionalInitParams->gFpsClamp) : 1.0f) : -1.0f; + + InitImGui(pOptionalInitParams); + InitGL(); + ResizeGL(width,height); + + ImGuiIO& io = ImGui::GetIO(); + // program main loop + while ( !quit ) + { + for (size_t i = 0; i < 5; i++) gImGuiBindingMouseDblClicked[i] = false; // We manually set it (otherwise it won't work with low frame rates) + // check for messages + if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) + { + + // handle or dispatch messages + if ( msg.message == WM_QUIT ) + { + quit = TRUE; + } + else + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + + + }; + + + // Setup timestep + const double current_time = ::GetTickCount(); + io.DeltaTime = (float) ((current_time - time)*0.001); + time = current_time; + if (io.DeltaTime<=0) io.DeltaTime = 1.0f/60.0f; + + // If needed we must wait (gImGuiInverseFPSClamp-io.DeltaTime) seconds (=> honestly I shouldn't add the * 2.0f factor at the end, but ImGui tells me the wrong FPS otherwise... why? <=) + if (gImGuiInverseFPSClamp>0 && io.DeltaTime < gImGuiInverseFPSClamp) WaitFor((unsigned int) ((gImGuiInverseFPSClamp-io.DeltaTime)*1000.f * 2.0f) ); + + + if (!gImGuiPaused) { + // Setup inputs + BYTE keystate[256]; + ::GetKeyboardState(keystate); + for (int i = 0; i < 256; i++) io.KeysDown[i] = (keystate[i] & 0x80) != 0; + io.KeyCtrl = (keystate[VK_CONTROL] & 0x80) != 0; + io.KeyShift = (keystate[VK_SHIFT] & 0x80) != 0; + + // Start the frame + ImGui::NewFrame(); + for (size_t i = 0; i < 5; i++) { + io.MouseDoubleClicked[i]=gImGuiBindingMouseDblClicked[i]; // We manually set it (otherwise it won't work with low frame rates) + } + } + + DrawGL(); + + if (!gImGuiPaused) { + // Rendering + glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); + //glClearColor(0.8f, 0.6f, 0.6f, 1.0f); + //glClear(GL_COLOR_BUFFER_BIT); + + ImGui::Render(); + } + + SwapBuffers( hDC ); + if (gImGuiAppIconized) WaitFor(500); + + } + + DestroyGL(); + ImGui::Shutdown(); + DestroyImGuiFontTexture(); + DestroyImGuiProgram(); + DestroyImGuiBuffer(); + + // shutdown OpenGL + wglMakeCurrent( NULL, NULL ); + wglDeleteContext( hRC ); + ReleaseDC( hWnd, hDC ); + + // destroy the window explicitly + DestroyWindow( hWnd ); + + return msg.wParam; +} + + +#endif //#ifndef IMIMPL_BINDING_H + diff --git a/examples/opengl_various_bindings/ImImpl_RenderDrawLists.h b/examples/opengl_various_bindings/ImImpl_RenderDrawLists.h new file mode 100644 index 000000000..7ff8cc967 --- /dev/null +++ b/examples/opengl_various_bindings/ImImpl_RenderDrawLists.h @@ -0,0 +1,615 @@ +#ifndef IMIMPL_RENDERDRAWLISTS_H +#define IMIMPL_RENDERDRAWLISTS_H + +#include +#include + +extern void InitGL(); +extern void ResizeGL(int w,int h); +extern void DrawGL(); +extern void DestroyGL(); + +// These variables can be declared extern and set at runtime----------------------------------------------------- +bool gImGuiPaused = false; +float gImGuiInverseFPSClamp = -1.0f; // CAN'T BE 0. < 0 = No clamping. +// -------------------------------------------------------------------------------------------------------------- + +struct ImImpl_InitParams { + ImVec2 gWindowSize; + char gWindowTitle[1024]; + char gOptionalFntFilePath[2048]; + char gOptionalImageFilePath[2048]; + ImVec2 gOptionalTexCoordUVForWhite; + float gFpsClamp; // <0 -> no clamp + const unsigned char* pOptionalReferenceToFntFileInMemory; + size_t pOptionalSizeOfFntFileInMemory; + const unsigned char* pOptionalReferenceToImageFileInMemory; + size_t pOptionalSizeOfImageFileInMemory; + ImImpl_InitParams( + int windowWidth=1270, + int windowHeight=720, + const char* windowTitle=NULL, + const char* optionalFntFilePath=NULL, + const char* optionalImageFilePath=NULL, + float optionalTexCoordUForWhite=-1.f, + float optionalTexCoordVForWhite=-1.f + ,const unsigned char* _pOptionalReferenceToFntFileInMemory=NULL, + size_t _pOptionalSizeOfFntFileInMemory=0, + const unsigned char* _pOptionalReferenceToImageFileInMemory=NULL, + size_t _pOptionalSizeOfImageFileInMemory=0 + ) : gFpsClamp(-1.0f) + ,pOptionalReferenceToFntFileInMemory(_pOptionalReferenceToFntFileInMemory), + pOptionalSizeOfFntFileInMemory(_pOptionalSizeOfFntFileInMemory), + pOptionalReferenceToImageFileInMemory(_pOptionalReferenceToImageFileInMemory), + pOptionalSizeOfImageFileInMemory(_pOptionalSizeOfImageFileInMemory) + { + gWindowSize.x = windowWidth<=0?1270:windowWidth;gWindowSize.y = windowHeight<=0?720:windowHeight; + gOptionalTexCoordUVForWhite.x = optionalTexCoordUForWhite; + gOptionalTexCoordUVForWhite.y = optionalTexCoordVForWhite; + + gWindowTitle[0]='\0'; + if (windowTitle) { + const size_t len = strlen(windowTitle); + if (len<1023) strcat(gWindowTitle,windowTitle); + else { + memcpy(gWindowTitle,windowTitle,1023); + gWindowTitle[1023]='\0'; + } + } + else strcat(gWindowTitle,"ImGui OpenGL Example"); + + gOptionalFntFilePath[0]='\0'; + if (optionalFntFilePath) { + const size_t len = strlen(optionalFntFilePath); + if (len<2047) strcat(gOptionalFntFilePath,optionalFntFilePath); + } + + gOptionalImageFilePath[0]='\0'; + if (optionalImageFilePath) { + const size_t len = strlen(optionalImageFilePath); + if (len<2047) strcat(gOptionalImageFilePath,optionalImageFilePath); + } + + } + +}; + +struct ImImpl_PrivateParams { +#ifndef IMIMPL_SHADER_NONE + +#ifndef IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS +#define IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS 1 +#elif (IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS<=0) +#undef IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS +#define IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS 1 +#endif //IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS + + GLuint vertexBuffers[IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS]; + GLuint program; + // gProgram uniform locations: + GLint uniLocOrthoMatrix; + GLint uniLocTexture; + // gProgram attribute locations: + GLint attrLocPosition; + GLint attrLocUV; + GLint attrLocColour; + // font texture + GLuint fontTex; + ImImpl_PrivateParams() :program(0),uniLocOrthoMatrix(-1),uniLocTexture(-1), + attrLocPosition(-1),attrLocUV(-1),attrLocColour(-1),fontTex(0) + {for (int i=0;igOptionalFntFilePath[0]!='\0') optionalFntFilePath = (const char*) &pOptionalInitParams->gOptionalFntFilePath[0]; + if (pOptionalInitParams->gOptionalImageFilePath[0]!='\0') optionalImageFilePath = (const char*) &pOptionalInitParams->gOptionalImageFilePath[0]; + optionalTexCoordUForWhite = pOptionalInitParams->gOptionalTexCoordUVForWhite.x; + optionalTexCoordVForWhite = pOptionalInitParams->gOptionalTexCoordUVForWhite.y; + } + + ImGuiIO& io = ImGui::GetIO(); + + DestroyImGuiFontTexture(); // reentrant + // Load font texture + glGenTextures(1, &gImImplPrivateParams.fontTex); + glBindTexture(GL_TEXTURE_2D, gImImplPrivateParams.fontTex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + void* tex_data = NULL; + int tex_x=0, tex_y=0; + bool fontOk = false; + if (optionalFntFilePath && optionalImageFilePath) { + // Custom font from filesystem + io.Font = new ImBitmapFont(); + io.Font->LoadFromFile(optionalFntFilePath); + if (io.Font->IsLoaded()) { + int tex_comp; + tex_data = stbi_load(optionalImageFilePath, &tex_x, &tex_y, &tex_comp, 4); + if(tex_data != NULL) { + fontOk = true; + if (optionalTexCoordUForWhite<0 || optionalTexCoordVForWhite<0) { + // Automatically find white pixel from the texture we just loaded + // (io.FontTexUvForWhite needs to contains UV coordinates pointing to a white pixel in order to render solid objects) + bool found = false; + for (int tex_data_off = 0; tex_data_off < tex_x*tex_y; tex_data_off++) + if (((unsigned int*)tex_data)[tex_data_off] == 0xffffffff) { + io.FontTexUvForWhite = ImVec2((float)(tex_data_off % tex_x)/(tex_x), (float)(tex_data_off / tex_x)/(tex_y)); + found = true; + break; + } + if (!found) { + fprintf(stderr,"Error: white pixel not found in font image: \"%s\"\n",optionalImageFilePath); + fontOk = false; + } + else printf("InitImGuiFontTexture(...) Tip: for faster loading \"%s\" please use: optionalTexCoordUForWhite = %1.10f, optionalTexCoordVForWhite = %1.10f\n",optionalImageFilePath,io.FontTexUvForWhite.x,io.FontTexUvForWhite.y); + } + else {io.FontTexUvForWhite.x = optionalTexCoordUForWhite;io.FontTexUvForWhite.y = optionalTexCoordVForWhite;} + } + } + } + // IMIMPL_ALLOW_CLIENT_EMBEDDED_FONT + if (!fontOk && pOptionalInitParams) { + const unsigned char* pFnt = pOptionalInitParams->pOptionalReferenceToFntFileInMemory; + const size_t fntSize = pOptionalInitParams->pOptionalSizeOfFntFileInMemory; + const unsigned char* pImg = pOptionalInitParams->pOptionalReferenceToImageFileInMemory; + const size_t imgSize = pOptionalInitParams->pOptionalSizeOfImageFileInMemory; + if (pFnt && fntSize>0 && pImg && imgSize>0) { + if (io.Font) {delete io.Font; io.Font = NULL;} + if (tex_data) {stbi_image_free(tex_data);tex_data=0;} + // Load custom font (embedded in code) + io.Font = new ImBitmapFont(); + io.Font->LoadFromMemory(pFnt, fntSize); + io.FontYOffset = +1; + if (io.Font->IsLoaded()) { + int tex_comp; + tex_data = stbi_load_from_memory(pImg, (int)imgSize, &tex_x, &tex_y, &tex_comp, 4); + if(tex_data != NULL) { + fontOk = true; + if (optionalTexCoordUForWhite<0 || optionalTexCoordVForWhite<0) { + // Automatically find white pixel from the texture we just loaded + // (io.FontTexUvForWhite needs to contains UV coordinates pointing to a white pixel in order to render solid objects) + bool found = false; + for (int tex_data_off = 0; tex_data_off < tex_x*tex_y; tex_data_off++) + if (((unsigned int*)tex_data)[tex_data_off] == 0xffffffff) { + io.FontTexUvForWhite = ImVec2((float)(tex_data_off % tex_x)/(tex_x), (float)(tex_data_off / tex_x)/(tex_y)); + found = true; + break; + } + if (!found) { + fprintf(stderr,"Error: white pixel not found in embedded font image.\n"); + fontOk = false; + } + else printf("InitImGuiFontTexture(...) Tip: for faster loading the embedded font image please use: optionalTexCoordUForWhite = %1.10f, optionalTexCoordVForWhite = %1.10f\n",io.FontTexUvForWhite.x,io.FontTexUvForWhite.y); + } + else {io.FontTexUvForWhite.x = optionalTexCoordUForWhite;io.FontTexUvForWhite.y = optionalTexCoordVForWhite;} + } + } + } + } + // end IMIMPL_ALLOW_CLIENT_EMBEDDED_FONT + if (!fontOk) { + if (io.Font) {delete io.Font; io.Font = NULL;} + if (tex_data) {stbi_image_free(tex_data);tex_data=0;} + + // Default font (embedded in code) + const void* png_data; + unsigned int png_size; + ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); + int tex_comp; + tex_data = stbi_load_from_memory((const unsigned char*)png_data, (int)png_size, &tex_x, &tex_y, &tex_comp, 4); + fontOk = (tex_data != NULL); + } + + if (fontOk) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_x, tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data); + stbi_image_free(tex_data);tex_data=0; + } + else { + if (io.Font) {delete io.Font; io.Font = NULL;} + if (tex_data) {stbi_image_free(tex_data);tex_data=0;} + } +} + + +static void InitImGuiProgram() { +#ifndef IMIMPL_SHADER_NONE +// ----------------------------------------------------------------------- +// START SHADER CODE +//------------------------------------------------------------------------ +// shaders +#ifdef IMIMPL_SHADER_GL3 +static const GLchar* gVertexShaderSource[] = { +#ifdef IMIMPL_SHADER_GLES + "#version 300 es\n" +#else //IMIMPL_SHADER_GLES + "#version 330\n" +#endif //IMIMPL_SHADER_GLES + "precision highp float;\n" + "uniform mat4 ortho;\n" + "layout (location = 0 ) in vec2 Position;\n" + "layout (location = 1 ) in vec2 UV;\n" + "layout (location = 2 ) in vec4 Colour;\n" + "out vec2 Frag_UV;\n" + "out vec4 Frag_Colour;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Colour = Colour;\n" + "\n" + " gl_Position = ortho*vec4(Position.xy,0,1);\n" + "}\n" + }; + +static const GLchar* gFragmentShaderSource[] = { +#ifdef IMIMPL_SHADER_GLES + "#version 300 es\n" +#else //IMIMPL_SHADER_GLES + "#version 330\n" +#endif //IMIMPL_SHADER_GLES + "precision mediump float;\n" + "uniform lowp sampler2D Texture;\n" + "in vec2 Frag_UV;\n" + "in vec4 Frag_Colour;\n" + "out vec4 FragColor;\n" + "void main()\n" + "{\n" + " FragColor = Frag_Colour * texture( Texture, Frag_UV.st);\n" + "}\n" + }; +#else //NO IMIMPL_SHADER_GL3 +static const GLchar* gVertexShaderSource[] = { +#ifdef IMIMPL_SHADER_GLES + "#version 100\n" + "precision highp float;\n" +#endif //IMIMPL_SHADER_GLES + "uniform mat4 ortho;\n" + "attribute vec2 Position;\n" + "attribute vec2 UV;\n" + "attribute vec4 Colour;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Colour;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Colour = Colour;\n" + "\n" + " gl_Position = ortho*vec4(Position.xy,0,1);\n" + "}\n" + }; + +static const GLchar* gFragmentShaderSource[] = { +#ifdef IMIMPL_SHADER_GLES + "#version 100\n" + "precision mediump float;\n" + "uniform lowp sampler2D Texture;\n" +#else //IMIMPL_SHADER_GLES + "uniform sampler2D Texture;\n" +#endif //IMIMPL_SHADER_GLES + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Colour;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Colour * texture2D( Texture, Frag_UV.st);\n" + "}\n" + }; +#endif //IMIMPL_SHADER_GL3 +//------------------------------------------------------------------------ +// END SHADER CODE +//------------------------------------------------------------------------ + + if (gImImplPrivateParams.program==0) { + gImImplPrivateParams.program = CompileShaders(gVertexShaderSource, gFragmentShaderSource ); + if (gImImplPrivateParams.program==0) { + fprintf(stderr,"Error compiling shaders.\n"); + return; + } + //Get Uniform locations + gImImplPrivateParams.uniLocTexture = glGetUniformLocation(gImImplPrivateParams.program,"Texture"); + gImImplPrivateParams.uniLocOrthoMatrix = glGetUniformLocation(gImImplPrivateParams.program,"ortho"); + + //Get Attribute locations + gImImplPrivateParams.attrLocPosition = glGetAttribLocation(gImImplPrivateParams.program,"Position"); + gImImplPrivateParams.attrLocUV = glGetAttribLocation(gImImplPrivateParams.program,"UV"); + gImImplPrivateParams.attrLocColour = glGetAttribLocation(gImImplPrivateParams.program,"Colour"); + + // Debug + /* + printf("gUniLocTexture = %d\n",gImImplPrivateParams.gUniLocTexture); + printf("gUniLocLayers = %d\n",gImImplPrivateParams.gUniLocOrthoMatrix); + printf("gAttrLocPosition = %d\n",gImImplPrivateParams.gAttrLocPosition); + printf("gAttrLocUV = %d\n",gImImplPrivateParams.gAttrLocUV); + printf("gAttrLocColour = %d\n",gImImplPrivateParams.gAttrLocColour); + */ + } +#endif //IMIMPL_SHADER_NONE +} + +static void DestroyImGuiProgram() { +#ifndef IMIMPL_SHADER_NONE + if (gImImplPrivateParams.program) { + glDeleteProgram(gImImplPrivateParams.program); + gImImplPrivateParams.program = 0; + } +#endif //IMIMPL_SHADER_NONE +} +static void InitImGuiBuffer() { +#ifndef IMIMPL_SHADER_NONE + if (gImImplPrivateParams.vertexBuffers[0]==0) glGenBuffers(IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS, &gImImplPrivateParams.vertexBuffers[0]); +#endif //IMIMPL_SHADER_NONE +} +static void DestroyImGuiBuffer() { +#ifndef IMIMPL_SHADER_NONE + if (gImImplPrivateParams.vertexBuffers[0]) { + glDeleteBuffers( IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS, &gImImplPrivateParams.vertexBuffers[0] ); + gImImplPrivateParams.vertexBuffers[0] = 0; + } +#endif //IMIMPL_SHADER_NONE +} + + + +static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) +{ + // ---------------------------------------------------------------------------------------------------------------- + // Warning: we SHOULD store the gl state here and restore it later; we don't do it: we just return a gl state with: + // GL_BLEND,GL_SCISSOR_TEST disabled + // GL_DEPTH_TEST enabled + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // glCullFace(GL_BACK); + // glActiveTexture(GL_TEXTURE0); with bound texture our font texture + // glEnable(GL_TEXTURE_2D); // Only in case IMIMPL_SHADER_NONE is defined + + // These settings should not harm most applications + // ----------------------------------------------------------------------------------------------------------------- + +#ifndef IMIMPL_SHADER_NONE + size_t total_vtx_count = 0; + for (int n = 0; n < cmd_lists_count; n++) total_vtx_count += cmd_lists[n]->vtx_buffer.size(); + if (total_vtx_count == 0) return; + + static int bufferNum = 0; +#if IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS > 1 + if (++bufferNum == IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS) bufferNum = 0; + //fprintf(stderr,"Using buffer: %d\n",bufferNum); +#endif //IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS + glBindBuffer(GL_ARRAY_BUFFER, gImImplPrivateParams.vertexBuffers[bufferNum]); + glBufferData(GL_ARRAY_BUFFER, total_vtx_count * sizeof(ImDrawVert), NULL, GL_STREAM_DRAW); + + GLintptr dataOffset = 0; + for (int n = 0; n < cmd_lists_count; n++) { + const ImDrawList* cmd_list = cmd_lists[n]; + glBufferSubData(GL_ARRAY_BUFFER,dataOffset,cmd_list->vtx_buffer.size() * sizeof(ImDrawVert),&cmd_list->vtx_buffer[0]); + dataOffset += cmd_list->vtx_buffer.size() * sizeof(ImDrawVert); + } + + // Setup render state: alpha-blending enabled, no face culling (or GL_FRONT face culling), no depth testing, scissor enabled + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glCullFace(GL_FRONT); // with this I can leave GL_CULL_FACE as it is + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + // Setup texture + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, gImImplPrivateParams.fontTex); + // Setup program and uniforms + glUseProgram(gImImplPrivateParams.program); + glUniform1i(gImImplPrivateParams.uniLocTexture, 0); + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho[4][4] = { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUniformMatrix4fv(gImImplPrivateParams.uniLocOrthoMatrix, 1, GL_FALSE, &ortho[0][0]); + + glEnableVertexAttribArray(gImImplPrivateParams.attrLocPosition); + glEnableVertexAttribArray(gImImplPrivateParams.attrLocUV); + glEnableVertexAttribArray(gImImplPrivateParams.attrLocColour); + + glVertexAttribPointer(gImImplPrivateParams.attrLocPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (const void*)(0)); + glVertexAttribPointer(gImImplPrivateParams.attrLocUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (const void*)(0 + 8)); + glVertexAttribPointer(gImImplPrivateParams.attrLocColour, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (const void*)(0 + 16)); + + int vtx_offset = 0; + for (int n = 0; n < cmd_lists_count; n++) + { + const ImDrawList* cmd_list = cmd_lists[n]; + const ImDrawCmd* pcmd_end = cmd_list->commands.end(); + for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++) { + glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w), (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y)); + glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count); + vtx_offset += pcmd->vtx_count; + } + } + glDisableVertexAttribArray(gImImplPrivateParams.attrLocPosition); + glDisableVertexAttribArray(gImImplPrivateParams.attrLocUV); + glDisableVertexAttribArray(gImImplPrivateParams.attrLocColour); + glUseProgram(0); + + glEnable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glCullFace(GL_BACK); + glDisable(GL_BLEND); +#else //IMIMPL_SHADER_NONE + if (cmd_lists_count == 0) + return; + + // We are using the OpenGL fixed pipeline to make the example code simpler to read! + // A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer. + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glCullFace(GL_FRONT); // with this I can leave GL_CULL_FACE as it is + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + // Setup texture + glBindTexture(GL_TEXTURE_2D, gImImplPrivateParams.fontTex); + glEnable(GL_TEXTURE_2D); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // Render command lists + for (int n = 0; n < cmd_lists_count; n++) + { + const ImDrawList* cmd_list = cmd_lists[n]; + const unsigned char* vtx_buffer = (const unsigned char*)cmd_list->vtx_buffer.begin(); + glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer)); + glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer+8)); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer+16)); + + int vtx_offset = 0; + const ImDrawCmd* pcmd_end = cmd_list->commands.end(); + for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++) + { + glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w), (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y)); + glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count); + vtx_offset += pcmd->vtx_count; + } + } + glDisable(GL_SCISSOR_TEST); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + glEnable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glCullFace(GL_BACK); + glDisable(GL_BLEND); +#endif //IMIMPL_SHADER_NONE +} + +#ifndef _WIN32 +#include +#else //_WIN32 +// Is there a header with ::Sleep(...) ? +#endif //_WIN32 +static void WaitFor(unsigned int ms) { +#ifdef _WIN32 + if (ms > 0) Sleep(ms); +#else + // delta in microseconds + useconds_t delta = (useconds_t) ms * 1000; + // On some systems, the usleep argument must be < 1000000 + while (delta > 999999L) { + usleep(999999); + delta -= 999999L; + } + if (delta > 0L) usleep(delta); +#endif +} + + + +#endif //IMIMPL_RENDERDRAWLISTS_H + + + + diff --git a/examples/opengl_various_bindings/fonts/DejaVuFontsLicense.txt b/examples/opengl_various_bindings/fonts/DejaVuFontsLicense.txt new file mode 100644 index 000000000..ca8513a4f --- /dev/null +++ b/examples/opengl_various_bindings/fonts/DejaVuFontsLicense.txt @@ -0,0 +1,104 @@ +DejaVu Fonts License v1.00 +—————————————————————————————— +This license can also be found at this permalink: http://www.fontsquirrel.com/license/dejavu-sans + +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. +Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) + + + +Bitstream Vera Fonts Copyright +—————————————————————————————— +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is +a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license (“Fonts”) and associated +documentation files (the “Font Software”), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words “Bitstream” or the word +“Vera”. + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the “Bitstream +Vera” names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot +org. + + + +Arev Fonts Copyright +———————————————————— +Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license (“Fonts”) and +associated documentation files (the “Font Software”), to reproduce +and distribute the modifications to the Bitstream Vera Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to +the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words “Tavmjong Bah” or the word “Arev”. + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +“Tavmjong Bah Arev” names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Tavmjong Bah shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Font Software without prior written authorization +from Tavmjong Bah. For further information, contact: tavmjong @ free +. fr. + diff --git a/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBA18_all.inl b/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBA18_all.inl new file mode 100644 index 000000000..0e36cf460 --- /dev/null +++ b/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBA18_all.inl @@ -0,0 +1,226 @@ +static const unsigned int DejaVuSansCondensedBoldOutlineRGBAbinary18_fnt_size = 5185; +static const unsigned int DejaVuSansCondensedBoldOutlineRGBAbinary18_fnt_data[5188/4] = +{ + 0x03464d42,0x00002501,0xd0001200,0x01006400,0x00000000,0x44010101,0x56616a65,0x65532075,0x20666972,0x646e6f43,0x65736e65,0x0f020064,0x12000000,0x00000e00,0x01010001,0x00010000,0x31030000,0x44000000,0x56616a65,0x6e615375,0x6e6f4373,0x736e6564,0x6f426465,0x754f646c, + 0x6e696c74,0x42475265,0x6e696241,0x31797261,0x2e305f38,0x00676e70,0x0013c404,0x00002000,0x4300fc00,0x03000300,0xffffff00,0x000005ff,0x0000210f,0x54009a00,0x0e000600,0x02000000,0x00000600,0x0000220f,0x94009800,0x07000700,0x02000000,0x00000700,0x0000230f,0x63007600, + 0x0d000d00,0x02ffff00,0x00000b00,0x0000240f,0x13008900,0x11000a00,0x01000000,0x00000900,0x0000250f,0x25006e00,0x0f000f00,0x01ffff00,0x00000d00,0x0000260f,0x25008d00,0x0f000e00,0x01ffff00,0x00000c00,0x0000270f,0x2300fb00,0x07000400,0x02000000,0x00000400,0x0000280f, + 0x1200d800,0x11000700,0x01000000,0x00000600,0x0000290f,0x1200cf00,0x11000800,0x01ffff00,0x00000600,0x00002a0f,0x8d000a00,0x0a000900,0x01ffff00,0x00000700,0x00002b0f,0x71008100,0x0c000b00,0x03000000,0x00000b00,0x00002c0f,0x8600f900,0x08000600,0x0affff00,0x00000500, + 0x00002d0f,0xa1001900,0x05000700,0x08ffff00,0x00000600,0x00002e0f,0x9100de00,0x06000500,0x0a000000,0x00000500,0x00002f0f,0x45006000,0x0f000700,0x02ffff00,0x00000500,0x0000300f,0x35006200,0x0f000b00,0x01ffff00,0x00000900,0x0000310f,0x55004500,0x0e000900,0x01000000, + 0x00000900,0x0000320f,0x56002400,0x0e000b00,0x01ffff00,0x00000900,0x0000330f,0x3400da00,0x0f000b00,0x01ffff00,0x00000900,0x0000340f,0x56001800,0x0e000b00,0x01ffff00,0x00000900,0x0000350f,0x56003000,0x0e000a00,0x02000000,0x00000900,0x0000360f,0x3300f200,0x0f000b00, + 0x01ffff00,0x00000900,0x0000370f,0x73004000,0x0d000a00,0x02000000,0x00000900,0x0000380f,0x46000000,0x0f000b00,0x01ffff00,0x00000900,0x0000390f,0x36001a00,0x0f000b00,0x01ffff00,0x00000900,0x00003a0f,0x7f007f00,0x0b000500,0x05000000,0x00000500,0x00003b0f,0x5200f900, + 0x0d000600,0x05ffff00,0x00000500,0x00003c0f,0x6f00e800,0x0b000b00,0x04000000,0x00000b00,0x00003d0f,0x98000c00,0x08000b00,0x05000000,0x00000b00,0x00003e0f,0x6f00f400,0x0b000b00,0x04000000,0x00000b00,0x00003f0f,0x46000c00,0x0f000a00,0x01ffff00,0x00000800,0x0000400f, + 0x1200e000,0x10000f00,0x02ffff00,0x00000e00,0x0000410f,0x65002d00,0x0d000e00,0x02fffe00,0x00000a00,0x0000420f,0x6300a000,0x0d000d00,0x02ffff00,0x00000b00,0x0000430f,0x2500ab00,0x0f000d00,0x01ffff00,0x00000b00,0x0000440f,0x65003c00,0x0d000e00,0x02ffff00,0x00000c00, + 0x0000450f,0x6200bb00,0x0d000c00,0x02ffff00,0x00000a00,0x0000460f,0x6200c800,0x0d000c00,0x02ffff00,0x00000a00,0x0000470f,0x2500b900,0x0f000d00,0x01ffff00,0x00000c00,0x0000480f,0x5300d900,0x0d000f00,0x02ffff00,0x00000d00,0x0000490f,0x72006000,0x0d000800,0x02ffff00, + 0x00000600,0x00004a0f,0x1200bc00,0x11000900,0x02fffe00,0x00000600,0x00004b0f,0x5300e900,0x0d000f00,0x02ffff00,0x00000c00,0x00004c0f,0x6200d500,0x0d000c00,0x02ffff00,0x00000a00,0x00004d0f,0x5400b500,0x0d001100,0x02ffff00,0x00000f00,0x00004e0f,0x65000f00,0x0d000e00, + 0x02ffff00,0x00000c00,0x00004f0f,0x25009c00,0x0f000e00,0x01ffff00,0x00000c00,0x0000500f,0x6100e200,0x0d000c00,0x02ffff00,0x00000a00,0x0000510f,0x0000d900,0x11000e00,0x01ffff00,0x00000c00,0x0000520f,0x65000000,0x0d000e00,0x02ffff00,0x00000b00,0x0000530f,0x35008600, + 0x0f000b00,0x01ffff00,0x00000a00,0x0000540f,0x6100ef00,0x0d000c00,0x02ffff00,0x00000a00,0x0000550f,0x45006800,0x0e000e00,0x02ffff00,0x00000c00,0x0000560f,0x64004b00,0x0d000e00,0x02fffe00,0x00000a00,0x0000570f,0x5400a100,0x0d001300,0x02fffe00,0x00000f00,0x0000580f, + 0x63008400,0x0d000d00,0x02ffff00,0x00000a00,0x0000590f,0x64006800,0x0d000d00,0x02fffe00,0x00000a00,0x00005a0f,0x73000000,0x0d000c00,0x02ffff00,0x00000a00,0x00005b0f,0x25002d00,0x10000700,0x01000000,0x00000600,0x00005c0f,0x45005800,0x0f000700,0x02ffff00,0x00000500, + 0x00005d0f,0x25002500,0x10000700,0x01ffff00,0x00000600,0x00005e0f,0x97006500,0x07000b00,0x02000000,0x00000b00,0x00005f0f,0xa1003c00,0x04000900,0x0fffff00,0x00000700,0x0000600f,0xa1001100,0x05000700,0x01ffff00,0x00000700,0x0000610f,0x81000000,0x0b000b00,0x05ffff00, + 0x00000900,0x0000620f,0x35005600,0x0f000b00,0x01ffff00,0x00000900,0x0000630f,0x81003a00,0x0b000a00,0x05ffff00,0x00000800,0x0000640f,0x36000000,0x0f000c00,0x01ffff00,0x00000900,0x0000650f,0x81002f00,0x0b000a00,0x05ffff00,0x00000900,0x0000660f,0x55004f00,0x0e000900, + 0x01ffff00,0x00000600,0x0000670f,0x4300ef00,0x0e000c00,0x05ffff00,0x00000900,0x0000680f,0x4400e200,0x0e000c00,0x01ffff00,0x00000a00,0x0000690f,0x54008300,0x0e000700,0x01ffff00,0x00000500,0x00006a0f,0x0000ad00,0x12000700,0x01fffe00,0x00000500,0x00006b0f,0x4400d500, + 0x0e000c00,0x01ffff00,0x00000900,0x00006c0f,0x54008b00,0x0e000700,0x01ffff00,0x00000500,0x00006d0f,0x7e008500,0x0a001000,0x05ffff00,0x00000e00,0x00006e0f,0x7d00a600,0x0a000c00,0x05ffff00,0x00000a00,0x00006f0f,0x7000dc00,0x0b000b00,0x05ffff00,0x00000900,0x0000700f, + 0x56000000,0x0e000b00,0x05ffff00,0x00000900,0x0000710f,0x4500ae00,0x0e000c00,0x05ffff00,0x00000900,0x0000720f,0x7c00cc00,0x0a000a00,0x05ffff00,0x00000700,0x0000730f,0x80004f00,0x0b000900,0x05ffff00,0x00000800,0x0000740f,0x56003b00,0x0e000900,0x02ffff00,0x00000600, + 0x0000750f,0x7000b700,0x0b000c00,0x05ffff00,0x00000a00,0x0000760f,0x7d00b300,0x0a000c00,0x05fffe00,0x00000800,0x0000770f,0x7e009600,0x0a000f00,0x05fffe00,0x00000c00,0x0000780f,0x7c00c000,0x0a000b00,0x05ffff00,0x00000800,0x0000790f,0x4500c800,0x0e000c00,0x05fffe00, + 0x00000800,0x00007a0f,0x7c00e200,0x0a000a00,0x05ffff00,0x00000800,0x00007b0f,0x1300a800,0x11000900,0x01000000,0x00000900,0x00007c0f,0x0000b500,0x12000500,0x01000000,0x00000500,0x00007d0f,0x13009400,0x11000900,0x01000000,0x00000900,0x00007e0f,0x9200bf00,0x06000b00, + 0x06000000,0x00000b00,0x0000a00f,0x4700fc00,0x03000300,0xffffff00,0x000005ff,0x0000a10f,0x54009300,0x0e000600,0x01000000,0x00000600,0x0000a20f,0x35007a00,0x0f000b00,0x03ffff00,0x00000900,0x0000a30f,0x56000c00,0x0e000b00,0x01ffff00,0x00000900,0x0000a40f,0x81000c00, + 0x0b000b00,0x04ffff00,0x00000900,0x0000a50f,0x73003400,0x0d000b00,0x02ffff00,0x00000900,0x0000a60f,0x25003500,0x10000500,0x02000000,0x00000500,0x0000a70f,0x25001b00,0x10000900,0x01ffff00,0x00000700,0x0000a80f,0xa1000000,0x05000800,0x01ffff00,0x00000700,0x0000a90f, + 0x64005a00,0x0d000d00,0x02000000,0x00000e00,0x0000aa0f,0x81004500,0x0b000900,0x01ffff00,0x00000700,0x0000ab0f,0x7c00d700,0x0a000a00,0x05ffff00,0x00000800,0x0000ac0f,0x96007100,0x07000b00,0x06000000,0x00000b00,0x0000ad0f,0xa1000900,0x05000700,0x08ffff00,0x00000600, + 0x0000ae0f,0x63009200,0x0d000d00,0x02000000,0x00000e00,0x0000af0f,0x9000f800,0x05000700,0x01000000,0x00000700,0x0000b00f,0x98005000,0x08000700,0x01000000,0x00000700,0x0000b10f,0x71008d00,0x0c000b00,0x03000000,0x00000b00,0x0000b20f,0x8d003800,0x0a000800,0x01ffff00, + 0x00000600,0x0000b30f,0x8d002f00,0x0a000800,0x01ffff00,0x00000600,0x0000b40f,0xa1002100,0x05000600,0x01000100,0x00000700,0x0000b50f,0x4500a100,0x0e000c00,0x05ffff00,0x00000a00,0x0000b60f,0x46002d00,0x0f000a00,0x02ffff00,0x00000900,0x0000b70f,0x9100d200,0x06000500, + 0x06000000,0x00000500,0x0000b80f,0x9100cb00,0x06000600,0x0c000000,0x00000700,0x0000b90f,0x89009200,0x0a000700,0x01ffff00,0x00000600,0x0000ba0f,0x80005900,0x0b000900,0x01ffff00,0x00000700,0x0000bb0f,0x8d000000,0x0a000900,0x05000000,0x00000800,0x0000bc0f,0x25003b00, + 0x0f001000,0x01ffff00,0x00000e00,0x0000bd0f,0x25005d00,0x0f001000,0x01ffff00,0x00000e00,0x0000be0f,0x25004c00,0x0f001000,0x01ffff00,0x00000e00,0x0000bf0f,0x45004e00,0x0f000900,0x01ffff00,0x00000800,0x0000c00f,0x13001e00,0x11000e00,0xfefffe00,0x00000aff,0x0000c10f, + 0x0000bb00,0x11000e00,0xfefffe00,0x00000aff,0x0000c20f,0x0000ca00,0x11000e00,0xfefffe00,0x00000aff,0x0000c30f,0x13000000,0x11000e00,0xfefffe00,0x00000aff,0x0000c40f,0x0000e800,0x11000e00,0xfefffe00,0x00000aff,0x0000c50f,0x1200f000,0x10000e00,0xfffffe00,0x00000aff, + 0x0000c60f,0x5400c700,0x0d001100,0x02fffe00,0x00000e00,0x0000c70f,0x13003b00,0x11000d00,0x01ffff00,0x00000b00,0x0000c80f,0x13007000,0x11000c00,0xfeffff00,0x00000aff,0x0000c90f,0x13004900,0x11000c00,0xfeffff00,0x00000aff,0x0000ca0f,0x13005600,0x11000c00,0xfeffff00, + 0x00000aff,0x0000cb0f,0x13006300,0x11000c00,0xfeffff00,0x00000aff,0x0000cc0f,0x0000f700,0x11000800,0xfeffff00,0x000006ff,0x0000cd0f,0x1200c600,0x11000800,0xfeffff00,0x000006ff,0x0000ce0f,0x1300b200,0x11000900,0xfeffff00,0x000006ff,0x0000cf0f,0x13009e00,0x11000900, + 0xfeffff00,0x000006ff,0x0000d00f,0x65001e00,0x0d000e00,0x02ffff00,0x00000c00,0x0000d10f,0x13000f00,0x11000e00,0xfeffff00,0x00000cff,0x0000d20f,0x00000000,0x12000e00,0xfeffff00,0x00000cff,0x0000d30f,0x00001e00,0x12000e00,0xfeffff00,0x00000cff,0x0000d40f,0x00007800, + 0x12000e00,0xfeffff00,0x00000cff,0x0000d50f,0x00006900,0x12000e00,0xfeffff00,0x00000cff,0x0000d60f,0x00005a00,0x12000e00,0xfeffff00,0x00000cff,0x0000d70f,0x72006900,0x0c000b00,0x03000000,0x00000b00,0x0000d80f,0x25007e00,0x0f000e00,0x01ffff00,0x00000c00,0x0000d90f, + 0x00002d00,0x12000e00,0xfeffff00,0x00000cff,0x0000da0f,0x00003c00,0x12000e00,0xfeffff00,0x00000cff,0x0000db0f,0x00004b00,0x12000e00,0xfeffff00,0x00000cff,0x0000dc0f,0x00000f00,0x12000e00,0xfeffff00,0x00000cff,0x0000dd0f,0x13002d00,0x11000d00,0xfefffe00,0x00000aff, + 0x0000de0f,0x6200ae00,0x0d000c00,0x02ffff00,0x00000a00,0x0000df0f,0x2300ee00,0x0f000c00,0x01ffff00,0x00000a00,0x0000e00f,0x35006e00,0x0f000b00,0x01ffff00,0x00000900,0x0000e10f,0x35004a00,0x0f000b00,0x01ffff00,0x00000900,0x0000e20f,0x35003e00,0x0f000b00,0x01ffff00, + 0x00000900,0x0000e30f,0x36003200,0x0f000b00,0x01ffff00,0x00000900,0x0000e40f,0x36002600,0x0f000b00,0x01ffff00,0x00000900,0x0000e50f,0x13007d00,0x11000b00,0xffffff00,0x000009ff,0x0000e60f,0x71009900,0x0b000f00,0x05ffff00,0x00000d00,0x0000e70f,0x72004b00,0x0d000a00, + 0x05ffff00,0x00000800,0x0000e80f,0x46003800,0x0f000a00,0x01ffff00,0x00000900,0x0000e90f,0x45004300,0x0f000a00,0x01ffff00,0x00000900,0x0000ea0f,0x46001700,0x0f000a00,0x01ffff00,0x00000900,0x0000eb0f,0x46002200,0x0f000a00,0x01ffff00,0x00000900,0x0000ec0f,0x54007b00, + 0x0e000700,0x01ffff00,0x00000500,0x0000ed0f,0x54007300,0x0e000700,0x01ffff00,0x00000500,0x0000ee0f,0x55005900,0x0e000800,0x01fffe00,0x00000500,0x0000ef0f,0x54006b00,0x0e000700,0x01ffff00,0x00000500,0x0000f00f,0x3400ce00,0x0f000b00,0x01ffff00,0x00000900,0x0000f10f, + 0x4500bb00,0x0e000c00,0x01ffff00,0x00000a00,0x0000f20f,0x3500c200,0x0f000b00,0x01ffff00,0x00000900,0x0000f30f,0x3500b600,0x0f000b00,0x01ffff00,0x00000900,0x0000f40f,0x3500aa00,0x0f000b00,0x01ffff00,0x00000900,0x0000f50f,0x35009200,0x0f000b00,0x01ffff00,0x00000900, + 0x0000f60f,0x35009e00,0x0f000b00,0x01ffff00,0x00000900,0x0000f70f,0x7000d000,0x0b000b00,0x04000000,0x00000b00,0x0000f80f,0x72007500,0x0c000b00,0x04ffff00,0x00000900,0x0000f90f,0x2300e100,0x0f000c00,0x01ffff00,0x00000a00,0x0000fa0f,0x36000d00,0x0f000c00,0x01ffff00, + 0x00000a00,0x0000fb0f,0x2400c700,0x0f000c00,0x01ffff00,0x00000a00,0x0000fc0f,0x2400d400,0x0f000c00,0x01ffff00,0x00000a00,0x0000fd0f,0x00009400,0x12000c00,0x01fffe00,0x00000800,0x0000fe0f,0x0000a100,0x12000b00,0x01ffff00,0x00000900,0x0000ff0f,0x00008700,0x12000c00, + 0x01fffe00,0x00000800,0x0020260f,0x9200b000,0x06000e00,0x0a000000,0x00000e00,0x0020530f,0x9300a000,0x06000f00,0x06ffff00,0x00000e00,0x0020700f,0x8d004100,0x0a000800,0x01ffff00,0x00000600,0x0020710f,0x89009a00,0x0a000500,0x01ffff00,0x00000300,0x0020740f,0x8d004a00, + 0x0a000800,0x01ffff00,0x00000600,0x0020750f,0x8c005300,0x0a000800,0x01ffff00,0x00000600,0x0020760f,0x8c005c00,0x0a000800,0x01ffff00,0x00000600,0x0020770f,0x8c006500,0x0a000800,0x01ffff00,0x00000600,0x0020780f,0x8d002600,0x0a000800,0x01ffff00,0x00000600,0x0020790f, + 0x8b007700,0x0a000800,0x01ffff00,0x00000600,0x00207a0f,0x8800aa00,0x09000900,0x02ffff00,0x00000700,0x00207b0f,0xa1003200,0x04000900,0x04ffff00,0x00000700,0x00207c0f,0x9100e400,0x05000900,0x04ffff00,0x00000700,0x00207d0f,0x80006300,0x0b000600,0x01ffff00,0x00000400, + 0x00207e0f,0x7f007100,0x0b000600,0x01ffff00,0x00000400,0x00207f0f,0x98001800,0x08000900,0x03ffff00,0x00000700,0x0020800f,0x8b008000,0x0a000800,0x06ffff00,0x00000600,0x0020810f,0x8700ea00,0x09000700,0x06ffff00,0x00000600,0x0020820f,0x8700d000,0x09000800,0x06ffff00, + 0x00000600,0x0020830f,0x89008900,0x0a000800,0x06ffff00,0x00000600,0x0020840f,0x8700d900,0x09000800,0x06ffff00,0x00000600,0x0020850f,0x8b006e00,0x0a000800,0x06ffff00,0x00000600,0x0020860f,0x7b00f700,0x0a000800,0x06ffff00,0x00000600,0x0020870f,0x8800be00,0x09000800, + 0x06ffff00,0x00000600,0x0020880f,0x8d001400,0x0a000800,0x06ffff00,0x00000600,0x0020890f,0x8d001d00,0x0a000800,0x06ffff00,0x00000600,0x00208a0f,0x98002200,0x08000900,0x07ffff00,0x00000700,0x00208b0f,0xa1002800,0x04000900,0x09ffff00,0x00000700,0x00208c0f,0x9100ee00, + 0x05000900,0x09ffff00,0x00000700,0x00208d0f,0x7f007800,0x0b000600,0x06ffff00,0x00000400,0x00208e0f,0x7f006a00,0x0b000600,0x06ffff00,0x00000400,0x0020900f,0x98003e00,0x08000800,0x08ffff00,0x00000600,0x0020910f,0x98002c00,0x08000800,0x08ffff00,0x00000600,0x0020920f, + 0x98003500,0x08000800,0x08ffff00,0x00000600,0x0020930f,0x96008700,0x07000800,0x08ffff00,0x00000600,0x0020940f,0x98004700,0x08000800,0x08ffff00,0x00000600,0x0020950f,0x8800b400,0x09000900,0x06ffff00,0x00000700,0x0020960f,0x8900a000,0x09000900,0x06ffff00,0x00000700, + 0x0020970f,0x8600f200,0x09000600,0x06ffff00,0x00000400,0x0020980f,0x97005800,0x07000c00,0x08ffff00,0x00000a00,0x0020990f,0x96007d00,0x07000900,0x08ffff00,0x00000700,0x00209a0f,0x8700c700,0x09000800,0x08ffff00,0x00000700,0x00209b0f,0x94009000,0x07000700,0x08ffff00, + 0x00000500,0x00209c0f,0x8700e200,0x09000700,0x07ffff00,0x00000500,0x0020ac0f,0x3300e600,0x0f000b00,0x01ffff00,0x00000900,0x0022020f,0x72005600,0x0d000900,0x03ffff00,0x00000700,0x0022100f,0x25000000,0x10000d00,0x02ffff00,0x00000b00,0x0022110f,0x25000e00,0x10000c00, + 0x02ffff00,0x00000a00,0x0022430f,0x98000000,0x08000b00,0x05000000,0x00000b00,0x0022640f,0x81001800,0x0b000b00,0x04000000,0x00000b00,0x0022650f,0x7000c400,0x0b000b00,0x04000000,0x00000b00,0x0022c50f,0x9100d800,0x06000500,0x06000000,0x00000500,0x0023cf0f,0x7100a900, + 0x0b000d00,0x04000000,0x00000d00,0x0025a00f,0x45008500,0x0e000d00,0x03000000,0x00000d00,0x0025a10f,0x45007700,0x0e000d00,0x03000000,0x00000d00,0x0025ae0f,0x55006200,0x0e000800,0x03000000,0x00000700,0x0025b80f,0x7b00ed00,0x0a000900,0x05ffff00,0x00000700,0x0025cf0f, + 0x45009300,0x0e000d00,0x03ffff00,0x00000c00,0x0025fe0f,0x81002400,0x0b000a00,0x05000000,0x00000a00,0x0026390f,0x73001a00,0x0d000c00,0x02000000,0x00000c00,0x00263a0f,0x73002700,0x0d000c00,0x02000000,0x00000c00,0x00263b0f,0x73000d00,0x0d000c00,0x02000000,0x00000c00, + 0x0000000f, +}; + +static const unsigned int DejaVuSansCondensedBoldOutlineRGBAbinary18_0_png_size = 15431; +static const unsigned int DejaVuSansCondensedBoldOutlineRGBAbinary18_0_png_data[15432/4] = +{ + 0x474e5089,0x0a1a0a0d,0x0d000000,0x52444849,0x00010000,0x00010000,0x00000308,0x58ac6b00,0x01000054,0x544c5080,0x00000045,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0xffff0000,0xffffffff,0xffffffff,0xffffffff,0xf8f8f8ff,0xeff2f2f2,0xececefef,0xe7e7e7ec,0xe0e3e3e3,0xe0e0e0e0,0xdbdbdbe0,0xced5d5d5,0xc6c6cece,0xc3c3c3c6,0xbfbfbfbf,0xbababfbf,0xb4b4b4ba,0xa8aeaeae,0xa3a3a8a8,0x9f9f9fa3,0x959a9a9a,0x8f8f9595,0x8989898f,0x7f838383, + 0x7f7f7f7f,0x7c7c7c7f,0x6e767676,0x67676e6e,0x63636367,0x5e5f5f5f,0x58585e5e,0x53535358,0x4c4f4f4f,0x46464c4c,0x42424246,0x3e3f3f3f,0x3a3a3e3e,0x3737373a,0x2f323232,0x2b2b2f2f,0x2727272b,0x1f232323,0x1e1e1f1f,0x1d1d1d1e,0x181a1a1a,0x16161818,0x13131316,0x0f121212, + 0x0e0e0f0f,0x0b0b0b0e,0x080a0a0a,0x07070808,0x04040407,0x03040404,0x02020303,0x00000002,0x00000000,0x00000000,0xc381e300,0x0000003e,0x4e527433,0x00000053,0x02000000,0x07060303,0x110e0b0a,0x1e1a1815,0x2d28231f,0x3f3e3833,0x5e545247,0x78726760,0x928a7f7f,0xaea8a09e, + 0xc8c0c0b9,0xf3e7dfd1,0x19be4852,0x00200000,0x54414449,0x7dedda78,0x4b2a4feb,0x265fafd3,0x06230621,0x4b160545,0x0942c025,0xee07f48c,0x28821044,0x89611a28,0x4e22a277,0x84842102,0xebfc2f84,0x332faaa7,0xf72e803d,0x9ef3f67e,0x64c39f77,0xccf4e5ef,0xaebf5d00,0xaeaaaeae, + 0xe05259aa,0x1457dab0,0x153870f9,0xb6d496c7,0x2d4d57da,0xb753d3f3,0xd4d6e457,0x97365937,0x9ecfad95,0x57790e5d,0x7b467b42,0x2e1ac267,0xb8db678f,0xf158f76a,0xdf2bbd7b,0x69bc75f8,0x4e2e8cff,0x0e9e12c6,0x934c81b5,0x6ce5bde3,0x851d1abf,0xb955fdfb,0xea7a7a65,0xeb40eaf6, + 0x4df27faf,0xc8dbf196,0xe9b17d2f,0xf151e5d9,0xd6b8506a,0x4df9d811,0x3d70d8ea,0x3a2f9b35,0x76ed7602,0xed1c5568,0x2f87d12b,0x3cd95d7e,0xd45a6a18,0x1bd79d6f,0xa0030641,0x1b2d1b90,0x62a61d14,0xb8cc64fd,0x3ba62a12,0xe6bd121b,0x57b7cda7,0xf264d9fb,0x37fe7d63,0xf649cff9, + 0xff9d1922,0xe4975aec,0xa23e495e,0x7e179337,0xa7abd93c,0x3e202549,0xaa91c913,0x8934f15f,0xafe3ff66,0xb14adf3b,0x31792254,0x8de9ceb4,0x35896320,0x835d8d4a,0x78f540a2,0x881d2e5c,0xb8fefba6,0x711a61b7,0xdbe6d3d3,0x7c756a81,0xccb63279,0xf150a6fd,0xf2bd96a5,0xbe167fce, + 0xb669eda8,0xabe5bc1d,0x9f12fd9d,0x33500092,0x001bae04,0xceebf17c,0x0fd48256,0xe3922507,0xc37b9808,0xe69a58c9,0x8e04c094,0xfe1f65b0,0x11f2cef5,0xd83debbd,0x335977e5,0x019b976c,0x67fe778b,0x373219a1,0x50b6bbe5,0xf6541428,0x689b2142,0x040de2fc,0x77513420,0x6f7b63e8, + 0xcc9b3dd7,0x22756e01,0xa0204e8d,0x7c2df64e,0x2e4865be,0x9085b302,0x0ddf8f9a,0x3f4113ab,0xa2127276,0x25389800,0x5c702150,0xaffa3579,0xafddf5f2,0xf83c339b,0x2bd6d355,0xc1a78b16,0xf408b17a,0x40081a99,0xbf3240a9,0x287ce877,0x29e42f16,0xf34a6480,0x1eba6a53,0x7449c109, + 0xc3a92298,0x2bdebb99,0x04316bec,0x65399800,0xe4275fb5,0xd632b06e,0x24287732,0x75fbbcbe,0xbf079a73,0xa08f2e6c,0x3a3f7747,0x4c4c06b9,0x88010353,0x79092f35,0x46ca2974,0x36bd84a7,0x1b3d7000,0xee6e6c03,0x3c82135d,0xa4263e1e,0x777d36bb,0xf8077065,0xd34bbe00,0x4ddf029c, + 0xa2c54e5a,0xe55fe166,0x375fbbeb,0x75fb3ea7,0x0264a613,0x7559ba4e,0x0001ba79,0x09c7871c,0x702f6742,0xe4000999,0x462e8cba,0x718e26e4,0x3e3f43d3,0x8b6761ef,0x34d2e9b1,0x142270a7,0x77d7c446,0x7d4e6ebf,0x2c26ebf6,0x1e925511,0xf0992e35,0x08541b90,0x559259aa,0x1e580167, + 0x67a88025,0x1a94be97,0xa700044d,0xe640a84d,0x3003ac3d,0x226629cd,0x75fbbebe,0x5fb3ea73,0xeb651537,0x98fed815,0xf1b9514f,0xee3f0015,0x88841f4a,0xfcd4c2f5,0xeb78c771,0x6c124d30,0xeb0f4dd4,0x8a734c00,0xefaf8899,0xfa9cdd7e,0xb64dd7ec,0xc38ee7c4,0x1a2f7ac6,0x3ec9c4f0, + 0x84554190,0xcbf60029,0x893c9177,0x6e5e958b,0x7c49875a,0xb10bd414,0x361e9a8a,0xca732001,0xdf9f112c,0xd20033fd,0xc26ebf67,0xb4220bb1,0x9001c3b1,0xb240001a,0x95411c07,0xab003344,0xd268d4fd,0x27e6e420,0xe6e483d7,0xcde81bcf,0xd242a441,0xef9a064c,0x9cc800ea,0x3c44e512, + 0xb78891b8,0xcd1f334d,0x39bafdde,0x9bafd9f5,0x98f183b4,0x0d4ad5ae,0x23172000,0x385544a4,0x2ea00033,0x299cbe13,0xb79fcdb3,0x472958e9,0x34355c8a,0x9001d5df,0x9c8aa538,0x6f46f9b2,0xae09f6ac,0xfddf5f64,0xd9f539ba,0x9e809baf,0xef2e583b,0x06e5fa73,0x6be180ca,0xdfe900f7, + 0x2a100337,0x733a813c,0xaa68782c,0xfb0e78a9,0x27b3b1cf,0xd5df32de,0x6b7c6001,0x7c658a70,0x876f5244,0x19d32ac3,0x75fbbebf,0x7fb3ea73,0x0a87de6a,0x74ca3ec8,0x6e080103,0x8c59b1ad,0x0081d15a,0x5465aec0,0x3e57b236,0x1949a665,0x95c97bc9,0xbbbbe9b2,0x6a904008,0xa7331e82, + 0x0964bf6c,0xa8f2c549,0xba7f2984,0xea7375fb,0xbd365fb3,0x4e52a957,0x2372e82c,0x89271a78,0x9f3d20d3,0x12589390,0xc00639ec,0x2895375a,0x19bad684,0x9b30e242,0xe5429aa6,0xaca0afbd,0xdbbbbe9d,0x84921348,0x9c625daf,0x0c3efaf2,0x5b6a2309,0x0dbebfed,0x8dc136c2,0xbafdde5f, + 0xafd9f539,0x97a3cb9a,0x946cdd47,0xa69eb61b,0x8dd11c69,0x086b43ce,0x87372cf6,0x30a30ed7,0xc9d4d79f,0x4f048a24,0x158d8535,0xd2f330f0,0x10f7777c,0x1adc824e,0x1cb75654,0x5bdec956,0x315cdadd,0xfbbebf35,0xb3ea7375,0xb797369f,0x2d91865d,0xbb766c37,0xe1ba205d,0x480fd276, + 0xf0ff910e,0xd5fe5258,0x54e9b507,0xbb2435d9,0xf7c22cab,0xf5ebbeb2,0xeb1ba47a,0x032dd561,0x32a9ed30,0x8176bfb7,0x4e9c9b2d,0x7bb27ba6,0x8a379e6a,0xf06dc677,0x7b753884,0x1f39f63c,0x0e3c7a74,0x9b3337d3,0xdc88aa8e,0x06d76435,0x3421dd1e,0xe59fee66,0xeae347c0,0xa9f839aa, + 0xfe47e4ff,0x006ddee8,0x32a9ed30,0x8174bfb7,0x6047f639,0xe6bbefd2,0x53dd93dd,0x4c51bd73,0x17b8fde9,0xe6e29c7a,0xe6fbeea7,0xf998e6ad,0x64d5a060,0x9bfd130e,0x7a600657,0xc39e9997,0xa7ae435c,0xa6572de4,0x7472df36,0x551e5d81,0xb2ed71c9,0x0811ba94,0x5aa5cb04,0xa5d8cb92, + 0x54d54f59,0xd8172bfb,0x2c49fbd6,0x3c9f8e91,0x99ef66b9,0xbd7353dc,0x8fe94c51,0xb7bc84c5,0x69cd59a9,0x63a0dea1,0x21be6312,0x2a8183e9,0xdae19c49,0xcaf37d28,0xc2ba2844,0x1eeb0435,0xdf3720d3,0x8bf4c712,0xc789cbf7,0xf07bcfb0,0x447a6b9e,0xc26deb2f,0xd6696a07,0xfedd3553, + 0xf5b605dc,0xe317209a,0x5704e7c3,0x2a0e4cbd,0xae6a7b93,0x7d998a37,0x1b24c3a7,0x26ef5761,0x1fa2dd79,0xe6b88df0,0x74107f2b,0xf72feac6,0x000b37d4,0x2d078384,0x03bbd8e9,0x844b3dc7,0xd3b8fe7e,0xdd7bf56d,0xbc67348f,0x212c46dd,0x4065433a,0x789d5b68,0x86a2b10d,0x886a7db6, + 0xafed1f7d,0x53b275e1,0x4ecd9987,0x93dea26f,0x2f787e85,0x0fb40029,0xfb0eee13,0x9b3e0366,0x2b0ed26f,0x71c4e7ae,0x6c778cf2,0x9d17d422,0x166b99b0,0x77400245,0x41ca28f0,0xa07c1a89,0x4629c76a,0xd4217c91,0x32651d88,0x59cab559,0xfad63500,0xcd042c9e,0x700ca2ae,0x7c691a07, + 0x76bba55c,0x2fc176f4,0x3a26f46a,0x28fdce58,0x58dbf053,0xec53981f,0xe7640dbb,0xfb3338e3,0xcdd279c3,0xa3f64d6a,0xb0895882,0x0004d7b9,0x780783ba,0x183a82ea,0xbfa19d7e,0x34807f05,0xb8fcf186,0x4daacf1b,0x08f0d6ce,0x980029bb,0xc6951576,0xe2ef5b16,0xd21f6b82,0x35f8cb5d, + 0xd5fdf246,0x6e0cf571,0x595e930a,0x4c9dd3df,0xc05cb4a0,0x01b37ccf,0x1270e8f2,0x0209510d,0x5a45ff16,0x1fa9b11b,0x949fb04d,0x9001d308,0x4053e9af,0x1f0cf6a8,0x31f0c118,0x95eb68c3,0x4b90bf3c,0x03a0a86f,0x2aa71960,0xbac97084,0xc455cf34,0x01484a46,0x1b05aef9,0x0a41ae4f, + 0xe9309065,0xfb4522c5,0xf1350f60,0xc11b37da,0x2f162a72,0x768a1950,0xd837c931,0x8ff7410f,0xc226bb47,0xdc844fa2,0xb5d3147a,0x3d0000cf,0x00a4f019,0x5690bf6c,0x8a856e0b,0x1d46b559,0x11eb8aab,0xbf55231d,0xab94c00e,0x1a409b28,0x5ecc0075,0x600ff5a7,0x1315f181,0x66dc573c, + 0x7a2ddab7,0x9085ba1f,0x098dfbe7,0x90dc9979,0x8e365a38,0x9b590676,0xb7cd80c9,0x9d2ee324,0xe05c28b0,0x00cfef82,0x19e40720,0x691eb600,0xd085620c,0x64ed9530,0xa904db18,0x16c92463,0x5759a5a2,0x2c381151,0x4c00e9a9,0xfe709d79,0x80032834,0x037367cc,0x19ec75d6,0xacdca1f6, + 0x9be4b533,0x90d7ad8d,0xe47ce63a,0xe326dd1b,0x02cf5084,0x9b6cb248,0x61399679,0xe381ad76,0xa00067f2,0x0784b883,0x5734f94f,0x6bf64e8f,0xc64f94a4,0x59f94c53,0x63a9a419,0xd2d3b184,0x18a8abac,0x8e2f01aa,0x5e530004,0x4e2f5b27,0x45e96c62,0xc61f3e93,0x4d6ea49f,0x78b643ec, + 0x8df9906c,0x42bb8fc6,0xeebacb36,0xecd5f5ab,0x5dad865b,0xdf35de30,0xbb30898a,0xd7180abe,0x0cf1969c,0x7427fb00,0x70de7eb4,0x836ecb47,0x1a9ef8bc,0x7d77b7af,0xa7a1fca6,0xa5b5e0c8,0x31515759,0x14c12e34,0x794c00e1,0x56c3a89d,0xeaf4084c,0x3a0f86dc,0xd366ba09,0x8334843e, + 0x5c373fcc,0xd635af38,0x00db3575,0xa31f2845,0x621cdd7a,0xb6735ce7,0x2df31a9c,0x0f50d71b,0x803d5368,0x97196963,0x5e07cf12,0xcb877eef,0x4231dd4d,0xd669697f,0xd90c5455,0x731d307a,0xdca6d7ec,0xd18e6c4c,0x1e04466f,0x8a5f24b2,0x0c86c757,0x7fb77718,0xdf01bb7e,0x61395195, + 0x49d8a507,0x1a631722,0x9800f7d2,0xb63b8f90,0x835c6261,0xe56361f1,0xdcf22768,0x4a467a3b,0x19275797,0xc70df726,0x018fb5c8,0x022aed30,0xe2df3752,0xdda6d7e2,0x1400264c,0xad3fdab7,0x6c92028d,0x60bf6cb2,0x80d7be07,0xf1f63485,0x60ea7fc0,0x8f3f49dc,0x09a8fd29,0x6ba000ce, + 0x48b5fa82,0xb04b113e,0xe3c1c2bb,0x723ccfbe,0xf274755e,0xfd628fcc,0x5caf5ef5,0x94b68edc,0x0008c759,0x2a2ae330,0xc55fccaa,0x9bb4cf65,0x08008829,0x7ed1d8d5,0x254a113c,0xd58003ed,0xbdf949c4,0xac07fac6,0x2572a038,0x605bb8e9,0xced9d80a,0xd8c49170,0x64c20978,0x16b8c05b, + 0x46516be9,0xacf070bf,0x65ba4775,0x7b1611b6,0x80bd8ecd,0x8fadc3df,0xd2c8c729,0x8e28abac,0x0d7e13d3,0x33759801,0x3d614f05,0xde550b4a,0xba3d98f5,0x7de8a1fb,0xfc534c20,0x1f59436e,0xe94175bd,0x98f2ee8e,0xedceb600,0xf7cdea36,0x7461132d,0x5cde3f32,0xd7c9ef01,0x2cd58556, + 0x9aca3c1c,0xbe39b76c,0x719910e3,0xb6554515,0xe655ee11,0xd18299ba,0x3750e4c9,0xfaaa5c8e,0x3d03ea43,0x286fdf02,0x526b9bcb,0x4fb8d66f,0x1b8f7770,0x886106fe,0xd7a7eb80,0x3bed7539,0x6a20e587,0x1e5b9a93,0x55cbb70f,0x11ef5ff5,0xc9e11d32,0x2378bcce,0x3d920658,0xf095811d, + 0x1af9b36b,0x37caa65a,0xe292faf0,0xf80991a7,0x42a5b52f,0x7661f8ec,0x1e3d58f0,0x75adce0f,0xf92ebbf8,0xfc6c6ce4,0x0e536c56,0xccc2fd21,0x627b0a13,0x8a996ed9,0x1c36da64,0xe3cfb649,0x503ca69c,0x1e59d2d0,0x3bdfe7d4,0xac8de2f3,0x30595cc3,0x98e0cacc,0x22b1aa94,0x000c81aa, + 0x460d05ff,0xfc417fc0,0xec8a941f,0x3fdb1360,0xfa11fad4,0x1366cd15,0x0ff5b0d4,0x205a0bf8,0x072ecaf7,0x5d2d747a,0xdd847019,0x4581fcf0,0xc4f330ba,0xffeb445a,0x350f40b2,0x71a702e1,0x177e8722,0x1db2840f,0x745eb40c,0x2738b3eb,0xb68a0793,0x8a3de146,0x71234ec1,0x0081e49e, + 0x3946f133,0x75828de1,0x2d063527,0x706bbeb1,0xf1ae15c0,0xee2a5fec,0xde01801f,0x5ff768a8,0xfc09b2c4,0x257ed59a,0x486477cd,0xfcca7a05,0xa26be8f2,0xcf244cfa,0x3efba284,0x5253465d,0x04f330bf,0x38932574,0x17fc5b1b,0x4e2c77a2,0x98f17524,0x5b0adea5,0xf15244af,0x54efe884, + 0x03d98950,0x1686ddb5,0x1c752228,0xfe4195ce,0xfb155029,0x11bc7201,0x045ef730,0xcb717268,0xce7c78ee,0x00380d82,0xfb3a4a5e,0x09d0aa97,0x0150e218,0x26d1d4be,0x0943b525,0x05150d58,0x856d9300,0x6fdab003,0xb73cf251,0xd8b0cc47,0xad06797e,0x5fa6bbb9,0xd4027998,0xdc8d5694, + 0x5ce23fbb,0x2271e095,0x0e3214b0,0xf4e02300,0xdf309bb0,0x66254115,0x4bf6d40f,0xd48f9c82,0x515531ee,0x9ec8a1fc,0x9a44c822,0xbc590345,0xa6a6021e,0x5ad6e1a8,0x07bbe49d,0xe700ebf4,0xc3ac0069,0xd735fc23,0x982cb013,0xbf7799d2,0x00ea3970,0x65000228,0x2de48275,0xb96e8e8f, + 0x2fddbc51,0x5d2e2283,0xbe027e98,0xab926b46,0xfb27675f,0x46132472,0x03c1b04b,0xdbe6b62b,0xcc0733ab,0xec89504c,0x65ad6281,0x7d83a365,0x6a699131,0x5879da38,0xc5b8ef71,0x48540085,0xdfe74839,0x033296d6,0x31812800,0x365c2634,0x890289fc,0x9f6d0f9d,0xf250a002,0xc8f91b76, + 0xbb747332,0xfc5cedc7,0x3c60ba5d,0xc008dac1,0xc76eb90d,0xb64c914c,0xe944181e,0x92aa6643,0x6f63bbf8,0x4cf3050f,0x03c98950,0x35047685,0x6017fc03,0x34c89afd,0x2c034cd3,0xdc000934,0x6aa3d42e,0xeb400066,0xd755fb89,0x2485323f,0x5f6cf5c9,0x4832b002,0xea239cb6,0xb43f76e8, + 0xa6919d7f,0xa278c171,0x4c020daf,0xc9543d06,0x3feab14b,0x398c92a0,0x0bb98695,0x02ac9b6e,0x1f6c910b,0xd340c183,0x84a824f9,0x0b78a079,0xeaff01d6,0x379f9934,0xc03e8010,0xcc08165d,0x2ff60002,0x4cebe828,0x0cc21cf7,0x0669bca3,0xe0007b80,0xe78c1c62,0x2d7c01d2,0xabde8dea, + 0xd4712d5c,0x4fe82e37,0xbe2533d4,0xce967e29,0xdd929fd4,0x4d04e97a,0x1a54ea4a,0x1663ca17,0xca3cb227,0x14825a91,0x12f39d86,0x824fcfcc,0xa49b0c4a,0x44e581e9,0x05ff58a3,0xa2fd4200,0x07365a11,0x96419580,0x78ec03e1,0x7b30ea1d,0xe2800cdb,0xa1a9d899,0xf196fb80,0xe295b3b6, + 0xd68fcafe,0x105f2abb,0xea5b344f,0xeb621d11,0x923543af,0x7a906ebf,0x7501a719,0x63cb952a,0xa602271e,0x14f47c7a,0xe0a9f183,0xa827353a,0xb140f0c4,0xdcaf5b9b,0x0025f09d,0x0977c1a7,0x9478de80,0x039da9d7,0x054bf6c0,0x5360dfe8,0xfb3280b0,0xb76029d3,0x4a9503db,0xe0dc7460, + 0xd3badb26,0x9fc0be61,0xa9c738f0,0xf10cdf0c,0x12a33334,0x5ae068f9,0x74a54e8c,0x71e16c71,0x300bfe22,0x3e29718f,0x4ff7e04d,0x3d989145,0x35b5bc50,0xc83001d1,0x1c603534,0x049aa373,0x7829f140,0x9e14b841,0x1fa70003,0x21fb94a5,0xf3879c25,0xabadc001,0x5dabe684,0xabe548d4, + 0x71d5f60b,0xdee5c735,0xe4db28f2,0x3a97818b,0xab43d295,0x51c11388,0xd5f758fd,0x4e66bbb8,0x81e18950,0x518616c2,0x644c0071,0x16ce1a9a,0x43c0f6d8,0xc1f311e8,0x52962b04,0xf50cb1a7,0x0003cdbc,0x9d3a77e9,0x55fc6423,0xb082e0ff,0x00cf9d50,0xf9a93fd8,0x32abcd3c,0x7ba5f229, + 0x7ed585ee,0xb2a9d2a9,0x9eb77505,0xdb07408f,0x207bb497,0x1138a467,0x0a463b47,0x412604da,0x8d9d51ec,0xa07b3122,0xdc84b73c,0x0c860f85,0x734c9900,0x5f0e7143,0xc43ce4d1,0x12745f73,0x7cbde83a,0xac9f9ba8,0xf92fdb02,0xd71c16e7,0x24413f37,0x6283ec5f,0x4fb2b542,0x92b67000, + 0xed3c8120,0xbd32c91c,0xb605fe6b,0x423f4197,0xb7cd8d17,0x879d3144,0xca7ae129,0x44e396fd,0xf891cf28,0xa3508975,0xc4a83a7c,0x3c5281e4,0xa56819f7,0x5bca1512,0x86e69932,0x335add62,0xedb64d59,0xa61cc975,0xc428704a,0x8aed4000,0xbb5bd01d,0x63ce4e46,0xfb35fc05,0x23c000c4, + 0x41feb001,0x911cb5b7,0xbe50ea89,0xb37740b8,0x7c394cec,0xf5cee271,0x196447db,0x8ece8eb5,0x7dc46c29,0x44e97bd8,0xcc260ef7,0x2a0e9f28,0xd7fdab71,0x6140f736,0xd6f6f06b,0x6636068f,0xf9a69cc9,0x68007f73,0x281cd9e5,0x486ff84d,0xecb2e489,0x5bd6ba60,0xe948f9b3,0x105798d7, + 0x35ce4001,0xa7d63632,0xbc7f0e7d,0x42cdbab0,0x9b4d1810,0x2361d31b,0xf30dedb6,0x254133f3,0x6563cb92,0xdbf57373,0x618af2e6,0x22ab2a39,0x20380144,0x80a9a2a2,0xa2d5a2ff,0x7ac423b2,0x45b04609,0xe8868a6c,0x0e4137f2,0x544307f8,0x0dc3f1fe,0xa0136f43,0x18a119af,0x8e6660eb, + 0xe59199f6,0xa662808c,0x10a1feda,0xf10fc919,0xe813a659,0xddf3ab6b,0x3480ce33,0xfad73a40,0x38238f54,0xee6a952f,0xd3be996f,0xf03ddf7d,0x09fc98f7,0x20dabb45,0x62a7c9bc,0x2713a489,0x5b39a054,0x963658b9,0x032e2aa5,0xd61cfd00,0x9ca5ef99,0xd3979d62,0xf6507525,0xe9967c43, + 0xb48df164,0xd66d81fe,0x115d033d,0x07e830d9,0x9b4346e8,0xd47a29cc,0x3f4e677c,0xee636bb3,0x73be996f,0xd2c74c05,0xe981e645,0x824cf12e,0x0782e9e4,0x1ca91dda,0x73f8e276,0x3ea4ee60,0x8a8c76d4,0x4e8625b1,0x5b14d9b3,0xa2f7fa3f,0x0dafb55b,0x8e99d683,0xf9341d48,0x74c93e21, + 0x716b8cb2,0x8face610,0xf9467bb2,0x22556e11,0x03f70a7b,0x22899264,0x8c3ad6f6,0xee7e3683,0xcc6d719f,0x9769adff,0x4790894f,0x6e43b337,0xa09a5ed4,0x0e5a9b5b,0xc5503d9a,0x76cac14e,0x1eba77ee,0x6c4bc529,0x9623d7ed,0xe8ddefe5,0xec4c931c,0x77273e94,0xd9a0ee44,0xd33f310f, + 0xd29b1409,0xd9e48361,0x67b925e2,0x4279773c,0x70ee1472,0x8eaefe3e,0x60dd537f,0xffb37065,0x4c9c2d74,0xb3e36b86,0x677d32df,0x47757f38,0x5a091ea8,0x66ee98df,0x279a2363,0xb8631029,0xc61d6119,0xead3b348,0x0c86acfa,0x01cee940,0x0d17be30,0x9cf553ee,0x8ea68d2b,0x1ba41d48, + 0xac61c2fc,0x99cbf66f,0x6817804e,0x8e2cefbd,0x34067e5a,0xe555d899,0xf5fc170a,0x35a8180f,0xea98f84b,0xe881ab6e,0xc1bb90e4,0x4f91e74c,0xdee74bae,0x924af3e7,0x80e338b0,0x18d68dc5,0x2dee208c,0x27ec85d3,0xe4c90f8b,0x02020079,0xa89e19b0,0x287f0002,0x5dc5fbe4,0xf301b829, + 0xb081e77b,0xe3a910f0,0xc1b4b9f2,0x32973a6f,0xb80fdc9d,0x96cc6a74,0xe4899f97,0x1955be48,0xb7ec4216,0x3788dd6a,0x57efe94c,0x6e664141,0xee7abfb0,0xe6f924bd,0xe1b18931,0x4857df71,0xe1f6c9a2,0xdac79149,0x23e56fe0,0x096d4f62,0x2f460100,0xae4c0033,0xa68b6414,0xb02cc5a7, + 0x369508cf,0x52e74df8,0xfe8613a6,0xb6233d37,0x9e7e68bd,0x0c10829c,0x0c1640b1,0xb6d4b88f,0xa4f2f391,0x73532e3a,0xa39eafe0,0xad1ee8f3,0xee13b629,0x1649e5ab,0xe260519d,0x34f16493,0x0031b568,0x5b8d7eaa,0x61d64b39,0x8f1f149a,0x57260018,0x4d5b9a0a,0xb55333cf,0xde54233f, + 0xa5cf97e0,0xb866274c,0xd200184f,0x4980cb33,0x2aa00005,0xc339ee05,0x03a58091,0xe799f77f,0xf3d5fc5e,0x8dbb003d,0xae2122be,0x711a6523,0x49656ce0,0x18d9d5aa,0xde386702,0x151f6e79,0xc9f84b52,0x9f069dc7,0xbd21b202,0x8b918dd6,0xf0019d40,0x06d2a119,0x4a5ce9bf,0xac0141f4, + 0x733f2003,0x56a52298,0x4a954065,0x14f1ff8b,0x210accf7,0x30e21266,0x77fcb981,0x0e7a35ce,0x6c02d800,0x181821fe,0xf0dfd1d7,0xb0b560d5,0x1b30538c,0x8fc00e75,0x68217474,0x36ec24f2,0x6192a248,0x5084fdbd,0x3e5f8379,0x9c600197,0x3d3710c4,0xe243ab03,0xcb8b72a1,0x75dc6594, + 0x795b0f05,0x2275fbb4,0xf57fe3a0,0x15f2471c,0x67a98689,0x8d0d81eb,0x31fc0d3e,0xf52096bb,0x051a61fd,0x71eefc31,0x9bc791f8,0xf9b40050,0xefbb2800,0xa61be68d,0xa84a7e30,0x9f2fc1bc,0x684e99cb,0x3f7637ce,0xe9858c68,0x29d1e599,0x28526649,0x0c5aec8b,0x0b7a00f8,0xe14e3e96, + 0xe60d4417,0xb73d5ff1,0x11a492f5,0x582c91ac,0xef9df09a,0x7729c8c1,0x64bf6fb8,0x94472762,0x0ae32deb,0x2c62a529,0x7d096f3a,0x35182fa0,0x5c300022,0xf75d6b29,0x4a85e78e,0x9508cfd4,0x9b4df837,0x53a672fd,0xf65494f0,0x847a08ef,0xcb28cf4c,0x3cb361c1,0xc400b176,0x723f78ea, + 0x88225c89,0xeaffe7c0,0x4e99d039,0x708fc69c,0xc9eb82e1,0xb8248e72,0x6aadb8ee,0x8f00832f,0xbdbe1b75,0xc1d4588f,0x2e44e012,0x001c27c6,0xcd452b93,0xa7c3043e,0x8cfaf574,0x5f837950,0x0f34c73e,0x3ac9d33d,0x524ec52c,0x73081c19,0x0aa18040,0xcd61f6af,0xaa13c93c,0xa822722e, + 0xcf57f36a,0x5ec3ed95,0x8352a7ab,0xbc1d16d2,0xbaa374bf,0x36df6cee,0x0a6c2eaa,0x0309729b,0x031d4167,0x4c7500dd,0x3d452b93,0x098f978a,0x253ec83a,0x2fc1b4d4,0x93a3079f,0x5274c888,0x178307ac,0x81a6a54d,0x66002039,0x5e598f01,0x2fba4d0d,0x183321ed,0x20350fb6,0x7f76a982, + 0x76e81cf5,0x8ec15b1a,0x05b93fed,0x1dda1140,0x9322f6be,0xe336ba89,0x6ffb514a,0x19f0fbc2,0x7e0da6a1,0xecbf66f3,0xb6d95894,0xd9667fcf,0xb6d7e730,0x6edfc30d,0xcf97f110,0xdea070ff,0x36e17b87,0xbad65423,0x95c4fb65,0xca73aab2,0x2ffe8457,0x6ed9b63c,0x734c22be,0xbef541a3, + 0xcccb22f3,0x665327ff,0xc2da230c,0x4b0d51d0,0xb01e469f,0x288a0b62,0x880be0b6,0x42d33dc3,0x7e0277e8,0xeeec45b7,0xdf2095fa,0x401a9cf6,0x2b972ec9,0xd0bf6c30,0xff4e7cdd,0xf5d0d493,0xa4ee3bbe,0x490a9a5f,0x095e1ab0,0xf920fbc3,0x87025602,0xe4dd7e22,0x688c30da,0xa877d258, + 0xc1add504,0x4c1e4610,0xd5f05755,0x7078e22a,0x8950b54f,0xe72a37ef,0xdf1b630f,0x9e08bddd,0xf35dddf2,0xb9764a00,0xcfc2e8a9,0xae23239b,0x352eaf6f,0x031f7acc,0xd0342360,0xc8892c7a,0x5d6a1911,0xfbca7b75,0x5602f920,0x0f14d506,0x36b9341a,0xff7a2324,0x810f1a84,0x3324466a, + 0xd9f0e30d,0x6a0aeaa9,0x2a8fc9b6,0x931a01c0,0xfdde8829,0x9a37ad40,0x79ea887f,0x56caf431,0xca00f326,0xe8b9b976,0x35304b02,0xa2980a8a,0xf1923b1c,0x746c000b,0xa31d248a,0x7bc7143e,0x4725912e,0x786395cc,0xc05f241f,0xf5fa0941,0xb2e12842,0xce32421b,0x64aa09a3,0xeef26683, + 0xe8c03b10,0x575730e6,0x87aab350,0x0059cd1d,0xac625fb6,0x2415e391,0x0309a18a,0x26803cc0,0x7454dcbb,0x62ecd281,0x11ac3f51,0x58f5fa8d,0x60003372,0xaf0f1694,0x9c883a08,0x3d4f64ad,0x2c344923,0xee83ef65,0x9b46600b,0x2507f6c6,0x570d8437,0x7f7b3e3d,0x26bee0de,0xdf563e7c, + 0x734829e5,0x59a82f6a,0x2ce4f055,0x68bce100,0x00c857e1,0x26100798,0x29cfdfbc,0xa05d1733,0xa8d13f34,0x5428da1f,0x29ca71e3,0x010fbd66,0x4950f5b0,0x69e0d26f,0x43e6bb47,0xe9ee99e5,0x944022d8,0xcb1f4ccf,0x1800e118,0xe57adb54,0x5cf1c904,0x4d8f5b5f,0x8f31f0ca,0xe8e48ca0, + 0x8003ef85,0x303f33ba,0x001a7be0,0x1371007d,0x66505cfd,0x0140ba2e,0xa6fcc8f8,0x76234094,0xce11635e,0x010fbd66,0x19c51e58,0xc3acf800,0x3c174d47,0x4e928895,0x003ad30f,0xd4dc55c6,0x6225eebe,0xc678ea74,0xef368c4f,0x5a0a9c55,0x95ea8d00,0x030007df,0xe131c421,0x0018f400, + 0x8ac401a6,0xe6653a2a,0x13740ba2,0xe3bf70b8,0xe1d48de4,0x42c89b84,0xc0a633ef,0x7e96234e,0x0188892a,0x8068862b,0x25112676,0x13a547d3,0x8aba4005,0x0a86bd98,0xa7822504,0xa8fee299,0x31d617ed,0x2ce81f58,0x74003efd,0x4004c5fb,0x00cd707a,0x89a00f30,0x05d15332,0xf1cb93b8, + 0xe46c02f4,0x5b02c223,0xd7de82eb,0x8e6b2224,0xb1f2847a,0xe2c53242,0xa043ace2,0x8960d51f,0xc53e9928,0x0061b83d,0x2f915748,0x061ccdeb,0x63de38b9,0xe5f0f860,0x48254930,0x1712ccb0,0xbe15d5cc,0x6f56e004,0xf0c0f4a1,0xaa331c08,0xd0069b9e,0xe8a99944,0x9e7d7202,0xf9897f66, + 0xb3531e20,0x2a83c1ef,0x19741dfa,0xd0b52490,0x0190f713,0x02bcb2bf,0x94e92889,0x9801413d,0x6b8ca07a,0x647a8078,0x2aeff840,0x8702e53a,0x5f0aeaa9,0x4832b001,0x189e2911,0xc7b42800,0x65df3d42,0x30002803,0x5d153328,0xacc33bc0,0x8fca8df0,0xd3c97245,0x198bc912,0x50684ac0, + 0x334d0577,0x6465835d,0x9c172c55,0x0a74e928,0x7a957e00,0x77810221,0xb1965f18,0x3fe54bb4,0x4d107de3,0xd5cd138c,0x3b000015,0x02ade63d,0xc47a27d8,0xca985771,0x74ae2900,0x001733cb,0x7a05d153,0x6e4635e7,0x598fd37c,0x87a7edc6,0x6e1eb0f7,0x9f5cc4ba,0xf9b643c2,0xa8c4ce76, + 0x2a749444,0x5d5d2001,0xf5c9c6eb,0xa404e87e,0x1e4b3a31,0x29507d7f,0x909fa4c9,0x15d55385,0x8fc6acd4,0x08451cfa,0x491c1d65,0x59683b14,0x72834fc7,0xdb8a6aea,0xe4ca26ae,0x07180ba2,0x6cc1af11,0xd67710c1,0xf283d538,0xb4b72e1d,0xb384bb5f,0xe67c16b6,0xe79223e2,0x511234a9, + 0x8004a9d2,0x9f7dd57c,0x790b958c,0x0c7e719c,0xa3c4cfea,0xafa7fafa,0x0aeae686,0x1c5642a1,0x0b732dd0,0xcd397811,0xedbd6be5,0x220a02a9,0x200e1af7,0xa9994cd5,0x3a2f8302,0x7976fa89,0x046d3b88,0xca7c1b0d,0x9df9de1c,0x63a69d88,0xe780e82c,0xa2262a9d,0x000353a4,0xb47755d3, + 0xaf0fd2f3,0xf6e2f0b2,0xbdca3f5b,0x9e1ec01d,0x628c115b,0x5210aeae,0xd33bb1c5,0x9182b042,0x5336cfb0,0x4f844140,0xb5ac69db,0x05533299,0xab1cef86,0x398a1fb8,0xab6ed143,0xbf666633,0x0226fc65,0xa4a224e8,0x1e9b8c53,0x7ca18f32,0x16d8d955,0xa1d5bd86,0x713bd96f,0xff3678d2, + 0x0857166f,0x9b111329,0x9568dbc1,0x81a2d93a,0x35a929c5,0xb0dce6b8,0x0c13b5e8,0x25106371,0x563d5a9f,0x6fd5eccf,0xc951861d,0xc25fe78c,0xe5655c9c,0x7e2b741d,0x98119595,0x61221c4c,0xf0c0e31b,0x27c5951f,0xe5543120,0x88f28d59,0xa27bc405,0xc53d761f,0x5de22278,0x5a31ca44, + 0x844154a5,0xdee41c35,0xa130973f,0xb8afee47,0xa09e6e3d,0x6a69ecc6,0x38a06fec,0x33254617,0x719d7f9e,0xdfb57273,0xb751a5c4,0xe1fd1de2,0xc034d30a,0x37ea6100,0x3fc2bee6,0x64a92d28,0x4c315b45,0x7c227e97,0xd7e934d8,0x29e1f008,0xec0d76c6,0xbc189467,0xd74f78ed,0x402b2a35, + 0x4932c1de,0x7afc2613,0x8f29c6c1,0xe45d8ac0,0xfa745835,0x8bbe4602,0x708a70e2,0xc690f596,0x0c7156be,0x2cf79bee,0xed40b6bc,0xc3ec6669,0x461132e2,0x979e3725,0x4e667947,0xe62883c2,0x68ef1585,0x1fd331c7,0x51e00715,0xfc7418cb,0x186560f2,0x94bd9823,0x94132ac7,0x7131b418, + 0x90da222d,0x26bfe0ef,0x001cc12e,0x55c19909,0x01972792,0x48d55970,0x1a64ebeb,0x47148cbb,0x12960afb,0x2171309a,0x2aa2360a,0x93bad43c,0xaed7b12d,0xd586bcb1,0x0be818f0,0xa8a22aae,0x1d345b24,0xfe0f16ed,0x39147f73,0x53de3963,0x0b8472a4,0xd996e793,0xa38d6cd3,0xa8dc587b, + 0xadb3c614,0x3649ccc7,0x8ee1ba16,0x075c209a,0x5eea8995,0x5baa0896,0x86c5a468,0x98e4832b,0x8a3c6355,0x244ecee1,0xc4e15a0f,0xaa21922a,0x0ddedd54,0x826cf69e,0x40050f60,0xcf7bc0cf,0x816bebdc,0xcb8dbbc3,0x146f3b60,0x3855446c,0x94f0cc96,0x0b18ec35,0xc71fef8b,0x29d8b1b2, + 0x00197c4a,0xfdc0083d,0x00702890,0x5bd0e7fc,0x7196ff14,0x3ad3d981,0x757cd400,0xf6963370,0x7f611438,0x6286573b,0xe997b883,0x338d1b92,0x92be1585,0x40abf9bc,0x96e783ea,0x56ce0469,0x062484f1,0x0ab96f9b,0xc1a5de0f,0x60046df5,0xda0b51b7,0x26e524f4,0x0006ab68,0x1a4f04a5, + 0xa0216167,0x154d2c67,0xbc65846c,0xe1b56237,0x4ace4e98,0xb57b9156,0x0bbda71d,0x0cb8ea54,0x0ac9e88b,0x87ee6a95,0xa875370e,0xa0f21df1,0x4284b7f8,0x314f80a1,0x4105e000,0xbbabfd3f,0x50de7e6e,0x639232c3,0x55da828c,0x91023d5d,0x2675fd50,0x9a117be6,0x6eb57f0d,0x2fbee000, + 0x6a2f401d,0x151b32cd,0x2c5ca496,0x62002526,0x5f57a624,0xe973e984,0xf5180065,0xe823d50a,0xa096cd3e,0x80e72bba,0x99582eb5,0xeb820ce8,0x73cdca81,0x4db469f3,0x924975bd,0xa057522e,0xfe7ad85b,0x1649348b,0x5d052f69,0x20bc003a,0x757fa7e8,0xfaac0200,0x998941d5,0x51611879, + 0xc21d48fc,0x4c538e50,0xe300026c,0xd28dc934,0x5000037d,0xf917b184,0xe000d662,0x9e41060a,0x492cd502,0xa02f2a8a,0x380581b3,0x3b2d000d,0xc4b1b2e0,0x5715c281,0x8cc2d7ba,0xa811a1f7,0x84724f24,0xece0f36e,0x20297129,0xc1b47000,0x0fd168d2,0x298cba09,0xf5f81060,0x6a13fddf, + 0xa81c704c,0x9fab167a,0xd09982fd,0xcf3ef6e4,0x0d3f3f71,0xda3800ea,0xf6099347,0x01257422,0x21a085c0,0xcca21203,0x8e2746f0,0xa64b883b,0x49f68d82,0xec290316,0x5ea6024c,0x01c70caf,0x2650a9fa,0xdc79bcfd,0xf729c31f,0x987855d6,0x029a47a6,0x765d90c5,0x0075fe46,0x533a3922, + 0xa0dceaf7,0x79331b47,0x983101eb,0x022f96e1,0xfadf01f0,0x0801d01c,0xf80308b0,0x6f7f41a1,0xbc0033e3,0xd69a318f,0xc18abc85,0xb1000c08,0x5c96c98d,0xaaf7b44e,0x8000941c,0xe5462945,0xc6174fe4,0x4f1350a1,0x0332848a,0x0067fca0,0xf22c1344,0x37bb8ae3,0xf481a430,0x14216157, + 0x00103f95,0x000e994a,0xc6030fac,0x9615ce01,0x8c53c473,0x4d6c7c55,0x3046434f,0x1d6db02f,0x0e15b676,0x298dbe80,0x97ad8071,0x001150f8,0x2f46cd46,0xa1747c97,0x92cfb6be,0xc72678eb,0xbe00037f,0xcc51a1fe,0xa0c0cb1d,0x2ea0fbc0,0xa2450fa4,0x7add5176,0xa1727abd,0x53713762, + 0x4c481077,0xb402f61f,0x6291a294,0x24e366ac,0x58d58596,0x64231ca4,0xb1bb9a59,0xf40008a1,0x065c8d82,0xb646dcfc,0x49b3658b,0x14ba3a60,0xa5473ab9,0x92fa3e30,0x371a0000,0x54414449,0xd415ebae,0x7d93fd93,0x3830308c,0xfe29ed80,0x0d700093,0xe24cf5c8,0x6590283c,0xc7fe80e0, + 0xde2966f1,0xa8575e5b,0xee720090,0xc404b0dd,0x9abef753,0xafe0a4f0,0x356314f1,0x453df7ca,0xec4071ca,0x00062a83,0x4821b141,0x90aba001,0x5ab56b5d,0x321dd600,0x5539eb9d,0x9bd4ab1b,0x41af2137,0x2e190190,0x23e34a03,0xc616e4ec,0xdd44b599,0x2e6d755b,0x857cd400,0x7f4ffc75, + 0xb8ac0eb9,0xa3a27a3e,0x29835e01,0xf36a27a0,0x9210f268,0xd9a6a6e7,0x89f15ba1,0xb7e76cc4,0xb925f835,0xa6b2a360,0xa54029d2,0x0ce9ddaf,0xd1f014e1,0xda38d2d8,0x42a031ea,0x39ca24cd,0x77e336c2,0x425124eb,0x6bd6d7bf,0x834fb016,0x5044a1b0,0x61e9d30e,0x007e3ec6,0xf2a0d7cd, + 0x0adcbfe7,0xff6dd652,0x8938599c,0xa8f85986,0x27dd5438,0xd61bf868,0x25b659ba,0x509f96c3,0xe800a701,0x4199ba72,0xf7c3b9fd,0xbf19b117,0x50e97fdb,0x0a96e78f,0x9caa1fd8,0x8201ce08,0x6fec6a1e,0xee3683fd,0x2e98d4c4,0x5731e5d1,0xabb512e0,0xaa747912,0x897b744e,0x4c97253b, + 0x13ac06fe,0x4bec3130,0xc93e5fca,0x833274d0,0x0466db7f,0x07fc6fff,0x6e2becc4,0xa8c10a96,0xfda4180a,0xdf11a908,0x1aa54c8a,0x4cc419b0,0x4ba6ca64,0x516b0974,0x066622c8,0x88340a76,0x345e4268,0x5ed4a4dc,0xc1fe0074,0x1eee5843,0x84ca2d61,0x691199d8,0xf2e64637,0x269eff64, + 0x9961b0c3,0xfcd27454,0xae6cc577,0x26489036,0x53641547,0xf42b885e,0xacf94b6b,0x00195778,0xe2db5530,0xcd1bc00a,0x5db352c4,0xdcbbaf26,0x6624be31,0x67476448,0x0e17ea2b,0xc0121919,0xc35da1dc,0x8a31624f,0x5df979cb,0x37d1458f,0x6b00c0ce,0x127f228a,0x6c3ae621,0x1d2b6d6c, + 0x4258269c,0x95970e4a,0x699aee7e,0x588bfe1d,0xca3f59b5,0x243f2449,0x142ffda8,0xa757b3fc,0x2e8949f2,0xb5c93daa,0x63437896,0x1aea6d1b,0xe44d6003,0xe384720d,0x9c8de639,0x37c726aa,0xc685d269,0xbf07aad8,0x00a5bd4f,0xd52681ec,0x76e32cad,0x2b06e48c,0x8955e1d6,0x21324b1a, + 0x886c3ae6,0x26ae469d,0x6e9d22d9,0x22182fdb,0xb63f3bf9,0x448358b3,0xfeaaeaf9,0xeb0e3c5e,0xb29e0fdd,0xd0aa1ccd,0xca08e73f,0x744a4fe3,0x00b994b9,0x587289dc,0x00cd8afa,0x9c7f0860,0xe9d89db3,0xe1d6726a,0x94ffe20b,0x4f910521,0x0296f330,0xb5cd2eed,0x09fecb4b,0x1f0ead0d, + 0x205d50d3,0x52bbf5a4,0x988461bd,0xa799b0ea,0xae34332c,0x5fe13c53,0x4dfefccd,0x49fa7780,0x1cc13063,0x5d7a8b88,0x14e85e57,0x5d7fb0c6,0x4004cbaf,0xd2453af9,0x0a6cf72c,0x28d85100,0xa60193c1,0x69d9c9aa,0x25aba444,0xe663a8bd,0xee3f052d,0x5c427d45,0xebbd2fc1,0x1cea291f, + 0xe3ce4202,0x2309bf0f,0x0d8754c4,0xc74c517a,0xbb60478a,0xfdab7bd1,0xeb0bfea4,0x22d8641f,0x5a3245da,0xfbb42bc1,0x0c686737,0xd7f3b34c,0x004cbaf5,0xc6d52be4,0x1cf95d60,0x0e94c380,0x1c9aa980,0xb701c003,0x39fe9179,0x8cb0296f,0x032d2ce3,0xcce0a66e,0x19fd497b,0x5e3f4840, + 0x022ffa0e,0x549a4615,0x79b14d87,0x70e3f9c2,0xa1e43635,0xcbe3b83f,0x03d0157d,0xf9ea05b5,0xc582979d,0x79239fba,0x7ec97bba,0x9dd089f1,0xebd43fca,0x80814d32,0xf945677f,0x83f0801c,0x35734418,0x8776bb39,0x146ddd21,0xcfe26c09,0x7a814b7b,0x300ed844,0xcd59f1a5,0x42065e50, + 0xf7ebbc34,0xea9751f2,0xcd7ad9b0,0xccd4a266,0x11664466,0xd2c2de68,0xe3e3b471,0x9f4f7916,0x48102ffb,0x790c7dd6,0xd0a13965,0x492cbb9f,0xdcc36ee0,0x326b5d12,0x34c77e00,0xc801f31a,0xb9aa49e6,0xbcda5b27,0x236edc9a,0x4f646803,0x37e5c243,0xc6052df7,0x5e30124b,0xbc62d2bf, + 0x49f48404,0x3af5b035,0x0c21e0ba,0xc3361d46,0x49002b83,0x8e49c7dd,0xd3c4d2cb,0x4abb793d,0x3fa868f5,0x09740dfb,0x16c87e0a,0x4d8fb54b,0xae897e65,0xfc647935,0xd4143817,0x0075540c,0x33e4c5a8,0xc4b95003,0x2003abb9,0xc5db9355,0x9106a029,0xcd996a44,0x24414b7d,0x25c8bfa7, + 0x3289279c,0x909162b3,0x96fbba72,0x0179641c,0xd90ca30d,0x2555a0ca,0xcea4dfcd,0xcebf29fd,0x5c57fc2e,0x57ec630e,0xbbd9aaed,0x838353ca,0xb63b99cb,0x3988cb7d,0xca2badf0,0x825d12bc,0x30c7714c,0xb46ec50b,0xb4a62d42,0x4f9d7d5e,0xe334b001,0xae49b3ba,0x0064c726,0x8f6c341a, + 0x0a5bee73,0x55fd49a2,0x8ea7e83e,0x207a4df3,0xcd9a7da4,0xe244d63d,0x6d8754bc,0x8c9cbf65,0xf980c836,0x99af43d5,0x8c0475a1,0x4952edad,0x7edec852,0x87529cbc,0x9bac2705,0x3227d967,0xba25b331,0x66e8ef66,0xa801c4a1,0x85a6fbb5,0xc0b04b60,0x06393554,0x4c4746c0,0x296f79fb, + 0x045185c0,0x854ee1c9,0x13331d88,0xb0eb98a2,0x97883551,0x03a30576,0x9db031ec,0x236a8a48,0x979e21d6,0x9682dbda,0x65080e24,0x33311323,0xef66ba25,0x5c2cd1fc,0x8c128ee2,0xe6f5a143,0xb9c9aaa6,0x8ed014e9,0xbcfb0279,0x761c14b7,0xf0fea872,0x99960c2f,0x22995d83,0xc3ae9944, + 0x04a07876,0x50a3a545,0x9f26ac14,0x8acca451,0x9d0e07e7,0x28d82896,0xa13fcf11,0xc0ff2fad,0xe8eff471,0xc24bc951,0xa4a40251,0x554f0a41,0x67df7393,0x6ac9fe28,0xce0c459f,0x9a414b79,0xeaa42ea4,0x1189c1e3,0xa2132b98,0xfb61d74c,0x54b90ecf,0x69fde290,0x13ded28e,0x4272e6d9, + 0x7cb5fa1d,0x64e03ba3,0xa1efc5ff,0xc0a02f5f,0xf060251d,0x33296e1d,0x2adce4d5,0x601a3fc5,0x5bde7ad3,0x27e10e0a,0x6a54c3fe,0xce7d679b,0xfde76639,0xef401c72,0xc3d3eb74,0xfce6adfd,0x4dd5ef36,0x36dde237,0xbcea0802,0x509c80de,0xc27b2ca7,0x3080101d,0x89eec0bc,0x67645bea, + 0x06b69fe5,0x002fdb15,0xdc46c83c,0x8a5c46ab,0xa5e734c9,0xd7e7e589,0x53616879,0x71a0497f,0xf6832c1e,0xc52ed675,0xd76e6512,0x05b77c59,0xe09dc5cd,0xae1b7e52,0x97cbf951,0x216e5fc3,0x5b7bd988,0x653a84e4,0xd104d46f,0xa986bb95,0x606fdabc,0xe0636aca,0x99592fa7,0xf385e498, + 0x103d1a20,0x86b3e3a2,0xcc2a3d4a,0x6d3e977c,0x7ac19deb,0xa5eba650,0xff28eaf7,0x610b92e4,0x98e4b32f,0x9bc1baf1,0xc82b463d,0x8e3cbd52,0x2d213e71,0xbd13705c,0x9504333a,0x28283195,0x231de7a9,0x37679737,0x25ea746d,0x5a29da90,0xf5e3d26f,0xbd1e97be,0x2a655dde,0x76ba0ea1, + 0xc3d91afe,0x1bbab2c9,0x4865af7e,0x92f7441c,0x17479411,0x2956dda8,0x76b52891,0xbf3a6af8,0xd97cbd41,0x27df3509,0xe32da7c6,0xba8d291c,0x47739659,0x40298ff2,0x97cd375b,0x04a0c747,0x448be581,0xb3ccde73,0x688323b8,0x4e70d998,0xecd148cb,0xe3f6f83c,0x9f531bf0,0x4d16981c, + 0x5811ac48,0xdaef4e9e,0xb5183dd8,0x6f6431ca,0x1d8af34f,0x1d42730d,0x18799f3c,0x5bf7f4fb,0xba2da9ee,0x94000869,0x897b4d35,0x4f57ba13,0x0f08f0c3,0xc46dda18,0x950f0f2b,0xac1ac6d9,0xfdcd49ca,0x0495e680,0xe8fe0200,0xa6a6bbda,0x563da3a0,0x89baacb3,0x274b5c48,0x1cbd1dde, + 0xde082eee,0x0c232aa4,0x874d1019,0x9e76670c,0x291968e4,0x988bba50,0xd66b979d,0x78ee9aa9,0xbeab123f,0x002329be,0xc6fcefd8,0xdf7443ac,0xee42a8d1,0xea1392f2,0x7c254f5c,0x4a5683e0,0xeb77ed74,0xb8c76df0,0xafbee635,0x5998ecf9,0x8ee3fb8a,0xa70f2c76,0xbc5622e5,0xc4fdc687, + 0xcfdc9eed,0xe9b6e834,0xdc33affd,0x854603ba,0xa74b1ce3,0xddc1efe0,0xdab5963d,0xf2d9aaeb,0x6f89a4be,0x9dd224bf,0x51c7ee3c,0x47f09ea8,0xae732be9,0x4ca42aae,0xbdee4c87,0xf34bcec8,0xb7cd822c,0x45703896,0xd0dbf396,0xae158f0a,0xe77dd1df,0xf703c368,0xb57c3ff0,0xb8a7509c, + 0x801ab40e,0x8049a454,0x3c923127,0x40ff0f7f,0xf166e019,0xfbb554c1,0x7b9e4675,0x50b4d860,0x5675f9ed,0x3e758a79,0xe995b762,0x4e3db286,0xd92f5293,0x091d89ff,0x1c919d39,0xacbc422a,0x80a69bb9,0x17a762d4,0x364862b1,0xb1cf5c45,0x46062b18,0x09c8baa1,0x94bc34de,0xb804c9a1, + 0xe16cba81,0x9d21f499,0x3dc08102,0x4ce61ab0,0x659583f0,0xf6dbf237,0xfdb767cb,0x7b802050,0x09c38ad1,0x39ef5dd0,0x427314b7,0x6fa0f01d,0x631278fc,0x6ef140ab,0xba250d44,0xcf7e800a,0x99311242,0x003948b5,0x54c3db55,0xd7b8f5eb,0x4d697e3b,0xc05fb637,0x99a7253c,0x21045a0a, + 0xd5a71ddc,0x67f01018,0x8601fb97,0x8bc3940b,0x5af75560,0x140c5b70,0xe39623ee,0x0b54000d,0x7137948f,0x46a41ac8,0x07964c87,0x1f12757b,0xfd62a3bc,0xcac63deb,0x84b1cbc5,0x5edb7e72,0x309ba79d,0x06ec1f0d,0x129beaae,0x005970ea,0xec3987de,0x3f427669,0x29a48d96,0x45d53774, + 0xe25a6741,0x9bc4c73d,0xbdb835b6,0xac6b6c1d,0xd9b7d1f1,0xac6c6d7a,0x406f347f,0x2d843456,0xed502a1b,0x904bd6d7,0x0e71fdcb,0xf8b30160,0xf0bca805,0x2f3d954f,0x846ca0b2,0x63bc372a,0x5270e9bc,0x94c871a2,0x53a040bd,0x8943a179,0x513256ea,0x19ec90ae,0x83a71ed5,0x36fca529, + 0x02211313,0x66ea116d,0xd2a3a84e,0x679a050f,0x439b4e43,0x8ebd934b,0xdf9aad04,0x1bc6bca0,0x9a3da058,0x2ae51d7c,0x95e8dc95,0x07aa9e35,0x6c47b5fb,0x102d7ad8,0x3716e9a1,0xb95eb6e5,0x4a7aef25,0x7479cac6,0x442a058f,0x59f7e303,0x36ee4ff6,0x8d1afa80,0x24a84206,0x5d4694de, + 0xf535ca1a,0xc41875e3,0x6e5a4f24,0x39001a7a,0xde642dbf,0x961c50ec,0x2dd4276f,0xa1953ac1,0xf8c174af,0x391283d1,0xeee5c879,0x1c3ba84b,0x2e9e2e94,0xfdda8103,0x0b8c6b05,0x18fc93a5,0x8c27ae1b,0x591788bb,0x414c0470,0x57449ef1,0x1fad3b54,0xa8ee21b0,0xe4b0f947,0x88ff588e, + 0xfecb4615,0xf5d5a473,0x5379919c,0x286a6007,0x34acb7d7,0x2ba2d3c9,0x49dbd21f,0x31e1d6fe,0x35621595,0x1d5f7044,0x007ee83a,0x4e199010,0xe94e9e9f,0x31eba7de,0xafafecde,0xd6719bf7,0x3e3f1978,0xa1b05e8e,0x34ded8b8,0xca03fa0b,0xf48b5bc4,0x0860db4a,0x54b3559e,0xb085e8ae, + 0x2660eb77,0x3057c65b,0x8edb9eea,0xfa9d3789,0x50d4cc56,0x10f8277e,0x39a6020d,0x6f3788d0,0xfd78c454,0x8545a358,0xe078b7b0,0xe88cd5ea,0xa06061e6,0x12eee10d,0x346e500e,0xb8821be1,0x15078bef,0xa25abe22,0x48d1f1f1,0x631436cc,0x3cfd1dd7,0x8ce53159,0x21cbdb4a,0x15d70658, + 0x5dec7153,0xde2c27b4,0xff093665,0x74e7b242,0x8423907a,0x947b5651,0x8a07b426,0xa0734c4f,0x09576f11,0xef77213e,0x587b9eba,0xf15f9131,0x909e0180,0xceb82b7c,0x57f229e3,0xf12ee168,0x9fe12fa8,0x2906fdf6,0xa8cdf998,0xefa1bcfc,0x5f4f53ba,0x6da55e63,0x7bf9515e,0x7d39b085, + 0x49e11b7b,0x8348d364,0x17b18174,0xa535c1c4,0x45da3907,0x53aa3e8c,0x90ee409a,0xfca2ef5c,0x73e2c5ba,0x149ba512,0x8d7d69d5,0x8699b0d4,0xacd3c745,0x54539eb4,0xadad43d1,0x555b81fc,0xaa2febc0,0x02644346,0xcc22a6f2,0x7a6a985e,0x0de7e4d4,0x931dd77d,0xe169bfb4,0xf87f4dda, + 0xe6588d19,0x41ae25f4,0xbba1ca51,0x3e41a793,0xf9619f17,0xa535c187,0xaa0cad07,0xc07672a8,0x3e61599a,0x7751faa8,0xf48a244b,0x6ca37e77,0x687e5e06,0x2dab12f0,0xaa938c51,0x2a1af1ad,0x74a4976d,0x7f938254,0xc5b8b6bc,0x2b33c607,0x1aaca48e,0xb068cbd5,0x91ed885d,0xf5d7b4f1, + 0x8c4dad30,0xbe94cb11,0x8c98738b,0x9b3473bf,0x09747965,0xa788246b,0x1d45a04a,0xa0f4a64a,0xe93c0ff5,0xae15d466,0x52fa885d,0xaa91d4f0,0x4f506cec,0x3dc27956,0x3b670efd,0x31018ac6,0x24731dbd,0x3d3f1841,0x64bf5ea0,0x3b638a2a,0x5ce552b0,0x1bf7290e,0x95303802,0xbf592823, + 0xd6c03ccb,0x2b2b4632,0x3583cb8f,0x3b46d7d8,0x6f3fad06,0xff2bbe68,0xfee05403,0x66588b11,0xdbef51f4,0x06c9a125,0x38d7cd98,0xf8d4934c,0x5a71bc41,0x4f820f4a,0xee7522e5,0x0aecc5c6,0xe11969ae,0x2e61d629,0xeab02dd9,0x247968bd,0x0c2b1bbb,0xc8f5c480,0xf5a6f94d,0x92cfda88, + 0xd6c7145c,0x91430d2b,0xb37f9340,0xf50bd8e2,0x1199416f,0xd576304b,0x5ba74e94,0xad235bbf,0xc163591b,0xa8c1b995,0x0eb0dd0a,0x2b1289cb,0x0568c0df,0xe1694579,0xfdf4c27f,0x964a3c0f,0x69a25786,0xe13acc83,0xc15e1634,0xeaa67960,0x107a54e6,0xf3b4a36e,0x77a58b7c,0xa52f8c04, + 0x48af0a0b,0xd32a38a9,0x0136602d,0xf8efc03a,0x1ede9a4e,0xfe77b97b,0xddaf84ac,0xe28b9259,0x2a590e80,0x86acaae6,0xb6a033a2,0x49740baf,0xb2900096,0x77eb24e5,0x967935eb,0x444ca1ca,0xb0edfe0d,0xaef6d70b,0x8a61f9c9,0x568cc8ea,0x11f4779c,0x8df367fa,0x7a575f9b,0x00098bf2, + 0xd4aae68c,0xea9aa473,0xb000ceaf,0x13938832,0xe5a87cae,0x1cc9a0df,0xf1ccd78f,0x5c758a39,0xf855c6d1,0x79d3ac79,0x1015aaa2,0x3b62a18d,0x6b1ed7c0,0x82c7d064,0xa2a64b7a,0xc5bca038,0x42cd24d3,0xf520ab8d,0x906bc563,0x53001249,0xfadc74e9,0xd1cf6bb5,0xd276ba7b,0xaba4d877, + 0x54a00df0,0xd6fdb7a1,0x70456823,0xe1990bf8,0xb67e508f,0x3ccaebfc,0xc79e7000,0x1442603e,0x5f993342,0xf3677b4c,0x7c76fa1e,0x4449609f,0xdd0e7c52,0x7fe31d8d,0x6549d154,0x795eb4b3,0x5a16ca48,0xa09a6559,0x6c07205c,0xd3c3f7b8,0x742c1a18,0x1869fc7f,0x6454dbda,0xe5b2a600, + 0x68ebf5b8,0x7cac13e7,0x0480c81c,0x3e87e58b,0xe872455e,0xc2b41622,0xba1bf807,0x82a00fe0,0x7af5bdbc,0x0074d78e,0x9a00027c,0xe3791a07,0xe254ca56,0x71cada13,0x275588ee,0x9258b761,0xee1cf8a4,0x00b0b37d,0x8d5543ff,0x2f90f7ce,0x04fb2a99,0x1843e92a,0xdddb6443,0x64c04c06, + 0xcc8ed1b9,0xd3a52000,0x6c17eb71,0x051697d3,0x8ceed1c0,0x08918f9e,0x1f4b7e30,0xd3951a34,0x75413c0a,0x32c7f663,0x806d35a6,0xa73ef2cc,0xaa963e0f,0x0c1e8525,0xabd2e533,0xe99b0866,0xae4f89d3,0x3b6ff449,0x2f3c1d62,0xafdd1b65,0x3ecaa64b,0xd37275bb,0x51b7b3c9,0x0d1faaee, + 0x22e5b4f4,0x3a720032,0xc2fd619d,0x69945f68,0x55ef1809,0x37ebfc39,0x7aec83ad,0x90d62d3e,0x7456811f,0xeff17252,0x8615607e,0x2d461aed,0xdb92b01d,0xee30be94,0x3d7544d8,0x6452cbd8,0x64a9bfd6,0x583f1d38,0x5cbd09c9,0xbc2a22a8,0xcaca7efb,0xf2cda399,0xd05fb652,0x1724bafd, + 0xf272c1c5,0xf7a375e8,0x1c0d32c1,0x20abef0c,0xa400246b,0xfac9396c,0x4f94e8dd,0xd5f0577e,0xc775f00b,0x5c38c967,0x88681ae3,0x184624fe,0x01547ada,0xf88fbc70,0x6d710bcb,0x02df8cb4,0x9cf0617f,0x39a431e6,0xc597342d,0x77dab5ae,0xbb7238f7,0x2a3b8ebc,0xbbc2ac13,0x3276c6af, + 0xec2eebf9,0x65845a5a,0x925cccc2,0x9a78e28b,0xf571bae4,0x2f823d90,0x79532d92,0xe5b29419,0x2257eb0c,0xd1fc6f76,0xf27f8cea,0x664d9532,0x544639e5,0x97bde3bd,0xb2c523b5,0xadc3a529,0xcb68d49a,0xad0e85b6,0xd93bbc61,0x4318a2ce,0x7342d396,0x54ed1c75,0x895181aa,0xbb8ea2bb, + 0x82452f88,0xfd034569,0xad2a1775,0x0e528b99,0x1724b57a,0x9b8cb1c5,0x775ebb7b,0xd92f5507,0x657add32,0xbaca38be,0x581cb652,0x4efa2dbf,0xcb589911,0x5b41cf3a,0x442205a7,0x8f3f99dd,0x894178ae,0xf8cb2918,0xa185b005,0xcbfe0115,0xb09909f6,0xdc3186e1,0x3691ebb3,0x1cbd1d2c, + 0xe50e83ce,0x8bb8ebd1,0x4d80ef0a,0xbc6ddee1,0x000382ee,0x981719a2,0x1c515325,0xc365878b,0x5ba65b4d,0xcc6c7a4e,0x9dd9cb64,0xf62654ec,0x38194d6b,0xfa8ceb96,0xe2f1af78,0x2505fc87,0x5ec0a462,0xba12cb01,0x9d38095f,0xc235a38c,0x6cd4b352,0x68d759a1,0xd69ddc6e,0xa54bb2ce, + 0x8f450e48,0xacbee3a8,0x7ac77857,0xec75c82e,0x80021775,0x198d31f0,0x67bcaffa,0x7b92a0c8,0x6aa9f41d,0xd2c70319,0xd631da85,0x692aacfa,0x37c3dbb8,0x9417885e,0x9a0523e8,0xba10f608,0x9889683f,0x13b87d30,0x4dec53bf,0x57bc3faf,0x4a30e60d,0x514cedb1,0xf0a8ddc7,0xa630df0e, + 0x001327ae,0x9d77768e,0x945a0ded,0xd26d3d1d,0xda1392c8,0xfd271884,0x0d533e8a,0x3366bb69,0x4a835d89,0xa7d075e1,0xc4168d2a,0xe9da385e,0xdb8d1e72,0xf971c195,0x17a514f8,0x3189417b,0x714f2052,0xdbf74152,0x7e265605,0x6e805302,0x7cd9a941,0xcb56c8a4,0x459e4195,0x434e0164, + 0x71d45fa4,0x47bc2a37,0x3a2547f2,0xd81c268d,0xee7bad24,0xc3bbe358,0x04111de3,0xae673d08,0x6e9e180d,0x271e4564,0x533e8afd,0x862b6975,0x3abb1750,0x41d7ba95,0xed76aa9f,0x4cabeb52,0xa068fce7,0x3b320210,0x02b2b477,0x4389417b,0x200728ea,0xb3e27e9f,0x2495c26b,0xa8a2c31c, + 0x71c141d4,0xa84e943f,0xe3a8d68b,0x8f78546e,0xc3c2e974,0x5f01775e,0x850d551c,0x54a0e970,0xd4cb571e,0x83e3bd59,0x0b43e639,0x927d3dfa,0xfa2d03cf,0xf457e938,0x5b4baa99,0xb10d0863,0xbdd4a9cb,0xb554fa0e,0x18d5476b,0x00018346,0xefae6a1d,0xc5ad109f,0x82f8727d,0x002ccf12, + 0xcbaa72c5,0x6bd76c7a,0xd99b67da,0x302e8e24,0xf7331b00,0x11b6fec1,0x9602cabd,0xfcef0af4,0x49a16c0d,0x09a33434,0x4964b5da,0xe418614b,0x2036a34e,0x31da1a83,0x0aa2d275,0xe24e31bb,0x75533e8a,0xa10c6b69,0x953abb10,0x9f41d7ba,0x10f196aa,0x94587354,0x3c93da00,0x09a00a1a, + 0x0bf80031,0x91f5564a,0x92a05ff2,0x9be6c408,0x2863cf24,0xc60533b9,0xdb75c3d0,0xefe5b095,0x87b72a09,0xcb1dcabe,0x1d2691e9,0xe9379f8b,0xf4727213,0xf64db680,0xe8988f24,0x315fa4e3,0xb690aa66,0x62ea10fa,0xf752a757,0xd148e03a,0xb68e48a2,0x8961abe6,0xdfaf5b47,0x1de4626d, + 0x4f71f480,0x63bc07f7,0x94c3486d,0xec498be9,0x346973a0,0xf11a3603,0xbf8e224c,0xf97274e0,0xefc5e3a9,0xfa9dcfd2,0xe67eb606,0x57d26fbe,0xc6592fb9,0x2176c9c7,0x69ef0881,0xedc79259,0x6e88502e,0xa6e8716b,0x15fa4e3e,0x690aa663,0x2ea10fab,0x752a7576,0x4d4e03af,0xb73dab2a, + 0xc0df1025,0xe1669eb4,0x85497726,0x2a52ae56,0x5138f8b2,0x0c971cc8,0x6bf35c64,0x11db84d6,0x7121b248,0xf6365e3b,0x81d846cb,0x1389fb5d,0x6e541cef,0x767d56bb,0xe7868681,0x9c61fac6,0x7a0ee551,0xb640b60d,0x8a469373,0x55e3aef6,0xda824d52,0x4f1adb88,0x271f5778,0x533e8afd, + 0x0fab6975,0x75762ea1,0x83af752a,0xe0400060,0x82d11b40,0x568f9e20,0x35d5bd9f,0xfe841fd2,0xc6cbc6c0,0xef524a5f,0xd3b5c9e2,0xb24b6fa0,0x41a28c1f,0xe785d597,0xf412838e,0x22c71a3e,0x809e6098,0x17e70ac5,0xb041aa7e,0x4338c855,0xbd9142fe,0xfcf72c14,0x6a838ed5,0x0641bf22, + 0x9ba47efc,0x04651700,0xfd271f45,0x75533e8a,0xa10c6b69,0xdd3d762e,0xc9a507d6,0xd1bf691a,0xe57a7092,0xa731e848,0xae29dd66,0x0398aeac,0x7994027c,0x6fa15555,0x44ecb039,0xa0c3a326,0xdf5961c7,0x92538e85,0xefc2d5f0,0x5dabdab4,0xf978912b,0xb27cf879,0x4025762f,0x58f7d534, + 0xac0558e9,0xcc3debc9,0x3b59e1e8,0x17f219c6,0x0530da2e,0x4f31966c,0x5581df01,0x9cce8760,0xe87faf68,0xb4a175a0,0x1dd9db08,0x688dbebe,0x4abe07e4,0xed2c5568,0xf8eaf748,0xa5c94dad,0x5e81d2f0,0xce1b0a73,0x2c320bc1,0x82d4b77f,0x395d7875,0x57c5e607,0x62c2a1c1,0x86b03719, + 0x3ef9b950,0x920ba8fe,0x0a91c9ae,0x763c1956,0x68178a50,0xe2dc204c,0xdeb612bb,0xa4551ecb,0xc3ad7c61,0xe8cd1ef6,0xc63b5911,0x6635be99,0xec76c291,0x6ceb3113,0x57a3feba,0xe65cd9af,0xec30e723,0x63775630,0x20f421d3,0x9f87fde9,0xd2f001ef,0xd6663e89,0x9ad8f679,0xa36cf1e5, + 0xcdeb078d,0xc0351bc7,0x4ed00018,0x6671f316,0x40aac097,0x0f6bda49,0x0ffd6bad,0xbdf01a17,0xacf1f8d0,0x9a028978,0xd8d84aef,0x09683c4b,0xa49feb55,0x95ef7fe7,0xbba0609b,0xb87f587f,0x3627748d,0x133365d3,0xa647bacc,0xf359c3d4,0xf73c6d05,0x7061893d,0x73c00091,0x22871cdb, + 0x93cbe7a3,0xbec3e9e2,0x8fab0920,0x5970b2ae,0xfd71629b,0x7fad790a,0x80009bb3,0x22a3efd3,0xd9d07a80,0x1c1a65b1,0xec570ec3,0x1e561f9e,0xfaa1e6cc,0xe3dbb2ef,0xfa36e65e,0xd797360f,0xb50d59b6,0xddfdfbd6,0x36944ef0,0x64c95902,0x62666cbd,0xea530cd8,0xe3df2e71,0xf5b38f4e, + 0x2b849376,0x83c50002,0x2ecb38f9,0xe8287eef,0xd38c2ffe,0x9d6de292,0x4091dad7,0x0d38e404,0xf0b1692f,0x0c706312,0x68715c3b,0x34aa3bcd,0xcdb77a3a,0xf5c17d1e,0x4e9ef343,0xe6f7adfb,0xb83f751d,0x55a32fbb,0xafa6846a,0xa9bf9e49,0xa94b398b,0xf4f340fe,0x0da9a0e0,0xef6f5286, + 0xefa89265,0x6b8fd6ed,0x7d1efac9,0xdb6be21b,0x0fb7fca1,0xaf94339e,0xc8e859e4,0xec31c19c,0xa27bc770,0x16ddc25e,0x265da938,0x7ad85160,0x708e76ad,0xb5eb65d3,0x52e3cedc,0x91887ee7,0x307c8a1c,0x16a027d0,0xf5d48b30,0x95bfcb14,0x8db23858,0xba62d096,0x3bd4a1bc,0x58cb22b5, + 0xa2fb0dd8,0xcc817054,0x8fd3effe,0x75ad40b6,0x49242053,0x3e296055,0xc31c1f41,0x6ab0070e,0xd18cd465,0xa562ddb3,0x23e56ad1,0x9a37b8a6,0xa9fda827,0x23f7d547,0x8ad34af6,0x9da3800e,0xc7368ca8,0xdc2bc697,0xa1b74a15,0xf95b3bd4,0xdf563666,0x8fa7fe53,0xae3ed5a5,0x90cbda0b, + 0x7a5471be,0x383e90cb,0xcb04f686,0x0376adcf,0xf9a20bc3,0x4ef185a9,0x8a7ba570,0x49d6ed0f,0x44d882a3,0x53c10f13,0x0eb83e50,0x344520df,0x02dfdeaa,0xfbc58acb,0x4679bc6e,0xa526a909,0xa8f119de,0xfa79ff93,0x17987731,0x14842af1,0xb8b25cf9,0xaedc3b74,0x340d4a65,0xdcbd6d05, + 0x312b1969,0x672ed4c0,0x7ed5a1f0,0xe28b4ab6,0x33d9cb04,0xe980685a,0x1093bbf0,0x4b99ab35,0xfcadb1cc,0x053e3b6f,0x9e9d1500,0x9338bfa6,0xb576e1d9,0x00cea03f,0x1dd8245b,0x39fc34a1,0x5c11b218,0x20c37b55,0xa5aa7ab5,0xd7f947a6,0xb6264b1c,0xd141cf97,0xd385d9b1,0xa8cca267, + 0x5ec6dcad,0x1b6017d1,0x1c095b3b,0xffe88bfc,0xe3ddea7f,0xbd00137f,0xbb87b66e,0x6cc94580,0xcf95e6d1,0xb1dced96,0xbf319d29,0x0d5fe871,0x9b375e80,0x40838d86,0x45b32517,0x9b3e579b,0xe44e5267,0x2b7faa04,0x6cdd7a00,0x325e609d,0xe579b45b,0x054e79b3,0xff4c0b2f,0x39bcc937, + 0x38944053,0x792a95a3,0x71ac712d,0xf2a2da26,0x92b71cd9,0xe787a5e2,0x30032ddf,0x83bd1444,0x7f2552b4,0x4b647d7b,0xfd7efb6a,0xff042dbf,0x16055fbf,0x58002c00,0x6000b000,0x8002c001,0x000b0005,0x002c0016,0x00b00058,0x02c00160,0x0b000580,0x2c001600,0xb0005800,0xc0016000, + 0x00058002,0x0016000b,0x0058002c,0x016000b0,0x058002c0,0x16000b00,0x58002c00,0x6000b000,0x8002c001,0x000b0005,0x002c0016,0x00b00058,0x02c00160,0x0b000580,0x2c001600,0xb0005800,0xc0016000,0x00058002,0x0016000b,0x0058002c,0x016000b0,0x058002c0,0x16000b00,0x58002c00, + 0x6000b000,0x8002c001,0x000b0005,0x002c0016,0x00b00058,0x02c00160,0x0b000580,0x2c001600,0xb0005800,0xc0016000,0x00058002,0x25fe000b,0x8c01ffc7,0x03859954,0x00a7226a,0x49000000,0xae444e45,0x00826042, +}; + diff --git a/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18.fnt b/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18.fnt new file mode 100644 index 000000000..82e9f7443 Binary files /dev/null and b/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18.fnt differ diff --git a/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18.fnt.inl b/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18.fnt.inl new file mode 100644 index 000000000..28339b2cf --- /dev/null +++ b/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18.fnt.inl @@ -0,0 +1,167 @@ +{ + 0x42,0x4d,0x46,0x03,0x01,0x25,0x00,0x00,0x00,0x12,0x00,0xd0,0x00,0x64,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x44,0x65,0x6a,0x61,0x56,0x75,0x20,0x53,0x65, + 0x72,0x69,0x66,0x20,0x43,0x6f,0x6e,0x64,0x65,0x6e,0x73,0x65,0x64,0x00,0x02,0x0f,0x00,0x00,0x00,0x12,0x00,0x0e,0x00,0x00,0x01,0x00,0x01,0x01,0x00,0x00,0x01,0x00, + 0x00,0x00,0x03,0x31,0x00,0x00,0x00,0x44,0x65,0x6a,0x61,0x56,0x75,0x53,0x61,0x6e,0x73,0x43,0x6f,0x6e,0x64,0x65,0x6e,0x73,0x65,0x64,0x42,0x6f,0x6c,0x64,0x4f,0x75, + 0x74,0x6c,0x69,0x6e,0x65,0x52,0x47,0x42,0x41,0x62,0x69,0x6e,0x61,0x72,0x79,0x31,0x38,0x5f,0x30,0x2e,0x70,0x6e,0x67,0x00,0x04,0xc4,0x13,0x00,0x00,0x20,0x00,0x00, + 0x00,0xfc,0x00,0x43,0x00,0x03,0x00,0x03,0x00,0xff,0xff,0xff,0xff,0x05,0x00,0x00,0x0f,0x21,0x00,0x00,0x00,0x9a,0x00,0x54,0x00,0x06,0x00,0x0e,0x00,0x00,0x00,0x02, + 0x00,0x06,0x00,0x00,0x0f,0x22,0x00,0x00,0x00,0x98,0x00,0x94,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x02,0x00,0x07,0x00,0x00,0x0f,0x23,0x00,0x00,0x00,0x76,0x00,0x63, + 0x00,0x0d,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0b,0x00,0x00,0x0f,0x24,0x00,0x00,0x00,0x89,0x00,0x13,0x00,0x0a,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x09,0x00,0x00, + 0x0f,0x25,0x00,0x00,0x00,0x6e,0x00,0x25,0x00,0x0f,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0d,0x00,0x00,0x0f,0x26,0x00,0x00,0x00,0x8d,0x00,0x25,0x00,0x0e,0x00,0x0f, + 0x00,0xff,0xff,0x01,0x00,0x0c,0x00,0x00,0x0f,0x27,0x00,0x00,0x00,0xfb,0x00,0x23,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x02,0x00,0x04,0x00,0x00,0x0f,0x28,0x00,0x00, + 0x00,0xd8,0x00,0x12,0x00,0x07,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x06,0x00,0x00,0x0f,0x29,0x00,0x00,0x00,0xcf,0x00,0x12,0x00,0x08,0x00,0x11,0x00,0xff,0xff,0x01, + 0x00,0x06,0x00,0x00,0x0f,0x2a,0x00,0x00,0x00,0x0a,0x00,0x8d,0x00,0x09,0x00,0x0a,0x00,0xff,0xff,0x01,0x00,0x07,0x00,0x00,0x0f,0x2b,0x00,0x00,0x00,0x81,0x00,0x71, + 0x00,0x0b,0x00,0x0c,0x00,0x00,0x00,0x03,0x00,0x0b,0x00,0x00,0x0f,0x2c,0x00,0x00,0x00,0xf9,0x00,0x86,0x00,0x06,0x00,0x08,0x00,0xff,0xff,0x0a,0x00,0x05,0x00,0x00, + 0x0f,0x2d,0x00,0x00,0x00,0x19,0x00,0xa1,0x00,0x07,0x00,0x05,0x00,0xff,0xff,0x08,0x00,0x06,0x00,0x00,0x0f,0x2e,0x00,0x00,0x00,0xde,0x00,0x91,0x00,0x05,0x00,0x06, + 0x00,0x00,0x00,0x0a,0x00,0x05,0x00,0x00,0x0f,0x2f,0x00,0x00,0x00,0x60,0x00,0x45,0x00,0x07,0x00,0x0f,0x00,0xff,0xff,0x02,0x00,0x05,0x00,0x00,0x0f,0x30,0x00,0x00, + 0x00,0x62,0x00,0x35,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0x31,0x00,0x00,0x00,0x45,0x00,0x55,0x00,0x09,0x00,0x0e,0x00,0x00,0x00,0x01, + 0x00,0x09,0x00,0x00,0x0f,0x32,0x00,0x00,0x00,0x24,0x00,0x56,0x00,0x0b,0x00,0x0e,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0x33,0x00,0x00,0x00,0xda,0x00,0x34, + 0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0x34,0x00,0x00,0x00,0x18,0x00,0x56,0x00,0x0b,0x00,0x0e,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00, + 0x0f,0x35,0x00,0x00,0x00,0x30,0x00,0x56,0x00,0x0a,0x00,0x0e,0x00,0x00,0x00,0x02,0x00,0x09,0x00,0x00,0x0f,0x36,0x00,0x00,0x00,0xf2,0x00,0x33,0x00,0x0b,0x00,0x0f, + 0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0x37,0x00,0x00,0x00,0x40,0x00,0x73,0x00,0x0a,0x00,0x0d,0x00,0x00,0x00,0x02,0x00,0x09,0x00,0x00,0x0f,0x38,0x00,0x00, + 0x00,0x00,0x00,0x46,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0x39,0x00,0x00,0x00,0x1a,0x00,0x36,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01, + 0x00,0x09,0x00,0x00,0x0f,0x3a,0x00,0x00,0x00,0x7f,0x00,0x7f,0x00,0x05,0x00,0x0b,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x00,0x0f,0x3b,0x00,0x00,0x00,0xf9,0x00,0x52, + 0x00,0x06,0x00,0x0d,0x00,0xff,0xff,0x05,0x00,0x05,0x00,0x00,0x0f,0x3c,0x00,0x00,0x00,0xe8,0x00,0x6f,0x00,0x0b,0x00,0x0b,0x00,0x00,0x00,0x04,0x00,0x0b,0x00,0x00, + 0x0f,0x3d,0x00,0x00,0x00,0x0c,0x00,0x98,0x00,0x0b,0x00,0x08,0x00,0x00,0x00,0x05,0x00,0x0b,0x00,0x00,0x0f,0x3e,0x00,0x00,0x00,0xf4,0x00,0x6f,0x00,0x0b,0x00,0x0b, + 0x00,0x00,0x00,0x04,0x00,0x0b,0x00,0x00,0x0f,0x3f,0x00,0x00,0x00,0x0c,0x00,0x46,0x00,0x0a,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x08,0x00,0x00,0x0f,0x40,0x00,0x00, + 0x00,0xe0,0x00,0x12,0x00,0x0f,0x00,0x10,0x00,0xff,0xff,0x02,0x00,0x0e,0x00,0x00,0x0f,0x41,0x00,0x00,0x00,0x2d,0x00,0x65,0x00,0x0e,0x00,0x0d,0x00,0xfe,0xff,0x02, + 0x00,0x0a,0x00,0x00,0x0f,0x42,0x00,0x00,0x00,0xa0,0x00,0x63,0x00,0x0d,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0b,0x00,0x00,0x0f,0x43,0x00,0x00,0x00,0xab,0x00,0x25, + 0x00,0x0d,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0b,0x00,0x00,0x0f,0x44,0x00,0x00,0x00,0x3c,0x00,0x65,0x00,0x0e,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0c,0x00,0x00, + 0x0f,0x45,0x00,0x00,0x00,0xbb,0x00,0x62,0x00,0x0c,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0a,0x00,0x00,0x0f,0x46,0x00,0x00,0x00,0xc8,0x00,0x62,0x00,0x0c,0x00,0x0d, + 0x00,0xff,0xff,0x02,0x00,0x0a,0x00,0x00,0x0f,0x47,0x00,0x00,0x00,0xb9,0x00,0x25,0x00,0x0d,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0c,0x00,0x00,0x0f,0x48,0x00,0x00, + 0x00,0xd9,0x00,0x53,0x00,0x0f,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0d,0x00,0x00,0x0f,0x49,0x00,0x00,0x00,0x60,0x00,0x72,0x00,0x08,0x00,0x0d,0x00,0xff,0xff,0x02, + 0x00,0x06,0x00,0x00,0x0f,0x4a,0x00,0x00,0x00,0xbc,0x00,0x12,0x00,0x09,0x00,0x11,0x00,0xfe,0xff,0x02,0x00,0x06,0x00,0x00,0x0f,0x4b,0x00,0x00,0x00,0xe9,0x00,0x53, + 0x00,0x0f,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0c,0x00,0x00,0x0f,0x4c,0x00,0x00,0x00,0xd5,0x00,0x62,0x00,0x0c,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0a,0x00,0x00, + 0x0f,0x4d,0x00,0x00,0x00,0xb5,0x00,0x54,0x00,0x11,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0f,0x00,0x00,0x0f,0x4e,0x00,0x00,0x00,0x0f,0x00,0x65,0x00,0x0e,0x00,0x0d, + 0x00,0xff,0xff,0x02,0x00,0x0c,0x00,0x00,0x0f,0x4f,0x00,0x00,0x00,0x9c,0x00,0x25,0x00,0x0e,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0c,0x00,0x00,0x0f,0x50,0x00,0x00, + 0x00,0xe2,0x00,0x61,0x00,0x0c,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0a,0x00,0x00,0x0f,0x51,0x00,0x00,0x00,0xd9,0x00,0x00,0x00,0x0e,0x00,0x11,0x00,0xff,0xff,0x01, + 0x00,0x0c,0x00,0x00,0x0f,0x52,0x00,0x00,0x00,0x00,0x00,0x65,0x00,0x0e,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0b,0x00,0x00,0x0f,0x53,0x00,0x00,0x00,0x86,0x00,0x35, + 0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0a,0x00,0x00,0x0f,0x54,0x00,0x00,0x00,0xef,0x00,0x61,0x00,0x0c,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0a,0x00,0x00, + 0x0f,0x55,0x00,0x00,0x00,0x68,0x00,0x45,0x00,0x0e,0x00,0x0e,0x00,0xff,0xff,0x02,0x00,0x0c,0x00,0x00,0x0f,0x56,0x00,0x00,0x00,0x4b,0x00,0x64,0x00,0x0e,0x00,0x0d, + 0x00,0xfe,0xff,0x02,0x00,0x0a,0x00,0x00,0x0f,0x57,0x00,0x00,0x00,0xa1,0x00,0x54,0x00,0x13,0x00,0x0d,0x00,0xfe,0xff,0x02,0x00,0x0f,0x00,0x00,0x0f,0x58,0x00,0x00, + 0x00,0x84,0x00,0x63,0x00,0x0d,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0a,0x00,0x00,0x0f,0x59,0x00,0x00,0x00,0x68,0x00,0x64,0x00,0x0d,0x00,0x0d,0x00,0xfe,0xff,0x02, + 0x00,0x0a,0x00,0x00,0x0f,0x5a,0x00,0x00,0x00,0x00,0x00,0x73,0x00,0x0c,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0a,0x00,0x00,0x0f,0x5b,0x00,0x00,0x00,0x2d,0x00,0x25, + 0x00,0x07,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x06,0x00,0x00,0x0f,0x5c,0x00,0x00,0x00,0x58,0x00,0x45,0x00,0x07,0x00,0x0f,0x00,0xff,0xff,0x02,0x00,0x05,0x00,0x00, + 0x0f,0x5d,0x00,0x00,0x00,0x25,0x00,0x25,0x00,0x07,0x00,0x10,0x00,0xff,0xff,0x01,0x00,0x06,0x00,0x00,0x0f,0x5e,0x00,0x00,0x00,0x65,0x00,0x97,0x00,0x0b,0x00,0x07, + 0x00,0x00,0x00,0x02,0x00,0x0b,0x00,0x00,0x0f,0x5f,0x00,0x00,0x00,0x3c,0x00,0xa1,0x00,0x09,0x00,0x04,0x00,0xff,0xff,0x0f,0x00,0x07,0x00,0x00,0x0f,0x60,0x00,0x00, + 0x00,0x11,0x00,0xa1,0x00,0x07,0x00,0x05,0x00,0xff,0xff,0x01,0x00,0x07,0x00,0x00,0x0f,0x61,0x00,0x00,0x00,0x00,0x00,0x81,0x00,0x0b,0x00,0x0b,0x00,0xff,0xff,0x05, + 0x00,0x09,0x00,0x00,0x0f,0x62,0x00,0x00,0x00,0x56,0x00,0x35,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0x63,0x00,0x00,0x00,0x3a,0x00,0x81, + 0x00,0x0a,0x00,0x0b,0x00,0xff,0xff,0x05,0x00,0x08,0x00,0x00,0x0f,0x64,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x0c,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00, + 0x0f,0x65,0x00,0x00,0x00,0x2f,0x00,0x81,0x00,0x0a,0x00,0x0b,0x00,0xff,0xff,0x05,0x00,0x09,0x00,0x00,0x0f,0x66,0x00,0x00,0x00,0x4f,0x00,0x55,0x00,0x09,0x00,0x0e, + 0x00,0xff,0xff,0x01,0x00,0x06,0x00,0x00,0x0f,0x67,0x00,0x00,0x00,0xef,0x00,0x43,0x00,0x0c,0x00,0x0e,0x00,0xff,0xff,0x05,0x00,0x09,0x00,0x00,0x0f,0x68,0x00,0x00, + 0x00,0xe2,0x00,0x44,0x00,0x0c,0x00,0x0e,0x00,0xff,0xff,0x01,0x00,0x0a,0x00,0x00,0x0f,0x69,0x00,0x00,0x00,0x83,0x00,0x54,0x00,0x07,0x00,0x0e,0x00,0xff,0xff,0x01, + 0x00,0x05,0x00,0x00,0x0f,0x6a,0x00,0x00,0x00,0xad,0x00,0x00,0x00,0x07,0x00,0x12,0x00,0xfe,0xff,0x01,0x00,0x05,0x00,0x00,0x0f,0x6b,0x00,0x00,0x00,0xd5,0x00,0x44, + 0x00,0x0c,0x00,0x0e,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0x6c,0x00,0x00,0x00,0x8b,0x00,0x54,0x00,0x07,0x00,0x0e,0x00,0xff,0xff,0x01,0x00,0x05,0x00,0x00, + 0x0f,0x6d,0x00,0x00,0x00,0x85,0x00,0x7e,0x00,0x10,0x00,0x0a,0x00,0xff,0xff,0x05,0x00,0x0e,0x00,0x00,0x0f,0x6e,0x00,0x00,0x00,0xa6,0x00,0x7d,0x00,0x0c,0x00,0x0a, + 0x00,0xff,0xff,0x05,0x00,0x0a,0x00,0x00,0x0f,0x6f,0x00,0x00,0x00,0xdc,0x00,0x70,0x00,0x0b,0x00,0x0b,0x00,0xff,0xff,0x05,0x00,0x09,0x00,0x00,0x0f,0x70,0x00,0x00, + 0x00,0x00,0x00,0x56,0x00,0x0b,0x00,0x0e,0x00,0xff,0xff,0x05,0x00,0x09,0x00,0x00,0x0f,0x71,0x00,0x00,0x00,0xae,0x00,0x45,0x00,0x0c,0x00,0x0e,0x00,0xff,0xff,0x05, + 0x00,0x09,0x00,0x00,0x0f,0x72,0x00,0x00,0x00,0xcc,0x00,0x7c,0x00,0x0a,0x00,0x0a,0x00,0xff,0xff,0x05,0x00,0x07,0x00,0x00,0x0f,0x73,0x00,0x00,0x00,0x4f,0x00,0x80, + 0x00,0x09,0x00,0x0b,0x00,0xff,0xff,0x05,0x00,0x08,0x00,0x00,0x0f,0x74,0x00,0x00,0x00,0x3b,0x00,0x56,0x00,0x09,0x00,0x0e,0x00,0xff,0xff,0x02,0x00,0x06,0x00,0x00, + 0x0f,0x75,0x00,0x00,0x00,0xb7,0x00,0x70,0x00,0x0c,0x00,0x0b,0x00,0xff,0xff,0x05,0x00,0x0a,0x00,0x00,0x0f,0x76,0x00,0x00,0x00,0xb3,0x00,0x7d,0x00,0x0c,0x00,0x0a, + 0x00,0xfe,0xff,0x05,0x00,0x08,0x00,0x00,0x0f,0x77,0x00,0x00,0x00,0x96,0x00,0x7e,0x00,0x0f,0x00,0x0a,0x00,0xfe,0xff,0x05,0x00,0x0c,0x00,0x00,0x0f,0x78,0x00,0x00, + 0x00,0xc0,0x00,0x7c,0x00,0x0b,0x00,0x0a,0x00,0xff,0xff,0x05,0x00,0x08,0x00,0x00,0x0f,0x79,0x00,0x00,0x00,0xc8,0x00,0x45,0x00,0x0c,0x00,0x0e,0x00,0xfe,0xff,0x05, + 0x00,0x08,0x00,0x00,0x0f,0x7a,0x00,0x00,0x00,0xe2,0x00,0x7c,0x00,0x0a,0x00,0x0a,0x00,0xff,0xff,0x05,0x00,0x08,0x00,0x00,0x0f,0x7b,0x00,0x00,0x00,0xa8,0x00,0x13, + 0x00,0x09,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x09,0x00,0x00,0x0f,0x7c,0x00,0x00,0x00,0xb5,0x00,0x00,0x00,0x05,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x00, + 0x0f,0x7d,0x00,0x00,0x00,0x94,0x00,0x13,0x00,0x09,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x09,0x00,0x00,0x0f,0x7e,0x00,0x00,0x00,0xbf,0x00,0x92,0x00,0x0b,0x00,0x06, + 0x00,0x00,0x00,0x06,0x00,0x0b,0x00,0x00,0x0f,0xa0,0x00,0x00,0x00,0xfc,0x00,0x47,0x00,0x03,0x00,0x03,0x00,0xff,0xff,0xff,0xff,0x05,0x00,0x00,0x0f,0xa1,0x00,0x00, + 0x00,0x93,0x00,0x54,0x00,0x06,0x00,0x0e,0x00,0x00,0x00,0x01,0x00,0x06,0x00,0x00,0x0f,0xa2,0x00,0x00,0x00,0x7a,0x00,0x35,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x03, + 0x00,0x09,0x00,0x00,0x0f,0xa3,0x00,0x00,0x00,0x0c,0x00,0x56,0x00,0x0b,0x00,0x0e,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xa4,0x00,0x00,0x00,0x0c,0x00,0x81, + 0x00,0x0b,0x00,0x0b,0x00,0xff,0xff,0x04,0x00,0x09,0x00,0x00,0x0f,0xa5,0x00,0x00,0x00,0x34,0x00,0x73,0x00,0x0b,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x09,0x00,0x00, + 0x0f,0xa6,0x00,0x00,0x00,0x35,0x00,0x25,0x00,0x05,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x05,0x00,0x00,0x0f,0xa7,0x00,0x00,0x00,0x1b,0x00,0x25,0x00,0x09,0x00,0x10, + 0x00,0xff,0xff,0x01,0x00,0x07,0x00,0x00,0x0f,0xa8,0x00,0x00,0x00,0x00,0x00,0xa1,0x00,0x08,0x00,0x05,0x00,0xff,0xff,0x01,0x00,0x07,0x00,0x00,0x0f,0xa9,0x00,0x00, + 0x00,0x5a,0x00,0x64,0x00,0x0d,0x00,0x0d,0x00,0x00,0x00,0x02,0x00,0x0e,0x00,0x00,0x0f,0xaa,0x00,0x00,0x00,0x45,0x00,0x81,0x00,0x09,0x00,0x0b,0x00,0xff,0xff,0x01, + 0x00,0x07,0x00,0x00,0x0f,0xab,0x00,0x00,0x00,0xd7,0x00,0x7c,0x00,0x0a,0x00,0x0a,0x00,0xff,0xff,0x05,0x00,0x08,0x00,0x00,0x0f,0xac,0x00,0x00,0x00,0x71,0x00,0x96, + 0x00,0x0b,0x00,0x07,0x00,0x00,0x00,0x06,0x00,0x0b,0x00,0x00,0x0f,0xad,0x00,0x00,0x00,0x09,0x00,0xa1,0x00,0x07,0x00,0x05,0x00,0xff,0xff,0x08,0x00,0x06,0x00,0x00, + 0x0f,0xae,0x00,0x00,0x00,0x92,0x00,0x63,0x00,0x0d,0x00,0x0d,0x00,0x00,0x00,0x02,0x00,0x0e,0x00,0x00,0x0f,0xaf,0x00,0x00,0x00,0xf8,0x00,0x90,0x00,0x07,0x00,0x05, + 0x00,0x00,0x00,0x01,0x00,0x07,0x00,0x00,0x0f,0xb0,0x00,0x00,0x00,0x50,0x00,0x98,0x00,0x07,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x07,0x00,0x00,0x0f,0xb1,0x00,0x00, + 0x00,0x8d,0x00,0x71,0x00,0x0b,0x00,0x0c,0x00,0x00,0x00,0x03,0x00,0x0b,0x00,0x00,0x0f,0xb2,0x00,0x00,0x00,0x38,0x00,0x8d,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x01, + 0x00,0x06,0x00,0x00,0x0f,0xb3,0x00,0x00,0x00,0x2f,0x00,0x8d,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x01,0x00,0x06,0x00,0x00,0x0f,0xb4,0x00,0x00,0x00,0x21,0x00,0xa1, + 0x00,0x06,0x00,0x05,0x00,0x01,0x00,0x01,0x00,0x07,0x00,0x00,0x0f,0xb5,0x00,0x00,0x00,0xa1,0x00,0x45,0x00,0x0c,0x00,0x0e,0x00,0xff,0xff,0x05,0x00,0x0a,0x00,0x00, + 0x0f,0xb6,0x00,0x00,0x00,0x2d,0x00,0x46,0x00,0x0a,0x00,0x0f,0x00,0xff,0xff,0x02,0x00,0x09,0x00,0x00,0x0f,0xb7,0x00,0x00,0x00,0xd2,0x00,0x91,0x00,0x05,0x00,0x06, + 0x00,0x00,0x00,0x06,0x00,0x05,0x00,0x00,0x0f,0xb8,0x00,0x00,0x00,0xcb,0x00,0x91,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x0c,0x00,0x07,0x00,0x00,0x0f,0xb9,0x00,0x00, + 0x00,0x92,0x00,0x89,0x00,0x07,0x00,0x0a,0x00,0xff,0xff,0x01,0x00,0x06,0x00,0x00,0x0f,0xba,0x00,0x00,0x00,0x59,0x00,0x80,0x00,0x09,0x00,0x0b,0x00,0xff,0xff,0x01, + 0x00,0x07,0x00,0x00,0x0f,0xbb,0x00,0x00,0x00,0x00,0x00,0x8d,0x00,0x09,0x00,0x0a,0x00,0x00,0x00,0x05,0x00,0x08,0x00,0x00,0x0f,0xbc,0x00,0x00,0x00,0x3b,0x00,0x25, + 0x00,0x10,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0e,0x00,0x00,0x0f,0xbd,0x00,0x00,0x00,0x5d,0x00,0x25,0x00,0x10,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0e,0x00,0x00, + 0x0f,0xbe,0x00,0x00,0x00,0x4c,0x00,0x25,0x00,0x10,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0e,0x00,0x00,0x0f,0xbf,0x00,0x00,0x00,0x4e,0x00,0x45,0x00,0x09,0x00,0x0f, + 0x00,0xff,0xff,0x01,0x00,0x08,0x00,0x00,0x0f,0xc0,0x00,0x00,0x00,0x1e,0x00,0x13,0x00,0x0e,0x00,0x11,0x00,0xfe,0xff,0xfe,0xff,0x0a,0x00,0x00,0x0f,0xc1,0x00,0x00, + 0x00,0xbb,0x00,0x00,0x00,0x0e,0x00,0x11,0x00,0xfe,0xff,0xfe,0xff,0x0a,0x00,0x00,0x0f,0xc2,0x00,0x00,0x00,0xca,0x00,0x00,0x00,0x0e,0x00,0x11,0x00,0xfe,0xff,0xfe, + 0xff,0x0a,0x00,0x00,0x0f,0xc3,0x00,0x00,0x00,0x00,0x00,0x13,0x00,0x0e,0x00,0x11,0x00,0xfe,0xff,0xfe,0xff,0x0a,0x00,0x00,0x0f,0xc4,0x00,0x00,0x00,0xe8,0x00,0x00, + 0x00,0x0e,0x00,0x11,0x00,0xfe,0xff,0xfe,0xff,0x0a,0x00,0x00,0x0f,0xc5,0x00,0x00,0x00,0xf0,0x00,0x12,0x00,0x0e,0x00,0x10,0x00,0xfe,0xff,0xff,0xff,0x0a,0x00,0x00, + 0x0f,0xc6,0x00,0x00,0x00,0xc7,0x00,0x54,0x00,0x11,0x00,0x0d,0x00,0xfe,0xff,0x02,0x00,0x0e,0x00,0x00,0x0f,0xc7,0x00,0x00,0x00,0x3b,0x00,0x13,0x00,0x0d,0x00,0x11, + 0x00,0xff,0xff,0x01,0x00,0x0b,0x00,0x00,0x0f,0xc8,0x00,0x00,0x00,0x70,0x00,0x13,0x00,0x0c,0x00,0x11,0x00,0xff,0xff,0xfe,0xff,0x0a,0x00,0x00,0x0f,0xc9,0x00,0x00, + 0x00,0x49,0x00,0x13,0x00,0x0c,0x00,0x11,0x00,0xff,0xff,0xfe,0xff,0x0a,0x00,0x00,0x0f,0xca,0x00,0x00,0x00,0x56,0x00,0x13,0x00,0x0c,0x00,0x11,0x00,0xff,0xff,0xfe, + 0xff,0x0a,0x00,0x00,0x0f,0xcb,0x00,0x00,0x00,0x63,0x00,0x13,0x00,0x0c,0x00,0x11,0x00,0xff,0xff,0xfe,0xff,0x0a,0x00,0x00,0x0f,0xcc,0x00,0x00,0x00,0xf7,0x00,0x00, + 0x00,0x08,0x00,0x11,0x00,0xff,0xff,0xfe,0xff,0x06,0x00,0x00,0x0f,0xcd,0x00,0x00,0x00,0xc6,0x00,0x12,0x00,0x08,0x00,0x11,0x00,0xff,0xff,0xfe,0xff,0x06,0x00,0x00, + 0x0f,0xce,0x00,0x00,0x00,0xb2,0x00,0x13,0x00,0x09,0x00,0x11,0x00,0xff,0xff,0xfe,0xff,0x06,0x00,0x00,0x0f,0xcf,0x00,0x00,0x00,0x9e,0x00,0x13,0x00,0x09,0x00,0x11, + 0x00,0xff,0xff,0xfe,0xff,0x06,0x00,0x00,0x0f,0xd0,0x00,0x00,0x00,0x1e,0x00,0x65,0x00,0x0e,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0c,0x00,0x00,0x0f,0xd1,0x00,0x00, + 0x00,0x0f,0x00,0x13,0x00,0x0e,0x00,0x11,0x00,0xff,0xff,0xfe,0xff,0x0c,0x00,0x00,0x0f,0xd2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x12,0x00,0xff,0xff,0xfe, + 0xff,0x0c,0x00,0x00,0x0f,0xd3,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x0e,0x00,0x12,0x00,0xff,0xff,0xfe,0xff,0x0c,0x00,0x00,0x0f,0xd4,0x00,0x00,0x00,0x78,0x00,0x00, + 0x00,0x0e,0x00,0x12,0x00,0xff,0xff,0xfe,0xff,0x0c,0x00,0x00,0x0f,0xd5,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x0e,0x00,0x12,0x00,0xff,0xff,0xfe,0xff,0x0c,0x00,0x00, + 0x0f,0xd6,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,0x0e,0x00,0x12,0x00,0xff,0xff,0xfe,0xff,0x0c,0x00,0x00,0x0f,0xd7,0x00,0x00,0x00,0x69,0x00,0x72,0x00,0x0b,0x00,0x0c, + 0x00,0x00,0x00,0x03,0x00,0x0b,0x00,0x00,0x0f,0xd8,0x00,0x00,0x00,0x7e,0x00,0x25,0x00,0x0e,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0c,0x00,0x00,0x0f,0xd9,0x00,0x00, + 0x00,0x2d,0x00,0x00,0x00,0x0e,0x00,0x12,0x00,0xff,0xff,0xfe,0xff,0x0c,0x00,0x00,0x0f,0xda,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x0e,0x00,0x12,0x00,0xff,0xff,0xfe, + 0xff,0x0c,0x00,0x00,0x0f,0xdb,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,0x0e,0x00,0x12,0x00,0xff,0xff,0xfe,0xff,0x0c,0x00,0x00,0x0f,0xdc,0x00,0x00,0x00,0x0f,0x00,0x00, + 0x00,0x0e,0x00,0x12,0x00,0xff,0xff,0xfe,0xff,0x0c,0x00,0x00,0x0f,0xdd,0x00,0x00,0x00,0x2d,0x00,0x13,0x00,0x0d,0x00,0x11,0x00,0xfe,0xff,0xfe,0xff,0x0a,0x00,0x00, + 0x0f,0xde,0x00,0x00,0x00,0xae,0x00,0x62,0x00,0x0c,0x00,0x0d,0x00,0xff,0xff,0x02,0x00,0x0a,0x00,0x00,0x0f,0xdf,0x00,0x00,0x00,0xee,0x00,0x23,0x00,0x0c,0x00,0x0f, + 0x00,0xff,0xff,0x01,0x00,0x0a,0x00,0x00,0x0f,0xe0,0x00,0x00,0x00,0x6e,0x00,0x35,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xe1,0x00,0x00, + 0x00,0x4a,0x00,0x35,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xe2,0x00,0x00,0x00,0x3e,0x00,0x35,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01, + 0x00,0x09,0x00,0x00,0x0f,0xe3,0x00,0x00,0x00,0x32,0x00,0x36,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xe4,0x00,0x00,0x00,0x26,0x00,0x36, + 0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xe5,0x00,0x00,0x00,0x7d,0x00,0x13,0x00,0x0b,0x00,0x11,0x00,0xff,0xff,0xff,0xff,0x09,0x00,0x00, + 0x0f,0xe6,0x00,0x00,0x00,0x99,0x00,0x71,0x00,0x0f,0x00,0x0b,0x00,0xff,0xff,0x05,0x00,0x0d,0x00,0x00,0x0f,0xe7,0x00,0x00,0x00,0x4b,0x00,0x72,0x00,0x0a,0x00,0x0d, + 0x00,0xff,0xff,0x05,0x00,0x08,0x00,0x00,0x0f,0xe8,0x00,0x00,0x00,0x38,0x00,0x46,0x00,0x0a,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xe9,0x00,0x00, + 0x00,0x43,0x00,0x45,0x00,0x0a,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xea,0x00,0x00,0x00,0x17,0x00,0x46,0x00,0x0a,0x00,0x0f,0x00,0xff,0xff,0x01, + 0x00,0x09,0x00,0x00,0x0f,0xeb,0x00,0x00,0x00,0x22,0x00,0x46,0x00,0x0a,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xec,0x00,0x00,0x00,0x7b,0x00,0x54, + 0x00,0x07,0x00,0x0e,0x00,0xff,0xff,0x01,0x00,0x05,0x00,0x00,0x0f,0xed,0x00,0x00,0x00,0x73,0x00,0x54,0x00,0x07,0x00,0x0e,0x00,0xff,0xff,0x01,0x00,0x05,0x00,0x00, + 0x0f,0xee,0x00,0x00,0x00,0x59,0x00,0x55,0x00,0x08,0x00,0x0e,0x00,0xfe,0xff,0x01,0x00,0x05,0x00,0x00,0x0f,0xef,0x00,0x00,0x00,0x6b,0x00,0x54,0x00,0x07,0x00,0x0e, + 0x00,0xff,0xff,0x01,0x00,0x05,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0xce,0x00,0x34,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xf1,0x00,0x00, + 0x00,0xbb,0x00,0x45,0x00,0x0c,0x00,0x0e,0x00,0xff,0xff,0x01,0x00,0x0a,0x00,0x00,0x0f,0xf2,0x00,0x00,0x00,0xc2,0x00,0x35,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01, + 0x00,0x09,0x00,0x00,0x0f,0xf3,0x00,0x00,0x00,0xb6,0x00,0x35,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xf4,0x00,0x00,0x00,0xaa,0x00,0x35, + 0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xf5,0x00,0x00,0x00,0x92,0x00,0x35,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00, + 0x0f,0xf6,0x00,0x00,0x00,0x9e,0x00,0x35,0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xf7,0x00,0x00,0x00,0xd0,0x00,0x70,0x00,0x0b,0x00,0x0b, + 0x00,0x00,0x00,0x04,0x00,0x0b,0x00,0x00,0x0f,0xf8,0x00,0x00,0x00,0x75,0x00,0x72,0x00,0x0b,0x00,0x0c,0x00,0xff,0xff,0x04,0x00,0x09,0x00,0x00,0x0f,0xf9,0x00,0x00, + 0x00,0xe1,0x00,0x23,0x00,0x0c,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0a,0x00,0x00,0x0f,0xfa,0x00,0x00,0x00,0x0d,0x00,0x36,0x00,0x0c,0x00,0x0f,0x00,0xff,0xff,0x01, + 0x00,0x0a,0x00,0x00,0x0f,0xfb,0x00,0x00,0x00,0xc7,0x00,0x24,0x00,0x0c,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0a,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0xd4,0x00,0x24, + 0x00,0x0c,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x0a,0x00,0x00,0x0f,0xfd,0x00,0x00,0x00,0x94,0x00,0x00,0x00,0x0c,0x00,0x12,0x00,0xfe,0xff,0x01,0x00,0x08,0x00,0x00, + 0x0f,0xfe,0x00,0x00,0x00,0xa1,0x00,0x00,0x00,0x0b,0x00,0x12,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0xff,0x00,0x00,0x00,0x87,0x00,0x00,0x00,0x0c,0x00,0x12, + 0x00,0xfe,0xff,0x01,0x00,0x08,0x00,0x00,0x0f,0x26,0x20,0x00,0x00,0xb0,0x00,0x92,0x00,0x0e,0x00,0x06,0x00,0x00,0x00,0x0a,0x00,0x0e,0x00,0x00,0x0f,0x53,0x20,0x00, + 0x00,0xa0,0x00,0x93,0x00,0x0f,0x00,0x06,0x00,0xff,0xff,0x06,0x00,0x0e,0x00,0x00,0x0f,0x70,0x20,0x00,0x00,0x41,0x00,0x8d,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x01, + 0x00,0x06,0x00,0x00,0x0f,0x71,0x20,0x00,0x00,0x9a,0x00,0x89,0x00,0x05,0x00,0x0a,0x00,0xff,0xff,0x01,0x00,0x03,0x00,0x00,0x0f,0x74,0x20,0x00,0x00,0x4a,0x00,0x8d, + 0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x01,0x00,0x06,0x00,0x00,0x0f,0x75,0x20,0x00,0x00,0x53,0x00,0x8c,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x01,0x00,0x06,0x00,0x00, + 0x0f,0x76,0x20,0x00,0x00,0x5c,0x00,0x8c,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x01,0x00,0x06,0x00,0x00,0x0f,0x77,0x20,0x00,0x00,0x65,0x00,0x8c,0x00,0x08,0x00,0x0a, + 0x00,0xff,0xff,0x01,0x00,0x06,0x00,0x00,0x0f,0x78,0x20,0x00,0x00,0x26,0x00,0x8d,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x01,0x00,0x06,0x00,0x00,0x0f,0x79,0x20,0x00, + 0x00,0x77,0x00,0x8b,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x01,0x00,0x06,0x00,0x00,0x0f,0x7a,0x20,0x00,0x00,0xaa,0x00,0x88,0x00,0x09,0x00,0x09,0x00,0xff,0xff,0x02, + 0x00,0x07,0x00,0x00,0x0f,0x7b,0x20,0x00,0x00,0x32,0x00,0xa1,0x00,0x09,0x00,0x04,0x00,0xff,0xff,0x04,0x00,0x07,0x00,0x00,0x0f,0x7c,0x20,0x00,0x00,0xe4,0x00,0x91, + 0x00,0x09,0x00,0x05,0x00,0xff,0xff,0x04,0x00,0x07,0x00,0x00,0x0f,0x7d,0x20,0x00,0x00,0x63,0x00,0x80,0x00,0x06,0x00,0x0b,0x00,0xff,0xff,0x01,0x00,0x04,0x00,0x00, + 0x0f,0x7e,0x20,0x00,0x00,0x71,0x00,0x7f,0x00,0x06,0x00,0x0b,0x00,0xff,0xff,0x01,0x00,0x04,0x00,0x00,0x0f,0x7f,0x20,0x00,0x00,0x18,0x00,0x98,0x00,0x09,0x00,0x08, + 0x00,0xff,0xff,0x03,0x00,0x07,0x00,0x00,0x0f,0x80,0x20,0x00,0x00,0x80,0x00,0x8b,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x06,0x00,0x06,0x00,0x00,0x0f,0x81,0x20,0x00, + 0x00,0xea,0x00,0x87,0x00,0x07,0x00,0x09,0x00,0xff,0xff,0x06,0x00,0x06,0x00,0x00,0x0f,0x82,0x20,0x00,0x00,0xd0,0x00,0x87,0x00,0x08,0x00,0x09,0x00,0xff,0xff,0x06, + 0x00,0x06,0x00,0x00,0x0f,0x83,0x20,0x00,0x00,0x89,0x00,0x89,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x06,0x00,0x06,0x00,0x00,0x0f,0x84,0x20,0x00,0x00,0xd9,0x00,0x87, + 0x00,0x08,0x00,0x09,0x00,0xff,0xff,0x06,0x00,0x06,0x00,0x00,0x0f,0x85,0x20,0x00,0x00,0x6e,0x00,0x8b,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x06,0x00,0x06,0x00,0x00, + 0x0f,0x86,0x20,0x00,0x00,0xf7,0x00,0x7b,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x06,0x00,0x06,0x00,0x00,0x0f,0x87,0x20,0x00,0x00,0xbe,0x00,0x88,0x00,0x08,0x00,0x09, + 0x00,0xff,0xff,0x06,0x00,0x06,0x00,0x00,0x0f,0x88,0x20,0x00,0x00,0x14,0x00,0x8d,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x06,0x00,0x06,0x00,0x00,0x0f,0x89,0x20,0x00, + 0x00,0x1d,0x00,0x8d,0x00,0x08,0x00,0x0a,0x00,0xff,0xff,0x06,0x00,0x06,0x00,0x00,0x0f,0x8a,0x20,0x00,0x00,0x22,0x00,0x98,0x00,0x09,0x00,0x08,0x00,0xff,0xff,0x07, + 0x00,0x07,0x00,0x00,0x0f,0x8b,0x20,0x00,0x00,0x28,0x00,0xa1,0x00,0x09,0x00,0x04,0x00,0xff,0xff,0x09,0x00,0x07,0x00,0x00,0x0f,0x8c,0x20,0x00,0x00,0xee,0x00,0x91, + 0x00,0x09,0x00,0x05,0x00,0xff,0xff,0x09,0x00,0x07,0x00,0x00,0x0f,0x8d,0x20,0x00,0x00,0x78,0x00,0x7f,0x00,0x06,0x00,0x0b,0x00,0xff,0xff,0x06,0x00,0x04,0x00,0x00, + 0x0f,0x8e,0x20,0x00,0x00,0x6a,0x00,0x7f,0x00,0x06,0x00,0x0b,0x00,0xff,0xff,0x06,0x00,0x04,0x00,0x00,0x0f,0x90,0x20,0x00,0x00,0x3e,0x00,0x98,0x00,0x08,0x00,0x08, + 0x00,0xff,0xff,0x08,0x00,0x06,0x00,0x00,0x0f,0x91,0x20,0x00,0x00,0x2c,0x00,0x98,0x00,0x08,0x00,0x08,0x00,0xff,0xff,0x08,0x00,0x06,0x00,0x00,0x0f,0x92,0x20,0x00, + 0x00,0x35,0x00,0x98,0x00,0x08,0x00,0x08,0x00,0xff,0xff,0x08,0x00,0x06,0x00,0x00,0x0f,0x93,0x20,0x00,0x00,0x87,0x00,0x96,0x00,0x08,0x00,0x07,0x00,0xff,0xff,0x08, + 0x00,0x06,0x00,0x00,0x0f,0x94,0x20,0x00,0x00,0x47,0x00,0x98,0x00,0x08,0x00,0x08,0x00,0xff,0xff,0x08,0x00,0x06,0x00,0x00,0x0f,0x95,0x20,0x00,0x00,0xb4,0x00,0x88, + 0x00,0x09,0x00,0x09,0x00,0xff,0xff,0x06,0x00,0x07,0x00,0x00,0x0f,0x96,0x20,0x00,0x00,0xa0,0x00,0x89,0x00,0x09,0x00,0x09,0x00,0xff,0xff,0x06,0x00,0x07,0x00,0x00, + 0x0f,0x97,0x20,0x00,0x00,0xf2,0x00,0x86,0x00,0x06,0x00,0x09,0x00,0xff,0xff,0x06,0x00,0x04,0x00,0x00,0x0f,0x98,0x20,0x00,0x00,0x58,0x00,0x97,0x00,0x0c,0x00,0x07, + 0x00,0xff,0xff,0x08,0x00,0x0a,0x00,0x00,0x0f,0x99,0x20,0x00,0x00,0x7d,0x00,0x96,0x00,0x09,0x00,0x07,0x00,0xff,0xff,0x08,0x00,0x07,0x00,0x00,0x0f,0x9a,0x20,0x00, + 0x00,0xc7,0x00,0x87,0x00,0x08,0x00,0x09,0x00,0xff,0xff,0x08,0x00,0x07,0x00,0x00,0x0f,0x9b,0x20,0x00,0x00,0x90,0x00,0x94,0x00,0x07,0x00,0x07,0x00,0xff,0xff,0x08, + 0x00,0x05,0x00,0x00,0x0f,0x9c,0x20,0x00,0x00,0xe2,0x00,0x87,0x00,0x07,0x00,0x09,0x00,0xff,0xff,0x07,0x00,0x05,0x00,0x00,0x0f,0xac,0x20,0x00,0x00,0xe6,0x00,0x33, + 0x00,0x0b,0x00,0x0f,0x00,0xff,0xff,0x01,0x00,0x09,0x00,0x00,0x0f,0x02,0x22,0x00,0x00,0x56,0x00,0x72,0x00,0x09,0x00,0x0d,0x00,0xff,0xff,0x03,0x00,0x07,0x00,0x00, + 0x0f,0x10,0x22,0x00,0x00,0x00,0x00,0x25,0x00,0x0d,0x00,0x10,0x00,0xff,0xff,0x02,0x00,0x0b,0x00,0x00,0x0f,0x11,0x22,0x00,0x00,0x0e,0x00,0x25,0x00,0x0c,0x00,0x10, + 0x00,0xff,0xff,0x02,0x00,0x0a,0x00,0x00,0x0f,0x43,0x22,0x00,0x00,0x00,0x00,0x98,0x00,0x0b,0x00,0x08,0x00,0x00,0x00,0x05,0x00,0x0b,0x00,0x00,0x0f,0x64,0x22,0x00, + 0x00,0x18,0x00,0x81,0x00,0x0b,0x00,0x0b,0x00,0x00,0x00,0x04,0x00,0x0b,0x00,0x00,0x0f,0x65,0x22,0x00,0x00,0xc4,0x00,0x70,0x00,0x0b,0x00,0x0b,0x00,0x00,0x00,0x04, + 0x00,0x0b,0x00,0x00,0x0f,0xc5,0x22,0x00,0x00,0xd8,0x00,0x91,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x05,0x00,0x00,0x0f,0xcf,0x23,0x00,0x00,0xa9,0x00,0x71, + 0x00,0x0d,0x00,0x0b,0x00,0x00,0x00,0x04,0x00,0x0d,0x00,0x00,0x0f,0xa0,0x25,0x00,0x00,0x85,0x00,0x45,0x00,0x0d,0x00,0x0e,0x00,0x00,0x00,0x03,0x00,0x0d,0x00,0x00, + 0x0f,0xa1,0x25,0x00,0x00,0x77,0x00,0x45,0x00,0x0d,0x00,0x0e,0x00,0x00,0x00,0x03,0x00,0x0d,0x00,0x00,0x0f,0xae,0x25,0x00,0x00,0x62,0x00,0x55,0x00,0x08,0x00,0x0e, + 0x00,0x00,0x00,0x03,0x00,0x07,0x00,0x00,0x0f,0xb8,0x25,0x00,0x00,0xed,0x00,0x7b,0x00,0x09,0x00,0x0a,0x00,0xff,0xff,0x05,0x00,0x07,0x00,0x00,0x0f,0xcf,0x25,0x00, + 0x00,0x93,0x00,0x45,0x00,0x0d,0x00,0x0e,0x00,0xff,0xff,0x03,0x00,0x0c,0x00,0x00,0x0f,0xfe,0x25,0x00,0x00,0x24,0x00,0x81,0x00,0x0a,0x00,0x0b,0x00,0x00,0x00,0x05, + 0x00,0x0a,0x00,0x00,0x0f,0x39,0x26,0x00,0x00,0x1a,0x00,0x73,0x00,0x0c,0x00,0x0d,0x00,0x00,0x00,0x02,0x00,0x0c,0x00,0x00,0x0f,0x3a,0x26,0x00,0x00,0x27,0x00,0x73, + 0x00,0x0c,0x00,0x0d,0x00,0x00,0x00,0x02,0x00,0x0c,0x00,0x00,0x0f,0x3b,0x26,0x00,0x00,0x0d,0x00,0x73,0x00,0x0c,0x00,0x0d,0x00,0x00,0x00,0x02,0x00,0x0c,0x00,0x00, + 0x0f +}; + + diff --git a/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18_0.png b/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18_0.png new file mode 100644 index 000000000..3a4294eff Binary files /dev/null and b/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18_0.png differ diff --git a/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18_0.png.inl b/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18_0.png.inl new file mode 100644 index 000000000..39749daf6 --- /dev/null +++ b/examples/opengl_various_bindings/fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18_0.png.inl @@ -0,0 +1,326 @@ +{ + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,1,0,0,0,1,0,8,3,0,0,0,107,172,88,84,0,0,1,128,80,76,84,69,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,248,248,248,242,242,242,239,239,239,236,236,236,231,231,231,227,227,227,224,224,224,224,224,224,219,219,219,213,213,213,206, + 206,206,198,198,198,195,195,195,191,191,191,191,191,191,186,186,186,180,180,180,174,174,174,168,168,168,163,163,163,159,159,159,154,154,154,149,149,149,143,143,143,137,137,137,131,131,131,127, + 127,127,127,127,127,124,124,124,118,118,118,110,110,110,103,103,103,99,99,99,95,95,95,94,94,94,88,88,88,83,83,83,79,79,79,76,76,76,70,70,70,66,66,66,63,63,63,62, + 62,62,58,58,58,55,55,55,50,50,50,47,47,47,43,43,43,39,39,39,35,35,35,31,31,31,30,30,30,29,29,29,26,26,26,24,24,24,22,22,22,19,19,19,18,18,18,15, + 15,15,14,14,14,11,11,11,10,10,10,8,8,8,7,7,7,4,4,4,4,4,4,3,3,3,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,227,129,195,62,0,0,0, + 51,116,82,78,83,0,0,0,0,0,0,2,3,3,6,7,10,11,14,17,21,24,26,30,31,35,40,45,51,56,62,63,71,82,84,94,96,103,114,120,127,127,138,146,158,160,168,174, + 185,192,192,200,209,223,231,243,82,72,190,25,0,0,32,0,73,68,65,84,120,218,237,125,235,79,42,75,211,175,95,38,33,6,35,6,69,5,22,75,37,192,66,9,140,244,7,238, + 68,16,130,40,40,26,97,137,119,162,34,78,2,33,132,132,132,47,252,235,167,170,47,51,61,128,46,247,126,246,243,158,119,159,195,100,239,229,244,204,0,93,191,174,174,174,170,174, + 170,89,82,224,176,218,87,20,249,112,56,21,199,150,212,182,218,87,77,45,243,211,83,183,87,228,214,212,55,89,54,151,149,173,207,158,93,14,121,87,66,123,70,123,103,194,26,46, + 143,103,219,184,106,247,88,241,123,189,43,223,248,117,188,105,255,140,46,78,198,18,158,14,181,129,76,147,227,189,229,108,191,26,29,133,251,253,85,185,101,122,122,234,246,234,64,235, + 175,127,242,77,150,241,219,200,47,125,177,233,217,229,81,241,106,80,184,214,17,216,249,77,234,216,112,61,53,155,47,58,2,118,237,118,104,85,28,237,43,209,135,47,126,93,217,60, + 24,106,90,212,111,157,215,27,65,6,3,160,144,27,45,27,20,29,166,98,253,100,204,184,18,42,166,59,27,18,189,230,167,205,183,87,251,217,100,242,99,125,254,55,249,207,73,246, + 34,25,157,255,236,90,151,228,94,73,62,162,55,147,23,126,60,217,171,167,73,37,32,62,19,201,145,170,95,241,52,137,102,255,227,175,59,223,74,177,84,34,121,49,180,206,233,141, + 32,99,137,53,74,141,93,131,162,64,245,120,92,46,29,136,166,251,254,184,183,97,26,113,211,211,230,219,129,106,117,124,121,50,182,204,253,166,80,241,165,150,189,242,206,127,22,190, + 168,237,105,182,29,188,229,171,157,253,18,159,146,0,80,51,4,174,27,0,124,241,235,206,86,130,212,15,7,37,146,227,8,152,123,195,201,88,154,230,148,192,4,142,176,101,31,254, + 245,206,242,17,189,235,61,216,229,119,89,51,108,151,155,1,139,119,254,103,161,25,50,55,229,187,182,80,40,20,84,246,66,33,155,104,252,226,13,4,32,52,81,119,232,99,123,111, + 215,61,155,204,1,110,117,34,141,78,32,160,78,246,45,124,190,101,72,46,2,179,133,144,154,143,223,13,171,19,65,63,118,114,18,162,0,152,56,37,80,33,112,92,121,53,250,175, + 242,245,221,175,155,51,60,248,85,211,214,43,22,139,167,193,122,177,8,244,153,26,8,64,169,64,50,191,119,232,124,40,22,47,228,41,128,100,74,243,83,106,186,30,9,193,73,116, + 152,34,169,195,153,187,222,43,236,107,49,4,0,152,57,101,181,95,39,228,110,176,50,214,50,119,40,36,190,188,251,117,115,154,7,191,108,46,143,160,71,119,63,58,185,6,76,76, + 83,3,1,136,53,47,9,121,116,41,202,70,167,132,189,54,0,112,61,27,3,108,110,238,93,19,130,60,30,62,38,164,187,54,125,119,101,112,7,248,0,190,75,211,156,2,223,77, + 90,78,197,162,102,225,95,229,235,187,95,55,167,62,251,117,19,166,100,2,78,186,89,117,121,186,1,0,28,135,199,9,66,103,47,112,153,9,0,228,186,140,46,70,228,38,142,113, + 211,67,63,62,239,97,103,139,177,233,210,52,167,112,34,20,70,196,215,119,191,110,78,125,246,235,38,44,17,85,146,30,53,46,153,240,144,27,84,8,170,89,146,85,103,1,88,30, + 37,128,168,103,151,190,148,26,77,4,0,167,77,168,64,230,61,172,3,48,205,41,102,34,190,190,251,117,115,234,179,95,55,21,101,235,21,216,254,152,79,81,185,241,21,0,63,238, + 74,31,132,136,245,194,212,252,113,199,120,235,48,77,18,108,212,77,15,235,0,76,115,138,153,136,175,239,126,221,156,250,236,215,77,182,196,231,142,195,198,122,47,26,240,196,201,62, + 144,65,85,132,41,0,246,203,119,145,60,137,139,149,94,110,90,135,73,124,20,212,11,177,138,154,30,54,1,32,115,202,44,17,159,223,253,51,0,210,103,191,110,194,177,11,34,180, + 177,195,1,144,26,0,64,178,7,28,65,149,68,51,0,171,253,212,104,210,32,228,230,39,215,131,228,230,207,27,232,205,65,164,66,210,76,6,154,239,234,0,200,156,18,229,68,60, + 184,145,136,183,77,51,31,205,222,253,186,57,245,217,175,155,180,131,241,152,174,213,74,13,0,32,23,35,164,68,85,56,51,0,160,46,19,190,156,41,179,205,159,183,233,88,41,71, + 138,92,53,52,223,213,1,144,56,165,138,156,178,249,70,111,172,246,9,174,100,95,223,253,186,57,245,217,175,155,128,158,59,88,46,239,115,250,229,6,202,128,225,107,247,0,233,223, + 55,3,16,42,60,129,58,115,44,120,104,170,169,120,14,251,207,177,179,39,222,50,223,213,1,96,124,107,112,138,101,124,68,82,111,135,195,42,211,25,191,190,251,117,115,234,179,127, + 106,222,135,10,200,62,202,116,3,1,8,110,173,177,89,140,90,209,129,0,192,174,101,84,54,178,87,62,101,166,73,25,201,123,201,149,178,233,187,187,8,64,144,106,130,30,51,167, + 108,191,100,9,73,197,242,168,132,41,127,186,251,117,115,234,179,95,54,189,87,169,82,78,44,232,114,35,120,26,39,137,211,32,61,159,144,147,88,18,236,57,6,192,90,55,149,40, + 132,214,186,25,66,226,48,155,166,154,66,229,189,175,160,172,157,190,187,219,72,19,146,132,175,93,98,156,242,250,62,12,9,35,106,91,237,191,190,13,194,54,193,141,95,222,253,186, + 57,245,217,175,154,203,163,151,71,221,108,148,27,182,158,166,105,28,209,141,206,67,107,8,246,44,55,135,215,14,163,48,159,215,212,201,36,138,4,79,53,133,141,21,240,48,243,210, + 124,119,247,16,78,130,220,26,84,86,183,28,86,201,222,91,221,218,92,49,53,191,190,251,117,115,234,179,159,54,151,183,93,134,145,45,55,108,118,187,93,32,186,225,118,210,15,72, + 14,145,255,240,88,82,254,213,7,181,233,84,217,53,36,187,171,44,194,247,178,190,235,245,122,164,27,235,97,213,45,3,48,237,169,50,183,191,118,129,45,155,156,78,166,123,178,123, + 106,158,55,138,119,198,109,240,132,56,117,123,60,246,57,31,116,122,60,14,211,55,51,155,142,170,136,220,53,100,215,6,30,221,33,52,102,238,159,229,192,71,227,234,170,57,248,169, + 255,228,71,254,232,222,109,0,48,237,169,50,183,191,116,129,57,246,71,96,210,239,187,230,221,147,221,83,115,189,81,76,233,253,184,23,122,156,226,230,167,238,251,230,173,230,152,249, + 96,160,213,100,14,19,253,155,87,6,96,122,151,153,158,195,92,67,174,167,228,45,87,166,54,223,114,116,129,93,30,85,201,113,237,178,148,186,17,8,4,203,165,90,146,203,216,165, + 89,79,213,84,251,43,23,216,214,251,73,44,145,142,159,60,185,102,239,153,220,83,115,189,81,76,233,143,197,132,188,183,169,89,205,105,161,222,160,99,18,99,190,33,233,131,129,42, + 73,156,225,218,40,125,243,202,68,40,186,194,53,4,235,30,211,32,55,223,18,199,244,139,247,203,137,199,176,207,123,240,158,107,122,68,47,235,109,194,7,106,105,214,83,53,221,254, + 220,5,182,245,154,32,23,227,195,231,4,87,189,76,14,42,147,123,106,174,55,138,153,125,167,195,36,27,97,87,239,38,121,221,162,31,240,141,184,230,43,127,16,116,198,234,47,247, + 212,55,11,0,132,131,7,45,233,216,187,3,199,61,75,132,126,254,184,211,109,245,123,221,143,52,103,188,221,70,44,33,58,67,101,64,104,91,157,120,13,177,162,134,182,125,106,136, + 125,31,237,175,225,117,178,83,135,153,205,78,111,162,222,147,133,126,120,47,41,0,180,15,19,238,14,251,102,3,62,155,111,210,14,43,174,231,196,113,242,140,119,108,34,212,23,157, + 176,153,107,22,69,2,64,119,240,40,202,65,137,26,124,160,106,199,41,70,145,124,33,212,136,29,101,50,89,181,202,89,0,53,214,250,158,44,4,205,174,162,12,112,7,26,105,124, + 92,165,187,118,244,118,193,47,106,244,38,58,88,206,253,40,83,240,219,88,31,152,83,236,187,13,100,231,227,56,51,251,195,121,210,205,106,77,246,163,130,88,137,176,185,215,4,0, + 186,131,7,120,234,130,58,24,126,157,161,191,5,127,128,52,134,241,252,184,27,207,170,77,206,214,240,8,187,41,0,152,118,21,149,198,22,91,239,226,130,107,31,210,93,203,248,53, + 70,242,253,213,113,245,12,110,10,147,94,89,223,211,157,76,160,180,92,192,207,124,179,1,242,232,112,18,13,81,9,2,22,255,69,90,27,177,169,31,77,176,159,148,8,211,1,144, + 175,233,83,64,168,246,12,31,24,193,240,49,195,104,235,149,60,191,144,75,111,168,160,3,96,25,167,42,132,112,201,186,52,207,85,196,70,74,72,1,249,174,5,27,79,174,65,10, + 101,144,48,233,197,34,69,251,96,15,53,241,218,55,27,193,114,42,22,47,80,25,138,118,49,201,55,216,15,65,247,143,71,187,38,194,162,79,132,220,122,20,211,181,207,0,0,61, + 25,240,164,0,108,191,144,86,11,110,133,138,89,181,70,29,171,138,235,17,29,35,85,191,14,192,148,171,40,155,64,26,117,0,204,94,167,245,15,96,129,241,21,19,60,87,220,102, + 183,218,45,122,31,186,133,144,231,251,141,9,121,153,220,144,56,90,54,142,118,6,89,155,201,128,205,183,36,227,46,157,176,40,92,224,130,239,207,0,32,7,228,25,0,182,30,105, + 12,98,133,208,48,149,237,100,24,219,4,169,99,36,201,22,162,165,89,87,81,17,56,44,169,233,0,76,121,157,112,254,52,40,3,128,204,103,115,3,214,117,236,25,246,161,220,172, + 51,181,228,155,141,173,215,144,58,230,124,228,27,221,38,227,132,80,207,2,72,178,108,155,121,150,57,97,118,173,129,227,242,103,0,160,131,184,132,7,79,249,52,87,143,78,246,107, + 164,148,79,198,83,76,249,89,25,164,169,99,132,177,211,210,172,171,168,24,170,1,47,142,4,0,83,94,39,91,47,78,98,108,233,69,147,62,31,198,159,164,110,77,236,67,182,120, + 108,144,249,141,198,143,187,66,54,203,186,238,171,245,213,236,91,134,173,93,48,222,53,223,138,137,48,187,190,10,24,215,156,150,241,12,0,251,39,116,180,126,222,112,71,203,110,131, + 188,248,158,26,175,183,119,125,166,252,161,167,200,224,181,165,89,87,81,49,52,46,193,20,225,0,76,121,157,168,195,86,76,8,244,234,220,134,15,58,9,186,102,211,62,132,52,131, + 204,63,55,92,56,175,53,214,117,53,219,0,69,40,31,163,122,221,28,98,231,92,115,182,156,26,243,45,27,215,80,15,104,83,61,128,99,105,25,151,18,207,7,94,239,126,135,203, + 77,221,49,66,127,105,105,214,85,84,12,217,122,48,29,115,236,215,166,220,76,108,142,209,111,70,4,30,178,36,95,138,87,199,134,12,24,119,183,127,126,187,1,223,149,81,57,97, + 7,165,216,73,34,23,99,26,210,247,0,152,144,143,59,182,97,98,92,131,241,97,99,229,104,39,242,220,59,122,70,74,151,87,39,25,38,247,13,199,200,181,143,1,48,237,42,2, + 82,55,223,226,226,215,166,221,76,38,0,20,183,218,63,173,141,2,146,108,178,108,191,96,7,190,215,128,133,52,246,241,192,127,234,96,220,73,63,143,41,253,168,9,206,0,160,107, + 130,250,181,72,62,17,75,176,187,194,193,227,190,207,60,114,94,117,116,242,204,143,98,253,245,94,175,92,220,142,182,148,89,199,8,0,48,227,42,42,170,204,95,197,101,207,180,155, + 41,136,0,8,213,216,209,126,60,17,74,37,237,3,128,213,196,73,249,189,198,250,7,172,56,160,114,37,233,184,91,96,10,216,217,206,112,145,196,216,120,9,194,100,91,192,184,22, + 233,107,81,70,191,112,240,172,117,71,186,101,182,17,22,123,205,142,189,128,223,195,173,143,41,199,200,210,172,171,40,142,211,19,126,13,1,152,117,51,5,79,97,61,74,11,85,222, + 245,152,61,186,251,161,232,125,32,76,83,252,110,67,89,31,189,117,65,233,142,238,242,152,0,182,206,237,54,234,205,247,45,19,97,116,50,63,222,92,1,239,201,215,86,133,213,44, + 28,60,202,154,108,183,57,190,227,16,153,113,21,69,85,182,17,238,85,230,186,153,130,209,201,228,80,55,142,92,170,250,67,234,3,61,2,223,111,40,203,155,107,82,111,214,184,79, + 112,119,143,27,254,6,97,136,128,235,167,215,57,117,237,59,135,229,32,106,147,154,91,30,15,183,203,85,245,95,239,17,50,29,225,201,206,188,120,35,88,6,146,61,29,129,149,240, + 107,179,249,26,90,166,202,55,240,250,146,226,167,145,9,248,47,181,165,66,236,248,97,118,240,88,61,30,15,206,173,117,248,187,46,249,228,108,108,252,86,108,83,14,33,253,194,204, + 19,10,123,98,217,110,153,138,100,218,54,28,73,182,207,227,156,166,60,80,208,210,89,30,212,231,223,59,243,226,141,172,195,92,89,48,204,202,224,152,148,170,177,34,170,129,12,0, + 255,5,13,70,192,127,65,252,31,148,138,236,96,19,219,63,212,250,17,250,21,205,102,19,212,176,245,15,248,11,90,32,247,202,46,7,122,116,45,93,25,112,132,221,240,252,129,69, + 186,48,243,196,90,68,235,255,178,64,15,53,225,2,167,113,34,135,126,23,15,132,178,29,12,180,94,116,235,179,56,39,147,7,138,182,70,225,61,138,193,78,35,113,158,228,129,0, + 51,241,70,57,225,141,130,117,39,53,6,45,177,190,107,112,192,21,174,241,236,95,42,238,31,128,1,222,168,104,247,95,196,178,9,252,154,213,126,37,205,119,100,72,5,122,202,252, + 242,232,107,162,250,76,36,207,132,162,251,62,93,70,83,82,191,48,243,4,116,37,147,56,27,91,252,23,162,119,44,78,36,117,241,152,165,222,10,91,175,68,82,241,132,232,239,84, + 80,137,217,3,181,221,134,22,40,34,117,28,206,149,65,254,41,80,21,251,1,114,188,17,48,247,94,4,104,114,113,203,238,120,124,206,130,13,56,0,94,74,58,251,151,170,208,9, + 24,226,80,1,190,212,209,38,37,181,67,9,88,13,21,5,0,147,109,133,3,176,218,111,81,242,60,183,71,204,176,216,126,121,6,173,185,187,166,95,152,121,2,212,148,86,141,220, + 187,63,226,92,149,224,113,34,176,20,50,14,0,35,224,244,176,155,48,223,21,65,37,102,15,212,246,75,130,156,143,212,238,49,85,81,252,161,200,158,34,200,68,154,69,3,89,188, + 30,2,166,166,168,225,214,90,157,228,187,7,244,235,0,231,105,0,172,195,35,252,53,215,19,176,44,152,210,153,119,191,112,57,234,0,40,2,0,101,117,130,228,45,143,142,110,185, + 81,188,221,47,131,34,46,93,152,126,2,190,70,107,146,171,95,103,39,251,114,36,19,70,75,176,193,3,43,182,230,219,171,51,7,204,76,80,137,236,129,98,173,101,101,163,131,125, + 49,145,105,106,56,218,121,88,113,239,184,197,133,0,84,72,57,72,231,223,214,150,50,3,0,40,129,49,52,38,92,54,252,137,2,137,157,15,109,159,2,160,80,242,118,27,249,200, + 50,115,116,187,199,237,92,252,93,186,96,60,193,218,8,192,13,185,110,199,76,145,76,182,30,24,68,233,67,102,170,146,248,187,99,111,15,5,243,76,80,137,201,3,133,118,4,53, + 3,252,23,96,253,154,200,52,211,76,3,44,52,9,0,220,46,212,163,106,102,0,64,235,137,251,85,215,63,50,133,36,201,245,108,95,2,176,50,72,182,156,35,234,232,118,63,180, + 127,157,145,166,113,193,120,162,175,13,2,76,6,61,84,201,75,177,234,63,160,146,140,57,149,134,185,11,110,155,172,2,11,145,108,31,131,193,64,211,249,36,168,132,121,160,120,11, + 214,1,255,234,52,153,159,55,16,128,62,192,93,22,8,204,2,0,246,47,40,232,235,76,247,28,194,12,163,188,105,6,128,123,0,224,98,28,140,231,210,1,124,45,234,141,222,171, + 92,45,113,212,55,46,232,79,212,51,37,190,41,126,150,206,212,159,146,221,122,233,4,77,74,234,84,26,23,202,99,22,39,178,60,202,145,90,130,20,134,157,243,18,204,207,79,130, + 74,12,155,164,233,129,229,68,163,88,255,5,0,66,253,162,17,90,54,7,128,149,65,150,225,3,236,120,29,234,48,123,219,12,128,226,153,216,169,161,128,251,150,241,182,179,149,226, + 254,202,143,214,187,42,95,16,79,52,91,234,17,29,98,235,175,67,53,146,191,110,144,122,25,167,1,117,42,149,203,99,30,39,2,166,122,124,244,20,131,241,169,224,58,53,39,168, + 196,240,64,177,155,91,175,220,157,240,37,0,167,193,119,9,128,222,120,148,215,169,157,3,192,246,75,5,232,223,96,83,176,128,50,251,211,41,96,183,219,3,149,74,96,116,220,224, + 38,219,186,211,97,190,192,159,240,56,199,169,12,223,12,241,52,51,163,18,249,104,224,90,140,78,165,116,113,108,225,113,34,254,11,48,143,113,41,62,77,224,247,79,69,145,152,61, + 80,188,181,53,209,1,48,200,52,53,96,28,115,163,154,4,64,241,41,120,65,184,20,158,3,0,167,31,165,148,251,33,37,156,135,243,1,192,173,171,132,230,171,93,212,72,229,171, + 11,246,213,113,53,199,229,222,242,40,219,228,139,129,151,58,149,210,67,171,136,19,193,81,253,88,247,213,184,187,102,78,80,137,225,129,194,22,134,81,113,0,76,100,154,26,206,22, + 216,246,192,67,232,17,243,193,4,43,150,82,167,177,12,245,188,205,3,0,233,119,58,157,35,100,252,85,255,224,130,176,80,157,207,0,216,63,169,249,60,205,171,50,41,242,165,123, + 238,133,213,126,169,210,169,178,5,117,183,158,143,64,7,219,151,180,123,32,103,164,56,17,71,59,70,10,218,4,38,65,236,81,157,141,34,49,123,160,60,183,132,220,133,15,134,12, + 0,153,76,115,67,113,14,95,209,228,60,196,115,95,116,18,58,232,189,124,168,155,159,172,2,219,47,249,231,22,28,215,55,63,65,36,95,236,131,98,66,181,178,79,0,112,182,146, + 32,129,60,237,28,201,50,189,107,254,5,182,151,65,63,66,23,141,205,183,68,49,157,135,41,225,122,202,253,150,227,68,40,207,145,248,117,137,80,163,124,58,168,196,228,129,82,60, + 247,25,104,165,18,21,202,91,50,153,230,134,98,221,90,51,89,77,182,237,117,201,28,166,74,112,40,196,0,64,237,138,29,208,91,187,70,78,206,99,5,252,53,251,196,0,192,35, + 1,176,254,65,183,181,28,145,137,234,80,190,184,64,119,179,236,76,57,124,113,226,206,245,219,71,100,25,181,142,206,142,41,108,196,125,216,123,233,68,247,14,38,204,40,159,14,42, + 113,171,253,215,54,247,64,97,107,240,246,214,143,6,54,102,201,156,166,249,115,127,0,104,229,217,28,40,77,248,111,72,137,228,178,236,96,186,214,91,179,249,72,233,215,152,87,16, + 1,64,206,53,50,54,214,167,125,14,127,188,176,186,205,66,16,24,77,155,27,211,97,35,182,237,13,243,243,51,65,37,146,203,99,101,115,115,245,219,230,242,138,97,57,42,171,34, + 68,1,56,32,162,162,169,128,255,162,213,162,178,35,196,122,9,70,176,69,108,138,134,232,242,55,65,14,248,7,67,84,254,241,195,13,67,111,19,160,175,25,161,24,235,96,102,142, + 246,153,145,229,140,128,98,166,218,254,161,16,25,201,15,241,89,166,19,232,107,171,243,221,51,206,128,52,64,58,215,250,84,143,35,56,47,149,106,238,111,153,190,211,125,223,61,240, + 247,152,252,9,69,187,218,32,188,201,167,98,137,164,19,39,84,160,57,91,185,88,54,150,165,42,46,3,0,253,28,214,153,239,165,156,98,157,151,211,37,117,80,246,67,124,150,233, + 100,241,141,180,254,129,109,214,61,3,93,17,217,48,232,7,232,70,67,155,204,41,122,212,124,103,78,63,179,107,99,238,111,153,190,115,5,76,199,210,69,230,129,233,46,241,76,130, + 228,233,130,7,218,29,169,28,118,226,248,115,96,238,164,62,212,118,140,138,177,37,134,78,179,217,20,91,63,250,247,162,91,181,175,13,131,214,153,142,72,29,52,249,33,62,201,116, + 178,140,107,113,16,230,172,143,178,123,70,249,17,110,85,34,123,10,247,3,100,146,137,34,246,214,58,140,131,54,126,238,159,113,109,204,255,173,105,151,79,137,144,71,55,179,67,110, + 212,94,154,160,91,155,90,14,154,61,80,197,78,193,202,118,238,119,186,30,41,197,75,108,237,215,35,150,229,239,221,232,28,147,76,236,148,62,39,119,68,238,160,217,15,49,63,211, + 9,20,155,210,97,131,228,217,226,37,185,103,60,119,121,66,114,20,238,112,62,254,174,142,127,83,221,96,101,112,179,255,116,45,156,76,134,107,227,179,223,50,125,103,56,127,117,71, + 168,30,9,90,223,152,238,102,99,35,154,39,41,16,99,184,25,97,29,198,72,179,211,234,250,172,134,12,64,233,206,1,48,190,23,13,238,83,245,156,43,141,166,142,72,29,164,27, + 252,194,97,172,111,246,203,153,78,128,23,104,189,239,44,142,90,126,6,52,153,216,85,229,10,23,252,245,15,24,168,53,75,248,152,234,110,171,129,232,228,144,187,193,76,231,145,79, + 174,75,231,222,231,243,74,146,176,56,227,128,197,141,214,24,140,32,238,45,211,133,236,39,139,15,201,228,121,0,2,2,176,25,158,168,2,0,127,40,228,251,197,93,41,184,1,243, + 123,231,129,176,240,16,169,227,242,185,180,193,111,58,151,50,157,220,15,184,116,106,204,150,151,159,137,228,72,190,85,25,22,66,236,183,106,221,136,55,76,233,239,87,65,65,102,110, + 176,191,122,238,189,36,249,230,49,137,177,225,113,223,87,72,162,201,246,225,73,145,199,218,224,111,229,35,98,79,109,9,0,1,70,47,51,0,76,174,20,100,139,166,167,197,44,176, + 207,8,149,54,248,77,231,82,166,19,134,254,55,61,35,182,189,104,126,158,156,130,16,12,177,64,22,12,143,184,212,182,145,243,242,164,58,46,83,115,224,175,158,163,243,232,30,173, + 41,182,19,238,171,229,73,22,157,81,96,226,147,100,241,52,104,181,49,0,170,126,141,91,57,75,214,97,154,20,31,143,24,0,38,87,10,154,91,77,207,51,83,181,63,35,84,222, + 224,151,207,165,76,39,102,184,79,24,0,210,51,203,128,73,5,0,160,42,5,238,57,195,145,128,165,3,127,247,153,231,94,252,213,243,61,0,187,141,190,34,33,174,35,101,26,113, + 224,108,101,73,170,213,217,24,2,103,56,222,121,110,31,21,82,75,248,201,199,157,6,159,2,178,33,189,214,141,145,139,64,157,1,240,25,161,210,6,191,233,92,74,244,65,1,172, + 3,32,63,115,152,34,165,86,101,64,149,74,139,255,241,20,247,204,10,33,102,18,226,48,129,185,252,119,206,53,122,14,0,216,2,108,254,33,24,24,215,209,223,240,213,96,181,176, + 140,83,48,27,117,14,192,143,116,116,33,104,242,36,236,54,72,162,146,97,189,253,132,80,121,131,95,62,151,1,96,156,196,16,55,61,3,171,67,226,161,114,139,203,148,101,220,117, + 5,15,91,121,180,251,117,34,160,227,127,245,28,71,242,21,137,134,169,103,235,129,13,141,62,13,252,49,187,150,32,245,253,97,26,5,49,252,238,113,248,145,199,155,80,0,180,249, + 0,40,187,239,141,230,27,166,48,126,74,168,188,193,47,159,203,153,78,104,206,55,118,63,104,140,133,233,153,229,209,41,73,102,82,40,139,236,90,12,248,0,122,11,150,62,78,225, + 23,68,13,230,241,95,61,183,245,146,164,17,172,145,44,88,154,240,157,239,193,200,41,119,184,111,191,100,98,39,71,148,235,45,227,10,41,165,98,44,58,111,9,125,160,47,24,53, + 34,0,48,92,41,107,93,247,142,231,133,74,212,207,8,149,55,248,77,155,253,114,166,83,240,148,84,246,239,8,122,132,76,207,40,203,193,97,179,60,118,177,0,196,234,120,63,114, + 137,92,34,136,192,231,255,234,57,208,153,78,156,198,143,112,225,130,235,201,114,142,36,184,238,184,173,106,47,131,0,143,117,27,190,189,143,88,212,193,18,224,68,46,198,39,28,0, + 147,43,69,205,62,4,195,167,116,245,250,140,80,121,131,95,62,199,52,15,61,211,201,58,44,197,78,82,25,28,8,115,64,128,161,10,175,246,97,205,60,201,19,170,46,114,34,168, + 106,243,87,207,149,237,195,94,171,167,82,131,210,22,29,188,191,116,163,186,238,108,223,54,170,46,108,10,155,114,9,3,103,65,29,3,221,0,117,76,147,43,69,61,138,151,143,9, + 58,200,62,37,212,180,193,47,159,7,163,147,136,200,116,82,172,7,131,23,77,165,166,129,57,32,0,102,1,143,89,94,13,77,186,47,237,33,51,24,182,15,53,32,130,169,118,127, + 245,28,232,118,26,91,193,142,237,63,185,5,64,17,218,29,190,246,34,147,137,186,54,227,74,81,251,111,194,251,240,25,161,166,13,126,243,102,191,236,148,88,217,182,207,127,102,217, + 48,231,215,182,13,195,223,110,16,241,151,207,255,112,160,222,135,123,225,54,35,84,214,186,101,251,196,149,178,170,115,202,87,132,254,47,60,182,217,110,190,34,76,115,163,65,245,190, + 243,34,203,204,255,39,83,102,12,35,218,194,208,81,13,75,159,70,30,176,98,11,138,40,182,224,11,136,195,61,211,66,232,119,2,126,183,69,236,238,250,149,32,223,246,156,26,64, + 201,46,151,43,48,108,191,208,221,124,78,255,147,212,208,245,190,59,238,164,95,154,10,73,176,26,94,9,195,251,32,249,2,86,2,135,34,126,221,228,218,48,140,104,88,210,119,168, + 4,213,173,193,16,70,30,76,85,87,240,213,42,226,120,112,79,181,80,137,239,55,42,231,15,99,27,223,221,189,8,158,242,221,93,243,0,74,118,185,169,232,194,207,155,35,35,174, + 111,175,46,53,204,122,31,3,96,35,52,208,122,44,137,200,17,25,106,93,117,123,202,251,32,249,2,86,6,213,20,15,26,52,185,54,36,35,122,255,132,26,15,129,106,70,36,51, + 13,227,240,217,169,234,10,106,182,201,143,42,192,1,26,147,41,136,222,253,64,173,55,154,127,136,234,121,49,244,202,86,38,243,0,202,118,185,185,232,2,75,48,53,138,10,152,162, + 28,59,146,241,11,0,108,116,138,36,29,163,62,20,199,123,46,145,37,71,204,149,99,120,31,36,95,192,65,9,250,245,66,40,225,178,27,66,50,206,163,9,170,100,131,102,242,238, + 16,59,192,232,230,48,87,87,80,179,170,135,29,205,89,0,182,95,98,172,145,227,21,36,138,161,9,3,192,60,128,38,187,220,84,116,129,210,236,98,81,63,172,17,141,250,245,88, + 114,51,0,96,148,22,15,175,8,58,136,156,173,100,79,61,35,73,52,44,101,239,131,238,11,96,70,155,198,246,7,37,55,132,13,87,61,62,123,127,222,224,190,38,124,62,86,223, + 229,41,72,115,106,47,168,89,85,240,228,44,0,225,188,104,225,87,200,0,152,7,16,38,188,223,207,41,51,23,93,160,52,63,209,168,31,218,40,84,227,113,202,41,102,189,15,1, + 176,245,80,73,111,210,224,105,71,187,230,67,229,153,238,233,216,34,64,148,207,76,31,203,24,225,0,24,84,219,122,229,4,201,241,92,95,91,143,77,202,240,49,143,160,140,228,232, + 133,239,3,128,186,51,63,48,224,123,26,0,125,0,113,19,253,92,80,102,46,186,64,1,248,200,252,166,148,64,35,118,94,99,17,206,102,189,15,1,88,30,197,25,0,248,172,195, + 71,77,23,60,149,136,146,78,15,211,58,0,198,85,220,212,190,238,37,98,116,234,120,198,79,140,54,239,85,156,10,90,0,141,234,149,223,7,0,3,33,196,49,225,0,244,24,0, + 166,1,196,138,42,58,101,230,162,11,116,19,184,112,191,227,228,141,212,225,132,155,200,66,239,51,166,192,78,35,150,126,42,137,136,1,43,134,104,128,118,38,17,37,211,71,165,19, + 5,64,186,138,152,189,134,10,4,37,130,167,153,226,254,168,237,23,214,49,88,31,232,44,253,62,0,116,251,197,4,64,122,112,205,0,48,15,160,137,50,83,209,5,184,147,203,241, + 244,2,108,228,35,194,2,91,235,130,222,215,36,34,107,142,122,132,242,177,66,50,197,226,226,172,67,160,31,213,96,137,40,153,62,197,61,184,97,0,72,87,145,47,235,205,28,6, + 185,56,222,99,96,248,240,229,48,73,37,72,176,204,18,23,204,213,21,190,4,224,86,111,161,244,192,240,8,28,51,170,158,155,6,208,68,153,169,232,2,114,125,158,102,127,137,249, + 32,30,83,179,239,193,131,42,250,29,116,25,144,36,181,208,19,247,144,1,191,178,188,2,137,40,233,148,61,65,1,152,122,160,140,107,120,128,122,100,64,248,239,42,58,229,2,135, + 169,234,10,95,1,176,50,72,17,41,158,24,0,40,180,199,66,61,223,101,3,40,0,48,40,51,21,93,192,59,195,172,240,141,202,143,69,114,201,211,18,201,139,25,192,74,104,80, + 119,5,77,51,93,131,101,100,85,44,23,156,40,233,116,10,0,126,149,122,33,2,129,119,24,95,150,177,180,75,229,63,227,125,16,77,140,19,205,213,21,0,0,59,61,230,173,2, + 216,39,122,196,113,87,152,202,0,41,174,116,203,51,23,0,83,209,5,122,231,53,70,110,124,211,143,89,198,237,167,135,247,176,30,110,186,196,92,159,194,67,182,249,118,206,196,168, + 68,148,116,42,1,32,93,93,235,198,201,245,126,232,4,164,49,58,75,30,127,125,80,41,201,164,159,144,133,83,213,21,212,172,198,143,250,28,69,8,101,29,28,73,20,59,104,89, + 199,79,131,114,234,106,138,219,174,38,202,228,162,11,24,7,17,175,193,108,193,16,119,214,56,213,131,242,29,46,183,180,95,187,132,179,182,22,124,230,226,35,146,231,169,52,18,81, + 210,169,4,128,124,213,125,159,140,149,11,121,156,113,126,12,234,207,196,163,250,250,167,175,134,230,234,10,161,66,86,28,208,45,115,11,17,120,57,205,229,107,189,237,169,2,10,34, + 247,26,14,32,213,76,153,169,2,131,47,58,137,250,118,121,136,59,109,4,13,27,124,202,28,222,249,157,136,157,166,99,44,232,128,231,157,42,38,162,164,83,3,0,211,85,119,180, + 243,210,15,175,178,240,226,246,91,63,202,189,29,192,30,158,91,17,140,98,174,174,16,82,197,177,59,211,66,176,130,145,176,207,54,83,64,65,132,79,219,105,172,181,153,50,83,5, + 134,239,28,171,184,31,138,57,67,209,110,171,51,102,102,191,101,252,38,2,232,36,162,164,83,140,155,30,50,143,161,124,85,217,216,22,134,189,213,161,111,217,59,113,210,120,54,255, + 111,22,87,8,41,19,17,155,193,219,104,149,58,217,162,129,197,41,169,53,184,230,220,176,232,181,19,12,113,99,16,37,159,90,61,86,207,236,213,111,29,134,81,201,140,231,95,194, + 156,92,101,229,29,116,43,126,149,149,17,152,76,28,34,97,27,227,192,240,31,149,197,39,32,49,84,229,89,141,242,136,5,196,123,162,31,118,61,197,120,34,226,93,68,202,49,90, + 165,84,65,132,53,28,228,222,63,151,48,161,71,238,175,184,61,110,158,160,198,236,105,106,236,111,160,56,23,70,37,51,158,127,157,113,115,114,181,223,196,165,81,183,226,29,253,225, + 10,211,52,192,0,97,234,55,230,190,194,63,40,45,169,100,69,91,49,76,151,126,34,124,216,52,233,215,8,240,225,41,198,118,13,236,103,148,24,188,237,120,79,215,53,42,43,64, + 222,193,50,73,19,38,252,122,193,198,41,143,192,138,93,228,53,88,116,250,2,70,190,139,226,112,138,112,150,245,144,198,190,86,113,12,238,155,247,44,188,182,64,237,105,102,236,195, + 226,50,17,70,37,55,158,151,71,121,102,78,194,131,40,230,133,21,239,104,199,49,211,31,21,7,224,81,203,24,116,252,242,96,101,24,35,152,189,148,199,42,19,148,24,180,49,113, + 45,34,218,144,239,224,191,38,46,193,28,0,9,153,193,85,146,39,151,1,112,89,213,72,235,235,100,26,187,140,20,71,251,10,150,18,154,48,113,33,10,54,162,42,60,212,186,147, + 45,177,215,174,177,188,134,213,240,24,232,11,174,42,162,168,36,91,52,29,237,22,15,254,115,127,20,57,99,57,222,83,164,114,132,11,147,231,150,217,211,108,141,163,123,88,220,168, + 20,198,179,173,199,204,73,54,22,186,225,142,154,32,92,7,149,137,234,94,150,8,170,91,104,164,197,134,43,131,228,152,85,99,60,138,225,206,78,36,15,90,225,196,42,146,33,170, + 84,221,222,13,158,246,108,130,96,15,5,64,207,192,123,207,220,235,107,129,195,187,141,203,96,59,111,20,108,68,85,56,150,204,240,148,53,236,24,11,139,239,31,199,178,177,216,41, + 74,124,25,0,61,8,192,253,144,40,112,0,252,231,208,91,20,255,150,113,129,217,211,58,0,212,124,117,112,51,150,246,56,20,97,127,59,87,134,98,131,184,151,233,146,27,141,51, + 133,21,190,146,188,249,171,64,234,131,231,150,105,4,206,86,241,132,36,6,155,111,185,10,15,222,165,193,245,109,4,96,183,81,11,218,244,36,229,38,104,171,6,0,165,4,79,26, + 103,97,33,160,103,44,77,21,108,132,101,188,55,98,181,225,152,78,206,74,86,145,123,181,29,167,189,11,84,234,184,12,139,232,201,10,149,106,238,135,14,55,117,168,241,29,242,160, + 248,183,132,66,161,128,79,49,0,224,5,65,63,253,171,187,110,126,222,80,195,50,146,99,140,130,218,85,93,61,2,145,80,253,117,38,230,123,17,154,13,127,181,110,0,224,190,47, + 29,64,47,106,205,50,27,21,150,164,92,44,38,37,0,98,36,166,87,95,132,233,115,233,101,0,24,245,10,213,35,232,62,205,150,160,186,43,231,128,181,46,88,153,232,12,130,235, + 129,202,205,115,243,105,180,77,189,117,73,146,46,82,87,160,91,216,122,254,139,52,73,22,105,47,5,93,58,0,188,32,232,167,127,117,0,2,172,250,213,65,137,153,121,24,97,81, + 252,72,29,194,80,142,83,76,108,2,0,227,52,201,141,210,125,3,0,80,132,177,23,249,98,214,0,224,10,6,65,158,2,213,44,73,138,42,47,160,179,129,5,56,13,0,45,59, + 224,178,177,196,129,194,21,87,186,215,194,140,247,161,17,168,36,79,114,132,110,243,224,236,41,113,41,32,0,112,180,193,210,104,209,15,9,186,140,41,96,16,248,245,223,253,19,106, + 76,112,28,168,122,22,171,159,253,130,153,208,228,246,62,207,113,63,63,13,234,0,56,218,71,147,9,246,34,116,37,1,192,133,160,33,3,18,162,204,240,70,39,142,59,136,75,166, + 130,141,246,73,22,3,41,236,76,2,166,94,175,12,199,1,250,169,80,38,253,188,121,220,31,195,41,247,214,85,120,152,166,71,154,2,197,144,93,118,70,254,117,0,34,57,58,83, + 247,234,220,160,71,27,51,121,235,1,49,152,225,150,47,2,240,1,223,250,28,208,1,8,176,8,3,248,161,65,127,111,227,51,0,188,143,49,154,214,133,188,138,193,8,12,0,177, + 141,201,150,92,78,180,247,170,28,148,0,128,69,41,70,229,228,79,23,198,161,80,19,79,138,132,50,3,160,252,103,0,68,19,44,242,227,138,187,55,48,164,129,244,87,97,33,20, + 149,63,16,0,74,153,14,0,172,15,3,198,1,206,21,150,115,196,83,140,85,124,108,77,79,67,70,48,47,176,109,29,118,182,21,14,128,190,141,41,113,128,173,151,248,80,17,0, + 70,205,70,47,151,124,116,161,190,182,207,146,235,120,38,199,127,3,0,190,254,161,81,204,29,203,192,160,192,251,160,46,164,15,69,162,118,81,221,122,189,122,114,161,98,55,113,83, + 119,16,72,76,31,246,2,180,148,162,145,98,172,102,227,36,150,133,213,88,164,28,35,100,89,154,187,177,161,8,0,244,130,141,92,6,252,220,70,182,139,101,179,73,96,58,186,20, + 185,58,71,165,48,62,250,146,0,0,26,55,73,68,65,84,174,235,21,212,147,253,147,125,140,48,48,56,128,237,41,254,147,0,112,13,200,245,76,226,60,40,144,101,224,128,254,199, + 241,102,41,222,91,94,87,168,144,0,114,238,221,176,4,196,83,247,190,154,240,164,224,175,241,20,99,53,202,247,61,69,202,113,64,236,131,42,6,0,65,177,33,72,1,160,171,144, + 93,107,181,90,0,214,29,50,157,235,57,85,27,171,212,155,55,33,175,65,144,1,25,46,3,74,227,35,236,228,22,198,153,181,68,221,91,117,109,46,0,212,124,133,117,252,79,127, + 185,14,172,184,62,122,162,163,1,94,131,41,160,39,106,243,104,242,16,146,231,166,166,217,161,91,241,137,196,108,231,183,53,248,37,185,96,163,178,166,210,41,64,165,175,221,233,12, + 225,20,240,209,216,210,56,218,234,49,160,66,205,36,202,57,194,54,227,119,235,36,81,66,191,215,214,107,22,176,79,131,176,161,68,80,14,211,233,97,198,62,126,0,205,215,160,242, + 231,191,220,10,82,214,109,255,156,89,56,137,134,89,248,168,56,84,221,39,104,248,27,214,186,89,182,37,195,150,159,80,1,167,0,232,114,186,153,65,253,185,195,247,23,177,25,191, + 219,127,233,80,143,231,150,10,216,31,170,156,8,206,1,130,30,106,236,111,253,131,54,238,196,212,152,46,209,229,49,87,224,18,181,171,18,121,116,170,78,116,123,137,59,37,151,76, + 254,6,172,19,48,49,236,75,202,95,62,201,208,116,50,131,127,219,102,4,255,111,252,7,196,236,43,110,150,10,193,168,10,24,164,253,8,169,17,223,138,76,165,26,176,25,196,76, + 100,202,166,75,116,9,107,81,200,34,102,6,118,10,52,136,104,66,94,52,220,164,212,94,116,0,254,193,67,88,238,30,97,45,202,132,216,153,17,105,55,70,230,242,100,255,158,38, + 195,176,97,153,84,116,210,252,119,197,108,174,54,144,72,38,71,21,100,83,94,136,43,244,107,75,249,172,120,87,25,0,48,85,219,226,10,192,27,205,196,82,179,93,38,175,187,220, + 49,190,36,102,72,100,71,103,43,234,23,14,25,25,18,192,220,161,93,195,79,98,49,138,203,121,249,93,143,69,209,55,206,192,0,107,138,34,127,18,33,230,58,108,108,109,43,29, + 156,38,88,66,74,14,151,149,126,238,154,105,29,254,139,88,181,89,63,202,73,36,63,36,168,253,47,20,252,179,87,167,242,73,137,46,170,61,201,181,150,120,67,99,27,109,234,26, + 3,96,77,228,13,114,132,227,57,230,141,156,170,38,199,55,105,210,133,198,216,170,7,191,79,189,165,0,236,129,38,213,173,44,227,118,140,228,6,43,214,225,85,137,26,75,50,33, + 230,58,108,136,157,70,174,38,217,34,157,110,219,47,24,34,249,59,63,182,179,88,131,68,249,234,170,254,94,60,14,235,221,15,158,178,205,28,170,208,63,231,8,202,227,79,74,116, + 185,148,185,0,220,137,114,88,250,138,205,0,96,8,127,156,179,157,216,233,106,114,214,225,11,226,255,148,33,5,145,79,48,243,150,2,237,46,205,181,75,203,254,9,13,173,14,31, + 211,80,93,32,164,245,187,82,189,97,132,152,234,176,153,167,44,51,52,174,83,60,225,95,205,252,254,77,128,119,250,73,99,48,193,28,136,139,122,93,87,94,232,20,198,176,127,93, + 175,203,4,64,249,58,69,210,44,247,108,10,0,81,216,40,193,147,1,166,170,201,217,105,68,164,171,37,189,168,99,230,45,5,63,238,69,125,66,92,193,47,189,235,31,41,234,28, + 2,66,206,227,15,191,9,35,196,84,135,13,122,81,76,199,138,71,96,187,209,123,171,253,164,254,11,235,31,100,216,34,218,69,50,90,193,43,180,251,55,103,104,12,76,179,243,215, + 245,186,76,0,228,43,213,198,96,93,249,28,128,195,148,14,128,169,154,28,3,192,1,183,121,145,254,57,111,41,176,140,227,44,45,3,110,166,224,204,123,73,253,25,64,72,63,94, + 14,250,47,2,21,70,154,84,135,77,177,121,194,249,227,112,53,54,228,161,63,184,227,203,125,21,208,3,181,5,234,249,157,151,130,197,186,159,35,121,186,123,201,126,241,137,208,157, + 202,63,212,235,50,77,129,128,127,103,69,249,28,128,240,131,24,68,115,53,57,187,118,135,33,221,109,20,9,108,226,207,123,75,129,122,68,216,14,48,165,241,89,205,80,94,6,66, + 52,188,235,247,242,81,151,234,176,217,122,205,102,162,212,204,102,68,102,17,104,222,194,210,113,180,227,227,22,121,79,159,251,47,16,72,214,125,12,121,101,57,161,208,159,187,44,73, + 224,110,195,220,18,93,107,50,0,126,199,52,26,243,1,200,230,73,170,185,39,91,218,188,154,220,110,35,3,104,100,79,67,194,229,55,247,45,5,198,75,18,48,94,191,210,98,188, + 4,132,244,73,53,176,245,58,186,224,33,12,70,29,54,195,131,43,0,73,221,199,73,142,203,210,196,211,61,121,187,74,245,104,168,63,251,13,116,9,10,126,200,22,75,181,143,77, + 101,126,137,174,53,121,100,252,23,56,20,212,12,84,117,0,168,197,228,51,3,80,185,196,185,171,3,32,85,147,219,197,41,160,6,145,68,106,153,205,125,75,65,36,167,191,200,37, + 156,39,137,50,179,98,145,144,114,186,251,150,28,100,121,1,13,163,12,217,202,160,85,37,205,223,164,206,253,41,191,206,46,252,87,92,14,99,236,87,237,170,217,187,202,83,131,131, + 203,153,59,182,125,203,136,57,240,173,43,202,188,18,93,130,76,113,199,48,11,197,110,180,66,45,166,180,94,125,157,79,1,176,52,227,186,179,73,174,38,199,100,0,26,52,108,143, + 115,238,91,10,162,73,253,85,62,232,167,142,243,77,122,32,164,125,154,205,61,214,68,226,188,84,135,109,101,191,156,140,54,200,128,249,213,67,175,153,161,117,4,140,173,237,82,73, + 82,200,222,126,188,156,82,135,5,39,172,155,103,217,39,50,49,179,37,186,102,239,232,102,161,196,1,168,181,251,166,133,96,75,176,192,84,53,57,6,192,70,71,76,251,121,111,41, + 192,133,81,4,201,225,78,133,136,29,51,19,162,152,235,176,81,53,136,151,118,5,163,3,236,49,176,157,72,138,106,35,214,33,158,151,218,219,130,150,36,14,8,101,35,19,49,51, + 37,186,102,239,252,209,44,92,226,142,18,140,67,161,245,230,166,170,201,185,233,20,208,142,121,2,251,188,183,20,28,118,114,168,254,240,47,12,150,153,131,93,153,34,68,153,174,195, + 118,120,160,4,69,165,163,80,20,172,38,159,81,164,204,138,231,7,14,157,150,40,216,40,17,207,63,161,173,47,255,192,113,244,239,232,81,201,75,194,81,2,164,164,65,10,79,85, + 147,115,223,103,40,254,201,106,159,69,12,206,121,75,65,154,164,46,164,234,227,193,137,17,152,43,19,162,76,215,97,251,207,14,185,84,144,226,253,105,142,210,222,19,217,230,114,66, + 29,250,181,124,163,59,224,100,255,197,239,161,95,47,160,192,29,37,96,240,29,110,41,51,213,228,220,42,197,63,26,96,211,122,222,91,10,14,225,39,254,195,84,106,155,103,125,206, + 57,102,231,253,114,28,64,239,116,235,211,195,253,173,230,252,54,239,213,77,55,226,221,54,2,8,234,188,222,128,156,80,167,44,123,194,29,16,128,48,188,192,238,137,234,91,100,103, + 229,159,182,6,21,219,47,0,60,200,70,220,171,70,92,138,201,52,231,165,137,229,231,215,121,104,97,83,127,73,160,113,30,44,131,246,117,214,46,197,18,101,110,215,89,124,183,5, + 205,197,157,224,82,126,27,174,81,249,203,151,195,95,110,33,136,217,123,91,228,132,58,101,111,212,4,209,149,187,134,169,188,218,111,96,202,106,99,224,167,47,89,153,152,228,133,243, + 32,26,61,16,162,227,179,134,74,61,42,204,124,151,62,109,235,157,193,122,80,166,235,165,247,234,40,255,228,146,11,97,47,179,228,152,241,186,193,155,61,70,43,200,82,189,60,142, + 113,62,33,45,92,112,19,189,58,51,4,149,149,49,40,40,169,231,29,35,55,151,103,55,109,116,234,37,144,218,41,90,111,210,227,245,190,151,30,189,222,93,101,42,161,14,186,118, + 254,26,217,195,201,178,186,27,126,175,101,72,28,68,247,146,17,148,71,23,168,221,86,41,145,40,181,118,248,106,58,191,65,189,124,217,9,53,223,39,198,167,45,227,28,41,141,186, + 89,150,115,71,242,143,41,64,91,55,205,151,71,199,160,4,129,229,139,68,115,222,204,179,184,35,131,104,152,217,112,78,203,72,209,236,60,248,246,227,240,27,83,159,28,152,22,77, + 72,172,17,88,158,78,239,218,216,61,24,181,202,49,100,111,79,243,138,29,13,115,66,29,60,159,121,24,251,244,247,91,238,169,45,186,105,8,0,148,53,77,123,137,19,186,87,79, + 195,240,8,15,24,218,109,196,43,15,15,149,217,198,26,172,202,73,205,253,128,230,149,4,0,2,254,232,218,187,166,166,160,163,61,86,179,172,186,137,72,92,75,39,222,29,189,28, + 238,46,8,222,164,42,35,12,25,16,77,135,12,103,118,158,228,104,25,41,80,186,139,152,157,151,107,214,169,154,238,120,63,18,171,190,190,41,35,0,216,239,252,198,172,67,116,223, + 209,168,66,238,242,146,19,234,92,79,37,124,224,131,86,74,116,237,119,235,240,109,199,184,53,230,190,175,249,236,152,89,138,251,227,142,118,44,15,167,229,34,86,188,135,198,253,196, + 237,158,220,207,52,232,182,233,253,175,51,220,186,3,70,133,227,28,75,167,224,239,193,221,61,150,181,218,235,170,217,242,190,164,137,111,191,36,210,157,60,238,199,81,168,158,240,71, + 233,43,115,174,174,42,164,76,135,76,238,189,200,206,75,243,44,130,205,183,150,56,112,69,150,243,219,208,10,143,21,174,223,209,125,231,104,195,3,247,240,63,124,181,156,80,167,184, + 14,180,26,128,84,164,73,128,39,49,146,60,127,15,255,64,25,224,102,241,193,84,181,251,117,70,158,123,96,216,180,80,237,249,117,86,121,138,117,62,98,183,149,233,134,178,61,78, + 147,82,47,217,255,137,29,9,57,157,145,28,42,66,188,172,185,155,166,128,212,98,167,23,177,98,72,54,69,92,207,177,24,43,6,70,161,186,200,9,222,52,188,148,161,201,4,184, + 129,186,108,225,153,244,33,157,2,129,192,61,176,26,230,76,240,131,149,101,55,242,219,246,203,103,183,253,80,32,128,123,209,138,195,9,208,93,239,57,183,20,115,66,29,240,160,111, + 252,120,18,99,171,64,241,110,68,13,37,186,10,128,126,207,66,18,49,153,181,72,57,0,85,219,195,84,235,245,184,215,59,126,105,77,55,182,95,192,60,37,167,153,10,90,4,33, + 220,29,167,213,24,16,240,103,151,251,1,134,11,148,195,139,96,85,247,90,112,91,12,20,238,35,150,227,13,0,84,11,143,148,55,113,200,26,164,70,135,76,150,7,123,117,18,31, + 188,163,98,253,235,61,198,202,197,203,177,132,114,126,219,94,157,167,155,48,13,31,236,6,174,234,155,18,234,112,89,0,222,135,57,236,105,118,66,63,150,141,164,41,116,55,213,69, + 65,103,90,226,61,199,196,155,182,53,184,189,29,108,107,172,241,209,183,217,122,109,108,172,127,52,111,64,86,52,132,45,27,42,80,237,215,214,75,144,203,253,113,14,96,1,179,248, + 5,168,188,240,79,149,61,47,178,160,108,132,42,55,188,99,188,233,112,82,162,113,200,148,189,64,160,83,121,161,67,137,234,86,50,81,174,144,236,25,213,30,167,131,41,165,252,54, + 19,19,33,2,109,17,234,102,78,168,163,210,15,5,154,103,67,78,155,67,75,147,189,142,4,173,154,223,160,188,198,27,88,160,61,154,124,29,229,42,149,220,232,149,53,158,170,7, + 251,181,71,108,216,122,45,16,161,233,22,55,229,182,94,185,37,239,122,74,198,202,121,116,143,5,42,68,3,227,247,89,246,79,238,54,128,250,26,141,6,66,168,36,222,148,70,93, + 26,202,53,245,227,117,24,196,36,79,90,110,122,26,0,57,191,45,100,222,236,80,28,150,111,39,212,45,193,58,149,161,175,116,193,248,209,131,18,57,121,200,229,238,75,168,59,28, + 148,46,158,46,3,129,218,253,5,107,140,11,165,147,252,24,27,174,39,140,187,136,23,89,112,4,76,65,241,158,68,87,84,59,173,31,176,33,238,168,71,249,176,228,142,88,255,136, + 21,70,203,254,115,164,213,245,156,145,121,83,7,96,106,40,215,183,172,52,201,211,162,43,31,210,219,73,254,214,225,49,149,21,98,53,68,112,95,29,58,232,126,0,16,144,25,78, + 159,158,78,233,222,167,235,49,222,236,175,175,247,155,113,214,120,25,63,62,142,94,176,161,184,216,222,52,11,250,3,202,196,91,139,244,74,219,96,8,158,85,179,84,174,232,133,176, + 119,235,96,38,91,198,87,48,234,158,219,142,137,55,157,250,86,204,212,80,126,39,248,16,13,2,166,57,208,136,55,111,84,196,120,253,88,163,69,133,176,183,120,224,234,213,140,232, + 230,97,96,160,13,225,238,18,14,80,110,52,225,27,130,184,239,139,7,21,34,190,90,162,241,241,209,72,204,54,20,99,215,29,253,60,89,49,229,140,74,219,203,33,88,6,215,21, + 83,113,236,93,180,39,44,222,101,54,9,255,66,178,231,116,122,144,35,132,81,86,123,148,38,180,7,138,79,76,115,160,17,111,87,9,62,33,119,239,186,158,123,88,49,145,95,241, + 128,1,158,144,124,43,184,206,227,41,242,87,104,225,46,241,168,47,225,159,246,253,6,41,152,249,205,168,252,188,161,239,186,83,79,95,99,94,165,109,94,81,249,123,133,176,57,125, + 123,27,225,73,100,211,72,131,116,129,177,23,196,193,53,165,7,57,218,69,140,62,170,83,154,64,238,144,92,239,162,252,186,197,226,115,18,165,155,20,213,105,125,141,212,176,153,134, + 69,199,211,172,180,158,83,84,209,67,173,173,252,129,91,85,192,235,47,170,70,67,100,2,242,166,34,204,94,152,106,122,212,228,231,13,125,215,29,147,180,191,105,225,218,77,127,248, + 25,141,88,230,244,37,174,65,81,202,161,187,147,167,65,62,23,159,97,249,135,193,53,165,7,173,12,170,168,114,118,192,154,89,97,62,168,250,81,119,75,36,138,244,119,126,163,108, + 6,94,126,104,240,18,171,45,81,140,147,170,173,241,26,42,109,151,164,116,84,130,147,127,188,182,184,197,7,198,51,43,142,164,172,26,213,203,104,176,93,136,237,145,241,180,215,245, + 48,173,77,140,17,203,148,190,139,115,152,140,191,115,52,155,101,121,116,9,107,36,136,167,74,160,69,29,74,166,244,160,245,15,60,233,102,212,21,174,93,136,250,82,240,212,145,170, + 236,108,80,79,86,121,194,61,253,14,103,59,198,138,1,49,189,29,115,36,65,24,63,61,160,94,191,100,42,138,99,59,176,82,229,92,14,41,247,27,2,56,48,149,35,40,89,191, + 203,60,192,214,50,70,43,43,143,203,131,53,216,215,70,59,6,173,63,111,104,190,43,255,3,84,224,254,17,139,88,102,244,81,239,219,37,161,201,6,152,205,215,56,76,147,212,248, + 65,188,113,90,74,15,130,79,229,34,117,238,198,197,236,10,174,105,25,225,41,214,97,46,217,45,176,234,189,104,121,36,187,27,43,12,128,196,245,200,77,249,166,245,136,218,207,146, + 92,20,199,214,43,13,67,145,64,147,127,179,226,216,11,245,111,65,153,17,75,48,118,213,148,78,167,91,191,91,35,173,27,89,99,193,149,185,193,168,10,221,176,14,203,137,18,43, + 223,192,104,5,121,69,105,225,127,194,244,253,15,60,74,150,134,87,162,105,131,204,58,225,52,22,94,193,96,121,166,234,230,84,122,16,110,163,180,243,124,139,165,119,4,140,47,165, + 11,10,175,72,169,56,42,211,45,96,54,1,58,192,239,248,78,154,222,30,123,185,119,254,172,132,175,221,89,146,139,226,128,14,89,42,230,170,172,134,162,51,160,182,175,11,116,73, + 150,0,144,178,229,36,235,119,235,53,121,150,202,161,76,68,13,254,237,176,11,215,246,174,201,249,97,138,234,200,140,86,156,119,244,17,250,103,243,141,155,95,87,122,242,139,9,0, + 140,230,170,212,115,164,154,234,175,206,0,176,50,136,147,19,174,124,168,229,223,160,201,28,143,215,204,241,57,138,117,92,209,198,85,248,121,172,211,121,162,170,21,16,141,161,98,59, + 192,215,30,107,100,208,199,130,122,75,166,162,56,160,188,197,211,36,205,66,141,171,32,245,99,197,107,144,73,18,0,83,233,116,220,250,181,107,207,209,123,186,118,210,119,216,164,171, + 240,13,160,84,161,183,253,214,35,104,69,112,248,11,153,225,143,80,126,182,252,235,202,60,0,112,158,199,62,96,66,20,66,51,153,95,76,123,103,243,30,250,118,124,159,96,73,68, + 82,124,14,221,141,29,227,127,84,209,73,101,179,180,94,121,72,202,22,90,89,101,154,160,92,32,7,108,184,247,195,211,24,26,44,116,127,252,105,24,218,219,84,100,0,166,178,229, + 184,245,235,104,231,19,172,124,28,200,128,4,139,229,135,62,94,69,114,232,34,22,180,194,7,248,27,186,224,15,160,130,188,189,245,122,142,215,116,0,124,2,0,154,7,26,121,227, + 86,202,84,226,19,218,202,113,238,136,85,39,97,183,88,146,164,248,28,238,125,179,176,0,255,67,85,141,206,247,144,47,153,42,251,4,42,233,67,24,67,100,219,221,6,76,192,100, + 185,209,142,204,0,32,165,211,113,235,23,108,211,151,22,5,192,209,238,140,158,143,145,8,48,126,75,31,52,26,149,211,10,60,65,117,99,246,199,50,166,53,109,128,204,242,62,167, + 15,62,150,170,37,133,30,12,51,229,210,171,102,8,155,233,211,137,79,174,73,244,111,59,98,29,60,47,101,27,221,175,75,166,202,62,187,117,114,211,201,179,183,81,238,170,31,13, + 244,180,229,34,50,0,114,58,157,97,253,194,104,95,148,105,9,24,239,85,57,252,235,55,173,131,236,122,62,45,214,144,31,129,86,116,82,114,241,239,126,96,21,134,237,26,70,45, + 29,176,146,219,148,190,48,238,216,68,117,61,216,203,82,100,214,191,169,100,56,29,63,88,201,9,189,92,168,34,42,188,251,126,202,202,153,163,205,242,82,182,95,208,253,186,36,23, + 197,193,114,242,232,117,163,247,193,50,13,28,12,239,171,32,107,36,0,164,108,57,201,250,221,232,148,79,126,87,240,213,11,240,117,199,103,201,56,92,227,26,104,136,254,36,70,24, + 218,122,84,1,112,188,143,248,203,11,113,109,180,140,223,2,127,97,240,156,230,49,164,57,45,52,151,197,174,181,218,119,247,56,114,187,188,142,59,42,19,172,194,187,175,198,118,50, + 249,235,46,236,90,90,132,101,194,204,92,146,139,226,120,154,228,186,113,245,144,61,130,47,146,45,83,121,25,148,178,229,12,235,87,34,118,111,252,209,234,140,127,242,50,149,77,102, + 229,57,70,84,189,227,189,151,181,35,197,178,41,165,195,173,154,212,104,203,182,133,14,173,97,188,59,217,206,162,24,67,150,211,66,115,117,28,237,84,170,129,81,137,187,162,142,187, + 136,47,69,130,105,69,3,253,117,23,42,173,153,139,82,14,122,181,36,23,197,177,140,155,123,187,94,119,7,85,47,217,50,221,122,101,190,56,202,186,82,182,28,88,191,45,250,78, + 17,153,88,203,58,207,65,91,167,5,34,68,221,153,63,143,174,120,65,137,24,41,203,248,5,176,133,161,21,1,254,203,246,9,153,176,225,134,49,220,179,235,145,54,44,29,189,28, + 206,131,14,229,209,235,184,139,10,239,128,77,225,222,109,188,238,130,3,0,162,25,23,152,37,83,81,28,139,135,101,195,77,91,166,91,78,122,108,204,100,203,217,157,236,84,38,246, + 107,77,25,56,150,235,140,250,120,175,241,226,135,252,5,37,98,164,192,94,1,203,18,186,95,9,56,157,140,163,53,194,82,179,212,108,161,89,215,104,110,220,157,214,206,178,75,165, + 72,14,69,143,168,227,190,172,87,120,199,122,46,200,117,236,117,23,2,128,240,49,141,25,250,175,188,103,200,160,146,123,29,244,169,106,25,3,199,210,133,218,49,214,250,172,42,105, + 184,219,195,55,94,136,23,148,232,35,5,154,8,246,16,186,63,104,137,152,48,125,184,19,191,83,236,77,175,63,188,87,13,230,48,74,177,237,76,81,199,221,168,240,14,223,48,166, + 174,39,19,0,142,118,119,157,237,13,90,148,29,61,109,210,200,146,19,218,132,24,39,253,138,62,83,13,105,187,102,51,137,93,131,74,225,117,208,167,42,141,22,196,94,56,218,233, + 114,30,141,219,149,193,113,249,248,20,165,23,123,65,137,49,82,32,79,113,82,65,247,219,5,86,38,126,2,83,128,110,65,169,217,124,164,200,86,203,149,65,158,69,100,1,78,67, + 164,95,212,113,55,42,188,71,242,71,37,58,141,38,28,216,36,173,123,238,88,227,187,195,227,29,17,4,8,61,103,174,13,24,158,110,100,69,30,39,253,138,62,83,117,105,43,134, + 80,23,187,58,149,186,215,65,159,170,118,237,82,235,171,76,231,252,104,160,16,2,50,59,119,180,178,2,123,65,137,67,234,40,7,32,159,126,226,179,107,194,149,36,28,195,162,168, + 212,65,193,113,63,148,78,168,139,214,168,227,110,84,120,143,116,233,194,195,94,119,1,95,28,85,13,133,112,233,160,84,30,87,203,212,89,189,227,131,57,230,67,11,250,61,125,146, + 207,3,45,250,56,233,87,244,153,170,75,91,99,8,13,177,203,169,212,189,14,250,84,181,107,71,213,24,70,131,1,0,29,106,174,239,159,16,173,197,125,114,248,130,18,207,44,0, + 197,114,170,203,122,108,215,107,218,103,155,217,36,142,46,48,0,27,51,247,193,254,182,17,189,202,2,150,244,10,239,252,13,108,161,73,52,52,163,9,218,181,100,73,75,97,24,228, + 78,163,54,32,131,26,218,49,117,210,162,10,187,49,78,226,138,62,83,117,105,107,12,161,16,187,58,149,186,215,65,159,170,150,241,16,84,115,88,148,0,218,147,60,26,10,160,9, + 49,0,248,11,74,86,245,145,242,95,160,146,8,196,230,155,36,207,99,40,185,51,5,198,208,195,117,219,149,176,229,239,9,42,183,135,190,202,29,203,233,145,38,29,139,159,55,233, + 19,114,114,244,128,182,77,246,36,143,152,232,227,164,95,49,102,170,144,182,250,16,234,98,87,167,82,247,58,224,72,209,162,72,142,182,230,171,97,137,71,91,175,223,109,98,228,29, + 128,244,113,79,247,7,188,99,109,72,195,148,233,139,73,236,160,115,105,52,3,54,26,241,76,34,142,191,224,116,114,249,169,227,197,239,210,207,157,250,6,182,126,230,190,111,210,87, + 185,47,89,198,199,201,118,33,129,8,239,105,89,146,199,237,46,80,136,110,107,113,232,166,62,78,250,21,99,166,10,105,171,15,161,46,118,117,42,117,175,3,78,77,42,171,61,183, + 37,16,223,192,180,158,102,225,38,119,73,133,86,174,82,42,178,248,56,81,200,28,151,12,100,92,243,107,214,132,219,17,72,178,33,113,59,94,54,246,203,70,216,129,93,251,137,19, + 239,28,84,110,187,86,125,118,129,134,134,231,198,250,97,156,81,229,14,122,13,182,64,182,115,147,70,138,246,174,227,85,82,77,130,218,136,219,26,79,120,87,31,39,253,138,62,83, + 117,105,171,15,161,46,118,117,42,117,175,131,96,0,64,224,64,27,209,130,32,158,143,86,159,189,213,53,210,31,132,254,192,198,203,198,95,74,82,239,226,201,181,211,160,111,75,178, + 31,140,162,65,151,213,133,231,142,131,18,244,62,26,199,34,152,96,158,128,197,10,231,23,126,170,65,176,85,200,56,67,254,66,145,189,20,44,247,252,213,142,131,106,34,191,65,6, + 252,126,164,155,0,23,101,4,69,31,39,253,138,62,83,117,105,107,12,161,46,118,61,221,214,7,165,201,26,105,191,209,146,112,122,229,72,232,49,167,102,221,41,174,172,174,152,3, + 124,2,148,121,85,85,161,111,57,176,236,68,38,163,195,160,199,97,89,223,133,142,83,146,240,213,194,239,180,218,171,93,43,145,120,249,121,248,124,178,47,118,37,64,52,213,247,88, + 233,88,5,172,201,235,61,204,232,225,89,59,198,25,242,23,46,218,48,5,108,150,49,79,1,223,129,85,96,135,206,156,104,175,127,232,160,117,161,180,8,219,217,29,190,190,141,104, + 228,7,190,74,104,85,44,237,72,247,234,248,173,77,201,165,240,210,129,94,115,10,27,206,193,11,50,44,127,183,212,130,117,120,93,57,7,230,197,87,193,161,194,98,25,55,176,134, + 80,185,249,62,254,168,11,146,174,201,145,10,86,25,60,118,80,138,23,104,76,32,220,226,187,18,182,222,203,30,85,164,97,124,173,195,246,30,205,232,17,89,59,198,153,190,53,102, + 145,194,118,236,19,49,235,108,186,254,163,87,175,217,92,230,35,231,48,236,48,86,119,99,211,33,244,32,233,253,135,159,239,1,240,210,137,62,102,214,121,246,216,154,229,241,108,163, + 141,7,235,205,199,27,53,192,24,0,208,78,22,243,113,102,151,192,170,64,73,218,107,15,173,107,253,15,23,26,240,189,208,248,241,172,120,137,2,154,239,74,216,216,75,60,104,9, + 85,235,159,164,231,127,239,149,155,96,160,187,127,88,127,184,141,116,39,54,211,101,51,19,204,186,71,166,212,195,89,243,5,109,60,247,61,137,97,112,145,0,192,115,219,28,135,34, + 163,231,203,147,226,233,195,190,32,9,171,143,174,178,112,89,155,98,113,253,10,121,173,127,179,155,0,128,211,239,163,34,128,122,208,217,177,101,26,28,195,14,87,236,158,31,86,30, + 204,230,161,250,239,178,219,227,94,230,54,250,15,54,151,215,182,89,13,181,214,251,253,221,240,78,148,54,2,89,201,100,189,108,102,98,216,12,83,234,113,46,223,227,78,143,179,245, + 118,147,132,43,2,0,197,131,249,56,203,46,239,126,40,232,254,47,140,211,146,226,109,157,215,218,145,64,4,228,56,13,47,105,177,240,18,99,112,12,59,92,113,104,205,59,170,52, + 58,122,183,205,30,125,193,245,67,243,158,78,251,173,247,230,29,117,63,184,187,47,163,85,106,132,166,175,73,158,191,169,139,57,75,169,254,64,243,244,224,160,169,13,134,82,111,239, + 101,146,168,239,237,214,143,107,201,250,30,125,27,226,107,219,161,252,183,15,158,51,148,175,228,89,232,200,156,193,49,236,112,199,123,162,94,194,221,22,56,169,93,38,96,81,216,122, + 173,118,142,112,211,101,235,181,220,206,227,82,231,126,136,145,28,138,124,48,208,39,160,22,48,139,212,245,20,203,191,149,88,56,178,141,150,208,98,186,188,161,212,59,181,34,203,88, + 216,13,251,162,84,112,129,204,254,239,211,143,182,64,173,117,83,32,36,73,85,96,41,62,65,31,28,195,14,7,176,106,101,212,140,209,179,221,98,165,209,106,229,35,166,184,55,154, + 39,168,253,169,71,213,247,35,246,74,211,138,14,128,163,157,168,140,54,199,151,198,43,220,21,74,183,161,212,59,91,249,102,54,86,223,83,254,167,143,165,213,62,174,11,218,203,144, + 190,113,84,122,203,144,62,56,134,246,4,203,207,173,118,3,195,11,162,249,169,133,241,78,112,165,123,138,15,237,214,73,163,130,216,68,19,15,193,83,80,62,184,14,223,32,69,52, + 170,222,223,2,203,138,197,251,110,188,121,70,9,169,38,165,222,25,241,168,147,255,121,250,49,119,152,23,241,42,132,20,249,92,178,184,116,59,220,174,101,74,13,52,5,109,189,220, + 105,25,43,49,192,212,46,103,240,161,213,126,182,74,139,226,4,203,217,51,90,104,128,233,240,187,147,16,53,171,153,75,204,177,173,252,111,59,62,5,0,21,157,158,166,191,56,147, + 217,225,118,181,63,160,206,0,91,36,216,29,161,52,252,57,24,178,17,92,85,123,195,32,181,122,170,165,166,71,249,215,28,75,38,182,151,207,65,209,177,217,133,211,103,162,204,168, + 173,220,198,94,209,23,96,27,59,91,9,28,252,139,232,255,127,234,221,227,127,19,0,189,110,182,135,187,128,69,201,108,209,230,149,207,150,237,220,177,41,157,49,191,113,232,95,13, + 128,94,55,155,134,141,131,64,23,37,179,69,155,87,62,155,103,82,78,228,4,170,127,43,0,122,221,108,157,96,94,50,91,180,121,229,179,121,78,5,47,11,76,255,55,201,188,57, + 83,64,148,56,163,149,42,121,45,113,172,113,38,218,162,242,217,28,183,146,226,165,135,231,223,45,3,48,68,20,189,131,180,82,37,127,123,125,100,75,106,251,126,253,191,45,4,255, + 191,95,5,22,0,44,0,88,0,176,0,96,1,192,2,128,5,0,11,0,22,0,44,0,88,0,176,0,96,1,192,2,128,5,0,11,0,22,0,44,0,88,0,176,0,96,1,192, + 2,128,5,0,11,0,22,0,44,0,88,0,176,0,96,1,192,2,128,5,0,11,0,22,0,44,0,88,0,176,0,96,1,192,2,128,5,0,11,0,22,0,44,0,88,0,176,0, + 96,1,192,2,128,5,0,11,0,22,0,44,0,88,0,176,0,96,1,192,2,128,5,0,11,0,22,0,44,0,88,0,176,0,96,1,192,2,128,5,0,11,0,22,0,44,0,88, + 0,176,0,96,1,192,2,128,5,0,11,0,22,0,44,0,88,0,176,0,96,1,192,2,128,5,0,11,0,22,0,44,0,88,0,176,0,96,1,192,2,128,5,0,11,0,254,37, + 199,255,1,140,84,153,133,3,106,34,167,0,0,0,0,73,69,78,68,174,66,96,130 +}; + + diff --git a/examples/opengl_various_bindings/imguistyleserializer.cpp b/examples/opengl_various_bindings/imguistyleserializer.cpp new file mode 100644 index 000000000..0384a875f --- /dev/null +++ b/examples/opengl_various_bindings/imguistyleserializer.cpp @@ -0,0 +1,222 @@ +// USAGE: +/* +1) Compile this cpp file +2) In your main.cpp just add (without including any additional file: there's no header!): +extern bool ImGuiSaveStyle(const char* filename,const ImGuiStyle& style); +extern bool ImGuiLoadStyle(const char* filename,ImGuiStyle& style); +3) Use them together with ImGui::GetStyle() to save/load the current style. + ImGui::GetStyle() returns a reference of the current style that can be set/get. + +Please note that other style options are not globally serializable because they are "window flags", +that must be set on a per-window basis (for example border,titlebar,scrollbar,resizable,movable,per-window alpha). + +To edit and save a style, you can use the default ImGui example and append to the "Debug" window the following code: + ImGui::Text("\n"); + ImGui::Text("Please modify the current style in:"); + ImGui::Text("ImGui Test->Window Options->Style Editor"); + static bool loadCurrentStyle = false; + static bool saveCurrentStyle = false; + static bool resetCurrentStyle = false; + loadCurrentStyle = ImGui::Button("Load Saved Style"); + saveCurrentStyle = ImGui::Button("Save Current Style"); + resetCurrentStyle = ImGui::Button("Reset Current Style"); + if (loadCurrentStyle) { + if (!ImGuiLoadStyle("./myimgui.style",ImGui::GetStyle())) { + fprintf(stderr,"Warning: \"./myimgui.style\" not present.\n"); + } + } + if (saveCurrentStyle) { + if (!ImGuiSaveStyle("./myimgui.style",ImGui::GetStyle())) { + fprintf(stderr,"Warning: \"./myimgui.style\" cannot be saved.\n"); + } + } + if (resetCurrentStyle) ImGui::GetStyle() = ImGuiStyle(); +*/ + +#include + +// From :-------------------------------------------------------- +#include // vsnprintf +#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) +static size_t ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + int w = vsnprintf(buf, buf_size, fmt, args); + va_end(args); + buf[buf_size-1] = 0; + return (w == -1) ? buf_size : (size_t)w; +} +//--------------------------------------------------------------------------- + +#include + + + +bool ImGuiSaveStyle(const char* filename,const ImGuiStyle& style) +{ + // Write .style file + FILE* f = fopen(filename, "wt"); + if (!f) return false; + + fprintf(f, "[Alpha]\n%1.3f\n", style.Alpha); + fprintf(f, "[WindowPadding]\n%1.3f %1.3f\n", style.WindowPadding.x,style.WindowPadding.y); + fprintf(f, "[WindowMinSize]\n%1.3f %1.3f\n", style.WindowMinSize.x,style.WindowMinSize.y); + fprintf(f, "[FramePadding]\n%1.3f %1.3f\n", style.FramePadding.x,style.FramePadding.y); + fprintf(f, "[ItemSpacing]\n%1.3f %1.3f\n", style.ItemSpacing.x,style.ItemSpacing.y); + fprintf(f, "[ItemInnerSpacing]\n%1.3f %1.3f\n", style.ItemInnerSpacing.x,style.ItemInnerSpacing.y); + fprintf(f, "[TouchExtraPadding]\n%1.3f %1.3f\n", style.TouchExtraPadding.x,style.TouchExtraPadding.y); + fprintf(f, "[AutoFitPadding]\n%1.3f %1.3f\n", style.AutoFitPadding.x,style.AutoFitPadding.y); + fprintf(f, "[WindowFillAlphaDefault]\n%1.3f\n", style.WindowFillAlphaDefault); + fprintf(f, "[WindowRounding]\n%1.3f\n", style.WindowRounding); + fprintf(f, "[TreeNodeSpacing]\n%1.3f\n", style.TreeNodeSpacing); + fprintf(f, "[ColumnsMinSpacing]\n%1.3f\n", style.ColumnsMinSpacing); + fprintf(f, "[ScrollBarWidth]\n%1.3f\n", style.ScrollBarWidth); + + for (size_t i = 0; i != ImGuiCol_COUNT; i++) + { + const ImVec4& c = style.Colors[i]; + fprintf(f, "[%s]\n", ImGui::GetStyleColorName(i));//ImGuiColNames[i]); + fprintf(f, "%1.3f %1.3f %1.3f %1.3f\n",c.x,c.y,c.z,c.w); + } + + fprintf(f,"\n"); + fclose(f); + + return true; +} + +bool ImGuiLoadStyle(const char* filename,ImGuiStyle& style) +{ + // Load .style file + if (!filename) return false; + + // Load file into memory + FILE* f; + if ((f = fopen(filename, "rt")) == NULL) return false; + if (fseek(f, 0, SEEK_END)) { + fclose(f); + return false; + } + const long f_size_signed = ftell(f); + if (f_size_signed == -1) { + fclose(f); + return false; + } + size_t f_size = (size_t)f_size_signed; + if (fseek(f, 0, SEEK_SET)) { + fclose(f); + return false; + } + char* f_data = (char*)ImGui::MemAlloc(f_size+1); + f_size = fread(f_data, 1, f_size, f); // Text conversion alter read size so let's not be fussy about return value + fclose(f); + if (f_size == 0) { + ImGui::MemFree(f_data); + return false; + } + f_data[f_size] = 0; + + // Parse file in memory + char name[128];name[0]='\0'; + const char* buf_end = f_data + f_size; + for (const char* line_start = f_data; line_start < buf_end; ) + { + const char* line_end = line_start; + while (line_end < buf_end && *line_end != '\n' && *line_end != '\r') + line_end++; + + if (name[0]=='\0' && line_start[0] == '[' && line_end > line_start && line_end[-1] == ']') + { + ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", line_end-line_start-2, line_start+1); + //fprintf(stderr,"name: %s\n",name); // dbg + } + else if (name[0]!='\0') + { + + float *pf[4]= {0,0,0,0}; + int npf = 0; + + // parsing 'name' here by filling the fields above + { + if (strcmp(name, "Alpha")==0) {npf=1;pf[0]=&style.Alpha;} + else if (strcmp(name, "WindowPadding")==0) {npf=2;pf[0]=&style.WindowPadding.x;pf[1]=&style.WindowPadding.y;} + else if (strcmp(name, "WindowMinSize")==0) {npf=2;pf[0]=&style.WindowMinSize.x;pf[1]=&style.WindowMinSize.y;} + else if (strcmp(name, "FramePadding")==0) {npf=2;pf[0]=&style.FramePadding.x;pf[1]=&style.FramePadding.y;} + else if (strcmp(name, "ItemSpacing")==0) {npf=2;pf[0]=&style.ItemSpacing.x;pf[1]=&style.ItemSpacing.y;} + else if (strcmp(name, "ItemInnerSpacing")==0) {npf=2;pf[0]=&style.ItemInnerSpacing.x;pf[1]=&style.ItemInnerSpacing.y;} + else if (strcmp(name, "TouchExtraPadding")==0) {npf=2;pf[0]=&style.TouchExtraPadding.x;pf[1]=&style.TouchExtraPadding.y;} + else if (strcmp(name, "AutoFitPadding")==0) {npf=2;pf[0]=&style.AutoFitPadding.x;pf[1]=&style.AutoFitPadding.y;} + else if (strcmp(name, "WindowFillAlphaDefault")==0) {npf=1;pf[0]=&style.WindowFillAlphaDefault;} + else if (strcmp(name, "WindowRounding")==0) {npf=1;pf[0]=&style.WindowRounding;} + else if (strcmp(name, "TreeNodeSpacing")==0) {npf=1;pf[0]=&style.TreeNodeSpacing;} + else if (strcmp(name, "ColumnsMinSpacing")==0) {npf=1;pf[0]=&style.ColumnsMinSpacing;} + else if (strcmp(name, "ScrollBarWidth")==0) {npf=1;pf[0]=&style.ScrollBarWidth;} + // all the colors here + else { + for (int j=0;j to help parsing + float x, y; + int i; + if (sscanf(line_start, "Pos=%f,%f", &x, &y) == 2) + settings->Pos = ImVec2(x, y); + else if (sscanf(line_start, "Size=%f,%f", &x, &y) == 2) + settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize); + else if (sscanf(line_start, "Collapsed=%d", &i) == 1) + settings->Collapsed = (i != 0); + */ + //--------------------------------------------------------------------------------- + name[0]='\0'; // mandatory + } + + line_start = line_end+1; + } + + // Release memory + ImGui::MemFree(f_data); + return true; +} + diff --git a/examples/opengl_various_bindings/main.cpp b/examples/opengl_various_bindings/main.cpp new file mode 100644 index 000000000..522d61e53 --- /dev/null +++ b/examples/opengl_various_bindings/main.cpp @@ -0,0 +1,190 @@ +//#define IMIMPL_USE_GLEW + +// Only one of these is mandatory: +//#define IMIMPL_USE_GLFW3 +//#define IMIMPL_USE_GLUT +//#define IMIMPL_USE_SDL2 +//#define IMIMPL_USE_WINAPI // IMIMPL_USE_GLEW above might be mandatory here + + +// These are optional definitions that nobody will ever use (all undefined by default): +//#define IMIMPL_SHADER_NONE // no shaders at all, and no vertex buffer object as well (minimal implementation). +//#define IMIMPL_NUM_ROUND_ROBIN_VERTEX_BUFFERS // undefined (=default) => 1. Memory usage vs performance. When defined MUST BE A VALUE >=1. +//#define IMIMPL_SHADER_GL3 // shader uses openGL 3.3 (glsl #version 330) +//#define IMIMPL_SHADER_GLES // shader uses gles (and if IMIMPL_SHADER_GL3 is defined glsl #version 300 es) + +#ifdef IMIMPL_USE_GLFW3 +#include "ImImpl_Binding_Glfw3.h" +#elif defined(IMIMPL_USE_GLUT) +#include "ImImpl_Binding_Glut.h" +#elif defined(IMIMPL_USE_SDL2) +#include "ImImpl_Binding_SDL2.h" +#elif defined(IMIMPL_USE_WINAPI) +#include "ImImpl_Binding_WinAPI.h" +#endif + + +#define DEMO_CAN_LOAD_SAVE_STYLES // This definition needs imguistyleserializer.cpp to be compiled with the project too (no need to include anything) +#ifdef DEMO_CAN_LOAD_SAVE_STYLES +extern bool ImGuiSaveStyle(const char* filename,const ImGuiStyle& style); +extern bool ImGuiLoadStyle(const char* filename,ImGuiStyle& style); +#endif //DEMO_CAN_LOAD_SAVE_STYLES + +void InitGL() // Mandatory +{ + //fprintf(stderr,"InitGL();\n"); + //ImGui::GetIO().FontAllowUserScaling = true; +#ifdef DEMO_CAN_LOAD_SAVE_STYLES +if (!ImGuiLoadStyle("./myimgui.style",ImGui::GetStyle())) { + fprintf(stderr,"Warning: \"./myimgui.style\" not present.\n"); +} +#endif //DEMO_CAN_LOAD_SAVE_STYLES +} +void ResizeGL(int w,int h) // Mandatory +{ + //fprintf(stderr,"ResizeGL(%d,%d);\n",w,h); +} +void DrawGL() // Mandatory +{ + + glClearColor(0.8f, 0.6f, 0.6f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + static bool show_test_window = true; + static bool show_another_window = false; + + // 1. Show a simple window + { + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // Me: However I've discovered that when I clamp the FPS to a low value (e.g.10), I have to catch double clicks manually in my binding to make them work. + // They work, but for some strange reasons only with windows properly set up through ImGui::Begin(...) and ImGui::End(...) (and whose name is NOT 'Debug'). + // [Please remember that double clicking the titlebar of a window minimizes it] + // No problem with full frame rates. + static bool open = true; + ImGui::Begin("Debug ", &open, ImVec2(300,300)); // Try using 10 FPS and replacing the title with "Debug"... + + static float f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + show_test_window ^= ImGui::Button("Test Window"); + show_another_window ^= ImGui::Button("Another Window"); + + // Calculate and show framerate + static float ms_per_frame[120] = { 0 }; + static int ms_per_frame_idx = 0; + static float ms_per_frame_accum = 0.0f; + ms_per_frame_accum -= ms_per_frame[ms_per_frame_idx]; + ms_per_frame[ms_per_frame_idx] = ImGui::GetIO().DeltaTime * 1000.0f; + ms_per_frame_accum += ms_per_frame[ms_per_frame_idx]; + ms_per_frame_idx = (ms_per_frame_idx + 1) % 120; + const float ms_per_frame_avg = ms_per_frame_accum / 120; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg); + +# ifdef DEMO_CAN_LOAD_SAVE_STYLES + ImGui::Text("\n"); + ImGui::Text("Please modify the current style in:"); + ImGui::Text("ImGui Test->Window Options->Style Editor"); + static bool loadCurrentStyle = false; + static bool saveCurrentStyle = false; + static bool resetCurrentStyle = false; + loadCurrentStyle = ImGui::Button("Load Saved Style"); + saveCurrentStyle = ImGui::Button("Save Current Style"); + resetCurrentStyle = ImGui::Button("Reset Current Style"); + if (loadCurrentStyle) { + if (!ImGuiLoadStyle("./myimgui.style",ImGui::GetStyle())) { + fprintf(stderr,"Warning: \"./myimgui.style\" not present.\n"); + } + } + if (saveCurrentStyle) { + if (!ImGuiSaveStyle("./myimgui.style",ImGui::GetStyle())) { + fprintf(stderr,"Warning: \"./myimgui.style\" cannot be saved.\n"); + } + } + if (resetCurrentStyle) ImGui::GetStyle() = ImGuiStyle(); +# endif //DEMO_CAN_LOAD_SAVE_STYLES + + ImGui::End(); + } + + // 2. Show another simple window, this time using an explicit Begin/End pair + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100)); + ImGui::Text("Hello"); + ImGui::End(); + } + + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + if (show_test_window) + { + ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call this, because positions are saved in .ini file. Here we just want to make the demo initial state a bit more friendly! + ImGui::ShowTestWindow(&show_test_window); + } + +} +void DestroyGL() // Mandatory +{ +} + + + +// Application code +#ifndef IMIMPL_USE_WINAPI +int main(int argc, char** argv) +{ + // Basic + ImImpl_Main(NULL,argc,argv); + + // Advanced + /* + // These lines load an embedded font. [However these files are way too big... inside they used a better format storing bytes at groups of 4, so the files are more concise (1/4?) than mine] + const unsigned char fntMemory[] = +# include "./fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18.fnt.inl" + const unsigned char imgMemory[] = +# include "./fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18_0.png.inl" + + ImImpl_InitParams gImGuiInitParams( + -1,-1,NULL, // optional window width, height, title + NULL,//"./fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18.fnt", // optional custom font from file (main custom font) + NULL,//"./fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18_0.png", // optional custom font from file (main custom font) + -1,-1, // optional white spot in font texture (returned by the console if not set) + &fntMemory[0],sizeof(fntMemory)/sizeof(fntMemory[0]), // optional custom font from memory (secondary custom font) WARNING (licensing problem): e.g. embedding a GPL font in your code can make your code GPL as well. + &imgMemory[0],sizeof(imgMemory)/sizeof(imgMemory[0]) // optional custom font from memory (secondary custom font) WARNING (licensing problem): e.g. embedding a GPL font in your code can make your code GPL as well. + ); + gImGuiInitParams.gFpsClamp = 10.0f; // Optional Max allowed FPS (default -1 => unclamped). Useful for editors and to save GPU and CPU power. + ImImpl_Main(&gImGuiInitParams,argc,argv);*/ + + + return 0; +} +#else //IMIMPL_USE_WINAPI +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int iCmdShow) // This branch has made my code less concise (I will consider stripping it) +{ + // Basic + ImImpl_WinMain(NULL,hInstance,hPrevInstance,lpCmdLine,iCmdShow); + + // Advanced + /* + // These lines load an embedded font. [However these files are way too big... inside they used a better format storing bytes at groups of 4, so the files are more concise (1/4?) than mine] + const unsigned char fntMemory[] = +# include "./fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18.fnt.inl" + const unsigned char imgMemory[] = +# include "./fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18_0.png.inl" + + ImImpl_InitParams gImGuiInitParams( + -1,-1,NULL, // optional window width, height, title + NULL,//"./fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18.fnt", // optional custom font from file (main custom font) + NULL,//"./fonts/DejaVuSansCondensedBoldOutlineRGBAbinary18_0.png", // optional custom font from file (main custom font) + -1,-1, // optional white spot in font texture (returned by the console if not set) + &fntMemory[0],sizeof(fntMemory)/sizeof(fntMemory[0]), // optional custom font from memory (secondary custom font) WARNING (licensing problem): e.g. embedding a GPL font in your code can make your code GPL as well. + &imgMemory[0],sizeof(imgMemory)/sizeof(imgMemory[0]) // optional custom font from memory (secondary custom font) WARNING (licensing problem): e.g. embedding a GPL font in your code can make your code GPL as well. + ); + gImGuiInitParams.gFpsClamp = 10.0f; // Optional Max allowed FPS (default -1 => unclamped). Useful for editors and to save GPU and CPU power. + ImImpl_WinMain(&gImGuiInitParams,hInstance,hPrevInstance,lpCmdLine,iCmdShow);*/ + + return 0; +} +#endif //IMIMPL_USE_WINAPI + + + diff --git a/examples/opengl_various_bindings/stb_image.h b/examples/opengl_various_bindings/stb_image.h new file mode 100644 index 000000000..5ab9c58ec --- /dev/null +++ b/examples/opengl_various_bindings/stb_image.h @@ -0,0 +1,4744 @@ +/* stb_image - v1.46 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c + when you control the images you're loading + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + #define STBI_ASSERT(x) to avoid using assert.h. + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline (no JPEG progressive) + PNG 1/2/4/8-bit-per-channel (16 bpc not supported) + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) + + Latest revisions: + 1.xx (2014-09-26) 1/2/4-bit PNG support (both grayscale and paletted) + 1.46 (2014-08-26) fix broken tRNS chunk in non-paletted PNG + 1.45 (2014-08-16) workaround MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) warnings + 1.43 (2014-07-15) fix MSVC-only bug in 1.42 + 1.42 (2014-07-09) no _CRT_SECURE_NO_WARNINGS; error-path fixes; STBI_ASSERT + 1.41 (2014-06-25) fix search&replace that messed up comments/error messages + 1.40 (2014-06-22) gcc warning + 1.39 (2014-06-15) TGA optimization bugfix, multiple BMP fixes + 1.38 (2014-06-06) suppress MSVC run-time warnings, fix accidental rename of 'skip' + 1.37 (2014-06-04) remove duplicate typedef + 1.36 (2014-06-03) converted to header file, allow reading incorrect iphoned-images without iphone flag + 1.35 (2014-05-27) warnings, bugfixes, TGA optimization, etc + + See end of file for full revision history. + + TODO: + stbi_info support for BMP,PSD,HDR,PIC + + + ============================ Contributors ========================= + + Image formats Bug fixes & warning fixes + Sean Barrett (jpeg, png, bmp) Marc LeBlanc + Nicolas Schulz (hdr, psd) Christpher Lloyd + Jonathan Dummer (tga) Dave Moore + Jean-Marc Lienher (gif) Won Chun + Tom Seddon (pic) the Horde3D community + Thatcher Ulrich (psd) Janez Zemva + Jonathan Blow + Laurent Gomila + Extensions, features Aruelien Pocheville + Jetro Lauha (stbi_info) Ryamond Barbiero + James "moose2000" Brown (iPhone PNG) David Woo + Ben "Disch" Wenger (io callbacks) Roy Eltham + Martin "SpartanJ" Golini Luke Graham + Omar Cornut (1/2/4-bit png) Thomas Ruf + John Bartholomew + Optimizations & bugfixes Ken Hamada + Fabian "ryg" Giesen Cort Stratton + Arseny Kapoulkine Blazej Dariusz Roszkowski + Thibault Reuille + Paul Du Bois + Guillaume George + Jerry Jansson + If your name should be here but Hayaki Saito + isn't, let Sean know. Johan Duparc + Ronny Chevalier + Michal Cichon +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// Limitations: +// - no jpeg progressive support +// - non-HDR formats support 8-bit samples only (jpeg, png) +// - no delayed line count (jpeg) -- IJG doesn't support either +// - no 1-bit BMP +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *comp -- outputs # of image components in image file +// int req_comp -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. +// If req_comp is non-zero, *comp has the number of components that _would_ +// have been output otherwise. E.g. if you set req_comp to 4, you will always +// get RGBA output, but you can check *comp to easily see if it's opaque. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *comp will be unchanged. The function stbi_failure_reason() +// can be queried for an extremely brief, end-user unfriendly explanation +// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid +// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB; nominally they +// would silently load as BGR, except the existing code should have just +// failed on such iPhone PNGs. But you can disable this conversion by +// by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through. +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image now supports loading HDR images in general, and currently +// the Radiance .HDR file format, although the support is provided +// generically. You can still load any file through the existing interface; +// if you attempt to load an HDR file, it will be automatically remapped to +// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). + + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for req_comp + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +typedef unsigned char stbi_uc; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +STBIDEF stbi_uc *stbi_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + +#ifndef STBI_NO_HDR + STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + #endif + + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); + + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_HDR + +// stbi_is_hdr is always defined +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); + +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +// define faster low-level operations (typically SIMD support) +#ifdef STBI_SIMD +typedef void (*stbi_idct_8x8)(stbi_uc *out, int out_stride, short data[64], unsigned short *dequantize); +// compute an integer IDCT on "input" +// input[x] = data[x] * dequantize[x] +// write results to 'out': 64 samples, each run of 8 spaced by 'out_stride' +// CLAMP results to 0..255 +typedef void (*stbi_YCbCr_to_RGB_run)(stbi_uc *output, stbi_uc const *y, stbi_uc const *cb, stbi_uc const *cr, int count, int step); +// compute a conversion from YCbCr to RGB +// 'count' pixels +// write pixels to 'output'; each pixel is 'step' bytes (either 3 or 4; if 4, write '255' as 4th), order R,G,B +// y: Y input channel +// cb: Cb input channel; scale/biased to be 0..255 +// cr: Cr input channel; scale/biased to be 0..255 + +STBIDEF void stbi_install_idct(stbi_idct_8x8 func); +STBIDEF void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func); +#endif // STBI_SIMD + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#ifndef STBI_NO_HDR +#include // ldexp +#include // strcmp, strtok +#endif + +#ifndef STBI_NO_STDIO +#include +#endif +#include +#include +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif +#include +#include // ptrdiff_t on osx + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; +} + +static int stbi__jpeg_test(stbi__context *s); +static stbi_uc *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_test(stbi__context *s); +static stbi_uc *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__bmp_test(stbi__context *s); +static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__tga_test(stbi__context *s); +static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_test(stbi__context *s); +static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +#endif +static int stbi__pic_test(stbi__context *s); +static stbi_uc *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__gif_test(stbi__context *s); +static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); + + +// this is not threadsafe +static const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +static void *stbi__malloc(size_t size) +{ + return malloc(size); +} + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + free(retval_from_stbi_load); +} + +#ifndef STBI_NO_HDR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp); + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp); + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp); + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp); + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_STDIO + +FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF unsigned char *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi_load_main(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} +#endif //!STBI_NO_STDIO + +STBIDEF unsigned char *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi_load_main(&s,x,y,comp,req_comp); +} + +unsigned char *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_load_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_HDR + +float *stbi_loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) + return stbi__hdr_load(s,x,y,comp,req_comp); + #endif + data = stbi_load_main(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} + +float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_HDR + +// these is-hdr-or-not is defined independent of whether STBI_NO_HDR is +// defined, for API simplicity; if STBI_NO_HDR is defined, it always +// reports false! + +int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_file(&s,f); + return stbi__hdr_test(&s); + #else + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + return 0; + #endif +} + +#ifndef STBI_NO_HDR +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + +void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + SCAN_load=0, + SCAN_type, + SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} + +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + return z + (stbi__get16le(s) << 16); +} + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc(req_comp * x * y); + if (good == NULL) { + free(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define COMBO(a,b) ((a)*8+(b)) + #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (COMBO(img_n, req_comp)) { + CASE(1,2) dest[0]=src[0], dest[1]=255; break; + CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; + CASE(2,1) dest[0]=src[0]; break; + CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; + CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; + CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; + CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break; + CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; + CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; + CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + default: STBI_ASSERT(0); + } + #undef CASE + } + + free(data); + return good; +} + +#ifndef STBI_NO_HDR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output = (float *) stbi__malloc(x * y * comp * sizeof(float)); + if (output == NULL) { free(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; + } + free(data); + return output; +} + +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp); + if (output == NULL) { free(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + free(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder (not actually fully baseline implementation) +// +// simple implementation +// - channel subsampling of at most 2 in each dimension +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - uses a lot of intermediate memory, could cache poorly +// - load http://nothings.org/remote/anemones.jpg 3 times on 2.8Ghz P4 +// stb_jpeg: 1.34 seconds (MSVC6, default release build) +// stb_jpeg: 1.06 seconds (MSVC6, processor = Pentium Pro) +// IJL11.dll: 1.08 seconds (compiled by intel) +// IJG 1998: 0.98 seconds (MSVC6, makefile provided by IJG) +// IJG 1998: 0.95 seconds (MSVC6, makefile + proc=PPro) + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + #ifdef STBI_SIMD + unsigned short dequant2[4][64]; + #endif + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi_uc dequant[4][64]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data; + stbi_uc *linebuf; + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int scan_n, order[4]; + int restart_interval, todo; +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0,code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1 << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// combined JPEG 'receive' and JPEG 'extend', since baseline +// always extends everything it receives. +stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n) +{ + unsigned int m = 1 << (n-1); + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + + #if 1 + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + #else + k = (j->code_buffer >> (32 - n)) & stbi__bmask[n]; + j->code_bits -= n; + j->code_buffer <<= n; + #endif + // the following test is probably a random branch that won't + // predict well. I tried to table accelerate it but failed. + // maybe it's compiling as a conditional move? + if (k < m) + return (-1 << n) + k + 1; + else + return k; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, int b) +{ + int diff,dc,k; + int t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) dc; + + // decode AC components, see JPEG spec + k = 1; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + data[stbi__jpeg_dezigzag[k++]] = (short) stbi__extend_receive(j,s); + } + } while (k < 64); + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) (int) (((x) * 4096 + 0.5)) +#define stbi__fsh(x) ((x) << 12) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +#ifdef STBI_SIMD +typedef unsigned short stbi_dequantize_t; +#else +typedef stbi_uc stbi_dequantize_t; +#endif + +// .344 seconds on 3*anemones.jpg +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64], stbi_dequantize_t *dequantize) +{ + int i,val[64],*v=val; + stbi_dequantize_t *dq = dequantize; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d,++dq, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0] * dq[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24], + d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SIMD +static stbi_idct_8x8 stbi__idct_installed = stbi__idct_block; + +STBIDEF void stbi_install_idct(stbi_idct_8x8 func) +{ + stbi__idct_installed = func; +} +#endif + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (z->scan_n == 1) { + int i,j; + #ifdef STBI_SIMD + __declspec(align(16)) + #endif + short data[64]; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; + #ifdef STBI_SIMD + stbi__idct_installed(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); + #else + stbi__idct_block(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); + #endif + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + } else { // interleaved! + int i,j,k,x,y; + short data[64]; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; + #ifdef STBI_SIMD + stbi__idct_installed(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); + #else + stbi__idct_block(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); + #endif + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + } + return 1; +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xC2: // stbi__SOF - progressive + return stbi__err("progressive jpeg","JPEG format not supported (progressive)"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4; + int t = q & 15,i; + if (p != 0) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = stbi__get8(z->s); + #ifdef STBI_SIMD + for (i=0; i < 64; ++i) + z->dequant2[t][i] = z->dequant[t][i]; + #endif + L -= 65; + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + L -= n; + } + return L==0; + } + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + stbi__skip(z->s, stbi__get16be(z->s)-2); + return 1; + } + return 0; +} + +// after we see stbi__SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad stbi__SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad stbi__SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + if (stbi__get8(z->s) != 0) return stbi__err("bad stbi__SOS","Corrupt JPEG"); + stbi__get8(z->s); // should be 63, but might be 0 + if (stbi__get8(z->s) != 0) return stbi__err("bad stbi__SOS","Corrupt JPEG"); + + return 1; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad stbi__SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + c = stbi__get8(s); + if (c != 3 && c != 1) return stbi__err("bad component count","Corrupt JPEG"); // JFIF requires + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad stbi__SOF len","Corrupt JPEG"); + + for (i=0; i < s->img_n; ++i) { + z->img_comp[i].id = stbi__get8(s); + if (z->img_comp[i].id != i+1) // JFIF requires + if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! + return stbi__err("bad component ID","Corrupt JPEG"); + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != SCAN_load) return 1; + + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); + if (z->img_comp[i].raw_data == NULL) { + for(--i; i >= 0; --i) { + free(z->img_comp[i].raw_data); + z->img_comp[i].data = NULL; + } + return stbi__err("outofmem", "Out of memory"); + } + // align blocks for installable-idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + z->img_comp[i].linebuf = NULL; + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. stbi__SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1) +#define stbi__SOS(x) ((x) == 0xda) + +static int decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no stbi__SOI","Corrupt JPEG"); + if (scan == SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no stbi__SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +static int decode_jpeg_image(stbi__jpeg *j) +{ + int m; + j->restart_interval = 0; + if (!decode_jpeg_header(j, SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } else if (x != 0) { + return 0; + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) + +// 0.38 seconds on 3*anemones.jpg (0.25 with processor = Pro) +// VC6 without processor=Pro is generating multiple LEAs per multiply! +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 16) + 32768; // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr*float2fixed(1.40200f); + g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); + b = y_fixed + cb*float2fixed(1.77200f); + r >>= 16; + g >>= 16; + b >>= 16; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#ifdef STBI_SIMD +static stbi_YCbCr_to_RGB_run stbi__YCbCr_installed = stbi__YCbCr_to_RGB_row; + +STBIDEF void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func) +{ + stbi__YCbCr_installed = func; +} +#endif + + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + int i; + for (i=0; i < j->s->img_n; ++i) { + if (j->img_comp[i].raw_data) { + free(j->img_comp[i].raw_data); + j->img_comp[i].raw_data = NULL; + j->img_comp[i].data = NULL; + } + if (j->img_comp[i].linebuf) { + free(j->img_comp[i].linebuf); + j->img_comp[i].linebuf = NULL; + } + } +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source + if (!decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n; + + if (z->s->img_n == 3 && n < 3) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4]; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = stbi__resample_row_hv_2; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + #ifdef STBI_SIMD + stbi__YCbCr_installed(out, y, coutput[1], coutput[2], z->s->img_x, n); + #else + stbi__YCbCr_to_RGB_row(out, y, coutput[1], coutput[2], z->s->img_x, n); + #endif + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n; // report original components, not output + return output; + } +} + +static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__jpeg j; + j.s = s; + return load_jpeg_image(&j, x,y,comp,req_comp); +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg j; + j.s = s; + r = decode_jpeg_header(&j, SCAN_type); + stbi__rewind(s); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!decode_jpeg_header(j, SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__jpeg j; + j.s = s; + return stbi__jpeg_info_raw(&j, x, y, comp); +} + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 255, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + STBI_ASSERT(sizes[i] <= (1 << i)); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt JPEG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int k = stbi__bit_reverse(next_code[s],s); + while (k < (1 << STBI__ZFAST_BITS)) { + z->fast[k] = (stbi__uint16) c; + k += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b < 0xffff) { + s = z->size[b]; + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; + } + + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +static int stbi__zexpand(stbi__zbuf *z, int n) // need to make room for n bytes +{ + char *q; + int cur, limit; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) realloc(z->zout_start, limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (a->zout >= a->zout_end) if (!stbi__zexpand(a, 1)) return 0; + *a->zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) return 1; + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (a->zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (a->zout + len > a->zout_end) if (!stbi__zexpand(a, len)) return 0; + p = (stbi_uc *) (a->zout - dist); + while (len--) + *a->zout++ = *p++; + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < hlit + hdist) { + int c = stbi__zhuffman_decode(a, &z_codelength); + STBI_ASSERT(c >= 0 && c < 19); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else if (c == 16) { + c = stbi__zreceive(a,2)+3; + memset(lencodes+n, lencodes[n-1], c); + n += c; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + memset(lencodes+n, 0, c); + n += c; + } else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + memset(lencodes+n, 0, c); + n += c; + } + } + if (n != hlit+hdist) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncomperssed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +// @TODO: should statically initialize these for optimal thread safety +static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32]; +static void stbi__init_zdefaults(void) +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncomperssed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zdefault_distance[31]) stbi__init_zdefaults(); + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + + +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +#define PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; +} stbi__png; + + +enum { + STBI__F_none=0, STBI__F_sub=1, STBI__F_up=2, STBI__F_avg=3, STBI__F_paeth=4, + STBI__F_avg_first, STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, STBI__F_sub, STBI__F_none, STBI__F_avg_first, STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n; + stbi__uint32 img_len; + int k; + int img_n = s->img_n; // copy it into a local for later + stbi_uc* line8 = NULL; // point into raw when depth==8 else temporary local buffer + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc(x * y * out_n); + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + img_len = ((((img_n * x * depth) + 7) >> 3) + 1) * y; + if (s->img_x == x && s->img_y == y) { + if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG"); + } else { // interlaced: + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + } + + if (depth != 8) { + line8 = (stbi_uc *) stbi__malloc((x+7) * out_n); // allocate buffer for one scanline + if (!line8) return stbi__err("outofmem", "Out of memory"); + } + + for (j=0; j < y; ++j) { + stbi_uc *in; + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior = cur - stride; + int filter = *raw++; + if (filter > 4) { + if (depth != 8) free(line8); + return stbi__err("invalid filter","Corrupt PNG"); + } + + if (depth == 8) { + in = raw; + raw += x*img_n; + } + else { + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + in = line8; + stbi_uc* decode_out = line8; + stbi_uc scale = (color == 0) ? 0xFF/((1<= 1; k-=2, raw++) { + *decode_out++ = scale * ((*raw >> 4) ); + *decode_out++ = scale * ((*raw ) & 0x0f); + } + } else if (depth == 2) { + for (k=x*img_n; k >= 1; k-=4, raw++) { + *decode_out++ = scale * ((*raw >> 6) ); + *decode_out++ = scale * ((*raw >> 4) & 0x03); + *decode_out++ = scale * ((*raw >> 2) & 0x03); + *decode_out++ = scale * ((*raw ) & 0x03); + } + } else if (depth == 1) { + for (k=x*img_n; k >= 1; k-=8, raw++) { + *decode_out++ = scale * ((*raw >> 7) ); + *decode_out++ = scale * ((*raw >> 6) & 0x01); + *decode_out++ = scale * ((*raw >> 5) & 0x01); + *decode_out++ = scale * ((*raw >> 4) & 0x01); + *decode_out++ = scale * ((*raw >> 3) & 0x01); + *decode_out++ = scale * ((*raw >> 2) & 0x01); + *decode_out++ = scale * ((*raw >> 1) & 0x01); + *decode_out++ = scale * ((*raw ) & 0x01); + } + } + } + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first pixel explicitly + for (k=0; k < img_n; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = in[k]; break; + case STBI__F_sub : cur[k] = in[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(in[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(in[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = in[k]; break; + case STBI__F_paeth_first: cur[k] = in[k]; break; + } + } + if (img_n != out_n) cur[img_n] = 255; + in += img_n; + cur += out_n; + prior += out_n; + // this is a little gross, so that we don't switch per-pixel or per-component + if (img_n == out_n) { + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, in+=img_n,cur+=img_n,prior+=img_n) \ + for (k=0; k < img_n; ++k) + switch (filter) { + CASE(STBI__F_none) cur[k] = in[k]; break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(in[k] + cur[k-img_n]); break; + CASE(STBI__F_up) cur[k] = STBI__BYTECAST(in[k] + prior[k]); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(in[k] + ((prior[k] + cur[k-img_n])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(cur[k-img_n],prior[k],prior[k-img_n])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(in[k] + (cur[k-img_n] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(cur[k-img_n],0,0)); break; + } + #undef CASE + } else { + STBI_ASSERT(img_n+1 == out_n); + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[img_n]=255,in+=img_n,cur+=out_n,prior+=out_n) \ + for (k=0; k < img_n; ++k) + switch (filter) { + CASE(STBI__F_none) cur[k] = in[k]; break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(in[k] + cur[k-out_n]); break; + CASE(STBI__F_up) cur[k] = STBI__BYTECAST(in[k] + prior[k]); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(in[k] + ((prior[k] + cur[k-out_n])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(in[k] + (cur[k-out_n] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(cur[k-out_n],0,0)); break; + } + #undef CASE + } + } + + if (depth != 8) free(line8); + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, int depth, int color, int interlaced) +{ + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((out_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, raw, raw_len, out_n, x, y, depth, color)) { + free(final); + return 0; + } + for (j=0; j < y; ++j) + for (i=0; i < x; ++i) + memcpy(final + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n, + a->out + (j*x+i)*out_n, out_n); + free(a->out); + raw += img_len; + raw_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + free(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + p[0] = p[2] * 255 / a; + p[1] = p[1] * 255 / a; + p[2] = t * 255 / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, depth=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + for (k=0; k < s->img_n; ++k) + tc[k] = (stbi_uc) (stbi__get16be(s) & 255); // non 8-bit images will be larger + } + break; + } + + case PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == SCAN_header) { s->img_n = pal_img_n; return 1; } + if (ioff + c.length > idata_limit) { + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + p = (stbi_uc *) realloc(z->idata, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, 16384, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + free(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0; + if (has_trans) + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } + free(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp) +{ + unsigned char *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, SCAN_load, req_comp)) { + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + result = stbi__convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_out_n; + } + free(p->out); p->out = NULL; + free(p->expanded); p->expanded = NULL; + free(p->idata); p->idata = NULL; + + return result; +} + +static unsigned char *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +// Microsoft/Windows BMP image +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +static int stbi__shiftsigned(int v, int shift, int bits) +{ + int result; + int z=0; + + if (shift < 0) v <<= -shift; + else v >>= shift; + result = v; + + z = bits; + while (z < 8) { + result += v >> z; + z += bits; + } + return result; +} + +static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, fake_a=0; + stbi_uc pal[256][4]; + int psize=0,i,j,compress=0,width; + int bpp, flip_vertically, pad, target, offset, hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + offset = stbi__get32le(s); + hsz = stbi__get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + bpp = stbi__get16le(s); + if (bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit"); + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + if (hsz == 12) { + if (bpp < 24) + psize = (offset - 14 - 24) / 3; + } else { + compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (bpp == 16 || bpp == 32) { + mr = mg = mb = 0; + if (compress == 0) { + if (bpp == 32) { + mr = 0xffu << 16; + mg = 0xffu << 8; + mb = 0xffu << 0; + ma = 0xffu << 24; + fake_a = 1; // @TODO: check for cases like alpha value is all 0 and switch it to 255 + STBI_NOTUSED(fake_a); + } else { + mr = 31u << 10; + mg = 31u << 5; + mb = 31u << 0; + } + } else if (compress == 3) { + mr = stbi__get32le(s); + mg = stbi__get32le(s); + mb = stbi__get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (mr == mg && mg == mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + STBI_ASSERT(hsz == 108 || hsz == 124); + mr = stbi__get32le(s); + mg = stbi__get32le(s); + mb = stbi__get32le(s); + ma = stbi__get32le(s); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + if (bpp < 16) + psize = (offset - 14 - hsz) >> 2; + } + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { free(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4)); + if (bpp == 4) width = (s->img_x + 1) >> 1; + else if (bpp == 8) width = s->img_x; + else { free(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, offset - 14 - hsz); + if (bpp == 24) width = 3 * s->img_x; + else if (bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (bpp == 24) { + easy = 1; + } else if (bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { free(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + if (target == 4) out[z++] = a; + } + } else { + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (stbi__uint32) (bpp == 16 ? stbi__get16le(s) : stbi__get32le(s)); + int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} + +// Targa Truevision - TGA +// by Jonathan Dummer + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp; + int sz; + stbi__get8(s); // discard Offset + sz = stbi__get8(s); // color type + if( sz > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + sz = stbi__get8(s); // image type + // only RGB or grey allowed, +/- RLE + if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0; + stbi__skip(s,9); + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + sz = stbi__get8(s); // bits per pixel + // only RGB or RGBA or grey allowed + if ((sz != 8) && (sz != 16) && (sz != 24) && (sz != 32)) { + stbi__rewind(s); + return 0; + } + tga_comp = sz; + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp / 8; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res; + int sz; + stbi__get8(s); // discard Offset + sz = stbi__get8(s); // color type + if ( sz > 1 ) return 0; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE + stbi__get16be(s); // discard palette start + stbi__get16be(s); // discard palette length + stbi__get8(s); // discard bits per palette color entry + stbi__get16be(s); // discard x origin + stbi__get16be(s); // discard y origin + if ( stbi__get16be(s) < 1 ) return 0; // test width + if ( stbi__get16be(s) < 1 ) return 0; // test height + sz = stbi__get8(s); // bits per pixel + if ( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) ) + res = 0; + else + res = 1; + stbi__rewind(s); + return res; +} + +static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp = tga_bits_per_pixel / 8; + int tga_inverted = stbi__get8(s); + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4]; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + /* int tga_alpha_bits = tga_inverted & 15; */ + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // error check + if ( //(tga_indexed) || + (tga_width < 1) || (tga_height < 1) || + (tga_image_type < 1) || (tga_image_type > 3) || + ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) && + (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) + ) + { + return NULL; // we don't report this as a bad TGA because we don't even know if it's TGA + } + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) + { + tga_comp = tga_palette_bits / 8; + } + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + tga_data = (unsigned char*)stbi__malloc( tga_width * tga_height * tga_comp ); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE) { + for (i=0; i < tga_height; ++i) { + int y = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + y*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_palette_bits / 8 ); + if (!tga_palette) { + free(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (!stbi__getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) { + free(tga_data); + free(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in 1 byte, then perform the lookup + int pal_idx = stbi__get8(s); + if ( pal_idx >= tga_palette_len ) + { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_bits_per_pixel / 8; + for (j = 0; j*8 < tga_bits_per_pixel; ++j) + { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else + { + // read in the data raw + for (j = 0; j*8 < tga_bits_per_pixel; ++j) + { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + free( tga_palette ); + } + } + + // swap RGB + if (tga_comp >= 3) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + int pixelCount; + int channelCount, compression; + int channel, i, count, len; + int w,h; + stbi_uc *out; + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + // Make sure the depth is 8 bits. + if (stbi__get16be(s) != 8) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Create the destination image. + out = (stbi_uc *) stbi__malloc(4 * w*h); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++) *p = (channel == 3 ? 255 : 0), p += 4; + } else { + // Read the RLE data. + count = 0; + while (count < pixelCount) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len ^= 0x0FF; + len += 2; + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out + channel; + if (channel > channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++) *p = channel == 3 ? 255 : 0, p += 4; + } else { + // Read the data. + for (i = 0; i < pixelCount; i++) + *p = stbi__get8(s), p += 4; + } + } + } + + if (req_comp && req_comp != 4) { + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = channelCount; + *y = h; + *x = w; + + return out; +} + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + int i; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp) +{ + stbi_uc *result; + int i, x,y; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if ((1 << 28) / x < y) return stbi__errpuc("too large", "Image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc(x*y*4); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + free(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[4096]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif g; + if (!stbi__gif_header(s, &g, comp, 1)) { + stbi__rewind( s ); + return 0; + } + if (x) *x = g.w; + if (y) *y = g.h; + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + p = &g->out[g->cur_x + g->cur_y]; + c = &g->color_table[g->codes[code].suffix * 4]; + + if (c[3] >= 128) { + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (code = 0; code < clear; code++) { + g->codes[code].prefix = -1; + g->codes[code].first = (stbi_uc) code; + g->codes[code].suffix = (stbi_uc) code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) return stbi__errpuc("no clear code", "Corrupt GIF"); + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 4096) return stbi__errpuc("too many codes", "Corrupt GIF"); + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +static void stbi__fill_gif_background(stbi__gif *g) +{ + int i; + stbi_uc *c = g->pal[g->bgindex]; + // @OPTIMIZE: write a dword at a time + for (i = 0; i < g->w * g->h * 4; i += 4) { + stbi_uc *p = &g->out[i]; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp) +{ + int i; + stbi_uc *old_out = 0; + + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + stbi__fill_gif_background(g); + } else { + // animated-gif-only path + if (((g->eflags & 0x1C) >> 2) == 3) { + old_out = g->out; + g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + memcpy(g->out, old_out, g->w*g->h*4); + } + } + + for (;;) { + switch (stbi__get8(s)) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + for (i=0; i < 256; ++i) // @OPTIMIZE: stbi__jpeg_reset only the previous transparent + g->pal[i][3] = 255; + if (g->transparent >= 0 && (g->eflags & 0x01)) + g->pal[g->transparent][3] = 0; + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (o == NULL) return NULL; + + if (req_comp && req_comp != 4) + o = stbi__convert_format(o, 4, req_comp, g->w, g->h); + return o; + } + + case 0x21: // Comment Extension. + { + int len; + if (stbi__get8(s) == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + stbi__get16le(s); // delay + g->transparent = stbi__get8(s); + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) + stbi__skip(s, len); + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + + u = stbi__gif_load_next(s, &g, comp, req_comp); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + } + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} + + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s) +{ + const char *signature = "#?RADIANCE\n"; + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s); + stbi__rewind(s); + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + + + // Check identifier + if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + // Read data + hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float)); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + free(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { free(hdr_data); free(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4); + + for (k = 0; k < 4; ++k) { + i = 0; + while (i < width) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + free(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + + if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') { + stbi__rewind( s ); + return 0; + } + stbi__skip(s,12); + hsz = stbi__get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) { + stbi__rewind( s ); + return 0; + } + if (hsz == 12) { + *x = stbi__get16le(s); + *y = stbi__get16le(s); + } else { + *x = stbi__get32le(s); + *y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) { + stbi__rewind( s ); + return 0; + } + *comp = stbi__get16le(s) / 8; + return 1; +} + +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + if (stbi__get16be(s) != 8) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained; + stbi__pic_packet packets[10]; + + stbi__skip(s, 92); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) return 0; + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + if (stbi__jpeg_info(s, x, y, comp)) + return 1; + if (stbi__png_info(s, x, y, comp)) + return 1; + if (stbi__gif_info(s, x, y, comp)) + return 1; + if (stbi__bmp_info(s, x, y, comp)) + return 1; + if (stbi__psd_info(s, x, y, comp)) + return 1; + if (stbi__pic_info(s, x, y, comp)) + return 1; + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) + return 1; + #endif + // test tga last because it's a crappy test! + if (stbi__tga_info(s, x, y, comp)) + return 1; + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 2008-08-02 + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 first released version +*/