parent
a3b62775cd
commit
20a30d9192
|
@ -1,6 +1,6 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014-2024 Omar Cornut
|
Copyright (c) 2014-2018 Omar Cornut
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,131 +1,72 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// DEAR IMGUI COMPILE-TIME OPTIONS
|
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
|
||||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
|
// A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h)
|
||||||
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
|
// B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h"
|
||||||
//-----------------------------------------------------------------------------
|
// If you do so you need to make sure that configuration settings are defined consistently _everywhere_ dear imgui is used, which include
|
||||||
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
// the imgui*.cpp files but also _any_ of your code that uses imgui. This is because some compile-time options have an affect on data structures.
|
||||||
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
|
||||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||||
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//---- Define assertion handler. Defaults to calling assert().
|
//---- Define assertion handler. Defaults to calling assert().
|
||||||
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
|
||||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||||
|
|
||||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.
|
||||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
|
||||||
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
|
||||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
|
||||||
//#define IMGUI_API __declspec( dllexport )
|
//#define IMGUI_API __declspec( dllexport )
|
||||||
//#define IMGUI_API __declspec( dllimport )
|
//#define IMGUI_API __declspec( dllimport )
|
||||||
|
|
||||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
|
//---- Don't define obsolete functions/enums names. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
|
||||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87+ disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This is automatically done by IMGUI_DISABLE_OBSOLETE_FUNCTIONS.
|
|
||||||
|
|
||||||
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
//---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
|
||||||
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
//---- It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp.
|
||||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
//#define IMGUI_DISABLE_DEMO_WINDOWS
|
||||||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
|
||||||
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
|
|
||||||
|
|
||||||
//---- Don't implement some functions to reduce linkage requirements.
|
//---- Don't implement some functions to reduce linkage requirements.
|
||||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
|
||||||
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
|
||||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself if you don't want to link with vsnprintf.
|
||||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
//#define IMGUI_DISABLE_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 wrapper so you can implement them yourself. Declare your prototypes in imconfig.h.
|
||||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
|
||||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
|
||||||
|
|
||||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||||
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
|
|
||||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||||
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
|
|
||||||
|
|
||||||
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||||
|
|
||||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
|
||||||
//#define IMGUI_USE_WCHAR32
|
|
||||||
|
|
||||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
// By default the embedded implementations are declared static and not available outside of imgui cpp files.
|
||||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
|
|
||||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||||
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
|
|
||||||
|
|
||||||
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
|
||||||
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
|
||||||
//#define IMGUI_USE_STB_SPRINTF
|
|
||||||
|
|
||||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
|
||||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
|
||||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
|
||||||
//#define IMGUI_ENABLE_FREETYPE
|
|
||||||
|
|
||||||
//---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT)
|
|
||||||
// Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided).
|
|
||||||
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
|
||||||
// (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
|
||||||
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
|
||||||
|
|
||||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
|
||||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
|
||||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
|
||||||
|
|
||||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||||
/*
|
/*
|
||||||
#define IM_VEC2_CLASS_EXTRA \
|
#define IM_VEC2_CLASS_EXTRA \
|
||||||
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
|
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
|
||||||
operator MyVec2() const { return MyVec2(x,y); }
|
operator MyVec2() const { return MyVec2(x,y); }
|
||||||
|
|
||||||
#define IM_VEC4_CLASS_EXTRA \
|
#define IM_VEC4_CLASS_EXTRA \
|
||||||
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
|
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
|
||||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||||
*/
|
*/
|
||||||
//---- ...Or use Dear ImGui's own very basic math operators.
|
|
||||||
//#define IMGUI_DEFINE_MATH_OPERATORS
|
|
||||||
|
|
||||||
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
//---- Use 32-bit vertex indices (default is 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it.
|
||||||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
|
||||||
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
|
||||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
|
||||||
//#define ImDrawIdx unsigned int
|
//#define ImDrawIdx unsigned int
|
||||||
|
|
||||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||||
//struct ImDrawList;
|
|
||||||
//struct ImDrawCmd;
|
|
||||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
|
||||||
//#define ImDrawCallback MyImDrawCallback
|
|
||||||
|
|
||||||
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
|
|
||||||
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
|
||||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
|
||||||
//#define IM_DEBUG_BREAK __debugbreak()
|
|
||||||
|
|
||||||
//---- Debug Tools: Enable slower asserts
|
|
||||||
//#define IMGUI_DEBUG_PARANOID
|
|
||||||
|
|
||||||
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
|
|
||||||
/*
|
/*
|
||||||
namespace ImGui
|
namespace ImGui
|
||||||
{
|
{
|
||||||
void MyFunction(const char* name, MyMatrix44* mtx);
|
void MyFunction(const char* name, const MyMatrix44& v);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,19 +1,9 @@
|
||||||
// [DEAR IMGUI]
|
// stb_rect_pack.h - v0.11 - public domain - rectangle packing
|
||||||
// This is a slightly modified version of stb_rect_pack.h 1.01.
|
|
||||||
// Grep for [DEAR IMGUI] to find the changes.
|
|
||||||
//
|
|
||||||
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
|
|
||||||
// Sean Barrett 2014
|
// Sean Barrett 2014
|
||||||
//
|
//
|
||||||
// Useful for e.g. packing rectangular textures into an atlas.
|
// Useful for e.g. packing rectangular textures into an atlas.
|
||||||
// Does not do rotation.
|
// Does not do rotation.
|
||||||
//
|
//
|
||||||
// Before #including,
|
|
||||||
//
|
|
||||||
// #define STB_RECT_PACK_IMPLEMENTATION
|
|
||||||
//
|
|
||||||
// in the file that you want to have the implementation.
|
|
||||||
//
|
|
||||||
// Not necessarily the awesomest packing method, but better than
|
// Not necessarily the awesomest packing method, but better than
|
||||||
// the totally naive one in stb_truetype (which is primarily what
|
// the totally naive one in stb_truetype (which is primarily what
|
||||||
// this is meant to replace).
|
// this is meant to replace).
|
||||||
|
@ -41,13 +31,9 @@
|
||||||
//
|
//
|
||||||
// Bugfixes / warning fixes
|
// Bugfixes / warning fixes
|
||||||
// Jeremy Jaussaud
|
// Jeremy Jaussaud
|
||||||
// Fabian Giesen
|
|
||||||
//
|
//
|
||||||
// Version history:
|
// Version history:
|
||||||
//
|
//
|
||||||
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
|
|
||||||
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
|
|
||||||
// 0.99 (2019-02-07) warning fixes
|
|
||||||
// 0.11 (2017-03-03) return packing success/fail result
|
// 0.11 (2017-03-03) return packing success/fail result
|
||||||
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||||
// 0.09 (2016-08-27) fix compiler warnings
|
// 0.09 (2016-08-27) fix compiler warnings
|
||||||
|
@ -86,10 +72,11 @@ typedef struct stbrp_context stbrp_context;
|
||||||
typedef struct stbrp_node stbrp_node;
|
typedef struct stbrp_node stbrp_node;
|
||||||
typedef struct stbrp_rect stbrp_rect;
|
typedef struct stbrp_rect stbrp_rect;
|
||||||
|
|
||||||
|
#ifdef STBRP_LARGE_RECTS
|
||||||
typedef int stbrp_coord;
|
typedef int stbrp_coord;
|
||||||
|
#else
|
||||||
#define STBRP__MAXVAL 0x7fffffff
|
typedef unsigned short stbrp_coord;
|
||||||
// Mostly for internal use, but this is the maximum supported coordinate value.
|
#endif
|
||||||
|
|
||||||
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||||
// Assign packed locations to rectangles. The rectangles are of type
|
// Assign packed locations to rectangles. The rectangles are of type
|
||||||
|
@ -265,6 +252,9 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
|
||||||
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
#ifndef STBRP_LARGE_RECTS
|
||||||
|
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (i=0; i < num_nodes-1; ++i)
|
for (i=0; i < num_nodes-1; ++i)
|
||||||
nodes[i].next = &nodes[i+1];
|
nodes[i].next = &nodes[i+1];
|
||||||
|
@ -283,7 +273,11 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
|
||||||
context->extra[0].y = 0;
|
context->extra[0].y = 0;
|
||||||
context->extra[0].next = &context->extra[1];
|
context->extra[0].next = &context->extra[1];
|
||||||
context->extra[1].x = (stbrp_coord) width;
|
context->extra[1].x = (stbrp_coord) width;
|
||||||
|
#ifdef STBRP_LARGE_RECTS
|
||||||
context->extra[1].y = (1<<30);
|
context->extra[1].y = (1<<30);
|
||||||
|
#else
|
||||||
|
context->extra[1].y = 65535;
|
||||||
|
#endif
|
||||||
context->extra[1].next = NULL;
|
context->extra[1].next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,13 +349,6 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
||||||
width -= width % c->align;
|
width -= width % c->align;
|
||||||
STBRP_ASSERT(width % c->align == 0);
|
STBRP_ASSERT(width % c->align == 0);
|
||||||
|
|
||||||
// if it can't possibly fit, bail immediately
|
|
||||||
if (width > c->width || height > c->height) {
|
|
||||||
fr.prev_link = NULL;
|
|
||||||
fr.x = fr.y = 0;
|
|
||||||
return fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = c->active_head;
|
node = c->active_head;
|
||||||
prev = &c->active_head;
|
prev = &c->active_head;
|
||||||
while (node->x + width <= c->width) {
|
while (node->x + width <= c->width) {
|
||||||
|
@ -425,11 +412,11 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
||||||
}
|
}
|
||||||
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
||||||
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
||||||
if (y + height <= c->height) {
|
if (y + height < c->height) {
|
||||||
if (y <= best_y) {
|
if (y <= best_y) {
|
||||||
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||||
best_x = xpos;
|
best_x = xpos;
|
||||||
//STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
|
STBRP_ASSERT(y <= best_y);
|
||||||
best_y = y;
|
best_y = y;
|
||||||
best_waste = waste;
|
best_waste = waste;
|
||||||
best = prev;
|
best = prev;
|
||||||
|
@ -543,6 +530,12 @@ static int STBRP__CDECL rect_original_order(const void *a, const void *b)
|
||||||
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef STBRP_LARGE_RECTS
|
||||||
|
#define STBRP__MAXVAL 0xffffffff
|
||||||
|
#else
|
||||||
|
#define STBRP__MAXVAL 0xffff
|
||||||
|
#endif
|
||||||
|
|
||||||
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||||
{
|
{
|
||||||
int i, all_rects_packed = 1;
|
int i, all_rects_packed = 1;
|
||||||
|
@ -550,6 +543,9 @@ STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int nu
|
||||||
// we use the 'was_packed' field internally to allow sorting/unsorting
|
// we use the 'was_packed' field internally to allow sorting/unsorting
|
||||||
for (i=0; i < num_rects; ++i) {
|
for (i=0; i < num_rects; ++i) {
|
||||||
rects[i].was_packed = i;
|
rects[i].was_packed = i;
|
||||||
|
#ifndef STBRP_LARGE_RECTS
|
||||||
|
STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort according to heuristic
|
// sort according to heuristic
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
// [DEAR IMGUI]
|
// [ImGui] this is a slightly modified version of stb_textedit.h 1.12. Those changes would need to be pushed into nothings/stb
|
||||||
// This is a slightly modified version of stb_textedit.h 1.14.
|
// [ImGui] - 2018-06: fixed undo/redo after pasting large amount of text (over 32 kb). Redo will still fail when undo buffers are exhausted, but text won't be corrupted (see nothings/stb issue #620)
|
||||||
// Those changes would need to be pushed into nothings/stb:
|
// [ImGui] - 2018-06: fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
||||||
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
// [ImGui] - fixed some minor warnings
|
||||||
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
|
|
||||||
// Grep for [DEAR IMGUI] to find the changes.
|
|
||||||
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
|
|
||||||
|
|
||||||
// stb_textedit.h - v1.14 - public domain - Sean Barrett
|
// stb_textedit.h - v1.12 - public domain - Sean Barrett
|
||||||
// Development of this library was sponsored by RAD Game Tools
|
// Development of this library was sponsored by RAD Game Tools
|
||||||
//
|
//
|
||||||
// This C header file implements the guts of a multi-line text-editing
|
// This C header file implements the guts of a multi-line text-editing
|
||||||
|
@ -31,14 +28,12 @@
|
||||||
// DEPENDENCIES
|
// DEPENDENCIES
|
||||||
//
|
//
|
||||||
// Uses the C runtime function 'memmove', which you can override
|
// Uses the C runtime function 'memmove', which you can override
|
||||||
// by defining IMSTB_TEXTEDIT_memmove before the implementation.
|
// by defining STB_TEXTEDIT_memmove before the implementation.
|
||||||
// Uses no other functions. Performs no runtime allocations.
|
// Uses no other functions. Performs no runtime allocations.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// VERSION HISTORY
|
// VERSION HISTORY
|
||||||
//
|
//
|
||||||
// 1.14 (2021-07-11) page up/down, various fixes
|
|
||||||
// 1.13 (2019-02-07) fix bug in undo size management
|
|
||||||
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
||||||
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
|
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
|
||||||
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
|
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
|
||||||
|
@ -61,7 +56,6 @@
|
||||||
// Ulf Winklemann: move-by-word in 1.1
|
// Ulf Winklemann: move-by-word in 1.1
|
||||||
// Fabian Giesen: secondary key inputs in 1.5
|
// Fabian Giesen: secondary key inputs in 1.5
|
||||||
// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
|
// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
|
||||||
// Louis Schnellbach: page up/down in 1.14
|
|
||||||
//
|
//
|
||||||
// Bugfixes:
|
// Bugfixes:
|
||||||
// Scott Graham
|
// Scott Graham
|
||||||
|
@ -97,8 +91,8 @@
|
||||||
// moderate sizes. The undo system does no memory allocations, so
|
// moderate sizes. The undo system does no memory allocations, so
|
||||||
// it grows STB_TexteditState by the worst-case storage which is (in bytes):
|
// it grows STB_TexteditState by the worst-case storage which is (in bytes):
|
||||||
//
|
//
|
||||||
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT
|
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT
|
||||||
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT
|
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Implementation mode:
|
// Implementation mode:
|
||||||
|
@ -152,8 +146,6 @@
|
||||||
// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
|
// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
|
||||||
// STB_TEXTEDIT_K_UP keyboard input to move cursor up
|
// STB_TEXTEDIT_K_UP keyboard input to move cursor up
|
||||||
// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
|
// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
|
||||||
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
|
|
||||||
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
|
|
||||||
// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
|
// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
|
||||||
// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
|
// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
|
||||||
// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
|
// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
|
||||||
|
@ -176,10 +168,14 @@
|
||||||
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
|
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
|
||||||
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
|
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
|
||||||
//
|
//
|
||||||
|
// Todo:
|
||||||
|
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
|
||||||
|
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
|
||||||
|
//
|
||||||
// Keyboard input must be encoded as a single integer value; e.g. a character code
|
// Keyboard input must be encoded as a single integer value; e.g. a character code
|
||||||
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
|
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
|
||||||
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
|
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
|
||||||
// i.e. (STB_TEXTEDIT_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
|
// i.e. (STB_TEXTED_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
|
||||||
//
|
//
|
||||||
// You can encode other things, such as CONTROL or ALT, in additional bits, and
|
// You can encode other things, such as CONTROL or ALT, in additional bits, and
|
||||||
// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example,
|
// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example,
|
||||||
|
@ -275,8 +271,8 @@
|
||||||
////
|
////
|
||||||
////
|
////
|
||||||
|
|
||||||
#ifndef INCLUDE_IMSTB_TEXTEDIT_H
|
#ifndef INCLUDE_STB_TEXTEDIT_H
|
||||||
#define INCLUDE_IMSTB_TEXTEDIT_H
|
#define INCLUDE_STB_TEXTEDIT_H
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -287,33 +283,33 @@
|
||||||
// and undo state.
|
// and undo state.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef IMSTB_TEXTEDIT_UNDOSTATECOUNT
|
#ifndef STB_TEXTEDIT_UNDOSTATECOUNT
|
||||||
#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
|
#define STB_TEXTEDIT_UNDOSTATECOUNT 99
|
||||||
#endif
|
#endif
|
||||||
#ifndef IMSTB_TEXTEDIT_UNDOCHARCOUNT
|
#ifndef STB_TEXTEDIT_UNDOCHARCOUNT
|
||||||
#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
|
#define STB_TEXTEDIT_UNDOCHARCOUNT 999
|
||||||
#endif
|
#endif
|
||||||
#ifndef IMSTB_TEXTEDIT_CHARTYPE
|
#ifndef STB_TEXTEDIT_CHARTYPE
|
||||||
#define IMSTB_TEXTEDIT_CHARTYPE int
|
#define STB_TEXTEDIT_CHARTYPE int
|
||||||
#endif
|
#endif
|
||||||
#ifndef IMSTB_TEXTEDIT_POSITIONTYPE
|
#ifndef STB_TEXTEDIT_POSITIONTYPE
|
||||||
#define IMSTB_TEXTEDIT_POSITIONTYPE int
|
#define STB_TEXTEDIT_POSITIONTYPE int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
// private data
|
// private data
|
||||||
IMSTB_TEXTEDIT_POSITIONTYPE where;
|
STB_TEXTEDIT_POSITIONTYPE where;
|
||||||
IMSTB_TEXTEDIT_POSITIONTYPE insert_length;
|
STB_TEXTEDIT_POSITIONTYPE insert_length;
|
||||||
IMSTB_TEXTEDIT_POSITIONTYPE delete_length;
|
STB_TEXTEDIT_POSITIONTYPE delete_length;
|
||||||
int char_storage;
|
int char_storage;
|
||||||
} StbUndoRecord;
|
} StbUndoRecord;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
// private data
|
// private data
|
||||||
StbUndoRecord undo_rec [IMSTB_TEXTEDIT_UNDOSTATECOUNT];
|
StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
|
||||||
IMSTB_TEXTEDIT_CHARTYPE undo_char[IMSTB_TEXTEDIT_UNDOCHARCOUNT];
|
STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
|
||||||
short undo_point, redo_point;
|
short undo_point, redo_point;
|
||||||
int undo_char_point, redo_char_point;
|
int undo_char_point, redo_char_point;
|
||||||
} StbUndoState;
|
} StbUndoState;
|
||||||
|
@ -339,10 +335,6 @@ typedef struct
|
||||||
// each textfield keeps its own insert mode state. to keep an app-wide
|
// each textfield keeps its own insert mode state. to keep an app-wide
|
||||||
// insert mode, copy this value in/out of the app state
|
// insert mode, copy this value in/out of the app state
|
||||||
|
|
||||||
int row_count_per_page;
|
|
||||||
// page size in number of row.
|
|
||||||
// this value MUST be set to >0 for pageup or pagedown in multilines documents.
|
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
//
|
//
|
||||||
// private data
|
// private data
|
||||||
|
@ -372,7 +364,7 @@ typedef struct
|
||||||
float ymin,ymax; // height of row above and below baseline
|
float ymin,ymax; // height of row above and below baseline
|
||||||
int num_chars;
|
int num_chars;
|
||||||
} StbTexteditRow;
|
} StbTexteditRow;
|
||||||
#endif //INCLUDE_IMSTB_TEXTEDIT_H
|
#endif //INCLUDE_STB_TEXTEDIT_H
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -385,11 +377,11 @@ typedef struct
|
||||||
|
|
||||||
// implementation isn't include-guarded, since it might have indirectly
|
// implementation isn't include-guarded, since it might have indirectly
|
||||||
// included just the "header" portion
|
// included just the "header" portion
|
||||||
#ifdef IMSTB_TEXTEDIT_IMPLEMENTATION
|
#ifdef STB_TEXTEDIT_IMPLEMENTATION
|
||||||
|
|
||||||
#ifndef IMSTB_TEXTEDIT_memmove
|
#ifndef STB_TEXTEDIT_memmove
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#define IMSTB_TEXTEDIT_memmove memmove
|
#define STB_TEXTEDIT_memmove memmove
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -399,7 +391,7 @@ typedef struct
|
||||||
//
|
//
|
||||||
|
|
||||||
// traverse the layout to locate the nearest character to a display position
|
// traverse the layout to locate the nearest character to a display position
|
||||||
static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
|
static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
|
||||||
{
|
{
|
||||||
StbTexteditRow r;
|
StbTexteditRow r;
|
||||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||||
|
@ -459,7 +451,7 @@ static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
|
||||||
}
|
}
|
||||||
|
|
||||||
// API click: on mouse down, move the cursor to the clicked location, and reset the selection
|
// API click: on mouse down, move the cursor to the clicked location, and reset the selection
|
||||||
static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
||||||
{
|
{
|
||||||
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
|
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
|
||||||
// goes off the top or bottom of the text
|
// goes off the top or bottom of the text
|
||||||
|
@ -477,7 +469,7 @@ static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *st
|
||||||
}
|
}
|
||||||
|
|
||||||
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
|
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
|
||||||
static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
||||||
{
|
{
|
||||||
int p = 0;
|
int p = 0;
|
||||||
|
|
||||||
|
@ -503,11 +495,11 @@ static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *sta
|
||||||
//
|
//
|
||||||
|
|
||||||
// forward declarations
|
// forward declarations
|
||||||
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
||||||
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
||||||
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
|
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
|
||||||
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
|
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
|
||||||
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
|
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -519,21 +511,36 @@ typedef struct
|
||||||
|
|
||||||
// find the x/y location of a character, and remember info about the previous row in
|
// find the x/y location of a character, and remember info about the previous row in
|
||||||
// case we get a move-up event (for page up, we'll have to rescan)
|
// case we get a move-up event (for page up, we'll have to rescan)
|
||||||
static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING *str, int n, int single_line)
|
static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
|
||||||
{
|
{
|
||||||
StbTexteditRow r;
|
StbTexteditRow r;
|
||||||
int prev_start = 0;
|
int prev_start = 0;
|
||||||
int z = STB_TEXTEDIT_STRINGLEN(str);
|
int z = STB_TEXTEDIT_STRINGLEN(str);
|
||||||
int i=0, first;
|
int i=0, first;
|
||||||
|
|
||||||
if (n == z && single_line) {
|
if (n == z) {
|
||||||
// special case if it's at the end (may not be needed?)
|
// if it's at the end, then find the last line -- simpler than trying to
|
||||||
|
// explicitly handle this case in the regular code
|
||||||
|
if (single_line) {
|
||||||
STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
|
STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
|
||||||
find->y = 0;
|
find->y = 0;
|
||||||
find->first_char = 0;
|
find->first_char = 0;
|
||||||
find->length = z;
|
find->length = z;
|
||||||
find->height = r.ymax - r.ymin;
|
find->height = r.ymax - r.ymin;
|
||||||
find->x = r.x1;
|
find->x = r.x1;
|
||||||
|
} else {
|
||||||
|
find->y = 0;
|
||||||
|
find->x = 0;
|
||||||
|
find->height = 1;
|
||||||
|
while (i < z) {
|
||||||
|
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
|
||||||
|
prev_start = i;
|
||||||
|
i += r.num_chars;
|
||||||
|
}
|
||||||
|
find->first_char = i;
|
||||||
|
find->length = 0;
|
||||||
|
find->prev_first = prev_start;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,16 +551,9 @@ static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING
|
||||||
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
|
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
|
||||||
if (n < i + r.num_chars)
|
if (n < i + r.num_chars)
|
||||||
break;
|
break;
|
||||||
if (i + r.num_chars == z && z > 0 && STB_TEXTEDIT_GETCHAR(str, z - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] special handling for last line
|
|
||||||
break; // [DEAR IMGUI]
|
|
||||||
prev_start = i;
|
prev_start = i;
|
||||||
i += r.num_chars;
|
i += r.num_chars;
|
||||||
find->y += r.baseline_y_delta;
|
find->y += r.baseline_y_delta;
|
||||||
if (i == z) // [DEAR IMGUI]
|
|
||||||
{
|
|
||||||
r.num_chars = 0; // [DEAR IMGUI]
|
|
||||||
break; // [DEAR IMGUI]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
find->first_char = first = i;
|
find->first_char = first = i;
|
||||||
|
@ -563,6 +563,7 @@ static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING
|
||||||
|
|
||||||
// now scan to find xpos
|
// now scan to find xpos
|
||||||
find->x = r.x0;
|
find->x = r.x0;
|
||||||
|
i = 0;
|
||||||
for (i=0; first+i < n; ++i)
|
for (i=0; first+i < n; ++i)
|
||||||
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
|
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
|
||||||
}
|
}
|
||||||
|
@ -570,7 +571,7 @@ static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING
|
||||||
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
|
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
|
||||||
|
|
||||||
// make the selection/cursor state valid if client altered the string
|
// make the selection/cursor state valid if client altered the string
|
||||||
static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||||
|
@ -584,7 +585,7 @@ static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *st
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete characters while updating undo
|
// delete characters while updating undo
|
||||||
static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
|
static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
|
||||||
{
|
{
|
||||||
stb_text_makeundo_delete(str, state, where, len);
|
stb_text_makeundo_delete(str, state, where, len);
|
||||||
STB_TEXTEDIT_DELETECHARS(str, where, len);
|
STB_TEXTEDIT_DELETECHARS(str, where, len);
|
||||||
|
@ -592,7 +593,7 @@ static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *s
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete the section
|
// delete the section
|
||||||
static void stb_textedit_delete_selection(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||||
|
@ -629,7 +630,7 @@ static void stb_textedit_move_to_first(STB_TexteditState *state)
|
||||||
}
|
}
|
||||||
|
|
||||||
// move cursor to last character of selection
|
// move cursor to last character of selection
|
||||||
static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||||
stb_textedit_sortselection(state);
|
stb_textedit_sortselection(state);
|
||||||
|
@ -641,13 +642,13 @@ static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditSt
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef STB_TEXTEDIT_IS_SPACE
|
#ifdef STB_TEXTEDIT_IS_SPACE
|
||||||
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
|
||||||
{
|
{
|
||||||
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
|
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
|
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
|
||||||
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c )
|
static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
|
||||||
{
|
{
|
||||||
--c; // always move at least one character
|
--c; // always move at least one character
|
||||||
while( c >= 0 && !is_word_boundary( str, c ) )
|
while( c >= 0 && !is_word_boundary( str, c ) )
|
||||||
|
@ -662,7 +663,7 @@ static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
|
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
|
||||||
static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c )
|
static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
|
||||||
{
|
{
|
||||||
const int len = STB_TEXTEDIT_STRINGLEN(str);
|
const int len = STB_TEXTEDIT_STRINGLEN(str);
|
||||||
++c; // always move at least one character
|
++c; // always move at least one character
|
||||||
|
@ -689,10 +690,10 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
|
||||||
}
|
}
|
||||||
|
|
||||||
// API cut: delete selection
|
// API cut: delete selection
|
||||||
static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
stb_textedit_delete_selection(str,state); // implicity clamps
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -700,7 +701,7 @@ static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state
|
||||||
}
|
}
|
||||||
|
|
||||||
// API paste: replace existing selection with passed-in text
|
// API paste: replace existing selection with passed-in text
|
||||||
static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE *text, int len)
|
static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
|
||||||
{
|
{
|
||||||
// if there's a selection, the paste should delete it
|
// if there's a selection, the paste should delete it
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
|
@ -712,7 +713,9 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
|
// remove the undo since we didn't actually insert the characters
|
||||||
|
if (state->undostate.undo_point)
|
||||||
|
--state->undostate.undo_point;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,14 +724,14 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// API key: process a keyboard input
|
// API key: process a keyboard input
|
||||||
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
|
static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
|
||||||
{
|
{
|
||||||
retry:
|
retry:
|
||||||
switch (key) {
|
switch (key) {
|
||||||
default: {
|
default: {
|
||||||
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE) c;
|
STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;
|
||||||
|
|
||||||
// can't add newline in single-line mode
|
// can't add newline in single-line mode
|
||||||
if (c == '\n' && state->single_line)
|
if (c == '\n' && state->single_line)
|
||||||
|
@ -742,7 +745,7 @@ retry:
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
stb_textedit_delete_selection(str,state); // implicity clamps
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
||||||
stb_text_makeundo_insert(state, state->cursor, 1);
|
stb_text_makeundo_insert(state, state->cursor, 1);
|
||||||
++state->cursor;
|
++state->cursor;
|
||||||
|
@ -851,16 +854,12 @@ retry:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STB_TEXTEDIT_K_DOWN:
|
case STB_TEXTEDIT_K_DOWN:
|
||||||
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT:
|
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: {
|
||||||
case STB_TEXTEDIT_K_PGDOWN:
|
|
||||||
case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: {
|
|
||||||
StbFindState find;
|
StbFindState find;
|
||||||
StbTexteditRow row;
|
StbTexteditRow row;
|
||||||
int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
||||||
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN;
|
|
||||||
int row_count = is_page ? state->row_count_per_page : 1;
|
|
||||||
|
|
||||||
if (!is_page && state->single_line) {
|
if (state->single_line) {
|
||||||
// on windows, up&down in single-line behave like left&right
|
// on windows, up&down in single-line behave like left&right
|
||||||
key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
|
key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
|
||||||
goto retry;
|
goto retry;
|
||||||
|
@ -869,32 +868,24 @@ retry:
|
||||||
if (sel)
|
if (sel)
|
||||||
stb_textedit_prep_selection_at_cursor(state);
|
stb_textedit_prep_selection_at_cursor(state);
|
||||||
else if (STB_TEXT_HAS_SELECTION(state))
|
else if (STB_TEXT_HAS_SELECTION(state))
|
||||||
stb_textedit_move_to_last(str, state);
|
stb_textedit_move_to_last(str,state);
|
||||||
|
|
||||||
// compute current position of cursor point
|
// compute current position of cursor point
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||||
|
|
||||||
for (j = 0; j < row_count; ++j) {
|
|
||||||
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
|
||||||
int start = find.first_char + find.length;
|
|
||||||
|
|
||||||
if (find.length == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// [DEAR IMGUI]
|
|
||||||
// going down while being on the last line shouldn't bring us to that line end
|
|
||||||
if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// now find character position down a row
|
// now find character position down a row
|
||||||
|
if (find.length) {
|
||||||
|
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
||||||
|
float x;
|
||||||
|
int start = find.first_char + find.length;
|
||||||
state->cursor = start;
|
state->cursor = start;
|
||||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||||
x = row.x0;
|
x = row.x0;
|
||||||
for (i=0; i < row.num_chars; ++i) {
|
for (i=0; i < row.num_chars; ++i) {
|
||||||
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
|
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
|
||||||
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||||
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
x += dx;
|
x += dx;
|
||||||
|
@ -909,25 +900,17 @@ retry:
|
||||||
|
|
||||||
if (sel)
|
if (sel)
|
||||||
state->select_end = state->cursor;
|
state->select_end = state->cursor;
|
||||||
|
|
||||||
// go to next line
|
|
||||||
find.first_char = find.first_char + find.length;
|
|
||||||
find.length = row.num_chars;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case STB_TEXTEDIT_K_UP:
|
case STB_TEXTEDIT_K_UP:
|
||||||
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT:
|
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: {
|
||||||
case STB_TEXTEDIT_K_PGUP:
|
|
||||||
case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: {
|
|
||||||
StbFindState find;
|
StbFindState find;
|
||||||
StbTexteditRow row;
|
StbTexteditRow row;
|
||||||
int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
||||||
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP;
|
|
||||||
int row_count = is_page ? state->row_count_per_page : 1;
|
|
||||||
|
|
||||||
if (!is_page && state->single_line) {
|
if (state->single_line) {
|
||||||
// on windows, up&down become left&right
|
// on windows, up&down become left&right
|
||||||
key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
|
key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
|
||||||
goto retry;
|
goto retry;
|
||||||
|
@ -942,21 +925,18 @@ retry:
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||||
|
|
||||||
for (j = 0; j < row_count; ++j) {
|
|
||||||
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
|
||||||
|
|
||||||
// can only go up if there's a previous row
|
// can only go up if there's a previous row
|
||||||
if (find.prev_first == find.first_char)
|
if (find.prev_first != find.first_char) {
|
||||||
break;
|
|
||||||
|
|
||||||
// now find character position up a row
|
// now find character position up a row
|
||||||
|
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
||||||
|
float x;
|
||||||
state->cursor = find.prev_first;
|
state->cursor = find.prev_first;
|
||||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||||
x = row.x0;
|
x = row.x0;
|
||||||
for (i=0; i < row.num_chars; ++i) {
|
for (i=0; i < row.num_chars; ++i) {
|
||||||
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
|
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
|
||||||
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||||
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
x += dx;
|
x += dx;
|
||||||
|
@ -971,14 +951,6 @@ retry:
|
||||||
|
|
||||||
if (sel)
|
if (sel)
|
||||||
state->select_end = state->cursor;
|
state->select_end = state->cursor;
|
||||||
|
|
||||||
// go to previous line
|
|
||||||
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
|
|
||||||
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
|
|
||||||
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
|
|
||||||
--prev_scan;
|
|
||||||
find.first_char = find.prev_first;
|
|
||||||
find.prev_first = prev_scan;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1102,6 +1074,10 @@ retry:
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @TODO:
|
||||||
|
// STB_TEXTEDIT_K_PGUP - move cursor up a page
|
||||||
|
// STB_TEXTEDIT_K_PGDOWN - move cursor down a page
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1113,8 +1089,8 @@ retry:
|
||||||
|
|
||||||
static void stb_textedit_flush_redo(StbUndoState *state)
|
static void stb_textedit_flush_redo(StbUndoState *state)
|
||||||
{
|
{
|
||||||
state->redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
|
state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
|
||||||
state->redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
|
state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// discard the oldest entry in the undo list
|
// discard the oldest entry in the undo list
|
||||||
|
@ -1126,13 +1102,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
|
||||||
int n = state->undo_rec[0].insert_length, i;
|
int n = state->undo_rec[0].insert_length, i;
|
||||||
// delete n characters from all other records
|
// delete n characters from all other records
|
||||||
state->undo_char_point -= n;
|
state->undo_char_point -= n;
|
||||||
IMSTB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
|
STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
||||||
for (i=0; i < state->undo_point; ++i)
|
for (i=0; i < state->undo_point; ++i)
|
||||||
if (state->undo_rec[i].char_storage >= 0)
|
if (state->undo_rec[i].char_storage >= 0)
|
||||||
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
|
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
|
||||||
}
|
}
|
||||||
--state->undo_point;
|
--state->undo_point;
|
||||||
IMSTB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
|
STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1142,7 +1118,7 @@ static void stb_textedit_discard_undo(StbUndoState *state)
|
||||||
// fill up even though the undo buffer didn't
|
// fill up even though the undo buffer didn't
|
||||||
static void stb_textedit_discard_redo(StbUndoState *state)
|
static void stb_textedit_discard_redo(StbUndoState *state)
|
||||||
{
|
{
|
||||||
int k = IMSTB_TEXTEDIT_UNDOSTATECOUNT-1;
|
int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
|
||||||
|
|
||||||
if (state->redo_point <= k) {
|
if (state->redo_point <= k) {
|
||||||
// if the k'th undo state has characters, clean those up
|
// if the k'th undo state has characters, clean those up
|
||||||
|
@ -1150,21 +1126,14 @@ static void stb_textedit_discard_redo(StbUndoState *state)
|
||||||
int n = state->undo_rec[k].insert_length, i;
|
int n = state->undo_rec[k].insert_length, i;
|
||||||
// move the remaining redo character data to the end of the buffer
|
// move the remaining redo character data to the end of the buffer
|
||||||
state->redo_char_point += n;
|
state->redo_char_point += n;
|
||||||
IMSTB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((IMSTB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
|
STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
||||||
// adjust the position of all the other records to account for above memmove
|
// adjust the position of all the other records to account for above memmove
|
||||||
for (i=state->redo_point; i < k; ++i)
|
for (i=state->redo_point; i < k; ++i)
|
||||||
if (state->undo_rec[i].char_storage >= 0)
|
if (state->undo_rec[i].char_storage >= 0)
|
||||||
state->undo_rec[i].char_storage += n;
|
state->undo_rec[i].char_storage += n;
|
||||||
}
|
}
|
||||||
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
|
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
|
||||||
// [DEAR IMGUI]
|
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
|
||||||
size_t move_size = (size_t)((IMSTB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
|
|
||||||
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
|
|
||||||
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
|
|
||||||
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
|
|
||||||
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
|
|
||||||
IMSTB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
|
|
||||||
|
|
||||||
// now move redo_point to point to the new one
|
// now move redo_point to point to the new one
|
||||||
++state->redo_point;
|
++state->redo_point;
|
||||||
}
|
}
|
||||||
|
@ -1177,32 +1146,32 @@ static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numch
|
||||||
|
|
||||||
// if we have no free records, we have to make room, by sliding the
|
// if we have no free records, we have to make room, by sliding the
|
||||||
// existing records down
|
// existing records down
|
||||||
if (state->undo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
|
if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
|
||||||
stb_textedit_discard_undo(state);
|
stb_textedit_discard_undo(state);
|
||||||
|
|
||||||
// if the characters to store won't possibly fit in the buffer, we can't undo
|
// if the characters to store won't possibly fit in the buffer, we can't undo
|
||||||
if (numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
|
if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
|
||||||
state->undo_point = 0;
|
state->undo_point = 0;
|
||||||
state->undo_char_point = 0;
|
state->undo_char_point = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we don't have enough free characters in the buffer, we have to make room
|
// if we don't have enough free characters in the buffer, we have to make room
|
||||||
while (state->undo_char_point + numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT)
|
while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
|
||||||
stb_textedit_discard_undo(state);
|
stb_textedit_discard_undo(state);
|
||||||
|
|
||||||
return &state->undo_rec[state->undo_point++];
|
return &state->undo_rec[state->undo_point++];
|
||||||
}
|
}
|
||||||
|
|
||||||
static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
|
static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
|
||||||
{
|
{
|
||||||
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
|
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
|
||||||
if (r == NULL)
|
if (r == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
r->where = pos;
|
r->where = pos;
|
||||||
r->insert_length = (IMSTB_TEXTEDIT_POSITIONTYPE) insert_len;
|
r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
|
||||||
r->delete_length = (IMSTB_TEXTEDIT_POSITIONTYPE) delete_len;
|
r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
|
||||||
|
|
||||||
if (insert_len == 0) {
|
if (insert_len == 0) {
|
||||||
r->char_storage = -1;
|
r->char_storage = -1;
|
||||||
|
@ -1214,7 +1183,7 @@ static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
StbUndoState *s = &state->undostate;
|
StbUndoState *s = &state->undostate;
|
||||||
StbUndoRecord u, *r;
|
StbUndoRecord u, *r;
|
||||||
|
@ -1241,7 +1210,7 @@ static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
// characters stored for *undoing* don't leave room for redo
|
// characters stored for *undoing* don't leave room for redo
|
||||||
// if the last is true, we have to bail
|
// if the last is true, we have to bail
|
||||||
|
|
||||||
if (s->undo_char_point + u.delete_length >= IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
|
if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
|
||||||
// the undo records take up too much character space; there's no space to store the redo characters
|
// the undo records take up too much character space; there's no space to store the redo characters
|
||||||
r->insert_length = 0;
|
r->insert_length = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1250,7 +1219,7 @@ static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
// there's definitely room to store the characters eventually
|
// there's definitely room to store the characters eventually
|
||||||
while (s->undo_char_point + u.delete_length > s->redo_char_point) {
|
while (s->undo_char_point + u.delete_length > s->redo_char_point) {
|
||||||
// should never happen:
|
// should never happen:
|
||||||
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
|
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
|
||||||
return;
|
return;
|
||||||
// there's currently not enough room, so discard a redo record
|
// there's currently not enough room, so discard a redo record
|
||||||
stb_textedit_discard_redo(s);
|
stb_textedit_discard_redo(s);
|
||||||
|
@ -1282,11 +1251,11 @@ static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
s->redo_point--;
|
s->redo_point--;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
StbUndoState *s = &state->undostate;
|
StbUndoState *s = &state->undostate;
|
||||||
StbUndoRecord *u, r;
|
StbUndoRecord *u, r;
|
||||||
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
|
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// we need to do two things: apply the redo record, and create an undo record
|
// we need to do two things: apply the redo record, and create an undo record
|
||||||
|
@ -1338,20 +1307,20 @@ static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int le
|
||||||
stb_text_createundo(&state->undostate, where, 0, length);
|
stb_text_createundo(&state->undostate, where, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
|
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
|
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
|
||||||
if (p) {
|
if (p) {
|
||||||
for (i=0; i < length; ++i)
|
for (i=0; i < length; ++i)
|
||||||
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
|
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
|
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
|
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
|
||||||
if (p) {
|
if (p) {
|
||||||
for (i=0; i < old_length; ++i)
|
for (i=0; i < old_length; ++i)
|
||||||
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
|
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
|
||||||
|
@ -1363,8 +1332,8 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
|
||||||
{
|
{
|
||||||
state->undostate.undo_point = 0;
|
state->undostate.undo_point = 0;
|
||||||
state->undostate.undo_char_point = 0;
|
state->undostate.undo_char_point = 0;
|
||||||
state->undostate.redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
|
state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
|
||||||
state->undostate.redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
|
state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
|
||||||
state->select_end = state->select_start = 0;
|
state->select_end = state->select_start = 0;
|
||||||
state->cursor = 0;
|
state->cursor = 0;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
|
@ -1373,7 +1342,6 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
|
||||||
state->initialized = 1;
|
state->initialized = 1;
|
||||||
state->single_line = (unsigned char) is_single_line;
|
state->single_line = (unsigned char) is_single_line;
|
||||||
state->insert_mode = 0;
|
state->insert_mode = 0;
|
||||||
state->row_count_per_page = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// API initialize
|
// API initialize
|
||||||
|
@ -1387,16 +1355,16 @@ static void stb_textedit_initialize_state(STB_TexteditState *state, int is_singl
|
||||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int stb_textedit_paste(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE const *ctext, int len)
|
static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
|
||||||
{
|
{
|
||||||
return stb_textedit_paste_internal(str, state, (IMSTB_TEXTEDIT_CHARTYPE *) ctext, len);
|
return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif//IMSTB_TEXTEDIT_IMPLEMENTATION
|
#endif//STB_TEXTEDIT_IMPLEMENTATION
|
||||||
|
|
||||||
/*
|
/*
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,19 +1,5 @@
|
||||||
// [DEAR IMGUI]
|
// stb_truetype.h - v1.19 - public domain
|
||||||
// This is a slightly modified version of stb_truetype.h 1.26.
|
// authored from 2009-2016 by Sean Barrett / RAD Game Tools
|
||||||
// Mostly fixing for compiler and static analyzer warnings.
|
|
||||||
// Grep for [DEAR IMGUI] to find the changes.
|
|
||||||
|
|
||||||
// stb_truetype.h - v1.26 - public domain
|
|
||||||
// authored from 2009-2021 by Sean Barrett / RAD Game Tools
|
|
||||||
//
|
|
||||||
// =======================================================================
|
|
||||||
//
|
|
||||||
// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES
|
|
||||||
//
|
|
||||||
// This library does no range checking of the offsets found in the file,
|
|
||||||
// meaning an attacker can use it to read arbitrary memory.
|
|
||||||
//
|
|
||||||
// =======================================================================
|
|
||||||
//
|
//
|
||||||
// This library processes TrueType files:
|
// This library processes TrueType files:
|
||||||
// parse files
|
// parse files
|
||||||
|
@ -46,11 +32,11 @@
|
||||||
// Daniel Ribeiro Maciel
|
// Daniel Ribeiro Maciel
|
||||||
//
|
//
|
||||||
// Bug/warning reports/fixes:
|
// Bug/warning reports/fixes:
|
||||||
// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe
|
// "Zer" on mollyrocket Fabian "ryg" Giesen
|
||||||
// Cass Everitt Martins Mozeiko github:aloucks
|
// Cass Everitt Martins Mozeiko
|
||||||
// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam
|
// stoiko (Haemimont Games) Cap Petschulat
|
||||||
// Brian Hook Omar Cornut github:vassvik
|
// Brian Hook Omar Cornut
|
||||||
// Walter van Niftrik Ryan Griege
|
// Walter van Niftrik github:aloucks
|
||||||
// David Gow Peter LaValle
|
// David Gow Peter LaValle
|
||||||
// David Given Sergey Popov
|
// David Given Sergey Popov
|
||||||
// Ivan-Assen Ivanov Giumo X. Clanjor
|
// Ivan-Assen Ivanov Giumo X. Clanjor
|
||||||
|
@ -58,18 +44,11 @@
|
||||||
// Johan Duparc Thomas Fields
|
// Johan Duparc Thomas Fields
|
||||||
// Hou Qiming Derek Vinyard
|
// Hou Qiming Derek Vinyard
|
||||||
// Rob Loach Cort Stratton
|
// Rob Loach Cort Stratton
|
||||||
// Kenney Phillis Jr. Brian Costabile
|
// Kenney Phillis Jr. github:oyvindjam
|
||||||
// Ken Voskuil (kaesve)
|
// Brian Costabile github:vassvik
|
||||||
//
|
//
|
||||||
// VERSION HISTORY
|
// VERSION HISTORY
|
||||||
//
|
//
|
||||||
// 1.26 (2021-08-28) fix broken rasterizer
|
|
||||||
// 1.25 (2021-07-11) many fixes
|
|
||||||
// 1.24 (2020-02-05) fix warning
|
|
||||||
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
|
|
||||||
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
|
|
||||||
// 1.21 (2019-02-25) fix warning
|
|
||||||
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
|
|
||||||
// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
|
// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
|
||||||
// 1.18 (2018-01-29) add missing function
|
// 1.18 (2018-01-29) add missing function
|
||||||
// 1.17 (2017-07-23) make more arguments const; doc fix
|
// 1.17 (2017-07-23) make more arguments const; doc fix
|
||||||
|
@ -96,7 +75,7 @@
|
||||||
//
|
//
|
||||||
// USAGE
|
// USAGE
|
||||||
//
|
//
|
||||||
// Include this file in whatever places need to refer to it. In ONE C/C++
|
// Include this file in whatever places neeed to refer to it. In ONE C/C++
|
||||||
// file, write:
|
// file, write:
|
||||||
// #define STB_TRUETYPE_IMPLEMENTATION
|
// #define STB_TRUETYPE_IMPLEMENTATION
|
||||||
// before the #include of this file. This expands out the actual
|
// before the #include of this file. This expands out the actual
|
||||||
|
@ -263,6 +242,19 @@
|
||||||
// recommend it.
|
// recommend it.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
|
||||||
|
//
|
||||||
|
// Documentation & header file 520 LOC \___ 660 LOC documentation
|
||||||
|
// Sample code 140 LOC /
|
||||||
|
// Truetype parsing 620 LOC ---- 620 LOC TrueType
|
||||||
|
// Software rasterization 240 LOC \ .
|
||||||
|
// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
|
||||||
|
// Bitmap management 100 LOC /
|
||||||
|
// Baked bitmap interface 70 LOC /
|
||||||
|
// Font name matching & access 150 LOC ---- 150
|
||||||
|
// C runtime library abstraction 60 LOC ---- 60
|
||||||
|
//
|
||||||
|
//
|
||||||
// PERFORMANCE MEASUREMENTS FOR 1.06:
|
// PERFORMANCE MEASUREMENTS FOR 1.06:
|
||||||
//
|
//
|
||||||
// 32-bit 64-bit
|
// 32-bit 64-bit
|
||||||
|
@ -277,8 +269,8 @@
|
||||||
//// SAMPLE PROGRAMS
|
//// SAMPLE PROGRAMS
|
||||||
////
|
////
|
||||||
//
|
//
|
||||||
// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless.
|
// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
|
||||||
// See "tests/truetype_demo_win32.c" for a complete version.
|
//
|
||||||
#if 0
|
#if 0
|
||||||
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
|
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
|
||||||
#include "stb_truetype.h"
|
#include "stb_truetype.h"
|
||||||
|
@ -304,8 +296,6 @@ void my_stbtt_initfont(void)
|
||||||
void my_stbtt_print(float x, float y, char *text)
|
void my_stbtt_print(float x, float y, char *text)
|
||||||
{
|
{
|
||||||
// assume orthographic projection with units = screen pixels, origin at top left
|
// assume orthographic projection with units = screen pixels, origin at top left
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glBindTexture(GL_TEXTURE_2D, ftex);
|
glBindTexture(GL_TEXTURE_2D, ftex);
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
|
@ -313,10 +303,10 @@ void my_stbtt_print(float x, float y, char *text)
|
||||||
if (*text >= 32 && *text < 128) {
|
if (*text >= 32 && *text < 128) {
|
||||||
stbtt_aligned_quad q;
|
stbtt_aligned_quad q;
|
||||||
stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
|
stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
|
||||||
glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
|
glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
|
||||||
glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
|
glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
|
||||||
glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
|
glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
|
||||||
glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
|
glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
|
||||||
}
|
}
|
||||||
++text;
|
++text;
|
||||||
}
|
}
|
||||||
|
@ -566,8 +556,6 @@ STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int p
|
||||||
//
|
//
|
||||||
// It's inefficient; you might want to c&p it and optimize it.
|
// It's inefficient; you might want to c&p it and optimize it.
|
||||||
|
|
||||||
STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
|
|
||||||
// Query the font vertical metrics without having to create a font first.
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -653,12 +641,6 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
|
||||||
// To use with PackFontRangesGather etc., you must set it before calls
|
// To use with PackFontRangesGather etc., you must set it before calls
|
||||||
// call to PackFontRangesGatherRects.
|
// call to PackFontRangesGatherRects.
|
||||||
|
|
||||||
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
|
|
||||||
// If skip != 0, this tells stb_truetype to skip any codepoints for which
|
|
||||||
// there is no corresponding glyph. If skip=0, which is the default, then
|
|
||||||
// codepoints without a glyph recived the font's "missing character" glyph,
|
|
||||||
// typically an empty box by convention.
|
|
||||||
|
|
||||||
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
|
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
|
||||||
int char_index, // character to display
|
int char_index, // character to display
|
||||||
float *xpos, float *ypos, // pointers to current position in screen pixel space
|
float *xpos, float *ypos, // pointers to current position in screen pixel space
|
||||||
|
@ -687,7 +669,6 @@ struct stbtt_pack_context {
|
||||||
int height;
|
int height;
|
||||||
int stride_in_bytes;
|
int stride_in_bytes;
|
||||||
int padding;
|
int padding;
|
||||||
int skip_missing;
|
|
||||||
unsigned int h_oversample, v_oversample;
|
unsigned int h_oversample, v_oversample;
|
||||||
unsigned char *pixels;
|
unsigned char *pixels;
|
||||||
void *nodes;
|
void *nodes;
|
||||||
|
@ -713,7 +694,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
|
||||||
// file will only define one font and it always be at offset 0, so it will
|
// file will only define one font and it always be at offset 0, so it will
|
||||||
// return '0' for index 0, and -1 for all other indices.
|
// return '0' for index 0, and -1 for all other indices.
|
||||||
|
|
||||||
// The following structure is defined publicly so you can declare one on
|
// The following structure is defined publically so you can declare one on
|
||||||
// the stack or as a global or etc, but you should treat it as opaque.
|
// the stack or as a global or etc, but you should treat it as opaque.
|
||||||
struct stbtt_fontinfo
|
struct stbtt_fontinfo
|
||||||
{
|
{
|
||||||
|
@ -723,7 +704,7 @@ struct stbtt_fontinfo
|
||||||
|
|
||||||
int numGlyphs; // number of glyphs, needed for range checking
|
int numGlyphs; // number of glyphs, needed for range checking
|
||||||
|
|
||||||
int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf
|
int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
|
||||||
int index_map; // a cmap mapping for our chosen character encoding
|
int index_map; // a cmap mapping for our chosen character encoding
|
||||||
int indexToLocFormat; // format needed to map from glyph index to glyph
|
int indexToLocFormat; // format needed to map from glyph index to glyph
|
||||||
|
|
||||||
|
@ -752,7 +733,6 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
|
||||||
// and you want a speed-up, call this function with the character you're
|
// and you want a speed-up, call this function with the character you're
|
||||||
// going to process, then use glyph-based functions instead of the
|
// going to process, then use glyph-based functions instead of the
|
||||||
// codepoint-based functions.
|
// codepoint-based functions.
|
||||||
// Returns 0 if the character codepoint is not defined in the font.
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -806,18 +786,6 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1,
|
||||||
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
|
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
|
||||||
// as above, but takes one or more glyph indices for greater efficiency
|
// as above, but takes one or more glyph indices for greater efficiency
|
||||||
|
|
||||||
typedef struct stbtt_kerningentry
|
|
||||||
{
|
|
||||||
int glyph1; // use stbtt_FindGlyphIndex
|
|
||||||
int glyph2;
|
|
||||||
int advance;
|
|
||||||
} stbtt_kerningentry;
|
|
||||||
|
|
||||||
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
|
|
||||||
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
|
|
||||||
// Retrieves a complete list of all of the kerning pairs provided by the font
|
|
||||||
// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write.
|
|
||||||
// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1)
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -852,7 +820,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
|
||||||
// returns # of vertices and fills *vertices with the pointer to them
|
// returns # of vertices and fills *vertices with the pointer to them
|
||||||
// these are expressed in "unscaled" coordinates
|
// these are expressed in "unscaled" coordinates
|
||||||
//
|
//
|
||||||
// The shape is a series of contours. Each one starts with
|
// The shape is a series of countours. Each one starts with
|
||||||
// a STBTT_moveto, then consists of a series of mixed
|
// a STBTT_moveto, then consists of a series of mixed
|
||||||
// STBTT_lineto and STBTT_curveto segments. A lineto
|
// STBTT_lineto and STBTT_curveto segments. A lineto
|
||||||
// draws a line from previous endpoint to its x,y; a curveto
|
// draws a line from previous endpoint to its x,y; a curveto
|
||||||
|
@ -862,12 +830,6 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
|
||||||
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
|
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
|
||||||
// frees the data allocated above
|
// frees the data allocated above
|
||||||
|
|
||||||
STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
|
|
||||||
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
|
|
||||||
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
|
|
||||||
// fills svg with the character's SVG data.
|
|
||||||
// returns data size or 0 if SVG not found.
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// BITMAP RENDERING
|
// BITMAP RENDERING
|
||||||
|
@ -954,7 +916,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
||||||
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
|
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
|
||||||
// These functions compute a discretized SDF field for a single character, suitable for storing
|
// These functions compute a discretized SDF field for a single character, suitable for storing
|
||||||
// in a single-channel texture, sampling with bilinear filtering, and testing against
|
// in a single-channel texture, sampling with bilinear filtering, and testing against
|
||||||
// larger than some threshold to produce scalable fonts.
|
// larger than some threshhold to produce scalable fonts.
|
||||||
// info -- the font
|
// info -- the font
|
||||||
// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
|
// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
|
||||||
// glyph/codepoint -- the character to generate the SDF for
|
// glyph/codepoint -- the character to generate the SDF for
|
||||||
|
@ -1369,22 +1331,6 @@ static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
|
||||||
return stbtt__cff_get_index(&cff);
|
return stbtt__cff_get_index(&cff);
|
||||||
}
|
}
|
||||||
|
|
||||||
// since most people won't use this, find this table the first time it's needed
|
|
||||||
static int stbtt__get_svg(stbtt_fontinfo *info)
|
|
||||||
{
|
|
||||||
stbtt_uint32 t;
|
|
||||||
if (info->svg < 0) {
|
|
||||||
t = stbtt__find_table(info->data, info->fontstart, "SVG ");
|
|
||||||
if (t) {
|
|
||||||
stbtt_uint32 offset = ttULONG(info->data + t + 2);
|
|
||||||
info->svg = t + offset;
|
|
||||||
} else {
|
|
||||||
info->svg = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return info->svg;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
|
static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
|
||||||
{
|
{
|
||||||
stbtt_uint32 cmap, t;
|
stbtt_uint32 cmap, t;
|
||||||
|
@ -1464,8 +1410,6 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in
|
||||||
else
|
else
|
||||||
info->numGlyphs = 0xffff;
|
info->numGlyphs = 0xffff;
|
||||||
|
|
||||||
info->svg = -1;
|
|
||||||
|
|
||||||
// find a cmap encoding table we understand *now* to avoid searching
|
// find a cmap encoding table we understand *now* to avoid searching
|
||||||
// later. (todo: could make this installable)
|
// later. (todo: could make this installable)
|
||||||
// the same regardless of glyph.
|
// the same regardless of glyph.
|
||||||
|
@ -1549,12 +1493,12 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
|
||||||
search += 2;
|
search += 2;
|
||||||
|
|
||||||
{
|
{
|
||||||
stbtt_uint16 offset, start, last;
|
stbtt_uint16 offset, start;
|
||||||
stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
|
stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
|
||||||
|
|
||||||
|
STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
|
||||||
start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
|
start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
|
||||||
last = ttUSHORT(data + endCount + 2*item);
|
if (unicode_codepoint < start)
|
||||||
if (unicode_codepoint < start || unicode_codepoint > last)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
|
offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
|
||||||
|
@ -1814,7 +1758,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
|
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
|
||||||
} else if (numberOfContours < 0) {
|
} else if (numberOfContours == -1) {
|
||||||
// Compound shapes.
|
// Compound shapes.
|
||||||
int more = 1;
|
int more = 1;
|
||||||
stbtt_uint8 *comp = data + g + 10;
|
stbtt_uint8 *comp = data + g + 10;
|
||||||
|
@ -1881,7 +1825,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
||||||
if (comp_verts) STBTT_free(comp_verts, info->userdata);
|
if (comp_verts) STBTT_free(comp_verts, info->userdata);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
|
if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
|
||||||
STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
|
STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
|
||||||
if (vertices) STBTT_free(vertices, info->userdata);
|
if (vertices) STBTT_free(vertices, info->userdata);
|
||||||
vertices = tmp;
|
vertices = tmp;
|
||||||
|
@ -1891,6 +1835,9 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
||||||
// More components ?
|
// More components ?
|
||||||
more = flags & (1<<5);
|
more = flags & (1<<5);
|
||||||
}
|
}
|
||||||
|
} else if (numberOfContours < 0) {
|
||||||
|
// @TODO other compound variations?
|
||||||
|
STBTT_assert(0);
|
||||||
} else {
|
} else {
|
||||||
// numberOfCounters == 0, do nothing
|
// numberOfCounters == 0, do nothing
|
||||||
}
|
}
|
||||||
|
@ -2008,7 +1955,7 @@ static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int gly
|
||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fdselector == -1) return stbtt__new_buf(NULL, 0); // [DEAR IMGUI] fixed, see #6007 and nothings/stb#1422
|
if (fdselector == -1) stbtt__new_buf(NULL, 0);
|
||||||
return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
|
return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2144,7 +2091,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
|
||||||
subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
|
subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
|
||||||
has_subrs = 1;
|
has_subrs = 1;
|
||||||
}
|
}
|
||||||
// FALLTHROUGH
|
// fallthrough
|
||||||
case 0x1D: // callgsubr
|
case 0x1D: // callgsubr
|
||||||
if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
|
if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
|
||||||
v = (int) s[--sp];
|
v = (int) s[--sp];
|
||||||
|
@ -2249,7 +2196,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (b0 != 255 && b0 != 28 && b0 < 32)
|
if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))
|
||||||
return STBTT__CSERR("reserved operator");
|
return STBTT__CSERR("reserved operator");
|
||||||
|
|
||||||
// push immediate
|
// push immediate
|
||||||
|
@ -2319,48 +2266,6 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
|
|
||||||
{
|
|
||||||
stbtt_uint8 *data = info->data + info->kern;
|
|
||||||
|
|
||||||
// we only look at the first table. it must be 'horizontal' and format 0.
|
|
||||||
if (!info->kern)
|
|
||||||
return 0;
|
|
||||||
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
|
|
||||||
return 0;
|
|
||||||
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return ttUSHORT(data+10);
|
|
||||||
}
|
|
||||||
|
|
||||||
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
|
|
||||||
{
|
|
||||||
stbtt_uint8 *data = info->data + info->kern;
|
|
||||||
int k, length;
|
|
||||||
|
|
||||||
// we only look at the first table. it must be 'horizontal' and format 0.
|
|
||||||
if (!info->kern)
|
|
||||||
return 0;
|
|
||||||
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
|
|
||||||
return 0;
|
|
||||||
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
length = ttUSHORT(data+10);
|
|
||||||
if (table_length < length)
|
|
||||||
length = table_length;
|
|
||||||
|
|
||||||
for (k = 0; k < length; k++)
|
|
||||||
{
|
|
||||||
table[k].glyph1 = ttUSHORT(data+18+(k*6));
|
|
||||||
table[k].glyph2 = ttUSHORT(data+20+(k*6));
|
|
||||||
table[k].advance = ttSHORT(data+22+(k*6));
|
|
||||||
}
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
|
static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
|
||||||
{
|
{
|
||||||
stbtt_uint8 *data = info->data + info->kern;
|
stbtt_uint8 *data = info->data + info->kern;
|
||||||
|
@ -2394,7 +2299,7 @@ static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1
|
||||||
static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
|
static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
|
||||||
{
|
{
|
||||||
stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
|
stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
|
||||||
switch (coverageFormat) {
|
switch(coverageFormat) {
|
||||||
case 1: {
|
case 1: {
|
||||||
stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
|
stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
|
||||||
|
|
||||||
|
@ -2415,8 +2320,7 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
|
|
||||||
case 2: {
|
case 2: {
|
||||||
stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
|
stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
|
||||||
|
@ -2440,10 +2344,12 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph
|
||||||
return startCoverageIndex + glyph - strawStart;
|
return startCoverageIndex + glyph - strawStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
|
|
||||||
default: return -1; // unsupported
|
default: {
|
||||||
|
// There are no other cases.
|
||||||
|
STBTT_assert(0);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2452,7 +2358,7 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph
|
||||||
static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
|
static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
|
||||||
{
|
{
|
||||||
stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
|
stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
|
||||||
switch (classDefFormat)
|
switch(classDefFormat)
|
||||||
{
|
{
|
||||||
case 1: {
|
case 1: {
|
||||||
stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
|
stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
|
||||||
|
@ -2461,8 +2367,9 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
|
||||||
|
|
||||||
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
|
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
|
||||||
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
|
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
|
||||||
break;
|
|
||||||
}
|
classDefTable = classDef1ValueArray + 2 * glyphCount;
|
||||||
|
} break;
|
||||||
|
|
||||||
case 2: {
|
case 2: {
|
||||||
stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
|
stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
|
||||||
|
@ -2484,15 +2391,17 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
|
||||||
else
|
else
|
||||||
return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
|
return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
classDefTable = classRangeRecords + 6 * classRangeCount;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
// There are no other cases.
|
||||||
|
STBTT_assert(0);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
return -1;
|
||||||
return -1; // Unsupported definition type, return an error.
|
|
||||||
}
|
|
||||||
|
|
||||||
// "All glyphs not assigned to a class fall into class 0". (OpenType spec)
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define to STBTT_assert(x) if you want to break on unimplemented formats.
|
// Define to STBTT_assert(x) if you want to break on unimplemented formats.
|
||||||
|
@ -2504,7 +2413,7 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, in
|
||||||
stbtt_uint8 *lookupList;
|
stbtt_uint8 *lookupList;
|
||||||
stbtt_uint16 lookupCount;
|
stbtt_uint16 lookupCount;
|
||||||
stbtt_uint8 *data;
|
stbtt_uint8 *data;
|
||||||
stbtt_int32 i, sti;
|
stbtt_int32 i;
|
||||||
|
|
||||||
if (!info->gpos) return 0;
|
if (!info->gpos) return 0;
|
||||||
|
|
||||||
|
@ -2524,9 +2433,9 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, in
|
||||||
stbtt_uint16 lookupType = ttUSHORT(lookupTable);
|
stbtt_uint16 lookupType = ttUSHORT(lookupTable);
|
||||||
stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
|
stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
|
||||||
stbtt_uint8 *subTableOffsets = lookupTable + 6;
|
stbtt_uint8 *subTableOffsets = lookupTable + 6;
|
||||||
if (lookupType != 2) // Pair Adjustment Positioning Subtable
|
switch(lookupType) {
|
||||||
continue;
|
case 2: { // Pair Adjustment Positioning Subtable
|
||||||
|
stbtt_int32 sti;
|
||||||
for (sti=0; sti<subTableCount; sti++) {
|
for (sti=0; sti<subTableCount; sti++) {
|
||||||
stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
|
stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
|
||||||
stbtt_uint8 *table = lookupTable + subtableOffset;
|
stbtt_uint8 *table = lookupTable + subtableOffset;
|
||||||
|
@ -2541,15 +2450,20 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, in
|
||||||
int straw, needle;
|
int straw, needle;
|
||||||
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
|
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
|
||||||
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
|
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
|
||||||
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
|
|
||||||
stbtt_int32 valueRecordPairSizeInBytes = 2;
|
stbtt_int32 valueRecordPairSizeInBytes = 2;
|
||||||
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
|
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
|
||||||
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
|
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
|
||||||
stbtt_uint8 *pairValueTable = table + pairPosOffset;
|
stbtt_uint8 *pairValueTable = table + pairPosOffset;
|
||||||
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
|
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
|
||||||
stbtt_uint8 *pairValueArray = pairValueTable + 2;
|
stbtt_uint8 *pairValueArray = pairValueTable + 2;
|
||||||
|
// TODO: Support more formats.
|
||||||
|
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
|
||||||
|
if (valueFormat1 != 4) return 0;
|
||||||
|
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
|
||||||
|
if (valueFormat2 != 0) return 0;
|
||||||
|
|
||||||
if (coverageIndex >= pairSetCount) return 0;
|
STBTT_assert(coverageIndex < pairSetCount);
|
||||||
|
STBTT__NOTUSED(pairSetCount);
|
||||||
|
|
||||||
needle=glyph2;
|
needle=glyph2;
|
||||||
r=pairValueCount-1;
|
r=pairValueCount-1;
|
||||||
|
@ -2572,15 +2486,12 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, in
|
||||||
return xAdvance;
|
return xAdvance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} break;
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 2: {
|
case 2: {
|
||||||
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
|
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
|
||||||
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
|
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
|
||||||
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
|
|
||||||
stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
|
stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
|
||||||
stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
|
stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
|
||||||
int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
|
int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
|
||||||
|
@ -2588,24 +2499,36 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, in
|
||||||
|
|
||||||
stbtt_uint16 class1Count = ttUSHORT(table + 12);
|
stbtt_uint16 class1Count = ttUSHORT(table + 12);
|
||||||
stbtt_uint16 class2Count = ttUSHORT(table + 14);
|
stbtt_uint16 class2Count = ttUSHORT(table + 14);
|
||||||
stbtt_uint8 *class1Records, *class2Records;
|
STBTT_assert(glyph1class < class1Count);
|
||||||
stbtt_int16 xAdvance;
|
STBTT_assert(glyph2class < class2Count);
|
||||||
|
|
||||||
if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
|
// TODO: Support more formats.
|
||||||
if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
|
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
|
||||||
|
if (valueFormat1 != 4) return 0;
|
||||||
|
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
|
||||||
|
if (valueFormat2 != 0) return 0;
|
||||||
|
|
||||||
class1Records = table + 16;
|
if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
|
||||||
class2Records = class1Records + 2 * (glyph1class * class2Count);
|
stbtt_uint8 *class1Records = table + 16;
|
||||||
xAdvance = ttSHORT(class2Records + 2 * glyph2class);
|
stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
|
||||||
|
stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
|
||||||
return xAdvance;
|
return xAdvance;
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
// There are no other cases.
|
||||||
|
STBTT_assert(0);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0; // Unsupported position format
|
// TODO: Implement other stuff.
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2618,7 +2541,8 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int
|
||||||
|
|
||||||
if (info->gpos)
|
if (info->gpos)
|
||||||
xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
|
xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
|
||||||
else if (info->kern)
|
|
||||||
|
if (info->kern)
|
||||||
xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
|
xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
|
||||||
|
|
||||||
return xAdvance;
|
return xAdvance;
|
||||||
|
@ -2679,45 +2603,6 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
|
||||||
STBTT_free(v, info->userdata);
|
STBTT_free(v, info->userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
stbtt_uint8 *data = info->data;
|
|
||||||
stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
|
|
||||||
|
|
||||||
int numEntries = ttUSHORT(svg_doc_list);
|
|
||||||
stbtt_uint8 *svg_docs = svg_doc_list + 2;
|
|
||||||
|
|
||||||
for(i=0; i<numEntries; i++) {
|
|
||||||
stbtt_uint8 *svg_doc = svg_docs + (12 * i);
|
|
||||||
if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
|
|
||||||
return svg_doc;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
|
|
||||||
{
|
|
||||||
stbtt_uint8 *data = info->data;
|
|
||||||
stbtt_uint8 *svg_doc;
|
|
||||||
|
|
||||||
if (info->svg == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
svg_doc = stbtt_FindSVGDoc(info, gl);
|
|
||||||
if (svg_doc != NULL) {
|
|
||||||
*svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
|
|
||||||
return ttULONG(svg_doc + 8);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
|
|
||||||
{
|
|
||||||
return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// antialiasing software rasterizer
|
// antialiasing software rasterizer
|
||||||
|
@ -3067,23 +2952,6 @@ static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
|
|
||||||
{
|
|
||||||
STBTT_assert(top_width >= 0);
|
|
||||||
STBTT_assert(bottom_width >= 0);
|
|
||||||
return (top_width + bottom_width) / 2.0f * height;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
|
|
||||||
{
|
|
||||||
return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static float stbtt__sized_triangle_area(float height, float width)
|
|
||||||
{
|
|
||||||
return height * width / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
|
static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
|
||||||
{
|
{
|
||||||
float y_bottom = y_top+1;
|
float y_bottom = y_top+1;
|
||||||
|
@ -3138,13 +3006,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
|
||||||
float height;
|
float height;
|
||||||
// simple case, only spans one pixel
|
// simple case, only spans one pixel
|
||||||
int x = (int) x_top;
|
int x = (int) x_top;
|
||||||
height = (sy1 - sy0) * e->direction;
|
height = sy1 - sy0;
|
||||||
STBTT_assert(x >= 0 && x < len);
|
STBTT_assert(x >= 0 && x < len);
|
||||||
scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
|
scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
|
||||||
scanline_fill[x] += height; // everything right of this pixel is filled
|
scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
|
||||||
} else {
|
} else {
|
||||||
int x,x1,x2;
|
int x,x1,x2;
|
||||||
float y_crossing, y_final, step, sign, area;
|
float y_crossing, step, sign, area;
|
||||||
// covers 2+ pixels
|
// covers 2+ pixels
|
||||||
if (x_top > x_bottom) {
|
if (x_top > x_bottom) {
|
||||||
// flip scanline vertically; signed area is the same
|
// flip scanline vertically; signed area is the same
|
||||||
|
@ -3157,82 +3025,29 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
|
||||||
dy = -dy;
|
dy = -dy;
|
||||||
t = x0, x0 = xb, xb = t;
|
t = x0, x0 = xb, xb = t;
|
||||||
}
|
}
|
||||||
STBTT_assert(dy >= 0);
|
|
||||||
STBTT_assert(dx >= 0);
|
|
||||||
|
|
||||||
x1 = (int) x_top;
|
x1 = (int) x_top;
|
||||||
x2 = (int) x_bottom;
|
x2 = (int) x_bottom;
|
||||||
// compute intersection with y axis at x1+1
|
// compute intersection with y axis at x1+1
|
||||||
y_crossing = y_top + dy * (x1+1 - x0);
|
y_crossing = (x1+1 - x0) * dy + y_top;
|
||||||
|
|
||||||
// compute intersection with y axis at x2
|
|
||||||
y_final = y_top + dy * (x2 - x0);
|
|
||||||
|
|
||||||
// x1 x_top x2 x_bottom
|
|
||||||
// y_top +------|-----+------------+------------+--------|---+------------+
|
|
||||||
// | | | | | |
|
|
||||||
// | | | | | |
|
|
||||||
// sy0 | Txxxxx|............|............|............|............|
|
|
||||||
// y_crossing | *xxxxx.......|............|............|............|
|
|
||||||
// | | xxxxx..|............|............|............|
|
|
||||||
// | | /- xx*xxxx........|............|............|
|
|
||||||
// | | dy < | xxxxxx..|............|............|
|
|
||||||
// y_final | | \- | xx*xxx.........|............|
|
|
||||||
// sy1 | | | | xxxxxB...|............|
|
|
||||||
// | | | | | |
|
|
||||||
// | | | | | |
|
|
||||||
// y_bottom +------------+------------+------------+------------+------------+
|
|
||||||
//
|
|
||||||
// goal is to measure the area covered by '.' in each pixel
|
|
||||||
|
|
||||||
// if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
|
|
||||||
// @TODO: maybe test against sy1 rather than y_bottom?
|
|
||||||
if (y_crossing > y_bottom)
|
|
||||||
y_crossing = y_bottom;
|
|
||||||
|
|
||||||
sign = e->direction;
|
sign = e->direction;
|
||||||
|
// area of the rectangle covered from y0..y_crossing
|
||||||
// area of the rectangle covered from sy0..y_crossing
|
|
||||||
area = sign * (y_crossing-sy0);
|
area = sign * (y_crossing-sy0);
|
||||||
|
// area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
|
||||||
|
scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
|
||||||
|
|
||||||
// area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
|
step = sign * dy;
|
||||||
scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
|
|
||||||
|
|
||||||
// check if final y_crossing is blown up; no test case for this
|
|
||||||
if (y_final > y_bottom) {
|
|
||||||
int denom = (x2 - (x1+1));
|
|
||||||
y_final = y_bottom;
|
|
||||||
if (denom != 0) { // [DEAR IMGUI] Avoid div by zero (https://github.com/nothings/stb/issues/1316)
|
|
||||||
dy = (y_final - y_crossing ) / denom; // if denom=0, y_final = y_crossing, so y_final <= y_bottom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// in second pixel, area covered by line segment found in first pixel
|
|
||||||
// is always a rectangle 1 wide * the height of that line segment; this
|
|
||||||
// is exactly what the variable 'area' stores. it also gets a contribution
|
|
||||||
// from the line segment within it. the THIRD pixel will get the first
|
|
||||||
// pixel's rectangle contribution, the second pixel's rectangle contribution,
|
|
||||||
// and its own contribution. the 'own contribution' is the same in every pixel except
|
|
||||||
// the leftmost and rightmost, a trapezoid that slides down in each pixel.
|
|
||||||
// the second pixel's contribution to the third pixel will be the
|
|
||||||
// rectangle 1 wide times the height change in the second pixel, which is dy.
|
|
||||||
|
|
||||||
step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
|
|
||||||
// which multiplied by 1-pixel-width is how much pixel area changes for each step in x
|
|
||||||
// so the area advances by 'step' every time
|
|
||||||
|
|
||||||
for (x = x1+1; x < x2; ++x) {
|
for (x = x1+1; x < x2; ++x) {
|
||||||
scanline[x] += area + step/2; // area of trapezoid is 1*step/2
|
scanline[x] += area + step/2;
|
||||||
area += step;
|
area += step;
|
||||||
}
|
}
|
||||||
STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
|
y_crossing += dy * (x2 - (x1+1));
|
||||||
STBTT_assert(sy1 > y_final-0.01f);
|
|
||||||
|
|
||||||
// area covered in the last pixel is the rectangle from all the pixels to the left,
|
STBTT_assert(STBTT_fabs(area) <= 1.01f);
|
||||||
// plus the trapezoid filled by the line segment in this pixel all the way to the right edge
|
|
||||||
scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
|
scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
|
||||||
|
|
||||||
// the rest of the line is filled based on the total height of the line segment in this pixel
|
|
||||||
scanline_fill[x2] += sign * (sy1-sy0);
|
scanline_fill[x2] += sign * (sy1-sy0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3240,9 +3055,6 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
|
||||||
// clipping logic. since this does not match the intended use
|
// clipping logic. since this does not match the intended use
|
||||||
// of this library, we use a different, very slow brute
|
// of this library, we use a different, very slow brute
|
||||||
// force implementation
|
// force implementation
|
||||||
// note though that this does happen some of the time because
|
|
||||||
// x_top and x_bottom can be extrapolated at the top & bottom of
|
|
||||||
// the shape and actually lie outside the bounding box
|
|
||||||
int x;
|
int x;
|
||||||
for (x=0; x < len; ++x) {
|
for (x=0; x < len; ++x) {
|
||||||
// cases:
|
// cases:
|
||||||
|
@ -3349,13 +3161,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
||||||
if (e->y0 != e->y1) {
|
if (e->y0 != e->y1) {
|
||||||
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
|
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
|
||||||
if (z != NULL) {
|
if (z != NULL) {
|
||||||
if (j == 0 && off_y != 0) {
|
STBTT_assert(z->ey >= scan_y_top);
|
||||||
if (z->ey < scan_y_top) {
|
|
||||||
// this can happen due to subpixel positioning and some kind of fp rounding error i think
|
|
||||||
z->ey = scan_y_top;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
|
|
||||||
// insert at front
|
// insert at front
|
||||||
z->next = active;
|
z->next = active;
|
||||||
active = z;
|
active = z;
|
||||||
|
@ -3424,7 +3230,7 @@ static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
|
||||||
|
|
||||||
static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
|
static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
|
||||||
{
|
{
|
||||||
/* threshold for transitioning to insertion sort */
|
/* threshhold for transitioning to insertion sort */
|
||||||
while (n > 12) {
|
while (n > 12) {
|
||||||
stbtt__edge t;
|
stbtt__edge t;
|
||||||
int c01,c12,c,m,i,j;
|
int c01,c12,c,m,i,j;
|
||||||
|
@ -3559,7 +3365,7 @@ static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
|
||||||
points[n].y = y;
|
points[n].y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
|
// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
|
||||||
static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
|
static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
|
||||||
{
|
{
|
||||||
// midpoint
|
// midpoint
|
||||||
|
@ -3984,7 +3790,6 @@ STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, in
|
||||||
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
|
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
|
||||||
spc->h_oversample = 1;
|
spc->h_oversample = 1;
|
||||||
spc->v_oversample = 1;
|
spc->v_oversample = 1;
|
||||||
spc->skip_missing = 0;
|
|
||||||
|
|
||||||
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
|
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
|
||||||
|
|
||||||
|
@ -4010,11 +3815,6 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
|
||||||
spc->v_oversample = v_oversample;
|
spc->v_oversample = v_oversample;
|
||||||
}
|
}
|
||||||
|
|
||||||
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
|
|
||||||
{
|
|
||||||
spc->skip_missing = skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
|
#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
|
||||||
|
|
||||||
static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
|
static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
|
||||||
|
@ -4157,7 +3957,6 @@ static float stbtt__oversample_shift(int oversample)
|
||||||
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
||||||
{
|
{
|
||||||
int i,j,k;
|
int i,j,k;
|
||||||
int missing_glyph_added = 0;
|
|
||||||
|
|
||||||
k=0;
|
k=0;
|
||||||
for (i=0; i < num_ranges; ++i) {
|
for (i=0; i < num_ranges; ++i) {
|
||||||
|
@ -4169,9 +3968,6 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
|
||||||
int x0,y0,x1,y1;
|
int x0,y0,x1,y1;
|
||||||
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
|
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
|
||||||
int glyph = stbtt_FindGlyphIndex(info, codepoint);
|
int glyph = stbtt_FindGlyphIndex(info, codepoint);
|
||||||
if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
|
|
||||||
rects[k].w = rects[k].h = 0;
|
|
||||||
} else {
|
|
||||||
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
|
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
|
||||||
scale * spc->h_oversample,
|
scale * spc->h_oversample,
|
||||||
scale * spc->v_oversample,
|
scale * spc->v_oversample,
|
||||||
|
@ -4179,9 +3975,6 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
|
||||||
&x0,&y0,&x1,&y1);
|
&x0,&y0,&x1,&y1);
|
||||||
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
|
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
|
||||||
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
|
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
|
||||||
if (glyph == 0)
|
|
||||||
missing_glyph_added = 1;
|
|
||||||
}
|
|
||||||
++k;
|
++k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4215,7 +4008,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info
|
||||||
// rects array must be big enough to accommodate all characters in the given ranges
|
// rects array must be big enough to accommodate all characters in the given ranges
|
||||||
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
||||||
{
|
{
|
||||||
int i,j,k, missing_glyph = -1, return_value = 1;
|
int i,j,k, return_value = 1;
|
||||||
|
|
||||||
// save current values
|
// save current values
|
||||||
int old_h_over = spc->h_oversample;
|
int old_h_over = spc->h_oversample;
|
||||||
|
@ -4234,7 +4027,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
|
||||||
sub_y = stbtt__oversample_shift(spc->v_oversample);
|
sub_y = stbtt__oversample_shift(spc->v_oversample);
|
||||||
for (j=0; j < ranges[i].num_chars; ++j) {
|
for (j=0; j < ranges[i].num_chars; ++j) {
|
||||||
stbrp_rect *r = &rects[k];
|
stbrp_rect *r = &rects[k];
|
||||||
if (r->was_packed && r->w != 0 && r->h != 0) {
|
if (r->was_packed) {
|
||||||
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
|
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
|
||||||
int advance, lsb, x0,y0,x1,y1;
|
int advance, lsb, x0,y0,x1,y1;
|
||||||
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
|
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
|
||||||
|
@ -4280,13 +4073,6 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
|
||||||
bc->yoff = (float) y0 * recip_v + sub_y;
|
bc->yoff = (float) y0 * recip_v + sub_y;
|
||||||
bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
|
bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
|
||||||
bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
|
bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
|
||||||
|
|
||||||
if (glyph == 0)
|
|
||||||
missing_glyph = j;
|
|
||||||
} else if (spc->skip_missing) {
|
|
||||||
return_value = 0;
|
|
||||||
} else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
|
|
||||||
ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
|
|
||||||
} else {
|
} else {
|
||||||
return_value = 0; // if any fail, report failure
|
return_value = 0; // if any fail, report failure
|
||||||
}
|
}
|
||||||
|
@ -4310,7 +4096,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect
|
||||||
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
|
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
|
||||||
{
|
{
|
||||||
stbtt_fontinfo info;
|
stbtt_fontinfo info;
|
||||||
int i, j, n, return_value; // [DEAR IMGUI] removed = 1;
|
int i,j,n, return_value = 1;
|
||||||
//stbrp_context *context = (stbrp_context *) spc->pack_info;
|
//stbrp_context *context = (stbrp_context *) spc->pack_info;
|
||||||
stbrp_rect *rects;
|
stbrp_rect *rects;
|
||||||
|
|
||||||
|
@ -4355,19 +4141,6 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *
|
||||||
return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
|
return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
|
|
||||||
{
|
|
||||||
int i_ascent, i_descent, i_lineGap;
|
|
||||||
float scale;
|
|
||||||
stbtt_fontinfo info;
|
|
||||||
stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
|
|
||||||
scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
|
|
||||||
stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
|
|
||||||
*ascent = (float) i_ascent * scale;
|
|
||||||
*descent = (float) i_descent * scale;
|
|
||||||
*lineGap = (float) i_lineGap * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
|
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
|
||||||
{
|
{
|
||||||
float ipw = 1.0f / pw, iph = 1.0f / ph;
|
float ipw = 1.0f / pw, iph = 1.0f / ph;
|
||||||
|
@ -4479,14 +4252,15 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
|
||||||
float y_frac;
|
float y_frac;
|
||||||
int winding = 0;
|
int winding = 0;
|
||||||
|
|
||||||
|
orig[0] = x;
|
||||||
|
orig[1] = y;
|
||||||
|
|
||||||
// make sure y never passes through a vertex of the shape
|
// make sure y never passes through a vertex of the shape
|
||||||
y_frac = (float) STBTT_fmod(y, 1.0f);
|
y_frac = (float) STBTT_fmod(y, 1.0f);
|
||||||
if (y_frac < 0.01f)
|
if (y_frac < 0.01f)
|
||||||
y += 0.01f;
|
y += 0.01f;
|
||||||
else if (y_frac > 0.99f)
|
else if (y_frac > 0.99f)
|
||||||
y -= 0.01f;
|
y -= 0.01f;
|
||||||
|
|
||||||
orig[0] = x;
|
|
||||||
orig[1] = y;
|
orig[1] = y;
|
||||||
|
|
||||||
// test a ray from (-infinity,y) to (x,y)
|
// test a ray from (-infinity,y) to (x,y)
|
||||||
|
@ -4548,7 +4322,7 @@ static float stbtt__cuberoot( float x )
|
||||||
return (float) STBTT_pow( x,1.0f/3.0f);
|
return (float) STBTT_pow( x,1.0f/3.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// x^3 + a*x^2 + b*x + c = 0
|
// x^3 + c*x^2 + b*x + a = 0
|
||||||
static int stbtt__solve_cubic(float a, float b, float c, float* r)
|
static int stbtt__solve_cubic(float a, float b, float c, float* r)
|
||||||
{
|
{
|
||||||
float s = -a / 3;
|
float s = -a / 3;
|
||||||
|
@ -4587,7 +4361,12 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
||||||
int w,h;
|
int w,h;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
|
|
||||||
if (scale == 0) return NULL;
|
// if one scale is 0, use same scale for both
|
||||||
|
if (scale_x == 0) scale_x = scale_y;
|
||||||
|
if (scale_y == 0) {
|
||||||
|
if (scale_x == 0) return NULL; // if both scales are 0, return NULL
|
||||||
|
scale_y = scale_x;
|
||||||
|
}
|
||||||
|
|
||||||
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
|
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
|
||||||
|
|
||||||
|
@ -4653,17 +4432,18 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
||||||
for (i=0; i < num_verts; ++i) {
|
for (i=0; i < num_verts; ++i) {
|
||||||
float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
|
float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
|
||||||
|
|
||||||
if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
|
// check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
|
||||||
float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
|
float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
|
||||||
|
|
||||||
float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
|
|
||||||
if (dist2 < min_dist*min_dist)
|
if (dist2 < min_dist*min_dist)
|
||||||
min_dist = (float) STBTT_sqrt(dist2);
|
min_dist = (float) STBTT_sqrt(dist2);
|
||||||
|
|
||||||
|
if (verts[i].type == STBTT_vline) {
|
||||||
|
float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
|
||||||
|
|
||||||
// coarse culling against bbox
|
// coarse culling against bbox
|
||||||
//if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
|
//if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
|
||||||
// sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
|
// sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
|
||||||
dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
|
float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
|
||||||
STBTT_assert(i != 0);
|
STBTT_assert(i != 0);
|
||||||
if (dist < min_dist) {
|
if (dist < min_dist) {
|
||||||
// check position along line
|
// check position along line
|
||||||
|
@ -4690,8 +4470,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
||||||
float ax = x1-x0, ay = y1-y0;
|
float ax = x1-x0, ay = y1-y0;
|
||||||
float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
|
float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
|
||||||
float mx = x0 - sx, my = y0 - sy;
|
float mx = x0 - sx, my = y0 - sy;
|
||||||
float res[3] = {0.f,0.f,0.f};
|
float res[3],px,py,t,it;
|
||||||
float px,py,t,it,dist2;
|
|
||||||
float a_inv = precompute[i];
|
float a_inv = precompute[i];
|
||||||
if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
|
if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
|
||||||
float a = 3*(ax*bx + ay*by);
|
float a = 3*(ax*bx + ay*by);
|
||||||
|
@ -4718,10 +4497,6 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
||||||
float d = (mx*ax+my*ay) * a_inv;
|
float d = (mx*ax+my*ay) * a_inv;
|
||||||
num = stbtt__solve_cubic(b, c, d, res);
|
num = stbtt__solve_cubic(b, c, d, res);
|
||||||
}
|
}
|
||||||
dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
|
|
||||||
if (dist2 < min_dist*min_dist)
|
|
||||||
min_dist = (float) STBTT_sqrt(dist2);
|
|
||||||
|
|
||||||
if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
|
if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
|
||||||
t = res[0], it = 1.0f - t;
|
t = res[0], it = 1.0f - t;
|
||||||
px = it*it*x0 + 2*t*it*x1 + t*t*x2;
|
px = it*it*x0 + 2*t*it*x1 + t*t*x2;
|
||||||
|
@ -4981,12 +4756,6 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const
|
||||||
|
|
||||||
// FULL VERSION HISTORY
|
// FULL VERSION HISTORY
|
||||||
//
|
//
|
||||||
// 1.25 (2021-07-11) many fixes
|
|
||||||
// 1.24 (2020-02-05) fix warning
|
|
||||||
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
|
|
||||||
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
|
|
||||||
// 1.21 (2019-02-25) fix warning
|
|
||||||
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
|
|
||||||
// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
|
// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
|
||||||
// 1.18 (2018-01-29) add missing function
|
// 1.18 (2018-01-29) add missing function
|
||||||
// 1.17 (2017-07-23) make more arguments const; doc fix
|
// 1.17 (2017-07-23) make more arguments const; doc fix
|
||||||
|
|
Loading…
Reference in New Issue