mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-15 17:23:13 +02:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
7751ce0a69 | |||
9bb95db68a | |||
0a8acf241c | |||
c388c7e6eb | |||
088df3d1ba | |||
09fae1c209 | |||
016dbb7472 | |||
6ec65c46aa | |||
0fa3d6e25f | |||
f898e658bb | |||
22fe7f23b1 | |||
b756510f21 | |||
b6ac371496 | |||
81b9480413 | |||
b9d9f62ae3 | |||
4b94454fb4 | |||
b86505bf2f | |||
df1c056c88 | |||
eb1b9d4521 | |||
d35ceb793e | |||
a61b92f362 | |||
51bbe1d961 | |||
e4d4dae3bf | |||
bd3c53754d | |||
a1162ac001 |
11
README.md
11
README.md
@ -1,9 +1,9 @@
|
|||||||
ImGui
|
ImGui
|
||||||
=====
|
=====
|
||||||
|
|
||||||
ImGui is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is portable, renderer agnostic and carries minimal amount of dependencies (only 3 files are needed). It is based on an "immediate" graphical user interface paradigm which allows you to build simple user interfaces with ease.
|
ImGui is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is portable, renderer agnostic and carries minimal amount of dependencies (only 3 files are needed). It is based on an "immediate" graphical user interface paradigm which allows you to build user interfaces with ease.
|
||||||
|
|
||||||
ImGui is designed to enable fast iteration and allow programmers to create "content creation" or "debug" tools (as opposed to tools for the average end-user). It favors simplicity and thus lacks certain features normally found in more high-level libraries, such as string localisation.
|
ImGui is designed to enable fast iteration and allow programmers to create "content creation" or "debug" tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries
|
||||||
|
|
||||||
ImGui is particularly suited to integration in 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard.
|
ImGui is particularly suited to integration in 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard.
|
||||||
|
|
||||||
@ -23,6 +23,10 @@ Gallery
|
|||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
UTF-8 is supported for text display and input. Here using M+ font to display Japanese:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
References
|
References
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@ -63,7 +67,8 @@ Credits
|
|||||||
|
|
||||||
Developed by [Omar Cornut](http://www.miracleworld.net). The library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com).
|
Developed by [Omar Cornut](http://www.miracleworld.net). The library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com).
|
||||||
|
|
||||||
Embeds [proggy_clean](http://upperbounds.net) font by Tristan Grimmer (also MIT license).
|
Embeds [proggy_clean](http://upperbounds.net) font by Tristan Grimmer (MIT license).
|
||||||
|
Embeds [M+ fonts](http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html) font by Coji Morishita (free software license).
|
||||||
|
|
||||||
Inspiration, feedback, and testing: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Thanks!
|
Inspiration, feedback, and testing: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Thanks!
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;winmm.lib;comctl32.lib;gdi32.lib;user32.lib</AdditionalDependencies>
|
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;winmm.lib;comctl32.lib;gdi32.lib;imm32.lib;user32.lib</AdditionalDependencies>
|
||||||
<SubSystem>
|
<SubSystem>
|
||||||
</SubSystem>
|
</SubSystem>
|
||||||
</Link>
|
</Link>
|
||||||
@ -64,7 +64,7 @@
|
|||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;winmm.lib;comctl32.lib;gdi32.lib;user32.lib</AdditionalDependencies>
|
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;winmm.lib;comctl32.lib;gdi32.lib;imm32.lib;user32.lib</AdditionalDependencies>
|
||||||
<SubSystem>
|
<SubSystem>
|
||||||
</SubSystem>
|
</SubSystem>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <imm.h>
|
||||||
#include <mmsystem.h>
|
#include <mmsystem.h>
|
||||||
#include <d3dx9.h>
|
#include <d3dx9.h>
|
||||||
#define DIRECTINPUT_VERSION 0x0800
|
#define DIRECTINPUT_VERSION 0x0800
|
||||||
@ -163,8 +164,8 @@ LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||||||
return true;
|
return true;
|
||||||
case WM_CHAR:
|
case WM_CHAR:
|
||||||
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||||
if (wParam > 1 && wParam < 256)
|
if (wParam > 0 && wParam < 0x10000)
|
||||||
io.AddInputCharacter((char)wParam);
|
io.AddInputCharacter((unsigned short)wParam);
|
||||||
return true;
|
return true;
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
{
|
{
|
||||||
@ -176,6 +177,19 @@ LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
if (HIMC himc = ImmGetContext(hWnd))
|
||||||
|
{
|
||||||
|
COMPOSITIONFORM cf;
|
||||||
|
cf.ptCurrentPos.x = x;
|
||||||
|
cf.ptCurrentPos.y = y;
|
||||||
|
cf.dwStyle = CFS_FORCE_POSITION;
|
||||||
|
ImmSetCompositionWindow(himc, &cf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void InitImGui()
|
void InitImGui()
|
||||||
{
|
{
|
||||||
RECT rect;
|
RECT rect;
|
||||||
@ -204,6 +218,7 @@ void InitImGui()
|
|||||||
io.KeyMap[ImGuiKey_Z] = 'Z';
|
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||||
|
|
||||||
io.RenderDrawListsFn = ImImpl_RenderDrawLists;
|
io.RenderDrawListsFn = ImImpl_RenderDrawLists;
|
||||||
|
io.ImeSetInputScreenPosFn = ImImpl_ImeSetInputScreenPosFn;
|
||||||
|
|
||||||
// Create the vertex buffer
|
// Create the vertex buffer
|
||||||
if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
|
if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
|
||||||
|
53
examples/opengl_example/Makefile
Normal file
53
examples/opengl_example/Makefile
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#
|
||||||
|
# Cross Platform Make file
|
||||||
|
#
|
||||||
|
# Compatible with Ubuntu 14.04.1 and Mac OS X
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# if you using Mac OS X:
|
||||||
|
# You should install glew via homebrew
|
||||||
|
# brew install glew
|
||||||
|
# Also you'll need glfw
|
||||||
|
# http://www.glfw.org
|
||||||
|
#
|
||||||
|
|
||||||
|
CXX = g++
|
||||||
|
|
||||||
|
OBJS = main.o
|
||||||
|
OBJS += ../../imgui.o
|
||||||
|
|
||||||
|
UNAME_S := $(shell uname -s)
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(UNAME_S), Linux) #LINUX
|
||||||
|
ECHO_MESSAGE = "Linux"
|
||||||
|
CXXFLAGS = -I../../ `pkg-config --cflags glfw3`
|
||||||
|
LIBS = `pkg-config --static --libs glfw3` -lGLEW
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(UNAME_S), Darwin) #APPLE
|
||||||
|
ECHO_MESSAGE = "Mac OS X"
|
||||||
|
|
||||||
|
LIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
|
||||||
|
LIBS += -L/usr/local/Cellar/glew/1.10.0/lib -L/usr/local/lib
|
||||||
|
LIBS += -lglew -lglfw3
|
||||||
|
|
||||||
|
CXXFLAGS = -I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/include
|
||||||
|
CXXFLAGS += -I../../
|
||||||
|
|
||||||
|
# CXXFLAGS += -D__APPLE__
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
all:imgui_example
|
||||||
|
@echo Build complete for $(ECHO_MESSAGE)
|
||||||
|
|
||||||
|
imgui_example:$(OBJS)
|
||||||
|
$(CXX) -o imgui_example $(OBJS) $(CXXFLAGS) $(LIBS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm $(OBJS)
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
#
|
|
||||||
# Quick and dirty makefile to build on Linux
|
|
||||||
# tested on Ubuntu 14.04.1 32bit
|
|
||||||
#
|
|
||||||
|
|
||||||
SRC = main.cpp ../../imgui.cpp
|
|
||||||
|
|
||||||
OBJ = $(SRC:.cpp=.o)
|
|
||||||
|
|
||||||
CXXFLAGS = -I../../ `pkg-config --cflags glfw3`
|
|
||||||
|
|
||||||
LIBS = `pkg-config --static --libs glfw3` -lGLEW
|
|
||||||
|
|
||||||
all: $(OBJ)
|
|
||||||
$(CXX) $(OBJ) $(LIBS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) -f $(OBJ)
|
|
@ -1,18 +0,0 @@
|
|||||||
# This makefile currently only works for mac os
|
|
||||||
# You should install via homebrew:
|
|
||||||
# brew install glew
|
|
||||||
# brew install glfw3
|
|
||||||
#
|
|
||||||
|
|
||||||
CXXFLAGS=-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
|
|
||||||
CXXFLAGS+=-I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/Cellar/glfw3/3.0.4/include
|
|
||||||
CXXFLAGS+=-L/usr/local/Cellar/glew/1.10.0/lib -L/usr/local/Cellar/glfw3/3.0.4/lib
|
|
||||||
CXXFLAGS+=-lglew -lglfw3
|
|
||||||
CXXFLAGS+=-I../../
|
|
||||||
CXXFLAGS+= -D__APPLE__
|
|
||||||
|
|
||||||
main: main.cpp ../../imgui.cpp
|
|
||||||
$(CXX) $(CXXFLAGS) -o $@ $^
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm main
|
|
@ -1,11 +1,20 @@
|
|||||||
#define GLEW_STATIC
|
#ifdef _MSC_VER
|
||||||
#include <GL/glew.h>
|
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
||||||
#include <GLFW/glfw3.h>
|
#include <Windows.h>
|
||||||
|
#include <Imm.h>
|
||||||
|
#endif
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "stb_image.h" // for .png loading
|
#include "stb_image.h" // for .png loading
|
||||||
#include "../../imgui.h"
|
#include "../../imgui.h"
|
||||||
|
|
||||||
|
// glew & glfw
|
||||||
|
#define GLEW_STATIC
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||||
|
#define GLFW_EXPOSE_NATIVE_WGL
|
||||||
|
#include <GLFW/glfw3native.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static GLFWwindow* window;
|
static GLFWwindow* window;
|
||||||
@ -70,32 +79,32 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
|
|||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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()
|
static const char* ImImpl_GetClipboardTextFn()
|
||||||
{
|
{
|
||||||
return glfwGetClipboardString(window);
|
return glfwGetClipboardString(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImImpl_SetClipboardTextFn(const char* text, const char* text_end)
|
static void ImImpl_SetClipboardTextFn(const char* text)
|
||||||
{
|
{
|
||||||
if (!text_end)
|
|
||||||
text_end = text + strlen(text);
|
|
||||||
|
|
||||||
if (*text_end == 0)
|
|
||||||
{
|
|
||||||
// Already got a zero-terminator at 'text_end', we don't need to add one
|
|
||||||
glfwSetClipboardString(window, text);
|
glfwSetClipboardString(window, text);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Add a zero-terminator because glfw function doesn't take a size
|
|
||||||
char* buf = (char*)malloc(text_end - text + 1);
|
|
||||||
memcpy(buf, text, text_end-text);
|
|
||||||
buf[text_end-text] = '\0';
|
|
||||||
glfwSetClipboardString(window, buf);
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// 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
|
// GLFW callbacks to get events
|
||||||
static void glfw_error_callback(int error, const char* description)
|
static void glfw_error_callback(int error, const char* description)
|
||||||
@ -122,8 +131,8 @@ static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int act
|
|||||||
|
|
||||||
static void glfw_char_callback(GLFWwindow* window, unsigned int c)
|
static void glfw_char_callback(GLFWwindow* window, unsigned int c)
|
||||||
{
|
{
|
||||||
if (c > 0 && c <= 255)
|
if (c > 0 && c < 0x10000)
|
||||||
ImGui::GetIO().AddInputCharacter((char)c);
|
ImGui::GetIO().AddInputCharacter((unsigned short)c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenGL code based on http://open.gl tutorials
|
// OpenGL code based on http://open.gl tutorials
|
||||||
@ -178,17 +187,44 @@ void InitImGui()
|
|||||||
io.RenderDrawListsFn = ImImpl_RenderDrawLists;
|
io.RenderDrawListsFn = ImImpl_RenderDrawLists;
|
||||||
io.SetClipboardTextFn = ImImpl_SetClipboardTextFn;
|
io.SetClipboardTextFn = ImImpl_SetClipboardTextFn;
|
||||||
io.GetClipboardTextFn = ImImpl_GetClipboardTextFn;
|
io.GetClipboardTextFn = ImImpl_GetClipboardTextFn;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
io.ImeSetInputScreenPosFn = ImImpl_ImeSetInputScreenPosFn;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Load font texture
|
// Load font texture
|
||||||
glGenTextures(1, &fontTex);
|
glGenTextures(1, &fontTex);
|
||||||
glBindTexture(GL_TEXTURE_2D, fontTex);
|
glBindTexture(GL_TEXTURE_2D, fontTex);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// Default font (embedded in code)
|
||||||
const void* png_data;
|
const void* png_data;
|
||||||
unsigned int png_size;
|
unsigned int png_size;
|
||||||
ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
|
ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
|
||||||
int tex_x, tex_y, tex_comp;
|
int tex_x, tex_y, tex_comp;
|
||||||
void* tex_data = stbi_load_from_memory((const unsigned char*)png_data, (int)png_size, &tex_x, &tex_y, &tex_comp, 0);
|
void* tex_data = stbi_load_from_memory((const unsigned char*)png_data, (int)png_size, &tex_x, &tex_y, &tex_comp, 0);
|
||||||
|
IM_ASSERT(tex_data != NULL);
|
||||||
|
#else
|
||||||
|
// Custom font from filesystem
|
||||||
|
io.Font = new ImBitmapFont();
|
||||||
|
io.Font->LoadFromFile("../../extra_fonts/mplus-2m-medium_18.fnt");
|
||||||
|
IM_ASSERT(io.Font->IsLoaded());
|
||||||
|
|
||||||
|
int tex_x, tex_y, tex_comp;
|
||||||
|
void* tex_data = stbi_load("../../extra_fonts/mplus-2m-medium_18.png", &tex_x, &tex_y, &tex_comp, 0);
|
||||||
|
IM_ASSERT(tex_data != NULL);
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
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));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_x, tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_x, tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data);
|
||||||
stbi_image_free(tex_data);
|
stbi_image_free(tex_data);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\glfw\lib-msvc100;$(SolutionDir)\glew\lib\Release\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)\glfw\lib-msvc100;$(SolutionDir)\glew\lib\Release\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>opengl32.lib;imm32.lib;glfw3.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<SubSystem>NotSet</SubSystem>
|
<SubSystem>NotSet</SubSystem>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -63,7 +63,7 @@
|
|||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\glfw\lib-msvc100;$(SolutionDir)\glew\lib\Release\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(SolutionDir)\glfw\lib-msvc100;$(SolutionDir)\glew\lib\Release\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>opengl32.lib;imm32.lib;glfw3.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<SubSystem>NotSet</SubSystem>
|
<SubSystem>NotSet</SubSystem>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* stb_image - v1.43 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
|
/* stb_image - v1.46 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
|
||||||
when you control the images you're loading
|
when you control the images you're loading
|
||||||
no warranty implied; use at your own risk
|
no warranty implied; use at your own risk
|
||||||
|
|
||||||
@ -13,7 +13,7 @@
|
|||||||
avoid problematic images and only need the trivial interface
|
avoid problematic images and only need the trivial interface
|
||||||
|
|
||||||
JPEG baseline (no JPEG progressive)
|
JPEG baseline (no JPEG progressive)
|
||||||
PNG 8-bit-per-channel only
|
PNG 1/2/4/8-bit-per-channel (16 bpc not supported)
|
||||||
|
|
||||||
TGA (not sure what subset, if a subset)
|
TGA (not sure what subset, if a subset)
|
||||||
BMP non-1bpp, non-RLE
|
BMP non-1bpp, non-RLE
|
||||||
@ -28,11 +28,15 @@
|
|||||||
- overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
|
- overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
|
||||||
|
|
||||||
Latest revisions:
|
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.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.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.41 (2014-06-25) fix search&replace that messed up comments/error messages
|
||||||
1.40 (2014-06-22) gcc warning
|
1.40 (2014-06-22) gcc warning
|
||||||
1.39 (2014-06-15) TGA optimization fix, multiple BMP fixes
|
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.38 (2014-06-06) suppress MSVC run-time warnings, fix accidental rename of 'skip'
|
||||||
1.37 (2014-06-04) remove duplicate typedef
|
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.36 (2014-06-03) converted to header file, allow reading incorrect iphoned-images without iphone flag
|
||||||
@ -60,17 +64,19 @@
|
|||||||
James "moose2000" Brown (iPhone PNG) David Woo
|
James "moose2000" Brown (iPhone PNG) David Woo
|
||||||
Ben "Disch" Wenger (io callbacks) Roy Eltham
|
Ben "Disch" Wenger (io callbacks) Roy Eltham
|
||||||
Martin "SpartanJ" Golini Luke Graham
|
Martin "SpartanJ" Golini Luke Graham
|
||||||
Thomas Ruf
|
Omar Cornut (1/2/4-bit png) Thomas Ruf
|
||||||
John Bartholomew
|
John Bartholomew
|
||||||
Optimizations & bugfixes Ken Hamada
|
Optimizations & bugfixes Ken Hamada
|
||||||
Fabian "ryg" Giesen Cort Stratton
|
Fabian "ryg" Giesen Cort Stratton
|
||||||
Arseny Kapoulkine Blazej Dariusz Roszkowski
|
Arseny Kapoulkine Blazej Dariusz Roszkowski
|
||||||
Thibault Reuille
|
Thibault Reuille
|
||||||
If your name should be here but Paul Du Bois
|
Paul Du Bois
|
||||||
isn't, let Sean know. Guillaume George
|
Guillaume George
|
||||||
Jerry Jansson
|
Jerry Jansson
|
||||||
Hayaki Saito
|
If your name should be here but Hayaki Saito
|
||||||
Johan Duparc
|
isn't, let Sean know. Johan Duparc
|
||||||
|
Ronny Chevalier
|
||||||
|
Michal Cichon
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STBI_INCLUDE_STB_IMAGE_H
|
#ifndef STBI_INCLUDE_STB_IMAGE_H
|
||||||
@ -525,6 +531,11 @@ static int stbi__err(const char *str)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *stbi__malloc(size_t size)
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
// stbi__err - error
|
// stbi__err - error
|
||||||
// stbi__errpf - error returning pointer to float
|
// stbi__errpf - error returning pointer to float
|
||||||
// stbi__errpuc - error returning pointer to unsigned char
|
// stbi__errpuc - error returning pointer to unsigned char
|
||||||
@ -577,11 +588,11 @@ static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp
|
|||||||
FILE *stbi__fopen(char const *filename, char const *mode)
|
FILE *stbi__fopen(char const *filename, char const *mode)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
#if _MSC_VER >= 1400
|
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||||
if (0 != fopen_s(&f, filename, "rb"))
|
if (0 != fopen_s(&f, filename, mode))
|
||||||
f=0;
|
f=0;
|
||||||
#else
|
#else
|
||||||
f = fopen(filename, "rb");
|
f = fopen(filename, mode);
|
||||||
#endif
|
#endif
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
@ -756,7 +767,7 @@ static void stbi__refill_buffer(stbi__context *s)
|
|||||||
int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
|
int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
// at end of file, treat same as if from memory, but need to handle case
|
// 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, stbi__err.g. 0-byte file
|
// where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
|
||||||
s->read_from_callbacks = 0;
|
s->read_from_callbacks = 0;
|
||||||
s->img_buffer = s->buffer_start;
|
s->img_buffer = s->buffer_start;
|
||||||
s->img_buffer_end = s->buffer_start+1;
|
s->img_buffer_end = s->buffer_start+1;
|
||||||
@ -854,7 +865,7 @@ static stbi__uint32 stbi__get32le(stbi__context *s)
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// generic converter from built-in img_n to req_comp
|
// generic converter from built-in img_n to req_comp
|
||||||
// individual types do this automatically as much as possible (stbi__err.g. jpeg
|
// individual types do this automatically as much as possible (e.g. jpeg
|
||||||
// does all cases internally since it needs to colorspace convert anyway,
|
// does all cases internally since it needs to colorspace convert anyway,
|
||||||
// and it never has alpha, so very few cases ). png can automatically
|
// 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
|
// interleave an alpha=255 channel, but falls back to this for other cases
|
||||||
@ -875,7 +886,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
|
|||||||
if (req_comp == img_n) return data;
|
if (req_comp == img_n) return data;
|
||||||
STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
|
STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
|
||||||
|
|
||||||
good = (unsigned char *) malloc(req_comp * x * y);
|
good = (unsigned char *) stbi__malloc(req_comp * x * y);
|
||||||
if (good == NULL) {
|
if (good == NULL) {
|
||||||
free(data);
|
free(data);
|
||||||
return stbi__errpuc("outofmem", "Out of memory");
|
return stbi__errpuc("outofmem", "Out of memory");
|
||||||
@ -915,7 +926,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
|
|||||||
static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
|
static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
|
||||||
{
|
{
|
||||||
int i,k,n;
|
int i,k,n;
|
||||||
float *output = (float *) malloc(x * y * comp * sizeof(float));
|
float *output = (float *) stbi__malloc(x * y * comp * sizeof(float));
|
||||||
if (output == NULL) { free(data); return stbi__errpf("outofmem", "Out of memory"); }
|
if (output == NULL) { free(data); return stbi__errpf("outofmem", "Out of memory"); }
|
||||||
// compute number of non-alpha components
|
// compute number of non-alpha components
|
||||||
if (comp & 1) n = comp; else n = comp-1;
|
if (comp & 1) n = comp; else n = comp-1;
|
||||||
@ -933,7 +944,7 @@ 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)
|
static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp)
|
||||||
{
|
{
|
||||||
int i,k,n;
|
int i,k,n;
|
||||||
stbi_uc *output = (stbi_uc *) malloc(x * y * comp);
|
stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp);
|
||||||
if (output == NULL) { free(data); return stbi__errpuc("outofmem", "Out of memory"); }
|
if (output == NULL) { free(data); return stbi__errpuc("outofmem", "Out of memory"); }
|
||||||
// compute number of non-alpha components
|
// compute number of non-alpha components
|
||||||
if (comp & 1) n = comp; else n = comp-1;
|
if (comp & 1) n = comp; else n = comp-1;
|
||||||
@ -1601,16 +1612,16 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
|
|||||||
z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
|
z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
|
||||||
|
|
||||||
for (i=0; i < s->img_n; ++i) {
|
for (i=0; i < s->img_n; ++i) {
|
||||||
// number of effective pixels (stbi__err.g. for non-interleaved MCU)
|
// 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].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;
|
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
|
// to simplify generation, we'll allocate enough memory to decode
|
||||||
// the bogus oversized data from using interleaved MCUs and their
|
// the bogus oversized data from using interleaved MCUs and their
|
||||||
// big blocks (stbi__err.g. a 16x16 iMCU on an image of width 33); we won't
|
// big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
|
||||||
// discard the extra data until colorspace conversion
|
// 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].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].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
|
||||||
z->img_comp[i].raw_data = malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15);
|
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) {
|
if (z->img_comp[i].raw_data == NULL) {
|
||||||
for(--i; i >= 0; --i) {
|
for(--i; i >= 0; --i) {
|
||||||
free(z->img_comp[i].raw_data);
|
free(z->img_comp[i].raw_data);
|
||||||
@ -1626,7 +1637,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use comparisons since in some cases we handle more than one case (stbi__err.g. stbi__SOF)
|
// use comparisons since in some cases we handle more than one case (e.g. stbi__SOF)
|
||||||
#define stbi__DNL(x) ((x) == 0xdc)
|
#define stbi__DNL(x) ((x) == 0xdc)
|
||||||
#define stbi__SOI(x) ((x) == 0xd8)
|
#define stbi__SOI(x) ((x) == 0xd8)
|
||||||
#define stbi__EOI(x) ((x) == 0xd9)
|
#define stbi__EOI(x) ((x) == 0xd9)
|
||||||
@ -1875,7 +1886,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
|||||||
|
|
||||||
// allocate line buffer big enough for upsampling off the edges
|
// allocate line buffer big enough for upsampling off the edges
|
||||||
// with upsample factor of 4
|
// with upsample factor of 4
|
||||||
z->img_comp[k].linebuf = (stbi_uc *) malloc(z->s->img_x + 3);
|
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"); }
|
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->hs = z->img_h_max / z->img_comp[k].h;
|
||||||
@ -1893,7 +1904,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// can't error after this so, this is safe
|
// can't error after this so, this is safe
|
||||||
output = (stbi_uc *) malloc(n * z->s->img_x * z->s->img_y + 1);
|
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"); }
|
if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
|
||||||
|
|
||||||
// now go ahead and resample
|
// now go ahead and resample
|
||||||
@ -2015,7 +2026,7 @@ stbi_inline static int stbi__bit_reverse(int v, int bits)
|
|||||||
{
|
{
|
||||||
STBI_ASSERT(bits <= 16);
|
STBI_ASSERT(bits <= 16);
|
||||||
// to bit reverse n bits, reverse 16 and shift
|
// to bit reverse n bits, reverse 16 and shift
|
||||||
// stbi__err.g. 11 bits, bit reverse and shift away 5
|
// e.g. 11 bits, bit reverse and shift away 5
|
||||||
return stbi__bitreverse16(v) >> (16-bits);
|
return stbi__bitreverse16(v) >> (16-bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2338,7 +2349,7 @@ static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse
|
|||||||
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
|
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
|
||||||
{
|
{
|
||||||
stbi__zbuf a;
|
stbi__zbuf a;
|
||||||
char *p = (char *) malloc(initial_size);
|
char *p = (char *) stbi__malloc(initial_size);
|
||||||
if (p == NULL) return NULL;
|
if (p == NULL) return NULL;
|
||||||
a.zbuffer = (stbi_uc *) buffer;
|
a.zbuffer = (stbi_uc *) buffer;
|
||||||
a.zbuffer_end = (stbi_uc *) buffer + len;
|
a.zbuffer_end = (stbi_uc *) buffer + len;
|
||||||
@ -2359,7 +2370,7 @@ STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, 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_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header)
|
||||||
{
|
{
|
||||||
stbi__zbuf a;
|
stbi__zbuf a;
|
||||||
char *p = (char *) malloc(initial_size);
|
char *p = (char *) stbi__malloc(initial_size);
|
||||||
if (p == NULL) return NULL;
|
if (p == NULL) return NULL;
|
||||||
a.zbuffer = (stbi_uc *) buffer;
|
a.zbuffer = (stbi_uc *) buffer;
|
||||||
a.zbuffer_end = (stbi_uc *) buffer + len;
|
a.zbuffer_end = (stbi_uc *) buffer + len;
|
||||||
@ -2386,7 +2397,7 @@ STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer
|
|||||||
STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)
|
STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)
|
||||||
{
|
{
|
||||||
stbi__zbuf a;
|
stbi__zbuf a;
|
||||||
char *p = (char *) malloc(16384);
|
char *p = (char *) stbi__malloc(16384);
|
||||||
if (p == NULL) return NULL;
|
if (p == NULL) return NULL;
|
||||||
a.zbuffer = (stbi_uc *) buffer;
|
a.zbuffer = (stbi_uc *) buffer;
|
||||||
a.zbuffer_end = (stbi_uc *) buffer+len;
|
a.zbuffer_end = (stbi_uc *) buffer+len;
|
||||||
@ -2477,89 +2488,144 @@ static int stbi__paeth(int a, int b, int c)
|
|||||||
#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings
|
#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings
|
||||||
|
|
||||||
// create the png data from post-deflated data
|
// 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)
|
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__context *s = a->s;
|
||||||
stbi__uint32 i,j,stride = x*out_n;
|
stbi__uint32 i,j,stride = x*out_n;
|
||||||
|
stbi__uint32 img_len;
|
||||||
int k;
|
int k;
|
||||||
int img_n = s->img_n; // copy it into a local for later
|
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);
|
STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
|
||||||
a->out = (stbi_uc *) malloc(x * y * out_n);
|
a->out = (stbi_uc *) stbi__malloc(x * y * out_n);
|
||||||
if (!a->out) return stbi__err("outofmem", "Out of memory");
|
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 (s->img_x == x && s->img_y == y) {
|
||||||
if (raw_len != (img_n * x + 1) * y) return stbi__err("not enough pixels","Corrupt PNG");
|
if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG");
|
||||||
} else { // interlaced:
|
} else { // interlaced:
|
||||||
if (raw_len < (img_n * x + 1) * y) return stbi__err("not enough pixels","Corrupt PNG");
|
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) {
|
for (j=0; j < y; ++j) {
|
||||||
|
stbi_uc *in;
|
||||||
stbi_uc *cur = a->out + stride*j;
|
stbi_uc *cur = a->out + stride*j;
|
||||||
stbi_uc *prior = cur - stride;
|
stbi_uc *prior = cur - stride;
|
||||||
int filter = *raw++;
|
int filter = *raw++;
|
||||||
if (filter > 4) return stbi__err("invalid filter","Corrupt PNG");
|
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<<depth)-1) : 1; // scale grayscale values to 0..255 range
|
||||||
|
if (depth == 4) {
|
||||||
|
for (k=x*img_n; k >= 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 first row, use special filter that doesn't sample previous row
|
||||||
if (j == 0) filter = first_row_filter[filter];
|
if (j == 0) filter = first_row_filter[filter];
|
||||||
|
|
||||||
// handle first pixel explicitly
|
// handle first pixel explicitly
|
||||||
for (k=0; k < img_n; ++k) {
|
for (k=0; k < img_n; ++k) {
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
case STBI__F_none : cur[k] = raw[k]; break;
|
case STBI__F_none : cur[k] = in[k]; break;
|
||||||
case STBI__F_sub : cur[k] = raw[k]; break;
|
case STBI__F_sub : cur[k] = in[k]; break;
|
||||||
case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
|
case STBI__F_up : cur[k] = STBI__BYTECAST(in[k] + prior[k]); break;
|
||||||
case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
|
case STBI__F_avg : cur[k] = STBI__BYTECAST(in[k] + (prior[k]>>1)); break;
|
||||||
case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); 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] = raw[k]; break;
|
case STBI__F_avg_first : cur[k] = in[k]; break;
|
||||||
case STBI__F_paeth_first: cur[k] = raw[k]; break;
|
case STBI__F_paeth_first: cur[k] = in[k]; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (img_n != out_n) cur[img_n] = 255;
|
if (img_n != out_n) cur[img_n] = 255;
|
||||||
raw += img_n;
|
in += img_n;
|
||||||
cur += out_n;
|
cur += out_n;
|
||||||
prior += out_n;
|
prior += out_n;
|
||||||
// this is a little gross, so that we don't switch per-pixel or per-component
|
// this is a little gross, so that we don't switch per-pixel or per-component
|
||||||
if (img_n == out_n) {
|
if (img_n == out_n) {
|
||||||
#define CASE(f) \
|
#define CASE(f) \
|
||||||
case f: \
|
case f: \
|
||||||
for (i=x-1; i >= 1; --i, raw+=img_n,cur+=img_n,prior+=img_n) \
|
for (i=x-1; i >= 1; --i, in+=img_n,cur+=img_n,prior+=img_n) \
|
||||||
for (k=0; k < img_n; ++k)
|
for (k=0; k < img_n; ++k)
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
CASE(STBI__F_none) cur[k] = raw[k]; break;
|
CASE(STBI__F_none) cur[k] = in[k]; break;
|
||||||
CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-img_n]); break;
|
CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(in[k] + cur[k-img_n]); break;
|
||||||
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
|
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(in[k] + prior[k]); break;
|
||||||
CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-img_n])>>1)); 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(raw[k] + stbi__paeth(cur[k-img_n],prior[k],prior[k-img_n])); 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(raw[k] + (cur[k-img_n] >> 1)); 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(raw[k] + stbi__paeth(cur[k-img_n],0,0)); break;
|
CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(cur[k-img_n],0,0)); break;
|
||||||
}
|
}
|
||||||
#undef CASE
|
#undef CASE
|
||||||
} else {
|
} else {
|
||||||
STBI_ASSERT(img_n+1 == out_n);
|
STBI_ASSERT(img_n+1 == out_n);
|
||||||
#define CASE(f) \
|
#define CASE(f) \
|
||||||
case f: \
|
case f: \
|
||||||
for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \
|
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)
|
for (k=0; k < img_n; ++k)
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
CASE(STBI__F_none) cur[k] = raw[k]; break;
|
CASE(STBI__F_none) cur[k] = in[k]; break;
|
||||||
CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-out_n]); break;
|
CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(in[k] + cur[k-out_n]); break;
|
||||||
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
|
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(in[k] + prior[k]); break;
|
||||||
CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-out_n])>>1)); 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(raw[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); 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(raw[k] + (cur[k-out_n] >> 1)); 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(raw[k] + stbi__paeth(cur[k-out_n],0,0)); break;
|
CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(in[k] + stbi__paeth(cur[k-out_n],0,0)); break;
|
||||||
}
|
}
|
||||||
#undef CASE
|
#undef CASE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (depth != 8) free(line8);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, int interlaced)
|
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;
|
stbi_uc *final;
|
||||||
int p;
|
int p;
|
||||||
if (!interlaced)
|
if (!interlaced)
|
||||||
return stbi__create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y);
|
return stbi__create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y, depth, color);
|
||||||
|
|
||||||
// de-interlacing
|
// de-interlacing
|
||||||
final = (stbi_uc *) malloc(a->s->img_x * a->s->img_y * out_n);
|
final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n);
|
||||||
for (p=0; p < 7; ++p) {
|
for (p=0; p < 7; ++p) {
|
||||||
int xorig[] = { 0,4,0,2,0,1,0 };
|
int xorig[] = { 0,4,0,2,0,1,0 };
|
||||||
int yorig[] = { 0,0,4,0,2,0,1 };
|
int yorig[] = { 0,0,4,0,2,0,1 };
|
||||||
@ -2570,7 +2636,8 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_l
|
|||||||
x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p];
|
x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p];
|
||||||
y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p];
|
y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p];
|
||||||
if (x && y) {
|
if (x && y) {
|
||||||
if (!stbi__create_png_image_raw(a, raw, raw_len, out_n, 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);
|
free(final);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2579,8 +2646,8 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_l
|
|||||||
memcpy(final + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n,
|
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);
|
a->out + (j*x+i)*out_n, out_n);
|
||||||
free(a->out);
|
free(a->out);
|
||||||
raw += (x*out_n+1)*y;
|
raw += img_len;
|
||||||
raw_len -= (x*out_n+1)*y;
|
raw_len -= img_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a->out = final;
|
a->out = final;
|
||||||
@ -2618,7 +2685,7 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int
|
|||||||
stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
|
stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
|
||||||
stbi_uc *p, *temp_out, *orig = a->out;
|
stbi_uc *p, *temp_out, *orig = a->out;
|
||||||
|
|
||||||
p = (stbi_uc *) malloc(pixel_count * pal_img_n);
|
p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n);
|
||||||
if (p == NULL) return stbi__err("outofmem", "Out of memory");
|
if (p == NULL) return stbi__err("outofmem", "Out of memory");
|
||||||
|
|
||||||
// between here and free(out) below, exitting would leak
|
// between here and free(out) below, exitting would leak
|
||||||
@ -2710,7 +2777,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|||||||
stbi_uc palette[1024], pal_img_n=0;
|
stbi_uc palette[1024], pal_img_n=0;
|
||||||
stbi_uc has_trans=0, tc[3];
|
stbi_uc has_trans=0, tc[3];
|
||||||
stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
|
stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
|
||||||
int first=1,k,interlace=0, is_iphone=0;
|
int first=1,k,interlace=0, color=0, depth=0, is_iphone=0;
|
||||||
stbi__context *s = z->s;
|
stbi__context *s = z->s;
|
||||||
|
|
||||||
z->expanded = NULL;
|
z->expanded = NULL;
|
||||||
@ -2729,13 +2796,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|||||||
stbi__skip(s, c.length);
|
stbi__skip(s, c.length);
|
||||||
break;
|
break;
|
||||||
case PNG_TYPE('I','H','D','R'): {
|
case PNG_TYPE('I','H','D','R'): {
|
||||||
int depth,color,comp,filter;
|
int comp,filter;
|
||||||
if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
|
if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
|
||||||
first = 0;
|
first = 0;
|
||||||
if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
|
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_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
||||||
s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
s->img_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 != 8) return stbi__err("8bit only","PNG not supported: 8-bit only");
|
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");
|
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");
|
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");
|
comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG");
|
||||||
@ -2819,7 +2886,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|||||||
s->img_out_n = s->img_n+1;
|
s->img_out_n = s->img_n+1;
|
||||||
else
|
else
|
||||||
s->img_out_n = s->img_n;
|
s->img_out_n = s->img_n;
|
||||||
if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, interlace)) return 0;
|
if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0;
|
||||||
if (has_trans)
|
if (has_trans)
|
||||||
if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
|
if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
|
||||||
if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
|
if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
|
||||||
@ -2872,7 +2939,7 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req
|
|||||||
}
|
}
|
||||||
*x = p->s->img_x;
|
*x = p->s->img_x;
|
||||||
*y = p->s->img_y;
|
*y = p->s->img_y;
|
||||||
if (n) *n = p->s->img_n;
|
if (n) *n = p->s->img_out_n;
|
||||||
}
|
}
|
||||||
free(p->out); p->out = NULL;
|
free(p->out); p->out = NULL;
|
||||||
free(p->expanded); p->expanded = NULL;
|
free(p->expanded); p->expanded = NULL;
|
||||||
@ -3074,7 +3141,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
target = req_comp;
|
target = req_comp;
|
||||||
else
|
else
|
||||||
target = s->img_n; // if they want monochrome, we'll post-convert
|
target = s->img_n; // if they want monochrome, we'll post-convert
|
||||||
out = (stbi_uc *) malloc(target * s->img_x * s->img_y);
|
out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y);
|
||||||
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
||||||
if (bpp < 16) {
|
if (bpp < 16) {
|
||||||
int z=0;
|
int z=0;
|
||||||
@ -3303,7 +3370,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
*y = tga_height;
|
*y = tga_height;
|
||||||
if (comp) *comp = tga_comp;
|
if (comp) *comp = tga_comp;
|
||||||
|
|
||||||
tga_data = (unsigned char*)malloc( tga_width * tga_height * tga_comp );
|
tga_data = (unsigned char*)stbi__malloc( tga_width * tga_height * tga_comp );
|
||||||
if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
|
if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
|
||||||
|
|
||||||
// skip to the data's starting position (offset usually = 0)
|
// skip to the data's starting position (offset usually = 0)
|
||||||
@ -3322,7 +3389,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
// any data to skip? (offset usually = 0)
|
// any data to skip? (offset usually = 0)
|
||||||
stbi__skip(s, tga_palette_start );
|
stbi__skip(s, tga_palette_start );
|
||||||
// load the palette
|
// load the palette
|
||||||
tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 );
|
tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_palette_bits / 8 );
|
||||||
if (!tga_palette) {
|
if (!tga_palette) {
|
||||||
free(tga_data);
|
free(tga_data);
|
||||||
return stbi__errpuc("outofmem", "Out of memory");
|
return stbi__errpuc("outofmem", "Out of memory");
|
||||||
@ -3513,7 +3580,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
return stbi__errpuc("bad compression", "PSD has an unknown compression format");
|
return stbi__errpuc("bad compression", "PSD has an unknown compression format");
|
||||||
|
|
||||||
// Create the destination image.
|
// Create the destination image.
|
||||||
out = (stbi_uc *) malloc(4 * w*h);
|
out = (stbi_uc *) stbi__malloc(4 * w*h);
|
||||||
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
||||||
pixelCount = w*h;
|
pixelCount = w*h;
|
||||||
|
|
||||||
@ -3798,7 +3865,7 @@ static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int re
|
|||||||
stbi__get16be(s); //skip `pad'
|
stbi__get16be(s); //skip `pad'
|
||||||
|
|
||||||
// intermediate buffer is RGBA
|
// intermediate buffer is RGBA
|
||||||
result = (stbi_uc *) malloc(x*y*4);
|
result = (stbi_uc *) stbi__malloc(x*y*4);
|
||||||
memset(result, 0xff, x*y*4);
|
memset(result, 0xff, x*y*4);
|
||||||
|
|
||||||
if (!stbi__pic_load_core(s,x,y,comp, result)) {
|
if (!stbi__pic_load_core(s,x,y,comp, result)) {
|
||||||
@ -4049,14 +4116,14 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
|
|||||||
|
|
||||||
if (g->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
|
if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header
|
||||||
g->out = (stbi_uc *) malloc(4 * g->w * g->h);
|
g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
|
||||||
if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
|
if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
|
||||||
stbi__fill_gif_background(g);
|
stbi__fill_gif_background(g);
|
||||||
} else {
|
} else {
|
||||||
// animated-gif-only path
|
// animated-gif-only path
|
||||||
if (((g->eflags & 0x1C) >> 2) == 3) {
|
if (((g->eflags & 0x1C) >> 2) == 3) {
|
||||||
old_out = g->out;
|
old_out = g->out;
|
||||||
g->out = (stbi_uc *) malloc(4 * g->w * g->h);
|
g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
|
||||||
if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
|
if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
|
||||||
memcpy(g->out, old_out, g->w*g->h*4);
|
memcpy(g->out, old_out, g->w*g->h*4);
|
||||||
}
|
}
|
||||||
@ -4279,7 +4346,7 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
|
|||||||
if (req_comp == 0) req_comp = 3;
|
if (req_comp == 0) req_comp = 3;
|
||||||
|
|
||||||
// Read data
|
// Read data
|
||||||
hdr_data = (float *) malloc(height * width * req_comp * sizeof(float));
|
hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float));
|
||||||
|
|
||||||
// Load image data
|
// Load image data
|
||||||
// image data is stored as some number of sca
|
// image data is stored as some number of sca
|
||||||
@ -4318,7 +4385,7 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
|
|||||||
len <<= 8;
|
len <<= 8;
|
||||||
len |= stbi__get8(s);
|
len |= stbi__get8(s);
|
||||||
if (len != width) { free(hdr_data); free(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
|
if (len != width) { free(hdr_data); free(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
|
||||||
if (scanline == NULL) scanline = (stbi_uc *) malloc(width * 4);
|
if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4);
|
||||||
|
|
||||||
for (k = 0; k < 4; ++k) {
|
for (k = 0; k < 4; ++k) {
|
||||||
i = 0;
|
i = 0;
|
||||||
@ -4555,6 +4622,12 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
revision history:
|
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)
|
1.43 (2014-07-15)
|
||||||
fix MSVC-only compiler problem in code changed in 1.42
|
fix MSVC-only compiler problem in code changed in 1.42
|
||||||
1.42 (2014-07-09)
|
1.42 (2014-07-09)
|
||||||
|
@ -10,12 +10,22 @@ bmfont reads fonts (.ttf, .fon, etc.) and output a .fnt file and a texture file,
|
|||||||
proggy_clean.fon --> [bmfont] ---> proggy_clean_13.fnt
|
proggy_clean.fon --> [bmfont] ---> proggy_clean_13.fnt
|
||||||
proggy_clean_13.png
|
proggy_clean_13.png
|
||||||
|
|
||||||
|
If you need a free font that supports chinese/japanese characters, you can use the M+ fonts.
|
||||||
|
TTF and sources are availables at http://mplus-fonts.sourceforge.jp/mplus-outline-fonts.
|
||||||
|
This directory include some of the M+ fonts converted by bmfont.
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Configure bmfont:
|
Configure bmfont:
|
||||||
|
|
||||||
- Export .fnt as Binary
|
- Export .fnt as Binary
|
||||||
|
- Output .png, 32-bits (or whatever is suitable for your loader/renderer)
|
||||||
- Tip: uncheck "Render from TrueType outline" and "Font Smoothing" for best result with non-anti-aliased type fonts.
|
- Tip: uncheck "Render from TrueType outline" and "Font Smoothing" for best result with non-anti-aliased type fonts.
|
||||||
But you can experiment with other settings if you want anti-aliased fonts.
|
But you can experiment with other settings if you want anti-aliased fonts.
|
||||||
|
- Tip: use pngout.exe (http://advsys.net/ken/utils.htm) to further reduce the file size of .png files
|
||||||
|
All files in this folder have been optimised with pngout.exe
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
(A) Use font data embedded in ImGui
|
(A) Use font data embedded in ImGui
|
||||||
|
|
||||||
@ -34,28 +44,45 @@ Configure bmfont:
|
|||||||
|
|
||||||
2. Load the .PNG data from 'png_data' into a texture
|
2. Load the .PNG data from 'png_data' into a texture
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
(B) Use fonts from external files
|
(B) Use fonts from external files
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
You need to set io.FontTexUvForWhite to UV coordinates pointing to a white pixel in the texture.
|
||||||
|
You can either locate a white pixel manually or use code at runtime to find or write one.
|
||||||
|
The OpenGL example include sample code to find a white pixel given an uncompressed 32-bits texture:
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
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));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
1. Load the .FNT data, e.g.
|
1. Load the .FNT data, e.g.
|
||||||
|
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
// proggy_clean_13 [default]
|
// proggy_clean_13 [default]
|
||||||
|
io.Font = new ImBitmapFont();
|
||||||
io.Font->LoadFromFile("proggy_clean_13.fnt");
|
io.Font->LoadFromFile("proggy_clean_13.fnt");
|
||||||
|
IM_ASSERT(io.Font->IsLoaded());
|
||||||
io.FontTexUvForWhite = ImVec2(0.0f/256.0f,0.0f/128);
|
io.FontTexUvForWhite = ImVec2(0.0f/256.0f,0.0f/128);
|
||||||
io.FontYOffset = +1;
|
io.FontYOffset = +1;
|
||||||
|
|
||||||
// proggy_small_12
|
// proggy_small_12
|
||||||
io.Font = new ImBitmapFont();
|
io.Font = new ImBitmapFont();
|
||||||
io.Font->LoadFromFile("proggy_small_12.fnt");
|
io.Font->LoadFromFile("proggy_small_12.fnt");
|
||||||
|
IM_ASSERT(io.Font->IsLoaded());
|
||||||
io.FontTexUvForWhite = ImVec2(84.0f/256.0f,20.0f/64);
|
io.FontTexUvForWhite = ImVec2(84.0f/256.0f,20.0f/64);
|
||||||
io.FontYOffset = +2;
|
io.FontYOffset = +2;
|
||||||
|
|
||||||
// proggy_small_14
|
// proggy_small_14
|
||||||
io.Font = new ImBitmapFont();
|
io.Font = new ImBitmapFont();
|
||||||
io.Font->LoadFromFile("proggy_small_14.fnt");
|
io.Font->LoadFromFile("proggy_small_14.fnt");
|
||||||
|
IM_ASSERT(io.Font->IsLoaded());
|
||||||
io.FontTexUvForWhite = ImVec2(84.0f/256.0f,20.0f/64);
|
io.FontTexUvForWhite = ImVec2(84.0f/256.0f,20.0f/64);
|
||||||
io.FontYOffset = +3;
|
io.FontYOffset = +3;
|
||||||
|
|
||||||
@ -67,5 +94,7 @@ Configure bmfont:
|
|||||||
io.Font->LoadFromFile("courier_new_18.fnt");
|
io.Font->LoadFromFile("courier_new_18.fnt");
|
||||||
io.FontTexUvForWhite = ImVec2(4.0f/256.0f,5.0f/256);
|
io.FontTexUvForWhite = ImVec2(4.0f/256.0f,5.0f/256);
|
||||||
|
|
||||||
|
|
||||||
2. Load the matching .PNG data into a texture
|
2. Load the matching .PNG data into a texture
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
BIN
extra_fonts/mplus-2m-medium_18.fnt
Normal file
BIN
extra_fonts/mplus-2m-medium_18.fnt
Normal file
Binary file not shown.
After Width: | Height: | Size: 117 KiB |
BIN
extra_fonts/mplus-2m-medium_18.png
Normal file
BIN
extra_fonts/mplus-2m-medium_18.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 284 KiB |
432
imgui.cpp
432
imgui.cpp
@ -1,4 +1,4 @@
|
|||||||
// ImGui library v1.12
|
// ImGui library v1.13
|
||||||
// See ImGui::ShowTestWindow() for sample code.
|
// See ImGui::ShowTestWindow() for sample code.
|
||||||
// Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
|
// Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
|
||||||
// Get latest version at https://github.com/ocornut/imgui
|
// Get latest version at https://github.com/ocornut/imgui
|
||||||
@ -22,7 +22,6 @@
|
|||||||
Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
|
Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
|
||||||
- doesn't look fancy, doesn't animate
|
- doesn't look fancy, doesn't animate
|
||||||
- limited layout features, intricate layouts are typically crafted in code
|
- limited layout features, intricate layouts are typically crafted in code
|
||||||
- assume ASCII text, using strlen() and [] operators, etc
|
|
||||||
- occasionally use statically sized buffers for string manipulations - won't crash, but some long text may be clipped
|
- occasionally use statically sized buffers for string manipulations - won't crash, but some long text may be clipped
|
||||||
|
|
||||||
END-USER GUIDE
|
END-USER GUIDE
|
||||||
@ -139,6 +138,7 @@
|
|||||||
API BREAKING CHANGES
|
API BREAKING CHANGES
|
||||||
====================
|
====================
|
||||||
|
|
||||||
|
- 2014/09/25 (1.13) removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
|
||||||
- 2014/09/24 (1.12) renamed SetFontScale() to SetWindowFontScale()
|
- 2014/09/24 (1.12) renamed SetFontScale() to SetWindowFontScale()
|
||||||
- 2014/09/24 (1.12) moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
|
- 2014/09/24 (1.12) moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
|
||||||
- 2014/08/30 (1.09) removed IO.FontHeight (now computed automatically)
|
- 2014/08/30 (1.09) removed IO.FontHeight (now computed automatically)
|
||||||
@ -246,7 +246,7 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs);
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
static const char* GetClipboardTextFn_DefaultImpl();
|
static const char* GetClipboardTextFn_DefaultImpl();
|
||||||
static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_end);
|
static void SetClipboardTextFn_DefaultImpl(const char* text);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// User facing structures
|
// User facing structures
|
||||||
@ -319,28 +319,30 @@ ImGuiIO::ImGuiIO()
|
|||||||
FontTexUvForWhite = ImVec2(0.0f,0.0f);
|
FontTexUvForWhite = ImVec2(0.0f,0.0f);
|
||||||
FontBaseScale = 1.0f;
|
FontBaseScale = 1.0f;
|
||||||
FontAllowUserScaling = false;
|
FontAllowUserScaling = false;
|
||||||
|
FontFallbackGlyph = (ImWchar)'?';
|
||||||
PixelCenterOffset = 0.0f;
|
PixelCenterOffset = 0.0f;
|
||||||
MousePos = ImVec2(-1,-1);
|
MousePos = ImVec2(-1,-1);
|
||||||
MousePosPrev = ImVec2(-1,-1);
|
MousePosPrev = ImVec2(-1,-1);
|
||||||
MouseDoubleClickTime = 0.30f;
|
MouseDoubleClickTime = 0.30f;
|
||||||
MouseDoubleClickMaxDist = 6.0f;
|
MouseDoubleClickMaxDist = 6.0f;
|
||||||
|
|
||||||
// Memory management functions, default to posix
|
// User functions
|
||||||
|
RenderDrawListsFn = NULL;
|
||||||
MemAllocFn = malloc;
|
MemAllocFn = malloc;
|
||||||
MemReallocFn = realloc;
|
MemReallocFn = realloc;
|
||||||
MemFreeFn = free;
|
MemFreeFn = free;
|
||||||
|
GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependant default implementations
|
||||||
// Platform dependant default implementations
|
|
||||||
GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;
|
|
||||||
SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
|
SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
|
||||||
|
ImeSetInputScreenPosFn = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass in translated ASCII characters for text input.
|
// Pass in translated ASCII characters for text input.
|
||||||
// - with glfw you can get those from the callback set in glfwSetCharCallback()
|
// - with glfw you can get those from the callback set in glfwSetCharCallback()
|
||||||
// - on Windows you can get those using ToAscii+keyboard state, or via the VM_CHAR message
|
// - on Windows you can get those using ToAscii+keyboard state, or via the VM_CHAR message
|
||||||
void ImGuiIO::AddInputCharacter(char c)
|
static size_t ImStrlenW(const ImWchar* str);
|
||||||
|
void ImGuiIO::AddInputCharacter(ImWchar c)
|
||||||
{
|
{
|
||||||
const size_t n = strlen(InputCharacters);
|
const size_t n = ImStrlenW(InputCharacters);
|
||||||
if (n < sizeof(InputCharacters) / sizeof(InputCharacters[0]))
|
if (n < sizeof(InputCharacters) / sizeof(InputCharacters[0]))
|
||||||
{
|
{
|
||||||
InputCharacters[n] = c;
|
InputCharacters[n] = c;
|
||||||
@ -390,6 +392,11 @@ static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t)
|
|||||||
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
|
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
|
||||||
static inline float ImLength(const ImVec2& lhs) { return sqrt(lhs.x*lhs.x + lhs.y*lhs.y); }
|
static inline float ImLength(const ImVec2& lhs) { return sqrt(lhs.x*lhs.x + lhs.y*lhs.y); }
|
||||||
|
|
||||||
|
static int ImTextCharToUtf8(char* buf, size_t buf_size, unsigned int in_char); // return output UTF-8 bytes count
|
||||||
|
static int ImTextStrToUtf8(char* buf, size_t buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
|
||||||
|
static int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // return input UTF-8 bytes count
|
||||||
|
static int ImTextStrFromUtf8(ImWchar* buf, size_t buf_size, const char* in_text, const char* in_text_end); // return input UTF-8 bytes count
|
||||||
|
|
||||||
static int ImStricmp(const char* str1, const char* str2)
|
static int ImStricmp(const char* str1, const char* str2)
|
||||||
{
|
{
|
||||||
int d;
|
int d;
|
||||||
@ -405,6 +412,14 @@ static char* ImStrdup(const char *str)
|
|||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t ImStrlenW(const ImWchar* str)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
while (*str++)
|
||||||
|
n++;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
static const char* ImStristr(const char* haystack, const char* needle, const char* needle_end)
|
static const char* ImStristr(const char* haystack, const char* needle, const char* needle_end)
|
||||||
{
|
{
|
||||||
if (!needle_end)
|
if (!needle_end)
|
||||||
@ -606,19 +621,20 @@ struct ImGuiDrawContext
|
|||||||
|
|
||||||
struct ImGuiTextEditState;
|
struct ImGuiTextEditState;
|
||||||
#define STB_TEXTEDIT_STRING ImGuiTextEditState
|
#define STB_TEXTEDIT_STRING ImGuiTextEditState
|
||||||
#define STB_TEXTEDIT_CHARTYPE char
|
#define STB_TEXTEDIT_CHARTYPE ImWchar
|
||||||
#include "stb_textedit.h"
|
#include "stb_textedit.h"
|
||||||
|
|
||||||
// State of the currently focused/edited text input box
|
// State of the currently focused/edited text input box
|
||||||
struct ImGuiTextEditState
|
struct ImGuiTextEditState
|
||||||
{
|
{
|
||||||
char Text[1024]; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so own buffer.
|
ImWchar Text[1024]; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
|
||||||
char InitialText[1024]; // backup of end-user buffer at focusing time, to ESC key can do a revert. Also used for arithmetic operations (but could use a pre-parsed float there).
|
char InitialText[1024*3+1]; // backup of end-user buffer at the time of focus (in UTF-8, unconverted)
|
||||||
size_t BufSize; // end-user buffer size, <= 1024 (or increase above)
|
size_t BufSize; // end-user buffer size, <= 1024 (or increase above)
|
||||||
float Width; // widget width
|
float Width; // widget width
|
||||||
float ScrollX;
|
float ScrollX;
|
||||||
STB_TexteditState StbState;
|
STB_TexteditState StbState;
|
||||||
float CursorAnim;
|
float CursorAnim;
|
||||||
|
ImVec2 LastCursorPos;
|
||||||
bool SelectedAllMouseLock;
|
bool SelectedAllMouseLock;
|
||||||
ImFont Font;
|
ImFont Font;
|
||||||
float FontSize;
|
float FontSize;
|
||||||
@ -628,14 +644,15 @@ struct ImGuiTextEditState
|
|||||||
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
|
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
|
||||||
bool CursorIsVisible() const { return CursorAnim <= 0.0f || fmodf(CursorAnim, 1.20f) <= 0.80f; } // Blinking
|
bool CursorIsVisible() const { return CursorAnim <= 0.0f || fmodf(CursorAnim, 1.20f) <= 0.80f; } // Blinking
|
||||||
bool HasSelection() const { return StbState.select_start != StbState.select_end; }
|
bool HasSelection() const { return StbState.select_start != StbState.select_end; }
|
||||||
void SelectAll() { StbState.select_start = 0; StbState.select_end = (int)strlen(Text); StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }
|
void SelectAll() { StbState.select_start = 0; StbState.select_end = (int)ImStrlenW(Text); StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }
|
||||||
|
|
||||||
void OnKeyboardPressed(int key);
|
void OnKeyboardPressed(int key);
|
||||||
void UpdateScrollOffset();
|
void UpdateScrollOffset();
|
||||||
ImVec2 CalcDisplayOffsetFromCharIdx(int i) const;
|
ImVec2 CalcDisplayOffsetFromCharIdx(int i) const;
|
||||||
|
|
||||||
// Static functions because they are used to render non-focused instances of a text input box
|
// Static functions because they are used to render non-focused instances of a text input box
|
||||||
static const char* GetTextPointerClipped(ImFont font, float font_size, const char* text, float width, ImVec2* out_text_size = NULL);
|
static const char* GetTextPointerClippedA(ImFont font, float font_size, const char* text, float width, ImVec2* out_text_size = NULL);
|
||||||
|
static const ImWchar* GetTextPointerClippedW(ImFont font, float font_size, const ImWchar* text, float width, ImVec2* out_text_size = NULL);
|
||||||
static void RenderTextScrolledClipped(ImFont font, float font_size, const char* text, ImVec2 pos_base, float width, float scroll_x);
|
static void RenderTextScrolledClipped(ImFont font, float font_size, const char* text, ImVec2 pos_base, float width, float scroll_x);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1705,7 +1722,7 @@ ImVec2 CalcTextSize(const char* text, const char* text_end, const bool hide_text
|
|||||||
else
|
else
|
||||||
text_display_end = text_end;
|
text_display_end = text_end;
|
||||||
|
|
||||||
const ImVec2 size = window->Font()->CalcTextSize(window->FontSize(), 0, text, text_display_end, NULL);
|
const ImVec2 size = window->Font()->CalcTextSizeA(window->FontSize(), 0, text, text_display_end, NULL);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2373,7 +2390,7 @@ void End()
|
|||||||
{
|
{
|
||||||
g.LogClipboard->append("\n");
|
g.LogClipboard->append("\n");
|
||||||
if (g.IO.SetClipboardTextFn)
|
if (g.IO.SetClipboardTextFn)
|
||||||
g.IO.SetClipboardTextFn(g.LogClipboard->begin(), g.LogClipboard->end());
|
g.IO.SetClipboardTextFn(g.LogClipboard->begin());
|
||||||
g.LogClipboard->clear();
|
g.LogClipboard->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3795,15 +3812,15 @@ bool RadioButton(const char* label, int* v, int v_button)
|
|||||||
}; // namespace ImGui
|
}; // namespace ImGui
|
||||||
|
|
||||||
// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, ASCII, fixed-width font)
|
// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, ASCII, fixed-width font)
|
||||||
int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return (int)strlen(obj->Text); }
|
int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return (int)ImStrlenW(obj->Text); }
|
||||||
char STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return (char)obj->Text[idx]; }
|
ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->Text[idx]; }
|
||||||
float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { (void)line_start_idx; return obj->Font->CalcTextSize(obj->FontSize, 0, &obj->Text[char_idx], &obj->Text[char_idx]+1, NULL).x; }
|
float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { (void)line_start_idx; return obj->Font->CalcTextSizeW(obj->FontSize, 0, &obj->Text[char_idx], &obj->Text[char_idx]+1, NULL).x; }
|
||||||
char STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : (char)key; }
|
int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : key; }
|
||||||
char STB_TEXTEDIT_NEWLINE = '\n';
|
ImWchar STB_TEXTEDIT_NEWLINE = '\n';
|
||||||
void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx)
|
void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx)
|
||||||
{
|
{
|
||||||
const char* text_remaining = NULL;
|
const ImWchar* text_remaining = NULL;
|
||||||
const ImVec2 size = obj->Font->CalcTextSize(obj->FontSize, FLT_MAX, obj->Text + line_start_idx, NULL, &text_remaining);
|
const ImVec2 size = obj->Font->CalcTextSizeW(obj->FontSize, FLT_MAX, obj->Text + line_start_idx, NULL, &text_remaining);
|
||||||
r->x0 = 0.0f;
|
r->x0 = 0.0f;
|
||||||
r->x1 = size.x;
|
r->x1 = size.x;
|
||||||
r->baseline_y_delta = size.y;
|
r->baseline_y_delta = size.y;
|
||||||
@ -3812,22 +3829,22 @@ void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int
|
|||||||
r->num_chars = (int)(text_remaining - (obj->Text + line_start_idx));
|
r->num_chars = (int)(text_remaining - (obj->Text + line_start_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_white(char c) { return c==0 || c==' ' || c=='\t' || c=='\r' || c=='\n'; }
|
static bool is_white(unsigned int c) { return c==0 || c==' ' || c=='\t' || c=='\r' || c=='\n'; }
|
||||||
static bool is_separator(char c) { return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
|
static bool is_separator(unsigned int c) { return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
|
||||||
|
|
||||||
#define STB_TEXTEDIT_IS_SPACE(c) (is_white(c) || is_separator(c))
|
#define STB_TEXTEDIT_IS_SPACE(c) (is_white((unsigned int)c) || is_separator((unsigned int)c))
|
||||||
void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int idx, int n) { char* dst = obj->Text+idx; const char* src = obj->Text+idx+n; while (char c = *src++) *dst++ = c; *dst = '\0'; }
|
void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int idx, int n) { ImWchar* dst = obj->Text+idx; const ImWchar* src = obj->Text+idx+n; while (ImWchar c = *src++) *dst++ = c; *dst = '\0'; }
|
||||||
|
|
||||||
bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int idx, const char* new_text, int new_text_len)
|
bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int idx, const ImWchar* new_text, int new_text_len)
|
||||||
{
|
{
|
||||||
char* buf_end = obj->Text + obj->BufSize;
|
ImWchar* buf_end = obj->Text + obj->BufSize;
|
||||||
const size_t text_len = strlen(obj->Text);
|
const size_t text_len = ImStrlenW(obj->Text);
|
||||||
|
|
||||||
if (new_text_len > buf_end - (obj->Text + text_len + 1))
|
if (new_text_len > buf_end - (obj->Text + text_len + 1))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
memmove(obj->Text + (size_t)idx + new_text_len, obj->Text + (size_t)idx, text_len - (size_t)idx);
|
memmove(obj->Text + (size_t)idx + new_text_len, obj->Text + (size_t)idx, (text_len - (size_t)idx) * sizeof(ImWchar));
|
||||||
memcpy(obj->Text + (size_t)idx, new_text, (size_t)new_text_len);
|
memcpy(obj->Text + (size_t)idx, new_text, (size_t)new_text_len * sizeof(ImWchar));
|
||||||
obj->Text[text_len + (size_t)new_text_len] = 0;
|
obj->Text[text_len + (size_t)new_text_len] = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -3865,7 +3882,7 @@ void ImGuiTextEditState::UpdateScrollOffset()
|
|||||||
{
|
{
|
||||||
// Scroll in chunks of quarter width
|
// Scroll in chunks of quarter width
|
||||||
const float scroll_x_increment = Width * 0.25f;
|
const float scroll_x_increment = Width * 0.25f;
|
||||||
const float cursor_offset_x = Font->CalcTextSize(FontSize, 0, Text, Text+StbState.cursor, NULL).x;
|
const float cursor_offset_x = Font->CalcTextSizeW(FontSize, 0, Text, Text+StbState.cursor, NULL).x;
|
||||||
if (ScrollX > cursor_offset_x)
|
if (ScrollX > cursor_offset_x)
|
||||||
ScrollX = ImMax(0.0f, cursor_offset_x - scroll_x_increment);
|
ScrollX = ImMax(0.0f, cursor_offset_x - scroll_x_increment);
|
||||||
else if (ScrollX < cursor_offset_x - Width)
|
else if (ScrollX < cursor_offset_x - Width)
|
||||||
@ -3874,22 +3891,35 @@ void ImGuiTextEditState::UpdateScrollOffset()
|
|||||||
|
|
||||||
ImVec2 ImGuiTextEditState::CalcDisplayOffsetFromCharIdx(int i) const
|
ImVec2 ImGuiTextEditState::CalcDisplayOffsetFromCharIdx(int i) const
|
||||||
{
|
{
|
||||||
const char* text_start = GetTextPointerClipped(Font, FontSize, Text, ScrollX, NULL);
|
const ImWchar* text_start = GetTextPointerClippedW(Font, FontSize, Text, ScrollX, NULL);
|
||||||
const char* text_end = (Text+i >= text_start) ? Text+i : text_start; // Clip if requested character is outside of display
|
const ImWchar* text_end = (Text+i >= text_start) ? Text+i : text_start; // Clip if requested character is outside of display
|
||||||
IM_ASSERT(text_end >= text_start);
|
IM_ASSERT(text_end >= text_start);
|
||||||
|
|
||||||
const ImVec2 offset = Font->CalcTextSize(FontSize, Width, text_start, text_end, NULL);
|
const ImVec2 offset = Font->CalcTextSizeW(FontSize, Width, text_start, text_end, NULL);
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [Static]
|
// [Static]
|
||||||
const char* ImGuiTextEditState::GetTextPointerClipped(ImFont font, float font_size, const char* text, float width, ImVec2* out_text_size)
|
const char* ImGuiTextEditState::GetTextPointerClippedA(ImFont font, float font_size, const char* text, float width, ImVec2* out_text_size)
|
||||||
{
|
{
|
||||||
if (width <= 0.0f)
|
if (width <= 0.0f)
|
||||||
return text;
|
return text;
|
||||||
|
|
||||||
const char* text_clipped_end = NULL;
|
const char* text_clipped_end = NULL;
|
||||||
const ImVec2 text_size = font->CalcTextSize(font_size, width, text, NULL, &text_clipped_end);
|
const ImVec2 text_size = font->CalcTextSizeA(font_size, width, text, NULL, &text_clipped_end);
|
||||||
|
if (out_text_size)
|
||||||
|
*out_text_size = text_size;
|
||||||
|
return text_clipped_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Static]
|
||||||
|
const ImWchar* ImGuiTextEditState::GetTextPointerClippedW(ImFont font, float font_size, const ImWchar* text, float width, ImVec2* out_text_size)
|
||||||
|
{
|
||||||
|
if (width <= 0.0f)
|
||||||
|
return text;
|
||||||
|
|
||||||
|
const ImWchar* text_clipped_end = NULL;
|
||||||
|
const ImVec2 text_size = font->CalcTextSizeW(font_size, width, text, NULL, &text_clipped_end);
|
||||||
if (out_text_size)
|
if (out_text_size)
|
||||||
*out_text_size = text_size;
|
*out_text_size = text_size;
|
||||||
return text_clipped_end;
|
return text_clipped_end;
|
||||||
@ -3900,8 +3930,8 @@ void ImGuiTextEditState::RenderTextScrolledClipped(ImFont font, float font_size,
|
|||||||
{
|
{
|
||||||
// NB- We start drawing at character boundary
|
// NB- We start drawing at character boundary
|
||||||
ImVec2 text_size;
|
ImVec2 text_size;
|
||||||
const char* text_start = GetTextPointerClipped(font, font_size, buf, scroll_x, NULL);
|
const char* text_start = GetTextPointerClippedA(font, font_size, buf, scroll_x, NULL);
|
||||||
const char* text_end = GetTextPointerClipped(font, font_size, text_start, width, &text_size);
|
const char* text_end = GetTextPointerClippedA(font, font_size, text_start, width, &text_size);
|
||||||
|
|
||||||
// Draw a little clip symbol if we've got text on either left or right of the box
|
// Draw a little clip symbol if we've got text on either left or right of the box
|
||||||
const char symbol_c = '~';
|
const char symbol_c = '~';
|
||||||
@ -4028,12 +4058,14 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
|||||||
if (g.ActiveId != id)
|
if (g.ActiveId != id)
|
||||||
{
|
{
|
||||||
// Start edition
|
// Start edition
|
||||||
strcpy(edit_state.Text, buf);
|
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
|
||||||
strcpy(edit_state.InitialText, buf);
|
ImFormatString(edit_state.InitialText, IM_ARRAYSIZE(edit_state.InitialText), "%s", buf);
|
||||||
|
ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), buf, NULL);
|
||||||
edit_state.ScrollX = 0.0f;
|
edit_state.ScrollX = 0.0f;
|
||||||
edit_state.Width = w;
|
edit_state.Width = w;
|
||||||
stb_textedit_initialize_state(&edit_state.StbState, true);
|
stb_textedit_initialize_state(&edit_state.StbState, true);
|
||||||
edit_state.CursorAnimReset();
|
edit_state.CursorAnimReset();
|
||||||
|
edit_state.LastCursorPos = ImVec2(-1.f,-1.f);
|
||||||
|
|
||||||
if (tab_focus_requested || is_ctrl_down)
|
if (tab_focus_requested || is_ctrl_down)
|
||||||
select_all = true;
|
select_all = true;
|
||||||
@ -4052,6 +4084,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
|||||||
bool value_changed = false;
|
bool value_changed = false;
|
||||||
bool cancel_edit = false;
|
bool cancel_edit = false;
|
||||||
bool enter_pressed = false;
|
bool enter_pressed = false;
|
||||||
|
static char text_tmp_utf8[IM_ARRAYSIZE(edit_state.InitialText)];
|
||||||
if (g.ActiveId == id)
|
if (g.ActiveId == id)
|
||||||
{
|
{
|
||||||
// Edit in progress
|
// Edit in progress
|
||||||
@ -4096,55 +4129,62 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
|||||||
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Z)) edit_state.OnKeyboardPressed(STB_TEXTEDIT_K_UNDO); // I don't want to use shortcuts but we should probably have an Input-catch stack
|
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Z)) edit_state.OnKeyboardPressed(STB_TEXTEDIT_K_UNDO); // I don't want to use shortcuts but we should probably have an Input-catch stack
|
||||||
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Y)) edit_state.OnKeyboardPressed(STB_TEXTEDIT_K_REDO);
|
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Y)) edit_state.OnKeyboardPressed(STB_TEXTEDIT_K_REDO);
|
||||||
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_A)) edit_state.SelectAll();
|
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_A)) edit_state.SelectAll();
|
||||||
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_X))
|
else if (is_ctrl_down && (IsKeyPressedMap(ImGuiKey_X) || IsKeyPressedMap(ImGuiKey_C)))
|
||||||
{
|
{
|
||||||
if (!edit_state.HasSelection())
|
// Cut, Copy
|
||||||
|
const bool cut = IsKeyPressedMap(ImGuiKey_X);
|
||||||
|
if (cut && !edit_state.HasSelection())
|
||||||
edit_state.SelectAll();
|
edit_state.SelectAll();
|
||||||
|
|
||||||
const int ib = ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end);
|
|
||||||
const int ie = ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end);
|
|
||||||
if (g.IO.SetClipboardTextFn)
|
if (g.IO.SetClipboardTextFn)
|
||||||
g.IO.SetClipboardTextFn(edit_state.Text+ib, edit_state.Text+ie);
|
|
||||||
stb_textedit_cut(&edit_state, &edit_state.StbState);
|
|
||||||
}
|
|
||||||
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_C))
|
|
||||||
{
|
{
|
||||||
const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0;
|
const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0;
|
||||||
const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : (int)strlen(edit_state.Text);
|
const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : (int)ImStrlenW(edit_state.Text);
|
||||||
if (g.IO.SetClipboardTextFn)
|
ImTextStrToUtf8(text_tmp_utf8, IM_ARRAYSIZE(text_tmp_utf8), edit_state.Text+ib, edit_state.Text+ie);
|
||||||
g.IO.SetClipboardTextFn(edit_state.Text+ib, edit_state.Text+ie);
|
g.IO.SetClipboardTextFn(text_tmp_utf8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cut)
|
||||||
|
stb_textedit_cut(&edit_state, &edit_state.StbState);
|
||||||
}
|
}
|
||||||
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_V))
|
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_V))
|
||||||
{
|
{
|
||||||
|
// Paste
|
||||||
if (g.IO.GetClipboardTextFn)
|
if (g.IO.GetClipboardTextFn)
|
||||||
|
{
|
||||||
if (const char* clipboard = g.IO.GetClipboardTextFn())
|
if (const char* clipboard = g.IO.GetClipboardTextFn())
|
||||||
{
|
{
|
||||||
// Remove new-line from pasted buffer
|
// Remove new-line from pasted buffer
|
||||||
size_t clipboard_len = strlen(clipboard);
|
size_t clipboard_len = strlen(clipboard);
|
||||||
char* clipboard_filtered = (char*)ImGui::MemAlloc(clipboard_len+1);
|
ImWchar* clipboard_filtered = (ImWchar*)ImGui::MemAlloc((clipboard_len+1) * sizeof(ImWchar));
|
||||||
int clipboard_filtered_len = 0;
|
int clipboard_filtered_len = 0;
|
||||||
for (int i = 0; clipboard[i]; i++)
|
for (const char* s = clipboard; *s; )
|
||||||
{
|
{
|
||||||
const char c = clipboard[i];
|
unsigned int c;
|
||||||
|
const int bytes_count = ImTextCharFromUtf8(&c, s, NULL);
|
||||||
|
if (bytes_count <= 0)
|
||||||
|
break;
|
||||||
|
s += bytes_count;
|
||||||
if (c == '\n' || c == '\r')
|
if (c == '\n' || c == '\r')
|
||||||
continue;
|
continue;
|
||||||
clipboard_filtered[clipboard_filtered_len++] = clipboard[i];
|
clipboard_filtered[clipboard_filtered_len++] = c;
|
||||||
}
|
}
|
||||||
clipboard_filtered[clipboard_filtered_len] = 0;
|
clipboard_filtered[clipboard_filtered_len] = 0;
|
||||||
stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len);
|
stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len);
|
||||||
ImGui::MemFree(clipboard_filtered);
|
ImGui::MemFree(clipboard_filtered);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (g.IO.InputCharacters[0])
|
else if (g.IO.InputCharacters[0])
|
||||||
{
|
{
|
||||||
// Text input
|
// Text input
|
||||||
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
|
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
|
||||||
{
|
{
|
||||||
const char c = g.IO.InputCharacters[n];
|
const ImWchar c = g.IO.InputCharacters[n];
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
// Filter
|
// Filter
|
||||||
if (!isprint(c) && c != ' ')
|
if (c < 256 && !isprint((char)(c & 0xFF)) && c != ' ')
|
||||||
continue;
|
continue;
|
||||||
if (flags & ImGuiInputTextFlags_CharsDecimal)
|
if (flags & ImGuiInputTextFlags_CharsDecimal)
|
||||||
if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
|
if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
|
||||||
@ -4171,9 +4211,13 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Apply new value immediately - copy modified buffer back
|
// Apply new value immediately - copy modified buffer back
|
||||||
if (strcmp(edit_state.Text, buf) != 0)
|
// Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer
|
||||||
|
// FIXME: We actually always render 'buf' in RenderTextScrolledClipped
|
||||||
|
// FIXME-OPT: CPU waste to do this everytime the widget is active, should mark dirty state from the textedit callbacks
|
||||||
|
ImTextStrToUtf8(text_tmp_utf8, IM_ARRAYSIZE(text_tmp_utf8), edit_state.Text, NULL);
|
||||||
|
if (strcmp(text_tmp_utf8, buf) != 0)
|
||||||
{
|
{
|
||||||
ImFormatString(buf, buf_size, "%s", edit_state.Text);
|
ImFormatString(buf, buf_size, "%s", text_tmp_utf8);
|
||||||
value_changed = true;
|
value_changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4202,12 +4246,17 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
|||||||
|
|
||||||
if (g.ActiveId == id)
|
if (g.ActiveId == id)
|
||||||
{
|
{
|
||||||
|
const ImVec2 cursor_pos = frame_bb.Min + style.FramePadding + edit_state.CalcDisplayOffsetFromCharIdx(edit_state.StbState.cursor);
|
||||||
|
|
||||||
// Draw blinking cursor
|
// Draw blinking cursor
|
||||||
if (g.InputTextState.CursorIsVisible())
|
if (g.InputTextState.CursorIsVisible())
|
||||||
{
|
|
||||||
const ImVec2 cursor_pos = frame_bb.Min + style.FramePadding + edit_state.CalcDisplayOffsetFromCharIdx(edit_state.StbState.cursor);
|
|
||||||
window->DrawList->AddRect(cursor_pos - font_off_up + ImVec2(0,2), cursor_pos + font_off_dn - ImVec2(0,3), window->Color(ImGuiCol_Text));
|
window->DrawList->AddRect(cursor_pos - font_off_up + ImVec2(0,2), cursor_pos + font_off_dn - ImVec2(0,3), window->Color(ImGuiCol_Text));
|
||||||
}
|
|
||||||
|
// Notify OS of text input position
|
||||||
|
if (io.ImeSetInputScreenPosFn && ImLength(edit_state.LastCursorPos - cursor_pos) > 0.01f)
|
||||||
|
io.ImeSetInputScreenPosFn((int)cursor_pos.x - 1, (int)(cursor_pos.y - window->FontSize())); // -1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.
|
||||||
|
|
||||||
|
edit_state.LastCursorPos = cursor_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||||
@ -5386,7 +5435,140 @@ const ImBitmapFont::FntGlyph* ImBitmapFont::FindGlyph(unsigned short c) const
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 ImBitmapFont::CalcTextSize(float size, float max_width, const char* text_begin, const char* text_end, const char** remaining) const
|
// Convert UTF-8 to 32-bits character, process single character input.
|
||||||
|
// Based on stb_from_utf8() from github.com/nothings/stb/
|
||||||
|
static int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
|
||||||
|
{
|
||||||
|
if (*in_text != 0)
|
||||||
|
{
|
||||||
|
unsigned int c = -1;
|
||||||
|
const unsigned char* str = (const unsigned char*)in_text;
|
||||||
|
if (!(*str & 0x80))
|
||||||
|
{
|
||||||
|
c = (unsigned int)(*str++);
|
||||||
|
*out_char = c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((*str & 0xe0) == 0xc0)
|
||||||
|
{
|
||||||
|
if (in_text_end && in_text_end - (const char*)str < 2) return -1;
|
||||||
|
if (*str < 0xc2) return -1;
|
||||||
|
c = (*str++ & 0x1f) << 6;
|
||||||
|
if ((*str & 0xc0) != 0x80) return -1;
|
||||||
|
c += (*str++ & 0x3f);
|
||||||
|
*out_char = c;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if ((*str & 0xf0) == 0xe0)
|
||||||
|
{
|
||||||
|
if (in_text_end && in_text_end - (const char*)str < 3) return -1;
|
||||||
|
if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return -1;
|
||||||
|
if (*str == 0xed && str[1] > 0x9f) return -1; // str[1] < 0x80 is checked below
|
||||||
|
c = (*str++ & 0x0f) << 12;
|
||||||
|
if ((*str & 0xc0) != 0x80) return -1;
|
||||||
|
c += (*str++ & 0x3f) << 6;
|
||||||
|
if ((*str & 0xc0) != 0x80) return -1;
|
||||||
|
c += (*str++ & 0x3f);
|
||||||
|
*out_char = c;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if ((*str & 0xf8) == 0xf0)
|
||||||
|
{
|
||||||
|
if (in_text_end && in_text_end - (const char*)str < 4) return -1;
|
||||||
|
if (*str > 0xf4) return -1;
|
||||||
|
if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return -1;
|
||||||
|
if (*str == 0xf4 && str[1] > 0x8f) return -1; // str[1] < 0x80 is checked below
|
||||||
|
c = (*str++ & 0x07) << 18;
|
||||||
|
if ((*str & 0xc0) != 0x80) return -1;
|
||||||
|
c += (*str++ & 0x3f) << 12;
|
||||||
|
if ((*str & 0xc0) != 0x80) return -1;
|
||||||
|
c += (*str++ & 0x3f) << 6;
|
||||||
|
if ((*str & 0xc0) != 0x80) return -1;
|
||||||
|
c += (*str++ & 0x3f);
|
||||||
|
// utf-8 encodings of values used in surrogate pairs are invalid
|
||||||
|
if ((c & 0xFFFFF800) == 0xD800) return -1;
|
||||||
|
*out_char = c;
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out_char = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ImTextStrFromUtf8(ImWchar* buf, size_t buf_size, const char* in_text, const char* in_text_end)
|
||||||
|
{
|
||||||
|
ImWchar* buf_out = buf;
|
||||||
|
ImWchar* buf_end = buf + buf_size;
|
||||||
|
while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
|
||||||
|
{
|
||||||
|
unsigned int c;
|
||||||
|
in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
|
||||||
|
if (c < 0x10000) // FIXME: Losing characters that don't fit in 2 bytes
|
||||||
|
*buf_out++ = (ImWchar)c;
|
||||||
|
}
|
||||||
|
*buf_out = 0;
|
||||||
|
return buf_out - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on stb_to_utf8() from github.com/nothings/stb/
|
||||||
|
static int ImTextCharToUtf8(char* buf, size_t buf_size, unsigned int c)
|
||||||
|
{
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int n = (size_t)buf_size;
|
||||||
|
if (c < 0x80)
|
||||||
|
{
|
||||||
|
if (i+1 > n) return 0;
|
||||||
|
buf[i++] = (char)c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (c < 0x800)
|
||||||
|
{
|
||||||
|
if (i+2 > n) return 0;
|
||||||
|
buf[i++] = 0xc0 + (c >> 6);
|
||||||
|
buf[i++] = 0x80 + (c & 0x3f);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else if (c >= 0xdc00 && c < 0xe000)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (c >= 0xd800 && c < 0xdc00)
|
||||||
|
{
|
||||||
|
if (i+4 > n) return 0;
|
||||||
|
buf[i++] = 0xf0 + (c >> 18);
|
||||||
|
buf[i++] = 0x80 + ((c >> 12) & 0x3f);
|
||||||
|
buf[i++] = 0x80 + ((c >> 6) & 0x3f);
|
||||||
|
buf[i++] = 0x80 + ((c ) & 0x3f);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
//else if (c < 0x10000)
|
||||||
|
{
|
||||||
|
if (i+3 > n) return 0;
|
||||||
|
buf[i++] = 0xe0 + (c >> 12);
|
||||||
|
buf[i++] = 0x80 + ((c>> 6) & 0x3f);
|
||||||
|
buf[i++] = 0x80 + ((c ) & 0x3f);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ImTextStrToUtf8(char* buf, size_t buf_size, const ImWchar* in_text, const ImWchar* in_text_end)
|
||||||
|
{
|
||||||
|
char* buf_out = buf;
|
||||||
|
const char* buf_end = buf + buf_size;
|
||||||
|
while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
|
||||||
|
{
|
||||||
|
buf_out += ImTextCharToUtf8(buf_out, buf_end-buf_out-1, (unsigned int)*in_text);
|
||||||
|
in_text++;
|
||||||
|
}
|
||||||
|
*buf_out = 0;
|
||||||
|
return buf_out - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec2 ImBitmapFont::CalcTextSizeA(float size, float max_width, const char* text_begin, const char* text_end, const char** remaining) const
|
||||||
{
|
{
|
||||||
if (max_width == 0.0f)
|
if (max_width == 0.0f)
|
||||||
max_width = FLT_MAX;
|
max_width = FLT_MAX;
|
||||||
@ -5395,6 +5577,7 @@ ImVec2 ImBitmapFont::CalcTextSize(float size, float max_width, const char* text_
|
|||||||
|
|
||||||
const float scale = size / (float)Info->FontSize;
|
const float scale = size / (float)Info->FontSize;
|
||||||
const float line_height = (float)Info->FontSize * scale;
|
const float line_height = (float)Info->FontSize * scale;
|
||||||
|
const FntGlyph* fallback_glyph = FindGlyph(GImGui.IO.FontFallbackGlyph);
|
||||||
|
|
||||||
ImVec2 text_size = ImVec2(0,0);
|
ImVec2 text_size = ImVec2(0,0);
|
||||||
float line_width = 0.0f;
|
float line_width = 0.0f;
|
||||||
@ -5402,7 +5585,10 @@ ImVec2 ImBitmapFont::CalcTextSize(float size, float max_width, const char* text_
|
|||||||
const char* s = text_begin;
|
const char* s = text_begin;
|
||||||
while (s < text_end)
|
while (s < text_end)
|
||||||
{
|
{
|
||||||
const char c = *s;
|
unsigned int c;
|
||||||
|
const int bytes_count = ImTextCharFromUtf8(&c, s, text_end);
|
||||||
|
s += bytes_count > 0 ? bytes_count : 1; // Handle decoding failure by skipping to next byte
|
||||||
|
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
{
|
{
|
||||||
if (text_size.x < line_width)
|
if (text_size.x < line_width)
|
||||||
@ -5410,22 +5596,87 @@ ImVec2 ImBitmapFont::CalcTextSize(float size, float max_width, const char* text_
|
|||||||
text_size.y += line_height;
|
text_size.y += line_height;
|
||||||
line_width = 0;
|
line_width = 0;
|
||||||
}
|
}
|
||||||
else if (const FntGlyph* glyph = FindGlyph((unsigned short)c))
|
else if (c == '\t')
|
||||||
|
{
|
||||||
|
// FIXME: Better TAB handling needed.
|
||||||
|
if (const FntGlyph* glyph = FindGlyph((unsigned short)' '))
|
||||||
|
line_width += (glyph->XAdvance + Info->SpacingHoriz) * 4 * scale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const FntGlyph* glyph = FindGlyph((unsigned short)c);
|
||||||
|
if (!glyph)
|
||||||
|
glyph = fallback_glyph;
|
||||||
|
if (glyph)
|
||||||
{
|
{
|
||||||
const float char_width = (glyph->XAdvance + Info->SpacingHoriz) * scale;
|
const float char_width = (glyph->XAdvance + Info->SpacingHoriz) * scale;
|
||||||
//const float char_extend = (glyph->XOffset + glyph->Width * scale);
|
//const float char_extend = (glyph->XOffset + glyph->Width * scale);
|
||||||
|
|
||||||
if (line_width + char_width >= max_width)
|
if (line_width + char_width >= max_width)
|
||||||
break;
|
break;
|
||||||
line_width += char_width;
|
line_width += char_width;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_width > 0 || text_size.y == 0.0f)
|
||||||
|
{
|
||||||
|
if (text_size.x < line_width)
|
||||||
|
text_size.x = line_width;
|
||||||
|
text_size.y += line_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remaining)
|
||||||
|
*remaining = s;
|
||||||
|
|
||||||
|
return text_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec2 ImBitmapFont::CalcTextSizeW(float size, float max_width, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining) const
|
||||||
|
{
|
||||||
|
if (max_width == 0.0f)
|
||||||
|
max_width = FLT_MAX;
|
||||||
|
if (!text_end)
|
||||||
|
text_end = text_begin + ImStrlenW(text_begin);
|
||||||
|
|
||||||
|
const float scale = size / (float)Info->FontSize;
|
||||||
|
const float line_height = (float)Info->FontSize * scale;
|
||||||
|
const FntGlyph* fallback_glyph = FindGlyph(GImGui.IO.FontFallbackGlyph);
|
||||||
|
|
||||||
|
ImVec2 text_size = ImVec2(0,0);
|
||||||
|
float line_width = 0.0f;
|
||||||
|
|
||||||
|
const ImWchar* s = text_begin;
|
||||||
|
while (s < text_end)
|
||||||
|
{
|
||||||
|
const unsigned int c = (unsigned int)(*s++);
|
||||||
|
|
||||||
|
if (c == '\n')
|
||||||
|
{
|
||||||
|
if (text_size.x < line_width)
|
||||||
|
text_size.x = line_width;
|
||||||
|
text_size.y += line_height;
|
||||||
|
line_width = 0;
|
||||||
|
}
|
||||||
else if (c == '\t')
|
else if (c == '\t')
|
||||||
{
|
{
|
||||||
|
// FIXME: Better TAB handling needed.
|
||||||
if (const FntGlyph* glyph = FindGlyph((unsigned short)' '))
|
if (const FntGlyph* glyph = FindGlyph((unsigned short)' '))
|
||||||
line_width += (glyph->XAdvance + Info->SpacingHoriz) * 4 * scale;
|
line_width += (glyph->XAdvance + Info->SpacingHoriz) * 4 * scale;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
s += 1;
|
{
|
||||||
|
const FntGlyph* glyph = FindGlyph((unsigned short)c);
|
||||||
|
if (!glyph)
|
||||||
|
glyph = fallback_glyph;
|
||||||
|
if (glyph)
|
||||||
|
{
|
||||||
|
const float char_width = (glyph->XAdvance + Info->SpacingHoriz) * scale;
|
||||||
|
//const float char_extend = (glyph->XOffset + glyph->Width * scale);
|
||||||
|
if (line_width + char_width >= max_width)
|
||||||
|
break;
|
||||||
|
line_width += char_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line_width > 0 || text_size.y == 0.0f)
|
if (line_width > 0 || text_size.y == 0.0f)
|
||||||
@ -5451,6 +5702,7 @@ void ImBitmapFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& c
|
|||||||
const float tex_scale_x = 1.0f / (float)Common->ScaleW;
|
const float tex_scale_x = 1.0f / (float)Common->ScaleW;
|
||||||
const float tex_scale_y = 1.0f / (float)(Common->ScaleH);
|
const float tex_scale_y = 1.0f / (float)(Common->ScaleH);
|
||||||
const float outline = (float)Info->Outline;
|
const float outline = (float)Info->Outline;
|
||||||
|
const FntGlyph* fallback_glyph = FindGlyph(GImGui.IO.FontFallbackGlyph);
|
||||||
|
|
||||||
// Align to be pixel perfect
|
// Align to be pixel perfect
|
||||||
pos.x = (float)(int)pos.x;
|
pos.x = (float)(int)pos.x;
|
||||||
@ -5460,9 +5712,14 @@ void ImBitmapFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& c
|
|||||||
|
|
||||||
float x = pos.x;
|
float x = pos.x;
|
||||||
float y = pos.y;
|
float y = pos.y;
|
||||||
for (const char* s = text_begin; s < text_end; s++)
|
for (const char* s = text_begin; s < text_end; )
|
||||||
{
|
{
|
||||||
const char c = *s;
|
unsigned int c;
|
||||||
|
const int bytes_count = ImTextCharFromUtf8(&c, s, text_end);
|
||||||
|
s += bytes_count > 0 ? bytes_count : 1; // Handle decoding failure by skipping to next byte
|
||||||
|
if (c >= 0x10000)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
{
|
{
|
||||||
x = pos.x;
|
x = pos.x;
|
||||||
@ -5470,7 +5727,10 @@ void ImBitmapFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& c
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const FntGlyph* glyph = FindGlyph((unsigned short)c))
|
const FntGlyph* glyph = FindGlyph((unsigned short)c);
|
||||||
|
if (!glyph)
|
||||||
|
glyph = fallback_glyph;
|
||||||
|
if (glyph)
|
||||||
{
|
{
|
||||||
const float char_width = (glyph->XAdvance + Info->SpacingHoriz) * scale;
|
const float char_width = (glyph->XAdvance + Info->SpacingHoriz) * scale;
|
||||||
//const float char_extend = (glyph->XOffset + glyph->Width * scale);
|
//const float char_extend = (glyph->XOffset + glyph->Width * scale);
|
||||||
@ -5562,12 +5822,11 @@ static const char* GetClipboardTextFn_DefaultImpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Win32 API clipboard implementation
|
// Win32 API clipboard implementation
|
||||||
static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_end)
|
static void SetClipboardTextFn_DefaultImpl(const char* text)
|
||||||
{
|
{
|
||||||
if (!OpenClipboard(NULL))
|
if (!OpenClipboard(NULL))
|
||||||
return;
|
return;
|
||||||
if (!text_end)
|
const char* text_end = text + strlen(text);
|
||||||
text_end = text + strlen(text);
|
|
||||||
const int buf_length = (int)(text_end - text) + 1;
|
const int buf_length = (int)(text_end - text) + 1;
|
||||||
HGLOBAL buf_handle = GlobalAlloc(GMEM_MOVEABLE, buf_length * sizeof(char));
|
HGLOBAL buf_handle = GlobalAlloc(GMEM_MOVEABLE, buf_length * sizeof(char));
|
||||||
if (buf_handle == NULL)
|
if (buf_handle == NULL)
|
||||||
@ -5590,15 +5849,14 @@ static const char* GetClipboardTextFn_DefaultImpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
|
// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
|
||||||
static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_end)
|
static void SetClipboardTextFn_DefaultImpl(const char* text)
|
||||||
{
|
{
|
||||||
if (GImGui.PrivateClipboard)
|
if (GImGui.PrivateClipboard)
|
||||||
{
|
{
|
||||||
ImGui::MemFree(GImGui.PrivateClipboard);
|
ImGui::MemFree(GImGui.PrivateClipboard);
|
||||||
GImGui.PrivateClipboard = NULL;
|
GImGui.PrivateClipboard = NULL;
|
||||||
}
|
}
|
||||||
if (!text_end)
|
const char* text_end = text + strlen(text);
|
||||||
text_end = text + strlen(text);
|
|
||||||
GImGui.PrivateClipboard = (char*)ImGui::MemAlloc((size_t)(text_end - text) + 1);
|
GImGui.PrivateClipboard = (char*)ImGui::MemAlloc((size_t)(text_end - text) + 1);
|
||||||
memcpy(GImGui.PrivateClipboard, text, (size_t)(text_end - text));
|
memcpy(GImGui.PrivateClipboard, text, (size_t)(text_end - text));
|
||||||
GImGui.PrivateClipboard[(size_t)(text_end - text)] = 0;
|
GImGui.PrivateClipboard[(size_t)(text_end - text)] = 0;
|
||||||
@ -5798,6 +6056,22 @@ void ShowTestWindow(bool* open)
|
|||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::TreeNode("UTF-8 Text"))
|
||||||
|
{
|
||||||
|
// UTF-8 test (need a suitable font, try extra_fonts/mplus* files for example)
|
||||||
|
// Most compiler appears to support UTF-8 in source code (with Visual Studio you need to save your file as 'UTF-8 without signature')
|
||||||
|
// However for the sake for maximum portability here we are *not* including raw UTF-8 character in this source file, instead we encode the string with with hexadecimal constants.
|
||||||
|
// In your own application please be reasonable and use UTF-8 in the source or get the data from external files. :)
|
||||||
|
//const char* utf8_string = "\xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93\x20\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; // Japanese text for "Kakikukeo" (Hiragana) followed by "Nihongo" (kanji)
|
||||||
|
ImGui::Text("(CJK text will only appears if the font supports it. Please check in\nthe extra_fonts/ folder if you intend to use non-ASCII characters.\nNote that characters values are preserved even if the font cannot be\ndisplayed, so you can safely copy & paste garbled characters.)");
|
||||||
|
ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
|
||||||
|
ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
|
||||||
|
static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
|
||||||
|
ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int e = 0;
|
static int e = 0;
|
||||||
ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
|
ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
|
||||||
ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
|
ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
|
||||||
|
48
imgui.h
48
imgui.h
@ -1,4 +1,4 @@
|
|||||||
// ImGui library v1.12
|
// ImGui library v1.13
|
||||||
// See .cpp file for commentary.
|
// See .cpp file for commentary.
|
||||||
// See ImGui::ShowTestWindow() for sample code.
|
// See ImGui::ShowTestWindow() for sample code.
|
||||||
// Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase.
|
// Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase.
|
||||||
@ -17,6 +17,7 @@ struct ImGuiWindow;
|
|||||||
#include "imconfig.h"
|
#include "imconfig.h"
|
||||||
#include <float.h> // FLT_MAX
|
#include <float.h> // FLT_MAX
|
||||||
#include <stdarg.h> // va_list
|
#include <stdarg.h> // va_list
|
||||||
|
#include <stddef.h> // ptrdiff_t
|
||||||
#include <stdlib.h> // NULL, malloc
|
#include <stdlib.h> // NULL, malloc
|
||||||
|
|
||||||
#ifndef IM_ASSERT
|
#ifndef IM_ASSERT
|
||||||
@ -25,6 +26,7 @@ struct ImGuiWindow;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef unsigned int ImU32;
|
typedef unsigned int ImU32;
|
||||||
|
typedef unsigned short ImWchar;
|
||||||
typedef ImU32 ImGuiID;
|
typedef ImU32 ImGuiID;
|
||||||
typedef int ImGuiCol; // enum ImGuiCol_
|
typedef int ImGuiCol; // enum ImGuiCol_
|
||||||
typedef int ImGuiKey; // enum ImGuiKey_
|
typedef int ImGuiKey; // enum ImGuiKey_
|
||||||
@ -400,7 +402,10 @@ struct ImGuiStyle
|
|||||||
// Read 'Programmer guide' section in .cpp file for general usage.
|
// Read 'Programmer guide' section in .cpp file for general usage.
|
||||||
struct ImGuiIO
|
struct ImGuiIO
|
||||||
{
|
{
|
||||||
|
//------------------------------------------------------------------
|
||||||
// Settings (fill once) // Default value:
|
// Settings (fill once) // Default value:
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
ImVec2 DisplaySize; // <unset> // Display size, in pixels. For clamping windows positions.
|
ImVec2 DisplaySize; // <unset> // Display size, in pixels. For clamping windows positions.
|
||||||
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
|
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
|
||||||
float IniSavingRate; // = 5.0f // Maximum time between saving .ini file, in seconds. Set to a negative value to disable .ini saving.
|
float IniSavingRate; // = 5.0f // Maximum time between saving .ini file, in seconds. Set to a negative value to disable .ini saving.
|
||||||
@ -414,42 +419,56 @@ struct ImGuiIO
|
|||||||
ImVec2 FontTexUvForWhite; // = (0.0f,0.0f) // Font texture must have a white pixel at this UV coordinate. Adjust if you are using custom texture.
|
ImVec2 FontTexUvForWhite; // = (0.0f,0.0f) // Font texture must have a white pixel at this UV coordinate. Adjust if you are using custom texture.
|
||||||
float FontBaseScale; // = 1.0f // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale()
|
float FontBaseScale; // = 1.0f // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale()
|
||||||
bool FontAllowUserScaling; // = false // Set to allow scaling text with CTRL+Wheel.
|
bool FontAllowUserScaling; // = false // Set to allow scaling text with CTRL+Wheel.
|
||||||
|
ImWchar FontFallbackGlyph; // = '?' // Replacement glyph is one isn't found.
|
||||||
float PixelCenterOffset; // = 0.0f // Try to set to 0.5f or 0.375f if rendering is blurry
|
float PixelCenterOffset; // = 0.0f // Try to set to 0.5f or 0.375f if rendering is blurry
|
||||||
|
|
||||||
// Settings - Rendering function (REQUIRED)
|
//------------------------------------------------------------------
|
||||||
|
// User Functions
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
// REQUIRED: rendering function.
|
||||||
// See example code if you are unsure of how to implement this.
|
// See example code if you are unsure of how to implement this.
|
||||||
void (*RenderDrawListsFn)(ImDrawList** const draw_lists, int count);
|
void (*RenderDrawListsFn)(ImDrawList** const draw_lists, int count);
|
||||||
|
|
||||||
// Settings - Clipboard Support
|
// Optional: access OS clipboard (default to use native Win32 clipboard on Windows, otherwise use a ImGui private clipboard)
|
||||||
// Override to provide your clipboard handlers.
|
// Override to access OS clipboard on other architectures.
|
||||||
// On Windows architecture, defaults to use the native Win32 clipboard, otherwise default to use a ImGui private clipboard.
|
|
||||||
// NB- for SetClipboardTextFn, the string is *NOT* zero-terminated at 'text_end'
|
|
||||||
const char* (*GetClipboardTextFn)();
|
const char* (*GetClipboardTextFn)();
|
||||||
void (*SetClipboardTextFn)(const char* text, const char* text_end);
|
void (*SetClipboardTextFn)(const char* text);
|
||||||
|
|
||||||
// Settings - Memory allocation
|
// Optional: override memory allocations (default to posix malloc/realloc/free)
|
||||||
// Default to posix malloc/realloc/free functions.
|
|
||||||
void* (*MemAllocFn)(size_t sz);
|
void* (*MemAllocFn)(size_t sz);
|
||||||
void* (*MemReallocFn)(void* ptr, size_t sz);
|
void* (*MemReallocFn)(void* ptr, size_t sz);
|
||||||
void (*MemFreeFn)(void* ptr);
|
void (*MemFreeFn)(void* ptr);
|
||||||
|
|
||||||
|
// Optional: notify OS Input Method Editor of text input position (e.g. when using Japanese/Chinese inputs, otherwise this isn't needed)
|
||||||
|
void (*ImeSetInputScreenPosFn)(int x, int y);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
// Input - Fill before calling NewFrame()
|
// Input - Fill before calling NewFrame()
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||||
bool MouseDown[5]; // Mouse buttons. ImGui itself only uses button 0 (left button) but you can use others as storage for convenience.
|
bool MouseDown[5]; // Mouse buttons. ImGui itself only uses button 0 (left button) but you can use others as storage for convenience.
|
||||||
int MouseWheel; // Mouse wheel: -1,0,+1
|
int MouseWheel; // Mouse wheel: -1,0,+1
|
||||||
bool KeyCtrl; // Keyboard modifier pressed: Control
|
bool KeyCtrl; // Keyboard modifier pressed: Control
|
||||||
bool KeyShift; // Keyboard modifier pressed: Shift
|
bool KeyShift; // Keyboard modifier pressed: Shift
|
||||||
bool KeysDown[512]; // Keyboard keys that are pressed (in whatever order user naturally has access to keyboard data)
|
bool KeysDown[512]; // Keyboard keys that are pressed (in whatever order user naturally has access to keyboard data)
|
||||||
char InputCharacters[16]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper.
|
ImWchar InputCharacters[16]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper.
|
||||||
|
|
||||||
|
// Function
|
||||||
|
void AddInputCharacter(ImWchar); // Helper to add a new character into InputCharacters[]
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
// Output - Retrieve after calling NewFrame(), you can use them to discard inputs or hide them from the rest of your application
|
// Output - Retrieve after calling NewFrame(), you can use them to discard inputs or hide them from the rest of your application
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input)
|
bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input)
|
||||||
bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input)
|
bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input)
|
||||||
|
|
||||||
// Function
|
//------------------------------------------------------------------
|
||||||
void AddInputCharacter(char c); // Helper to add a new character into InputCharacters[]
|
|
||||||
|
|
||||||
// [Internal] ImGui will maintain those fields for you
|
// [Internal] ImGui will maintain those fields for you
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
ImVec2 MousePosPrev;
|
ImVec2 MousePosPrev;
|
||||||
ImVec2 MouseDelta;
|
ImVec2 MouseDelta;
|
||||||
bool MouseClicked[5];
|
bool MouseClicked[5];
|
||||||
@ -670,6 +689,7 @@ struct ImBitmapFont
|
|||||||
float GetFontSize() const { return (float)Info->FontSize; }
|
float GetFontSize() const { return (float)Info->FontSize; }
|
||||||
bool IsLoaded() const { return Info != NULL && Common != NULL && Glyphs != NULL; }
|
bool IsLoaded() const { return Info != NULL && Common != NULL && Glyphs != NULL; }
|
||||||
|
|
||||||
ImVec2 CalcTextSize(float size, float max_width, const char* text_begin, const char* text_end, const char** remaining = NULL) const;
|
ImVec2 CalcTextSizeA(float size, float max_width, const char* text_begin, const char* text_end, const char** remaining = NULL) const; // utf8
|
||||||
|
ImVec2 CalcTextSizeW(float size, float max_width, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL) const; // wchar
|
||||||
void RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, ImDrawVert*& out_vertices) const;
|
void RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, ImDrawVert*& out_vertices) const;
|
||||||
};
|
};
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 7.1 KiB |
BIN
web/utf8_sample_01.png
Normal file
BIN
web/utf8_sample_01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
Reference in New Issue
Block a user