summaryrefslogtreecommitdiff
path: root/Build/source/texk/ptexenc/unicode.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/ptexenc/unicode.c')
-rw-r--r--Build/source/texk/ptexenc/unicode.c210
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;
+}