Skip to content

Commit

Permalink
UTF32 support improvements
Browse files Browse the repository at this point in the history
 - Make ImWchar32 unsigned.
 - Fix Win32 version of ImFileOpen by including windows.h sooner.
 - Make ImGuiIO::AddInputCharacterUTF16() more robust by disallowing illegal
surrogate pairs.
 - Allow pushing higher plane codepoints through ImGuiIO::AddInputCharacter().
  • Loading branch information
samhocevar committed Sep 29, 2019
1 parent 853dac3 commit 775a0f1
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 19 deletions.
43 changes: 29 additions & 14 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1258,30 +1258,34 @@ ImGuiIO::ImGuiIO()
// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
void ImGuiIO::AddInputCharacter(unsigned int c)
{
if (c > 0 && c < 0x10000)
if (c > 0 && c < (sizeof(ImWchar) == 2 ? 0x10000 : 0x110000))
InputQueueCharacters.push_back((ImWchar)c);
}

// UTF16 string use Surrogate to encode unicode > 0x10000, so we should save the Surrogate.
// UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so
// we should save the high surrogate.
void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
{
if (c >= 0xD800 && c <= 0xDBFF)
if ((c & 0xFC00) == 0xD800) // High surrogate, must save
{
if (Surrogate != 0)
InputQueueCharacters.push_back(0xFFFD);
Surrogate = c;
return;
}
else

ImWchar cp = c;
if (Surrogate != 0)
{
ImWchar cp = c;
if (c >= 0xDC00 && c <= 0xDFFF)
{
if (sizeof(ImWchar) == 2)
cp = 0xFFFD;
else
cp = ((ImWchar)(Surrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000;
Surrogate = 0;
}
InputQueueCharacters.push_back(cp);
if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate
InputQueueCharacters.push_back(0xFFFD);
else if (sizeof(ImWchar) == 2)
cp = 0xFFFD;
else
cp = ((ImWchar)(Surrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000;
Surrogate = 0;
}
InputQueueCharacters.push_back(cp);
}

void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
Expand Down Expand Up @@ -1582,6 +1586,17 @@ ImU32 ImHashStr(const char* data_p, size_t data_size, ImU32 seed)
return ~crc;
}

#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef __MINGW32__
#include <Windows.h>
#else
#include <windows.h>
#endif
#endif

FILE* ImFileOpen(const char* filename, const char* mode)
{
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__)
Expand Down
2 changes: 1 addition & 1 deletion imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ typedef unsigned int ImGuiID; // Unique ID used by widgets (typically hash
#define ImWchar ImWchar16
#endif
typedef unsigned short ImWchar16; // A single U16 character for keyboard input/display. We encode them as multi bytes UTF-8 when used in strings.
typedef int ImWchar32; // A single 32bit character for keyboard input/display, define ImWchar to ImWchar32 to use it. See imconfig.h .
typedef unsigned int ImWchar32; // A single U32 character for keyboard input/display. Define ImWchar to ImWchar32 to use it. See imconfig.h .
typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling
typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions
typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type
Expand Down
8 changes: 4 additions & 4 deletions imgui_draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1905,7 +1905,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
dst_tmp.GlyphsSet.Resize(dst_tmp.GlyphsHighest + 1);

for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
for (int codepoint = src_range[0]; codepoint <= src_range[1]; codepoint++)
for (unsigned int codepoint = src_range[0]; codepoint <= src_range[1]; codepoint++)
{
if (dst_tmp.GlyphsSet.GetBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option for MergeMode (e.g. MergeOverwrite==true)
continue;
Expand Down Expand Up @@ -2601,7 +2601,7 @@ void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1,
void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst)
{
IM_ASSERT(IndexLookup.Size > 0); // Currently this can only be called AFTER the font has been built, aka after calling ImFontAtlas::GetTexDataAs*() function.
int index_size = IndexLookup.Size;
unsigned int index_size = IndexLookup.Size;

if (dst < index_size && IndexLookup.Data[dst] == (ImWchar)-1 && !overwrite_dst) // 'dst' already exists
return;
Expand All @@ -2615,7 +2615,7 @@ void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst)

const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const
{
if (c >= IndexLookup.Size)
if (c >= (size_t)IndexLookup.Size)
return FallbackGlyph;
const ImWchar i = IndexLookup.Data[c];
if (i == (ImWchar)-1)
Expand All @@ -2625,7 +2625,7 @@ const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const

const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const
{
if (c >= IndexLookup.Size)
if (c >= (size_t)IndexLookup.Size)
return NULL;
const ImWchar i = IndexLookup.Data[c];
if (i == (ImWchar)-1)
Expand Down

0 comments on commit 775a0f1

Please sign in to comment.