feat: add IMGUI_USE_WCHAR32 support, cross-compile natives, publish to mvn.mrlokop.dev
CI / Build Java (push) Has been cancelled
CI / Build Native (macos-latest - macos) (push) Has been cancelled
CI / Build Native (ubuntu-latest - linux) (push) Has been cancelled
CI / Build Native (ubuntu-latest - windows) (push) Has been cancelled
CI / Archive Natives (push) Has been cancelled
CI / Update Binaries (push) Has been cancelled
CI / Release (push) Has been cancelled
CI / Build Java (push) Has been cancelled
CI / Build Native (macos-latest - macos) (push) Has been cancelled
CI / Build Native (ubuntu-latest - linux) (push) Has been cancelled
CI / Build Native (ubuntu-latest - windows) (push) Has been cancelled
CI / Archive Natives (push) Has been cancelled
CI / Update Binaries (push) Has been cancelled
CI / Release (push) Has been cancelled
- Enable IMGUI_USE_WCHAR32 in imconfig.h (ImWchar = uint32_t) - Extend ImFontGlyphRangesBuilder, ImFontConfig, ImFontAtlas for 32-bit codepoints - Cross-compile natives for macOS universal, Linux x86_64 (glibc), Windows x86_64 - Publish as org.nnstd.imgui:...:1.90.0-wchar32+mrlokop2 to mvn.mrlokop.dev - Add BUILDING.md with full rebuild and publish instructions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
2fcd517b3e
commit
34c40304f6
17 files changed
+439
-55
No files matched your search
@@ -594,9 +594,11 @@ public final class ImFontAtlas extends ImGuiStructDestroyable {
|
||||
/*JNI
|
||||
#define RETURN_GLYPH_2_SHORT(glyphs) \
|
||||
const ImWchar* ranges = glyphs; \
|
||||
int size = 0; \
|
||||
int pairCount = 0; \
|
||||
for (; ranges[0]; ranges += 2) \
|
||||
size += 2; \
|
||||
pairCount++; \
|
||||
int shortsPerImWchar = (int)(sizeof(ImWchar) / sizeof(jshort)); \
|
||||
int size = pairCount * 2 * shortsPerImWchar + shortsPerImWchar; \
|
||||
jshortArray jShorts = env->NewShortArray(size); \
|
||||
env->SetShortArrayRegion(jShorts, 0, size, (jshort*)glyphs); \
|
||||
return jShorts;
|
||||
|
||||
@@ -347,6 +347,33 @@ public final class ImFontConfig extends ImGuiStructDestroyable {
|
||||
nSetGlyphRanges(glyphRanges);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience overload: encodes int[] codepoint pairs into WCHAR32 short[] layout and calls setGlyphRanges.
|
||||
* Expects int[] pairs [ lo, hi, lo, hi, ..., 0 ] (zero-terminated).
|
||||
* THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE.
|
||||
*/
|
||||
public void setGlyphRanges(final int[] codepoints) {
|
||||
// count pairs
|
||||
int pairCount = 0;
|
||||
for (int i = 0; i + 1 < codepoints.length; i += 2) {
|
||||
if (codepoints[i] == 0) break;
|
||||
pairCount++;
|
||||
}
|
||||
// each pair = 4 shorts (2 per endpoint), plus 2 terminator shorts
|
||||
final short[] encoded = new short[pairCount * 4 + 2];
|
||||
int out = 0;
|
||||
for (int i = 0; i < pairCount; i++) {
|
||||
final int lo = codepoints[i * 2];
|
||||
final int hi = codepoints[i * 2 + 1];
|
||||
encoded[out++] = (short) (lo & 0xFFFF);
|
||||
encoded[out++] = (short) ((lo >> 16) & 0xFFFF);
|
||||
encoded[out++] = (short) (hi & 0xFFFF);
|
||||
encoded[out++] = (short) ((hi >> 16) & 0xFFFF);
|
||||
}
|
||||
// terminator already zero from array initialisation
|
||||
setGlyphRanges(encoded);
|
||||
}
|
||||
|
||||
private native void nSetGlyphRanges(short[] glyphRanges); /*
|
||||
THIS->GlyphRanges = glyphRanges != NULL ? (ImWchar*)&glyphRanges[0] : NULL;
|
||||
*/
|
||||
|
||||
@@ -10,12 +10,14 @@ import java.util.List;
|
||||
* You can use the ImFontGlyphRangesBuilder helper to create glyph ranges based on text input. For example: for a game where your script is known,
|
||||
* if you can feed your entire script to it and only build the characters the game needs.
|
||||
* <p>
|
||||
* Direct reimplementation of native ImFontGlyphRangesBuilder in java
|
||||
* Direct reimplementation of native ImFontGlyphRangesBuilder in java.
|
||||
* Built with IMGUI_USE_WCHAR32=1: supports full Unicode range U+0000..U+10FFFF.
|
||||
* buildRanges() emits each range endpoint as two little-endian shorts (32-bit ImWchar layout).
|
||||
*/
|
||||
public final class ImFontGlyphRangesBuilder {
|
||||
private static final int UNICODE_CODEPOINT_MAX = 0xFFFF;
|
||||
private static final int UNICODE_CODEPOINT_MAX = 0x10FFFF;
|
||||
|
||||
// have to use type long because values are unsigned integers
|
||||
// have to use type long because values are unsigned integers; sized the same way as native (divide by 8)
|
||||
private final long[] usedChars = new long[(UNICODE_CODEPOINT_MAX + 1) / 8];
|
||||
|
||||
public ImFontGlyphRangesBuilder() {
|
||||
@@ -23,56 +25,98 @@ public final class ImFontGlyphRangesBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds single character to resulting ranges
|
||||
* Adds single character to resulting ranges (char overload for source compatibility)
|
||||
*/
|
||||
public void addChar(final char c) {
|
||||
setBit(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all characters from the given string to resulting ranges
|
||||
* Adds a Unicode codepoint (including SMP, U+10000..U+10FFFF) to resulting ranges
|
||||
*/
|
||||
public void addText(final String text) {
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
addChar(text.charAt(i));
|
||||
public void addChar(final int codepoint) {
|
||||
if (codepoint >= 0 && codepoint <= UNICODE_CODEPOINT_MAX) {
|
||||
setBit(codepoint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all given ranges to resulting ranges
|
||||
* Adds all codepoints from the given string to resulting ranges.
|
||||
* Handles supplementary characters (emoji, etc.) via codePointAt iteration.
|
||||
*/
|
||||
public void addText(final String text) {
|
||||
int i = 0;
|
||||
while (i < text.length()) {
|
||||
final int cp = text.codePointAt(i);
|
||||
addChar(cp);
|
||||
i += Character.charCount(cp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all given ranges to resulting ranges.
|
||||
* Expects the WCHAR32 short[] layout: each 32-bit codepoint encoded as two little-endian shorts,
|
||||
* pairs of codepoints form a [lo, hi] range, terminated by two zero shorts.
|
||||
* Format: [ lo_lo16, lo_hi16, hi_lo16, hi_hi16, ..., 0, 0 ]
|
||||
*/
|
||||
public void addRanges(final short[] ranges) {
|
||||
for (int i = 0; i < ranges.length; i += 2) {
|
||||
for (int i = 0; i + 3 < ranges.length; i += 4) {
|
||||
final int lo = (ranges[i] & 0xFFFF) | ((ranges[i + 1] & 0xFFFF) << 16);
|
||||
final int hi = (ranges[i + 2] & 0xFFFF) | ((ranges[i + 3] & 0xFFFF) << 16);
|
||||
if (lo == 0) {
|
||||
break;
|
||||
}
|
||||
for (int k = lo; k <= hi && k <= UNICODE_CODEPOINT_MAX; k++) {
|
||||
setBit(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all given ranges to resulting ranges.
|
||||
* Expects int[] pairs: [ lo, hi, lo, hi, ..., 0 ] (zero-terminated).
|
||||
*/
|
||||
public void addRanges(final int[] ranges) {
|
||||
for (int i = 0; i + 1 < ranges.length; i += 2) {
|
||||
if (ranges[i] == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (int k = ranges[i]; k <= ranges[i + 1]; k++) {
|
||||
addChar((char) k);
|
||||
for (int k = ranges[i]; k <= ranges[i + 1] && k <= UNICODE_CODEPOINT_MAX; k++) {
|
||||
setBit(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the final result (ordered ranges with all the unique characters submitted)
|
||||
* Result of this function can be directly passed to ImFontAtlas
|
||||
* Builds the final result (ordered ranges with all the unique characters submitted).
|
||||
* Result is in WCHAR32 short[] layout: each range endpoint is two little-endian shorts,
|
||||
* terminated by two zero shorts.
|
||||
* Format: [ lo_lo16, lo_hi16, hi_lo16, hi_hi16, ..., 0, 0 ]
|
||||
*/
|
||||
public short[] buildRanges() {
|
||||
final List<Short> out = new ArrayList<>();
|
||||
for (int n = 0; n <= UNICODE_CODEPOINT_MAX; n++) {
|
||||
if (getBit(n)) {
|
||||
out.add((short) n);
|
||||
final int lo = n;
|
||||
while (n < UNICODE_CODEPOINT_MAX && getBit(n + 1)) {
|
||||
n++;
|
||||
}
|
||||
out.add((short) n);
|
||||
final int hi = n;
|
||||
// emit lo as two LE shorts
|
||||
out.add((short) (lo & 0xFFFF));
|
||||
out.add((short) ((lo >> 16) & 0xFFFF));
|
||||
// emit hi as two LE shorts
|
||||
out.add((short) (hi & 0xFFFF));
|
||||
out.add((short) ((hi >> 16) & 0xFFFF));
|
||||
}
|
||||
}
|
||||
|
||||
final short[] result = new short[out.size() + 1];
|
||||
// terminator: two zero shorts (= one 32-bit zero ImWchar)
|
||||
final short[] result = new short[out.size() + 2];
|
||||
for (int i = 0; i < out.size(); i++) {
|
||||
result[i] = out.get(i);
|
||||
}
|
||||
result[result.length - 2] = 0;
|
||||
result[result.length - 1] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user