diff options
Diffstat (limited to 'Build/source/texk/ptexenc/unicode.c')
-rw-r--r-- | Build/source/texk/ptexenc/unicode.c | 210 |
1 files changed, 209 insertions, 1 deletions
diff --git a/Build/source/texk/ptexenc/unicode.c b/Build/source/texk/ptexenc/unicode.c index 4a2bfe2458a..0a4b3b30a0d 100644 --- a/Build/source/texk/ptexenc/unicode.c +++ b/Build/source/texk/ptexenc/unicode.c @@ -129,6 +129,214 @@ long UCStoUPTEX (long ucs) /* using over U+10.FFFF Area */ long UPTEXtoUCS (long uptex) { - if (uptex>=UCS_MAX) return uptex % UCS_MAX; /* for OTF package */ + long vs[2]; + if ((uptex>=0x220000 && uptex<=0x2FFFFF) || /* for 2-codepoint sequence */ + uptex>=0x400000) { /* for SVS, IVS */ + if (UVS_divide_code(uptex, vs) == 0) return 0; + return uptex; + } + if (uptex>=UCS_MAX*2) return uptex; + if (uptex>=UCS_MAX) return uptex % UCS_MAX; /* for OTF package */ return uptex; } + +int +UVS_get_codepoint_length(long ucv) +{ + int len = 0; + + if (ucv < 0x220000) { + len = 1; + } + else if (ucv >= 0x25E6E6 && ucv <= 0x25FFFF) { /* RGI Emoji Flag Sequence */ + if ((ucv & 0xFF) < 0xE6) return 0; /* illegal value */ + len = 2; + } + else if (ucv >= 0x800000 && ucv <= 0x80007F) { /* Emoji Keycap Sequence */ + ucv &= 0x7F; + if ( ucv==0x23 || ucv==0x2A || + (ucv>=0x30 && ucv<=0x39) ) len = 3; + else return 0; /* illegal value */ + } + else if (ucv < 0x300000) { + len = 2; + } + else if (ucv >= 0x400000 && ucv <= 0x43FFFFF) { + len = 2; + } + + return len; +} + +long +UVS_get_codepoint_in_sequence(long ucv, int n) +{ + long uvs, cp[3], len; + + cp[1] = cp[2] = 0; + + if (ucv < 0x220000) { + cp[0] = ucv % 0x110000; + len = 1; + } + else if (ucv >= 0x25E6E6 && ucv <= 0x25FFFF) { /* RGI Emoji Flag Sequence */ + if ((ucv & 0xFF) < 0xE6) return 0; /* illegal value */ + cp[0] = ((ucv >> 8) & 0xFF) + 0x1F100; + cp[1] = (ucv & 0xFF) + 0x1F100; + len = 2; + } + else if (ucv >= 0x800000 && ucv <= 0x80007F) { /* Emoji Keycap Sequence */ + cp[0] = ucv & 0x7F; + cp[1] = 0xFE0F; + cp[2] = 0x20E3; + len = 3; + } + else if (ucv < 0x300000) { + len = 2; + uvs = ucv >> 16; + if (uvs >= 0x22 && uvs <= 0x25) { /* (Semi-)Voiced Sound Mark */ + cp[0] = ucv & 0x1FFFF; + cp[1] = ((uvs - 0x22) >> 1) + 0x3099; + } + if (uvs >= 0x26 && uvs <= 0x2F) { /* Emoji Modifier Fitzpatrick */ + cp[0] = ucv & 0x1FFFF; + cp[1] = ((uvs - 0x26) >> 1) + 0x1F3FB; + } + } + else if (ucv >= 0x400000) { + len = 2; + uvs = ucv >> 16; + if (uvs >= 0x40 && uvs <= 0x7F) { /* SVS, VS1 .. VS16 */ + cp[0] = ucv & 0x3FFFF; + cp[1] = ((uvs - 0x40) >> 2) + 0xFE00; + } + if (uvs >= 0x80 && uvs <= 0x43F) { /* IVS, VS17 .. VS256 */ + cp[0] = ucv & 0x3FFFF; + cp[1] = ((uvs - 0x80) >> 2) + 0xE0100; + } + } + + if (n<0) + return len; + if (n>=1 && n<=3) { + return cp[n-1]; + } + + /* Unsupported */ + return 0; +} + +long +UVS_combine_code(long ucv, long uvs) +{ + if ( uvs == 0x20E3 && + ( ucv == 0x7C0023 || ucv == 0x7C002A || /* U+00xx U+FE0F U+20E3 */ + (ucv >= 0x7C0030 && ucv <= 0x7C0039))) { /* Emoji Keycap Sequence */ + return 0x40000 + ucv; + } + + if (ucv > 0x3FFFF) + return 0; + + if (((ucv >= 0x03000 && ucv <= 0x031FF) || + (ucv >= 0x1AFF0 && ucv <= 0x1B16F)) && + uvs >= 0x3099 && uvs <= 0x309A) { /* Kana (Semi-)Voiced Sound Mark */ + return ((uvs - 0x3099) << 17) + 0x220000 + ucv; + } + if (((ucv >= 0x02600 && ucv <= 0x027BF) || + (ucv >= 0x1F300 && ucv <= 0x1F9FF)) && + uvs >= 0x1F3FB && uvs <= 0x1F3FF) { /* Emoji Modifier Fitzpatrick */ + return ((uvs - 0x1F3FB) << 17) + 0x260000 + ucv; + } + if ( (ucv >=0x1F1E6 && ucv <= 0x1F1FF) && + (uvs >=0x1F1E6 && uvs <= 0x1F1FF) ) { /* RGI Emoji Flag Sequence */ + return ((ucv & 0xFF) << 8) + (uvs & 0xFF) + 0x250000; + } + if (ucv <= 0x2FFFF && uvs >= 0xFE00 && uvs <= 0xFE0F) { /* SVS, VS1 .. VS16 */ + return ((uvs - 0xFE00) << 18) + 0x400000 + ucv; + } + if (uvs >= 0xE0100) { /* IVS */ + if ( ucv <= 0x033FF || + (ucv >= 0x04DC0 && ucv <= 0x04DFF) || + (ucv >= 0x0A000 && ucv <= 0x0F8FF) || + (ucv >= 0x0FB00 && ucv <= 0x1FFFF) ) return 0; + if (ucv <= 0x0FFFF && uvs <=0xE01EF) { /* BMP, VS17 .. VS256 */ + return ((uvs - 0xE0100) << 18) + 0x800000 + ucv; + } + if (ucv <= 0x2FFFF && uvs <=0xE010F) { /* SIP, VS17 .. VS32 */ + return ((uvs - 0xE0100) << 18) + 0x800000 + ucv; + } + if ( uvs <=0xE010F) { /* TIP, VS17 .. VS32 */ + return ((uvs - 0xE0100) << 18) + 0x800000 + ucv; + } + } + /* Unsupported Combination */ + return 0; +} + +long +UVS_divide_code(long code, long* uvs) +{ + long u, v, p; + + u = code & 0x1FFFF; /* upto U+1FFFF */ + v = code >> 16; + /* for Combining Katakana-Hiragana (Semi-)Voiced Sound Mark */ + if (((u>=0x03000 && u<=0x031FF) || + (u>=0x1AFF0 && u<=0x1B16F)) && + v>=0x22 && v<=0x25) { + p = (v - 0x22) >> 1; /* Voiced or Semi-Voiced */ + if (uvs) *uvs = 0x3099 + p; + return u; + } + /* for Emoji Modifier Fitzpatrick */ + if (((u>=0x02600 && u<=0x027BF) || + (u>=0x1F300 && u<=0x1F9FF)) && + v>=0x26 && v<=0x2F) { + p = (v - 0x26) >> 1; /* Emoji Modifier Fitzpatrick Type-1..6 */ + if (uvs) *uvs = 0x1F3FB + p; + return u; + } + /* for RGI Emoji Flag Sequence */ + if ( u>=0x1E6E6 && v==0x25 ) { + if ((u & 0xFF) < 0xE6) goto Undefined; /* illegal value */ + u = ((u >> 8) & 0xFF) + 0x1F100; + v = ( u & 0xFF) + 0x1F100; /* Regional Indicator Symbol Letter */ + if (!uvs) goto Undefined; + *uvs = v; + return u; + } + + if (code<0x400000 || code>=0x4400000) { + /* Undefined */ + goto Undefined; + } + + /* for Variation Selector */ + u = code & 0x3FFFF; /* upto U+3FFFF */ + v = code >> 18; + p = u >> 16; + if (v < 0x20) { /* SVS VS1 .. VS16 */ + if (p==3) goto Undefined; + if (uvs) *uvs = v - 0x10 + 0xFE00; + return u; + } else + if (v == 0x20 && u <= 0x7F ) { /* for Emoji Keycap Sequence, need space for U+20E3 */ + if (uvs) { *uvs = 0xFE0F; *(uvs+1) = 0x20E3; } + return u; + } else /* IVS */ + if (v < 0x40) { /* VS17 .. VS32 */ + if (p==1) goto Undefined; + if (uvs) *uvs = v - 0x20 + 0xE0100; + return u; + } else if (v <= 0x1FF) { /* VS33 .. VS256 */ + if (p>0) goto Undefined; + if (uvs) *uvs = v - 0x20 + 0xE0100; + return u; + } + + Undefined: + /* Undefined */ + if (uvs) *uvs = 0; + return 0; +} |