fix: use real UTF-8 for jstring -> native conversion
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

JNI's GetStringUTFChars emits MUTF-8, which encodes codepoints above
U+FFFF as a surrogate-pair of two 3-byte sequences. ImGui's UTF-8 decoder
rejects those, so SMP emoji (U+1F000+) never reach the glyph atlas even
when the glyph is registered.

Add Jni::ToTrueUtf8 / Jni::FreeTrueUtf8 helpers in jni_common that decode
via GetStringChars (UTF-16) and emit proper 1/2/3/4-byte UTF-8, then
route every generator- and manually-written JNI call site through them
(1921 occurrences across the generated tree and 3 hand-written files,
plus the jni_content.kt generator template so future regenerations stay
consistent).
This commit is contained in:
MRLokop committed 2026-04-20 11:04:08 +03:00
1 parent 34c40304f6
commit d9aa2c811b
20 files changed
+3897 -3846

No files matched your search

@@ -350,8 +350,8 @@ private fun convertManualJni(mOrig: CtMethod<*>, method: CtMethod<*>): CtMethod<
}
if (p.isType("String")) {
getLines += "auto ${p.simpleName} = obj_${p.simpleName} == NULL ? NULL : (char*)env->GetStringUTFChars(obj_${p.simpleName}, JNI_FALSE)"
releaseLines += "if (${p.simpleName} != NULL) env->ReleaseStringUTFChars(obj_${p.simpleName}, ${p.simpleName})"
getLines += "auto ${p.simpleName} = Jni::ToTrueUtf8(env, obj_${p.simpleName})"
releaseLines += "Jni::FreeTrueUtf8(${p.simpleName})"
isConverted = true
}
@@ -361,14 +361,12 @@ private fun convertManualJni(mOrig: CtMethod<*>, method: CtMethod<*>): CtMethod<
const char* ${p.simpleName}[$countParam];
for (int i = 0; i < ${p.simpleName}$PARAM_ARR_LEN_POSTFIX; i++) {
const jstring str = (jstring)env->GetObjectArrayElement(obj_${p.simpleName}, i);
auto rawStr = (char*)env->GetStringUTFChars(str, JNI_FALSE);
${p.simpleName}[i] = rawStr;
${p.simpleName}[i] = Jni::ToTrueUtf8(env, str);
}
""".trimIndent()
releaseLines += """
for (int i = 0; i < $countParam; i++) {
const jstring str = (jstring)env->GetObjectArrayElement(obj_${p.simpleName}, i);
env->ReleaseStringUTFChars(str, ${p.simpleName}[i]);
Jni::FreeTrueUtf8((char*)${p.simpleName}[i]);
}
""".trimIndent()
isConverted = true