Несоответствие кодовой точки между Java и C - PullRequest
1 голос
/ 03 апреля 2019

Итак, у меня возникли некоторые проблемы со следующим char в порту imgui до kotlin

Проведя целый день в кодировках и кодировках, я пришел к единственной надежде: полагаться на кодовые точки Юникода.

Этот символ на JVM

"–"[0].toInt() // same as codePointAt()

возвращает кодовую точку u2013

На C я не уверен, но так как это то, что делается сделано :

const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const
{
    if (c >= IndexLookup.Size)
        return FallbackGlyph;
    const ImWchar i = IndexLookup.Data[c];
    if (i == (ImWchar)-1)
        return FallbackGlyph;
    return &Glyphs.Data[i];
}

Где

typedef unsigned short ImWchar

и

ImVector<ImWchar> IndexLookup; // Sparse. Index glyphs by Unicode code-point.

Итак, делая это

char* a = "–";
int b = a[0];

возвращает кодовую точку u0096

Насколько я читал, похоже, что 127 (0x7F) мы находимся на территории "Расширенной Ascii", что плохо, потому что, похоже, существуют разные версии / интерпретации этого.

Например, эта таблица кодирования не соответствует моей кодовой точке, но Cp1252 кодировка соответствует, поэтому я склонен думать, что это то, что на самом деле используется на C.

В таблице внизу только что упомянутой ссылки вы можете увидеть, что 150 (десятичное число из правого столбца с указанным номером) действительно соответствует 2013 (шестнадцатеричное, я нахожу это немного несвязно, но все равно).

Чтобы решить эту проблему, я попытался преобразовать свои String на Kotlin в ту же кодировку (игнорируя на данный момент, конечно, это зависит от платформы), поэтому для каждого c: Char

"$c".toByteArray(Charset.forName("Cp1252"))[0].toUnsignedInt

Это работает, но нарушает рендеринг для иностранных шрифтов, таких как китайский, японский и т. Д.

Итак, мой вопрос: почему разница между u2013 на JVM и u0096 на C?

Какой правильный способ справиться с этим?

1 Ответ

1 голос
/ 09 апреля 2019

В тот момент, когда я решил, как this в Windows, я вставил эту функцию перед получением кодовой точки char.Это в основном переназначает все те символы, которые отличаются от ISO-8859-1.Вы можете видеть их в этой таблице , все они с этой светло-серой рамкой.

internal fun Char.remapCodepointIfProblematic(): Int {
    val i = toInt()
    return when (Platform.get()) {
        /*  https://en.wikipedia.org/wiki/Windows-1252#Character_set
         *  manually remap the difference from  ISO-8859-1 */
        Platform.WINDOWS -> when (i) {
            // 8_128
            0x20AC -> 128 // €
            0x201A -> 130 // ‚
            0x0192 -> 131 // ƒ
            0x201E -> 132 // „
            0x2026 -> 133 // …
            0x2020 -> 134 // †
            0x2021 -> 135 // ‡
            0x02C6 -> 136 // ˆ
            0x2030 -> 137 // ‰
            0x0160 -> 138 // Š
            0x2039 -> 139 // ‹
            0x0152 -> 140 // Œ
            0x017D -> 142 // Ž
            // 9_144
            0x2018 -> 145 // ‘
            0x2019 -> 146 // ’
            0x201C -> 147 // “
            0x201D -> 148 // ”
            0x2022 -> 149 // •
            0x2013 -> 150 // –
            0x2014 -> 151 // —
            0x02DC -> 152 // ˜
            0x2122 -> 153 // ™
            0x0161 -> 154 // š
            0x203A -> 155 // ›
            0x0153 -> 156 // œ
            0x017E -> 158 // ž
            0x0178 -> 159 // Ÿ
            else -> i
        }
        else -> i // TODO
    }
}
...